news 2026/9/8 11:48:23

从零实现 DeepSeek Harness:Python 工具链与 VS Code 接入实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从零实现 DeepSeek Harness:Python 工具链与 VS Code 接入实战

在 AI 开发工具链里,DeepSeek Harness 插件这个组合词被搜索的频率越来越高。有人想把它装进 VS Code,有人想找一个桌面端,还有人以为它是某种能自动完成任务的 Agent。搜索不到完整资料时,很容易在安装环节卡住。这篇文章会换一个思路:不依赖某个不确定维护状态的现成插件,而是把 DeepSeek Harness 拆成可以自己实现的工程能力。

Harness 的英文本意是“背带、挽具”,在机器学习工程里,它通常指一层承上启下的运行框架:向下统一调用模型接口,向上提供工具注册、上下文管理、结果回传等能力。所谓 DeepSeek Harness 插件,可以理解成“把 DeepSeek 模型接进自己工具链的一层框架”。这篇文章会从零写一个最小可用的 Python Harness,支持统一 API 调用、工具函数注册、CLI 交互,再把它接入 VS Code。整个过程就像一次空城计:用单个脚本模拟出完整插件平台的核心结构,等确实需要重型功能时再逐步扩展。

1. 先理解 DeepSeek Harness 是什么,为什么很多人都在安装它

1.1 Harness 的通俗含义和技术定义

Harness 的英文原意是“挽具、背带”,用于把牲畜套在车或犁上。迁移到软件工程后,Harness 变成了“把多个部件组合起来运行的控制框架”。在 LLM 应用里,Harness 更直观的理解是:模型本身只负责文字生成,真正让它能干活的,是外层挂上的一堆工具、提示词、上下文管理逻辑,以及调用这些逻辑的统一入口。

技术定义上,Harness 是一层承上启下的中间层。它的下层是模型 API,上层是用户界面或业务系统。它负责处理几个重复性很高的问题:API Key 怎么读取、请求参数怎么构造、工具函数如何暴露给模型、模型输出如何解析、错误如何重试。没有这层封装时,每个脚本都要重复写一遍网络请求;有了这层封装后,业务代码只需要描述“我想让模型做什么”,不需要关心底层 HTTP 细节。

在很多英文资料里,Harness Engineering 被用来指一类为模型搭建执行环境的工程实践。它和评估工具中的 Evaluation Harness 不完全是一回事。评估 Harness 侧重批量跑数据集、计算指标;工程 Harness 侧重线上应用中的调用、工具编排和异常处理。本文讨论的是后者。

1.2 DeepSeek Harness 插件解决哪几类问题

DeepSeek 模型本身以 API 形式提供服务。如果只是测试对话,直接 curl 一下就行。但一旦进入真实工具链,“DeepSeek Harness 插件”这类需求通常是为了解决以下问题。

第一,统一 API 调用。多个脚本要共用同一个模型地址、Key 和超时策略,不该每处都重复写 requests 请求。

第二,给模型开放外部工具。让模型可以读取文件、执行命令、查询天气、操作数据库,而不是只能基于训练知识回答问题。Harness 在这一层负责工具注册和调用结果回传。

第三,把模型接进开发环境。VS Code 插件、命令行工具、桌面端,本质都是同一个 API 的前端。Harness 通过提供稳定入口,让不同前端都能调用同一套能力。

第四,管理上下文和成本。对话轮数变多后,Harness 需要决定哪些历史消息保留,哪些截断,避免 token 消耗失控。

如果你在搜索“deepseek harness 安装”,多数情况是想快速跑通一个能用的入口。安装本身并不难,难的是装完后不知道它内部怎么工作,遇到问题没法排查。所以这篇文章选择从实现角度切入,而不是推荐一个安装包。

1.3 Harness、Agent、普通插件有什么区别

这三个词经常被混用,实际上边界很清楚。

普通插件是宿主应用的一个扩展点。VS Code 插件、浏览器插件,都是在宿主环境提供的入口里增加功能。插件本身不关心模型调度,它只是在 UI 上把代码或文本发给后端。

Harness 是模型运行的外层框架。它关心请求怎么构造、工具怎么注册、响应怎么解析。插件通常是 Harness 的前端表现。

