系列篇章💥
No. | 文章 |
---|---|
1 | 【GLM-4开发实战】Function Call进阶实战:外部函数调用回顾 |
2 | 【GLM-4开发实战】Function Call进阶实战:常见挑战之意图识别处理 |
3 | 【GLM-4开发实战】Function Call进阶实战:常见挑战之海量函数处理 |
4 | 【GLM-4开发实战】Function Call进阶实战:常见挑战之并发调用处理 |
目录
- 系列篇章💥
- 引言
- 一、概述
- 二、Function Call调用详细流程
- 1、定义模型客户端
- 2、定义工具函数
- 3、定义数据对象
- 4、数据转换为String类型
- 5、函数调用测试
- 6、定义函数的说明
- 7、大模型调用测试(不带工具函数)
- 8、大模型调用测试(携带工具函数)
- 9、查看结果中的tool_calls属性
- 10、构建字段格式函数列表
- 11、获取执行函数并执行
- 12、第二次调用大模型
- 13、查看最终执行结果
- 三、Function Call函数调用封装
- 结语
引言
在人工智能领域,Function Call是大模型能力扩展的核心。它不仅在Retrieval-Augmented Generation(RAG)中扮演着重要角色,也是Agent智能体架构设计中不可或缺的一部分。本文将深入探讨GLM-4模型中Function Call的进阶应用,通过实战案例,回顾并总结外部函数调用的技巧与经验。
一、概述
Function Call作为模型与外部世界交互的桥梁,其重要性不言而喻。本章节旨在通过GLM-4模型的Function Call功能,为大家提供一个全面的使用回顾,帮助大家更高效地利用这一功能。
二、Function Call调用详细流程
1、定义模型客户端
首先,需要构建一个客户端,用于与GLM-4模型进行通信。
import os
import openai
from openai import OpenAI
import shutil
import numpy as np
import pandas as pd
import json
import io
import inspect
import requests
import re
import random
import string
## 初始化客户端
api_key = os.getenv("ZHIPU_API_KEY")
## pip install zhipuai
from zhipuai import ZhipuAI
client = ZhipuAI(api_key=api_key)
2、定义工具函数
定义了一个大模型里面肯定没有的算法工具函数
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 * 10
return json.dumps(res.to_string())
3、定义数据对象
创建数据对象,为函数调用提供必要的数据支持。
df = pd.DataFrame({'x1':[1, 2], 'x2':[3, 4]})
df
输出:
4、数据转换为String类型
与大模型进行配合调用的时候,尽可能的让调用的函数参数和返回值都用String表示。
df_str = df.to_string()
df_str
输出:
5、函数调用测试
进行初步的函数调用,测试其基本功能。
result_json=sunwukong_function(df_str)
result_json
输出:
6、定义函数的说明
方便大模型识别函数自动完成调用,注意格式为:JSON Schema的格式
sunwukong={
"type": "function",
"function": {"name": "sunwukong_function",
"description": "用于执行孙悟空算法函数,定义了一种特殊的数据集计算过程",
"parameters": {"type": "object",
"properties": {"data": {"type": "string",
"description": "执行孙悟空算法的数据集"},
},
"required": ["data"],
},
}
}
定义工具列表
tools = [sunwukong]
7、大模型调用测试(不带工具函数)
在没有外部函数工具的情况下测试大模型的第一次调用并执行孙悟空算法
messages=[
{"role": "system", "content": "数据集data:%s,数据集以字符串形式呈现" % df_str},
{"role": "user", "content": "请在数据集data上执行孙悟空算法"}
]
response = client.chat.completions.create(
model="glm-4",
messages=messages
)
response.choices[0].message
输出:
CompletionMessage(content='抱歉,但似乎有一些混淆。"孙悟空算法"并不是一个公认的数据处理或机器学习算法。孙悟空是中国古典文学作品《西游记》中的虚构人物,以其变化无常和神通广大著称。\n\n然而,根据您提供的数据集(以字符串形式表示),如果您是想要进行某种形式的数据处理或分析,下面是一个用Python实现的对给定字符串形式的数据集进行解析的简单示例:\n\n```python\n# 这是您提供的数据集字符串\ndata_str = """\nx1 x2\n0 1 3\n1 2 4\n"""\n\n# 将字符串分割成行\nlines = data_str.strip().split("\\n")\n\n# 解析标题和值\nheader = lines[0].split()\nvalues = [line.split() for line in lines[1:]]\n\n# 转换数据为字典形式\ndata_dict = {h: [] for h in header}\nfor row in values:\n for i, value in enumerate(row):\n data_dict[header[i]].append(int(value))\n\n# 输出字典形式的数据集\nprint(data_dict)\n\n# 如果需要转换为Pandas DataFrame(如果适用的话)\nimport pandas as pd\n\ndf = pd.DataFrame(data_dict)\nprint(df)\n```\n\n当运行这段代码时,它将输出以下字典形式的数据集:\n\n```\n{\'x1\': [0, 1], \'x2\': [1, 2]}\n```\n\n然后,它将创建一个Pandas DataFrame,如下所示:\n\n```\n x1 x2\n0 0 1\n1 1 2\n```\n\n请注意,这段代码假设每行数据的列数是相同的,并且所有值都可以转换为整数。\n\n如果您有一个具体的任务或算法想要应用到这个数据集上,请详细描述,我将尽力提供帮助。', role='assistant', tool_calls=None)
8、大模型调用测试(携带工具函数)
第一次调用大模型,测试Funcation call流程,本次调用时,设置工具函数tools和tool_choice(由大模型自己判断选择是否需要调用外部工具函数)
messages=[
{"role": "system", "content": "数据集data:%s,数据集以字符串形式呈现" % df_str},
{"role": "user", "content": "请在数据集data上执行孙悟空算法"}
]
response = client.chat.completions.create(
model="glm-4",
messages=messages,
tools=tools,
tool_choice="auto",
)
response.choices[0].message
输出:
CompletionMessage(content='', role='assistant', tool_calls=[CompletionMessageToolCall(id='call_8822099358575188366', function=Function(arguments='{"data":"x1 x2\\n0 1 3\\n1 2 4"}', name='sunwukong_function'), type='function', index=0)])
输出结果可以看到,模型识别正确识别出来需要调用的函数,并且正确解析了参数 将第一次调用结果放入变量first_response中
first_response = response.choices[0].message
first_response
输出:
CompletionMessage(content=None, role='assistant', tool_calls=[CompletionMessageToolCall(id='call_8730210251242354639', function=Function(arguments='{"data":"x1 x2\\n0 1 3\\n1 2 4"}', name='sunwukong_function'), type='function', index=0)])
9、查看结果中的tool_calls属性
分析函数调用的结果,特别是tool_calls属性,了解函数调用的细节。
response.choices[0].message.tool_calls
输出:
[CompletionMessageToolCall(id='call_8730210251242354639', function=Function(arguments='{"data":"x1 x2\\n0 1 3\\n1 2 4"}', name='sunwukong_function'), type='function', index=0)]
10、构建字段格式函数列表
构建字典形式的函数调用列表,key为函数名,value为函数体
available_tools = {
"sunwukong_function": sunwukong_function,
}
11、获取执行函数并执行
根据大模型的返回值中获取到函数调用需要到的:函数名,参数,函数体,并且执行函数。
tool_calls = response.choices[0].message.tool_calls
for tool_call in tool_calls:
## 函数名
function_name = tool_call.function.name
## 根据函数名获取到函数体
function_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)
输出:
查询执行函数,执行效果
function_response = function_to_call(**function_args)
function_response
输出:
12、第二次调用大模型
把结果给到大模型,大模型进行增强生成
在第一次调用的基础上,进行第二次调用,观察是否有性能提升或结果优化。
messages.append(response.choices[0].message.model_dump())
for tool_call in tool_calls:
function_name = tool_call.function.name
function_to_call = available_tools[function_name]
function_args = json.loads(tool_call.function.arguments)
## 真正执行外部函数的就是这儿的代码
function_response = function_to_call(**function_args)
messages.append(
{
"role": "tool",
"content": function_response,
"tool_call_id": tool_call.id,
}
)
## 第二次调用模型
second_response = client.chat.completions.create(
model="glm-4",
messages=messages,
tools=tools
)
# 获取最终结果
final_response = second_response.choices[0].message.content
13、查看最终执行结果
分析第二次调用的结果,评估Function Call的整体表现和可能的改进空间。
final_response
输出:
'根据孙悟空算法执行结果,数据集data经过计算后的结果为:\n```\n x1 x2\n0 10 30\n1 20 40\n```'
三、Function Call函数调用封装
Function Call相关业务逻辑整体封装调用;封装Function Call不仅可以提高代码的可读性和可维护性,还可以在不同场景下复用函数调用逻辑。本部分将对Function Call相关使用代码进行封装,将Function Call封装为可复用的模块,以及如何通过封装提高开发效率。
from openai import OpenAI
import json
## 步骤1:构建函数
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 * 10
return json.dumps(res.to_string())
available_tools = {
"sunwukong_function": sunwukong_function,
}
df_str=pd.DataFrame({'x1':[1, 2], 'x2':[3, 4]}).to_string
def run_conversation():
# Step 1: send the conversation and available functions to the model
messages=[
{"role": "system", "content": "数据集data:%s,数据集以字符串形式呈现" % df_str},
{"role": "user", "content": "请在数据集data上执行孙悟空算法"}
]
## 步骤2:函数说明 JSON Schema格式
tools = [
{
"type": "function",
"function": {"name": "sunwukong_function",
"description": "用于执行孙悟空算法函数,定义了一种特殊的数据集计算过程",
"parameters": {"type": "object",
"properties": {"data": {"type": "string",
"description": "执行孙悟空算法的数据集"},
},
"required": ["data"],
},
}
}]
## 步骤3:第一次调大模型
response = client.chat.completions.create(
model="glm-4",
messages=messages,
tools=tools,
tool_choice="auto", # auto is default, but we'll be explicit
)
response_message = response.choices[0].message
tool_calls = response_message.tool_calls
# Step 2: check if the model wanted to call a function
if tool_calls:
messages.append(response.choices[0].message.model_dump())
for tool_call in tool_calls:
function_name = tool_call.function.name
function_to_call = available_tools[function_name]
function_args = json.loads(tool_call.function.arguments)
function_response = function_to_call(**function_args)
messages.append({
"role": "tool",
"content": f"{json.dumps(function_response)}",
"tool_call_id":tool_call.id
})
## 步骤四:第二次调用大模型
second_response = client.chat.completions.create(
model="glm-4", # 填写需要调用的模型名称
messages=messages,
tools=tools,
)
return second_response
result=run_conversation()
查看调用结果
result.choices[0].message.content
输出:
'根据您的请求,我已经在数据集data上执行了孙悟空算法。执行结果如下:\n\n" x1 x2\n0 10 30\n1 20 40"\n\n这是数据集经过孙悟空算法处理后的结果。如果您还有其他问题或需要进一步的帮助,请随时告诉我。'
结语
Function Call作为连接人工智能模型与外部世界的纽带,其应用广泛且深入。通过本文的深入分析与实战回顾,我们希望能够为读者提供Function Call使用的宝贵经验和策略,助力开发者们在AI领域的进一步探索和实践。随着技术的不断进步,Function Call的应用也将更加多样化和高效,期待与大家共同见证这一领域的未来发展。
🎯🔖更多专栏系列文章:AI大模型提示工程完全指南、AI大模型探索之路(零基础入门)、AI大模型预训练微调进阶、AI大模型开源精选实践、AI大模型RAG应用探索实践🔥🔥🔥 其他专栏可以查看博客主页📑
😎 作者介绍:我是寻道AI小兵,资深程序老猿,从业10年+、互联网系统架构师,目前专注于AIGC的探索。
📖 技术交流:欢迎关注【小兵的AI视界】公众号或扫描下方👇二维码,加入技术交流群,开启编程探索之旅。
💘精心准备📚500本编程经典书籍、💎AI专业教程,以及高效AI工具。等你加入,与我们一同成长,共铸辉煌未来。
如果文章内容对您有所触动,别忘了点赞、⭐关注,收藏!加入我,让我们携手同行AI的探索之旅,一起开启智能时代的大门!