Chapter 11

LLM Seam:模型适配器、流式协议与 DeepSeek Adapter

目标不是背 API,而是建立能从顶层设计一路推导到源码细节的心智模型。读完本章,你应该能解释“为什么这样设计”,而不仅是“代码在哪里”。

1. LLM seam 不是“封装 fetch”这么简单

Harness 需要一个统一消息与流式 chunk 词汇,让 loop 不知道当前 provider 是 DeepSeek、OpenAI-compatible 还是其他实现。Adapter 负责把统一请求翻译为 provider wire format,再把 SSE/stream 响应翻译回来。

2. DeepSeek Adapter 的责任边界

  • 序列化 harness message/tool schema 到 DeepSeek chat-completions。
  • 处理 reasoning content 与 tool-call 相关的 provider 约束。
  • 解析 SSE,转换为统一 StreamChunk。
  • 把 transport timeout、abort、malformed response 映射成稳定 LLM error。
  • 每次操作重新解析动态设置/凭据,而不是启动时冻结。

3. Retry 为什么不该偷偷写在 adapter 内

如果 adapter 自己在一个 stream 调用里重试,session 看到的“一个 step = 一个模型请求”可能失真。DSH 倾向把 retry 放到持久 step 边界,使失败与重试可观察、可恢复。

4. 设计自己的 adapter 时的最小接口

interface LlmAdapter {
  stream(req: ModelRequest, signal: AbortSignal): AsyncIterable<StreamChunk>
}

type StreamChunk =
  | { kind: 'text'; delta: string }
  | { kind: 'reasoning'; delta: string }
  | { kind: 'tool-call'; id: string; name: string; argsDelta: string }
  | { kind: 'finish'; reason: 'stop' | 'tool' | 'error' };
源码定位:DeepSeek LLM Adapter · packages/llm/llm-deepseek/README.md
打开官方源码/文档