Tag: python

  • Getting the output of a SQL tool in an OCI Gen AI Agent πŸ“Š

    The Generative AI Agent service in OCI recently added the ability to add a SQL Tool, this enables an agent to generate a SQL query and optionally run the query against a database and return the results of the query to the agent πŸ€–. I created a short video that steps through how to use a SQL Tool βš’οΈ with an agent, which can be found here πŸ“Ό.

    More recently (mid-July 2025) the SQL Tool has been further enhanced so that responses include the following:

    • The raw output of the SQL query
    • A conversational “LLM style” response

    Previously a SQL Tool would only return the raw output of the SQL query, I found this quite useful as I could use Python packages such as matplotlib to visualise results, as of mid-July responses from the agent also include an LLM style conversational response, for example (taken from my agent that queries a database of bird sightings πŸ¦…):

    Raw Output of SQL Query

    Conversational LLM Style Response

    I’ve put together a short Python script that demonstrates how to get access to this data from a response, I typically use Streamlit as a front-end for the demo agents that I build, however to keep things simple, we’ll use the good old “shell” for this demo!

    Here is the script –

    import oci
    textinput = "what were the 3 most popular birds in 1997"
    config = oci.config.from_file(profile_name="DEFAULT")
    service_ep = "https://agent-runtime.generativeai.uk-london-1.oci.oraclecloud.com"
    agent_ep_id = "ocid1.genaiagentendpoint.oc1.uk-london-1.xwywwkz7bn5f5aogazpvkijnoj2u75yadsq"
    generative_ai_agent_runtime_client = oci.generative_ai_agent_runtime.GenerativeAiAgentRuntimeClient(config,service_endpoint=service_ep)
    create_session_response = generative_ai_agent_runtime_client.create_session(
        create_session_details=oci.generative_ai_agent_runtime.models.CreateSessionDetails(
            display_name="Session",
            description="Session"),
        agent_endpoint_id=agent_ep_id)
    sess_id = create_session_response.data.id
    response = generative_ai_agent_runtime_client.chat(
        agent_endpoint_id=agent_ep_id,
        chat_details=oci.generative_ai_agent_runtime.models.ChatDetails(
            user_message=textinput,
            session_id=sess_id))
    output = response.data.traces[3].output
    output = eval(output)
    sql_response = output["result"]
    print("")
    print("SQL Response: " + str(sql_response))
    text_response = response.data.message.content.text
    print("")
    print("Text Response: " + str(text_response))
    

    To use this script you’ll need to update the following:

    Finally make sure you have the latest version of the OCI SDK for Python, to upgrade to the latest version run the following command –

    pip3 install oci --upgrade

    When run the output should look something like this:

    Here is an example of how I’ve used matplotlib (within a Streamlit front-end) to visualise results using the raw output of the SQL query.

    As you can see below, it returns the conversational response, I then take the raw SQL output and use matplotlib to make it look pretty πŸ’„ – I may put together a post on this too.

    Thanks for reading!

  • Crawling a web site using Trafilatura πŸ•·οΈ

    I’ve been building a lot of OCI Generative AI Agents for customer demos recently πŸ€–, one demo that typically resonates well with customers is a RAG agent that uses text scraped from their public website, for example when working with a council this can demonstrate how residents can use a Generative AI Agent to quickly get answers to their questions about council services…….without the hassle of navigating their maze of a website πŸ‘©β€πŸ’».

    For reference here’s how an OCI Gen AI Agent works at a high-level.

    In the real world a Gen AI Agent would use internal data that isn’t publicly accessible, however I typically don’t have access to customers data, therefore the approach of crawling their public website works well to showcase the capabilities of a Gen AI Agent and begin a conversation on real-world use-cases that use internal data πŸ“Š.

    I wrote a very hacky Python script to crawl a site and dump the content to a text file which can then be ingested into a Gen AI Agent…….however this is super unreliable as the script is held together with sticking plasters 🩹 and constantly needs to be updated to work around issues experienced when crawling.

    I recently stumbled across a fantastic Python package named Trafilatura which can reliably and easily scrape a site, enabling me to retire my hacky Python script 🐍.

    Trafilatura can be installed using the instructions here (basically pip install trafilatura).

    Once it had been installed, I was able to scrape my own blog (which you are currently reading) using two commands!

    trafilatura --sitemap "https://brendg.co.uk/" --list >> URLs.txt
    trafilatura -i URLs.txt -o txtfiles/
    

    The first command grabs the sitemap for https://brendg.co.uk, and writes a list of all URLs found to URL.txt.

    The second command takes the URL.txt file as input and for each URL within, crawls the page and writes the contents to a text file within the folder txtfiles.

    Below is an example of one of the text files that have been output, you can clearly see the text from the blog post scraped.

    Such a useful tool, which will save me a ton of time ⏱️!

  • Batch Converting Word Documents to PDF using Python πŸ

    I’ve been working on a project deploying an OCI Generative AI Agent πŸ€–, which I’ve previously spoken about here πŸ“Ό.

    Marketing blurbOCI Generative AI Agents is a fully managed service that combines the power of large language models (LLMs) with AI technologies to create intelligent virtual agents that can provide personalized, context-aware, and highly engaging customer experiences.

    When creating a Knowledge Base for the agent to use, the only file types that are supported (at present) are PDF and text files. I had a customer that needed to add Word documents (DOCX format) to the agent, rather than converting these manually which would have taken a lifetime πŸ•£, I whipped up a Python script that uses the docx2pdf package – https://pypi.org/project/docx2pdf/ to perform a batch conversion of DOCX files to PDF, one thing to note is that the machine that runs the script needs Word installing locally.

    Here is the script πŸ‘‡

    import os
    import docx2pdf # install using "pip install docx2pdf" prior to running the script
    os.chdir("/Users/bkgriffi/Downloads") # the directory that contains the folders for the source (DOCX) and destination (PDF) files
    def convert_docx_to_pdf(docx_folder, pdf_folder): # function that performs the conversion
        for filename in os.listdir(docx_folder):
            if filename.endswith(".docx"):
                docx_path = os.path.join(docx_folder, filename)
                pdf_filename = filename[:-5] + ".pdf"
                pdf_path = os.path.join(pdf_folder, pdf_filename)
                try:
                    docx2pdf.convert(docx_path, pdf_path)
                    print(f"Converted: {filename} to {pdf_filename}")
                except Exception as e:
                    print(f"Error converting {filename}: {e}")
    convert_docx_to_pdf("DOCX-Folder", "PDF-Folder") # calling the function, with a source folder named DOCX-Folder and a destination folder named PDF-Folder, these folders should reside in the directory specified in line 4
    

    Folder structure πŸ—‚οΈ

    Source DOCX files πŸ“„

    Script Running πŸƒ

    Output PDF files

    Once the documents have been converted to PDF format they could be added to an OCI Storage Bucket and ingested into the OCI Generative AI Agent.

  • Using Resource Principal authentication with OCI πŸ”

    When connecting to OCI services in using the SDKs there are four options for authentication πŸ”:

    • API Key
    • Session Token
    • Instance Principal
    • Resoure Principal

    Each of these is covered in detail within the OCI SDK Authentication Methods documentation πŸ“•.

    I had a situation recently where I wanted to use Resource Principal authentication to authenticate a Container Instance to an OCI Generative AI Agent, the container was running a Python-based front end for an agent that I had created, however rather than using an API Key to authenticate as a specific user account to the Generative AI Agent service, I wanted to authenticate as the actual Container Instance itself.

    Doing this meant that I didn’t need to store a private key and config file (of the user account) on the Container Instance, which could be viewed as a security risk.

    There are three steps required to configure Resource Principal authentication which I have explained below, one thing to note is that this approach can be adapted for authenticating to other OCI services.

    Step 1 – Create a Dynamic Group that includes the Container Instance πŸ«™

    This defines the resource that will be connecting from (the Container Instance) to the Generative AI Agent. To create the Dynamic Group, I did the following within the OCI Console – I navigated to:

    Identity & Security > Domains > (My Domain) > Dynamic groups > Create dynamic group.

    I then created a group named Container-Instances with the following rule:

    ALL {resource.type=’computecontainerinstance’}

    This Dynamic Group contains every Container Instance within my tenant, I could have been more granular and specified an individual Container Instance.

    For further details on how to create Dynamic Groups be sure to check out the official documentation.

    Step 2 – Create a Policy that provides members of the Dynamic Group with access to the Generative AI Agents service πŸ“„

    The policy grants permissions to the Dynamic Group created above so that members of this group are able to connect to the Generative AI Agent service, to create the policy I did the following within the OCI Console:

    Navigated to – Identity & Security > Domains > Policies > Create Policy

    I then created a policy with the following statement:

    Allow dynamic-group Container-Instances to manage genai-agent-family in tenancy

    This provides the Dynamic Group named Container-Instances (created in Step 1) the desired access to the Generative AI Agent service – each OCI service has specific resource types that can be used within policies, the full policy reference for the Generative AI Agent service can be found here.

    Step 3 – Update the Python code to authenticate to the Generative AI Agent service using the identify of the Container Instance (Resource Principal) 🐍

    To update the Python script that connects to the Generative AI Agent so that it uses Resource Principal rather than API Key authentication, I updated the following lines of code from this:

    config = oci.config.from_file("config")
    service_ep = "https://agent-runtime.generativeai.uk-london-1.oci.oraclecloud.com"
    agent_ep_id = "OCID"
    
    generative_ai_agent_runtime_client = oci.generative_ai_agent_runtime.GenerativeAiAgentRuntimeClient(config,service_endpoint=service_ep)
    

    To this:

    rps = oci.auth.signers.get_resource_principals_signer() 
    service_ep = "https://agent-runtime.generativeai.uk-london-1.oci.oraclecloud.com"
    agent_ep_id = "OCID"
    
    generative_ai_agent_runtime_client = oci.generative_ai_agent_runtime.GenerativeAiAgentRuntimeClient(config={},signer=rps,service_endpoint=service_ep)
    
    

    The two major changes are:

    • Using “oci.auth.signers.get_resource_principals_signer()” rather than loading a config file with “config = oci.config.from_file(“config”)”
    • When connecting to the service, using config={},signer=rps,service_endpoint=service_ep” (key bits in bold) rather than “config,service_endpoint=service_ep

    As mentioned earlier the approach that I’ve covered above an be adapted to work with other OCI services.

  • Creating a front end for an OCI Generative AI Agent using Streamlit πŸŽ¨

    I stumbled upon an amazing tool recently called Streamlit. Streamlit makes it super-simple to create web apps using Python without any front-end dev experience (which was music to my ears!).

    I had one use-case which was perfect for Streamlit – creating a front end for OCI Generative AI Agents. I’ve built a number of PoCs recently and have used the OCI Console to demonstrate an OCI Generative AI Agent in action, whilst this is functional, it’s not particularly pretty πŸ˜€.

    If you want to know more about OCI Generative AI Agents, be sure to check out this short video that I created that walks through the end-to-end process of creating an agent in less than 10 minutes ⏱️.

    Anyway……back to the main topic. The advantage of using Streamlit is that it enables custom web apps to be created in minutes, which are highly customizable and therefore perfect for PoCs to demonstrate the art of the possible .

    Before I jump into sharing the code, this is how the end result looked (running locally on my Mac, will also work on Windows too) – using an agent that I developed to help understand UK immigration policy πŸ“„. Here I am asking about the rules for an entrepreneur.

    Installing Streamlit is a breeze using the single command below.

    pip install streamlit
    

    Once I’d done this, I put together the following Python script to create the web app, this can also be downloaded from GitHub.

    Disclaimer: I’m no developer and this code is a little hacky, but it gets the job done!

    The following variables need to be updated before running the script – further info can be found in the code comments:

    • st.title – Set’s the title of the page
    • st.sidebar.image – Configures the image to use in the sidebar
    • config – Set’s the OCI SDK profile to use, further info on this can be found here – https://docs.oracle.com/en-us/iaas/Content/API/Concepts/sdkconfig.htm
    • service_ep – Defines the Generative AI Agent service endpoint to connect to (this varies by region)
    • agent_ep_id – Sets the OCID of the agent to connect to
    import streamlit as st
    import time
    import oci
    
    # Page Title
    st.title("OCI Generative AI Agents Demo 🧠") # Update this with your own title
    
    # Sidebar Image
    st.sidebar.image("https://brendg.co.uk/wp-content/uploads/2021/05/myavatar.png") # Update this with your own image
    
    # OCI GenAI settings
    config = oci.config.from_file(profile_name="DEFAULT") # Update this with your own profile name
    service_ep = "https://agent-runtime.generativeai.us-chicago-1.oci.oraclecloud.com" # Update this with the appropriate endpoint for your region, a list of valid endpoints can be found here - https://docs.oracle.com/en-us/iaas/api/#/en/generative-ai-agents-client/20240531/
    agent_ep_id = "ocid1.genaiagentendpoint.oc1.us-chicago-1.amaaaaaaayvpzvaa7z2imflumr7bbxeguh6y7bpnw2yie4lca2usxrct" # Update this with your own agent endpoint OCID, this can be found within Generative AI Agents > Agents > (Your Agent) > Endpoints > (Your Endpoint) > OCID
    
    # Response Generator
    def response_generator(textinput):
        # Initialize service client with default config file
        generative_ai_agent_runtime_client = oci.generative_ai_agent_runtime.GenerativeAiAgentRuntimeClient(config,service_endpoint=service_ep)
    
        # Create Session
        create_session_response = generative_ai_agent_runtime_client.create_session(
            create_session_details=oci.generative_ai_agent_runtime.models.CreateSessionDetails(
                display_name="USER_Session",
                description="User Session"),
            agent_endpoint_id=agent_ep_id)
    
        sess_id = create_session_response.data.id
    
        response = generative_ai_agent_runtime_client.chat(
            agent_endpoint_id=agent_ep_id,
            chat_details=oci.generative_ai_agent_runtime.models.ChatDetails(
                user_message=textinput,
                session_id=sess_id))
    
        #print(str(response.data))
        response = response.data.message.content.text
        return response
    
    # Initialize chat history
    if "messages" not in st.session_state:
        st.session_state.messages = []
    
    # Display chat messages from history on app rerun
    for message in st.session_state.messages:
        with st.chat_message(message["role"]):
            st.markdown(message["content"])
    
    # Accept user input
    if prompt := st.chat_input("How can I help?"):
        # Add user message to chat history
        st.session_state.messages.append({"role": "user", "content": prompt})
        # Display user message in chat message container
        with st.chat_message("user"):
            st.markdown(prompt)
    
        # Display assistant response in chat message container
        with st.chat_message("assistant"):
            response = response_generator(prompt)
            write_response = st.write(response)
        # Add assistant response to chat history
        st.session_state.messages.append({"role": "assistant", "content": response})
    

    Once this file has been saved, it’s simple to run with a single command:

    streamlit run OCI-GenAI-Agents-Streamlit.py
    

    It will then automatically launch a browser and show the web app in action πŸ–₯️

    This basic example can easily be updated to meet your requirements, the Streamlit documentation is very comprehensive and easy to follow with some useful examples – https://docs.streamlit.io/.