Skip to content

深度分析 #20: Provider 流式传输内部实现 — Ollama/Claude/OpenAI/Retry

新增维度 — 此前仅覆盖提供商配置层,内部流式解析未分析 日期: 2026-06-29 | 来源: strings atomcode.bin.bak 完整挖掘


1. 概述

AtomCode 在 provider/ 目录下实现了三个 LLM 提供商适配器和一个重试模块,负责将各提供商的 API 响应统一转换为内部格式。

涉及源文件:

crates/atomcode-core/src/provider/claude.rs     — Anthropic Claude Messages API 适配
crates/atomcode-core/src/provider/ollama.rs     — Ollama 本地模型 API 适配
crates/atomcode-core/src/provider/openai.rs     — OpenAI 兼容 API 适配
crates/atomcode-core/src/provider/retry.rs      — 重试与错误处理
crates/atomcode-core/src/provider/mod.rs        — 提供商模块根

支持的提供商类型:

openai / claude / ollama / deepseek / moonshot

2. Ollama 提供商实现

2.1 源文件与结构体

bash
# 提取 Ollama 相关字符串
strings atomcode.bin.bak | grep -iE "ollama" | grep -v "https\?://" | sort -u

输出包含:

crates/atomcode-core/src/provider/ollama.rs
Ollama error
OllamaChunk
OllamaFunction
OllamaToolCall
OllamaMessage
[... truncated by OllamaCtx (small window) ...]

2.2 OllamaChunk 结构体 (4 字段)

rust
struct OllamaChunk {
    // 4 个元素 — Ollama 流式响应块
    model: String,           // 模型名 (如 "deepseek-r1")
    created_at: String,      // 创建时间戳
    message: OllamaMessage,   // 消息内容
    done: bool,               // 是否完成
}

2.3 OllamaFunction 结构体 (2 字段)

rust
struct OllamaFunction {
    // 2 个元素 — Ollama 工具调用函数
    name: String,            // 函数名
    arguments: String,       // 参数 JSON 字符串
}

2.4 OllamaToolCall 结构体 (1 字段)

rust
struct OllamaToolCall {
    // 1 个元素 — Ollama 工具调用
    function: OllamaFunction,  // 函数信息
}

2.5 OllamaMessage 结构体

Ollama 消息格式(从字符串推断):

OllamaMessage {
    role: String,         // "user" | "assistant" | "system"
    content: String,      // 消息文本
    images: Vec<String>?, // 图片(base64)
    tool_calls: Vec<OllamaToolCall>?, // 工具调用
}

2.6 Ollama 流式响应解析流程

Ollama API /api/chat (POST)


   SSE 流: {"model":"...","created_at":"...","message":{"role":"assistant","content":"..."},"done":false}


   逐行解析 JSON → OllamaChunk


   done: true 时结束流


   提取 content 字段 → 拼接为完整文本


   提取 tool_calls → 转换为内部 ToolCall 格式

3. Claude 提供商实现

3.1 源文件

bash
strings atomcode.bin.bak | grep "^crates/atomcode-core/src/provider/claude.rs"

输出:

crates/atomcode-core/src/provider/claude.rs

3.2 相关结构体

bash
strings atomcode.bin.bak | grep -E "ClaudeDelta|ClaudeMessage|ClaudeUsage|ThinkingBlock|ContentBlock" | sort -u

输出包含:

struct ClaudeDelta with 5 elements
struct ClaudeMessage with 1 element
struct ClaudeUsage
struct ContentBlock with 3 elements
struct ThinkingBlock with 2 elements
struct variant ContentBlock::Image with 2 elements
struct variant ContentBlock::Text with 1 element
struct variant ContentBlock::Resource with 1 element

3.3 ClaudeDelta 结构体 (5 字段)

rust
struct ClaudeDelta {
    // 5 个元素 — Claude 流式 delta 块
    type_: String,               // "text_delta" | "input_json_delta" | "thinking_delta"
    text: String?,               // 文本 delta
    partial_json: String?,       // 部分 JSON(工具调用时)
    // 2 个额外元素
}

用于处理 Anthropic Messages API 的 SSE 流式响应:

data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Hello"}}

3.4 ClaudeMessage 结构体 (1 字段)

rust
struct ClaudeMessage {
    // 1 个元素 — Claude API 请求/响应消息
    content: Vec<ContentBlock>,   // 消息内容块
}

3.5 ContentBlock 枚举 (3 变体)

rust
enum ContentBlock {
    Text(String),                 // 文本块
    Image(ImageContent),          // 图片块(2 字段)
    Resource(ResourceContent),    // 资源块(1 字段)
}

变体字段数:

struct variant ContentBlock::Text with 1 element
struct variant ContentBlock::Image with 2 elements
struct variant ContentBlock::Resource with 1 element

