mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
docs(i18n): proofread active Chinese documentation
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write
|
||||
# pnpm run verify-translation-pairing --write docs/user/develop/practice/index.md
|
||||
index.md: e197d499d7f5bd9911ea60bebf584251cd4ed915
|
||||
index.zh.md: 8b8d08f9d0c6d0ca8d95fbaa3281c98b7a600fe4
|
||||
index.zh.md: cacf13e8b23060ea5c309d30e51d732f09c76000
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
[English](index.md) | 中文
|
||||
|
||||
当一个能力(插件)足够通用(比如"执行 bash 命令"),Harness 会把它拆成三个包:**接口**、**实现**、**消费者**。这样可以独立替换其中任何一层。
|
||||
当一项能力足够通用,需要支持可替换的实现时(例如 Bash 执行),Harness 会将其拆成三个包:**接口**、**实现**和**消费方**。这样便可独立替换其中任何一层。
|
||||
|
||||
## 以 Bash 为例
|
||||
|
||||
考虑 "Bash 执行" 这个能力:
|
||||
以 Bash 执行能力为例:
|
||||
|
||||
- **接口** (`dsh-bash`) — 定义"bash 执行"长什么样:输入是什么、输出是什么
|
||||
- **实现** (`dsh-bash-local`) — 真正在本地跑命令的代码
|
||||
- **消费者** (`dsh-tool-bash`) — 把这个能力包装成模型能调用的 tool
|
||||
- **接口** (`dsh-bash`):定义 Bash 请求和结果的结构
|
||||
- **实现** (`dsh-bash-local`):在本地计算机上执行命令
|
||||
- **消费方** (`dsh-tool-bash`):将该能力公开为模型可调用的工具
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌──────────────────┐ ┌──────────────┐
|
||||
@@ -38,23 +38,23 @@
|
||||
# endpoint: 'https://sandbox.example.com'
|
||||
```
|
||||
|
||||
接口不变、tool 不变,只换实现。
|
||||
更换实现时,接口和工具均保持不变。
|
||||
|
||||
### 独立演进
|
||||
|
||||
- 接口定义稳定后很少改动
|
||||
- 实现可以独立优化(性能、安全)
|
||||
- 消费者(tool)可以调整对模型的呈现方式
|
||||
- 消费方可以调整能力向模型呈现的方式。
|
||||
|
||||
### 依赖解耦
|
||||
|
||||
- 实现 depend on 接口
|
||||
- 消费者 depend on 接口
|
||||
- 实现和消费者**互不依赖**
|
||||
- 实现依赖接口。
|
||||
- 消费方依赖接口。
|
||||
- 实现和消费方**互不依赖**。
|
||||
|
||||
## Harness 中内置的三件套
|
||||
|
||||
| 能力 | 接口 (seam) | 实现 | 消费者 (tool) |
|
||||
| 能力 | 接口(seam) | 实现 | 消费方(工具) |
|
||||
|------|-------------|------|---------------|
|
||||
| Bash | `dsh-bash` | `dsh-bash-local` | `dsh-tool-bash` |
|
||||
| 文件系统 | `dsh-fs` | `dsh-fs-local` + `dsh-fs-policy` | `dsh-tool-fs` |
|
||||
@@ -115,7 +115,7 @@ export function apply(ctx: Context) {
|
||||
}
|
||||
```
|
||||
|
||||
### 第三步:编写消费者 (tool)
|
||||
### 第三步:编写消费方
|
||||
|
||||
```ts ignore-check
|
||||
// packages/my-cap/tool-my-cap/src/index.ts
|
||||
@@ -153,10 +153,10 @@ export function apply(ctx: Context) {
|
||||
|
||||
## 设计要点
|
||||
|
||||
- **不要预防性拆分** — 只有当你确实需要可替换实现时才拆三件套。一个简单的 tool 插件不需要拆分。
|
||||
- **接口定义 Request/Result 类型** — 实现和消费者只依赖接口包。
|
||||
- **Explicit > Implicit** — 实现中的默认值处理应该是显式的 `resolve(request): Spec` 步骤,不是隐藏在 `run()` 中的 `?? default`。
|
||||
- **不要预防性拆分**:只有确实需要可替换实现时,才拆分为三个包。简单的工具插件无需拆分。
|
||||
- **接口拥有 Request/Result 类型**:实现和消费方只依赖接口包。
|
||||
- **显式优于隐式**:实现应通过显式的 `resolve(request): Spec` 步骤处理默认值,而不是在 `run()` 中隐藏 `?? default`。
|
||||
|
||||
## 下一步
|
||||
|
||||
- [LLM 适配器](./llm-adapter.md) — 实现一个 LLM 后端(最常见的 seam 扩展)
|
||||
- [LLM 适配器](./llm-adapter.md):实现一个 LLM 后端,这是一种常见的能力 seam 扩展
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/user/develop/practice/llm-adapter.md
|
||||
llm-adapter.md: 7445688530c1ba61e5c065f9f5e49db6498da5b1
|
||||
llm-adapter.zh.md: c30200314a01f7a61d48e3f47288013c31e5aef4
|
||||
llm-adapter.zh.md: e491bc0b6ef633b0b40cb094faf07fc84445c026
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
[English](llm-adapter.md) | 中文
|
||||
|
||||
本文介绍如何为 Harness 接入一个新的 LLM 提供方。
|
||||
本文介绍如何为 Harness 接入新的模型提供方。
|
||||
|
||||
## 概述
|
||||
|
||||
LLM 适配器是一个继承 `LlmAdapter` 的类,实现 `stream()` 方法,将 Harness 的统一请求格式转换为具体 API 的调用。
|
||||
LLM 适配器是一个继承 `LlmAdapter` 并实现 `stream()` 方法的类,它会将 Harness 的提供方无关请求转换为具体提供方的 API 调用,并将响应转换回 Harness 分片。
|
||||
|
||||
## 最小实现
|
||||
|
||||
@@ -51,7 +51,7 @@ export function apply(ctx: Context, config: Config) {
|
||||
|
||||
## StreamChunk 协议
|
||||
|
||||
`stream()` 必须按以下协议 yield chunk:
|
||||
`stream()` 必须按以下协议生成分片:
|
||||
|
||||
```ts
|
||||
import { CallId, type StreamChunk } from '@deepseek-ai/dsh-llm'
|
||||
@@ -102,17 +102,17 @@ async function* exampleChunks(): AsyncIterable<StreamChunk> {
|
||||
|
||||
### 关键规则
|
||||
|
||||
- 每个 `block-start` 必须有对应的 `block-end`
|
||||
- `index` 从 0 递增,标识内容块顺序
|
||||
- `tool-call-delta` 的 `argumentsDelta` 是 JSON 字符串的增量(可以一次 yield 全部,也可以分多次)
|
||||
- `finish` 必须是最后一个 chunk
|
||||
- `usage` 在 `finish` 之前 yield
|
||||
- 每个 `block-start` 都必须有与之对应的 `block-end`。
|
||||
- `index` 从 0 开始递增,用于标识内容块的顺序。
|
||||
- `tool-call-delta` 的 `argumentsDelta` 是原始 JSON 文本的增量,可以在一个分片中完整生成,也可以分多个分片生成。
|
||||
- `finish` 必须是最后一个分片。
|
||||
- `usage` 必须在 `finish` 之前生成。
|
||||
|
||||
## GenerateOptions
|
||||
|
||||
`stream()` 接收仓库导出的 `GenerateOptions`。它包含模型名、由适配器持有的推理强度 ID、对话历史、系统提示词、tool schema、生成参数、停止序列和中止信号;完整字段以 `@deepseek-ai/dsh-llm` 导出的 TypeScript 类型为准。适配器必须将支持的字段映射到具体 API;无法支持的字段应抛出带稳定 code 的 `LlmError`,不能静默丢弃。
|
||||
`stream()` 接收仓库导出的 `GenerateOptions`。它包含模型、适配器拥有的推理强度 ID、对话历史、系统提示词、工具 schema、生成参数、停止序列和中止信号;完整字段以 `@deepseek-ai/dsh-llm` 导出的 TypeScript 类型为准。适配器必须将支持的字段映射到具体 API;如果无法支持某个字段,应抛出带稳定 code 的 `LlmError`,不得静默丢弃。
|
||||
|
||||
请覆写 `resolveModel(provider, model, signal?)`,在一次查询中返回确切的提供方/模型身份以及可选的 `context` 和 `reasoning` 元数据。推理元数据包含有序的不透明 ID、展示名称,以及可选的配置默认值;请保留适配器给出的权威可选列表,包括其上游能力 API 返回的 `off`,而不要将这些值提升为核心枚举。异步查询必须响应这个可选信号,让取消和资源释放都能达到完全停稳。服务会校验聚合结果,并在调用 `stream()` 前拒绝显式指定但不受支持的推理强度;省略 `reasoning` 表示该模型没有可选的推理强度能力。
|
||||
请覆写 `resolveModel(provider, model, signal?)`,在一次查询中返回确切的提供方/模型身份以及可选的 `context` 和 `reasoning` 元数据。推理元数据包含有序的不透明 ID、展示名称,以及可选的配置默认值;请保留适配器给出的权威可选列表,包括其上游能力 API 返回的 `off`,不要将这些值提升为核心枚举。异步查询必须响应该可选信号,使取消和资源释放过程完全停稳。服务会校验聚合结果,并在调用 `stream()` 前拒绝显式指定但不受支持的推理强度;省略 `reasoning` 表示该模型没有可选的推理强度能力。
|
||||
|
||||
## 注册适配器
|
||||
|
||||
@@ -120,7 +120,7 @@ async function* exampleChunks(): AsyncIterable<StreamChunk> {
|
||||
ctx.llm.registerAdapter(['model-name-1', 'model-name-2'], adapter)
|
||||
```
|
||||
|
||||
第一个参数是该适配器支持的模型名列表。当用户在 `cordis.yml` 中配置 `model: model-name-1` 时,框架会路由到这个适配器。
|
||||
第一个参数是该适配器支持的模型名列表。当用户在 `cordis.yml` 中配置 `model: model-name-1` 时,框架会将请求路由到该适配器。
|
||||
|
||||
## 在 cordis.yml 中使用
|
||||
|
||||
@@ -145,7 +145,7 @@ ctx.llm.registerAdapter(['model-name-1', 'model-name-2'], adapter)
|
||||
|
||||
## 实战参考
|
||||
|
||||
仓库中有两个完整实现可供参考:
|
||||
仓库中包含以下两个完整实现:
|
||||
|
||||
- `packages/llm/llm-deepseek/` — DeepSeek API 适配器(OpenAI 兼容格式)
|
||||
- `packages/llm/llm-pi-ai/` — Pi AI 适配器(不同的 API 格式)
|
||||
@@ -154,7 +154,7 @@ ctx.llm.registerAdapter(['model-name-1', 'model-name-2'], adapter)
|
||||
|
||||
## 错误处理
|
||||
|
||||
适配器应将传输和协议故障作为带稳定 code 的 `LlmError` 抛出;agent loop 会保留该错误及其 code,供诊断和策略使用。不要依赖普通 `Error` 被自动转换。每个提供方 HTTP 请求还必须合并 `attributionHeaders()`,并传递 `options.signal`。
|
||||
适配器应通过带稳定 code 的 `LlmError` 抛出传输和协议故障;agent loop(智能体循环)会保留该错误及其 code,用于诊断和策略处理。不要依赖普通 `Error` 被自动转换。每个提供方 HTTP 请求还必须合并 `attributionHeaders()`,并传递 `options.signal`。
|
||||
|
||||
```ts
|
||||
import {
|
||||
|
||||
Reference in New Issue
Block a user