怎么做正规网站,商标号在线查询,东莞网络营销网站建设,手机网站带后台源代码本文档将带你深入理解 AI Agent 的核心机制#xff1a;如何让大模型连接外部世界。我们将从最基础的概念出发#xff0c;一步步揭示技术背后的原理。 1. 什么是 Tool Calling (工具调用)#xff1f;
核心定义#xff1a; Tool Calling 是指赋予大语言模型#xff08;LLM如何让大模型连接外部世界。我们将从最基础的概念出发一步步揭示技术背后的原理。1. 什么是 Tool Calling (工具调用)核心定义Tool Calling 是指赋予大语言模型LLM使用外部工具的能力。如果说 LLM 是一个博学的“大脑”那么 Tool Calling 就是给它装上了“手”和“眼睛”。1.1 为什么 LLM 需要工具(The Why)LLM 本质上是一个“文本生成器”它有三大先天缺陷必须通过使用工具来弥补无法获取实时信息痛点它的知识截止于训练结束的那一天比如不知道今天的股价。工具搜索引擎、天气 API、股票接口。数学与逻辑短板痛点它是基于概率预测下一个字的做算术题经常瞎编幻觉。工具计算器、Python 解释器。无法与世界交互痛点它只能生成文字不能真正地“做事”副作用。工具发邮件 API、数据库写入接口、智能家居控制器。2. 实现 Tool Calling 的两种方式既然 Tool Calling 是目的那么我们该如何实现它呢主要有两种技术路线方式 APrompt Engineering (提示词工程)这是在早期模型如 GPT-3中常用的方法也称为ReAct 模式。做法在 System Prompt 里写死规则“如果你要用工具请按这个格式输出Action: search, Action Input: query”。缺点非常不稳定。模型经常忘记格式或者输出少个括号导致程序无法解析。方式 BFunction Calling (函数调用)这是现代模型如 GPT-4, Gemini引入的原生能力。做法直接把工具的定义JSON Schema传给模型 API。优点模型经过专门训练Fine-tuning能百分之百输出符合语法的结构化数据JSON。结论Function Call 是实现 Tool Calling 的最佳实践。3. 深入解析Function Call 技术原理Function Call 本质上解决了“自然语言”到“机器指令”的翻译问题。关键认知LLM 永远不会自己执行代码。当触发 Function Call 时LLM 只是生成了一个文本指令JSON。真正执行代码的依然是你的 Python/Java 后端。3.1 核心工作流程 (Workflow)这是一个“LLM - 代码 - LLM”的三明治结构。UserLLM (Brain)App (Python Code)Tool (Function)AppLLMToolWhat is 123 * 456?1. App 把用户问题 工具定义(Schema) 发给 LLMPrompt Tools Definition2. LLM 思考这需要计算我要调用 multiplyResponse (包含 tool_calls: multiply(123, 456))3. App 暂停生成去执行本地代码执行 multiply(123, 456)返回结果 560884. App 把运行结果作为 ToolMessage 发回给 LLMUser Prompt Tool Call Tool Result(56088)5. LLM 看到结果生成最终回答The answer is 56088.The answer is 56088.UserLLM (Brain)App (Python Code)Tool (Function)AppLLMTool3.2 数据结构解密 (Under the Hood)当我们说“定义工具”时到底发给了 LLM 什么通常是JSON Schema。发送给 LLM 的工具定义{name:multiply,description:Multiplies two integers.,parameters:{type:object,properties:{a:{type:integer},b:{type:integer}},required:[a,b]}}LLM 返回的调用指令{tool_calls:[{name:multiply,arguments:{\a\: 123, \b\: 456}}]}4. 技术演进与未来ReAct 时代靠 Prompt 苦苦支撑极不稳定。Native Function Calling模型微调稳定性大增成为行业标准。Agents (智能体)能够自主规划、连续多轮调用工具完成复杂任务。MCP (Model Context Protocol)未来的通用标准。它像 USB 协议一样定义了数据和工具的接口标准让 AI 能即插即用地连接任何系统。5. 实战示例对比我们在src/examples/function_call/下提供了三种实现方式的对比。以下是每种方式的完整代码及深度解析。示例 1: LangChain Native 方式 (推荐)这是现代 AI 应用开发的标准做法利用 LangChain 封装好的接口代码最简洁兼容性最好。文件:src/examples/function_call/demo_with_function_call.pyimportsrc.configs.configfromloguruimportloggerfromlangchain_core.toolsimporttoolfromsrc.llm.gemini_chat_modelimportget_gemini_llm# 1. 定义工具 (使用 tool 装饰器)tooldefmultiply(a:int,b:int)-int:Multiplies two integers.returna*b# 2. 初始化 LLMllmget_gemini_llm()# 3. 绑定工具 (Native Function Calling)# 这会把工具的 schema 转换为 Gemini API 能理解的格式 (Function Declaration)llm_with_toolsllm.bind_tools([multiply])# 4. 执行logger.info( Demo: Native Function Calling (bind_tools) )queryWhat is 123 multiplied by 456?logger.info(fUser Question:{query})responsellm_with_tools.invoke(query)logger.info(fLLM Response Type:{type(response)})logger.info(fLLM Response Content:{response.content})# 5. 检查是否触发了 Function Callifresponse.tool_calls:logger.info(Tool Call Detected!)fortool_callinresponse.tool_calls:logger.info(fTool Name:{tool_call[name]})logger.info(fArguments:{tool_call[args]})# 执行工具 (可选)iftool_call[name]multiply:resultmultiply.invoke(tool_call[args])logger.info(fTool Execution Result:{result})else:logger.info(No tool call detected.)深度代码解析tool:作用: LangChain 提供的装饰器。它不仅定义了函数还会自动提取函数的docstring文档字符串和类型注解Type Hints将其转换为 LLM 能理解的JSON Schema描述。重要性: 文档字符串写得越好LLM 越能准确理解何时调用这个工具。llm.bind_tools([multiply]):作用: 这是 LangChain 的核心适配器方法。功能: 它将 Python 函数列表转换为特定 LLM 提供商这里是 Google Gemini所需的 API 格式如FunctionDeclaration。对于 OpenAI它会转换为functions或tools参数格式。返回值: 返回一个新的Runnable对象这个对象已经“知道”了这些工具的存在。response.tool_calls:作用:AIMessage对象的一个属性。如果模型决定调用工具这个列表会包含调用信息。结构:[{name: multiply, args: {a: 123, b: 456}, id: ...}]。优势: 这是一个标准的 Python 字典/对象不需要你去解析原始的 JSON 字符串LangChain 已经帮你解析好了。示例 2: Manual / ReAct 方式 (手动 Prompt)这是在 Function Calling 技术出现之前的做法。虽然现在不推荐用于新模型但了解它有助于理解 Function Call 的本质。文件:src/examples/function_call/demo_no_function_call.pyimportsrc.configs.configfromloguruimportloggerfromlangchain_core.promptsimportChatPromptTemplatefromsrc.llm.gemini_chat_modelimportget_gemini_llm# 1. 定义工具 (Tools)defmultiply(a:int,b:int)-int:Multiplies two integers.returna*bdefmain():# 2. 初始化 LLMllmget_gemini_llm()# 3. 定义 ReAct 风格的 Prompt (手动教 LLM 如何调用工具)# 我们不使用 bind_tools而是把工具描述写在 Prompt 里react_system_prompt You are a helpful assistant. You have access to the following tools: 1. multiply: Multiplies two integers. Input should be two numbers separated by a comma. To use a tool, please use the following format exactly: Thought: Do I need to use a tool? Yes Action: multiply Action Input: 5, 4 Observation: [Tool output will be placed here] If you do not need to use a tool, just answer the question directly. promptChatPromptTemplate.from_messages([(system,react_system_prompt),(user,{input})])chainprompt|llm# 4. 执行logger.info( Demo: Manual Tool Usage (No Function Call) )queryWhat is 123 multiplied by 456?logger.info(fUser Question:{query})responsechain.invoke({input:query})contentresponse.content logger.info(fLLM Response (Raw Content):\n{content})# 5. 手动解析并执行 (模拟 Agent 的工作)# 这是一个非常简化的解析器ifisinstance(content,str)andAction: multiplyincontent:try:# Extract input (Assuming format Action Input: x, y)linescontent.split(\n)action_input_linenext(lineforlineinlinesifline.strip().startswith(Action Input:))input_straction_input_line.split(:)[1].strip()args[int(x.strip())forxininput_str.split(,)]logger.info(fDetected Tool Call: multiply with args{args})# Execute toolresultmultiply(args[0],args[1])logger.info(fTool Execution Result:{result})exceptExceptionase:logger.error(fFailed to parse or execute tool:{e})else:logger.info(No tool call detected or format incorrect.)if__name____main__:main()深度代码解析Prompt Engineering (react_system_prompt):作用: 我们必须在 System Prompt 中手动写一段很长的说明书教 LLM“如果你要用工具请必须按这个格式写…”。痛点: 这非常消耗 Token而且模型很容易不遵守格式比如把Action Input写成了Input导致解析失败。手动解析逻辑 (Parsing Logic):作用: 代码中的if Action: multiply in content:和content.split(\n)部分。痛点: 这是非常脆弱的。我们必须用字符串匹配和正则表达式去“猜测”模型的意图。如果模型多输出一个空格或换行解析器可能就挂了。这正是Function Call致力解决的问题——把非结构化的文本解析变成结构化的 API 调用。示例 3: Google Native SDK 方式如果你不想引入 LangChain 的复杂性想直接使用 Google 官方 SDK这是最轻量级的选择。文件:src/examples/function_call/demo_gemini_native.pyimportosfromdotenvimportload_dotenvfromgoogleimportgenaifromgoogle.genaiimporttypes# 1. 加载环境变量load_dotenv()api_keyos.getenv(GOOGLE_API_KEY)ifnotapi_key:print(Error: GOOGLE_API_KEY not found in .env)exit(1)# 2. 定义工具函数defmultiply(a:int,b:int)-int:Multiplies two integers.returna*b# Wrapper 类定义 (省略见完整代码) ...defmain():# 3. 初始化 Clientclientgenai.Client(api_keyapi_key)# 4. 配置模型参数 (预定义配置)my_configtypes.GenerateContentConfig(tools[multiply],tool_configtypes.ToolConfig(function_calling_configtypes.FunctionCallingConfig(modetypes.FunctionCallingConfigMode.ANY# 强制模型使用工具)))# 5. 实例化封装后的 Modelprint( Demo: Native Gemini SDK (Wrapped Style) )my_modelGeminiModelWrapper(client,gemini-2.5-pro,my_config)# 6. 调用queryWhat is 123456 multiplied by 6854321?print(fUser Question:{query})responsemy_model.generate(query)# 7. 解析结果print(f\nResponse Text:{response.text})# 检查 Function Callsif(response.candidatesandresponse.candidates[0].contentandresponse.candidates[0].content.parts):forpartinresponse.candidates[0].content.parts:ifpart.function_call:fcpart.function_callprint(f\nFunction Call Detected:)print(f Name:{fc.name})print(f Args:{fc.args})# 增加对 fc.args 的非空检查以满足静态类型检查argsfc.argsiffc.namemultiplyandargsisnotNone:resultmultiply(int(args[a]),int(args[b]))print(f Execution Result:{result})if__name____main__:main()深度代码解析genai.Client:作用: Google GenAI V1 SDK 的核心入口。types.GenerateContentConfig:作用: 用于配置生成请求的参数。tools[multiply]: 这里的亮点是Google SDK 能够直接接受 Python 函数作为工具列表它内部会自动反射生成 JSON Schema无需手动编写 Schema。modetypes.FunctionCallingConfigMode.ANY:作用:强制模式。这告诉模型“不管用户问什么你必须调用一个工具不准直接回答文本”。场景: 当你明确知道这一步必须执行动作如计算、查询时使用。默认是AUTO模型自己决定用不用。part.function_call:作用: SDK 将返回的 JSON 指令反序列化为 Python 对象。属性: 包含name(函数名) 和args(参数字典)。这使得参数提取变得非常安全和简单。7. 常见误区 (Myth Busting)❌误区LLM 只要联网就能自己调用工具。✅真相LLM 必须由开发者显式地提供工具定义并在代码中显式地执行工具。它自己没有手。❌误区Function Call 只能调用 Python 函数。✅真相Function Call 只是输出文本指令。你的后端可以用 Python、Java、Go 甚至 Shell 脚本来执行这个指令。❌误区模型会无条件执行任何工具。✅真相模型会根据 Prompt 和上下文判断。但这也带来了安全风险Prompt Injection。千万不要给 LLM 一个delete_database()的工具而不加权限控制