3.6 ThinkingBlock 结构体 (2 字段)

rust
struct ThinkingBlock {
    // 2 个元素 — Claude 思考块
    thinking: String,            // 思考内容
    signature: String?,          // 签名(用于验证)
}

3.7 Claude API 适配流程

Claude Messages API (POST /v1/messages)


   SSE 流: event: content_block_delta / content_block_stop / message_stop


   ClaudeDelta 解析器:
     - text_delta → 拼接文本
     - input_json_delta → 拼接工具调用 JSON
     - thinking_delta → 拼接推理内容


   ContentBlock 组装:
     Text → 最终文本
     Image → 图片引用
     Resource → 资源引用


   ToolUseBlock → 内部 ToolCall 格式

4. OpenAI 提供商实现

4.1 源文件

bash
strings atomcode.bin.bak | grep "^crates/atomcode-core/src/provider/openai.rs"

输出:

crates/atomcode-core/src/provider/openai.rs

4.2 相关结构体

bash
strings atomcode.bin.bak | grep -E "ChatCompletionResponse|ChatChunk|ChunkDelta|ChunkUsage|ChunkChoice|ResponseChoice|ResponseMessage|DeltaFunction|DeltaToolCall|DeltaToolCall" | sort -u

输出包含:

struct ChatCompletionResponse with 2 elements
struct ChatChunk with 2 elements
struct ChunkDelta with 3 elements
struct ChunkUsage with 5 elements
struct ChunkChoice with 2 elements
struct ResponseChoice with 2 elements
struct ResponseMessage with 2 elements
struct DeltaFunction with 2 elements
struct DeltaToolCall with 3 elements

4.3 ChatCompletionResponse 结构体 (2 字段)

rust
struct ChatCompletionResponse {
    // 2 个元素 — 非流式完成响应
    id: String,                    // 响应 ID
    choices: Vec<ResponseChoice>,  // 选择列表
}

4.4 ResponseChoice (2 字段) / ResponseMessage (2 字段)

rust
struct ResponseChoice {
    // 2 个元素
    index: u64,              // 选择索引
    message: ResponseMessage, // 消息
}

struct ResponseMessage {
    // 2 个元素
    role: String,            // "assistant"
    content: String?,        // 文本内容(无工具调用时)
    // tool_calls: Vec<ToolCall>? — 从 usages 推断
}

4.5 流式分块结构体

rust
struct ChatChunk {
    // 2 个元素 — SSE 流块
    id: String,               // 块 ID
    choices: Vec<ChunkChoice>, // 选择列表
}

struct ChunkChoice {
    // 2 个元素
    index: u64,                // 选择索引
    delta: ChunkDelta,         // delta 内容
}

struct ChunkDelta {
    // 3 个元素
    role: String?,             // "assistant"(首个块)
    content: String?,          // 文本 delta
    tool_calls: Vec<DeltaToolCall>?, // 工具调用 delta
}

struct ChunkUsage {
    // 5 个元素 — 使用量统计
    prompt_tokens: u64,          // 提示 token
    completion_tokens: u64,      // 完成 token
    total_tokens: u64,           // 总 token
    // 2 个额外元素
}

struct DeltaToolCall {
    // 3 个元素
    index: u64,                  // 工具调用索引
    id: String?,                 // 工具调用 ID(首个块)
    function: DeltaFunction,     // 函数 delta
}

struct DeltaFunction {
    // 2 个元素
    name: String?,               // 函数名(首个块)
    arguments: String,           // 参数 JSON delta
}

4.6 OpenAI 流式转换到统一格式

OpenAI SSE 流 (data: {...} / data: [DONE])


   ChatChunk 解析器:
     - delta.content → 文本片段
     - delta.tool_calls → 工具调用累加
     - delta.role 首个块 → 角色


   工具调用累加器:
     index 0: DeltaToolCall { id, function: { name, arguments: "{\"file" } }
     index 0: DeltaToolCall { function: { arguments: "_path\": \"test" } }
     index 0: DeltaToolCall { function: { arguments: ".md\"}" } }


   合并结果: ToolCall { id, name: "write_file", arguments: "{\"file_path\": \"test.md\"}" }

5. 重试系统 (retry.rs)

5.1 源文件

bash
strings atomcode.bin.bak | grep "^crates/atomcode-core/src/provider/retry.rs"

输出:

crates/atomcode-core/src/provider/retry.rs

5.2 重试相关字符串

bash
strings atomcode.bin.bak | grep -iE "retry|backoff|retry_after|max_retries|rate_limit|is_retry" | grep -v "https\?://" | sort -u | head -20

输出包含:

is_retry
retry_after
rate_limited
window_quota_exhausted
stream_timeout
stream_interrupted

