第3周 Day 2:Function Calling —— 让 Agent 听懂人话,自己干活

0 阅读6分钟

上周做完英语 Agent 后,我发现一个问题:用户得自己点按钮才能触发功能。

比如想学单词,得先点"学习单词"按钮,然后输入单词。

Agent 不会自己判断用户想干什么

我想让它更智能一点——用户直接说"我想学 cat",Agent 就自动调用学习功能,而不是让用户先选按钮。

这就要用到 Function Calling


一、什么是 Function Calling?

场景对比

没有 Function Calling有 Function Calling
AI:"我不会查天气"AI:自动调用 get_weather()
AI:"我不会查你的订单"AI:自动调用 get_order()
AI:"我不知道你学了什么"AI:自动调用 get_learning_history()

Function Calling = 给 AI 一个工具箱,它会自己判断用什么工具

和"我写代码调用 API"的区别

方式流程
我写代码调用 API我写代码 → 用户点按钮 → 代码调用 API → 返回结果
Function Calling用户说话 → AI 自己判断 → AI 调用函数 → 返回结果

区别在于"谁在判断"

  • 我写代码:提前安排好,用户点按钮就调用某某接口
  • Function Calling:AI实时判断用户的话,自己决定调用什么

打个比方:

方式比喻
我写代码我给服务员一个菜单,顾客只能点菜单上的菜
Function Calling我给服务员一个厨房,顾客说要什么,服务员自己找食材做

二、Function Calling 怎么工作?

整个流程:

image.png AI 不是真的会"学单词",但它知道这件事可以用 learn_word 函数来做


三、实战:升级英语 Agent

目标很明确:

之前现在
用户点按钮 → 输入单词 → 系统处理用户说"我想学 cat" → Agent 自动调用学习功能
用户点按钮 → 等待随机单词 → 输入答案用户说"给我一个测验题" → Agent 自动出题

一句话:把"点按钮"变成"说人话"


步骤 1:定义工具箱

首先,我要告诉 Agent 有哪些工具可用:

TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "learn_word",
            "description": "学习一个英语单词,用户想学某个单词时调用",
            "parameters": {
                "type": "object",
                "properties": {
                    "word": {"type": "string", "description": "要学习的英文单词"}
                },
                "required": ["word"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_random_word",
            "description": "获取一个随机单词用于测验,用户想做测验时调用",
            "parameters": {"type": "object", "properties": {}}
        }
    },
    {
        "type": "function",
        "function": {
            "name": "check_answer",
            "description": "检查用户的测验答案,用户回答测验题时调用",
            "parameters": {
                "type": "object",
                "properties": {
                    "user_answer": {"type": "string", "description": "用户的答案"}
                },
                "required": ["user_answer"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_history",
            "description": "查看学习历史,用户想知道学了什么时调用",
            "parameters": {"type": "object", "properties": {}}
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_wrong_words",
            "description": "查看错题本,用户想复习错题时调用",
            "parameters": {"type": "object", "properties": {}}
        }
    }
]

这就是"工具说明书",告诉 AI:

  • 我有 5 个工具:学习、测验、检查答案、查历史、查错题
  • 每个工具需要什么参数

步骤 2:实现真正的函数

AI 只会告诉我们"调用什么函数",不会真的执行函数。执行还得靠我们。

# 单词库
WORDS = [
    {"en": "cat", "cn": "猫"},
    {"en": "dog", "cn": "狗"},
    {"en": "bird", "cn": "鸟"},
    {"en": "apple", "cn": "苹果"},
    {"en": "happy", "cn": "开心的"},
]

def learn_word(word):
    """学习单词"""
    for w in WORDS:
        if w["en"] == word.lower():
            return {"success": True, "word": w["en"], "cn": w["cn"]}
    return {"success": False, "message": f"单词 '{word}' 不在库里"}

def get_random_word():
    """获取测验题"""
    import random
    w = random.choice(WORDS)
    return {"success": True, "cn": w["cn"], "en": w["en"]}

def check_answer(user_answer):
    """检查答案"""
    # 检查是否正确...

def get_history():
    """查看历史"""
    return {"success": True, "total": 5, "words": ["cat", "dog"]}

def get_wrong_words():
    """查看错题"""
    return {"success": True, "wrong_words": [...]}

# 函数映射表
FUNCTION_MAP = {
    "learn_word": learn_word,
    "get_random_word": get_random_word,
    "check_answer": check_answer,
    "get_history": get_history,
    "get_wrong_words": get_wrong_words
}

步骤 3:实现 Function Calling 流程

def chat(user_input: str) -> str:
    # 1. 把用户消息发给 AI(带上工具定义)
    messages = [
        {"role": "system", "content": "你是英语学习助手,根据用户需求调用对应函数"},
        {"role": "user", "content": user_input}
    ]

    data = {
        "model": "glm-5",
        "messages": messages,
        "tools": TOOLS,  # 关键:告诉 AI 有哪些工具
        "tool_choice": "auto"  # 让 AI 自己决定是否调用
    }

    response = requests.post(API_URL, headers=API_HEADERS, json=data)
    result = response.json()

    # 2. 检查 AI 是否要调用函数
    message = result["choices"][0]["message"]

    if "tool_calls" in message and message["tool_calls"]:
        # AI 要调用函数
        for tool_call in message["tool_calls"]:
            function_name = tool_call["function"]["name"]
            arguments = json.loads(tool_call["function"]["arguments"])

            # 3. 执行函数
            # **arguments 是字典解包,把 {"word": "cat"} 变成 learn_word(word="cat")
            func_result = FUNCTION_MAP[function_name](**arguments)

            # 4. 把结果发给 AI,让它回答用户
            messages.append({
                "role": "tool",
                "tool_call_id": tool_call["id"],
                "name": function_name,
                "content": json.dumps(func_result)
            })

        # 5. 再次调用 AI,获取最终回答
        response2 = requests.post(API_URL, headers=API_HEADERS, json={"model": "glm-5", "messages": messages})
        return response2.json()["choices"][0]["message"]["content"]

    else:
        # AI 直接回答了(不需要调用函数)
        return message.get("content", "")

步骤 4:测试效果

动画.gif 测试 1:学习单词

用户: 我想学 cat 这个单词
AI: 让我帮你学习 cat...
    → 调用 learn_word("cat")
    → 结果:{"word": "cat", "cn": "猫"}
AI 回答: cat"猫"的意思,一种常见的宠物。

测试 2:获取测验题

用户: 给我一个测验题
AI: 测验来了!
    → 调用 get_random_word()
    → 结果:{"cn": "狗", "en": "dog"}
AI 回答: 中文意思是「狗」,请猜英文单词是什么?

测试 3:查历史

用户: 我学过哪些单词?
AI: 你已经学了 5 个单词:cat、dog、bird...
    → 调用 get_history()

成功!AI 能自动判断要调用什么函数。


四、踩坑记录

Q1:AI 返回了多个函数调用怎么办?

用户说"帮我查北京和上海的天气",AI 可能返回两个 get_weather 调用。

咋办:循环执行每个函数调用,把所有结果给 AI。

Q2:AI 没有调用函数,直接回答了?

用户说"你好",AI 直接回答问候。

原因:这句话不需要调用函数,检查 tool_calls 是否为空即可。

Q3:GLM-5 的 Function Calling 格式?

GLM-5 使用 OpenAI 兼容格式,可以直接用:

{
    "choices": [{
        "message": {
            "tool_calls": [{
                "id": "call_xxx",
                "function": {
                    "name": "learn_word",
                    "arguments": "{\"word\": \"cat\"}"
                }
            }]
        }
    }]
}

五、和上周的英语 Agent 对比

上周的 Agent这周的 Agent
用户点击按钮触发功能用户说人话触发功能
功能写在代码里,我提前安排好AI 自己判断要用什么功能
只能做我定义的 4 种功能可以扩展更多功能(只需加工具定义)

本质区别:从"我安排"变成"AI 判断"。


六、今日总结

今天干了啥:

  • ✅ 理解 Function Calling 是什么(AI 自己决定用什么工具)
  • ✅ 理解 Function Calling 和"写代码调用 API"的区别(谁在判断)
  • ✅ 把英语 Agent 升级成能"听懂人话"的版本
  • ✅ 实现完整流程(用户说话 → AI 判断 → 执行函数 → AI 回答)

明天要干的:

  • 学习 RAG(检索增强生成)
  • 让 Agent 能读取用户的数据,回答"个性化问题"

写于 2026-04-21,Function Calling —— 让 Agent 听懂人话,自己干活

image.png