DeepSeek Harness · 猫狗识别框架研究学习与实践指南

学习型项目 · 研究 · 实践

从一句话需求,到一套能跑、可验证、可复盘的 Cordis 插件系统 —— 用"搭建一个真实系统"的方式,彻底理解 dsh 框架「一切皆插件」的架构思想。

  • 交付物:web 系统 + dsh 插件 + ds-v4-flash API
  • 运行地址http://127.0.0.1:3080
  • 插件cat-dog-classify-plugin
  • 数据:50 猫图 + 50 狗图,批量识别 100% 正确,24 用例全过

目录

  1. 项目定位:为什么要做这个系统
  2. 制作过程:8 个阶段的完整旅程
  3. 工程结构:目录、架构与分工
  4. 项目构建结果:验收、测试与踩坑
  5. 框架知识地图:概念全景
  6. 进阶方向与学习闭环
  7. 附录:命令速查

1. 项目定位:为什么要做这个系统

DeepSeek Harness(dsh)是 DeepSeek AI 开源的 Agent 编排框架,核心口号只有五个字——一切皆插件:模型适配器、工具注册表、会话日志、HTTP 服务、Agent 主循环,都是插件。

本项目(猫狗识别)正是为理解这套思想而设计的:功能足够简单(上传图片 → 输出"猫"/“狗”),却要求你亲手走完插件开发的完整闭环——注册模型工具、注册 HTTP 路由、装配进 profile、验证插件树,并用真实 API 完成全链路联调。

📌 框架知识点(贯穿全程的核心概念)

插件(Plugin)→ 上下文(Context)→ 服务(Service)→ 可逆注册(Effect)→ 装配层(Patch)。
理解这五个概念,就理解了 dsh 插件化设计的骨架。

两条学习入口(同一份能力,两个入口)

入口面向对象走哪个管道
HTTP 接口 /api/cat-dog-classify浏览器页面node:http 处理器,插件自解析 multipart
模型工具 classify_pet_imageharness 会话中的 Agentdsh 工具管道(校验/权限/执行/日志由框架统一处理)

关键设计决策:两个入口复用同一个 ClassifierService 业务实例,业务逻辑只写一遍,互不复刻。


2. 制作过程:8 个阶段的完整旅程

这条旅程把"需求 → 设计 → UE → 规则 → 测试 → 插件 → 联调 → 验证"串成一条可复制的学习路线,每一步都产出可检验的文档或代码。

第 0 步:先想清楚,你要学什么

  • 产出:明确的目标与学习对象
  • 明确 dsh 是什么、为什么学它;项目定位为"通过构建一个小系统来理解插件框架"。此阶段没有文件,却决定了后续所有技术选型的基调。

第 1 步:把一句话需求变成规格

  • 产出doc/req-001-spec.md
  • FR-1~FR-7NFR-1~NFR-5AC-1~AC-7
  • 需求原文仅一句:“web 系统 + dsh 插件连接 ds-v4-flash API,识别猫狗图片”。学习型项目的第一课是先文档后代码:把模糊想法拆成功能需求、非功能需求、可检验的验收标准,并约定三条约束(插件优先 / 指令源唯一 / 以官方文档为准)。

📌 框架知识点

dsh 处于开发者预览阶段,API 可能变动。规格里预留"以安装版本官方文档为准"的兜底条款,并把 dsh --profile web --dump-config 的插件树输出作为最终验收依据 —— 这比任何文档都真实。

第 2 步:技术设计:搭建系统骨架

  • 产出doc/tech-design-spec.md
  • 分层架构双入口复用错误码表
  • 设计文档回答三个关键问题:分层架构(表现层/能力层/服务层/接入层)、双入口复用(工具与路由共享同一份 ClassifierService)、错误码表INVALID_IMAGE(400)FILE_TOO_LARGE(413)MODEL_TIMEOUT(504)MODEL_AUTH_ERROR(502)RESULT_PARSE_ERROR(502))。这张错误码表后来被"一处定义、处处引用"——设计文档、规则、前端、路由、测试用例全部一致。

