news 2026/10/22 3:32:25

LangChain Agent 不稳定?试试 Harness Engineering 这套外壳

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LangChain Agent 不稳定?试试 Harness Engineering 这套外壳

很多人在 LangChain 里写 Agent,写完第一版感觉特别顺,模型一调、工具一接,好像什么都能干。但一旦丢到真实业务里,问题就全冒出来了:任务稍微绕一点就跑偏,同样的输入有时候对有时候错,Token 消耗忽高忽低,甚至同一个 Agent 在不同时段的表现都稳定不下来。遇到这种情况,大部分人第一反应是换更强的模型,或者把 Prompt 改得更长更细。但实测下来,真正让 Agent 表现发生质变的,往往不是模型本身,而是外面那层“约束”和“调度”的壳子,也就是 Harness Engineering。

我第一次接触到这个概念是在一个内部项目复盘会上。当时团队里做了一个文档问答 Agent,模型用的已经是当时能拿到的最强版本,Prompt 也迭代了七八版,但效果就是卡在那里:简单问题没问题,复杂问题开始胡诌。后来一位做系统设计的老工程师提了一句“你们别老想着让模型变聪明,得想想怎么让系统变聪明”,这句话直接改变了我的思路。我们把注意力从 Prompt 内部转向了 Agent 的外部框架——工具的注册方式、调度的策略、输出的校验机制、状态的流转控制,全部重新设计了一遍。结果同样一个模型,准确率从 68% 拉到 90% 以上,Token 消耗反而下降了 30% 多。

这篇文章就想把这个思路完整梳理一遍。会先从 Harness Engineering 的核心思想讲起,说明它为什么比单纯调 Prompt 更有效;然后拆解它在 LangChain 里的具体落地方式,包括工具注册表怎么设计、路由决策怎么控制、输出怎么校验、状态机怎么管理;接着用一个虚构的客户支持 Agent 案例完整走一遍实操流程;最后把项目里真实踩过的坑和排查思路整理出来。无论你是刚开始接触 LangChain 的新手,还是已经被 Agent 不稳定问题折磨过一阵子的开发者,这篇文章应该都能给你一些可以直接抄走的方案。

1. Harness Engineering 的核心思想:别让模型做所有决策

很多 Agent 项目失败,根源不在模型能力不够,而是我们让模型承担了太多它不擅长的工作。模型擅长的是“文本生成”和“模式补全”,但任务拆解、格式控制、状态管理、工具选择这些事情,它做起来既不稳定又浪费 Token。Harness Engineering 的核心理念就是把这些决策从模型手里拿回来,交给外部代码来处理。

1.1 为什么 Prompt Engineering 到了后期总是不够用

Prompt Engineering 在项目初期见效特别快,因为它的成本极低,改几个字就能看到变化。但到了中后期,它的边际收益会急剧下降。原因也很简单:Prompt 本质上是在“说服”模型做正确的事,而模型的注意力分配天生就是概率性的。你今天加了句“请一步一步思考”,它可能老实两天,加到第十几个版本之后,模型学会了“假装一步一步思考”,该错的还是错。

我在项目里见过最典型的一个例子是日期理解。我们在 Prompt 里反复强调“当前时间是 2025 年 6 月”,但模型在处理用户消息“下周一之前帮我整理完”的时候,依然会按照训练数据里的时间惯性去推算。这不是 Prompt 写得不够清楚,而是模型的“当前时间感”天然就是模糊的。Harness Engineering 的解法很直接:当前时间根本不需要让模型知道,外部代码直接算好具体日期,作为参数传给工具函数,模型只是负责填参数而已。

另一个例子是输出格式。用 Prompt 约束模型输出 JSON,成功率看起来不低,但一旦返回内容变长,偶尔就会出现尾括号缺失、字段名拼错、字符串里混入特殊字符的问题。你当然可以在 Prompt 后面再加一句“请确保输出合法 JSON”,但实测下来,模型出现格式错误的概率并不会因此降为零。Harness Engineering 的做法是:让模型用结构化生成(比如函数调用)来输出,外部代码拿到的是已经结构化的参数,压根不存在解析失败的问题。

