大模型实操Agent-如何从0开始搭建function calling

构建Agent的重要的一步是Function calling(函数调用),本文不使用任何langchain等框架或者coze等平台,从0开始构建一个可以调用function的Agent。

Function calling其实就是提供了一种方式,允许LLM与外部系统进行交互,还有如何进行交互。

1、买火车票

我让Kimi帮买张火车票,它会直接拒绝,甚至换ChatGPT、文心、通义等其他大模型,得到的回答只有:"我无法直接为您购买火车票"。
不过,LLM是知道买票,但它不能直接操作,它的本质是语言模型,所以需要和外部系统进行交互,那么就需要函数调用(function call)

让Kimi帮买张火车票

2、Agent构建思路

首先理清思路,确定好Agent的目标、需要的function,其次理解用户问题、选择工具,最后将返回的结果,整理好给用户。

设计思路

2.1 场景示例-天气Agent

创建一个获取最新天气的Agent,以及如何使用function call。

  • Agent的目标:可以回答关于天气的问题。

  • function:调用某地方的天气情况,并且反馈

  • 流程

    • a.思考: 用户输入问题,LLM先对问题进行分析
    • b.行动: 如果问到了天气问题,则分析出需要调用的function以及function要传入的参数
    • c.响应:function返回后,将答案整理好回复给用户。
  • 函数自定

    • a.定义一个获取天气的函数(属于Tools中的一个,这里用于演示,不做真实调用):

       def get_weather(location): 
         return "天气晴朗"
      
    • b.再定义一个大模型的发送信息的方法:

      def send_messages(messages): 
        client = OpenAI(
                            api_key="<你的llm的key>", 
                            base_url="https://api.llm.com")
        response = client.chat.completions.create( 
                            model="llm-chat", 
                            messages=messages) 
        return response.choices[0].message
      

2.2 实操Agent-天气Agent

从“用户提出问题”到“思考”到“响应”调用了多次LLM模型,所以要求模型按照顺序去调用LLM:

一定需要理清思路!一定需要理清思路!
换句话说写好system prompt!换句话说写好system prompt!

以下是思考过程

你在运行一个“思考”,“工具调用”,“响应”循环。每次只运行一个阶段

1.“思考”阶段:你要仔细思考用户的问题
2.“工具调用阶段”:选择可以调用的工具,并且输出对应工具需要的参数
3.“响应”阶段:根据工具调用返回的影响,回复用户问题。

已有的工具如下:
get_weather:
e.g. get_weather:天津
返回天津的天气情况

Example:
question:天津的天气怎么样?
thought:我应该调用工具查询天津的天气情况
Action:
{
    "function_name":"get_response_time"
    "function_params":{
        "location":"天津"
    }
}
调用Action的结果:“天气晴朗”
Answer:天津的天气晴朗

提示工程

上边的逻辑正好可以当作system的提示工程:

system="""
    你在运行一个“思考”,“工具调用”,“响应”循环。每次只运行一个阶段

    1.“思考”阶段:你要仔细思考用户的问题
    2.“工具调用阶段”:选择可以调用的工具,并且输出对应工具需要的参数
    3.“响应”阶段:根据工具调用返回的影响,回复用户问题。

    已有的工具如下:
    get_weather:
    e.g. get_weather:天津
    返回天津的天气情况

    Example:
    question:天津的天气怎么样?
    thought:我应该调用工具查询天津的天气情况
    Action:
    {
        "function_name":"get_response_time"
        "function_params":{
            "location":"天津"
        }
    }
    调用Action的结果:“天气晴朗”
    Answer:天津的天气晴朗
"""

用户Query

第一步,向模型提问一个问题

question="北京天气怎么样"

messages = [{"role": "system", "content": system_prompt},
{"role": "user", "content": question}]

message = send_messages(messages)
print(f"Model-1th>\n {message.content}")

返回值:

Model-1th>
 thought:我应该调用工具查询北京的天气情况
Action:
{
        "function_name":"get_weather",
        "function_params":{
                "location":"北京"
        }
}

可以看出模型已经进行了思考,并且返回了可以调用的工具了

函数调用

第二步,如果从“第一步”的返回值中可以提取调用工具的json

 "function_name":"get_weather",
 "function_params": "location":"北京"

第三步,调用真实工具,获取真实结果

invoke_function(**function_name,**function_params)

返回结果

第四步,将工具调用的结果追加到message中,一起给到模型,让它总结回答:

messages.append({"role": "assistant", 
                 "content": f"调用Action的结果:{tianqi}"}) 
message = send_messages(messages)
print(f"result>\n {message.content}")

返回值:

result> 
北京今天的天气晴朗。

3、tools功能的演进

上篇文章提过,笔者认为function calling和tool using功能相同,只是描述不同,看每个人的语言习惯。
随着LLM调用工具的普及,这种调用方法集成在大模型api接口中就变得越重要。

大部分模型厂商已经支持了function call,下面是deepseek工具调用的一个例子:

response = client.chat.completions.create(
    model="deepseek-chat",
    messages=messages,
    tools=tools
)

其中 tools是可以供模型选择的工具。

写在最后

从0开发写function的逻辑,需要让模型思考、观察、行动。其实这个流程的循环其实就是ReAct框架的原理。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,699评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,124评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,127评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,342评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,356评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,057评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,654评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,572评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,095评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,205评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,343评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,015评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,704评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,196评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,320评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,690评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,348评论 2 358

推荐阅读更多精彩内容