第 3 步:UE 设计先行,原型即页面

  • 产出doc/ue-design-spec.mdweb/index.html
  • 单页 5 区域状态机 5 态错误映射
  • 流程值得学习:先出 UE 设计文档,人工确认后,才动手生成原型。单页 5 区域(标题→上传→操作→结果→页脚),视觉规范主色 #4D6BFE 呼应 DeepSeek 品牌,emoji 图标、零外部依赖(符合最小实现)。交互状态机 idle → preview → loading → success/error,5 个错误码逐一映射为友好中文提示。

web/index.html 单文件(HTML + 内联 CSS + 原生 JS):fetch POST /api/cat-dog-classify、FormData 字段 image、AbortController 60s 超时、所有动态文本 textContent 渲染(零 innerHTML 拼接模型输出)、loading 中换图会中止旧请求。

📌 框架知识点

页面是纯静态文件,最终由 dsh web 服务的 HTTP 层承载(插件注册路由把它挂出来)。所以前端不用自己起服务,接口与页面天然同源 —— 这正是"web 系统 + 插件"一体化的含义。

第 4 步:给 AI 协作者立规矩

  • 产出AGENTS.md + .qoder/rules/
  • 行为规范权限清单规则索引
  • 学习型项目里 AI 是最主要的协作者。AGENTS.md 定义行为规范(插件优先、最小实现、验证优先)、工具使用权限、插件加载策略、工作流约束与"关键事实速查表";.qoder/rules/ 提供四个按场景分工的规则(coding-standards、plugin-rules、api-contract、service-workflow),AGENTS.md 维护规则索引。

📌 框架知识点

配置文件也是学习框架的窗口 —— AGENTS.md 会被 dsh 加载这件事,本身就是"一切皆插件"的体现:指令加载是插件、技能发现是插件、规则消费也是插件。

第 5 步:测试用例先行

  • 产出test/test-cases.md + 100 张测试图
  • TC-01~TC-24LLM 可自动执行PASS/FAIL/BLOCKED
  • 在写插件之前先把验收合同定下来,并把它升级成 LLM 可自动执行的规格:每条用例结构化(编号/依赖/执行方式/可复制命令/精确断言/判定规则),判定仅三种输出 PASS / FAIL / BLOCKED(前提不满足不算失败)。测试数据:50 张猫图 + 50 张狗图,另加非法格式/超限文件的现场构造指令。写用例的过程就是反向梳理设计的过程。

第 6 步:插件开发:本旅程的核心

  • 产出plugins/cat-dog-classify-plugin/(四文件)+ 装配层
  • classifier.tstool.tsroute.tsindex.ts

先调研 API 再动手写码。 三个可靠信息源:官方文档与社区教程、npm 包的类型定义(.d.ts 就是最精确的 API 文档)、运行时验证(dsh --dump-config 看真实插件树)。

四个源文件的分工
文件角色要点
classifier.ts纯业务,零框架依赖校验 → base64 编码 → 提示词组装 → OpenAI 兼容调用(temperature=0、60s 超时)→ 归一化为"猫/狗"(歧义不猜测 → 抛 RESULT_PARSE_ERROR)。零依赖便于直接单测
tool.ts模型工具 classify_pet_imagedefineTool 声明 schema;required每属性required: true,不是 JSON Schema 的数组;工具只写业务
route.tsHTTP 路由node:http 语义,手工解析 multipart(boundary 切分 + Content-Disposition 提取 + 大小上限);错误码 → HTTP 状态映射(400/413/504/502)
index.ts装配入口 apply(ctx)inject = ['tools'] 必需依赖;ctx.effect 可逆注册工具;ctx.inject(['webServer']) 声明可选路由依赖
装配:让插件进入插件树

dsh 的插件树由多层 patch 叠加:bundle 层 → profile 的 cordis.patch.yml → --patch 覆盖层。本项目把装配写进项目根 dsh-patch.yml

