LLM 适配器:厂商协议译成 harness 词汇

Agent Loop 调用 ctx.llm.stream() 时,底下可能是 DeepSeek、OpenAI 或别的厂商,SSE 格式各不相同。DeepSeek-Harness(dsh)把「消息 / 内容块 / StreamChunk」定为提供方无关的词汇表,具体协议由适配器翻译。换厂商等于换适配器,Loop 与会话日志只认世界语。

LLM 适配器桥接厂商与 harness

词汇表与适配器

ctx.llm 定义 Message、Content Block(textreasoningtool-calltool-result 等)和流式分片:block-starttext-deltafinish 等。适配器如 dsh-llm-deepseekdsh-llm-pi-ai 实现同一 LlmAdapter 接口,在挂载时注册到路由表。

1
2
3
4
- name: '@deepseek-ai/dsh-llm'
- name: '@deepseek-ai/dsh-llm-deepseek'
config:
apiKeyEnv: DEEPSEEK_API_KEY
1
2
3
4
5
6
7
for await (const chunk of ctx.llm.stream({
provider: 'deepseek-official',
model: 'deepseek-v4-flash',
messages: [/* ... */],
})) {
// StreamChunk
}

每个流恰好以一个终止 finish 结束:stoptool-callsmax-tokens,或带稳定错误码的 error / aborted。消费方按 failure.code 路由(RATE_LIMITNO_ADAPTERCONTEXT_WINDOW_EXCEEDED 等),不解析消息文本。

冻结、组装与重试边界

stream() 查找路由、对照精确模型能力校验、把请求深度冻结后再委派适配器——保证「模型可见即已记录」,扩展改不了已发出的请求快照。BlockAssembler 是唯一分片组装算法:可宽容地从纯 text-delta 建 partial,已对 block-end 关闭的块再来的 delta 会被忽略。

ctx.llm 从不自己重试;一次 stream 就是一次提供方尝试。重试落在 @deepseek-ai/dsh-llm-retry,挂在 Agent 失败步骤扩展点上,策略可按厂商替换。适配器卸载时路由从注册表消失,仍是 Cordis 可逆副作用。

核心在 packages/llm/llm/types.ts 定协议,assembler.ts 拼块,error.ts / adapter-failure.ts 归一化终止分片。模型一旦发出 tool-call,执行走 ctx.tools 的统一流水线——下一章拆那条传送带。

LLM 适配器:厂商协议译成 harness 词汇

https://simonsu.net/2026/09/16/dsh-06-llm-adapter/

Author

simonisacoder

Posted on

2026-09-16

Licensed under

Comments