1.2 Harness Engineering 的“约束”到底是什么意思

Harness 这个词在工程领域原本指“线束”或“安全背带”,引申到 Agent 开发里,意思就是给 Agent 装上一套外部约束系统,让它在一个受控的轨道里运行。这套约束包括几个层面:

第一层是工具约束。Agent 能调用哪些工具、每个工具的参数格式是什么、工具的返回结果怎么处理,全部由外部系统定义。模型只能从注册表里选工具,不能凭空创造工具。

第二层是流程约束。Agent 的每一步操作都由外部状态机控制,同一个任务里,哪些步骤允许执行、哪些步骤还没解锁,代码说了算。模型只能在当前状态下做有限的选择。

第三层是质量约束。Agent 的输出必须经过外部校验器检查,格式不对就重试,内容不合法就拦截,置信度过低就切换方案。模型自己判断不了的“自己的输出对不对”,外部代码来兜底。

这三层约束合在一起,其实就是把“模型 + 工具 + 控制逻辑”封装成一个更可靠的系统。系统的可靠性不依赖模型的临场发挥,而是依赖外部代码的可预期性。这就像你雇了一个很有才华的新人,他不会用公司的报销系统、不懂项目流程、也不清楚谁负责什么,但他逻辑能力很强。你不可能靠一遍遍叮嘱他“记住了啊,报销要找财务”来解决问题,而是应该给他一套标准作业流程、一张职权对照表、一个审批系统,让他不用动脑子就能把事情做对。

1.3 一个公式理解 Harness Engineering 的价值

假设模型单独处理一个任务的成功率是 p,任务可以被拆成 n 个独立步骤。如果所有步骤都靠模型自由发挥,总成功率是 p 的 n 次方。p 是 0.9,n 是 5,总成功率只有 59%——这就是很多 Agent 项目表现不稳定的数学解释。如果你通过外部约束把其中 3 个步骤的成功率提升到接近 1,总成功率瞬间变成 0.9 乘以 0.9 再乘以 1 的三次方,也就是 81%。如果约束做得好,把关键步骤的成功率提升到 99% 以上,总成功率就能稳定在 95% 左右。

“让模型少做决策”并不意味着削弱模型的作用,恰恰相反,是让模型把精力集中在它最擅长的事情上:理解语义、拆解意图、生成自然语言。而那些木讷、繁琐、但绝不能出错的逻辑工作,交给代码来做。这套思路在 LangChain 里落地,几乎每个组件都能对上号。

2. LangChain 里的 Harness 骨架:从工具注册到状态流转

LangChain 本身提供了一整套组件,大多数人只用了它最简单的链式调用和 Prompt 模板,其实它的真正威力在于把 Agent 的外部控制逻辑做得非常丰富。下面这几个组件,就是我理解中的 Harness 骨架的核心部位。

2.1 工具注册表:把模型的“可选择项”锁进笼子

在 LangChain 里,工具通过@tool装饰器或者BaseTool子类注册。很多项目把工具做得很随意,函数名随便起,参数没有严格校验,返回值五花八门。这样的工具表交给模型,模型光是理解每个工具是干嘛的就得消耗大量 Token,而且很容易选错。

我在实际项目里的做法是给工具注册表加严格的三层约束。第一层是命名约束:工具名必须是“动词 + 名词”的格式,比如get_order_status、calc_shipping_date、send_refund_request,绝对不允许出现do_stuff这种含糊名字。第二层是参数约束:每个参数都要声明类型、取值范围和默认值,模型填参数的时候必须按 schema 来。第三层是返回约束:工具返回的结构必须是固定的,要么是字段明确的 JSON,要么是带状态码的结果对象,不能让模型去“理解”一个格式混乱的返回结果。

这里要特别注意一个问题:模型选错工具的根因往往不是它笨,而是工具之间的边界模糊。比如你同时提供了一个get_order_info和一个get_order_status,模型很容易混淆二者的职责。我的建议是,每个 Agent 的工具数量控制在 8 个以内,每个工具的 description 第一句说“什么时候用”,第二句说“什么时候不要用”。如果发现两个工具的 description 里有重叠语义,就得考虑合并。

