Processor 与 LLM 适配
一次模型调用拆成两层:LLM 适配负责向提供方发起 streamText 并产出原始流事件;Processor 消费这些事件,写入 Message / Part,并向 runLoop 返回 continue、stop 或 compact。标题生成等少数路径可直接调 LLM 适配。先厘清三个词:
| 术语 | 含义 |
|---|---|
| LLM 适配 | 把会话语义翻译成某家提供方协议的那一层:组装 system / messages / tools、应用插件参数与请求头、选定语言适配器、发起流 |
| 语言适配器 | 统一模型接口在具体提供方上的实现:把统一请求翻译成该家的 HTTP 报文,再把该家的流事件翻译回统一事件(文本增量、tool-call、步边界、结束原因等) |
| 步(step) | 一次模型生成。SDK 在一次流式调用内可分多步:模型输出 tool-call、工具执行完,SDK 带着结果自动开始下一步;每步以 step-start 与 step-finish 为界 |
flowchart LR RL[runLoop] --> P[processor.process] P --> L[llm.stream] L --> E[流事件] E --> H[handleEvent 落库] H --> O{返回} O --> C[continue] O --> S[stop] O --> K[compact]| 层 | 职责 |
|---|---|
| LLM 适配 | 组装 system / messages / tools,应用插件参数与头,调用提供方流式接口 |
| Processor | 状态 busy、Part 增量、工具状态机、步边界、压缩信号、清理未闭合片段 |
LLM 适配步骤
Section titled “LLM 适配步骤”- 组装 system(角色提示、环境、技能、插件变换)。
- 触发参数与请求头类插件钩子。
- 使用本轮已过滤的工具表。
- 按模型选择语言适配器,调用
streamText。
各家的协议差异收敛在适配层,不下沉到 Processor:
- 消息形状:空消息、toolCallId 允许的字符集、思考字段名、prompt cache 标记、工具 JSON Schema 的写法、采样默认值都不同,统一在发出前修正。
- 因此 Processor 只面对统一事件形状(文本增量、tool-call、步边界、结束原因等),不需要按厂商写分支。
- 换提供方等价于换语言适配器与模型元数据:适配层之下换了实现,Processor 与外环不动。
模型标识优先级:调用方显式传入 → 会话最近用户消息上的模型 → 默认模型。工作流类特殊模型由提供方加载规则决定,不靠用户自然语言推断。
步边界是一次模型生成的起点与终点,也是用量、快照与治理的锚点:
| 边界 | Processor 的动作 |
|---|---|
| start-step | 记录快照锚点,写 step-start Part |
| finish-step | 结算本步 tokens 与 cost 并累计到助手消息,结束本次生成观测,写 step-finish Part,按需触发会话摘要与文件 patch,判断是否需要压缩 |
flowchart LR A[start-step 快照锚点] --> G[模型生成] G --> T[tool-call 与执行] T -->|SDK 带结果开始下一步| A G --> B[finish-step 结算与落库]这个边界之所以重要:
- 计费与用量按步累计,助手消息上的 tokens / cost 是各步之和。
- 文件变更 patch 与工具执行的快照范围以步为界,跨步不混。
- 协作治理的成本硬停落在步边界,而不是中断在飞任务:走到这里时本步的 Part、patch 与记账都已收尾,停下不留半截产物。
- 上下文接近上限的判定也在 finish-step 完成;标记后由
runLoop转入压缩。
需要固定 JSON 形态时,调用方在 prompt 输入中显式传入 format: { type: "json_schema", schema }。运行时不会因用户口头描述字段而自动注入 format。命中后通过专用结构化工具收口,结果写入助手消息,外环可提前结束。
Processor 事件处理
Section titled “Processor 事件处理”flowchart TD Start[start] --> Busy[会话 busy] Busy --> Text[text / reasoning 增量] Busy --> Tool[tool 输入 / 调用 / 结果] Busy --> Step[step 起止与 token] Step --> Sum[可选 SessionSummary] Tool --> Doom[循环调用检测等] Text --> End[finish / error] Tool --> End Step --> End收尾:
- 需要压缩 →
compact - 阻断或错误 →
stop - 否则 →
continue
上下文溢出类错误可转为需要压缩,而不是直接失败退出。清理阶段会闭合未完成的 text/reasoning,将未完成工具标为中止,并写入完成时间。
与外环的衔接
Section titled “与外环的衔接”| Processor 返回 | runLoop |
|---|---|
| continue | 进入 while 下一圈 |
| stop | 结束本次 loop |
| compact | 创建或排队 compaction,下圈优先处理 |
细节见runLoop 与上下文压缩与端到端主链路。
| 现象 | 优先看 |
|---|---|
| 提供方报错 / 超时 | 模型配置、适配器、请求头与参数钩子 |
| 有调用无 Part | Processor 事件是否到达、写存储是否失败 |
| 工具结果后不续问 | 返回值是 stop 还是 continue;是否还有未决 tool-call |
| 用量或费用对不上 | 各步是否都有 step-finish 结算;重试或换模是否另开了一次生成 |
| 期望 JSON 却未结构化 | 是否显式传了 json_schema format |
相关阅读: