☰
基于Deepseek Harness的防幻觉Agent智能体:电源硬件设计实践
2026/10/7 22:35:45 网站建设 项目流程

做过硬件的人都知道,电源设计这行最怕的不是你不会算,而是你"以为算对了"。一个Buck电路的占空比算错5%,可能只是效率难看一点;但一个MOSFET的耐压裕量取错,批量回来后就是冒烟、打火、甚至返工整板。这类错误有一个共同特征:它们都来自"看似合理的推理"。而大模型恰好是最擅长产出"看似合理"内容的工具——所以当我开始用Deepseek做硬件设计辅助时,第一诉求不是让它多能干,而是让它"少犯错"。

这个项目就是用Deepseek Harness搭建的一套专门面向电源硬件设计的防幻觉Agent智能体架构。它不是简单地把Deepseek的API包一层Prompt,而是把"模型自由生成"改造成"流程约束求解",让模型只负责推理和决策,所有数值计算、器件选型、参数校验全部交给确定性工具链。目标很明确:把AI当成一个"话很多但手指很准"的助理,而不是一个"什么都敢说"的百科。

这篇文章我会完整分享这套架构的设计思路、防幻觉的落地手段、关键代码实现,以及我在实际调试中踩过的坑。如果你也在做LLM Agent类的工程化项目,尤其是垂直领域的(医疗、硬件、财务、法律),这套"约束优先、工具兜底、验证闭环"的思路应该能直接抄作业。

1. 这个项目到底解决了什么问题

1.1 电源硬件设计里的"高成本犯错"

先说场景。电源硬件设计从需求到量产,中间要经历规格解析、拓扑选型、器件计算、环路补偿、热设计、PCB布局、仿真验证等环节。每个环节都有大量经验性的数值判断,比如:

  • 输入12V、输出3.3V/5A的Buck变换器,开关频率选多少合适;
  • 电感纹波电流取输出电流的20%~40%,但饱和裕量要留多少;
  • 输出电容的ESR纹波与陶瓷电容的降额系数怎么联合约束;
  • 环路补偿的穿越频率一般取开关频率的1/10~1/5,相位裕量要大于45°;
  • 功率MOSFET的耐压要按输入电压的1.5~2倍降额。

这些规则不是不能写在文档里,但新手很容易"记混"——比如把Buck的占空比公式记成Vout/Vin,反激的反射电压算错,或者直接把某个参考设计里的电感值抄过来但没核对频率。这些都是典型的"看起来对,实际上错"。

大模型的加入放大了这个问题。你问Deepseek"12V转3.3V/5A用什么拓扑",它会给出正确答案;但你问它"帮我算一下这个设计里输出电容的容值",它可能会基于一个你根本没给出的纹波要求,自行假设一个纹波率然后给你算出一个"漂亮"的结果。这个结果在数学上自洽,在工程上完全没有依据——这就是幻觉。

1.2 为什么通用Chat类Agent在硬件设计中不可用

我最早尝试的方案很简单:把Deepseek的API接进来,写好系统Prompt,让它扮演"资深电源工程师",然后直接对话设计需求。测下来的结果很有意思:

  • 拓扑推荐、概念解释这类定性问题,回答质量很高;
  • 涉及具体数值计算时,准确率大概只有60%左右;
  • 更危险的是,它会在计算中自己"脑补"缺失参数,比如你只说了输入12V输出3.3V,它默认你用了300kHz开关频率、默认电感纹波20%、默认用某款料号——然后给你一串貌似严谨的结果;
  • 追问它"这个电感饱和电流怎么算的",它还能一本正经地编一个推导过程。

我意识到问题不在模型本身,而在架构。你让一个对话模型直接面对"需要精确数值输出"的任务,它一定会用下一个词预测的方式"猜"一个数值,哪怕它背后并没有真正计算。这不是Deepseek的缺陷,是所有生成式模型的工作原理决定的。

所以方向变了:不要试图让模型"算得更准",而是让它根本不直接计算。所有必须精确的环节,全部拆出来交给确定性工具。