2.2 结构化生成:让模型的输出天然可解析

LangChain 里处理模型输出的方式有三种,按照可靠程度从低到高排列:纯文本 + 解析、JSON 模式、结构化输出。纯文本加正则解析是最原始的方案,也是我早期项目里天天修 bug 的根源;JSON 模式好一些,但遇到长输出还是可能出现轻微格式问题。

真正稳定的是结构化输出,LangChain 里通过with_structured_output()来启用。这个方法的本质是把模型的输出映射到你预定义的 Pydantic 模型上,模型生成 JSON 之后,框架会做严格的类型检查和字段验证。我在项目里强烈建议所有 Agent 的中间步骤都使用结构化输出,哪怕你下一步就要把它转成自然语言回复给用户。中间的每一步都保证结构正确,后面出了问题就能快速定位是哪个环节的锅,而不会出现“格式乱了不知道是模型的问题还是解析的问题”。

2.3 路由与控制:用代码把 Agent 的行动限制在轨道上

LangChain 的 Agent 支持工具调用,但默认情况下它会让模型在一次回复里同时决定“做什么”和“怎么做”。Harness Engineering 的思路是把这两个决策拆开:路由层(做什么)可以交给模型,执行层(怎么做)尽量交给代码。

举个我常说的例子:一个客服 Agent 接到的用户问题可能是查询订单、申请退款、投诉物流、咨询商品信息。如果让模型自己在一次推理里完成“分类 + 选工具 + 填参数 + 生成回复”全过程,出错概率就会累积。我的做法是先让模型只做路由决策,输出一个结构化的分类结果,比如{"category": "refund", "intent": "apply"},然后外部代码根据这个结果进入不同的处理分支。

LangChain 里实现这种方式有两种选择:一种是用RouterChain做简单的路由,另一种是直接用LangGraph的状态机做流程控制。我的经验是,简单的分支用 RouterChain 就够,复杂的多步骤流程务必迁移到 LangGraph。LangGraph 允许你显式定义每个状态、每条边、每个条件的跳转逻辑,相当于把 Agent 的行动路径画成了一张地图,模型只能在地图里移动,不能自己开辟新路。

2.4 记忆与上下文管理:别让模型背太多包袱

很多 Agent 表现变差,不是因为模型变笨了,而是上下文窗口被无关信息塞满了。Harness Engineering 里很重要的一块是控制模型“看到什么”。LangChain 提供了ConversationBufferWindowMemory、ConversationSummaryMemory等组件,但我在实际使用中更推荐手动管理上下文。

核心原则是:只让模型看到当前任务需要的最小信息量。比如用户查订单状态,模型的上下文里只需要有订单号、订单状态、物流信息,完全不需要带上用户三年前的购买记录。我在项目里习惯用trim_messages配合自定义的上下文过滤器,把历史消息压缩成摘要,把工具返回的大块数据截取关键字段,再组装成模型需要的最小集合。这一步做得好不好,直接决定 Agent 的响应速度和准确性。

2.5 外部校验循环:人类反馈与自动评测的闭环

Harness Engineering 还有一个容易被忽略的组件——评测闭环。很多人把 Agent 部署上线就完事了,但 Agent 的 Prompt、工具定义、路由逻辑都需要持续迭代。LangChain 生态里有 LangSmith 这样的平台,可以记录每次调用的输入输出、Token 消耗、延迟,还能接入人工标注和自动评测器。

我在项目里的做法是:给每个 Agent 准备一套固定的评测集,大概 20 到 50 条高质量样本,每条样本标注了正确答案和期望行为。每次修改 Harness 配置之后,首先跑一遍评测集对比结果变化,而不是直接上生产环境看效果。这套评测闭环的价值在后期特别明显:你可以精确地说出“这次改动让准确率提升了 3 个百分点”,而不是凭感觉说“好像变好了”。

3. 实操实录:用 LangChain 打造一个稳定的客户支持 Agent

理论部分说了这么多,下面用一个虚构场景来完整走一遍实操流程。假设我们要做一个支持退货退款的客户支持 Agent,要求是:能查订单、能计算退款金额、能判断退货资格、能生成安抚话术,同时要求整个过程可控、可观测、不容易跑偏。

