function Calling工具系统怎么实现

模型怎么调用工具

模型不能直接执行命令,不能直接访问文件系统;模型不能直接操作任何东西,只能输出文案(模型底层生成 Token 序列,但模型 API 可以按照协议把生成结果解释和暴露为文本、工具调用、结构化数据或其他类型的输出);那么模型怎么动手,它会输出一个协作协议,叫function Calling,也叫tool Use;整个流程分四步

  1. 告诉模型有哪些工具

    • 模型要调用工具需要先知道有哪些工具可以调用
    json 复制代码
    ​{​"tools": [{​
        "name": "ReadFile",​
            "description": "读取指定路径的文件内容。返回带行号的文件文本。路径必须是绝对路径。",
            ​"input_schema": {
                ​"type": "object",
                ​"properties": {
                ​"path": {
                    ​"type": "string",
                    ​"description": "文件的绝对路径"
                  ​}
                ​},
            ​"required": ["path"]
          ​}
        ​}]
    ​}

    注意:工具描述是整个工具系统里最重要的部分,直接决定了模型的工具使用行为,包括了什么时候调,调哪个,参数怎么传

    工具接口 复制代码
    {  
        ​name() -> string​
        description() -> string
        ​inputSchema() -> JSON Schema
        ​execute(context, input) -> ToolResult
        ​isReadOnly() -> boolean
        ​isDestructive() -> boolean
        ​isConcurrencySafe(input) -> boolean
        ​category() -> string
        ​validateInput(input) -> error or null
    ​}
  2. 模型决定调用工具

    • 当模型认为需要调用某个工具时,会在回复里发起一个结构化请求, 这一步还没有开始执行工具,只是发起调用请求
    json 复制代码
    {
        "role": "assistant",
        "content": [{
            "type": "text",
            "text": "让我读取这个文件的内容。"
            },{
            "type": "tool_use",
            "id": "toolu_abc123",
            "name": "ReadFile",
            "input": {"path": "/home/user/project/main.py"}
           }
         ]
    }

3.agent执行工具,把结果告诉模型

  • 拿到模型的tool_use请求后,执行对应的操作,比如执行某个命令,把结果作为tool_result发回给模型
swift 复制代码
{
    "role": "user",
    "content": [{
        "type": "tool_result",
        "tool_use_id": "toolu_abc123",  // 和上面发起调用请求的id对应,模型才指定是哪个工具的结果
        "content": "1\tdef main():\n2\t print('hello')\n3\t"
      }]
}

注意: tool_result是user侧发送的请求,因为在对话的角度看,模型只负责思考决策,不负责执行,执行是用户的操作,所以执行结果是用户反馈给模型的

4.模型继续

  • 模型拿到工具结果后做出下一步决策,看是否需要调用下一个工具还是直接给出答案

一个工具的全生命周期

  • 六个内置核心工具
    • ReadFile
    • WriteFile
    • EditFile
    • Bash (bash命令 最强大 最危险)
    • Glob (找文件)
    • Grep (找内容)

mcp工具生命周期

mcp和普通工具都实现一样的Tool接口,包装成普通工具注册到字典,调用和内置工具一个流程;mcp只是对工具集的拓展,调用还是和functionCalling一样

python 复制代码
class Tool(ABC):
    name: str
    description: str
    params_model: type[BaseModel]
    category: ToolCategory = "read"
    is_concurrency_safe: bool = False
    is_system_tool: bool = False
    should_defer: bool = False

    @property
    def is_read_only(self) -> bool:
        return self.category == "read"

    def get_schema(self) -> dict[str, Any]:
        schema = self.params_model.model_json_schema()
        schema.pop("title", None)

        return {
            "name": self.name,
            "description": self.description,
            "input_schema": schema,
        }

    @abstractmethod
    async def execute(self, params: BaseModel) -> ToolResult: ...
相关推荐
Lank_M3 小时前
白底都占八成,PNG 为何只在图表页赢过 JPG
前端
张一凡933 小时前
给 Coding Agent 加一道"架构闸门":Jin 是如何做到"先审架构、再写代码、不漂移"的
前端·后端·agent
Linye3 小时前
AI 写的 HTML 原型全是空壳?聊聊真实 DOM 交互避坑
前端·人工智能
ZANE3 小时前
纯前端实现的 PDF 与图片互相转换工具技术实现
前端
Swot3 小时前
SvelteKit Remote Functions 使用指南
前端·后端
Cooper254 小时前
三源热榜去重加 AI 摘要:URL 唯一键踩出的三个坑
前端·python
Yk酱228404 小时前
A2UI探索随笔-技术选型
前端
前端繁华如梦4 小时前
# 从 73000 行压缩代码到 TypeScript 模块化:我把一个 Three.js FPS 游戏 1:1 复刻了一遍
前端
Penge6664 小时前
React Context 详解:从 Props 传递到跨组件状态共享
前端
Penge6664 小时前
React 事件处理:bind(this) 原理与实际开发常用写法
前端