2. 为什么用Harness而不是直接堆Agent

2.1 Harness和Agent的区别

先澄清一个概念。很多朋友问我:Deepseek Harness是什么?和Agent有什么区别?这里我先说结论:Harness不是Agent,它是Agent外面的那层"安全带"和"操作台"。

Agent是一个智能体,它具备"感知-决策-行动"的循环能力,可以自主调用工具、分解任务、决定下一步做什么。而Harness是承载这个循环的工程框架,它规定了Agent每一步能做什么、不能做什么、怎么做、做完之后结果如何被验证。

你可以这样理解:Agent是司机,Harness是装了车道偏离预警、限速器、强制制动系统的驾驶舱。司机技术再好,该有的约束还是得有——尤其是当他拉着一车高价值货物的时候。

在我这个项目里,Harness承担了四件事:

  1. 任务编排:把"做一个电源设计"拆成"解析规格→选拓扑→算参数→选器件→跑校验→生成报告"的固定流程,Agent不能跳步;
  2. 工具注册与路由:只暴露经过封装的计算函数和数据库接口,Agent无法"绕过去自行计算";
  3. 输出约束:强制Agent以结构化JSON输出中间结果与最终结果,所有自由文本必须附在JSON的"解释"字段里,不允许夹带数值结论;
  4. 验证拦截:Agent每产出一个关键数值,Harness都会调用独立的校验工具做交叉检查,不过关直接打回重新生成。

2.2 防幻觉的核心:把"自由发挥"变成"约束求解"

折腾了这么久,我总结出一句话:防幻觉的本质不是提高模型的准确性,而是缩小模型的自由空间。

模型最喜欢的是"开放问题",最怕的是"强约束问题"。所以在Harness里,我做了三件事来压缩自由空间:

  • 用枚举替代填空:拓扑类型、器件类型、降额标准、纹波系数范围,全部定义成枚举值或者区间值。模型只能从给定集合里选,不能自己"发明"参数。
  • 用工具替代口算:任何数值输出的背后都是Python函数在算,模型只负责提供输入参数和选择公式。比如电感计算模型只需要给出"拓扑=Buck、Vin=12、Vout=3.3、Iout=5、纹波系数=0.3、频率=300k",剩下的是工具函数的事。
  • 用交叉验证替代信任:算完之后,Harness会从另一个角度复算。比如电感算完了,反过来计算该电感下的纹波电流是否在设定范围内;如果偏离超过阈值,就判定为"计算链断裂",要求Agent修复。

这样一套组合拳下来,幻觉空间被压到最小。模型仍然可能"觉得"某个参数合理但在工程上不适用,但那是下游"规则校验器"要拦截的事,不在推理环节里放任。

3. 整体架构设计

3.1 分层架构总览

整套系统我分了五层,每一层职责单一,方便单独测试和替换:

层级模块职责
交互层需求解析器把用户输入的非结构化需求转换成结构化设计约束
Harness编排层流程引擎、状态管理控制Agent执行流程,记录上下文与中间产物
领域工具层计算引擎、器件库、降额规则库、仿真接口提供确定性的计算与数据查询能力
防幻觉校验层Schema校验器、数值边界检查器、一致性复算器对Agent每一个关键输出做强制检查
模型层Deepseek推理模型、判别模型负责语言理解、方案决策、文本生成

这五层里,真正"智能"的部分只有模型层,其余全部是确定性代码。这是我刻意为之的结果:智能部分越少越好,确定性部分越多越好。

交互层做的事情很杂但很重要。用户可能说"我要做一个12V输入的模块电源,输出3.3V给FPGA供电,电流大概5A,板子空间有限"。需求解析器要把它拆成结构化字段:InputVoltage=12V,OutputVoltage=3.3V,OutputCurrent=5A,BoardArea=受限,LoadType=FPGA核心供电。其中"FPGA核心供电"会进一步映射为"需要低纹波、快速瞬态响应",于是后续的拓扑推荐会偏向Buck而非LDO。

3.2 关键设计:工具调用优先于模型计算

