AI Agent工程实现:七要素与七决策点拆解
1. 从七个零件到七个岔路口AI Agent 工程实现的底层逻辑聊 AI Agent 的人很多但真正动手搭过一套能跑、能扛、能维护的 Agent 系统的人并不多。大部分人第一次接触 Agent 这个概念都是从“让大模型自己调用工具”开始的——写个提示词挂两个函数模型返回一个 JSON代码解析一下执行看起来就完成了。但真把它放到生产环境里跑上几天各种问题就会像雨后春笋一样冒出来循环停不下来、工具调用参数乱填、上下文越滚越长、并发一上来就雪崩、同一个任务每次跑出来的结果都不一样。这些问题的根源其实不在于模型不够聪明而在于工程实现层面缺少一套清晰的拆解框架。我自己的经验是一个能落地的 AI Agent本质上就是七个核心要素的组合加上七个关键决策点的取舍。七要素决定了 Agent “由什么构成”七决策点决定了 Agent “怎么运转”。把这两层搞清楚再去看 LangGraph、Spring AI、扣子这类框架就不会被它们的 API 绕晕因为你已经知道每个 API 背后对应的是哪个要素、哪个决策。这篇文章面向的是已经了解 LLM 基本调用方式、准备把 Agent 从 demo 推进到可用系统的开发者。不管你是用 Python 生态的 LangChain/LangGraph还是 Java 侧的 Spring AI或者干脆基于 Rust 自己撸一套底层的工程逻辑是相通的。我会把七要素和七决策点逐一拆开配上参数选择的计算过程、实操中踩过的坑、以及可以直接抄的配置思路。读完你至少能做到两件事第一拿到一个 Agent 需求时知道该从哪几个维度去设计第二Agent 跑出问题时知道该去哪个环节排查。2. 七要素拆解一个 Agent 到底由什么构成2.1 模型层不是选最强的而是选最合适的模型是整个 Agent 的“大脑”但选模型这件事很多人一上来就陷入“哪个榜单第一就用哪个”的误区。Open LLM Leaderboard 这类公开榜单确实有参考价值但榜单测的是通用能力而 Agent 场景对模型的要求非常具体指令遵循能力、结构化输出稳定性、工具调用格式的准确率、以及长上下文下的注意力保持。我自己的选型逻辑是这样的先看任务复杂度再看成本约束最后看延迟要求。举个具体的例子如果你做的是一个客服工单分类 Agent任务本质是“读一段文本输出一个枚举值”这种场景用 7B 到 14B 级别的模型完全够用没必要上最大的模型。但如果你做的是需要多步推理的代码生成 Agent那模型的基础推理能力就是硬门槛省这个钱会导致后面工具调用连环出错排查成本远高于模型成本。这里有个实操中很容易忽略的点模型的结构化输出能力必须单独验证。不要只看它聊天聊得好不好要专门写一组测试用例让它输出指定格式的 JSON统计格式错误率。我实测下来有些模型在通用对话上表现很好但一旦要求输出严格的 JSON schema错误率能到 20% 以上这种模型直接用在 Agent 里就是灾难。验证方法很简单准备 50 条真实任务输入让模型输出结构化结果用 JSON 解析器跑一遍统计失败率。失败率超过 5% 的要么换模型要么加一层输出校验和重试。另外关于 LLM 的 token有个很形象的类比key 是“我是谁”query 是“我在找什么”value 是“我能提供什么”。在 Agent 场景里这个类比特别有用——系统提示词定义了 Agent 的身份key用户输入和中间结果构成了查询意图query而工具返回的结果就是 value。理解这三者的关系能帮你在设计上下文时想清楚哪些信息该放在系统提示里固定下来哪些该随任务动态注入哪些该由工具实时返回。2.2 工具层Agent 的手和脚也是最容易出事的地方工具调用是 Agent 区别于普通聊天机器人的核心能力。但工具层的设计远比“写几个函数挂上去”复杂。我见过太多项目工具定义得很随意参数没有约束返回格式不统一结果就是模型调用时频繁出错或者调用成功了但结果没法用。工具设计的第一原则是每个工具只做一件事且参数必须可枚举或可校验。比如你要做一个“查询订单”的工具参数不要设计成query: string让模型自由发挥而应该拆成order_id: string带格式校验和query_type: enum枚举值status/logistics/refund。参数越具体模型填错的概率越低。第二原则是返回结果要结构化且带状态标识。工具返回不要只给一个字符串要给一个包含success、data、error_code、error_message的结构。这样 Agent 在拿到结果后能根据状态决定是继续下一步还是走异常处理分支。我踩过的一个坑就是工具返回了错误信息但格式是纯文本模型把错误信息当成了正常结果继续往下走最后输出了一堆看似合理实则完全错误的内容。第三原则是工具要有超时和幂等设计。Agent 调用工具时网络抖动、下游服务慢都是常态。如果工具没有超时控制一个卡住的调用会把整个 Agent 循环拖死。幂等性则是为了防止 Agent 在重试时重复执行有副作用的操作比如重复下单、重复发消息。对于有副作用的工具建议加一个idempotency_key参数由 Agent 框架层生成并透传。2.3 记忆层短期靠上下文长期靠检索Agent 的记忆分两层短期记忆和长期记忆。短期记忆就是当前对话的上下文窗口长期记忆则是跨会话、跨任务的知识沉淀。短期记忆的管理核心是上下文预算分配。一个 Agent 的上下文窗口是有限的系统提示词、工具定义、历史对话、工具返回结果、当前任务输入这些都要占空间。我的经验是给系统提示词和工具定义预留 20%历史对话预留 30%工具返回预留 30%当前任务预留 20%。一旦某部分超预算就要触发压缩或截断策略。压缩不是简单截断而是用模型对历史对话做摘要保留关键决策点和结果丢弃中间的冗余推理过程。长期记忆的实现主流做法是向量检索加结构化存储。向量库负责语义相似度召回结构化存储负责精确查询。这里有个容易忽略的点写入长期记忆的内容必须经过筛选。不是所有对话都值得记只有那些包含用户偏好、任务结论、错误教训的内容才值得写入。我一般会在 Agent 流程里加一个“记忆写入决策”步骤用一个轻量模型判断当前内容是否值得长期保存避免记忆库被垃圾信息污染。2.4 规划层把大任务拆成可执行的小步骤规划层是 Agent 的“项目经理”角色。它的核心任务是把用户的模糊需求拆解成一系列可执行、可验证的子步骤。规划的质量直接决定了 Agent 能不能完成复杂任务。规划的实现方式有两种主流路线一种是显式规划让模型先输出一个完整的步骤列表然后逐步执行另一种是隐式规划模型在每一步根据当前状态决定下一步做什么。显式规划的好处是可解释、可干预适合流程相对固定的场景隐式规划更灵活适合探索性任务但容易跑偏。我自己的选择是混合模式对于步骤数少于 5 步的任务用隐式规划减少一次模型调用的开销对于步骤数可能超过 5 步的复杂任务先做一次显式规划生成步骤列表然后在执行过程中允许动态调整。这样既保证了复杂任务的方向性又保留了灵活性。规划层还有一个关键设计是步骤验证。每执行完一步要有一个轻量的验证逻辑判断这一步是否成功。验证可以是规则校验比如检查返回结果是否包含必要字段也可以是模型校验让模型判断结果是否满足预期。验证不通过就触发重规划而不是硬着头皮往下走。2.5 执行层循环机制的设计与终止条件执行层是 Agent 的“发动机”核心是一个循环观察当前状态决定下一步动作执行动作更新状态判断是否终止。这个循环看起来简单但终止条件的设计是工程实现中最容易出问题的地方。常见的终止条件有三类任务完成、达到最大步数、遇到不可恢复错误。任务完成判断需要依赖规划层的验证逻辑最大步数是兜底保护防止无限循环不可恢复错误包括工具连续失败、模型连续输出无效格式等。我踩过最深的坑就是循环没有设置合理的最大步数。有一次做一个数据清洗 Agent任务本身不复杂但因为工具返回格式有问题模型一直在“尝试修复”循环跑了 200 多步烧掉了大量 token 才被手动终止。后来我给自己定了个规矩任何 Agent 循环的最大步数不超过 15 步超过这个数说明任务拆解或工具设计有问题应该停下来排查而不是让模型继续试。循环的每一步还要记录完整的执行轨迹包括当前状态、模型输出、工具调用参数、工具返回结果、耗时。这些轨迹不仅是排查问题的依据也是后续优化 Agent 的宝贵数据。2.6 编排层多 Agent 协作与单 Agent 多工具的取舍编排层解决的是“一个 Agent 搞不定多个 Agent 怎么配合”的问题。但我要先泼一盆冷水大部分场景不需要多 Agent。我见过不少项目明明一个 Agent 加几个工具就能解决非要拆成 Planner Agent、Executor Agent、Reviewer Agent 三个角色结果通信开销翻倍调试难度指数级上升效果还不如单 Agent。判断是否需要多 Agent 的标准很简单如果子任务之间需要不同的系统提示词、不同的工具集、或者不同的模型那才考虑拆分。比如一个代码生成场景写代码和审查代码确实需要不同的提示词和关注点拆成两个 Agent 是合理的。但如果只是“查数据然后总结”一个 Agent 完全够用。多 Agent 编排的通信机制也有讲究。常见的有共享内存所有 Agent 读写同一个状态对象和消息传递Agent 之间通过消息队列通信。共享内存实现简单但容易出现状态竞争消息传递解耦彻底但调试复杂。我一般推荐共享内存加锁的方式在状态更新时加版本号避免并发写冲突。2.7 安全层Agent 的刹车和护栏安全层是 Agent 工程实现中最容易被忽视、但出事后果最严重的一层。Agent 有了工具调用能力就意味着它能对真实世界产生副作用——发消息、改数据、调接口。一旦失控后果不是“回答错了”这么简单。安全层的设计分三个层次输入过滤、行为约束、输出审查。输入过滤是防止提示词注入比如用户输入里包含“忽略之前的指令”这类内容要在进入 Agent 之前就检测并处理。行为约束是限制 Agent 能调用的工具范围和参数范围比如涉及资金操作的工具必须加二次确认或人工审批。输出审查是在 Agent 返回结果前检查结果是否包含敏感信息或不当内容。这里有个实操技巧给每个工具打上风险等级标签。低风险工具如查询类可以直接调用中风险工具如写入类需要参数校验高风险工具如删除类、支付类必须走人工确认流程。这个标签体系要在工具注册时就定义好而不是等到出问题再补。3. 七个决策点Agent 运转时的关键取舍3.1 决策点一什么时候该调用工具什么时候该直接回答这是 Agent 循环中最频繁的决策。模型每收到一个输入都要判断这个问题我能直接回答还是需要调用工具判断错了要么浪费一次工具调用要么给出过时或错误的信息。我的经验是在系统提示词里明确给出判断规则而不是让模型自由发挥。规则可以这样写涉及实时数据、外部系统状态、需要精确计算的问题必须调用工具涉及常识、通用知识、简单推理的问题直接回答。同时给几个正反例让模型有参照。但规则不是万能的。我实测下来模型在边界情况上仍然会判断失误。所以我在执行层加了一个兜底逻辑如果模型直接回答了但回答中包含了“根据我的知识”“截至我训练时”这类模糊表述就强制触发一次工具调用验证。这个兜底逻辑帮我避免了好几次“模型自信地给出过时信息”的事故。3.2 决策点二工具调用的参数怎么生成和校验参数生成是工具调用中最容易出错的环节。模型需要根据当前上下文填充工具定义的参数。参数类型越复杂出错概率越高。我的做法是三层校验第一层是模型输出时的格式校验要求模型输出严格的 JSON用 schema 验证第二层是参数值校验检查参数是否在允许范围内比如枚举值是否合法、字符串长度是否超限第三层是业务校验在工具执行前做一次业务规则检查比如查询的订单 ID 是否属于当前用户。三层校验都通过才执行工具。任何一层失败都把错误信息返回给模型让它重新生成参数。但重试次数要限制我一般设置最多重试 2 次超过就终止当前步骤走异常处理流程。因为连续重试失败通常意味着模型理解不了这个工具继续试只是浪费 token。3.3 决策点三上下文怎么压缩和传递上下文管理是 Agent 工程实现中最考验功力的地方。上下文太短模型缺少必要信息上下文太长成本高、延迟大、还容易触发模型的“中间遗忘”问题。我的压缩策略是分层压缩系统提示词和工具定义不压缩这是固定开销历史对话按轮次压缩每 5 轮做一次摘要保留决策点和结果工具返回结果按需压缩只保留关键字段大段数据存到外部存储上下文里只放引用 ID。传递策略上我倾向于显式传递关键状态而不是依赖模型从长上下文中自己找。比如当前任务的目标、已完成的步骤、待完成的步骤这些信息在每一步都显式地放在提示词里而不是让模型去翻历史记录。这样虽然增加了提示词长度但大幅提升了模型决策的准确性。3.4 决策点四循环什么时候终止前面在七要素里提到了终止条件这里重点讲终止判断的实现细节。终止判断不能只依赖模型自己说“我完成了”因为模型经常在没完成的时候就说完成了。我的做法是双重判断模型输出一个完成信号同时规划层的验证逻辑独立判断任务是否真的完成。两者都认为完成才终止循环。如果模型说完成了但验证不通过就把验证失败的原因返回给模型让它继续。另外最大步数的设置要结合任务复杂度动态调整。简单任务 5 步中等任务 10 步复杂任务 15 步。超过最大步数时不要直接报错而是输出当前已完成的部分和未完成的部分让调用方决定是继续还是放弃。3.5 决策点五错误怎么处理和恢复Agent 运行中的错误分三类模型错误输出格式不对、调用不存在的工具、工具错误超时、返回异常、业务错误参数不合法、权限不足。三类错误的处理策略不同。模型错误用重试加提示修正把错误信息返回给模型让它重新生成。工具错误用降级加兜底比如查询工具超时可以返回缓存数据或提示用户稍后重试。业务错误用终止加报告因为业务错误通常意味着当前路径走不通继续循环没有意义。我踩过的一个坑是错误处理没有区分可恢复和不可恢复。有一次工具返回了“权限不足”但我的处理逻辑把它当成了可重试错误模型反复尝试调用同一个工具循环了十几次才被最大步数拦住。后来我在错误分类里明确标注了哪些错误可重试、哪些不可重试不可重试的错误直接终止当前分支。3.6 决策点六并发怎么扛“AI Agent 怎么扛并发”是最近被问得很多的问题。Agent 的并发压力来自两个层面模型调用的并发和工具调用的并发。模型调用的并发控制核心是限流加排队。不要一次性把所有请求都发给模型服务要根据模型服务的配额设置并发上限超出的请求进入队列。队列要有优先级交互式请求优先于批处理请求。同时要有超时机制排队超过一定时间的请求直接返回“系统繁忙”避免用户无限等待。工具调用的并发控制更复杂因为不同工具的承载能力不同。我的做法是给每个工具配置独立的并发池和超时时间。查询类工具并发可以高一些写入类工具并发要低有副作用的工具最好串行化。工具调用还要加熔断机制连续失败达到阈值就暂时熔断避免雪崩。另外Agent 的状态管理在并发场景下要特别注意。如果多个请求共享同一个 Agent 实例状态必须隔离。我一般用请求级别的状态对象每个请求独立创建请求结束就销毁避免状态污染。3.7 决策点七效果怎么评估和迭代Agent 上线不是终点而是迭代的起点。评估 Agent 效果不能只看“用户满不满意”要有量化的指标。我常用的指标有四个任务完成率成功完成的任务占比、平均步数完成任务的循环步数、工具调用准确率工具调用参数正确的比例、平均耗时。这四个指标能覆盖效果、效率、质量、性能四个维度。评估数据的来源是执行轨迹。每次 Agent 运行都记录完整轨迹定期抽样分析。分析的重点是失败案例看失败集中在哪个环节是规划不合理还是工具调用出错还是终止判断失误。找到问题环节后针对性地优化提示词、调整工具定义、或者修改循环逻辑。迭代要有节奏不要频繁改动。我一般两周一个迭代周期每个周期聚焦一个指标优化。改动后要跑回归测试确保没有引入新的问题。回归测试集要覆盖典型场景和边界场景每次迭代都跑一遍。4. 实操落地从零搭一个可用的 Agent 骨架4.1 技术选型LangGraph、Spring AI 还是自研技术选型没有绝对的好坏只有适不适合。LangGraph 的优势是生态成熟、工具丰富、社区活跃适合快速验证和中小规模生产。Spring AI 的优势是和 Java 生态无缝集成适合已有 Java 技术栈的团队。自研的优势是完全可控、没有框架约束适合有特殊需求或对性能有极致要求的场景。我的建议是先用 LangGraph 或 Spring AI 快速搭出原型验证核心流程跑得通再根据实际瓶颈决定是否自研。不要一上来就自研因为 Agent 的坑大多在流程设计上不在框架实现上。框架帮你把流程跑通了你才知道真正的瓶颈在哪。如果决定自研核心要实现四个模块模型调用封装、工具注册与调度、状态管理、循环控制。模型调用封装要支持多模型切换和重试工具注册要支持动态注册和参数校验状态管理要支持请求隔离和持久化循环控制要支持终止条件和错误处理。4.2 核心流程的代码骨架下面是一个简化的 Agent 循环骨架用 Python 伪代码展示核心逻辑。实际实现中需要根据具体框架调整。class AgentLoop: def __init__(self, model, tools, max_steps10): self.model model self.tools tools self.max_steps max_steps def run(self, task_input): state { task: task_input, history: [], step: 0, done: False } while not state[done] and state[step] self.max_steps: # 1. 构建当前上下文 context self.build_context(state) # 2. 模型决策 decision self.model.decide(context) # 3. 判断决策类型 if decision.type tool_call: result self.execute_tool(decision) state[history].append({ step: state[step], action: decision, result: result }) elif decision.type final_answer: if self.verify(decision, state): state[done] True state[answer] decision.content else: state[history].append({ step: state[step], action: verification_failed, reason: answer not verified }) state[step] 1 return state这个骨架的关键点在于每一步都记录历史决策类型显式区分完成判断有独立验证。实际实现中还要加上错误处理、超时控制、日志记录等。4.3 工具注册的配置示例工具注册我推荐用配置化的方式而不是硬编码。下面是一个工具配置的示例TOOL_CONFIG { query_order: { description: 根据订单ID查询订单状态, parameters: { order_id: {type: string, pattern: ^ORD[0-9]{10}$}, query_type: {type: enum, values: [status, logistics, refund]} }, risk_level: low, timeout: 5, retry: 2, idempotent: True }, send_notification: { description: 向用户发送通知消息, parameters: { user_id: {type: string}, message: {type: string, max_length: 500} }, risk_level: medium, timeout: 10, retry: 1, idempotent: False, idempotency_key_required: True } }这个配置里risk_level决定了工具调用前需要几层校验timeout和retry决定了容错策略idempotent决定了重试是否安全。把这些元信息在注册时就定义好运行时就不用临时判断逻辑更清晰。4.4 上下文预算的计算过程上下文预算的计算我一般按 token 数来算。假设模型上下文窗口是 128K token我的分配方案是系统提示词和工具定义固定 20K token历史对话动态分配上限 40K token工具返回结果动态分配上限 30K token当前任务输入预留 20K token输出预留18K token当历史对话超过 40K 时触发摘要压缩把最早的 10K token 对话压缩成 2K token 的摘要。当工具返回结果超过 30K 时只保留关键字段大段数据存外部存储上下文里放引用 ID。这个分配不是固定的要根据任务类型调整。对话密集型任务历史对话预算要高一些工具密集型任务工具返回预算要高一些。关键是每次调整后要跑测试看任务完成率有没有下降。5. 常见问题与排查技巧实录5.1 循环停不下来怎么办循环停不下来是最常见的问题表现是 Agent 反复执行相似动作步数不断增加但任务没有进展。排查思路是看执行轨迹找到循环开始重复的那一步分析为什么模型认为还需要继续。常见原因有三个一是工具返回结果没有包含模型期望的信息模型以为没查到反复查二是终止条件判断逻辑有 bug模型说完成了但验证不通过三是提示词里没有明确告诉模型“什么情况下应该停止”。解决方法首先检查工具返回格式是否包含明确的状态标识其次检查验证逻辑是否正确最后在提示词里加一句“如果你已经获得了足够的信息来回答用户问题请直接输出最终答案不要继续调用工具”。5.2 工具调用参数总是填错参数填错通常是因为工具定义不够清晰或者参数约束不够严格。排查时先看错误集中在哪个参数上如果是枚举参数填错说明枚举值没有在工具描述里列清楚如果是格式参数填错说明缺少格式示例。解决方法在工具描述里给出每个参数的示例值枚举参数列出所有合法值格式参数给出正则表达式或示例。同时加参数校验层校验失败时把错误信息和正确格式一起返回给模型帮助它修正。5.3 并发上来后响应变慢甚至超时并发问题通常出在模型调用和工具调用的资源竞争上。排查时先看是模型调用慢还是工具调用慢再看是哪个环节在排队。解决方法模型调用加限流和队列工具调用按工具类型配置独立并发池。同时检查是否有共享状态导致的锁竞争如果有改成请求级状态隔离。另外超时时间要合理设置不要设得太长否则慢请求会拖垮整个系统。5.4 同一个任务每次结果不一样结果不一致是 LLM 的固有特性但可以通过工程手段降低波动。排查时先看波动在哪个环节是规划步骤不同还是工具调用参数不同还是最终答案表述不同。解决方法降低模型温度参数规划步骤用更确定的提示词工具调用参数加更严格的校验。对于关键任务可以加一次结果一致性检查如果两次运行结果差异过大触发人工审核。5.5 常见问题速查表问题现象可能原因排查方向解决思路循环停不下来终止条件失效看执行轨迹重复点加最大步数兜底明确停止条件参数填错工具定义模糊看错误参数分布加参数示例和校验层并发超时资源竞争看模型和工具耗时限流、队列、独立并发池结果不一致模型随机性看波动环节降温度、加校验、一致性检查工具调用失败下游服务问题看错误码分布超时、重试、熔断、降级上下文溢出预算分配不合理看 token 消耗分布分层压缩外部存储5.6 几个踩坑后总结的实操心得第一个心得Agent 的提示词要当代码来管理。不要直接在代码里拼字符串要把提示词抽成模板文件加版本号改动要走 review。因为提示词的一个小改动可能对 Agent 行为产生巨大影响没有版本管理根本追查不了问题。第二个心得执行轨迹要存够久。我一般保留 30 天的完整轨迹因为很多问题不是当天发现的用户可能过几天才反馈。轨迹里要包含完整的输入输出、时间戳、模型版本、工具版本缺一个都可能导致排查卡住。第三个心得不要追求一次做完美。Agent 系统是迭代出来的先跑通核心流程再逐步加记忆、加规划、加安全。一上来就设计一个大而全的架构大概率是过度设计而且调试起来极其痛苦。第四个心得测试集比提示词更重要。我每个 Agent 项目都会维护一个至少 50 条的真实任务测试集每次改动提示词或工具定义都跑一遍测试集看通过率。没有测试集的 Agent 迭代就是盲人摸象。6. 关于 Agent 框架和工具链的一些个人看法LangGraph 的工具调用机制是我目前用得最顺手的它的状态图模型和 Agent 循环天然契合节点和边的概念让流程可视化程度很高。但它的学习曲线确实陡新手容易在状态定义和条件边上卡住。我的建议是先跑通官方示例理解状态流转的逻辑再动手改。Spring AI Agent 适合 Java 团队它的优势是类型安全和依赖注入工具定义用注解就能完成和 Spring 生态集成得很自然。但它的生态丰富度不如 Python 侧一些高级功能可能需要自己实现。基于 Rust 语言做 AI Agent 是最近比较热的方向优势是性能和内存安全适合对延迟和资源占用有极致要求的场景。但 Rust 生态的 LLM 客户端和工具库还在完善中开发效率会比 Python 低不少。我的看法是除非你有明确的性能瓶颈且 Python 优化空间已经用尽否则没必要为了性能牺牲开发效率。关于 Agent 中台我的观点是中台适合有多个 Agent 项目的团队单项目不需要中台。中台的核心价值是复用工具、统一监控、集中管理提示词。如果只有一个 Agent 项目这些能力直接做在项目里更简单。中台的建设和维护成本不低没有足够的项目数量摊薄成本反而会拖慢迭代速度。Agent 安全这块我特别想强调一点不要等出事再补安全。Agent 有了工具调用能力就等于给了它操作真实系统的权限。权限控制、操作审计、敏感操作二次确认这些要在第一版就设计进去而不是等上线后发现问题再补。补安全的成本远高于一开始就设计好。最后说一个我自己的判断Agent 的工程实现未来会越来越标准化。现在大家还在讨论七要素、七决策点过两年这些可能会像 MVC 一样成为常识。但标准化的过程需要大量实践沉淀现在动手做的人积累的经验就是未来的竞争力。不要等标准出来了再学那时候标准已经变成门槛了。