Agent 则更进一步,它有“自主规划”能力。Agent 拿到目标后,会拆解步骤,逐步调用模型和工具,根据中间结果调整下一步操作。一个 Agent 内部往往内置了一个 Harness,但 Harness 不一定具备 Agent 的规划能力。

表格对比会更直观。

术语核心特征典型使用场景容易混淆点
插件给宿主应用增加功能入口VS Code 中通过按钮触发 DeepSeek 调用只是前端入口,不是 Harness 本体
Harness统一管理模型调用、工具注册和上下文脚本或平台中稳定调度模型能力与“插件”混用,实际上 Harness 是框架层
Agent自主规划、拆解任务、循环调用工具给模型一个目标,让它自己决定调用哪些函数不是所有 Harness 都有 Agent 的自主规划

依赖这个表,搜索时就能判断资料质量:如果一个“Harness 插件”只能发请求,没有工具调用能力,那它更像一个 API 客户端,而不是完整 Harness。

1.4 用“空城计”理解最小 Harness 的定位

“空城计”在这里是一个工程策略隐喻。很多时候,我们并不需要一开始就搭建一个庞大的平台。面对模糊需求时,可以用一个小而完整的脚本,把核心链路跑通。

最小 Harness 就是这样的空城计:一个 Python 文件,几百行代码,却具备完整 Harness 的核心结构。看起来像一套系统,实际上只是一小段逻辑。等业务增长后,再把它替换成更重的组件。这种做法的好处是,每个环节都在自己控制范围里,出了问题能快速定位,不需要去读别人插件的源码。

注意:如果只是临时体验,单文件脚本足够。如果打算长期维护或多人协作,还是尽早拆模块化。

2. 环境准备:API、依赖、目录结构一次对齐

2.1 接入 DeepSeek API 前需要确认的四个信息

很多失败案例不是代码写错,而是前置信息没确认。至少需要确认四样东西:API Key、Base URL、模型名称、上下文长度。

API Key 需要在 DeepSeek 开放平台后台创建。创建后通常只完整显示一次,如果丢失只能重新生成。Base URL 一般指向https://api.deepseek.com,具体路径要参考当前官方文档,因为不同版本可能使用/chat/completions/v1/chat/completions等不同路径。模型名称常见的有deepseek-chatdeepseek-reasoner等,不同阶段可能有调整,不能凭记忆写死。

上下文长度决定单次请求能传多少 token。超出限制时,请求可能报错或内容被截断。低成本测试时,建议先使用短文本,确认链路通了再放大上下文。

检查项常见配置出错表现
API Key后台生成,妥善保存401 Unauthorized
Base URL按官方文档配置,不随意加/v1404、连接超时
Model使用官方文档中的模型标识400 model not found
上下文长度确认模型最大值长文本截断或请求失败

2.2 学习环境的依赖配置

最小依赖只需要 Python 3.10 以上和requests。如果习惯用 OpenAI SDK 也可以,但为了看清内部流程,建议先从 HTTP 请求开始。

创建虚拟环境并安装依赖:

mkdir deepseek-harness cd deepseek-harness python -m venv venv source venv/bin/activate # Windows 执行 venv\Scripts\activate pip install requests python-dotenv

python-dotenv用于读取.env文件,避免在代码里硬编码 Key。学习环境里,这两个包足够。

2.3 项目目录结构:从单文件起步,按模块扩展

建议初始目录如下:

deepseek-harness/ harness/ __init__.py core.py tools.py config.py scripts/ cli.py .env .gitignore requirements.txt README.md

harness/core.py放模型调用入口,harness/tools.py放工具注册器,harness/config.py放配置读取,scripts/cli.py放命令行交互界面。如果只是快速验证,也可以先只写一个main.py,把上述逻辑都放进去。但后续加工具、加日志时,还是按模块拆分更舒服。

需要在.gitignore中排除.env

.env venv/ __pycache__/ *.pyc .DS_Store

空城计策略的关键是:目录结构先做出来,但每层代码保持最小,不需要一开始就实现太多抽象类。

3. 用 Python 实现一个最小 Harness:模型调用、工具注册和插件扩展

3.1 配置管理:API Key 不进代码

先创建.env文件:

DEEPSEEK_API_KEY=sk-xxx DEEPSEEK_BASE_URL=https://api.deepseek.com DEEPSEEK_MODEL=deepseek-chat

再实现harness/config.py

