我最近在折腾 Deepseek 的工程化落地时,发现圈子里对 Harness 这个词的讨论明显多了起来。有人把它当成 Agent 的平替,有人以为是个 UI 壳子,还有人直接拿它跟 Codex 的封装层对着看。实际把一套 Harness 架构跑通之后,我的感受是:它更像是在大模型外面套了一层可控的“接线板”,所有输入输出、工具调用、状态流转都从这层走,模型本身被当成一个稳定的推理内核来用。
这篇东西我打算从架构思路、模块拆解、实际部署到一个典型应用场景完整过一遍,中间穿插我在调试时踩过的坑和最终的解决方案。无论是刚准备把 Deepseek 接进现有业务的新手,还是已经在做多 Agent 编排的工程师,这篇应该都能提供一些可复用的参考。提前说明一句:这里讲的 Harness 不是某个特定官方产品的说明书,而是我在多种开源方案和自建方案之间对比后,沉淀下来的一套通用实践路径。
1. Harness 到底是什么:先搞懂它和 Agent 的本质区别
在拆架构之前,得先把概念对齐。很多人在看 Deepseek Harness 相关的讨论时,第一反应是“这不就是个 Agent 框架吗”。这个理解只对了一半,而且恰好是把 Harness 用好的关键障碍。
1.1 从工程语义看 Harness 的本意
Harness 在传统工程领域里叫“线束”或者“装配架”,核心作用是让各个独立部件能够被统一固定、接线、调度。在软件工程里,这个词通常指代测试 Harness——就是一套用来挂载被测代码、模拟输入、校验输出的外围系统。你被测的单元是核心,但真正决定测试能不能稳定跑起来的,是外面这层夹具。
放到 Deepseek Harness 这个语境里,逻辑完全一致:Deepseek 模型是核心处理器,但它不直接面对用户、不直接调外部工具、不自己保存状态。外面这层 Harness 负责把用户的请求标准化,决定要不要调用工具、调用哪个工具、模型返回后怎么处理、出错怎么重试、上下文满了怎么截断。
这就引出了和 Agent 的核心边界:Agent 是模型自主决策的一个执行单位,强调的是“代理性”;Harness 是整个执行环境的“约束层”,强调的是“可控性”。一个健全的 Harness 里可以跑一个或多个 Agent,也可以跑纯粹的链式任务流,完全看你编排的方式。
1.2 为什么 Deepseek 特别适合 Harness 架构
Deepseek 家族的模型带有一个天然特征:它们的推理能力强,但原生接口非常朴素。你给它一个 Prompt,它返回文本,仅此而已。真正让模型能够“做事”,必须靠外部系统帮它拆解任务、注入上下文、解析输出。
我这个判断源于一次对比试验。同一套工具调用逻辑,我分别让裸接口的 Deepseek 和套了 Harness 的 Deepseek 去完成一个“查数据库 → 生成周报 → 发送邮件”的三步任务。裸接口这边,我完全靠手写流程判断来解析模型输出的 JSON,结果模型一旦改变输出格式,整个链路就断掉。Harness 这边,工具调用的 schema 校验、异常重试、结果回填都是自动处理的,模型只需要专注于表达意图,余下是编排层的事。
所以 Deepseek Harness 的实际定位,就是一套聚焦在模型外围的工程化装配层。它不改变模型的推理能力,但决定了你的模型能力能不能稳定、安全、高效地落地到真实业务里。
1.3 Harness 的边界感从哪来
判断一个系统算不算 Harness,有个干脆的标准:去掉模型之后,这套系统还能不能独立存在并完成除了“思考 ”之外的所有工作——上下文检索、工具路由、输出解析、记忆管理、权限控制。如果可以,那它就是 Harness;如果整个系统因为模型而瘫焕,那它只是模型的“夹带附件”。
我在设计自己的 Deepseek Harness 时,把边界画得非常清楚。模型只保留两个出口:一个是接收压缩过的上下文并产出文本,另一个是在需要的时候产出结构化“工具请求”。其他任何逻辑都不允许直接写在模型 Prompt 里。这样做的好处是后期替换模型非常轻松,你从 Deepseek 切到别的开源模型,Harness 的代码几乎不用动,只换模型接入层的配置就行。
2. 核心架构拆解:一个 Harness 的内部长什么样
现在进入正题,拆解一套完整的 Deepseek Harness 应该包含哪些核心模块。我把它分成四层:接入层、编排层、工具层、存储层。每一层都有自己的职责边界,层与层之间通过标准接口对接。
2.1 接入层:统一不同来源请求的“门卫”
接入层负责接收外部所有请求,不管是来自 Web 前端的对话、来自 API 的批处理任务,还是来自 VSCode 插件的代码补全请求,进入 Harness 后都会被转换成一种统一的内部消息格式。
为什么要统一格式?因为不同入口带来的请求差异很大。Web 对话里往往带着用户 ID、会话 ID,代码插件里带着当前文件内容和光标位置,批处理任务里带着任务优先级。如果这些请求直接用各自的格式往下流,编排层就得写一堆兼容逻辑,非常容易出bug。我在设计时参考了微服务架构里 API Gateway 的思路,所有请求先经过接入层做通道适配——头部解析、身份校验、速率限制——然后再转成标准化的消息对象向下传递。
这个模块看起来不起眼,但它是整套系统稳定性的第一道防线。我建议在接入层就做掉三件事:速率限制、请求大小限制、基础格式校验。不要等请求到达模型调用层才去拦截,那时候已经浪费了大量无效计算资源。
2.2 编排层:Harness 的大脑中枢
编排层是整个架构里最核心的部分,它决定了一个请求进入后沿着什么路径执行。我习惯把它再细分为三个子模块:会话状态机、上下文组装器、策略执行器。
会话状态机掌管任务流的生命周期。每个请求进来后,它确定当前处于哪个阶段:是初始对话、工具调用中、还是等待模型二次响应。状态机的好处在于可以让流程可预测——不会出现模型都返回结果了,系统还在傻等工具回传的错乱局面。
上下文组装器负责决定“模型这一次能看到什么”。这是 LangChain 那类框架容易忽略、但在 Harness 架构里至关重要的一环。它要做的事情包括:从会话历史里截取相关的片段、注入当前工具返回的结果、附加系统级别的固定指令,然后把组装好的上下文压缩到模型窗口允许的长度范围内。Deepseek 的模型上下文窗口虽然够大,但盲目把所有内容塞进去不仅浪费 Token,还会稀释指令跟随的效果。
策略执行器是干“判断”的地方。这里通常集成一套规则引擎,决定某个场景下的行为策略:当工具调用连续失败两次时是直接报错还是换一个工具重试;当模型输出包含危险操作指令时是拦截还是放行;当用户请求涉及多轮工具协作时,是并行执行还是串行等待。这些策略不写死在代码里,而是采用可配置的规则文件管理,让非开发人员也能调整系统行为。
2.3 工具层:让模型长出“手脚”
工具层是 Harness 和真实世界交互的桥梁。Deepseek 模型本身不感知外部系统,它只负责输出意图。这个意图之所以能变成实际动作,靠的就是工具层。
工具层在设计上要强调“注册制”,而不是“硬编码制”。每个工具都按统一模式声明自己的名称、描述、输入参数 schema、执行函数和超时设置。Harness 启动时会扫描所有已注册工具,把它们的功能描述打包进系统提示词中,让 Deepseek 知道“你有哪些工具可以用以及什么时候用”。
这套模式在架构上的好处是极度解耦。我可以在不修改主干代码的情况下,随时添加一个新工具——写一个符合规范的函数、注册进去、重启服务,搞定。整个过程不会影响已有工具的行为。类似地,某个工具出问题的时候也可以单独把它摘除,模型会自然调整策略,改用其他可用工具完成任务。
2.4 存储层:会话、记忆和外部数据的落脚点
最后是存储层。Harness 必须是有记忆能力的,否则多轮对话和长期任务管理都是空谈。我通常把存储分成两部分:短期会话存储和长期知识存储。
短期会话存储承担最近几轮对话的上下文缓存,我会用 Redis 这类内存级数据库,读写速度足够快,TTL 可以自由设置。需要特别注意的是,存储结构要保留完整元数据——不只是用户说了什么、模型回了什么,还要记录每轮对话的工具调用记录、Token 消耗、以及上下文截断时被丢弃了哪些内容。这些数据是后续调试和成本核算的原始凭据。
长期知识存储负责向量化文档和长期记忆。在设计这个模块时要注意,不要把向量数据库存储的内容全部灌进模型上下文——正确做法是先做检索,只把相关度最高的 Top-K 条结果送进组装器。这里的 K 值选择很影响系统质量,太小了容易漏信息,太大了会冲淡核心指令。我在实践中的初始值是 5,然后根据具体场景在 3 到 8 之间调优。
3. 实操落地:从零搭一套自己的 Deepseek Harness
理论拆完,接下来是实操环节。我会按照实际搭建的先后顺序,把关键步骤和配置贴出来,并解释每一步的必要性。
3.1 技术栈选型与目录结构规划
第一步是选技术栈。Deepseek Harness 的参考实现较多,但核心逻辑其实语言无关。我最终选型建议是 Python——生态成熟、AI 相关库最全、团队上手成本低。这里有个细节值得说:异步框架和同步框架的选择。
我用的是 FastAPI + asyncio。原因在于 Harness 的很多环节是 IO 密集型的——等待模型响应、等待工具执行——同步阻塞会让整条链路的吞吐量非常低。异步化以后,单机就可以轻松支撑几十路并发对话。虽然 asyncio 的调试体验不如同步代码,但考虑到收益,这个取舍完全值得。
目录结构我建议这样组织:
deepseek-harness/ ├── app/ │ ├── main.py # FastAPI 入口 │ ├── gateway/ # 接入层 │ ├── orchestrator/ # 编排层(状态机 + 上下文组装 + 策略) │ ├── tools/ # 工具注册与执行 │ ├── storage/ # Redis 与向量库操作 │ └── config/ # YAML 配置 ├── rules/ # 策略规则文件 ├── logs/ # 运行日志 └── tests/这个结构不是越复杂越好,而是强调每一层的边界清晰。刚开始时不要贪多,先把主干跑通,再逐步补充细节。
3.2 最小可运行 Harness 的配置实操
接下来是最小可运行实例。我们先把 Harness 的核心流程搭起来,这个流程是:用户提问 → 上下文组装 → 调用 Deepseek → 判断是否有工具请求 → 执行工具 → 二次调用模型 → 返回最终回答。
核心调用 Deepseek API 的部分,可以参考下面这个最小实现:
# app/orchestrator/llm_client.py import httpx from typing import List, Dict class DeepseekClient: def __init__(self, api_key: str, base_url: str, model: str): self.api_key = api_key self.base_url = base_url self.model = model async def chat_completion( self, messages: List[Dict], tools: List[Dict] | None = None, temperature: float = 0.3, ) -> Dict: payload = { "model": self.model, "messages": messages, "temperature": temperature, } if tools: payload["tools"] = tools payload["tool_choice"] = "auto" async with httpx.AsyncClient(timeout=120) as client: resp = await client.post( f"{self.base_url}/chat/completions", headers={"Authorization": f"Bearer {self.api_key}"}, json=payload, ) resp.raise_for_status() return resp.json()注意这里设置了tool_choice: "auto",这是启用 Deepseek 原生工具调用能力的关键。模型可以自主决定本次响应是直接回答问题,还是先调用某个工具。返回的 JSON 里会有tool_calls字段,Harness 据此触发工具执行。
等到模型返回了工具请求,下一步就是执行工具并回填结果。这里我直接写一个统一的工具执行分发器:
# app/orchestrator/tool_router.py import json from app.tools.registry import get_tool async def execute_tool_call(tool_call): tool_name = tool_call.function.name arguments = json.loads(tool_call.function.arguments) tool = get_tool(tool_name) result = await tool.execute(arguments) return { "role": "tool", "tool_call_id": tool_call.id, "content": json.dumps(result, ensure_ascii=False), }这里的注册表get_tool从全局的工具注册表里面根据名称取对应实例。每个工具都必须实现统一的execute方法,保证路由逻辑的高度一致。
3.3 核心循环逻辑:完整请求的生命周期
有了底层 client 和 tool router,就可以组装完整的编排循环。核心逻辑是:
# app/orchestrator/loop.py async def run_harness(user_input: str, session_id: str): messages = await load_session_history(session_id) messages.append({"role": "user", "content": user_input}) # 最多允许 5 次工具调用循环,防止死循环 for _ in range(5): response = await llm_client.chat_completion( messages=messages, tools=get_all_tool_schemas(), ) msg = response["choices"][0]["message"] messages.append(msg) if msg.get("tool_calls"): for tool_call in msg["tool_calls"]: tool_result = await execute_tool_call(tool_call) messages.append(tool_result) else: return msg["content"] return "执行超限,请简化请求"这段代码是整个 Harness 的骨架。我特别强调一下5 次工具循环上限的设计考量:没有这个限制,当模型陷入错误工具调用链的时候会无限循环消耗 Token,5 次是一个安全且合理的默认值。真实使用下来,绝大部分正常任务只需要一两次工具调用就能完成。
3.4 工具注册:让一个自定义工具“插上电”
现在演示如何注册一个自定义工具。假设我们要给 Harness 加一个查询 MySQL 的业务数据工具。工具注册的写法如下:
# app/tools/mysql_query.py from app.tools.registry import register_tool import pymysql @register_tool( name="mysql_query", description="查询 MySQL 数据库并返回结果列表,用于业务数据检索", parameters={ "type": "object", "properties": { "sql": {"type": "string", "description": "要执行的 SQL 语句"}, "limit": {"type": "integer", "description": "最多返回的行数", "default": 10} }, "required": ["sql"] }, ) async def mysql_query(sql: str, limit: int = 10): # 链接池在真实项目中应当复用,此处简化 conn = pymysql.connect(...) try: with conn.cursor() as cur: cur.execute(sql + f" LIMIT {limit}") result = cur.fetchall() return {"status": "ok", "rows": result} finally: conn.close()注册完成之后,Deepseek 模型在回答问“我们最近一周订单量是多少”这类问题时,会自动决定调用这个工具,并解析 SQL 查询参数。这里有一个关键经验:工具的 description 写得越具体,模型越知道什么时候该调用它,并且越能正确地填写参数。模糊的 description 会导致模型该用不用或乱用参数。
3.5 前端接入:VSCode 与桌面端的简单对接方式
Harness 本体搭建好之后,还需要一个入口。这里我以 VSCode 插件为例简单说下对接方式:VSCode 插件本质上只负责捕捉用户输入和展示模型输出,所有智能逻辑都可以远程调用 Harness 的 HTTP 接口。插件内部把当前文件内容、选中区域、光标位置打包进请求,Harness 处理完把结果原样返回。这个模式架构清晰,插件的开发成本极低。
如果你的需求是桌面端,原理也一样。直接把 Harness 的 HTTP 接口封装成本地服务,桌面应用通过 WebSocket 或者 HTTP 长连接通信。在架构上记得把“显示层”和“智能层”彻底分开,这样将来换前端框架不需要动 Harness 的任何代码。
4. 应用场景与架构决策:Harness 在实际业务里怎么长
Harness 架构的优势必须落到具体场景里才能体现出来。我挑三个实际验证过的方向展开讲:接入 Codex 生态的联动、本地知识库问答、多 Agent 协作架构。
4.1 场景一:把 Deepseek 接入 Codex 类编码代理
最近社区里 Codex 接入 Deepseek 的讨论很多,本质上就是 Deepseek 的编程能力 + Codex 的任务管理外壳。但如果你直接拿 Deepseek 的 API 替换掉 Codex 的默认模型,效果往往不理想。原因在于 Codex 对模型输出格式有严格约束,而 Deepseek 的接口和它默认模型并不完全对齐,需要 Harness 做一层适配。
我的实践经验是在工具层加一个“代码执行沙箱”工具。Harness 捕获 Deepseek 生成的代码块后,不直接执行,而是先送进沙箱做静态检查和测试用例运行,确认通过后再回填到对话里。这样既能保留 Codex 式的交互体验,又能避开直连代码执行带来的安全风险。
作为一个工程化经验:当你准备把任何模型接进已有的 Agent 生态时,都不要直接改模型接入层,而应该在 Harness 层做适配。模型是可替换件,Harness 才是稳定底座。
4.2 场景二:本地知识库增强问答
Harness 最典型的应用之一是 RAG(检索增强生成)。思路很简单:把文档切块、向量化、存入向量数据库;检索时取回相关片段,作为上下文注入模型;模型基于检索结果生成回答。
在这个场景中,Harness 的上下文组装器起着决定性作用。它在组装上下文时,不只是简单地拼接检索结果,还要处理:多条检索结果与用户问题的相关性排序、重复信息的去重、以及关键信息的摘要化。这些工作如果全都丢给模型做,会显著增加 Token 消耗并拖慢响应速度。预处理阶段的取舍,比模型阶段的技术要求更琐碎,但收益也更明显。
我自己落地时的流程是:文档入库 → 请求触发检索 → 排名过滤 → 摘要压缩 → 与 Prompt 模板合并 → 发送模型。整个流程在 Harness 编排层里是一条清晰的处理链,各项环节都有日志和数据指标可以监控,后期诊断非常直观。
4.3 场景三:多 Agent 协作模式的注意点
当任务复杂到单个 Harness 实例处理不过来时,可以调整架构为多 Harness 实例协作,这时的设计逻辑就接近微服务架构了。每个 Harness 实例负责一个特定领域——一个管数据分析、一个管文档生成、一个管外部 API 调用——它们之间通过消息队列通信。
实践中的核心难点是上下文协调。多个 Agent 各自维护独立的会话状态,当一个 Agent 的输出需要传给另一个 Agent 使用时,消息格式必须明确并且经过校验。我建议在设计阶段就定义好消息协议,里面至少要包含:发送方、接收方、消息类型、内容、时间戳和请求 ID。没有统一协议的多 Agent 协作到最后一定会变成不可维护的蜘蛛网。
5. 常见问题与排查技巧实录
整套架构跑通之后,剩下的工作基本就是和各类问题打交道。我把实践中遇到的高频问题按类别整理成表格,并附上排查思路和最终的解决方案。
| 问题现象 | 根因分析 | 排查步骤 | 解决方案 |
|---|---|---|---|
| 模型频繁输出无效工具调用 | 工具描述模糊或参数 schema 不完善 | 查看调用日志,看模型试图调用哪个工具、传了什么参数 | 重写工具 description,细化参数约束,加入枚举值和默认值 |
| 多轮对话后响应质量明显下降 | 上下文组装没有截断策略,会话历史越来越长 | 检查每次请求的 Token 消耗曲线,定位上下文膨胀节点 | 在组装器里加入摘要压缩和滑动窗口截断,保留核心意图丢弃冗余内容 |
| 工具执行成功但模型答非所问 | 工具执行结果没有按 schema 回填,或回填位置错误 | 检查工具 result 的 JSON 结构是否完整,确认 message 顺序是否正确 | 给工具结果回填加 schema 校验,结构不对直接抛出错误而不是静默放过 |
| 响应速度越来越慢 | 工具层存在阻塞 IO 调用,拖垮了事件循环 | 用 profiling 工具定位耗时函数 | 把阻塞操作替换为异步客户端,或放进线程池执行 |
| 高并发时报错连接池耗尽 | 数据库连接和外部 HTTP 连接没有复用 | 查看连接池监控指标 | 全部改为连接池模式,设置最大连接数和等待队列 |
| 模型开始重复调用同一个工具 | Harness 缺少工具结果去重和缓存机制 | 查看工具调用的参数,发现相同参数被反复调用 | 在工具层实现结果缓存,相同参数的调用直接返回缓存值 |
| 部署到新环境后功能异常但无报错 | 配置项依赖了原环境的绝对路径或硬编码变量 | 对比配置文件,检查环境变量差异 | 所有动态参数外置到环境变量和 YAML 配置,禁止代码硬编码 |
5.1 工具调用死循环的彻底驯服方法
在众多问题里,工具调用死循环是最消耗成本也最隐蔽的一个。现象是你去看日志,发现模型连续调用了同一个工具,比如反复去查库存,每次参数都差不多,就是不进入总结阶段。代码里的最大轮次限制虽然能兜底,但核心还是要让模型知道“什么时候停止调工具”。
我个人试过比较有效的做法:在系统提示词里加入“当工具结果足够回答用户问题时,必须直接给出最终答案,不要继续调用任何工具”。这招看起来朴素,但对大多数主流模型都有效。另外一个比较讨巧的方式是,当工具返回结果与上一次完全相同时,Harness 会自动注入一条提示“工具结果与上次一致,请基于当前信息直接回复”,强行打破循环。
5.2 上下文越长,回答越“糊”的救法
用 Deepseek 系列模型时会发现,上下文接近窗口上限时,模型的指令跟随能力会下降,甚至出现逻辑混乱。这不是模型不行,而是组装器没有做好注意力分配。模型需要在海量内容中努力抓住关键信息,越多无关噪声混进去,效果越差。
我的应对思路是给上下文做“高压缩比摘要”和“结构化标签”。系统不追求完整保留每一轮历史,而是每轮结束时由另一个小模型把当轮的关键信息压缩成结构化摘要——谁、做了什么工具调用、拿到了什么关键数据、还遗留什么待办。下一轮组装时,模型读的是高度浓缩但有明确结构的摘要,而不是逐字逐句的原始记录。这种架构调整之后,即使上下文轮次翻倍,模型的响应质量也保持稳定。
5.3 调试 Harness 时的三个核心指标
排查问题不能靠猜,得有数据支撑。我给自己的 Harness 定了三个核心监控指标:
第一个是平均工具调用次数。正常任务应该在 1-3 次之间。超过这个范围,基本说明工具描述有问题或上下文信息不足。第二个是上下文压缩率,就是原始信息量和最终送进模型的 Token 数之间的比例。压缩率太低说明组装器的去重和摘要逻辑没起作用。第三个是单轮失败率,这个指标直接反映了工具稳定性,失败率持续高于合理范围时需要优先检查工具代码,而不是模型配置。
这三个指标配合完整的链路日志,基本能覆盖 90% 的线上问题定位。接入层、编排层、工具层、存储层每层都打上耗时日志,请求 ID 贯穿全链路,一旦出问题就能按请求 ID 把所有环节的日志串起来看。
6. 成本和性能优化:Harness 不只是一个玩具
很多人把 Harness 当作一种概念玩具,但实际上生产环境的成本控制和性能调优,同样会落在这个架构上。
6.1 Token 消耗的三处瘦身
第一处是系统提示词。Deepseek 模型对系统提示词很敏感,但它不应成为信息堆砌的地方。我见过一些人把几十条业务规则全塞进系统提示词,每次请求都要把这几十条完整发送,Token 消耗迅速膨胀,而且模型对长提示词的指令跟随效果会边际递减。正确做法是保留核心行为准则,把长篇幅的知识库内容放到合适位置,需要时才通过检索注入。
第二处是历史消息压缩。多次请求的场景中,不压缩历史消息是最常见的浪费点。按前面的摘要压缩方案,把原始历史压缩到十分之一,长期运行下来的 Token 节省非常可观。
第三处是输出限制。给所有模型调用设置max_tokens上限,并训练输出的简洁性。很多场景的回答根本不需要长篇大论,合理的输出限制能直接降低响应延迟和成本。
6.2 并发接入层和应用层异步化的细节
前面提到 FastAPI 的异步化,具体到生产部署还需要注意几个点。首先,async def和def接口不要混用,混用会让 FastAPI 进行不必要的线程池切换,产生性能损耗和排查困难。其次,所有工具函数都应该是异步的,如果工具本身是同步库,用run_in_executor包装,而不是在事件循环里直接阻塞。还有一点,当多个工具之间没有依赖关系时,应当并行执行而不是串行执行,这个优化在多工具场景下能大幅缩短总响应时间。
6.3 推荐部署形态:容器化 + 负载均衡
Harness 本身是无状态的服务层,非常适合容器化部署。我强烈建议从第一天起就用 Dockerfile + docker-compose 管理整套环境,而不是依赖物理机环境配置。容器化之后,横向扩容变成简单的副本数调整,配合负载均衡即可支撑更高并发。
在容器编排上,除了模型接入层之外,建议将编排层单独部署成一个服务。这样模型调用频率高的场景和工具密集型场景可以分别扩容,避免单服务瓶颈拖累整个链路。数据库层使用云数据库或者独立容器部署,不在 Harness 应用容器里混布,保持职责分离。
7. 写在最后的几点体会
Harness 这套架构说简单也简单,说复杂也复杂。简单在于它的核心思路非常朴素——把模型包起来,就越权把控制权交还给业务系统;复杂在于每一层的边界怎么划分、规则怎么设计、策略怎么调整,都需要在实际业务场景里反复打磨。没有一套通用的完美配置,只有适合你场景持续迭代的好架构。
我自己在调整上下文组装策略时试过非常多的组合。有时候把检索返回的 Top-K 从 5 调到 3,回答的精确定度反而提升了不少;有时候给工具层加个结果缓存,整体响应速度直接涨了一个量级。这些微观调整不写进任何官方文档,只能靠自己的项目和场景去碰。
最后再分享一个真实有效的技巧:无论你用的是哪种方案,保持厂商中立都很重要。在 Harness 设计里把模型接入层做成可替换的,未来的模型生态只会越来越丰富,今天的选择未必是明天的方案。这个层面的灵活性,才是 Harness 架构最大的长期价值。