3.1 定义数据模型与工具层

第一步不是写 Prompt,而是定义清楚整个系统的数据模型和工具层。我在项目里习惯先写 Pydantic 模型,因为工具的输入输出、状态的流转、评测集的构建都依赖这些结构。

from pydantic import BaseModel, Field from typing import Optional, Literal from enum import Enum class OrderStatus(str, Enum): PAID = "paid" SHIPPED = "shipped" DELIVERED = "delivered" COMPLETED = "completed" class RefundEligibility(str, Enum): ELIGIBLE = "eligible" NOT_ELIGIBLE = "not_eligible" NEEDS_REVIEW = "needs_review" class OrderInfo(BaseModel): order_id: str = Field(description="订单号") status: OrderStatus = Field(description="当前订单状态") amount: float = Field(description="订单金额") days_since_purchase: int = Field(description="距购买天数") class RefundDecision(BaseModel): eligibility: RefundEligibility = Field(description="退款资格") refund_amount: float = Field(description="可退金额") reason: str = Field(description="决策理由") class ToolResult(BaseModel): success: bool = Field(description="是否成功") data: Optional[dict] = Field(default=None, description="返回数据") error: Optional[str] = Field(default=None, description="错误信息")

然后定义工具函数。这里有一个我反复强调的细节:工具函数内部要自己捕获异常,返回统一的 ToolResult 结构,千万不要让异常抛到模型层。模型最怕的就是收到一段 Python 报错堆栈,它会不知所措,然后开始编造。

from langchain_core.tools import tool @tool def get_order_info(order_id: str) -> dict: """当用户咨询订单状态、购买时间、订单金额时使用。仅查询不修改。""" try: # 这里实际上是从订单系统拉数据 data = _fetch_order(order_id) return ToolResult(success=True, data=data).model_dump() except OrderNotFoundException: return ToolResult(success=False, error="order_not_found").model_dump()

3.2 设计状态机:从“模型自由发挥”到“流程显式控制”

用 LangGraph 把流程控制起来。整个 Agent 分为 5 个核心节点:入口分类节点、订单查询节点、资格判断节点、决策历史节点、话术生成节点。

from langgraph.graph import StateGraph, START, END from typing import TypedDict, Literal class AgentState(TypedDict): user_input: str order_id: str | None order_info: OrderInfo | None refund_decision: RefundDecision | None category: str | None response: str | None retry_count: int def classify_node(state: AgentState) -> AgentState: # 这里用结构化输出让模型只做分类,不生成其他内容 result = router_llm.invoke( [{"role": "user", "content": state["user_input"]}] ) state["category"] = result.category return state def query_order_node(state: AgentState) -> AgentState: # 分类之后,外部代码决定要不要查订单,模型自己不用选工具 order_id = extract_order_id(state["user_input"]) state["order_id"] = order_id tool_result = get_order_info.invoke({"order_id": order_id}) state["order_info"] = OrderInfo(**tool_result["data"]) return state def decide_refund_node(state: AgentState) -> AgentState: # 把订单信息组装到 prompt,让模型基于事实做判断 decision = judge_llm.invoke({ "order_info": state["order_info"].model_dump(), "policy": REFUND_POLICY_TEXT }) state["refund_decision"] = decision return state

状态机的关键在于每一条边都是显式定义的。比如query_order_node执行完后,如果order_info里的状态是delivered,就直接走decision_node;如果状态是paid,要先去waiting_period_node判断是不是超过 7 天。这些条件分支全部是代码逻辑,模型没有插手的余地。

这样的设计带来的最大好处是可测试性。你可以单独 mock 某个节点的输入输出,验证每个分支的行为,而不是把整个 Agent 当作一个黑盒来猜。项目上线之后排查问题也快得多,用户说“我的订单明明能退款,你们机器人说不可以”,你直接查decide_refund_node之前的输入,马上就能判断是订单数据不对,还是判断逻辑的问题。

3.3 让模型只负责它擅长的那一段

在整个状态机里,模型的角色被限制在三个环节:入口分类、资格判断、话术生成。这三个环节的共同点是:都需要理解自然语言和上下文。而查订单、算时间差、校验参数这些工作全部由代码完成。