import os from dotenv import load_dotenv load_dotenv() class HarnessConfig: def __init__(self): self.api_key = os.getenv("DEEPSEEK_API_KEY", "").strip() self.base_url = os.getenv("DEEPSEEK_BASE_URL", "https://api.deepseek.com").strip() self.model = os.getenv("DEEPSEEK_MODEL", "deepseek-chat").strip() self.timeout = int(os.getenv("DEEPSEEK_TIMEOUT", "60")) self.max_tokens = int(os.getenv("DEEPSEEK_MAX_TOKENS", "1024")) def validate(self): if not self.api_key: raise ValueError("DEEPSEEK_API_KEY 未配置,请在 .env 或环境变量中配置")

注意strip()处理 Key 前后不小心复制进来的空格。这是最常见的低级错误,却会导致 401。

3.2 统一模型调用入口

harness/core.py实现一个最简客户端:

import requests class DeepSeekClient: def __init__(self, config): self.config = config def chat(self, messages, tools=None, temperature=0.7, max_tokens=None, stream=False): if not self.config.api_key: raise ValueError("DEEPSEEK_API_KEY 未配置") url = self.config.base_url.rstrip("/") + "/chat/completions" headers = { "Authorization": f"Bearer {self.config.api_key}", "Content-Type": "application/json", } payload = { "model": self.config.model, "messages": messages, "temperature": temperature, "max_tokens": max_tokens or self.config.max_tokens, "stream": stream, } if tools: payload["tools"] = tools resp = requests.post(url, headers=headers, json=payload, timeout=self.config.timeout) if resp.status_code != 200: raise RuntimeError( f"DeepSeek API error: status={resp.status_code}, body={resp.text}" ) return resp.json()

这里把模型调用收敛成一个chat方法。业务代码只需要传messages和可选的tools,不需要关心 URL、Headers、超时。后续要加日志、重试、缓存,也只需要改这一个文件。

如果要用 OpenAI SDK,只需要替换成一个OpenAI客户端:

from openai import OpenAI client = OpenAI( api_key=config.api_key, base_url=config.base_url, )

注意:是否兼容 OpenAI SDK,以你拿到的服务端实现为准。DeepSeek 开放平台的设计通常兼容 OpenAI 风格,但不同阶段可能有差异,落地前先看文档。

3.3 工具注册表:让模型能“调用插件”

Harness 区别于普通 API Demo 的核心,是工具注册机制。在harness/tools.py中实现一个简单注册表:

TOOL_REGISTRY = {} def register_tool(name, description, parameters): def decorator(func): TOOL_REGISTRY[name] = { "func": func, "description": description, "parameters": parameters, } return func return decorator def get_tools_for_api(): tools = [] for name, item in TOOL_REGISTRY.items(): tools.append({ "type": "function", "function": { "name": name, "description": item["description"], "parameters": item["parameters"], }, }) return tools def call_tool(name, arguments): if name not in TOOL_REGISTRY: return f"unknown tool: {name}" try: return TOOL_REGISTRY[name]["func"](**arguments) except Exception as e: return f"tool {name} error: {str(e)}"

注册两个最小工具:

import datetime @register_tool( name="get_current_time", description="获取当前系统时间。", parameters={ "type": "object", "properties": {}, }, ) def get_current_time(): return datetime.datetime.now().isoformat() @register_tool( name="read_file", description="读取文本文件内容,路径必须是绝对路径。", parameters={ "type": "object", "properties": { "path": {"type": "string", "description": "文件绝对路径"} }, "required": ["path"], }, ) def read_file(path: str): try: with open(path, "r", encoding="utf-8") as f: return f.read()[:2000] except Exception as e: return f"read file error: {e}"

这个注册表就是“插件”的雏形。每增加一个工具,只需要@register_tool注册一个函数,再写清描述和参数。模型通过描述知道什么时候该调用工具,Harness 通过注册表找到具体函数并执行。

3.4 工具调用循环:Harness 和普通 API Demo 的分水岭

普通对话是“模型生成 -> 返回”。加了工具后变成了循环:

  1. 用户消息放入messages
  2. Harness 把messages和工具描述发给模型。
  3. 如果模型返回tool_calls,Harness 解析调用名和参数。
  4. Harness 执行本地工具,把结果作为新消息追加到messages
  5. Harness 再次请求模型,让模型基于工具结果生成最终回答。
  6. 这个循环可以重复多次,直到模型不再请求工具。