在这个架构里,我把"工具调用"设为Agent唯一合法的数值产出通道。具体规则如下:

  • Agent生成的内容分为两类:决策性文本和数值声明;
  • 所有数值声明必须附带tool_call_id,表明该数值来自某次工具调用;
  • 没有工具调用ID的数值,一律在Schema校验阶段被标记为"未验证来源"并拒绝;
  • Agent可以建议参数(比如建议开关频率300kHz),但最终算出来的电感值、电容值必须由工具函数返回。

为了实现这个机制,我在工具函数的返回里加了来源元数据:

{ "status": "success", "data": { "inductance_uh": 3.3, "ripple_current_a": 1.2 }, "source": { "tool": "buck_inductor_calc", "inputs": { "vin": 12, "vout": 3.3, "iout": 5, "ripple_ratio": 0.3, "frequency_khz": 300 }, "formula": "L = (Vin - Vout) * D / (delta_I * fsw)" } }

这样每一步都有完整的溯源性。后续无论是人类审查还是机器校验,都能逐级回溯:这个3.3uH是怎么来的、用了什么公式、输入参数是什么。这正是硬件设计行业最看重的"可追溯性"。

3.3 数据来源与溯源

电源设计离不开器件选型,而器件选型又是模型幻觉的重灾区——大模型会一本正经地推荐一个型号,然后这个型号要么停产了、要么封装不对、要么耐压根本不够。我给这个问题的解法是:模型只负责"表达意图",不负责"记忆料号"。

Harness里内置了一个器件数据库检索工具。模型收到"需要一颗耐压30V左右的同步Buck上管MOSFET"这类需求时,它只能调用search_components工具去数据库里查,查到什么就用什么,查不到就如实说"数据库中没有满足条件的物料"。更狠的一点是:即使用户在Prompt里主动给出了料号,比如"用TI的TPS54360做个方案",模型也必须先去数据库核验这颗料的真实参数,核验失败就拒绝采纳,不能"顺着用户说"。

这在防幻觉里是一个非常重要的设计原则:永远不要让用户输入直接变成Agent的输出。用户的话要经过"解析-核验-采纳"三道关,才能进入设计方案。

4. 核心环节实现

4.1 Harness编排流程

实际跑起来的时候,Harness的主流程是这个样子的:

def run_design_flow(user_request: dict): # 第一步:结构化解析 constraints = parse_requirements(user_request) # 第二步:拓扑选择(模型决策 + 规则校验) topology = agent_choose_topology(constraints) if not check_topology_rules(topology, constraints): raise DesignFlowError("拓扑选择不满足约束") # 第三步:参数计算(工具链) design_params = calc_design_params(topology, constraints) # 第四步:器件选型(数据库检索) components = select_components(design_params, constraints) # 第五步:防幻觉校验(交叉复算) validation_result = validate_design(topology, design_params, components) # 第六步:生成设计报告 report = generate_report(topology, design_params, components, validation_result) return report

流程是强制线性的,Agent不能跳过校验直接生成报告。我在早期版本吃过这个亏:Agent发现校验环节算出来结果和自己想的不一样,就"很聪明"地在报告里写了另一个值,还附了一段看起来合理的解释。后来我在流程引擎里加了硬约束——报告中的所有关键数值必须取自design_params对象,任何与对象不一致的数值都会被标注并拒绝发布。

4.2 防幻觉校验链路的落地细节

防幻觉不是靠一个"校验函数"搞定,而是靠一条链路。我的实现里包含四个校验步骤:

第一层:Schema校验。Agent输出的JSON必须满足预定义的schema,字段类型、枚举值、必填项都必须符合。例如拓扑字段只能是Buck|Boost|Buck-Boost|Flyback|Forward|LLC|LDO,多一个别的词直接失败。

第二层:数值边界检查。每个关键参数都有工程边界。比如输出电容的ESR不得超过XX毫欧、电感饱和电流至少是最大峰值电流的1.2倍、MOSFET耐压至少要达到输入电压的1.5倍。这些边界来自行业规范和项目经验,是最硬的一层约束。

