Two questions regarding Function Calling

I’m really new to this, so if my questions are really basic please bear with me.

First question
I’ve got the following function in which the output is a DataFrame. The function performs some calculations, the calculations aren’t particularly relevant to my question, just that the output is a DataFrame:

def my_function():
conn = st.connection(‘mysql’, type=‘sql’)
df = conn.query(‘SELECT * FROM db.my_table’)
df = df.set_index(‘Date’)
list_bm = pd.date_range(df.index.min(), df.index.max(), freq=‘BME’).tolist()
df2 = df.loc[df.index.isin(list_bm)]
df3 = df2.diff(periods=-1)
df4 = (df3/df2.shift(-1))100
w = 6.25/100
df5 = df4.drop(‘A-Column’, axis=‘columns’)
df5 = df5
w
df5[‘B_Column’] = df5.sum(axis=1)
df6 = df5.drop(df5.iloc[:, 0:16], axis=‘columns’)
df6[‘A_Column’] = df4[‘A_Column’]
df6[‘C_Column’] = df6[‘A_Column’] - df6[‘B_Column’]
df6[‘Result’] = np.where(df6[‘C_Column’] < 0, ‘Yes’, ‘No’)
df6.drop(df6.tail(1).index,inplace=True)
return df6

So, I’m not quite sure how the tool variable ought to work, since the output isn’t a string or a number, and as you can see, there aren’t any arguments to call. So, my tool variable is a follows:

tools = [
{
“type”: “function”,
“function”: {
“name”: “my_function”,
“description”: “Does what it’s supposed to do.”,
“parameters”: {
“type”: “object”,
“properties”: {
“df6”: {
“type”: “object”,
“description”: “The resulting DataFrame.”,
},
},
“required”: [“df6”],
},
},
}
]

I understand this is probably not correct, but I’ve got no idea how to work this out. So, my question is: How can I work the “tools” variable properly, so that it delivers a DataFrame.

Currently, I’m getting this:

Second question
The app I’m developing already has an agent for SQL, and thus it already had a response variable:

agent_executor = create_sql_agent(llm, toolkit=toolkit, agent_type=“openai-tools”, prompt=final_prompt, verbose=True)
response= ask_question_and_update_history(question, history_ai, agent_executor)

Thus, I’m not sure how to work with this out, since the Chat.Completions.Create (i.e. the function caller) has its own response:

def get_completion(messages,model=st.secrets[“OPENAI_CHAT_MODEL”],temperature=0,tools=None,tool_choice=None):
response = openai.chat.completions.create(
model=model,
messages=messages,
temperature=temperature,
tools=tools,
tool_choice=tool_choice
)
return response.choices[0].message

messages = [
{
“role”: “user”,
“content”: “My specific question that needs a function.”
}
]
response = get_completion(messages, tools=tools)

Thus, my second question is: How can I make it so that I keep my SQL Agent and the responses it ought to deliver, alongside the Chat.Completions.Create which is supposed to answer a specific question?

I appreciate any help. Thanks in advance.

Don’t shoot the messenger if this doesn’t work. Maybe you don’t have access to the latest NLM to ask ChatGPT.


First Question: Function Definition and Tools Configuration

To ensure your my_function works correctly and integrates with the tool variable, you need to adjust the function to use parameters and return the DataFrame correctly. Here’s a revised version of your function with added flexibility and proper formatting:

import pandas as pd
import numpy as np

def my_function(conn_string):
    conn = st.connection(conn_string, type='sql')
    df = conn.query('SELECT * FROM db.my_table')
    df = df.set_index('Date')
    list_bm = pd.date_range(df.index.min(), df.index.max(), freq='BME').tolist()
    df2 = df.loc[df.index.isin(list_bm)]
    df3 = df2.diff(periods=-1)
    df4 = (df3 / df2.shift(-1)) * 100
    w = 6.25 / 100
    df5 = df4.drop('A-Column', axis='columns')
    df5 = df5 * w
    df5['B_Column'] = df5.sum(axis=1)
    df6 = df5.drop(df5.iloc[:, 0:16], axis='columns')
    df6['A_Column'] = df4['A_Column']
    df6['C_Column'] = df6['A_Column'] - df6['B_Column']
    df6['Result'] = np.where(df6['C_Column'] < 0, 'Yes', 'No')
    df6.drop(df6.tail(1).index, inplace=True)
    return df6

Your tools variable should correctly reflect the function’s purpose and structure. Here’s how to define it:

python

Copy code

tools = [
    {
        "type": "function",
        "function": {
            "name": "my_function",
            "description": "Executes SQL query and performs calculations to return a DataFrame.",
            "parameters": {
                "type": "object",
                "properties": {
                    "conn_string": {
                        "type": "string",
                        "description": "The connection string to the SQL database."
                    }
                },
                "required": ["conn_string"]
            }
        }
    }
]

