LLM 如何进行动态 API 调用?
概览部分
内容摘要
本视频详细讲解了如何让大语言模型(LLM)实现动态 API 调用。通过具体案例分析,揭示了常见的错误和误区,如函数定义不清晰、参数描述不完整等。视频还介绍了 Agent Loop 的工作原理、工具描述的编写规范、React 策略的核心思想,以及在实际应用中需要注意的几个关键点,包括容错机制、循环限制和业务逻辑的前置条件设置。
核心观点
- LLM 本身不具备调用 API 的能力,需要通过"操作系统"(Agent Loop)来引导其执行动作
- 函数定义必须包含名称、功能描述和参数说明,缺一不可
- React 策略是让 LLM 展示思考过程的关键手段
- 实际应用中需注意容错机制、参数精确性和任务循环限制
- 调 API 是一个不断"调教"的过程,没有一步到位的方案
目录
- [LLM 调 API 的基本原理](#LLM 调 API 的基本原理)
1.1 [什么是 Agent Loop?](#什么是 Agent Loop?)
1.2 函数定义的重要性 - [React 策略详解](#React 策略详解)
- 常见踩坑与解决方案
3.1 [不要假设 LLM 知道业务逻辑](#不要假设 LLM 知道业务逻辑)
3.2 参数类型要精确到每个值
3.3 做好容错机制
3.4 设置任务循环上限 - 总结与行动建议
1. LLM 调 API 的基本原理
1.1 什么是 Agent Loop?
Agent Loop 是一种机制,它为 LLM 提供了一个"操作系统",使其能够根据用户的输入,决定何时调用 API,并按照正确的格式传递参数。简单来说,它是一个控制流程的框架,帮助 LLM 在复杂的任务中做出决策。
核心思想: LLM 只是一个文本生成器,它不知道自己该做什么。你必须为它设计一套"操作规则",让它知道在什么情况下该调用哪个 API,以及如何传递参数。
示例流程
#mermaid-svg-rOLInARgirQex8ax{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rOLInARgirQex8ax .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rOLInARgirQex8ax .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rOLInARgirQex8ax .error-icon{fill:#552222;}#mermaid-svg-rOLInARgirQex8ax .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rOLInARgirQex8ax .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rOLInARgirQex8ax .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rOLInARgirQex8ax .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rOLInARgirQex8ax .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rOLInARgirQex8ax .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rOLInARgirQex8ax .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rOLInARgirQex8ax .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rOLInARgirQex8ax .marker.cross{stroke:#333333;}#mermaid-svg-rOLInARgirQex8ax svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rOLInARgirQex8ax p{margin:0;}#mermaid-svg-rOLInARgirQex8ax .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rOLInARgirQex8ax .cluster-label text{fill:#333;}#mermaid-svg-rOLInARgirQex8ax .cluster-label span{color:#333;}#mermaid-svg-rOLInARgirQex8ax .cluster-label span p{background-color:transparent;}#mermaid-svg-rOLInARgirQex8ax .label text,#mermaid-svg-rOLInARgirQex8ax span{fill:#333;color:#333;}#mermaid-svg-rOLInARgirQex8ax .node rect,#mermaid-svg-rOLInARgirQex8ax .node circle,#mermaid-svg-rOLInARgirQex8ax .node ellipse,#mermaid-svg-rOLInARgirQex8ax .node polygon,#mermaid-svg-rOLInARgirQex8ax .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rOLInARgirQex8ax .rough-node .label text,#mermaid-svg-rOLInARgirQex8ax .node .label text,#mermaid-svg-rOLInARgirQex8ax .image-shape .label,#mermaid-svg-rOLInARgirQex8ax .icon-shape .label{text-anchor:middle;}#mermaid-svg-rOLInARgirQex8ax .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rOLInARgirQex8ax .rough-node .label,#mermaid-svg-rOLInARgirQex8ax .node .label,#mermaid-svg-rOLInARgirQex8ax .image-shape .label,#mermaid-svg-rOLInARgirQex8ax .icon-shape .label{text-align:center;}#mermaid-svg-rOLInARgirQex8ax .node.clickable{cursor:pointer;}#mermaid-svg-rOLInARgirQex8ax .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rOLInARgirQex8ax .arrowheadPath{fill:#333333;}#mermaid-svg-rOLInARgirQex8ax .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rOLInARgirQex8ax .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rOLInARgirQex8ax .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rOLInARgirQex8ax .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rOLInARgirQex8ax .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rOLInARgirQex8ax .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rOLInARgirQex8ax .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rOLInARgirQex8ax .cluster text{fill:#333;}#mermaid-svg-rOLInARgirQex8ax .cluster span{color:#333;}#mermaid-svg-rOLInARgirQex8ax div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rOLInARgirQex8ax .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rOLInARgirQex8ax rect.text{fill:none;stroke-width:0;}#mermaid-svg-rOLInARgirQex8ax .icon-shape,#mermaid-svg-rOLInARgirQex8ax .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rOLInARgirQex8ax .icon-shape p,#mermaid-svg-rOLInARgirQex8ax .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rOLInARgirQex8ax .icon-shape .label rect,#mermaid-svg-rOLInARgirQex8ax .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rOLInARgirQex8ax .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rOLInARgirQex8ax .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rOLInARgirQex8ax :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
是
否
用户提问
是否需要调用API?
生成Action
调用API
API返回结果?
生成最终回答
错误处理/重试
这个流程展示了 LLM 调用 API 的典型路径:首先判断是否需要调用 API,如果需要,则生成相应的 Action,调用 API 后根据返回结果生成最终回答或进行错误处理。
1.2 函数定义的重要性
很多人以为只要给 LLM 一个函数定义,它就能自动学会什么时候调用。但实际情况是,LLM 不知道这些函数是干什么的,除非你明确告诉它。
正确的函数定义应包含以下三个要素:
- 函数名 :例如
get_weather - 功能描述:例如 "查询指定城市的当前天气状况"
- 参数说明 :例如:
city:城市名称,必须是中文全称(如北京、上海、深圳)status:状态,只接受active、inactive、pending,不能随意填写其他值
关键观点: 如果函数定义不清晰,LLM 就无法正确调用 API。它只会按照你给它的输入,输出下一个 token,而不会主动判断是否需要调用 API。
错误案例
有一位朋友尝试让 LLM 调用天气 API,他写了一个 get_weather 函数,但 LLM 返回的是一段关于天气的散文,而不是调用 API 的指令。原因在于,LLM 并不知道这个函数的作用,也没有被明确告知它应该在什么情况下使用这个函数。
2. React 策略详解
2.1 什么是 React 策略?
React 策略是一种让 LLM 展示其推理过程的方法。它要求 LLM 在每一步不仅给出行动(Action),还要输出其推理过程(Thought)。这种策略有助于开发者理解 LLM 的思考逻辑,并及时发现错误。
典型格式如下:
markdown
Thought: 用户想知道北京今天的天气情况。
Action: get_weather
Action Input: {"city": "北京"}
Observation: {"temperature": 28, "weather": "晴", "humidity": "45%"}
Thought: 获取到了北京今天的天气数据。
Action: final_answer
Action Input: {"answer": "温度28度,晴天,湿度45%,天气很好,适合出门。"}
核心思想: React 策略让 LLM 的行为变得透明,便于调试和优化。
3. 常见踩坑与解决方案
3.1 不要假设 LLM 知道你的业务逻辑
很多开发者在定义函数时,只写了"取消订单"这样的简单描述,但 LLM 可能会误解为"直接执行取消操作"。例如,有一个电商机器人,传入了 cancel_order,但用户说"算了不要了",而 LLM 仍然执行了取消操作,因为没有明确的前置条件。
关键建议 : 在函数描述中,必须明确写出前置条件,例如:"只有当订单状态为'已下单'时,才允许取消。"
3.2 参数类型要精确到每个值
LLM 有时会传递不符合预期的参数,例如将 status 设为 running 而不是 active,导致接口报错。因此,必须在参数描述中明确列出所有合法值。
对比表格(错误 vs 正确)
| 参数 | 错误描述 | 正确描述 |
|---|---|---|
| status | 接受任意字符串 | 仅接受 active, inactive, pending |
关键建议: 参数描述要尽可能详细,避免模糊表达。
3.3 做好容错机制
LLM 第一次调用 API 时,大概率会出错,可能是参数格式不对,也可能是漏了必填字段。因此,必须设计重试机制或错误反馈机制,让 LLM 能够自我修正。
示例容错流程
#mermaid-svg-uMJMxnAnLat6OQAu{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uMJMxnAnLat6OQAu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uMJMxnAnLat6OQAu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uMJMxnAnLat6OQAu .error-icon{fill:#552222;}#mermaid-svg-uMJMxnAnLat6OQAu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uMJMxnAnLat6OQAu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uMJMxnAnLat6OQAu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uMJMxnAnLat6OQAu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uMJMxnAnLat6OQAu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uMJMxnAnLat6OQAu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uMJMxnAnLat6OQAu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uMJMxnAnLat6OQAu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uMJMxnAnLat6OQAu .marker.cross{stroke:#333333;}#mermaid-svg-uMJMxnAnLat6OQAu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uMJMxnAnLat6OQAu p{margin:0;}#mermaid-svg-uMJMxnAnLat6OQAu .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-uMJMxnAnLat6OQAu .cluster-label text{fill:#333;}#mermaid-svg-uMJMxnAnLat6OQAu .cluster-label span{color:#333;}#mermaid-svg-uMJMxnAnLat6OQAu .cluster-label span p{background-color:transparent;}#mermaid-svg-uMJMxnAnLat6OQAu .label text,#mermaid-svg-uMJMxnAnLat6OQAu span{fill:#333;color:#333;}#mermaid-svg-uMJMxnAnLat6OQAu .node rect,#mermaid-svg-uMJMxnAnLat6OQAu .node circle,#mermaid-svg-uMJMxnAnLat6OQAu .node ellipse,#mermaid-svg-uMJMxnAnLat6OQAu .node polygon,#mermaid-svg-uMJMxnAnLat6OQAu .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uMJMxnAnLat6OQAu .rough-node .label text,#mermaid-svg-uMJMxnAnLat6OQAu .node .label text,#mermaid-svg-uMJMxnAnLat6OQAu .image-shape .label,#mermaid-svg-uMJMxnAnLat6OQAu .icon-shape .label{text-anchor:middle;}#mermaid-svg-uMJMxnAnLat6OQAu .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uMJMxnAnLat6OQAu .rough-node .label,#mermaid-svg-uMJMxnAnLat6OQAu .node .label,#mermaid-svg-uMJMxnAnLat6OQAu .image-shape .label,#mermaid-svg-uMJMxnAnLat6OQAu .icon-shape .label{text-align:center;}#mermaid-svg-uMJMxnAnLat6OQAu .node.clickable{cursor:pointer;}#mermaid-svg-uMJMxnAnLat6OQAu .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uMJMxnAnLat6OQAu .arrowheadPath{fill:#333333;}#mermaid-svg-uMJMxnAnLat6OQAu .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uMJMxnAnLat6OQAu .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uMJMxnAnLat6OQAu .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uMJMxnAnLat6OQAu .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uMJMxnAnLat6OQAu .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uMJMxnAnLat6OQAu .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uMJMxnAnLat6OQAu .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uMJMxnAnLat6OQAu .cluster text{fill:#333;}#mermaid-svg-uMJMxnAnLat6OQAu .cluster span{color:#333;}#mermaid-svg-uMJMxnAnLat6OQAu div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-uMJMxnAnLat6OQAu .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uMJMxnAnLat6OQAu rect.text{fill:none;stroke-width:0;}#mermaid-svg-uMJMxnAnLat6OQAu .icon-shape,#mermaid-svg-uMJMxnAnLat6OQAu .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uMJMxnAnLat6OQAu .icon-shape p,#mermaid-svg-uMJMxnAnLat6OQAu .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uMJMxnAnLat6OQAu .icon-shape .label rect,#mermaid-svg-uMJMxnAnLat6OQAu .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uMJMxnAnLat6OQAu .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uMJMxnAnLat6OQAu .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uMJMxnAnLat6OQAu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
调用API
成功?
生成回答
记录错误信息
尝试重试
关键建议: 容错机制可以显著提升系统的稳定性和用户体验。
3.4 设置任务循环上限
LLM 的 Agent Loop 理论上可以无限运行,但如果没设置上限,可能会出现"死循环"或"无限调用"问题。例如,一个任务可能跑了 200 多轮,耗费大量 Token。
关键建议: 建议设置最大循环次数,例如最多 10 次,防止资源浪费。
4. 总结与行动建议
全文总结
LLM 动态 API 调用并不是一个简单的"写个函数就完事"的过程。它需要一套完整的系统支持,包括 Agent Loop、函数定义、React 策略、容错机制和循环限制。只有把这些元素组合在一起,才能让 LLM 真正具备调用 API 的能力。
从视频中我们可以看到,很多开发者在实际应用中遇到了各种问题,比如函数定义不清晰、参数描述不准确、业务逻辑未明确等。这些问题都源于对 LLM 的能力认识不足,或者没有为它设计一套合适的"操作系统"。
核心收获
- LLM 本身不具备调用 API 的能力,必须通过 Agent Loop 引导
- 函数定义必须包含名称、功能描述和参数说明
- React 策略可以帮助我们理解 LLM 的推理过程
- 必须在函数描述中明确前置条件和参数范围
- 容错机制和循环限制是系统稳定性的关键
- 调 API 是一个持续"调教"的过程,没有一步到位的方案
行动建议
- 重新审视函数定义:确保每个 API 调用都有清晰的名称、功能描述和参数说明
- 引入 React 策略:让 LLM 显示其推理过程,便于调试和优化
- 建立容错机制:设计重试逻辑,提高系统稳定性
- 设置循环限制:防止无意义的重复调用
- 明确业务逻辑:在函数描述中加入前置条件,避免误操作
延伸思考
- LLM 是否可以通过学习历史调用日志来自动优化 API 调用?
- 在多模态场景下,如何结合图像识别和 API 调用?
- 未来是否有更智能的"自动化 API 调用"系统出现?
附录(可选)
术语表
- Agent Loop:LLM 的控制流程机制,用于决定何时调用 API。
- React 策略:一种让 LLM 展示推理过程的方法,增强可解释性。
- Token:LLM 处理的基本单位,通常指一个字或词。
- API:应用程序编程接口,用于系统间的数据交互。