core.py中增加一个运行循环:

class HarnessRunner: def __init__(self, client): self.client = client self.messages = [] self.max_iterations = 5 def run(self, user_message: str) -> str: self.messages.append({"role": "user", "content": user_message}) for _ in range(self.max_iterations): response = self.client.chat(self.messages, tools=get_tools_for_api()) choice = response["choices"][0] message = choice["message"] self.messages.append(message) tool_calls = message.get("tool_calls") if not tool_calls: return message.get("content", "") for call in tool_calls: func_name = call["function"]["name"] args_text = call["function"]["arguments"] import json try: args = json.loads(args_text) if args_text else {} except json.JSONDecodeError: args = {} result = call_tool(func_name, args) self.messages.append({ "role": "tool", "tool_call_id": call["id"], "content": str(result), }) return "达到最大工具调用轮数,停止执行"

这段代码最容易出错的地方是messages的组装。OpenAI 兼容格式要求:模型返回的message要原样追加到messages,然后再追加每个tool角色的结果。漏掉message.contenttool_call_id,都可能让服务端报错。

注意:工具调用循环必须设置最大轮数。业务上如果工具步骤有误,模型可能会一直重试,最终浪费 token。把max_iterations控制在 5 以内会比较合理。

3.5 最小 CLI:跑起来才算完成

scripts/cli.py

import sys from harness.config import HarnessConfig from harness.core import DeepSeekClient, HarnessRunner def main(): config = HarnessConfig() config.validate() client = DeepSeekClient(config) runner = HarnessRunner(client) print("DeepSeek Harness 已启动,输入 exit 或 quit 退出。") while True: try: user_input = input(">>> ") except (EOFError, KeyboardInterrupt): print() break if user_input.lower() in {"exit", "quit"}: break if not user_input.strip(): continue answer = runner.run(user_input) print(answer) if __name__ == "__main__": sys.exit(main())

这个 CLI 就是 Harness 的“插件前端”。虽然它没有图形界面,但已经具备完整链路。后续做 VS Code 插件、Web 界面,都可以复用它调用的HarnessRunner

4. 把 Harness 接进 VS Code 和命令行

4.1 VS Code 自定义任务接入

很多搜索“vscode 接入 deepseek”的读者,最终只是想在一段 Markdown 或代码里把内容发给模型。在没有安装第三方插件的情况下,可以直接用 VS Code 的任务机制跑上面的 CLI。

在项目根目录.vscode/tasks.json增加:

{ "version": "2.0.0", "tasks": [ { "label": "DeepSeek Harness", "type": "shell", "command": "python ${workspaceFolder}/scripts/cli.py", "presentation": { "reveal": "always", "panel": "dedicated", "focus": true } } ] }

之后按Ctrl+Shift+P运行 Tasks,选择DeepSeek Harness,就会在集成终端里打开一个可交互的模型入口。这个方案避免了安装未知来源的插件,适合公司网络或安全要求较高的环境。

也可以注册一个按键绑定,运行后直接把当前选中文本复制到剪贴板,再粘贴进 CLI。更复杂的使用方式可以后续自己实现。

4.2 命令行 Agent 工具接入兼容 API 的场景

网上搜索“codex 接入 deepseek”、“codex harness”时,会看到一些人通过配置OPENAI_BASE_URLOPENAI_API_KEY来让 OpenAI 风格的命令行工具指向 DeepSeek。这种做法的前提是目标工具支持自定义base_url

匹配时要注意以下几点:

  • 确认命令行工具是否允许配置base_url,以及配置文件位置。
  • 确认目标模型是否支持该工具内部使用的功能,例如 function calling、JSON mode 或视觉输入。
  • 确认工具的鉴权方式是否与服务端兼容。
  • 升级工具版本后要重新验证,不要假设配置长期有效。

不建议通过修改第三方 SDK 内部代码的方式强行接入。升级 SDK 后改动会被覆盖,维护成本很高。最稳妥的方式是:把上面第 3 节实现的 Harness 封装成一个小型 HTTP 服务,然后让命令行工具的base_url指向自己写的服务,由这个服务负责转发到 DeepSeek。这样虽然多了一层,但可控性更强。