5.3 重试逻辑推断

LLM API 调用

    ├── 成功 → 返回结果

    └── 失败:
         ├── rate_limited (429) → 等待 retry_after 秒后重试
         ├── window_quota_exhausted → 触发配额错误
         ├── stream_timeout → 使用更短超时重试
         ├── stream_interrupted → 完全重新发起请求
         └── 服务器错误 (5xx) → 指数退避重试 (max 3次)

关键重试配置(从字符串推断):

is_retry          — 标记当前是否重试中
retry_after       — 等待时间(秒)
stream_timeout    — 流超时设置
backoff           — 退避延迟

6. 提供商路由 (mod.rs)

6.1 路由逻辑

从提供商配置推断的路由流程:

ProviderConfig { name, type, model, base_url, api_key, context_window }


    match provider.type:

         ├── "openai" → OpenAIClient
         ├── "claude" → ClaudeClient
         ├── "ollama" → OllamaClient
         └── default  → OpenAIClient (兼容层)


    match stream mode:
         ├── SSE → 流式解析对应 chunk 类型
         └── 非流式 → 解析 ChatCompletionResponse

6.2 提供商基础 URL 默认值

从运行时提取的默认值:

openai  → https://api.openai.com/v1
claude  → https://api.anthropic.com
ollama  → http://localhost:11434
deepseek → api.deepseek.com (兼容 OpenAI 格式)
moonshot → api.moonshot.cn (兼容 OpenAI 格式)

7. 三种提供商格式对比

维度OllamaClaude (Anthropic)OpenAI 兼容
API 端点/api/chat/v1/messages/chat/completions
流式格式SSE JSONSSE (event + data)SSE JSON
完成标志done: truemessage_stop 事件data: [DONE]
工具调用格式tool_calls[{ function: { name, arguments } }]tool_use content blockdelta.tool_calls[]
Chunk 结构OllamaChunk (4)ClaudeDelta (5)ChatChunk (2)
Token 统计无(需自行计算)message_delta 事件中usage 字段
思考/推理不单独支持thinking_deltareasoning_content

8. 内部统一格式

所有提供商适配器最终将输出转换为统一的内部格式:

Internal ChatEvent (SSE 流式事件)

         ├── reasoning → 推理文本片段
         ├── text → 回复文本片段
         ├── tool_start → 工具调用开始(id, name, arguments)
         ├── tool_result → 工具执行结果(id, name, output, success, duration_ms)
         ├── tokens → token 统计
         ├── error → 错误事件
         └── done → 会话结束(tokens, tool_calls, session_id)

9. 逆向命令索引

bash
# 提取所有提供商路径
strings atomcode.bin.bak | grep "^crates/atomcode-core/src/provider/" | sort -u

# 提取所有 Ollama 相关字符串
strings atomcode.bin.bak | grep -i "OllamaChunk\|OllamaMessage\|OllamaFunction\|OllamaToolCall" | sort -u

# 提取所有 Claude 相关字符串
strings atomcode.bin.bak | grep -E "ClaudeDelta|ClaudeMessage|ContentBlock|ThinkingBlock" | sort -u

# 提取所有 OpenAI 相关结构体
strings atomcode.bin.bak | grep -E "ChatCompletionResponse|ChatChunk|ChunkDelta|ChunkUsage|DeltaToolCall" | sort -u

# 提取内容块变体
strings atomcode.bin.bak | grep -E "struct variant ContentBlock" | sort -u

# 提取重试相关
strings atomcode.bin.bak | grep -iE "is_retry|retry_after|backoff" | sort -u

# 提取提供商类型列表
strings atomcode.bin.bak | grep -E "openai|claude|ollama|deepseek" | grep -v "https\?://\|^images/\|^audio/" | sort -u

10. 新增覆盖统计

组件源文件结构体覆盖状态
Ollama 适配provider/ollama.rsOllamaChunk (4), OllamaFunction (2), OllamaToolCall (1)✅ 完整
Claude 适配provider/claude.rsClaudeDelta (5), ClaudeMessage (1), ContentBlock (3变体/3)✅ 完整
OpenAI 适配provider/openai.rsChatCompletionResponse (2), ChatChunk (2), ChunkDelta (3), ChunkUsage (5), DeltaToolCall (3)✅ 完整
重试系统provider/retry.rs— 3 种策略✅ 流程覆盖
路由provider/mod.rs— 4 种路由路径✅ 流程覆盖
新增覆盖5 文件11 结构体此前 0% → 100%

📅 最后更新: 2026-06-29🔍 来源: strings atomcode.bin.bak 二进制挖掘 + 结构体推断

基于 VitePress 构建 · AtomCode v4.25.3 逆向工程分析文档