入口分类我用了一个很轻量的模型调用,甚至可以用小模型完成。这个环节的目标是输出一个枚举值,不需要任何创造力,把模型调大反而是浪费。资格判断需要结合订单数据和退款政策,这里会把政策文档片段注入上下文,让模型做归纳推理。话术生成是这个 Agent 里最需要模型能力的环节,因为要安抚用户情绪、解释退款原因,措辞要自然得体。

有一件事要特别提醒:话术生成节点的输入,不要直接把订单 JSON 丢给模型。我们通常会组装成一个“人类可读的总结”,比如“用户订单号为 12345,购买金额 299 元,已签收 12 天,超出 7 天退货期限,不符合免费退货条件”。模型看到的是这样一段文字,而不是冰冷的字段名,生成的回复才会更自然。

3.4 评测集与回归测试:每次改动前先跑一遍

这个项目上线前,我会重点构建评测集。大概 30 条样本,覆盖退款通过、退款拒绝、需要人工审核、订单找不到、恶意高频请求等典型场景。每条样本不仅包括输入文本,还包括期望的状态流转路径和最终回复的关键词。

每次修改 Harness 的任何配置,比如改了退款政策、调整了某个工具的 description、换了路由模型,我都会先在评测集上跑一遍,对比哪些用例出现了行为变化。这个习惯帮我避免了好几次“改了 A 处长好了 B 处却坏了”的隐形回归问题。LangSmith 可以帮助自动记录评测结果,但我更推荐团队里有一个本地的回归脚本,用 pytest 组织用例,直接在 CI 里跑,这样任何改动引入的回归都逃不过版本控制。

4. 真实场景里的避坑实录:这些问题根本防不住

即使把 Harness 的骨架搭好了,在实际运行中还是会遇到一些意想不到的坑。下面这些是我在不同项目里真实踩过的,每个都花了不少时间排查。

4.1 工具描述写得越长,模型越容易选错

这是我在评测时发现的规律:工具 description 超过 100 个词时,模型的选择准确率明显下降。原因是模型在推理时对长文本的注意力分配是有限的,你的描述里有太多“有时”“一般来说”“建议”这样的软化词,模型反而抓不住硬规则。

解决方案是:description 用两句话,第一句是触发条件,第二句是强制规则。把“如果用户提到退款就调用该工具”写成 “Use this when the user explicitly mentions refund, return, or money back. Do NOT use for order status inquiries.”。缩短描述之后,我的测试集准确率提升了 4 个百分点。

4.2 让工具返回“干净数据”是省 Token 的大杀器

很多人的工具直接把后端原始接口返回的整个 JSON 丢给模型,里面可能有一堆内部字段、日志信息、无关的嵌套数组。模型被迫花大量 Token 去理解这些无用数据,还会被干扰。我的方案是:工具内部对原始数据做重写,只提取模型做决策所需的字段,格式尽量扁平。

比如查订单接口返回 200 个字段,工具函数里只挑出 status、amount、created_at、ship_date、return_deadline 五个字段,整理成简单的键值对。模型第一次调用就能直接使用,不用反复追问工具“这个字段是什么意思”。这一步优化之后,每个会话平均节省了约 15% 的 Token,而且响应速度明显变快。

4.3 把“拒绝用户”的流程做成专门的节点,而不是让模型临场发挥

客服场景里最难的往往不是“答应用户”的过程,而是“拒绝用户”的过程。早期版本里,我让模型根据退款政策自行判断能否退款,结果出现了大量不一致:同样的情况,有时候说可以退,有时候说不可以。原因是模型对数字边界条件的感知非常脆弱,14 天和 15 天在它眼里几乎没有区别。

现在的做法是:资格判断完全由代码计算,模型只负责根据计算结果生成话术。30 天退款期限的判断就是一行 Python 代码:days_since_purchase <= 30,不存在“模型觉得差不多能退”的可能性。模型拿到的退款决策只有三种值:eligible、not_eligible、needs_review,它只需基于这个值组织语言。

4.4 重试机制必须带上状态变化,否则就是死循环