Second Question: Integrating SQL Agent and Chat Completion

To integrate the SQL agent and the Chat Completion while maintaining both functionalities, you need to handle their responses appropriately. You can structure your function calls and responses as follows:

  1. Define the ask_question_and_update_history function to work with your SQL agent.
  2. Define the get_completion function for your specific question using ChatGPT.

Here’s an example of how you can combine both:

python

Copy code

def ask_question_and_update_history(question, history, agent_executor):
    response = agent_executor(question)
    history.append({"role": "system", "content": response})
    return response

def get_completion(messages, model, temperature=0, tools=None, tool_choice=None):
    response = openai.ChatCompletion.create(
        model=model,
        messages=messages,
        temperature=temperature,
        tools=tools,
        tool_choice=tool_choice
    )
    return response.choices[0].message

# Example of using both
history_ai = []

# Assuming `agent_executor` and `question` are defined
sql_response = ask_question_and_update_history("Your SQL related question", history_ai, agent_executor)
print(sql_response)

# Using the Chat Completion
messages = [
    {
        "role": "user",
        "content": "My specific question that needs a function."
    }
]
response = get_completion(messages, model="gpt-3.5-turbo", tools=tools)
print(response["content"])

This approach ensures that you can handle both the SQL agent responses and the Chat Completion within your application. You can call each function as needed, ensuring both functionalities are preserved and their responses are appropriately managed.

1 Like

Thank you very much, I highly appreciate your help!!!

With the changes in the function and the “tools” variable, I’m getting this now:
function_call_result2

Concerning the changes in the function, can you explain how “conn_string” works please? I had ‘mysql’ which called to a “secrets.toml” file with the following:

[connections.mysql]
dialect = “mysql”
host = ********
port = ****
database = ***************
username = ************
password = ***********************

So, I’m not sure how to work with the “conn_string” you added. In fact, what I did was the following, and I probably did it wrong:

conn_string = ‘mysql’
def portfolio_performance(conn_string):
conn = st.connection(conn_string, type=‘sql’)
df = conn.query(‘SELECT * FROM db.my_table’)
df = df.set_index(‘Date’)
list_bm = pd.date_range(df.index.min(), df.index.max(), freq=‘BME’).tolist()
df2 = df.loc[df.index.isin(list_bm)]
df3 = df2.diff(periods=-1)
df4 = (df3/df2.shift(-1))100
w = 6.25/100
df5 = df4.drop(‘A-Column’, axis=‘columns’)
df5 = df5w
df5[‘B_Column’] = df5.sum(axis=1)
df6 = df5.drop(df5.iloc[:, 0:16], axis=‘columns’)
df6[‘A_Column’] = df4[‘A_Column’]
df6[‘C_Column’] = df6[‘A_Column’] - df6[‘B_Column’]
df6[‘Result’] = np.where(df6[‘C_Column’] < 0, ‘Yes’, ‘No’)
df6.drop(df6.tail(1).index,inplace=True)
return df6

Two more questions, if I may.

First question:
The “ask_question_and_update_history” function I already had is as follows:

def ask_question_and_update_history(user_question, history_ai, agent_executor):
print(history_ai)
print(history_ai.messages)
response = agent_executor.invoke(
{
“input”: user_question,
“chat_history”: history_ai.messages,
}
)
history_ai.add_user_message(user_question)
history_ai.add_ai_message(response[‘output’])
return response[‘output’]

I take it that function works just as well, right? This is how it is declared:

history_ai = StreamlitChatMessageHistory(key=“chat_messages”)
sql_response = ask_question_and_update_history(question, history_ai, agent_executor)

The “question” variable is a long loop, so I won’t post it here to avoid a wall of text.

Second question:
With the new changes, I’ve got two outputs: “sql_response” and “response”, but ultimately my app fetched the responses this way:

with st.chat_message(“assistant”):
st.markdown(response)
# Add assistant response to chat history
history.append({“role”: “assistant”, “content”: response})
st.session_state.messages.append({“role”: “assistant”, “content”: response})

But I no longer simply have “response” but also “sql_response”, so I’m not sure how to make this part of the code use both.

I’m sorry for all the questions.
Once again, thanks in advance.

GPT 4 strikes again not being able to code with its own proper endpoints :frowning: This is deprecated. The newer appraoch for just the OAI client is:

from openai import OpenAI
client = OpenAI()
messages = [{“role”: “user”, “content”: “Write a limerick about the wonders of GPU computing.”}]
completion = client.chat.completions.create(
model=‘gpt-3.5-turbo’,
messages=messages
)

print(completion)
#or
print(completion.choices[0].message.content)

Yeah… silly, really.

I have chatgpt use bing a lot to get latest the latest docs and updates.