DeepSeek Harness LLM 适配器

2026-09-08 00:00    #AI   #工具   #DeepSeek  

LLM 适配器是继承 LlmAdapter 并实现 stream() 方法的类。它把 Harness 的提供方无关请求转换成具体提供方的 API 调用,再把响应转换回 Harness 的分片(StreamChunk)。

层级结构:顶层 agent-loop(消费提供方无关的流式生成服务)→ 中间 ctx.llm 注册表(维护 LlmAdapter 的抽象契约)→ 底层各适配器(对接不同 API 格式)。

最小实现

 1// 文件路径:src/my-llm-adapter.ts
 2import type { Context } from '@deepseek-ai/cordis'
 3import Schema from '@deepseek-ai/schemastery'
 4import { LlmAdapter, type GenerateOptions, type StreamChunk } from '@deepseek-ai/dsh-llm'
 5
 6// 适配器:继承抽象类,实现 stream()
 7class MyAdapter extends LlmAdapter {
 8  private apiKey: string
 9
10  constructor(apiKey: string) {
11    super()
12    this.apiKey = apiKey
13  }
14
15  // stream() 返回异步生成器,逐片产出 StreamChunk
16  async *stream(options: GenerateOptions): AsyncIterable<StreamChunk> {
17    // 1. Convert options.messages to the provider format.
18    // 2. Call the streaming API.
19    // 3. Convert the response into StreamChunk values.
20  }
21}
22
23// 插件配置:apiKey 与 providers 都必填
24export interface Config {
25  apiKey: string
26  providers: string[]
27}
28
29// 同名的 Schemastery schema,加载时校验配置
30export const Config: Schema<Config> = Schema.object({
31  apiKey: Schema.string().required(),
32  providers: Schema.array(Schema.string()).required(),
33})
34
35export const name = 'my-llm-adapter'
36// 声明依赖 llm 服务,保证 ctx.llm 已就绪
37export const inject = ['llm']
38
39export function apply(ctx: Context, config: Config) {
40  const adapter = new MyAdapter(config.apiKey)
41  // 把提供方路由列表绑定到这个适配器
42  ctx.llm.registerAdapter(config.providers, adapter)
43}

GenerateOptions:适配器收到什么

字段说明
provider选择已注册的适配器
model适配器拥有的模型 id,无需在启动时注册
messages对话历史
system prompt系统提示词
tools工具 schema
reasoning适配器拥有的推理强度 ID(可选)
signal中止信号,取消与资源释放用它完全停稳

适配器必须把支持的字段映射到具体 API。如果某个字段无法支持,应抛出带稳定 code 的 LlmError,不得静默丢弃;否则模型会拿到残缺的结果。

注册适配器

1ctx.llm.registerAdapter(['my-provider'], adapter)

在 cordis.yml 中使用

 1# 文件路径:cordis.yml
 2# 加载适配器插件,apiKey 从环境变量读取
 3- id: my-llm
 4  name: './src/my-llm-adapter.ts'
 5  config:
 6    apiKey: !!js process.env.MY_API_KEY
 7    providers:
 8      - my-provider
 9
10# 配置 agent-loop 使用新适配器的 provider 与 model
11- id: agent-loop
12  name: '@deepseek-ai/dsh-agent-loop'
13  config:
14    agents:
15      - id: main
16        provider: my-provider
17        model: my-model-v1

config.apiKey 从环境变量 MY_API_KEY 读取,不落盘。agent-loopagents.main 配置 provider 与 model,生成请求时命中新适配器。

实战参考

仓库有两个现成完整实现:llm-deepseek(适配 DeepSeek API,走 OpenAI 兼容格式)与 llm-pi-ai(适配 Pi AI,不同 API 格式)。

先读 llm-deepseek 再读 llm-pi-ai,最容易看出「契约不变、实现各异」的 seam 思想。

要点