# dsh-patch.yml
- insert:
    - id: cat-dog-classify
      name: 'file:///D:/szp/work/deepseek-harness/plugins/cat-dog-classify-plugin/index.ts'

并更新唯一指令源 command/start-web-command.md;用 dsh --profile web --dump-config 验证插件树中可见 id: cat-dog-classify

⚠️ 联调必踩的两个坑

模型名坑:设计文档里的占位名 ds-v4-flash-version 会 400。需先用密钥调 GET /models 探测真实模型列表,得到 deepseek-v4-flash-vision-exp(vision 多模态版)。

推理预算坑:该模型是推理模型,max_tokens=32 会让推理 token 吃光预算、content 为空,实测需 max_tokens=1024。→ 通过环境变量 DS_MODEL 覆盖模型名,密钥只走 DS_API_KEY

第 7 步:全链路验证:24 用例全过

  • 产出:验证报告(API 批量 / UI 自动化 / 异常注入 / Agent 工具调用)
  • 100% 正确单张 ~2s异常可构造

API 批量验证:100 张测试图逐张过 POST /api/cat-dog-classify,猫 50/50、狗 50/50,100% 正确,单张延迟约 2 秒。UI 浏览器自动化:逐条断言空态→预览→非法类型/超限拒绝→"识别中…“→成功展示。异常注入:把 DS_API_BASE 指向不可路由地址→504;去掉 DS_API_KEY→502;停服→前端"无法连接识别服务”。

📌 框架能力的最终证明

在 headless profile 会话中给 Agent 下达任务"识别 test/images/cat/cat_001.jpg 是猫还是狗",Agent 自主完成:读文件 → base64 编码 → 调用 classify_pet_image → 得到"识别结果:猫" → 回答"猫"。你写的工具,被另一个 AI 当成了它的手。

第 8 步:复盘:框架知识地图

  • 产出:概念全景与进阶方向(详见第 5 部分)
  • 把整个旅程对照框架概念做一次收束,形成可迁移到任何 dsh 插件开发任务的方法论,并指出进阶方向(事件钩子、自定义服务、正式发布为 npm 包、MCP 接入、多 Agent)。

3. 工程结构:目录、架构与分工

一份可导航的代码库地图,从总目录到文件分工,看懂"哪个文件负责什么"。

3.1 总目录结构

deepseek-harness/
├── AGENTS.md                          # Agent 行为准则(dsh 指令插件自动加载)
├── dsh-patch.yml                      # 装配层:把插件插入 dsh web profile 插件树
├── command/
│   └── start-web-command.md           # 启动命令唯一指令源
├── doc/                               # 文档区
│   ├── readme.md                      # 代码库导航入口
│   ├── ds-harness-doc.md              # 框架官方文档链接
│   ├── req-001.md                     # 原始需求(一句话需求)
│   ├── req-001-spec.md                # 需求规格说明书 REQ-001
│   ├── tech-design-spec.md            # 技术详细设计 TECH-DESIGN-001
│   ├── ue-design-spec.md              # 用户体验设计 UE-DESIGN-001
│   └── coach/                         # 教练式指南
│       ├── guide.md                   # 从 0 构建的学习指南(步骤式)
│       └── ds-harness-framework-dogcatclassify-research-study-practice.md  # 本文档
├── plugins/
│   └── cat-dog-classify-plugin/       # 核心交付物:猫狗识别 dsh 插件
│       ├── index.ts                   # 插件入口:apply(ctx) 注册服务
│       ├── classifier.ts              # ClassifierService 识别核心(零依赖)
│       ├── tool.ts                    # classify_pet_image 模型工具定义
│       ├── route.ts                   # /api/cat-dog-classify + 页面路由
│       ├── cordis.patch.yml           # 插件装配描述(bundle patch)
│       ├── package.json               # 包元信息(dsh.bundle 声明)
│       └── tsconfig.json              # TypeScript 配置
├── web/
│   └── index.html                     # 前端单页(原生 HTML+JS,无构建链)
├── test/
│   ├── test-cases.md                  # 测试用例集 TEST-001(LLM 可执行)
│   └── images/{cat,dog}/              # 各 50 张测试图片
├── .qoder/
│   ├── rules/                         # 项目规则(改代码前必读)
│   └── skills/start-web-service/      # 启停服务项目级技能
└── .test-loop/                        # 文档驱动测试的循环记录(产物)

