首页 / 资讯中心 / 文章详情

Agent Infra:从模型崇拜到基建觉醒,工程师的入场券

Agent Infra:从模型崇拜到基建觉醒,工程师的入场券 ★ FEATURED ARTICLE
1. 从“模型崇拜”到“基建觉醒”为什么Agent Infra成了新战场过去两年大家的目光几乎都聚焦在模型本身——参数规模、榜单排名、推理能力。但如果你最近半年跟一线做AI应用的团队聊过会发现一个微妙的变化大家不再只聊“用哪个模型”而是越来越多地聊“怎么把模型用起来”。这个“用起来”的过程就是Agent Infra要解决的核心问题。所谓Agent Infra我把它理解为“智能体基础设施”。它不是某个具体的模型也不是某个单一工具而是一整套让AI Agent能够稳定、高效、可观测地完成复杂任务的底层支撑体系。你可以把它想象成一家餐厅的后厨模型是那位手艺精湛的大厨但如果没有备菜区、传菜通道、洗碗间、库存管理系统大厨再厉害也只能一次做一道菜而且做完就乱。Agent Infra就是那个让大厨能同时处理几十道菜、还能保证不出错的后厨体系。为什么说这是“巨头的隐秘战场”因为模型层的竞争已经进入白热化参数和榜单的差距在缩小而真正决定一个AI产品能不能落地、能不能规模化、能不能赚钱的恰恰是中间这层基础设施。谁把Agent Infra做扎实了谁就能让开发者在自己的生态里“住下来”形成迁移成本。这就像当年云计算的竞争表面上是卖算力实际上是卖一整套开发、部署、运维的便利性。那为什么又说这是“每个工程师的入场券”因为Agent Infra涉及的技术栈非常宽——任务编排、工具调用、记忆管理、上下文压缩、错误恢复、可观测性、成本控制——这些都不是靠调一个API就能解决的。它需要工程师真正理解分布式系统、状态机、缓存策略、异步任务这些“老手艺”同时又要对LLM的行为特性有直觉。换句话说这是传统后端工程能力与AI应用理解的一次交汇而目前同时具备这两方面经验的人并不多。这篇文章我想从一线实操的角度把Agent Infra拆开来讲清楚它到底包含哪些模块每个模块的核心难点是什么有哪些常见的坑以及一个普通工程师可以从哪里切入。我不会只讲概念而是会给出具体的方案对比、参数选择逻辑和排查技巧。如果你正在做AI应用或者想从传统后端转向AI基础设施这篇内容应该能帮你省下不少试错时间。2. Agent Infra的核心模块拆解与选型逻辑2.1 任务编排引擎Agent的“中枢神经”任务编排是Agent Infra最核心的部分。一个Agent接到用户请求后需要决定先做什么、后做什么、什么时候调用工具、什么时候向用户确认、失败了怎么重试。这个过程如果用代码硬编码很快就会变成一团乱麻。所以我们需要一个编排引擎。目前主流的编排思路有三种。第一种是基于状态机的显式编排比如用LangGraph这类框架把每个步骤定义成节点用边来表示跳转条件。这种方式的优点是可控性强每一步都看得见适合流程相对固定的场景比如客服工单处理、数据ETL流水线。缺点是灵活性差遇到没预料到的分支就容易卡住。第二种是基于ReAct循环的隐式编排也就是让模型自己决定下一步做什么通过“思考-行动-观察”的循环来推进。这种方式灵活适合探索性任务比如研究型Agent、开放式问答。但缺点是容易陷入死循环或者调用一些不该调用的工具而且调试起来很痛苦因为每次运行的路径可能都不一样。第三种是混合模式也是我在实际项目中用得最多的用状态机定义主干流程在关键节点嵌入ReAct循环。比如一个合同审核Agent主干流程是“读取合同→提取条款→比对规则库→生成报告”这是固定的但在“提取条款”这一步可以用ReAct循环让模型自己决定要不要调用OCR工具、要不要查历史案例。这样既保证了整体可控又保留了局部灵活性。选型的时候我一般会问三个问题这个任务的步骤是否可枚举失败后的恢复策略是否明确是否需要人工介入如果三个答案都是“是”那就用状态机如果都是“否”那就用ReAct如果介于两者之间就上混合模式。注意不要一上来就追求“全自动”。很多团队在早期为了演示效果让Agent完全自主决策结果上线后各种意外。我的经验是先做“人机协同”的编排把人工确认节点显式地画在状态机里等跑顺了再逐步减少人工介入。2.2 工具调用层让Agent真正“动手”Agent和聊天机器人最大的区别就是它能调用外部工具。但工具调用这件事坑非常多。首先是工具描述的质量。很多人写工具描述就写一句“查询天气”然后抱怨模型总是调错。实际上工具描述应该包含功能说明、参数格式、返回值示例、什么情况下用、什么情况下不用。我通常会写成一个结构化的JSON Schema并且在description里用自然语言补充边界条件。其次是工具的数量控制。我见过一个Agent挂了四十多个工具结果模型的选择准确率急剧下降。后来我们做了分组把工具按场景分成“订单相关”“用户相关”“物流相关”每次只给模型暴露当前场景下的工具子集准确率立刻回升。一般来说单次暴露给模型的工具不要超过15个超过就要考虑分层路由。第三是工具调用的幂等性。Agent可能会因为重试而重复调用同一个工具如果这个工具是“创建订单”或者“发送短信”就会出问题。所以每个工具都要设计成幂等的或者引入一个去重机制。我们当时的做法是给每个工具调用生成一个唯一的request_id在服务端做去重缓存缓存时间设为任务的最大超时时间。还有一个容易被忽略的点工具调用的超时和熔断。Agent调用外部API时如果对方挂了不能让整个Agent卡死。我们给每个工具设置了独立的超时时间一般3-10秒并且用熔断器模式连续失败5次就暂时禁用该工具过30秒再半开重试。这些参数需要根据实际SLA来调没有万能值。2.3 记忆与上下文管理Agent的“工作记忆”Agent的记忆系统通常分三层短期记忆当前对话的上下文、长期记忆跨会话的知识、工作记忆当前任务的中间状态。这三层的管理策略完全不同。短期记忆最直接的问题就是上下文窗口有限。一个长对话很容易超过模型的token限制。常见的做法是滑动窗口加摘要保留最近N轮对话更早的对话用模型生成摘要。但这里有个细节——摘要的粒度。如果摘要太粗会丢失关键信息如果太细又起不到压缩作用。我的经验是按“任务阶段”来摘要而不是按固定轮数。比如一个订票任务可以分成“确认需求”“查询航班”“选择航班”“填写信息”“支付”几个阶段每个阶段结束后生成一个阶段摘要这样既压缩了上下文又保留了任务脉络。长期记忆一般用向量数据库来做语义检索。但这里有个常见误区把所有历史对话都塞进向量库。结果检索出来的内容噪音很大反而干扰模型。正确的做法是只存“值得记住”的内容比如用户的偏好、重要的事实、成功的解决方案。我们当时用了一个简单的规则如果用户明确说“记住这个”或者某个信息在后续对话中被重复引用就存入长期记忆。另外长期记忆需要定期清理和去重否则会越来越臃肿。工作记忆是任务执行过程中的临时状态比如“当前已经收集到的参数”“已经调用过的工具”“待确认的问题”。这部分我建议用结构化的方式存储比如一个JSON对象而不是纯文本。这样在恢复任务或者调试的时候能一眼看清当前状态。我们当时用Redis存工作记忆设置合理的TTL任务完成后自动过期。实操心得上下文压缩不要等到快满了才做。我一般会在上下文用到70%的时候就开始触发摘要留出缓冲空间。另外摘要生成最好用便宜的小模型不要用最贵的那个因为摘要本身不需要太强的推理能力。2.4 可观测性与评估Agent的“仪表盘”Agent系统最让人头疼的就是“黑盒感”。用户说“它刚才为什么那么做”你很难回答。所以可观测性是Agent Infra里不可或缺的一环。我通常会把可观测性分成三个层次日志、追踪、评估。日志是最基础的但Agent的日志不能只记“输入什么输出什么”还要记录每一步的决策理由、调用了哪些工具、每个工具的耗时和结果、token消耗、成本。我们当时用OpenTelemetry做埋点把每个Agent任务当成一个trace每个步骤当成一个span这样在Jaeger里就能看到完整的调用链。追踪之上是评估。评估分两种在线评估和离线评估。在线评估是在真实流量中抽样用规则或者小模型判断这次任务是否成功。离线评估是构建一个测试集定期跑回归。这里的关键是定义清楚“成功”的标准。比如一个客服Agent成功可以定义为“用户问题解决且没有转人工”一个数据分析Agent成功可以定义为“生成的SQL能正确执行且结果符合预期”。标准不同优化方向就不同。我还想强调一点成本可观测性。Agent的token消耗可能比普通对话高一个数量级因为有多轮思考和工具调用。如果不监控成本很容易出现“一个任务烧掉几块钱”的情况。我们当时给每个任务设置了token预算超过预算就触发告警或者降级到更便宜的模型。这个预算需要根据业务价值来定比如一个高价值的销售线索挖掘任务可以给到5万token一个简单的问答给2000token就够了。3. 从零搭建一个Agent Infra的实操路径3.1 环境准备与技术栈选型假设你现在要从零开始搭一个Agent Infra我会建议这样的技术栈组合编排层用LangGraph或者自己写一个轻量状态机如果团队对Python生态不熟用TypeScript写也可以工具调用层用OpenAI的Function Calling格式或者Anthropic的Tool Use格式这两个是目前事实上的标准记忆层用Redis做短期和工作记忆用Pgvector或者Qdrant做长期记忆可观测性用OpenTelemetry加Grafana或者Langfuse。这里我想特别说一下为什么推荐Pgvector而不是专门的向量数据库。对于大多数中小规模应用百万级向量以内Pgvector的性能完全够用而且它和业务数据在同一个数据库里做联合查询非常方便。比如你要查“某个用户的历史偏好”可以直接用SQL join不用跨系统同步。只有到了亿级向量、需要极致检索性能的时候才需要考虑专门的向量数据库。环境准备的具体步骤先装Python 3.11以上3.12对异步支持更好然后用poetry或者uv管理依赖。我最近在用uv安装速度比pip快很多而且锁文件更可靠。核心依赖包括langgraph、langchain-core、openai、redis、psycopg2、pgvector、opentelemetry-sdk。如果是生产环境还要加上fastapi做API层celery或者arq做异步任务队列。注意不要一上来就上Kubernetes。我见过不少团队Agent还没跑通就先搭了一套K8s结果大部分时间都在调网络和存储。先用Docker Compose把服务跑起来等QPS上来了再考虑编排系统。3.2 核心模块的代码实现与参数配置先看编排引擎的最小实现。我用LangGraph定义一个简单的状态机包含“理解意图”“调用工具”“生成回复”三个节点。关键代码如下from langgraph.graph import StateGraph, END from typing import TypedDict, Annotated import operator class AgentState(TypedDict): messages: Annotated[list, operator.add] next_step: str tool_calls: list def understand_intent(state: AgentState): # 调用LLM判断用户意图 response llm.invoke(state[messages]) if response.tool_calls: return {next_step: call_tool, tool_calls: response.tool_calls} return {next_step: generate_reply} def call_tool(state: AgentState): results [] for tool_call in state[tool_calls]: result execute_tool(tool_call) results.append(result) return {messages: [{role: tool, content: str(results)}], next_step: generate_reply} def generate_reply(state: AgentState): response llm.invoke(state[messages]) return {messages: [response], next_step: END} graph StateGraph(AgentState) graph.add_node(understand_intent, understand_intent) graph.add_node(call_tool, call_tool) graph.add_node(generate_reply, generate_reply) graph.set_entry_point(understand_intent) graph.add_conditional_edges(understand_intent, lambda x: x[next_step]) graph.add_edge(call_tool, generate_reply) graph.add_edge(generate_reply, END) app graph.compile()这段代码看起来简单但有几个参数需要仔细调。第一个是LLM的temperature。对于意图理解节点我建议用0或者0.1保证决策稳定对于生成回复节点可以用0.7左右让回复更自然。第二个是max_tokens。意图理解节点不需要太长输出设256就够了生成回复节点根据业务需求设一般1024-2048。第三个是超时时间。每个LLM调用都要设超时我一般设30秒超过就重试或者降级。工具调用的实现要注意错误处理。下面是一个带重试和熔断的工具执行函数import time from functools import wraps def with_retry(max_retries3, backoff1.5): def decorator(func): wraps(func) def wrapper(*args, **kwargs): last_exception None for attempt in range(max_retries): try: return func(*args, **kwargs) except Exception as e: last_exception e wait backoff ** attempt time.sleep(wait) raise last_exception return wrapper return decorator with_retry(max_retries3) def execute_tool(tool_call): tool_name tool_call[name] tool_args tool_call[args] # 根据tool_name路由到具体实现 if tool_name query_weather: return query_weather(**tool_args) elif tool_name search_database: return search_database(**tool_args) else: raise ValueError(fUnknown tool: {tool_name})记忆管理的实现短期记忆用Redis的List结构每个会话一个key设置TTL为24小时。长期记忆用Pgvector建表语句如下CREATE TABLE long_term_memory ( id SERIAL PRIMARY KEY, user_id VARCHAR(64) NOT NULL, content TEXT NOT NULL, embedding vector(1536), created_at TIMESTAMP DEFAULT NOW(), last_accessed TIMESTAMP DEFAULT NOW() ); CREATE INDEX ON long_term_memory USING ivfflat (embedding vector_cosine_ops) WITH (lists 100);这里的lists参数需要根据数据量来调。一般来说lists设为sqrt(行数)比较合适。比如10万行数据lists设316左右。太小会导致检索慢太大会导致召回率下降。3.3 部署与性能调优的关键参数部署Agent服务时有几个参数直接决定性能和成本。第一个是并发数。Agent任务通常是IO密集型的等LLM响应、等工具返回所以可以用异步IO来提高并发。我用FastAPI加uvicornworkers设为CPU核数的2倍然后用asyncio.Semaphore限制同时进行的LLM调用数一般设为10-20具体取决于你的API配额。第二个是缓存策略。LLM调用很贵能缓存就缓存。我通常做两级缓存第一级是精确缓存用Redis存“prompt hash → response”TTL设1小时第二级是语义缓存用向量检索找相似的历史prompt如果相似度超过0.95就直接返回历史结果。语义缓存能把重复问题的成本降低80%以上但要注意设置合理的相似度阈值太低会导致答非所问。第三个是降级策略。当API限流或者成本超预算时要有降级方案。我的做法是准备一个“小模型池”比如用7B级别的本地模型处理简单任务复杂任务才走大模型。判断标准可以用规则比如token数小于500且不涉及工具调用或者用小模型自己判断。实操心得部署时一定要加请求队列。我见过太多服务因为突发流量直接把API配额打满然后所有请求都失败。用Redis或者RabbitMQ做一个缓冲队列队列满了就返回“系统繁忙请稍后重试”比全部超时要好得多。4. 常见问题与排查技巧实录4.1 Agent陷入死循环怎么办这是最常见的问题。Agent反复调用同一个工具或者在不同节点之间来回跳转。排查思路分三步先看日志确认是哪个节点在循环再看状态检查工作记忆里是不是有某个条件一直没满足最后看提示词是不是工具描述或者系统提示里有歧义。我遇到过一个典型案例Agent在“查询订单”和“确认订单状态”之间反复跳。原因是工具返回的订单状态是“处理中”而系统提示里写的是“如果订单状态不是‘已完成’就继续查询”。模型就一直在查。解决办法是在提示词里加一句“如果连续两次查询结果相同则停止查询并告知用户当前状态”。另外在编排层加一个最大循环次数限制比如同一个节点最多执行5次超过就强制跳出。还有一个隐蔽的死循环原因工具返回的内容被截断了。比如工具返回了一个很长的JSON但你的代码只取了前1000个字符导致模型看不到关键字段以为工具没返回就反复调用。所以工具返回值的处理一定要完整如果太长就做摘要但不要静默截断。4.2 工具调用准确率低怎么优化工具调用准确率低通常有三个原因工具描述不清、工具太多、模型能力不够。优化顺序应该是先改描述再减数量最后才考虑换模型。改描述的具体做法把每个工具的description写成“功能参数返回值使用场景反例”。比如“查询天气”可以写成“根据城市名查询当前天气。参数city字符串城市中文名。返回温度、湿度、天气状况。使用场景用户询问某地天气时。不要用于查询历史天气或未来预报。”这样模型就不容易搞混。减数量的做法按场景分组每次只暴露相关工具。我们当时做了一个“工具路由器”先用一个小模型判断用户意图属于哪个场景然后只加载该场景的工具。准确率从62%提升到了89%。如果以上都做了还是不行再考虑换模型。一般来说GPT-4级别的模型在工具调用上明显优于小模型但成本也高。可以用“大模型决策小模型执行”的混合模式。4.3 上下文超限的应急处理上下文超限是长对话的必然问题。应急处理方案有三种截断、摘要、外置。截断最简单但会丢失信息摘要需要额外调用LLM有成本外置是把部分上下文存到外部存储需要时再检索回来。我的建议是组合使用最近5轮对话保留原文5-20轮做摘要20轮以上的只保留关键事实用规则提取比如订单号、日期、金额。另外工具返回的大段内容不要直接塞进上下文而是先存到工作记忆里只在上下文里放一个引用ID需要时再取。还有一个技巧用系统提示来“提醒”模型。在系统提示里加一句“如果用户提到之前的内容请先调用recall_memory工具获取历史信息”。这样模型就不会因为看不到历史而胡编。4.4 成本失控的排查与止损成本失控通常表现为某个任务消耗了异常多的token或者某个工具被频繁调用。排查方法是看可观测性面板按任务类型、用户、时间段分组统计token消耗。止损措施分短期和长期。短期给每个任务设token上限超过就强制结束并返回“任务过于复杂请简化后重试”。长期优化提示词减少不必要的上下文用缓存减少重复调用用更便宜的模型处理简单任务。我自己的经验是80%的成本来自20%的任务。所以重点优化那20%的高消耗任务而不是平均用力。比如我们发现“数据分析”类任务平均消耗1.5万token而“问答”类只有800token。于是我们专门为数据分析任务做了优化把常用的数据表结构缓存起来避免每次重新描述把SQL生成和SQL执行分开生成用大模型执行用规则引擎。4.5 常见问题速查表问题现象可能原因排查方法解决方案Agent反复调用同一工具提示词歧义或状态未更新查看工作记忆和工具返回值加循环限制明确停止条件工具调用准确率低描述不清或工具过多检查工具描述和暴露数量优化描述按场景分组上下文超限对话过长或工具返回太大统计token消耗分布摘要外置截断组合成本异常高重复调用或模型选择不当按任务类型统计token缓存降级预算控制响应延迟高串行调用或超时设置过长查看trace耗时分布并行化缩短超时异步任务成功率下降模型更新或工具变更对比历史评估结果回归测试版本锁定最后分享一个我踩过的坑不要在生产环境直接用latest版本的模型。我们有一次因为模型静默更新导致工具调用格式变了整个Agent服务挂了半天。后来我们锁定了具体版本号并且每次升级前都跑一遍回归测试。这个习惯帮我省了很多半夜救火的时间。5. 工程师如何拿到这张“入场券”如果你是一个传统后端工程师想切入Agent Infra我的建议是从“工具调用层”入手。因为这层最接近你已有的技能——写API、处理错误、做缓存、控超时。你可以先写一个简单的工具注册中心支持动态加载工具、自动生成Schema、统一错误处理。这个过程中你会自然接触到LLM的Function Calling格式、token计算、提示词工程。如果你是一个AI应用工程师想深入Infra那建议从“可观测性”入手。因为这是目前最缺人的方向。大多数团队能把Agent跑起来但跑起来之后两眼一抹黑。你可以学OpenTelemetry学怎么埋点、怎么建Dashboard、怎么定义评估指标。这个技能在任何一个做Agent的公司都是刚需。如果你是一个学生或者刚入行的开发者我建议你先用LangGraph或者类似的框架做一个完整的项目比如“自动调研助手”或者“智能客服工单系统”。不要只跑Demo要把它部署到云上让它真实地跑一周处理真实的问题。你会遇到各种在Demo里永远不会出现的问题网络抖动、API限流、用户输入奇怪字符、并发冲突。这些问题才是真正的经验。Agent Infra这个领域目前还没有形成标准答案。每个人都在摸索每个团队都有自己的最佳实践。这意味着两件事第一你学到的知识可能很快就过时所以要保持学习第二你有机会定义标准而不是只跟随标准。对于工程师来说这既是挑战也是机会。我个人的体会是做Agent Infra最需要的不是某个具体技术而是一种“系统思维”——你要同时考虑模型的概率性、系统的可靠性、成本的约束性、用户的体验性。这四个维度经常互相冲突而你的工作就是找到平衡点。这种平衡能力才是真正的“入场券”。
阅读完成 · 觉得有帮助?
咨询建站