4.3 桌面端和 Web 端:都是外表,核心还是 API

热搜词里经常出现“deepseek harness 桌面端”。桌面端本质上是一个用 Electron、Tauri 或 Qt 包装的聊天界面。它调用的还是 DeepSeek API。没有可靠桌面端时,自己用 Flask 或 FastAPI 暴露一个接口,再用网页打开,就能达到类似效果。

一个最小 Web 后端只需要把HarnessRunner封装成 HTTP 接口:

from flask import Flask, request, jsonify from harness.config import HarnessConfig from harness.core import DeepSeekClient, HarnessRunner app = Flask(__name__) config = HarnessConfig() runner = HarnessRunner(DeepSeekClient(config)) @app.post("/chat") def chat(): data = request.get_json() user_message = data.get("message", "") answer = runner.run(user_message) return jsonify({"answer": answer})

flask run启动后,浏览器页面或其他插件就能通过/chat接口调用同一个 Harness。这样一来,VS Code 插件、浏览器插件和桌面端都只是外壳,核心能力仍然在 Harness 层。

5. 运行验证和结果分析

5.1 第一步:验证普通对话

启动 CLI:

python scripts/cli.py

输入“你好,请用一句话介绍自己”。正常输出类似:

DeepSeek Harness 已启动,输入 exit 或 quit 退出。 >>> 你好,请用一句话介绍自己 你好,我是一个基于 DeepSeek 模型的智能助手。

这里验证的是最基础链路:API Key 有效、Base URL 正确、模型名称正确、请求能正常返回。

5.2 第二步:验证工具调用

输入“现在北京时间几点?”。如果模型识别到需要调用get_current_time,Harness 会执行工具,然后基于工具结果生成回答。预期输出会包含一个具体时间,而不是模型自己编造的时间。

这个验证很关键。如果模型回答的是一个编造时间,说明工具调用没有发生,或者工具调用结果没有正确回填到messages。需要检查工具描述的格式和call_tool的解析逻辑。

如果模型没有返回tool_calls,而是直接给出一个猜测时间,可以在工具描述里强调“这是获取当前时间的唯一来源”,或者降低temperature,让模型更倾向于调用工具。

5.3 第三步:观察 token 消耗

DeepSeekClient.chat里打印响应中的 usage 字段:

if "usage" in resp_data: usage = resp_data["usage"] print(f"[usage] prompt_tokens={usage.get('prompt_tokens')} " f"completion_tokens={usage.get('completion_tokens')} " f"total_tokens={usage.get('total_tokens')}")

通过 token 消耗可以判断:

  • 一个普通问题消耗了多少输入 token。
  • 工具调用会让请求变成多次,总 token 会不会成倍增长。
  • 是否需要在长对话中做历史截断。
  • 是否因为上下文增长导致成本超出预期。

实际项目中建议把 usage 写入结构化日志,方便按用户、按时段统计成本。

5.4 第四步:验证异常分支

至少要验证三类异常:

  • 配置错误:故意在.env中写错 API Key,观察是否返回 401。
  • 网络异常:断网后运行,观察是否报连接超时。
  • 模型不存在:把DEEPSEEK_MODEL改成不存在的模型,观察是否返回 400。

每类异常都要有明确提示,不能只是 Python 堆栈。可以在chat方法里统一抛RuntimeError,在 CLI 外层捕获并显示友好提示:

try: answer = runner.run(user_input) except Exception as e: print(f"请求失败: {e}")

6. 常见问题排查链路

6.1 连接超时、404 或网络不可达

现象可能原因检查方式处理建议
连接超时Base URL 错误、网络不可达、DNS 解析失败curl -v https://api.deepseek.com核对官方文档地址,检查网络连通性
404URL 路径拼接错误打印最终请求 URL查看是否多拼了/v1或漏了路径
SSL 证书错误本地证书环境异常临时关闭验证定位问题不使用verify=False,应修复证书环境

排查顺序:先确认 URL 本身能访问,再确认代码里的拼接结果和它一致。不要上来就改超时时间。

6.2 401 Unauthorized

现象可能原因检查方式处理建议
401API Key 无效后台重新生成 Key确认 Key 未过期、未泄露
401Key 前后有空格打印config.api_key长度使用strip()
401请求头格式错误抓包或打印 headers确认Bearer后有空格