3.2 分层架构

识别能力的分层设计,从浏览器到模型 API 一共四层,各层职责清晰、边界明确:

表现层   Web 页面(上传 / 预览 / 结果展示)
   │  HTTP POST /api/cat-dog-classify
   ▼
能力层   dsh 插件 cat-dog-classify-plugin
   ├─ 模型工具 classify_pet_image
   └─ HTTP 路由 /api/cat-dog-classify
   │  复用同一实例
   ▼
服务层   识别核心 ClassifierService
   ├─ 图片校验/编码
   └─ 提示词组装/结果解析
   │  OpenAI 兼容接口(图片 base64)
   ▼
接入层   ds-v4-flash 系列多模态 API(deepseek-v4-flash-vision-exp)

3.3 端到端数据流

web/index.html ──POST /api/cat-dog-classify──▶ cat-dog-classify-plugin ──▶ ds-v4-flash API
        ▲                                            │
        └────────── 识别结果 {"result":"猫"|"狗"} ────────┘
        同时:Agent 会话 ──ctx.tools──▶ classify_pet_image 工具(复用同一识别逻辑)

3.4 装配层(插件如何"插进"框架)

文件作用
dsh-patch.yml顶层装配:--patch overlay 把本地插件插入 web profile 插件树(用 file:///D:/... URL)
cordis.patch.yml插件自带 bundle patch,声明插件 id 与依赖服务(webServer、tools)
package.jsondsh.bundle.patch 字段关联装配文件;依赖 @deepseek-ai/cordisdsh-toolsdsh-host-webserver

4. 项目构建结果:验收、测试与踩坑

用可验证的数字与清单,说明"这套系统确实做成了、做对了"。

4.1 结果总览

指标数值
批量识别正确率(50 猫 + 50 狗)100%
测试用例 PASS(TC-01~TC-24)24/24
单张识别延迟~2s
验收标准(AC-1~AC-7)全部满足

4.2 验收标准(AC-1~AC-7)对照

编号验收项通过条件结果
AC-1服务启动执行启动命令后 dsh web 可用(http://127.0.0.1:3080)✅ 通过
AC-2插件加载插件树中可见 cat-dog-classify-plugin✅ 通过
AC-3图片识别-猫上传猫图输出"猫"✅ 通过
AC-4图片识别-狗上传狗图输出"狗"✅ 通过
AC-5Agent 工具调用Agent 可发现并调用"猫狗识别"工具✅ 通过
AC-6服务关闭可按技能流程干净关闭服务✅ 通过
AC-7文档交付需求规格文档交付完成✅ 通过

4.3 测试覆盖(TC-01~TC-24)

类别用例关键断言
服务类TC-01 / TC-02 / TC-13 / TC-14启动就绪、插件树可见、干净关闭、重复启动防护
API 类TC-03 ~ TC-09猫/狗批量识别、非法格式 400、超限 413、缺字段 400、超时 504、密钥缺失 502
单元类TC-10 / TC-12parseResult 归一化与歧义不猜测(8 项样例)
UI 类TC-15 ~ TC-21空态、预览、非法/超限拒绝、加载反馈、成功展示、服务不可达提示
静态检查TC-22 ~ TC-24无 innerHTML、5 错误码齐全、接口路径正确
Agent 类TC-11会话中出现 classify_pet_image 调用且回答含结论

4.4 关键事实速查表

启动命令npx @deepseek-ai/dsh --profile web --patch dsh-patch.yml
Web 地址http://127.0.0.1:3080
插件名cat-dog-classify-plugin
模型工具classify_pet_image(入参 {"image": string},出参 {"result": string}
HTTP 接口POST /api/cat-dog-classify(multipart/form-data,字段 image
模型标识deepseek-v4-flash-vision-exp(环境变量 DS_MODEL 可覆盖)
密钥环境变量DS_API_KEY
环境要求Node.js ^22.19.0 或 >=24.0.0

4.5 踩坑清单(完整记录)

这些坑是这趟旅程最宝贵的经验积累,每一个都有具体后果与解法:

后果解法
Node 24 type-stripping 不支持 TS 参数属性(constructor(public x)运行时 SyntaxError构造函数内显式赋值
占位模型名 ds-v4-flash-versionAPI 400 invalid_request_errorGET /models 探测,改 deepseek-v4-flash-vision-exp
推理模型 max_tokens=32推理吃光预算,content 为空max_tokens=1024
Windows 绝对路径装配ERR_UNSUPPORTED_ESM_URL_SCHEMEfile:///D:/... URL
dsh web 子命令不接受父级 --patchboot 报错--profile web --patch ... 形式
PowerShell 5.1 读 UTF-8 无 BOM 脚本中文注释乱码/匹配失败脚本存 BOM;响应断言用 UTF-8 hex 比对
npm --no-save 单包安装剪掉此前全部未记录包一次安装全部所需包(含可选原生依赖)
dsh Web UI 与业务页争抢 /UI 不可达按测试合同业务页占用 /;Agent 会话改用 headless 验证

5. 框架知识地图:概念全景

把工程动作翻译成框架概念,是这趟旅程真正的"学习成果"。

概念一句话理解本项目落点
Plugin能力单元,用 apply(ctx) 描述贡献index.ts 四文件
Context服务仓库,按 key 找服务而不 import 实现ctx.tools / ctx.webServer
Service具名能力,可被替换ToolRegistry、WebServer
Effect可逆注册,卸载自动回滚工具/路由注册的 disposer
inject声明依赖,服务就绪才执行['tools'] 必需、['webServer'] 按需
Profile/Bundle/Patch组合层,后层覆盖前层dsh-patch.yml overlay
dump-config真实插件树的"照妖镜"装配验收

你现在能做什么了

写一个模型工具、写一个 HTTP 路由、把插件装配进 web profile、验证插件树、用 headless 会话驱动 Agent、按 24 条用例做全量回归。这套流程可以迁移到任何 dsh 插件开发任务上。


6. 进阶方向与学习闭环

进阶方向

  • 事件钩子tools/pre-execute(权限门)、tools/post-execute(结果改写);
  • 自定义服务Service 子类对外提供 ctx.<key>
  • 正式发布:把插件做成 npm 包 + "dsh": {"bundle": {"patch": ...}}dsh plugin add 安装;
  • MCP 接入、多 Agent(spawn / fork / workflow)。

🔁 学习闭环

读文档 → 写规格 → 写设计 → 写测试 → 写插件 → 装配验证 → 注入异常 → 全量回归。每一步都留下可检验的产物,这就是"从 0 构建一个系统来学习框架"的正确姿势。


附录:命令速查

# 启动(唯一指令源 command/start-web-command.md)
npx @deepseek-ai/dsh --profile web --patch dsh-patch.yml

# 验证插件树
npx @deepseek-ai/dsh --profile web --patch dsh-patch.yml --dump-config

# 停止(Windows:定位 PID → 终止 → 复查端口释放)
netstat -ano | findstr :3080
Stop-Process -Id <PID> -Force

# 单张识别
curl.exe -s -F "image=@test\images\cat\cat_001.jpg" http://127.0.0.1:3080/api/cat-dog-classify

# headless 会话驱动 Agent
npx @deepseek-ai/dsh --profile headless --patch dsh-patch.yml "识别 test/images/cat/cat_001.jpg 是猫还是狗"

# 插件类型检查
npx tsc --noEmit -p plugins\cat-dog-classify-plugin\tsconfig.json

本文档基于 deepseek-harness 工程的真实交付物整理,供研究学习与实践复盘使用。

源码仓库:github.com/leo21cn/sharing-dsharness-dogcatclassify

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