Agent 在运行过程中经常会遇到工具调用失败的情况,比如数据库超时、外部接口返回 500。如果只是在原来的节点上重试两三次,大概率还是失败。我的建议是:重试之前先改变状态。比如从get_order_info失败之后,可以转入fallback_order_query节点,尝试从备用数据库查询;或者降级到ask_user_for_assistance节点,向用户索要更具体的订单信息。

这里的核心思路是重试不是“再试一次”,而是“换一种方式前进”。盲目重试只会消耗时间和 Token,而且用户等得越久越不耐烦。设置合理的最大重试次数也是必要的,超过次数直接转入人工客服流程,这也是 Harness 的一部分——把失败路径也设计成一条明确的轨道。

4.5 评测集的答案不要只盯“最终回复”,要盯“过程决策”

这一点是我踩了很深的一个坑之后才悟出来的。最早我的评测只看最终响应里有没有包含正确答案,后来发现两个 Agent 在最终回复上都输出了“可以退款”,但一个是正确地走完了全部流程,另一个是模型误打误撞猜对了。两者的差别在简单案例里看不出来,一旦遇到边界条件或者复杂案例,走错路的 Agent 就会暴露问题。

现在我的评测集每个样本都记录了期望的中间状态:分类结果应该是什么、订单查询节点有没有被调用、资格判断的结果是什么。跑完评测之后,先核对每一步的状态是否符合预期,再核对最终回复。这样才能保证 Harness 的约束确实在起作用,而不是模型在“绕过约束”硬答。

5. Harness Engineering 的扩展应用:从客服 Agent 到更复杂的业务系统

这套方法论不只是适用于客服场景。我陆续把它用在了好几个不同类型的项目里,虽然业务差异很大,但底层的逻辑几乎一样:把模型的自由度限制在语义理解部分,把确定性的逻辑交给代码。

5.1 数据分析型 Agent:让模型写代码,但别让它决定代码怎么跑

我做过一个数据分析 Agent,用户用自然语言提问“上个月的销售数据按地区分布怎么样”,Agent 需要调用一堆数据工具。最初版本让模型自己决定用哪个 SQL、怎么执行、怎么解读结果,结果惨不忍睹。后来改成 Harness 思路:路由模型只负责判断用户想要什么类型的分析,然后进入固定的模板流程。SQL 模板预编译好,只等模型填几个参数,比如时间范围、地区维度、聚合指标。执行之前还有一层参数校验器,防止模型把2025-06-01填成2025-6-1。

5.2 多步审批型 Agent:状态机比模型推理可靠得多

还有一个内部审批助手,用户请求“申请一笔市场活动经费”。这个流程涉及报销政策检查、部门负责人审批、财务预算校验等多个环节。如果用模型自由发挥,很容易跳步或者把必要的信息给漏了。用 LangGraph 搭出状态机之后,每一步都定义清楚了:用户提交请求 -> 提取关键字段 -> 校验必填项 -> 查询费控系统余额 -> 生成审批摘要 -> 发送给负责人。模型在整个流程里的角色只剩两个:把用户的口语化请求转成结构化字段,以及把审批摘要翻译成自然的通知文案。

5.3 Agent 的运营监控:Harness 是否正常运行也需要观测

Harness 本身也会出问题。工具升级导致返回数据格式变化、某个外部接口变慢导致超时、新调整的 Prompt 让模型在某个分支上的表现突变,这些都是可能的隐患。我在每次 Agent 上线后都会搭一套基础监控:每个节点的通过率、平均耗时、Token 消耗、失败时的错误类型分布。这套监控数据是修正 Harness 的依据,没有数据支撑的优化都是拍脑袋。

根据我个人经验,一个健康的 Agent 状态是:模型每个节点的通过率都在 95% 以上,整体流程没有隐藏的单点故障。如果某个节点的通过率明显低于其他节点,不要急着换模型,先看那个节点的输入输出格式是否合理、工具返回是否符合预期。很多表面上的“模型能力不足”,其实是 Harness 没给模型提供好“工作环境”。

5.4 Harness Engineering 的边界:不是所有场景都适合这套方法

