大模型从对话走向行动:GLM与Function Calling的Agent工程实践

📅 发布时间:2026/9/3 5:47:45
大模型从对话走向行动:GLM与Function Calling的Agent工程实践 过去一段时间智谱向外释放的信息一直有一个关键词被反复提起The next-generation……。如果你只盯着 earning transcript 和 RSI 这些偏资本市场的词汇很容易把注意力放在股价、融资、估值这些东西上。但作为从 ChatGLM 时代就开始跟进 GLM 系列模型的开发者我更愿意把“下一代”这个被截断的句子看成一次技术路线切换的信号大模型正在从“能聊天”走向“能干活”从“文本生成接口”走向“参与生产流程的智能体”。这篇文章不打算复盘经营数字也不做二级市场分析。我想做的是另一件事从技术公开信息和产品动作出发拆解“下一代大模型”到底会往哪里走并整理出一套开发者在今天就能上手验证的实践路径。文章会先讲清楚几个关键技术信号然后带你在智谱开放平台上跑通一个最基本的 GLM API 调用再实现一个真正具备“干活”雏形的工具调用小循环。最后补充生产环境里最容易被忽视的规范、排查方法和工程建议。读完这篇文章你至少能回答三个问题第一为什么“大模型会调用工具”比“模型又涨了几分”更重要第二如果你想在真实业务里接入 GLM最小闭环长什么样第三从单次 Prompt 到可维护的 Agent 工程中间到底隔着哪些坑。1. 从 Chat 到 Act下一代大模型真正要跨越的边界过去两年大模型竞争的核心一直是 Chat谁能更准确地回答问题、谁能写出更长的代码、谁能在榜单上多拿零点几分。这些能力当然重要但它本质上还是在解决“模型如何理解语言并生成文本”的问题。Chat 再强也需要用户把问题拆好、把上下文喂够、把输出手工搬运到下一个系统里。“下一代”真正要跨越的边界是从 Chat 到 Act。Act 意味着模型不再只负责生成建议而是可以直接调用工具、操作系统、访问数据库、操作软件界面最终完成一个具体的任务目标。智谱旗下像 AutoGLM 这类在产品端探索已经显示出一种明确的产品意图让模型成为能“动手”的数字助理而不是只能“动嘴”的问答机器人。对普通开发者来说这个变化带来的影响远比想象中更早。你会发现当模型具备了调用工具的能力系统的控制权开始从传统程序逻辑向模型决策转移。过去我们写软件每个步骤都是 if/else 写死的现在模型会根据用户输入动态选择“调用天气接口还是查询订单系统”程序变成了“模型做决策、代码做执行、上下文做记忆”的新结构。这种结构变化才是“下一代”真正的技术含义。它不会以一次发布会为分界而是会逐步渗透到 API 设计、任务编排、权限管理、可观测性这些基础设施层。这也是为什么我认为现在还不能完整预测下一代模型形态的开发者至少应该先把 Agent 的最小运行原理搞清楚。2. 下一代大模型的关键技术信号如果把近一年各大模型公司的产品动作放在一起看下一代大模型的轮廓其实已经比较清楚了。这里我提炼出六个信号它们不是孤立的技术点而是一套相互咬合的能力集合。2.1 Agent 从演示走向生产系统上一轮 Agent 浪潮里很多人对 Agent 的印象还停留在“演示视频里自动点外卖、自动订机票”。这类演示的问题在于它只能在受控环境里完成。一旦遇到真实系统中的权限、异常、超时、多步回滚纯靠模型“自由发挥”就会失控。下一代模型需要在可靠性上达到可生产标准。它不再是一段漂亮的 Demo而是能够稳定地执行“理解任务 - 拆解步骤 - 调用工具 - 检查结果 - 失败重试”的循环。这里的关键不是模型本身变聪明了多少而是它周围的工程约束有没有跟上比如工具返回结果能否被正确解析、模型误判时系统能否及时兜底。从工程视角看Agent 化带来的最大变化是“异常处理前置”。传统程序里异常发生在确定的分支里Agent 系统里模型可能在任何一步产生幻觉所以必须引入结果校验、权限拦截、人工确认等机制。这意味着后端开发要开始用“应对不确定行为”的思路来设计接口。2.2 工具调用Function Calling成为默认能力如果说 Agent 是下一代模型的“身体”那 Function Calling 就是“双手”。当模型决定自己需要查询数据时它不再只是生成一段文字告诉你“你应该去查天气接口”而是直接输出一个结构化的工具调用请求由程序去执行真实函数并把结果回传。这个能力的价值被很多人低估了。它把模型从“语言系统”延伸成了“行动系统”。对企业应用而言可观测、可控制、可审计的函数调用远比如同一个人在聊天框里自由发挥要可靠。下一代模型的竞争中谁能把 Function Calling 做得更稳定谁就能更早接入严肃业务。同时Function Calling 也在重新定义接口设计。以前开放平台的核心资产是“文本生成质量”以后的核心能力会变成“模型对工具 Schema 的理解能力”。开发者写 JSON Schema 的方式会直接决定 Agent 能不能准确调用到正确的函数。2.3 多模态与操作界面模型开始“看懂”真实世界下一代模型的另一个信号是输入模态从文字扩展到图像、音频、视频甚至整个计算机屏幕。之前大模型理解世界靠的是用户用文字描述而现在它可以直接“看”截图、“看”文档、“看”界面。对 Agent 类产品来说多模态是刚需。因为很多现实任务的目标不是自然语言能清晰描述的比如“帮我把这个页面上第三行的错误信息提取出来”或者“根据这张图调整前端样式”。模型如果只能处理文本就无法完成这类操作。界面的理解能力也会让 Agent 的使用方式发生改变。过去我们要给 Agent 提供 API、提供数据库连接本质上还是“走后门”多模态 GUI Agent 走的是“前门”像人一样看屏幕、移动鼠标、点击按钮。这两种路线会长期并存但后者会拉低 Agent 接入现有系统的门槛。对于没有开放 API 的历史系统这种方式会很有用。2.4 上下文工程从“长文本窗口”走向“有效记忆”大模型的上下文窗口越做越长这成了一个营销焦点。但真实业务里真正的问题不是“能不能塞进 100 万字”而是“模型能不能在这么多信息里找到关键内容并持续跟踪任务状态”。有效的记忆比物理长度更重要。下一代模型需要把工作记忆和长期记忆分开。工作记忆是当前任务轮次里必须保留的上下文比如用户需求、中间结果长期记忆则需要通过向量检索、摘要、结构化存储等方式管理。你不能指望所有历史都堆在一个上下文窗口里那样成本会失控效果也会随信息噪声增加而下降。从开发角度这意味着我们需要重新重视状态管理。过去无状态 API 请求模型很省心但 Agent 天然是有状态的一个长任务可能横跨几十次工具调用。模型怎么记住自己执行到第几步、怎么避免重复执行、怎么在多轮对话中同步状态这些工程问题最后都会落到上下文设计上。2.5 推理效率与单位成本拐点“更大参数、更强效果”是上一个阶段的叙事。但到了下一代模型要想真正进入生产流程必须把单位任务的推理成本降到业务能接受的水平。智谱在模型迭代中同步强调推理效率和工程化能力本质上就是这个方向。效率竞争会体现在两个层面一是同样的模型结构如何把单次推理成本打下来包括 KV Cache 优化、量化推理、投机采样等二是如何通过路由把简单任务交给小模型把复杂任务留给大模型。混合模型架构会逐渐成为企业的默认选择而不是所有请求都打向同一个旗舰模型。这对开发者的启示是不要只盯“哪个模型分高”还要建立单位成本意识。同样一个流程如果小模型能在 95% 的场景下胜任成本可能只是大模型的十分之一那整体架构就应该支持灵活路由和模型降级。2.6 开源权重与 API 服务走向分工开源模型与商业化 API 之间的关系在下一代会变得更清晰而不是谁取代谁。开源权重承担的是“可控性”需求数据不能出域、需要深度定制、行业私有化部署这些场景天然倾向开源模型。API 服务承担的是“先进性与弹性”需求希望直接用最新能力、不想自己维护推理集群、需要快速验证产品。智谱同时在做开源模型和 API 服务这其实也是中国大模型厂商比较典型的技术分工。例如一些早期 GLM 开源模型就让很多团队用较低成本完成了私有化验证而高并发、多模态、最新能力的场景则继续用云端 API。对技术选型者来说最忌讳一开始就把路线锁死。比较稳妥的做法是让业务代码与具体模型解耦尽量通过 OpenAI 兼容接口或统一抽象层接入这样未来无论是换 API、还是切到本地开源模型成本都可控。3. 技术栈准备与前置条件看完前面的分析你可能已经想动手验证一下了。下面我以智谱开放平台为例演示从零跑通一个 GLM 模型调用再实现一次工具调用。在开始之前需要确认几个前置条件操作系统Windows / macOS / Linux 均可文中命令以 Linux/macOS 为例Windows 的差异我会标注。Python建议 3.9 或以上版本。账号在智谱开放平台注册账号并完成实名认证。API Key在平台的 API Key 管理页面创建注意只在服务端使用绝不要提交到 Git 仓库。SDK本文使用 OpenAI Python SDK 来调用兼容接口你也可以直接用 requests 发送 raw HTTP 请求。先创建项目目录和虚拟环境避免污染全局 Python 环境。mkdir glm-next-demo cd glm-next-demo python3 -m venv .venv source .venv/bin/activate # Windows 用户执行.venv\Scripts\activate pip install --upgrade openai python-dotenv安装完成后在项目根目录创建.env文件把 API Key 放进去cat .env EOF ZHIPU_API_KEY你的_API_Key ZHIPU_BASE_URLhttps://open.bigmodel.cn/api/paas/v4/ ZHIPU_MODEL_IDglm-4 EOF这里有一个很容易踩的坑不同文章里写的模型 ID 可能已经过时因为平台会持续下线或新增模型。我的建议是以后台模型列表和官方文档为准。代码里的ZHIPU_MODEL_ID使用环境变量维护换模型时不需要改业务代码。再创建一个简单的配置文件统一读取环境变量# config.py import os from dotenv import load_dotenv load_dotenv() ZHIPU_API_KEY os.environ[ZHIPU_API_KEY] ZHIPU_BASE_URL os.environ.get( ZHIPU_BASE_URL, https://open.bigmodel.cn/api/paas/v4/ ) ZHIPU_MODEL_ID os.environ.get(ZHIPU_MODEL_ID, glm-4)如果你在真实项目中接入多个模型服务商建议把这层封装得更通用一些。最基础的做法是把api_key、base_url、model三项做成可配置的数据类后续对接不同厂商时业务层不需要感知差异。4. 最基础的 GLM API 调用示例现在我们已经配置好了环境下一步就是跑通最小调用。智谱开放平台提供了 OpenAI 兼容接口所以我们可以直接用 OpenAI SDK 来请求。# chat_demo.py from openai import OpenAI import config client OpenAI( api_keyconfig.ZHIPU_API_KEY, base_urlconfig.ZHIPU_BASE_URL, ) def chat_with_glm(question: str) - str: response client.chat.completions.create( modelconfig.ZHIPU_MODEL_ID, messages[ {role: system, content: 你是一名严谨的中文技术助手。}, {role: user, content: question}, ], temperature0.3, ) return response.choices[0].message.content if __name__ __main__: answer chat_with_glm(请用三句话解释什么是 Agent) print(answer)这段代码有几个关键点值得说明。第一base_url必须指向智谱开放平台的 v4 接口地址这与 OpenAI 官方接口在路径结构上略有差异所以需要显式指定。第二messages中的 system 消息用于设定行为边界真实项目中不要省掉它因为模型在无约束状态下更容易跑偏。第三temperature0.3是一个比较稳妥的业务向参数如果你的场景要求结果可复现甚至可以调到 0。运行脚本python chat_demo.py如果一切正常你会看到模型输出一段解释 Agent 的中文文本。这里第一步验证的是“链路是否通”只要网络正常、API Key 有效基本不会有太大问题。如果报错优先检查.env文件是否存在、API Key是否复制完整以及网络到bigmodel.cn是否连通。5. 让模型真正“干活”Function Calling 最小实现API 通了之后我们要做更接近下一代模型形态的实验让模型在需要的时候申请调用一个本地函数。这里用最简单的“天气查询”作为例子虽然业务意义不大但能完整展示工具调用的协议循环。5.1 定义一个工具并请求模型调用我们先定义工具 Schema。这个 Schema 相当于给模型一份“API 使用说明书”告诉它有哪些函数、参数是什么、什么时候应该使用。# function_calling_demo.py import json import os from openai import OpenAI import config client OpenAI( api_keyconfig.ZHIPU_API_KEY, base_urlconfig.ZHIPU_BASE_URL, ) tools [ { type: function, function: { name: get_current_weather, description: 查询指定城市的当前天气用于回答出行、穿衣建议等问题, parameters: { type: object, properties: { city: { type: string, description: 城市名例如北京 } }, required: [city] } } } ] def get_current_weather(city: str) - str: 真实项目中请替换成天气服务 API 调用 weather_data { 北京: 晴25℃, 上海: 多云28℃, 广州: 雷阵雨30℃, } return weather_data.get(city, f{city} 暂无数据) def main(): response client.chat.completions.create( modelconfig.ZHIPU_MODEL_ID, messages[ {role: user, content: 北京今天适合跑步吗} ], toolstools, tool_choiceauto, ) message response.choices[0].message print(模型原始返回 content:, message.content) if not message.tool_calls: print(模型没有选择调用工具直接回答:, message.content) return tool_call message.tool_calls[0] print(模型选择调用函数:, tool_call.function.name) print(函数入参 JSON:, tool_call.function.arguments) # 模拟程序侧执行函数 args json.loads(tool_call.function.arguments) function_result get_current_weather(args[city]) print(函数执行结果:, function_result) if __name__ __main__: main()运行代码python function_calling_demo.py正常情况下你会看到模型并没有直接生成“北京今天适合跑步”这种回答而是返回了一个tool_calls结构其中包含函数名get_current_weather和参数{city: 北京}。这个差异非常重要它说明模型已经具备了“识别出自己缺少信息 - 发起工具申请 - 等待程序执行结果”的行为模式。5.2 把工具结果返回给模型上面的示例只执行了函数但没有把结果送还给模型所以模型最终还无法生成完整回答。真实 Agent 循环还需要把工具结果以tool消息发回去让模型基于真实结果组织最终回复。下面这段代码可以看作是“一次性 Agent 循环”的最小版本# minimal_agent_loop.py import json from openai import OpenAI import config client OpenAI( api_keyconfig.ZHIPU_API_KEY, base_urlconfig.ZHIPU_BASE_URL, ) tools [ { type: function, function: { name: get_current_weather, description: 查询指定城市的当前天气, parameters: { type: object, properties: { city: {type: string, description: 城市名} }, required: [city] } } } ] def get_current_weather(city: str) - str: weather_data { 北京: 晴25℃, 上海: 多云28℃, 广州: 雷阵雨30℃, } return weather_data.get(city, f{city} 暂无数据) def main(): messages [ {role: user, content: 北京今天适合跑步吗请给出结论。} ] response client.chat.completions.create( modelconfig.ZHIPU_MODEL_ID, messagesmessages, toolstools, tool_choiceauto, ) assistant_msg response.choices[0].message if not assistant_msg.tool_calls: print(模型直接回答:, assistant_msg.content) return tool_call assistant_msg.tool_calls[0] function_name tool_call.function.name function_args json.loads(tool_call.function.arguments) print(f模型申请调用: {function_name}({function_args})) if function_name get_current_weather: function_result get_current_weather(function_args[city]) else: function_result 不支持的函数 # 关键点把第一轮模型回复追加到 messages并追加 tool 消息 messages.append({ role: assistant, content: assistant_msg.content, tool_calls: [ { id: tool_call.id, type: function, function: { name: tool_call.function.name, arguments: tool_call.function.arguments } } ] }) messages.append({ role: tool, tool_call_id: tool_call.id, content: json.dumps(function_result, ensure_asciiFalse) }) final_response client.chat.completions.create( modelconfig.ZHIPU_MODEL_ID, messagesmessages, toolstools, tool_choiceauto, ) print(最终回答:, final_response.choices[0].message.content) if __name__ __main__: main()这段代码的顺序非常关键。第一轮模型如果返回了tool_calls你不能只把function_result塞成一条普通用户消息而是必须先把“带工具调用的 assistant 消息”追加到消息列表再用tool消息回传执行结果。这样模型才能正确理解刚才它请求了什么工具、程序执行结果是什么、接下来应该基于结果继续回答。运行python minimal_agent_loop.py只要模型调用工具正常最终模型就会给出类似“北京今天晴25℃适合跑步”的结论。这个结论不是凭空生成的而是基于程序侧真实函数返回值生成的这就大大降低了幻觉带来的信息错误风险。从 Chat 到 Act 的关键一步正是这个看似不起眼的协议循环。6. 预期输出与验证方式对于第一个chat_demo.py预期输出是一段解释 Agent 的文本。对于function_calling_demo.py你观察到的核心输出应该是这样的结构模型选择调用函数: get_current_weather 函数入参 JSON: {city: 北京} 函数执行结果: 北京 晴25℃如果到了这一步说明模型已经理解了用户问题中隐含的信息需求并选择通过外部工具获取数据而不是直接猜测答案。对于minimal_agent_loop.py最终输出会在控制台看到一行“最终回答”。这里要注意如果 API 响应里的参数结构不是标准的 OpenAI 格式程序可能会在assistant_msg.tool_calls[0]这一行抛异常。此时可以先打印完整响应体定位是字段名不同还是类型嵌套不一致。出现这种问题时不要盲目修改代码应以该开放平台最新的 Function Calling 文档为准。验证是否成功的标准有三条第一模型能识别出“没有工具结果就无法回答”的问题第二程序能在本地执行函数并把结构化结果回传给模型第三模型最终回答的内容明显参考了函数返回的真实结果。如果模型依然自言自语、忽略工具返回那就是提示词或协议层级的问题。7. 常见问题与排查方法在实际接入 GLM 或任何大模型 API 时以下问题出现频率很高建议收藏备用。问题现象可能原因排查方式解决方案401 鉴权失败API Key 缺失、复制不完整、Key 被吊销检查.env和平台控制台确认没有把 Key 写死在代码里重新生成 Key确保启动时环境变量已加载404 Model Not Found模型 ID 在当前账号不存在或平台已下线旧模型查看开放平台“模型列表”页以平台当前支持的模型 ID 为准统一维护在配置中心429 Too Many Requests触发了并发限制或账户余额不足查看响应头中的限流信息与账户账单降低并发使用退避重试或为生产环境申请更高配额请求超时网络到bigmodel.cn不通、代理干扰、请求体过大用 curl 等方式测试基础连通性检查代理变量清理代理配置或把超时时间调大并做重试模型未调用工具tools Schema 描述不清晰或模型判断当前可直接作答打印 messages 和响应检查用户问题是否明确需要外部信息调整函数 description使“何时使用该函数”更直白必要时可以指定tool_choice工具结果未生效没有把 assistant 的 tool_calls 消息和 tool 消息都回传给模型检查改请求是否携带完整消息历史按协议把“assistant tool_calls”和“tool”逐条追加输出不稳定推理温度过高、上下文过长导致噪声查看响应中的 token 使用与内容一致性调低 temperature缩短上下文必要时做结构化输出校验这里特别提醒一个容易忽视的问题代码里用环境变量保存 API Key 是对的但不要把.env文件提交到 Git 仓库。同时在生产环境中不要把 Key 直接暴露给前端。正确做法是让后端服务持有 Key所有模型调用都通过后端代理完成这样也方便做权限控制和审计。8. 生产环境下的工程建议如果你已经跑通了上面的最小循环下一步就是思考怎么把它接入真实业务。这时候真正拉开差距的不是模型能力而是工程成熟度。以下几条建议来自我对 Agent 类项目的观察希望对你有用。8.1 三层调用架构不要在前端直接调模型小型 Demo 可以让前端直接调 API但生产环境必须要做后端代理。前端只发送用户消息给后端后端负责鉴权、拼装上下文、调用模型、校验结果、返回给前端。这样做的好处是可以在后端统一配置模型版本接入监控也能在模型出问题时快速降级到备用方案而不用发版改前端。8.2 固定模型版本警惕“隐藏漂移”很多开放平台的模型 ID 如果不带日期比如只写glm-4平台升级时可能会影响同一 ID 下的行为。在严肃项目里建议锁定到带时间戳或明确版本的模型 ID并在新版本上线前先做回归测试。生产环境最怕的不是模型不够聪明而是昨天能用的流程今天突然不行了但没人知道原因。8.3 Function 即契约要做版本管理当你的 Agent 需要调用十几个业务函数时函数的 Schema 就成了一份契约。任何参数的增删改都要像对外 API 一样走评审和版本管理。函数名要语义化参数的 description 要说明取值约束甚至要给出示例值因为模型对描述的理解直接决定它能不能正确调用。不要上一个业务同学随手起个do1的函数名那模型能猜对才奇怪。8.4 最小权限原则必须前置给 Agent 绑定工具时权限一定要做最小化授权。比如一个天气查询工具只需要给只读权限一个数据库查询工具最安全的做法是使用只读账号并且限制返回行数。千万不要为了让模型“更智能”就给它套一个能够执行任意 SQL 或 shell 命令的万能工具。Agent 的不可控性会让这类权限放大成严重的安全风险。8.5 建立完整的可观测性与审计链路每次模型请求除了记录常规的输入输出还要记录 system messages、工具调用顺序、各阶段的耗时和 token 消耗。当一次任务执行结果异常时可以通过 Trace 回放整个决策过程。这个回放能力在传统软件开发中不是必须的但在 Agent 系统里几乎是基础配置因为你无法从最终输出反推模型当初为什么决定调用某个函数。8.6 提示词和编排逻辑分开管理不要把一连串复杂指令写在代码字符串里然后认为这就是“AI 应用”。更合理的方式是将系统提示词、函数描述、业务规则放在独立的配置文件或配置中心里代码只负责编排执行。这样运营同学可以调整提示词而不需要每次找后端发版。提示词也应当有 Git 版本历史方便回滚和对比效果。8.7 从“直接使用输出”升级为“结构化输出 校验”在生产环境特别是涉及金额、状态变更、自动回复等场景时不能直接把模型返回的字符串当结果使用。更稳妥的做法是要求模型按 JSON 输出再用程序校验字段是否存在、枚举值是否合法、数值范围是否合理。校验不通过就重试或走人工兜底而不是让错误数据悄悄流入下游业务。8.8 做好成本和租户隔离多租户场景下不同客户或部门的调用量差异很大。建议在代理层做租户标识分别统计 token 消耗。模型路由也可以策略化简单翻译或抽取任务走小模型复杂推理走大模型。否则一个月下来成本清单会是一个让你意外的数字。9. 下一步实践与学习路径如果你想继续深入“下一代大模型”这个方向我建议按下面这个顺序逐步推进不要一上来就追求构建复杂的多 Agent 系统。第一步先在本地把上面三个示例跑熟理解普通对话与工具调用的协议差异。第二步尝试给模型增加一个真实的业务函数比如查数据库、查订单、发消息体会“程序执行真实逻辑”与“模型生成文字”之间的界限。第三步做一个简单的状态机管理一个多轮任务的执行与中断恢复。第四步再引入向量库做长期记忆并设计评估集来回归测试模型是否记得住关键上下文。这套路径的本质是从“调用模型 API”升级为“设计模型参与的软件系统”。下一代大模型会越来越像是一个决策引擎而开发者真正的价值在于设计出模型可以安全、可靠地“行动”的系统边界。你可以继续关注 GLM 系列的模型迭代、Function Calling 的更新、以及 Agent 产品在真实场景中的落地方式但更重要的是亲自动手把一个最小 Agent 跑起来感受从 Chat 到 Act 的变化到底发生在哪一层。