排查时不要只检查.env,还要看代码实际读取到的值。环境变量里的同名变量会覆盖.env中的配置,这很容易被忽略。

6.3 400 model not found 或参数错误

现象可能原因检查方式处理建议
400 model not found模型名称写错对比官方文档中的 model 字段使用当前文档中的模型标识
400 max_tokens 超限参数超出模型允许范围查看错误信息中的限制按上下文限制设置
400 tools 格式错误工具参数不符合 schema打印 payload 中的 tools参考 OpenAI function calling 格式

这一类问题通常在请求失败时的 response body 里有具体原因。不要只看状态码,要把resp.text完整打印出来。

6.4 工具调用结果异常

模型返回了tool_calls,但代码报错或回答不对,常见情况有:

  • arguments不是合法 JSON。模型偶尔会生成多余字符,解析失败时不能直接崩溃,要捕获JSONDecodeError
  • 工具参数类型不匹配。例如read_file要求path是字符串,但模型传了数组。call_tool里需要做类型校验或把异常变成可读信息。
  • tool_call_id缺失或不对。OpenAI 兼容格式要求 tool 消息必须关联tool_call_id,否则服务端可能拒绝。
  • 工具调用轮数限制触发。模型在连续调用工具时如果没有收敛,最终会达到max_iterations

解决方式是给工具调用循环增加完整日志,在每轮打印本轮是模型文本、工具调用名、工具参数、工具结果,这样能快速定位是哪一步断了。

6.5 环境配置能读,程序却提示未配置

现象可能原因处理建议
提示未配置,但.env有内容.env不在当前工作目录使用绝对路径加载.env,或确认启动目录
环境变量也有值,但没生效Shell 缓存重启终端,或unset DEEPSEEK_API_KEY后重新加载
多人协作时 Key 混乱.env被提交到了 Git加入.gitignore,并轮换已泄露 Key

排查时先打印os.getenv("DEEPSEEK_API_KEY"),确认代码真正读取到的是什么。

7. 成本、安全与生产化建议

7.1 API Key 安全清单

  • 不要把 Key 硬编码在代码里,也不要提交到 Git。每次代码仓库扫描,都应检查.env是否被误提交。
  • 不要把 Key 放在前端代码、浏览器插件源码或桌面端本地配置里。前端暴露的 Key 等于公开。
  • 用环境变量、密钥管理服务或者工厂内部的配置中心保存 Key。
  • 为 Key 设置消费上限或额度提醒,避免异常调用导致费用失控。
  • 一旦发现 Key 泄露,立即在平台后台轮换,不能只删仓库文件。

7.2 成本控制三件事

第一,限制单次请求的max_tokens。模型回答越长,费用越高。如果业务只需要短结论,设成 512 或 1024 即可。

第二,控制上下文长度。工具调用会让每轮请求都带上全部历史消息和工具结果。长时间运行后,历史会变得非常大。可以用滑动窗口只保留最近 N 轮,或者做一次摘要压缩再继续。

第三,使用降级策略。DeepSeek 服务不可用时,可以降级到本地小模型或返回缓存结果,而不是无限重试。重试时要使用指数退避,并加上最大重试次数。

成本手段学习环境生产环境
上下文不限制滑动窗口或摘要压缩
超时重试指数退避 + 熔断
日志print结构化日志 + usage 统计
降级直接报错缓存或备用模型

7.3 从学习 Demo 到生产 Harness 的差距

模块学习环境生产环境
配置.env配置中心或密钥管理服务
日志控制台打印JSON 日志、Trace ID、集中采集
工具权限本地随意调用沙箱、白名单、权限校验
监控请求数、延迟、错误率、token 消耗
回滚重启脚本版本化部署 + 灰度切换

特别要注意工具权限。示例中的read_file可以读取任意文件,这在本地演示没问题,但暴露到生产环境就是严重风险。真实场景里,文件工具只能访问指定目录,命令执行工具必须经过白名单和审计。

7.4 合理使用与合规边界

在使用 DeepSeek 或任何模型服务时,要遵守服务提供方的使用条款和当地法律法规。不要在 Harness 中加入任何尝试绕过来使用限制、突破内容边界或窃取未授权数据的功能。工具执行层也要做权限校验和审计,不能因为模型输出“想访问某个路径”就直接执行。