当然,Harness Engineering 也有它的局限。如果项目本身需要极强的开放性和创造力,比如头脑风暴助手、小说生成器、开放式问答,那过度约束模型反而会让效果变差。这类场景里,模型的发散性本身就是核心价值,你要的不是稳定而是惊喜。

还有一个边界是开发成本。Harness 的搭建和维护需要额外的工作量,状态机设计、工具层改造、评测集建设,都是真金白银的时间投入。对于原型验证阶段的 Agent,先小规模尝试 Prompt 方案是合理的,直接上完整 Harness 可能得不偿失。判断标准是:这个 Agent 是要上线跑三个月的生产系统,还是只做一次技术演示。前者值得投入 Harness,后者不必。

最后再分享一个小技巧:我在设计任何 Harness 之前,都会先写一份“这个 Agent 绝对不允许做什么”清单。比如客服 Agent 不允许承认自己是 AI、不允许承诺退款金额、不允许编造物流信息。这份清单直接转化成了状态机里的拦截条件,而不是写进 Prompt 里让模型“尽量遵守”。有了代码层面的硬性拦截,我才敢把 Agent 放开给真实用户使用,而不是每天提心吊胆看日志。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 3:32:00

原生Java高仿短视频APP双端源码解析:音视频链路与工程落地

简介&#xff1a;原生Java高仿短视频APP双端源码是一份完整的移动端短视频项目&#xff0c;面向Java/Android开发者及音视频技术学习者&#xff0c;适合用来理解App从界面到媒体处理再到服务端交互的完整实现。资源包含Android端Java代码、iOS端Objective-C代码&#xff0c;以及…

作者头像 李华
网站建设 2026/10/22 3:31:59

基于Anomalib 2.1的C#工业异常检测工具:免Python环境一键训练

做工业视觉这几年&#xff0c;我踩过最深的坑不是算法选型&#xff0c;而是环境的部署。产线上的工控机通常只有一个要求&#xff1a;双击就能跑。可Python环境对一线调试工程师来说&#xff0c;经常是一场噩梦。Anomalib 2.1本身是个非常优秀的异常检测库&#xff0c;但它默认…

作者头像 李华
网站建设 2026/10/22 3:31:57

iOS全屏播放器架构拆解:AVPlayer自定义实现与旋转适配

1. 从零拆解一个全屏播放器的核心架构播放器这个东西&#xff0c;看起来简单&#xff0c;做起来坑多。我最早接触音视频开发的时候&#xff0c;以为调个系统API就能搞定&#xff0c;结果真正上手才发现&#xff0c;光是全屏切换这一件事就够折腾好几天。这次拿一个Swift重构版本…

作者头像 李华
网站建设 2026/10/22 3:31:34

随机图模型原理与NetworkX实现:复杂网络分析中的零模型对照方法

简介&#xff1a;面向美赛建模参赛者与复杂网络研究初学者&#xff0c;这份压缩包提供了一套Random Graph&#xff08;随机图&#xff09;算法的MATLAB实现。核心程序文件覆盖ER随机图、BA无标度网络、WS小世界模型等经典模型的生成与基础指标计算&#xff0c;可直接运行并用于…

作者头像 李华
网站建设 2026/10/22 3:30:45

基于Java的智慧养猪App:物联网架构与Modbus设备接入实践

简介&#xff1a;面向智慧农业场景的“智慧化养猪”App是一套基于Java的Android工程源码&#xff0c;适合移动开发初学者、农业信息化从业者、物联网开发者和高校学生参考&#xff0c;可用于毕业设计或课程实战。资源共179个文件&#xff0c;压缩包整体约20.14MB&#xff0c;目…

作者头像 李华
网站建设 2026/10/22 3:30:35

权重初始化如何决定模型收敛速度?从Xavier到He的实战对比

训练不收敛的时候&#xff0c;你最先怀疑什么&#xff1f;学习率太大、数据没归一化、模型结构写错了&#xff0c;还是优化器参数没调好&#xff1f;我刚开始做深度学习那会儿也是这么排查的&#xff0c;直到有一次把学习率降到极小、数据预处理反复检查了好几遍&#xff0c;损…

作者头像 李华