第三层:一致性复算。独立于Agent的计算引擎,按照设计公式重新算一遍。重点检查"Agent交付的参数"与"初始约束条件"是否矛盾。举个例子:Agent交付的电感值是3.3uH,复算函数会代入纹波电流公式,算出来的纹波百分比如果超过预设的30%,就报警。

第四层:多候选交叉验证。同一个设计问题,让Deepseek用不同的温度参数(temperature=0.2和temperature=0.8)各生成一版方案,然后比较两份方案的关键参数是否一致。如果差异过大,说明模型在该环节处于"不稳定推理"状态,方案需要人工介入。这个方法不是100%准确,但能有效筛掉一部分随机性很大的幻觉输出。

4.3 一个完整的BUCK电源设计实例

拿一个最常见的设计来演示:12V输入,3.3V输出,5A负载,开关频率300kHz,纹波率取30%。

Agent接到任务后,Harness按流程走:

步骤一:规格解析。需求解析器输出结构化约束:拓扑候选=[Buck],Vin=12V,Vout=3.3V,Iout=5A,fsw=300kHz,ripple_ratio=0.3。

步骤二:拓扑选择。模型判断:输入12V输出3.3V,降压比约3.6倍,电流5A,属于典型的非隔离Buck场景。规则校验通过。

步骤三:计算。这里模型不做算术,而是调用工具函数:

# 占空比 D = Vout / (Vin * efficiency_guess) D = 3.3 / (12 * 0.9) # 约0.306 # 电感纹波电流 delta_I = Iout * ripple_ratio = 5 * 0.3 = 1.5A # 电感量 L = (Vin - Vout) * D / (delta_I * fsw) # = (12 - 3.3) * 0.306 / (1.5 * 300000) # = 8.7 * 0.306 / 450000 # = 5.9e-6 H ≈ 5.9uH

工具函数实际返回5.9uH,并推荐取标称值6.8uH(考虑磁芯损耗和直流电阻后取更接近的标准值)。

步骤四:器件选型。模型发起数据库查询:"输入12V、输出3.3V/5A的Buck设计,需要电感饱和电流至少大于峰值电流5 + 1.5/2 = 5.75A,取1.2倍裕量即6.9A;耐压需大于12*1.5=18V的MOSFET"。数据库返回候选器件列表,模型筛选后选定型号,所有料号都带数据表来源链接。

步骤五:校验。一致性复算器把6.8uH带回去算纹波电流:

delta_I = (12 - 3.3) * 0.306 / (6.8e-6 * 300000) = 8.7 * 0.306 / 2.04 = 1.31A ripple_ratio = 1.31 / 5 = 26.2%

26.2%落在15%~40%的合理范围内,通过。

步骤六:报告生成。模型把上述过程整理成设计报告,包含参数计算过程、器件选型理由和校验结论。全程没有任何一步依赖模型"心算",所有的数字要么来自工具函数,要么来自数据库。

5. 常见问题与排查实录

5.1 幻觉问题排查速查表

实际调试过程中我遇到了不少问题,整理成一张速查表,供大家参考:

现象根因解决方案
Agent推荐了数据库里不存在的料号模型在用训练记忆"编造"型号禁止模型直接输出料号,必须走search_components工具;工具返回后模型只能从结果中选择
计算参数在两次运行间不稳定采样随机性导致的非确定性降低temperature到0.2以下;用带tool_call的确定性工具输出覆盖模型数值
交叉复算与Agent交付值不一致Agent在文本中夹带了"自己算的"数值加强Schema约束,只允许读取工具返回字段,文本中禁止携带数值
校验器把合理设计误判为异常边界规则过于严格或公式不一致将复算公式与工具函数统一为同一代码模块,避免两套公式因精度而打架
Agent跳步直接生成报告流程编排不够硬在流程引擎中设置状态机,前置状态未完成禁止进入报告生成步骤

其中"两套公式打架"这个问题必须单独强调。早期我在工具函数和校验模块里分别写了一遍公式,结果工具用的是浮点精确计算,校验器用了四舍五入的简化版,导致明明参数没问题却报"复算不一致"。后来把所有公式统一下沉到一个power_math模块,工具和校验都调用同一个函数,这个问题彻底消失。