8. 扩展方向:把“空城计”变成真 Harness

8.1 从单文件到插件化加载

当前工具注册表是显式导入的。工具多了以后,可以用importlib自动扫描tools/目录下的 Python 文件,实现类似插件的加载机制。每个文件定义一个register()函数,放在固定目录中即可生效。这样新工具不需要改主流程代码,只需要新增文件。不过自动加载也带来风险:任何人往目录里放一个 Python 文件就可能执行任意代码。生产环境必须对插件加载目录做严格权限控制,不能静默加载未知来源插件。

也可以使用 YAML/JSON 配置描述工具参数,配合一个通用 executor 动态执行。这种方式更适合允许用户自己定义工具的 Harness。

8.2 在 Harness 之上叠加 Agent 规划能力

Harness 解决了“调用模型 + 调用工具”的问题,Agent 进一步解决“拆解任务”的问题。如果想要一个 Agent,可以在 Harness 之上加入规划循环:模型先生成一段计划,再按计划调用工具,每一步观察结果后修正下一步。这个循环和第 3.4 节的工具循环类似,但需要更详细的状态管理和中断机制。

建议不要一开始就上重型 Agent 框架。先把 Harness 的稳定性做好,再逐步加入目标规划、子任务拆分和反馈复盘。

8.3 一份可执行的学习路径

如果读者想从这篇文章继续深入,可以参考下面顺序:

  1. 读懂 DeepSeek API 文档中的messages结构,动手构造一次 HTTP 请求。
  2. 实践 function calling,把工具从 2 个扩展到 5 个以上。
  3. 给 Harness 增加日志、token 统计和异常恢复能力。
  4. 把它封装成小型 HTTP 服务,接入 Web 或桌面前端。
  5. 在工具层增加沙箱、权限和审计,再考虑自动加载插件。
  6. 如果确需 Agent 能力,再研究 ReAct 循环或引入成熟 Agent 框架。

最后回到这篇文章的核心判断:所谓 DeepSeek Harness 插件,不需要一开始就依赖某个神秘安装包。先理解 Harness 的层次结构,再手写一个最小闭环,后续无论接入 VS Code、命令行还是桌面端,都会很清楚哪里是模型 API,哪里是工具执行层,哪里只是前端表现。这个可控的最小骨架,就是“空城计”真正的价值:看起来像一座坚城,实际只是一小段扎实的代码,但足以让你在更大工程面前不慌不乱。

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

Cesium相机完全指南:从setView、flyTo到lookAt的实战笔记

很多刚接触Cesium的人,都是从加载地球、贴个多边形开始的。但玩到后面你会发现,整个场景其实就是一台虚拟摄像机在三维空间里取景,你做的所有操作——旋转、缩放、飞行、漫游,本质都是在对Cesium的camera对象编程。用好相机&#…

作者头像 李华
网站建设 2026/9/8 11:45:38

uncorr. ECC显示2是什么意思?内存纠错原理与故障排查指南

最近在机房处理一台运行中的服务器,管理界面弹出一条告警:uncorr. ECC 显示2。监控已经标红,但业务还没挂。很多人看到“ECC”两个字,第一反应就是“内存坏了,赶紧换”。这个判断方向没错,但太粗糙。ECC全称…

作者头像 李华
网站建设 2026/9/8 11:42:48

CMSIS-DSP源码深度剖析:从架构设计到工业固件落地实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/8 11:41:11

本地部署开源AI模型实战:从文生图到OCR的全流程指南

抱歉,这个任务我无法完成。 您提供的项目标题是“One of the Most Important Policy Decisions of Our Lifetime”,这是一个政治/政策议题类的话题,而不是一个技术项目、开源工具或模型。这与我的任务定位(撰写 CSDN 技术博客&am…

作者头像 李华
网站建设 2026/9/8 11:40:50

ComfyUI秋叶整合包安装与工作流实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/8 11:40:09

2026正规的免费阅读平台盘点 正版资质核验方法指南

正规免费阅读平台核心判定标准随着数字阅读需求的持续增长,免费阅读平台成为大众获取网文内容的主要渠道,但非正规平台带来的各类风险也不容忽视。2025年文旅部查处的违法违规网络文化平台案例显示,非正规免费阅读平台普遍存在四类典型问题&a…

作者头像 李华