
1. 从“能跑”到“跑得对”为什么你的 Agent 需要一个判断器做 Agent 开发的人大概都有过这种体验流程跑通了工具调用了日志也打印了但结果就是不对劲。模型该调搜索的时候它去调计算器该输出结构化数据的时候它给你来一段散文该停下来等你确认的时候它自作主张把下一步也干了。这不是模型能力不够而是缺少一个东西——判断器。所谓判断器说白了就是在 Agent 的执行链路里加一层“决策校验”。它不负责生成内容只负责判断当前这一步该不该做、做得对不对、要不要继续往下走。你可以把它理解成工厂流水线上的质检员产品能不能进入下一道工序质检员说了算而不是让机器自己拍脑袋。这次要聊的 Laya 和 Jev就是围绕这个思路出现的两个工具。Laya 偏向决策层的判断与编排Jev 则更聚焦在执行环节的校验与约束。两者配合起来能给 Agent 装上一套相对完整的“判断系统”。再加上 Python 生态的部署便利性整套方案落地门槛并不高。这篇文章适合谁看如果你正在做 Agent 项目已经过了“Hello World”阶段开始被各种边界情况折磨那这篇内容就是写给你的。如果你还在选框架的阶段也可以看看这套判断器的思路是否契合你的场景。我会从设计思路、核心机制、部署实操、问题排查几个维度展开尽量把踩过的坑和验证过的方案都讲清楚。2. Laya 与 Jev 的定位拆解两个判断器到底在判断什么2.1 Laya 的核心角色决策层的“红绿灯”Laya 在整套体系里承担的是决策判断的职责。Agent 在每一步执行前会先把当前状态、可用工具、历史上下文交给 Laya由它来判断这一步应该走哪条路。这个判断不是简单的 if-else而是基于模型对上下文的理解做出的语义级决策。我自己的理解是Laya 解决的是“选择困难症”问题。Agent 面对多个可选工具时经常会出现乱选、重复选、该选不选的情况。Laya 的作用就是在这些岔路口亮红绿灯告诉 Agent 此路通不通。它的判断逻辑通常包含几个维度意图匹配度当前用户请求和某个工具的适用场景是否吻合上下文一致性这一步的选择和前几步的执行结果是否矛盾资源可用性目标工具当前是否可用、是否在配额范围内风险等级这一步操作是否涉及敏感动作需不需要人工确认这几个维度组合起来就形成了一个多维度的判断矩阵。Laya 会根据这个矩阵输出一个决策结果Agent 拿到结果后再决定是否执行。2.2 Jev 的核心角色执行层的“校验器”如果说 Laya 管的是“做不做”那 Jev 管的就是“做得对不对”。Jev 工作在 Agent 实际调用工具之后、拿到返回结果之时负责校验执行结果是否符合预期。举个例子Agent 调用了一个数据查询接口返回了一堆 JSON。这堆 JSON 格式对不对、字段全不全、数值合不合理这些就是 Jev 要判断的事情。它不关心你为什么要查这个数据只关心查出来的东西能不能用。Jev 的校验通常覆盖这几类校验类型判断内容典型场景格式校验返回结构是否符合预期 schemaAPI 返回 JSON 字段缺失语义校验内容是否与请求意图一致搜索返回了不相关结果边界校验数值是否在合理范围内计算结果出现异常值安全校验是否包含敏感或违规内容用户输入注入攻击这四类校验叠加起来基本能拦住大部分“看起来跑了但结果不能用”的情况。2.3 两者协作的链路关系Laya 和 Jev 不是二选一的关系而是前后衔接的。一个完整的 Agent 执行链路大致是这样的用户输入 → Laya 判断该调哪个工具 → Agent 执行工具调用 → Jev 校验执行结果 → 结果合格则继续不合格则回退或重试 → 进入下一轮 Laya 判断这个链路里Laya 负责“入口把关”Jev 负责“出口质检”。两头都卡住了中间的执行环节才不会跑偏。我实测下来加了这两层判断之后Agent 的任务完成率大概能从 60% 出头提升到 85% 以上。当然这个数字因场景而异但趋势是明确的判断器带来的收益远大于它增加的延迟。3. 判断器的核心机制从规则到模型的演进3.1 规则引擎阶段快但不够聪明最早期的判断器基本都是规则堆出来的。写一堆 if-else匹配关键词命中就走对应分支。这种方式的好处是快、可控、可解释坏处是脆——稍微换个说法就匹配不上了。比如你写了一条规则“如果用户输入包含‘天气’就调天气接口”。结果用户说“今天出门要不要带伞”规则就失效了。你得再补一条规则再补一条最后规则库膨胀到几千条维护成本高得离谱。规则引擎适合场景非常固定的情况比如内部系统的固定流程。但面对开放域的用户输入规则引擎的天花板很低。3.2 模型判断阶段灵活但需要约束Laya 和 Jev 走的是模型判断路线。把判断任务交给语言模型来做利用模型的语义理解能力来处理多样化的输入。这就解决了规则引擎“换个说法就失效”的问题。但模型判断也有自己的问题不稳定。同一个输入今天判断对了明天可能就判断错了。温度参数稍微调一下结果就飘了。所以模型判断必须配合约束机制不能完全放任。常见的约束手段包括结构化输出强制模型输出 JSON 格式的判断结果而不是自由文本判断维度拆解把一个大判断拆成多个小判断逐个输出结果置信度阈值模型输出判断的同时给出置信度低于阈值时转人工或走兜底逻辑少样本示例在 prompt 里塞几个判断示例锚定模型的输出风格这几招组合起来能把模型判断的稳定性拉到可用的水平。3.3 混合判断规则兜底加模型主判实际落地中纯模型判断和纯规则判断都不太够用。我目前采用的方案是混合判断模型做主判断规则做兜底。具体来说Laya 先让模型输出一个判断结果和置信度。如果置信度高于某个阈值比如 0.8就直接采纳模型判断。如果低于阈值就进入规则兜底逻辑用预设的规则做二次判断。如果规则也判断不了就走人工确认或者默认安全路径。这个方案的好处是兼顾了灵活性和稳定性。大部分常规情况由模型快速处理边缘情况由规则兜底极端情况走人工。三层防护下来判断准确率能稳定在比较高的水平。Jev 那边也是类似的思路。模型负责语义级校验规则负责格式和边界校验。两者各管一段互不干扰。4. 部署实操Python 环境下把判断器跑起来4.1 环境准备与依赖安装部署这套判断器Python 环境是基础。我建议用 3.10 或 3.11 版本太老的版本有些库不支持太新的版本有些库还没跟上。用 conda 或者 venv 建一个独立环境避免和系统 Python 打架。conda create -n agent-judge python3.11 conda activate agent-judge核心依赖大概这几类pip install openai1.0.0 pip install pydantic2.0 pip install fastapi uvicorn pip install redis pip install loguruopenai用来调模型接口做语义判断pydantic用来定义判断结果的数据结构做格式校验fastapi用来把判断器包装成 HTTP 服务redis用来做判断结果的缓存避免重复判断loguru用来打日志排查问题的时候很方便注意模型接口的 key 不要硬编码在代码里用环境变量或者配置文件管理。我见过太多把 key 提交到仓库的案例了后果很严重。4.2 Laya 判断服务的搭建Laya 服务的核心是一个判断函数输入是当前上下文输出是判断结果。我用 FastAPI 把它包成一个接口from fastapi import FastAPI from pydantic import BaseModel from typing import List, Optional class JudgeRequest(BaseModel): user_input: str history: List[dict] available_tools: List[str] context: Optional[dict] None class JudgeResponse(BaseModel): decision: str confidence: float reason: str fallback: bool False app FastAPI() app.post(/laya/judge) async def laya_judge(req: JudgeRequest) - JudgeResponse: # 第一步模型判断 model_result await model_judge(req) # 第二步置信度检查 if model_result.confidence 0.8: return model_result # 第三步规则兜底 rule_result rule_fallback(req) if rule_result: return rule_result # 第四步默认安全路径 return JudgeResponse( decisionask_user, confidence0.5, reason无法确定意图转人工确认, fallbackTrue )这个结构看起来简单但每一层都有讲究。模型判断那一步的 prompt 设计是关键我后面会单独讲。置信度阈值 0.8 是调出来的太低会放过错误判断太高会频繁触发兜底。规则兜底那一步要覆盖高频场景不能太复杂。4.3 Jev 校验服务的搭建Jev 服务的结构和 Laya 类似但校验逻辑不同class VerifyRequest(BaseModel): tool_name: str tool_input: dict tool_output: dict expected_schema: Optional[dict] None class VerifyResponse(BaseModel): passed: bool issues: List[str] severity: str # low / medium / high app.post(/jev/verify) async def jev_verify(req: VerifyRequest) - VerifyResponse: issues [] # 格式校验 if req.expected_schema: schema_issues check_schema(req.tool_output, req.expected_schema) issues.extend(schema_issues) # 语义校验 semantic_issues await semantic_check(req) issues.extend(semantic_issues) # 边界校验 boundary_issues check_boundary(req.tool_output) issues.extend(boundary_issues) severity high if any(critical in i for i in issues) else \ medium if issues else low return VerifyResponse( passedlen(issues) 0, issuesissues, severityseverity )Jev 的校验是分层的格式校验最快最便宜语义校验最慢但最准。实际运行的时候格式校验不过就直接返回了不用再跑语义校验这样能省不少 token。4.4 判断结果的缓存策略判断器跑起来之后你会发现很多判断是重复的。同样的用户输入、同样的上下文判断结果应该是一样的。这时候加一层缓存能显著降低延迟和成本。我用 Redis 做判断结果缓存key 是输入内容的 hashvalue 是判断结果过期时间设 1 小时。命中缓存的判断直接返回不用再调模型。import hashlib import json import redis r redis.Redis(hostlocalhost, port6379, db0) def cache_key(req_dict: dict) - str: content json.dumps(req_dict, sort_keysTrue) return fjudge:{hashlib.md5(content.encode()).hexdigest()} async def cached_judge(req): key cache_key(req.dict()) cached r.get(key) if cached: return JudgeResponse(**json.loads(cached)) result await laya_judge(req) r.setex(key, 3600, result.json()) return result提示缓存 key 的生成要注意把影响判断结果的所有字段都包含进去漏了任何一个字段都可能导致缓存污染。我一开始就漏了 history 字段结果不同对话历史下的判断结果串了排查了半天才发现。5. Prompt 设计判断器准不准八成看这里5.1 Laya 判断 Prompt 的结构Laya 的 prompt 我改过十几版目前稳定下来的结构是这样的你是一个 Agent 决策判断器。你的任务是判断当前步骤应该调用哪个工具。 ## 可用工具 {tools_description} ## 对话历史 {history} ## 当前用户输入 {user_input} ## 判断要求 1. 分析用户意图判断需要调用哪个工具 2. 如果不需要调用任何工具输出 no_tool 3. 如果有多个工具可选选择最匹配的一个 4. 输出置信度范围 0-1 ## 输出格式 { decision: 工具名称或no_tool, confidence: 0.95, reason: 判断理由 }这个 prompt 有几个关键点工具描述要写清楚每个工具的适用场景不能只写名字对话历史要截断到最近几轮太长了模型会分心输出格式要严格约束用 JSON 而不是自由文本。5.2 Jev 校验 Prompt 的结构Jev 的 prompt 侧重点不同它要判断的是“结果对不对”你是一个执行结果校验器。你的任务是判断工具返回的结果是否合理。 ## 工具信息 工具名称{tool_name} 调用参数{tool_input} ## 返回结果 {tool_output} ## 校验要求 1. 结果是否与调用意图一致 2. 结果内容是否完整、无明显缺失 3. 结果是否包含异常值或错误信息 4. 如果发现问题指出具体问题 ## 输出格式 { passed: true/false, issues: [问题描述], severity: low/medium/high }Jev 的 prompt 里工具信息和调用参数是必须的。没有这些上下文模型没法判断结果是否合理。比如一个搜索工具返回了空结果如果不知道搜索词是什么就没法判断这个空结果是正常的还是异常的。5.3 少样本示例的选取技巧Prompt 里塞示例能显著提升判断准确率但示例怎么选有讲究。我的经验是正例和反例都要有只给正例模型不知道边界在哪覆盖高频场景把实际运行中出现最多的几种情况都放进去示例要短每个示例控制在 3-5 行太长了占 token 还分散注意力定期更新运行一段时间后把新出现的边缘情况补进去我一般放 3-5 个示例太多反而效果下降。示例的位置放在判断要求之前让模型先看例子再看规则。5.4 温度参数与输出稳定性判断任务对稳定性的要求很高所以温度参数要调低。我一般设 0.1 到 0.3 之间。设 0 也可以但有时候会陷入重复输出的死循环。0.1 是个比较稳妥的值。另外top_p也可以适当调低比如 0.9。这两个参数配合起来能让判断结果在多次调用之间保持较高的一致性。注意不同模型对温度参数的敏感度不一样。换模型的时候一定要重新调参不能直接沿用。我在切换模型的时候偷懒没调结果判断准确率掉了一大截查了两天才发现是温度的问题。6. 常见问题与排查技巧实录6.1 判断结果不稳定怎么办这是最常见的问题。同一个输入判断结果时对时错。排查思路按这个顺序来检查温度参数先确认温度是不是设高了调到 0.1 试试检查 prompt 一致性确认每次调用的 prompt 结构完全一样没有动态拼接导致的差异检查缓存如果用了缓存确认缓存 key 是否包含了所有影响判断的字段检查模型版本确认调用的模型版本没有变化有些接口会悄悄升级模型增加示例在 prompt 里补充几个容易判断错的示例如果以上都排查了还是不稳定那可能是模型本身的能力边界问题考虑换一个更强的模型或者把判断任务拆得更细。6.2 判断延迟太高怎么优化判断器增加了 Agent 的响应延迟这是必然的。但如果延迟高到影响体验就需要优化。我常用的几招优化手段效果代价加缓存重复判断延迟降为 0需要 Redis有内存成本并行判断多个判断同时跑需要改造调用逻辑小模型主判延迟降低 50% 以上准确率可能下降规则前置高频场景不走模型规则维护成本流式输出感知延迟降低实现复杂度增加我一般先加缓存这是性价比最高的。然后看高频场景能不能用规则覆盖能覆盖的就前置掉。最后才考虑换小模型因为准确率下降的代价可能比延迟更严重。6.3 判断器误判的兜底方案判断器再准也会有误判的时候关键是要有兜底。我的兜底策略分三级一级兜底判断置信度低于阈值时走规则判断二级兜底规则也判断不了时走默认安全路径通常是询问用户三级兜底用户反馈判断错误时记录 case 并加入示例库三级兜底下来即使判断器出错也不会造成严重后果。而且每次用户反馈都是一次优化机会示例库会越来越丰富判断准确率会逐步提升。6.4 常见问题速查表问题现象可能原因排查方向判断结果随机变化温度参数过高调低 temperature 到 0.1判断总是走兜底置信度阈值过高降低阈值或增加示例判断延迟波动大模型接口不稳定加超时和重试机制缓存命中率低缓存 key 设计不合理检查 key 包含的字段特定场景总判错示例覆盖不足补充该场景的示例判断服务 OOM并发过高或内存泄漏加限流检查连接池这张表是我踩坑踩出来的基本覆盖了 80% 的常见问题。遇到问题先查表能省不少时间。7. 工具选型Laya、Jev 还是自己造7.1 什么场景适合用现成方案如果你的 Agent 项目满足这几个条件用 Laya 和 Jev 这类现成方案是划算的项目周期紧没有时间从零造判断器判断需求比较通用没有太多特殊逻辑团队里没有专门做模型调优的人能接受一定程度的黑盒不需要完全可控现成方案的好处是开箱即用文档和社区支持都比较完善。坏处是灵活性受限遇到特殊需求可能改不动。7.2 什么场景适合自建判断器反过来如果满足这些条件建议自建判断逻辑和业务强相关通用方案覆盖不了对延迟、成本有极致要求需要深度优化团队有模型调优能力能持续迭代 prompt需要完全可控不能接受黑盒自建的成本主要在前期prompt 调优和兜底逻辑设计比较费时间。但一旦跑通后续的可控性和优化空间都更大。7.3 混合方案现成框架加自定义判断层实际落地中我更多采用的是混合方案用现成框架做基础判断在关键环节插入自定义判断层。比如用 Laya 做通用的工具选择判断但在涉及资金、权限等敏感操作时插入一层自定义的规则判断。这样既享受了现成方案的便利又保证了关键环节的可控性。混合方案的关键是定义好判断层的接口让自定义判断层能无缝接入框架的判断链路。这个接口设计好了后续替换或升级判断层都很方便。8. 判断器的边界与我的实际体会判断器不是万能的。它能解决的是“选择”和“校验”的问题解决不了“模型本身能力不足”的问题。如果模型对某个领域的理解就是不到位判断器再怎么判断也判断不出正确结果。我实际用下来判断器带来的最大价值不是提升准确率而是让错误变得可观测、可拦截。以前 Agent 跑错了你只能看最终结果不知道哪一步开始错的。加了判断器之后每一步的判断结果都有日志哪一步判断置信度低、哪一步校验没过一目了然。排查问题的效率提升了好几倍。另一个体会是判断器的 prompt 需要持续迭代。我现在的做法是每周 review 一次判断日志把判断错误的 case 挑出来分析原因补充到示例库里。这个习惯坚持了几个月判断准确率从最初的 70% 多提升到了 90% 以上。最后分享一个小技巧判断器的日志一定要打全包括输入、输出、置信度、耗时、是否命中缓存。这些信息在排查问题的时候都是关键线索。我一开始日志打得太简略出了问题只能靠猜后来把日志补全了排查效率完全不一样。