5.2 工程化避坑经验

再分享几个从实操中总结的细节,这些坑文档里一般不写:

第一,Prompt里的"数值禁忌"要写得极其具体。我试过在系统提示词里写"请确保所有数值来自工具调用",效果几乎为零。真正有效的是在输出Schema里把数值字段全部标记为readonly,并让流程引擎在合并模型输出时直接丢弃模型自带的数值字段,换成工具函数的返回值。

第二,防幻觉要防的是"局部幻觉"而不是"全局幻觉"。模型大部分时候是靠谱的,最危险的是它在某个环节"自以为是"一下。比如拓扑选对了、频率给对了,但电容的ESR限制条件记错了,导致选了个ESR偏高的大电容。针对这类局部幻觉,我采用"环节级校验"而不是"流程级校验"——每个环节结束都要做一次局部检查,不等到最后统一验证。

第三,Deepseek的API并发和稳定性需要兜底。Agent流程长、环节多,一次完整设计可能要调用5~8次模型接口。任何一个环节超时或返回异常,会导致整个流程重跑,成本很高。我在Harness里加了缓存层,相同输入的工具结果和模型结果会缓存复用;同时给每个环节加了超时重试和降级策略——模型超时时,如果该环节是纯文本总结,可以降级用模板填充;如果是决策环节,则直接报错让用户介入,不硬扛。

第四,也是最有体感的一条:一定要给Agent设计"不知道就直说"的通道。这个词用Prompt很难训出来,但用架构可以。当数据库检索不到物料、当计算结果显示约束无解、当用户需求自相矛盾(比如既要求极低纹波又要求极低成本),Agent必须能输出"无法满足,原因如下"而不是硬编一个方案。这个能力我在Harness里是通过一个constraint_conflict_detector实现的:它预先检查约束组合是否可行,比如纹波要求低于1%但板面积限定极小,就直接在Design Flow入口拦住,不让Agent进入后续流程。

第五,关于Harness的状态管理。一次完整电源设计会有大量的中间状态:用户输入、解析结果、拓扑选择、计算参数、器件候选、校验结果。如果全塞在模型上下文里,很快会超过上下文窗口,而且会让模型"遗忘"早期约束。我的做法是:上下文里只保留"当前环节的输入摘要"和"关键约束列表",其余全部存到独立的临时存储里,模型层只拿摘要做决策。这个做法既省钱又防走偏——模型看到的上下文越精简,越不容易自己加戏。

6. 写在最后的实操心得

搭这套架构,我把市面上各种Agent框架试了一圈,最后还是回归到一个很朴素的判断标准:你这个场景里,模型错了会怎样?如果答案是"会返工",那就值得多做一层防幻觉;如果答案是"无所谓",那用裸的Agent就行。

电源硬件设计正好是最经不起"看似合理"错误的领域之一。我做这个项目的最大体会是:大模型的角色应该定位在"方案空间探索者"和"文档生成器",而不是"数值计算器"和"参数记忆库"。前者是大模型的强项,后者天然会触发幻觉。

如果你也想在垂直领域搭类似的Agent,我有几个建议可以直接拿走:

  • 把所有模型算不准的事,全部变成工具函数调用;
  • 给每个关键输出加上"来源追溯",没有来源的数值一律不采信;
  • 校验公式与计算工具必须同源,不允许存在两套口径;
  • 流程状态机化,禁止跳步;
  • 为Agent保留一条"我做不到"的合法出口。

这套架构本身不复杂,核心思路就是一句话:给模型套上一套"约束安全带",把自由发挥的空间压到最低,剩下的交给工具和规则去兜底。目前这套系统已经支撑了我这边多个12V转低压大电流的模块电源设计项目,从方案选型到参数计算再到报告生成全流程可控。后续我打算把分立的仿真验证环节也接进来,让"仿真-修正-再仿真"形成闭环,到时候再和大家分享。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询