系列篇章💥
AI大模型探索之路-實戰篇4:DB-GPT數據應用開發框架調研實踐
AI大模型探索之路-實戰篇5: Open Interpreter開放代碼解釋器調研實踐
目錄
- 系列篇章💥
- 一、前言
- 二、Function Calling詳細流程剖析
- 1、創建OpenAI客戶端
- 2、定義函數
- 3、創建數據參數對象
- 4、對象轉化
- 5、函數調用測試
- 6、定義工具函數
- 7、發送OpenAI 對話請求測試
- 8、指定工具函數進行調用
- 9、存儲返回的結果信息
- 10、查看函數名稱和參數
- 11、調用工具函數
- 12、將第一次返回的結果合并到消息列表
- 13、將functiona的信息合并到消息列表
- 14、第二次OpenAI API調用
- 三、Function Calling完整樣例
- 四、結語
一、前言
繼之前對DB-GPT和Open Interpreter技術的深入調研,本文將轉向對OpenAI的Function Calling技術進行回顧與探討。此次分析的目的旨在為即將到來的智能數據分析平臺的順利落地做好充分的技術儲備。通過對Function Calling技術的深度剖析,我們希望建立更加堅實的理論基礎,并在此基礎上探索其在實際應用中的潛在價值和實施路徑。這將不僅有助于我們更好地理解語言模型如何與程序代碼交互,而且為未來的開發工作提供指導和靈感。
二、Function Calling詳細流程剖析
本章節旨在深入剖析從OpenAI客戶端的創建到數據參數的定義,再到函數的定義、調用以及最終結果的整理輸出的完整過程。這一詳盡的解析將幫助我們深入理解Function Calling技術的每一個細節和實際應用中的操作流程。
1、創建OpenAI客戶端
首先,我們需要創建一個有效的OpenAI客戶端。這包括獲取必要的API密鑰和配置環境參數。通過這個過程,我們可以確保在后續步驟中順暢地與OpenAI的服務器進行通信。
import openai
import os
import numpy as np
import pandas as pd
import json
import io
from openai import OpenAI
import inspect# 從環境變量中獲取OpenAI API密鑰
openai.api_key = os.getenv("OPENAI_API_KEY")# 使用API密鑰創建OpenAI客戶端實例
client = OpenAI(api_key=openai.api_key)
2、定義函數
定義了一個名為sunwukong_function的函數,該函數接受一個字符串類型的數據集作為參數,并將其轉換為pandas DataFrame對象。然后,它將DataFrame中的每個元素乘以10,并將結果轉換為JSON格式的字符串返回。
def sunwukong_function(data):"""孫悟空算法函數,該函數定義了數據集計算過程:param data: 必要參數,表示帶入計算的數據表,用字符串進行表示:return:sunwukong_function函數計算后的結果,返回結果為表示為JSON格式的Dataframe類型對象"""data = io.StringIO(data)df_new = pd.read_csv(data, sep='\s+', index_col=0)res = df_new * 10return json.dumps(res.to_string())
3、創建數據參數對象
接下來,我們需要定義數據參數。這些參數將作為輸入傳遞給Function Call函數,以生成相應的輸出結果。在本例中,我們將使用一個簡單的數學計算任務作為示例。
#創建了一個名為df的DataFrame對象,其中包含兩列數據x1和x2。
df = pd.DataFrame({'x1':[1, 2], 'x2':[3, 4]})
df
輸出
4、對象轉化
#將df對象轉換為字符串類型。
df_str = df.to_string()
df_str
輸出
5、函數調用測試
#將df字符串傳遞給sunwukong_function函數進行計算。最后,它將計算結果打印出來。
result_json=sunwukong_function(df_str)
result_json
6、定義工具函數
# 定義一個工具函數
sunwukong={"type": "function","function": {"name": "sunwukong_function","description": "用于執行孫悟空算法函數,定義了一種特殊的數據集計算過程","parameters": {"type": "object","properties": {"data": {"type": "string","description": "執行孫悟空算法的數據集"},},"required": ["data"],},}}
# 放入工具列表
tools = [sunwukong]
7、發送OpenAI 對話請求測試
我們通過大模型的對話請求API進行確認,大模型是否能能正確找到對應的函數工具。
# 這段代碼定義了一個名為messages的列表,其中包含兩個字典對象。第一個字典對象表示系統角色,其內容為數據集data的描述信息;第二個字典對象表示用戶角色,其內容為執行孫悟空算法的請求。
messages=[{"role": "system", "content": "數據集data:%s,數據集以字符串形式呈現" % df_str},{"role": "user", "content": "請在數據集data上執行孫悟空算法"}
]
# 使用OpenAI API中的chat.completions.create方法來生成響應。該方法接受兩個參數:model和messages。model參數指定要使用的模型版本,這里使用的是gpt-3.5-turbo模型;messages參數是要發送給API的消息列表,這里傳入的是前面定義的messages列表。response = client.chat.completions.create(model="gpt-3.5-turbo",messages=messages
)
# 從響應中提取出第一個選擇的消息,并將其打印出來。這個消息應該是由API根據輸入的數據集和請求生成的孫悟空算法的結果。
response.choices[0].message
輸出:
ChatCompletionMessage(content='抱歉,我不清楚您指的“孫悟空算法”是什么意思。請問您能提供更多關于該算法的背景或者說明嗎?這樣我才能幫助您更好地實現您的目標。', role='assistant', function_call=None, tool_calls=None)
當前對話中沒有設置工具函數,因此大模型并沒有找到自定義的工具函數
8、指定工具函數進行調用
我們再次進行大模型API調用,這一次我們指定功能工具函數tools,設置為自動選擇(tool_choice=“auto”,)讓模型自己檢查判斷是否需要調用工具函數。
messages=[{"role": "system", "content": "數據集data:%s,數據集以字符串形式呈現" % df_str},{"role": "user", "content": "請在數據集data上執行孫悟空算法"}
]
# 重新初始化消息列表后,設置tools參數和tool_choice,讓大模型自己選擇是否使用工具
# 不會直接執行function_call函數。這段代碼是調用OpenAI API的chat.completions.create方法,用于生成聊天機器人的回答。其中,model參數指定了使用的模型版本,messages參數傳入了要發送給API的消息列表,tools參數傳入了工具列表,tool_choice參數指定了選擇工具的方式。
response = client.chat.completions.create(model="gpt-3.5-turbo",messages=messages,tools=tools,tool_choice="auto", )
# 查看消息結果,返回內容為空,但是找到返回了工具函數
response.choices[0].message
輸出:
ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_z16cI8SX4FkoW71SNV95hjIL', function=Function(arguments='{"data":"x1 x2\\n0 1 3\\n1 2 4"}', name='sunwukong_function'), type='function')])
從輸出結果可以看到,工具配置生效,大模型已經找到了工具函數
9、存儲返回的結果信息
將結果信息存儲到first_response
# 打印出消息,可以看到消息中已經找到了函數sunwukong_function
first_response = response.choices[0].message
first_response
輸出:
ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_z16cI8SX4FkoW71SNV95hjIL', function=Function(arguments='{"data":"x1 x2\\n0 1 3\\n1 2 4"}', name='sunwukong_function'), type='function')])
查看結果信息中的工具信息
response.choices[0].message.tool_calls
輸出:
[ChatCompletionMessageToolCall(id='call_z16cI8SX4FkoW71SNV95hjIL', function=Function(arguments='{"data":"x1 x2\\n0 1 3\\n1 2 4"}', name='sunwukong_function'), type='function')]
10、查看函數名稱和參數
將工具函數放入到字典中,再循環獲取到工具列表中的每一個函數的名稱,參數
#定義了一個名為available_tools的字典,其中包含了可用的工具函數
available_tools = {"sunwukong_function": sunwukong_function,
}
#從API返回的回答中提取出工具調用信息,并遍歷每個工具調用。對于每個工具調用,獲取函數名、函數參數,并使用這些信息調用相應的工具函數。
tool_calls = response.choices[0].message.tool_callsfor tool_call in tool_calls:function_name = tool_call.function.namefunction_to_call = available_tools[function_name]function_args = json.loads(tool_call.function.arguments)function_response = function_to_call(**function_args)# 打印出函數名、函數參數和函數響應。
print(function_name)
print(function_args)
print(function_response)
輸出:
11、調用工具函數
#調用工具函數并獲取其響應。它首先使用工具函數名和參數調用相應的工具函數,并將返回值存儲在名為function_response的變量中。然后打印出這個響應
function_response = function_to_call(**function_args)
function_response
輸出:
12、將第一次返回的結果合并到消息列表
# 追加第一次模型返回結果消息
messages.append(first_response)
messages
輸出:
[{'role': 'system','content': '數據集data: x1 x2\n0 1 3\n1 2 4,數據集以字符串形式呈現'},{'role': 'user', 'content': '請在數據集data上執行孫悟空算法'},ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_z16cI8SX4FkoW71SNV95hjIL', function=Function(arguments='{"data":"x1 x2\\n0 1 3\\n1 2 4"}', name='sunwukong_function'), type='function')])]
13、將functiona的信息合并到消息列表
# 追加function返回消息
messages.append({"tool_call_id": tool_call.id,"role": "tool","name": function_name,"content": function_response,}
)
messages
輸出:
[{'role': 'system','content': '數據集data: x1 x2\n0 1 3\n1 2 4,數據集以字符串形式呈現'},{'role': 'user', 'content': '請在數據集data上執行孫悟空算法'},ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_z16cI8SX4FkoW71SNV95hjIL', function=Function(arguments='{"data":"x1 x2\\n0 1 3\\n1 2 4"}', name='sunwukong_function'), type='function')]),{'tool_call_id': 'call_z16cI8SX4FkoW71SNV95hjIL','role': 'tool','name': 'sunwukong_function','content': '" x1 x2\\n0 10 30\\n1 20 40"'}]
14、第二次OpenAI API調用
第二次調用大模型API,讓大模型幫忙整理響應信息
# 再次調用,由大模型重新整理工具函數返回的結果信息(主要是將結果信息整理的更加方便可視化)
second_response = client.chat.completions.create(model="gpt-3.5-turbo",messages=messages,
)print(second_response.choices[0].message.content)
三、Function Calling完整樣例
完整的Function Calling函數使用代碼如下
from openai import OpenAI
import jsonopenai.api_key = os.getenv("OPENAI_API_KEY")client = OpenAI(api_key=openai.api_key)# Example dummy function hard coded to return the same weather
# In production, this could be your backend API or an external API
def sunwukong_function(data):"""孫悟空算法函數,該函數定義了數據集計算過程:param data: 必要參數,表示帶入計算的數據表,用字符串進行表示:return:sunwukong_function函數計算后的結果,返回結果為表示為JSON格式的Dataframe類型對象"""data = io.StringIO(data)df_new = pd.read_csv(data, sep='\s+', index_col=0)res = df_new['x1'] * 10return json.dumps(res.to_string())df_str=pd.DataFrame({'x1':[1, 2], 'x2':[3, 4]}).to_stringdef run_conversation():# 步驟1:將對話和可用函數發送給模型messages=[{"role": "system", "content": "數據集data:%s,數據集以字符串形式呈現" % df_str},{"role": "user", "content": "請在數據集data上執行孫悟空算法"} ]tools = [{"type": "function","function": {"name": "sunwukong_function","description": "用于執行孫悟空算法函數,定義了一種特殊的數據集計算過程","parameters": {"type": "object","properties": {"data": {"type": "string","description": "執行孫悟空算法的數據集"},},"required": ["data"],},}}]response = client.chat.completions.create(model="gpt-3.5-turbo",messages=messages,tools=tools,tool_choice="auto", # auto is default, but we'll be explicit)response_message = response.choices[0].messagetool_calls = response_message.tool_calls# 步驟2:檢查模型是否想要調用函數if tool_calls:# 步驟3:調用函數# 注意:JSON響應可能不總是有效的;確保處理錯誤available_functions = {"sunwukong_function": sunwukong_function,} # 這個例子中只有一個函數,但您可以有多個函數messages.append(response_message) # 將助手的回復擴展到對話中# 步驟4:將每個函數調用和函數響應的信息發送給模型for tool_call in tool_calls:function_name = tool_call.function.namefunction_to_call = available_functions[function_name]function_args = json.loads(tool_call.function.arguments)function_response = function_to_call(**function_args)messages.append({"tool_call_id": tool_call.id,"role": "tool","name": function_name,"content": function_response,}) # 將函數響應擴展到對話中second_response = client.chat.completions.create(model="gpt-3.5-turbo",messages=messages,) # 從模型獲取新的響應,其中可以看到函數響應return second_response
result=run_conversation()
result.choices[0].message.content
輸出:
# 使用StringIO將字符串轉換為文件對象
df_str='\\n x1\\n0 10\\n1 20\\n.'
data = io.StringIO(df_str)# 使用read_csv()函數讀取數據,并設置第一列為索引
df_new = pd.read_csv(data, sep='\s+', index_col=0)
df_new
輸出:
四、結語
本文深入探討了函數調用的全過程,詳細闡述了其每一個細節步驟。在回顧函數調用的實踐應用中,我們不僅加深了對其運作機制的理解,還體會到了其在編程實踐中的強大功能和靈活性。通過逐步剖析與實際操作的結合,本文檔旨在為讀者提供一個全面而實用的指南,以促進對函數調用概念的掌握及其在實際編程中的應用。希望讀者能夠借此更好地利用函數調用,優化代碼結構,提升開發效率。
🎯🔖更多專欄系列文章:AIGC-AI大模型探索之路
如果文章內容對您有所觸動,別忘了點贊、?關注,收藏!加入我,讓我們攜手同行AI的探索之旅,一起開啟智能時代的大門!