LLM应用效果不佳?先别急着换模型,或许该优化你的Harness
先问大家一个问题你有多久没被“换模型”这三个字勾住魂了我见过太多团队和个人开发者从7B换到14B再换成70B甚至更大钱和精力烧了一大堆最后业务指标纹丝不动回复质量该飘还是飘工具调用该崩还是崩。后来我把注意力从模型参数上挪开挪到模型外面那层“壳”上——也就是Harness——结果一周之内就看到了肉眼可见的变化。所谓Harness在LLM应用里指的是包裹在模型外部的一整套编排与控制层它负责把用户问题包装成模型能理解的上下文、把模型的输出解析成可执行的工具调用、把中间状态保存下来、把失败情况处理掉。你可以把模型想象成一台性能出色的发动机Harness就是变速箱和传动系统发动机马力再大如果变速箱换挡逻辑混乱车一样跑不快。这篇内容适合正在做大模型应用、研究Agent、或者整天折腾本地模型的朋友我会从概念讲到实战再把我踩过的坑全部摊开。1. 先搞清楚Harness到底是什么凭什么它这么重要1.1 被大多数人忽略的“模型外部系统”很多人对AI应用的认知还停留在“把问题丢给模型然后把答案返给用户”这一层。这句话没错但只讲对了一半。模型面对的其实是一堆原始输入用户零散的需求、格式混乱的文档、不知道从哪里冒出来的多余信息。如果你把这些东西原封不动全塞进上下文再强的模型也会被带偏。模型的能力天花板通常体现在基准测试里但真实业务里发挥出来的只是“有效能力”。连接这两者的就是模型外部的那套系统Retrieval怎么抽内容、Prompt怎么组装、工具结果怎么回填、错误怎么重试。这些都不属于模型本身但它们决定了模型百分之多少的实力能真正落地。我们一般把这个系统统称为Harness。在工业界Harness工程已经成为和模型微调并行的重点方向。因为大家逐渐意识到一个扎心的事实模型能力的同质化越来越明显真正拉开差距的是你怎么用模型。1.2 Harness和Agent到底有什么区别很多人搜索“harness和agent区别”说明这个概念确实容易混。Agent指的是模型内部的一种推理范式——模型具备规划能力能够拆解任务、决定调用哪个工具、根据中间结果调整下一步行动。它是一种“智能策略”活在模型的推理过程中。而Harness是承载Agent运行的整套外部基础设施。它负责上下文打包、记忆读写、工具协议、执行循环、日志追踪、失败重试、权限控制。Agent是棋手的大脑Harness是棋盘、计时器、复盘系统和裁判规则。棋手再聪明没有棋盘他也下不了棋规则不清晰他也赢不了比赛。所以正确的理解是Agent解决的是“怎么想”的问题Harness解决的是“怎么让它好好干活”的问题。我们平时聊的LangChain、LangGraph这些框架本质上都是在帮你搭Harness层的骨架。1.3 Harness通常包含哪几个核心模块一个真正能上生产的Harness至少需要覆盖这么几块内容上下文编排决定哪些内容进入Prompt以什么顺序进入哪些内容必须丢弃。这是最影响质量的一环。工具接入层定义统一的工具调用协议负责把模型的文本输出解析成结构化指令再调用对应函数。执行循环驱动“思考-调用-观察-再思考”的循环并且设置终止条件防止Agent陷入死循环。记忆与状态管理保存中间变量、多轮对话历史、任务进度让系统具备“连续性”。观测与调试记录每一步的输入输出、耗时、Token消耗方便定位问题出在模型还是出在流程。一个设计良好的Harness能把80%的杂活消化在系统侧让模型只专注于最核心的理解与生成。这也是文章标题那句话的真实含义换一套Harness常常比换两代模型更管用。2. 为什么换Harness的效果常常比换模型还明显2.1 模型能力的“上限”和“有效能力”不是一回事有一个不严谨但很直观的公式业务效果约等于模型能力乘以Harness质量。模型能力从7B升到14B可能只是从80分涨到85分但Harness质量如果从0.3提升到0.8哪怕模型还是原来那个最终效果却可能是翻倍的。更常见的情况是很多项目的模型已经足够强了问题全出在模型外面。用户问一句“这个月的订单异常情况有哪些”系统把两万行的订单明细全部塞进Prompt模型要在一堆无关数据里找重点它不晕才怪。这时候换一个更大的模型无非是从“晕得厉害”变成“晕得轻一点”但问题根源还在。我见过最多的情况就是团队陷入“模型焦虑”效果一不好就归因于模型能力不够然后投入资源换模型、微调模型却从来不去看提交给模型的内容。模型就像一个大厨你的Harness是备菜流程。你把一堆带泥的菜直接丢给他他技术再好也做不出清爽的菜。2.2 同一模型、两套Harness的实测对比去年我用同一个模型跑过一组对照实验业务场景是从一批订单数据中生成每日简报。旧方案是典型的“无脑全塞”把全部数据以文本形式堆进Prompt让模型自己总结。新方案则是先做结构化处理用SQL聚合出关键指标再把汇总结果转成精简表格最后只让模型读表格并生成报告。对比数据大致如下对比项旧Harness全量文本直塞新Harness检索聚合精简输入单次调用Token消耗约8500约1200生成报告准确率78%左右94%左右平均响应耗时8秒以上2秒左右维护难度高提示词和业务逻辑全揉在一起低节点独立可替换模型从头到尾都是同一个没换过。差别只在于进入模型的内容形态。新Harness做了两件事一是把“查找数据”的工作交给SQL和工具完成二是让模型只读它真正需要看到的结果。模型负担轻了能力自然就发挥出来了。2.3 换Harness的本质是降低模型的“无效复杂度”模型不是万能的尤其在处理长文本和多步骤任务时上下文里的噪音会显著拉低表现。新版模型在长文本理解上有进步但“把一万行数据全部塞进去找异常”这种任务本质上是在做数据库该做的事情模型根本不擅长。Harness的价值就是把这些脏活、累活、需要精确计算的活转移到系统侧去处理。RAG负责检索相关内容、结构化查询负责精确计算、模板负责整理输出格式模型只负责综合判断和自然语言生成。这样做之后模型的注意力被聚焦在了一条最短路径上效果提升几乎是必然的。3. Harness设计实战从框架选型到落地案例3.1 框架选型直接用LangChain/LangGraph还是从零写很多人一上来就问该用哪个框架我的建议是不要迷信框架先想清楚你要解决什么问题。LangChain适合快速验证“给模型接一堆工具”的场景周边生态全文档多缺点是抽象层次太重出了问题你很难看清底层发生了什么。LangGraph则更适合状态明确、步骤较多的Agent任务它以图结构定义节点和边状态流转清晰可控调试体验比LangChain好不少。我的习惯是流程编排用LangGraph工具层自己定义schema不依赖框架封装的重型组件。这里给一个LangGraph风格的最小流程示意重点看它的结构化方式from langgraph.graph import StateGraph, END class AgentState(TypedDict): question: str context: str plan: list result: str step_count: int def parse_intent(state: AgentState): # 先判断是问答任务还是工具调用任务 return state def retrieve(state: AgentState): # 从知识库或数据库提取与问题相关的内容 return state def call_model(state: AgentState): # 将已有上下文打包给模型生成回答或工具调用 return state def check_output(state: AgentState): # 校验输出格式不合格则进入修复节点 return state graph StateGraph(AgentState) graph.add_node(parse_intent, parse_intent) graph.add_node(retrieve, retrieve) graph.add_node(call_model, call_model) graph.add_node(check_output, check_output) graph.set_entry_point(parse_intent) graph.add_edge(parse_intent, retrieve) graph.add_edge(retrieve, call_model) graph.add_edge(call_model, check_output) # 根据校验结果决定走修复路径还是直接结束 graph.add_conditional_edges(check_output, route_after_check)这个结构的好处是每个节点都是纯函数输入输出明确出了问题你只需要看日志里是哪一步断了。我强烈建议团队在初期就固定这种节点化的思路不要把所有逻辑写在一个巨大的while循环里。3.2 从零手写一个最小Harness核心循环不超过100行如果你不想用任何框架也可以自己手写一个最小版的Harness。别被这个词吓到核心其实就是一个带终止条件的循环import json def run_harness(question, max_steps5): current_input question history [] for step in range(max_steps): response llm.generate( systemSYSTEM_PROMPT, usercurrent_input, historyhistory ) action parse_action(response) # 解析模型输出中的工具调用 if action is None: # 模型已经给出最终答案 return response tool_result execute_tool(action) # 调用对应工具 history.append({input: current_input, action: action, result: tool_result}) current_input 上一步的工具返回结果如下请根据它继续\n str(tool_result) return 已达最大步数返回最近一次结果这段代码当然不能直接上生产但它揭示了Harness最核心的骨架模型输出被解析成结构化动作、动作被执行、结果被观察并回填到下一轮输入。所有复杂的Agent系统本质上都是在这个骨架之上加记忆、加路由、加校验、加并发。理解了这一层你再看任何框架源码都会觉得清晰很多。有一个细节特别重要解析模型输出和解析工具报错必须分成两个函数不要混在一起。模型输出不合法说明是生成格式问题工具执行报错说明是外部依赖问题。混在一起排查的时候会非常痛苦。3.3 用DeepSeek本地模型搭Harness的实际改造搜索热词里“deepseek harness”出现频率很高。很多人搜这个词其实是想要一套“给DeepSeek本地模型配好可用Agent外框”的方案。我理解社区想要的并不神秘就是一套把模型包起来、能让它稳定干活的控制层。我自己做过的案例是一个本地知识库助手最开始的方案特别简单用户提问模型直接回答。问题来了知识库内容一多模型就开始胡说八道用户的问题稍微复杂一点它就漏步骤。换了几个模型都一样。后来我调整了思路给系统加了几层Harness第一层做意图识别判断用户是想查资料、想总结、还是想执行某个操作第二层做检索召回只抽取相关的几段内容而不是把整个知识库送进去第三层做答案合成让模型基于检索结果回答并且要求引用来源第四层做校验检查答案是否包含了检索内容中的关键信息。结果模型没换系统的整体可用度立刻不一样了。原因很简单原来模型是“光着膀子硬答”现在是“被一套流程保护着干自己最擅长的事”。这也回答了那些搜“deepseek harness怎么用”的朋友所谓harness就是给模型配上一整套伺候它的流程和工具它自然就愿意好好工作了。3.4 低显存环境下Harness的价值更大搜索热词里还有“低显存运行模型”这正好是我经常被问到的问题。低显存环境下能跑的模型通常参数不大而小模型在指令跟随、格式遵循、长上下文理解上的能力天然弱一些。这时候Harness承担的责任就更重它必须替模型把障碍扫清。我在低显存环境下跑7B到14B级别模型时会刻意做三件事。第一把复杂的任务拆解成多步每步只让模型做一件简单的事避免一步到位。第二在Prompt里固定输出格式并且写一个格式校验模块发现模型输出不是合法JSON就自动让它修复一轮。第三尽量用工具替代模型的能力短板比如精确计算交给代码数据检索交给向量库模型只做最终判断。这套组合拳打下来8B模型在很多任务上是可以接近大模型效果的。很多人低估了“小模型加好Harness”总想着硬上大模型结果显存爆了、速度慢得要死实际效果还未必比一套精心设计的小模型方案好。4. 一次完整的Harness替换实操订单日报助手4.1 旧方案的典型痛点为了让你对“换Harness”有更具体的感知我把前面提到的那次对比实验拆开讲。原来的订单日报助手是这么跑的每天早上把上个交易日的全部订单数据导出来生成一段很长的文本直接扔给模型让它总结出今日要点、异常订单和趋势变化。这个方案有三个致命问题。第一订单数据量一大Prompt长度爆表Token成本高不说模型的注意力也被稀释了。第二模型做不了精确计算比如“退款率比均值高多少”这种问题它只能估计经常算错。第三输出格式不稳定有时候是表格有时候是长文下游对接非常痛苦。我一开始的做法是换更大的模型确实好了一点但成本上去了速度下来了而且计算错误依然存在。后来我才明白问题出在这个系统的“分工”上所有活儿都是模型一个人在干数据计算、重点筛选、格式生成全部压给模型再大的模型也扛不住。4.2 新Harness的设计思路与节点拆分新方案从根本上改变了分工。我把整个流程拆成四个节点数据聚合、异常检测、摘要生成、格式渲染。数据聚合节点直接执行预先写好的SQL脚本从数据库算出总订单数、总销售额、各渠道占比、退款单数等关键指标。异常检测节点用规则和阈值去扫订单数据比如“退款率超过5%的渠道”“支付失败次数环比上升超过20%的商品”这些判断用标准代码写结果精确可控。摘要生成节点把前两步的结果整理成一小段结构化文本交给模型让它生成自然语言日报。最后格式渲染节点把模型输出格式化成Markdown表格或飞书消息卡片。这个设计的核心逻辑是凡是代码能精确解决的绝不让模型做模型只负责做它擅长的自然语言组织。这个思维是Harness工程里最重要的原则。4.3 替换过程中的关键配置与调优替换过程有几个参数和细节值得拿出来讲。第一是最大步数我把模型相关的多轮生成控制在3轮以内防止它在生成日报时反复“自我修改”浪费Token还容易越改越差。第二是温度摘要生成节点的温度设为0.3左右保证稳定不追求创造性。第三是工具超时SQL查询和外部接口调用都设置了10秒超时避免一个慢查询卡住整个流程。还有一个小细节就是每个节点之间的数据格式要事先约定好。比如SQL节点输出的是字典列表摘要节点接收的必须是字符串。很多人栽就栽在“格式不统一”上模型读到了乱七八糟的中间结果再强的Harness也救不回来。调优阶段最花时间的其实是Prompt模板。因为每个节点都是独立的小任务Prompt写得好不好直接决定输出质量。我的习惯是Prompt里明确交代“你是一个数据汇报助手以下是经过计算后的指标请据此生成日报不要修改数字”。这句话能堵住大部分模型“自由发挥”的毛病。4.4 最终效果与收益复盘替换完成后我统计了一下各项指标单次日报生成从8500多Token降到了1200多Token成本直接降了一大截生成耗时从8秒压到了2秒左右指标计算的正确率从“看运气”变成了100%因为计算全在SQL里完成了日报格式稳定下游机器人直接解析发送不需要人工再改。夸张一点说这是一次“零成本换模型”的升级。没花一分钱换模型只是把活儿重新分了一下效果却比换两代模型都明显。这件事给我的触动很大也成了我后来做任何AI应用的默认思路先检查Harness再考虑模型。5. 常见问题排查与踩坑记录5.1 换了Harness之后效果反而变差了问题出在哪这种情况很常见尤其当你从简单方案切到复杂流程时。我遇到过的原因主要有三种一是工具链过重系统引入了好几个外部依赖任何一个响应慢了都会拖累全流程模型没变聪明速度倒是慢了一倍。二是上下文被“水词”撑爆了中间环节产生的日志、原始返回结果被原封不动塞进模型噪音比之前还多。三是Agent循环失控模型被赋予过高的自由度不停调用工具却不在关键节点做判断像没头苍蝇乱转。排查思路也很机械把每步的日志拉出来逐个节点看输入输出标出Token消耗和响应延迟找到瓶颈到底在哪一步。只要日志完整这种问题一般半天内就能定位。我最常说的那句话就是既然你给Harness加了那么多流程那你就得配得上它的复杂度日志和可观测性必须跟上否则就是给自己埋雷。5.2 模型输出格式总是不对要不要反复重试输出格式问题在小模型身上特别突出。我试过在Prompt里加各种强调还是偶尔会收到一串带了废话的JSON或者干脆连JSON.stringify都不合法。后来我采用了一个“校验加修复”的机制先让模型输出一个JSON块然后代码解析解析失败就把错误信息回传给模型让它根据报错自查。这个机制生效的前提是模型要有足够的上下文看到自己刚才的输出。所以修复Prompt要包含三部分原始要求、模型这次生成的脏输出、解析器报出的具体错误。绝大多数情况下只要模型能看到报错信息它自己就能改正格式问题。用这个办法小模型的格式可靠率也能刷到95%以上。另外有一个小技巧让模型输出JSON时在Prompt里给一个明确的键结构。比如要求“只输出一个包含summary和risks两个字段的JSON对象”比笼统说“输出JSON”要好用得多。5.3 被“搜索热词”带偏方向怎么识别有效信息我在调研Harness相关方案的时候看到过很多和主题无关的搜索词比如“照片修复模型”“JEV模型”“扩散模型”“TCN模型”等等。这些其实都是完全不同的技术方向不小心就会被绕进去。大家看资料的时候要注意热门关键词里混着太多噪声一定要以原始论文、官方文档和知名开源项目的资料为准。还有一个很常见的纠结点是“从0手写harness”还是“用框架”。我的建议是第一版方案尽量用现有框架搭一个能跑的雏形验证核心逻辑对不对第二版再决定是否要手写。不要一开始就陷入框架源码的海洋里也不要一上来就拒绝所有框架从零造轮子。保持务实你的目标是让业务跑起来不是证明自己能重写一个框架。5.4 多模型协同时的Harness设计要点最后补充一个进阶话题有些场景里你可能会同时用多个模型比如一个轻量的小模型做意图识别一个大一点的模型做最终生成。这时候Harness设计要重点关注“路由”逻辑。小模型判断错了把任务路由到大模型那边整个流程就歪了。我的做法是给小模型配一个带选项的槽位抽取任务让它只从预设的几个类别里选一个比如“问答、总结、工具调用、闲聊”。选项越少判断越准。然后路由节点根据分类结果把请求分发到不同处理链路。这样做的好处是每个模型都在自己擅长的子集上发力整体效果更可控。我个人的体会是Harness不是一个一次性的项目它更像一套需要持续打磨的工程系统。模型迭代得再快Agent Harness这套思维框架都不会过时。先把自己的业务场景拆清楚了再决定模型怎么选、Harness怎么搭效果绝对比盲目追新模型来得实在。最后再分享一个小技巧无论你用哪套方案请一定从第一天开始记录Token消耗、耗时和错误率这三个指标。你会发现当你纠结是换模型还是改Harness的时候这三个指标会直接给你答案。