feat(llm): 重写 Provider 适配层,支持 OpenAI Chat / Anthropic / DeepSeek / Qwen

重写 OpenaiChatProvider:移除 Phase 0 临时桥接,实现真实流式状态机
(ContentBlockStart / *Delta / ContentBlockEnd / ToolCallEnd),
MessageComplete.full_response 由 PartialMessageResponse::finalize 产出。

新增 AnthropicProvider:实现 Messages API + SSE 事件序列
(message_start → content_block_start → content_block_delta →
content_block_stop → message_delta → message_stop),
529(overloaded)映射为 RateLimit;thinking signature 由
partial.set_thinking_signature 内部写入。

新增 DeepSeekProvider / QwenProvider:OpenAI-compatible 协议的
newtype 包装,共享 GenericOpenaiProvider 的 HTTP / SSE / 转换逻辑;
Qwen 通过 extra_headers 注入 X-DashScope-SSE: enable。

新增 convert.rs 公共转换模块:从 Phase 0 cycle.rs / Phase 0
OpenaiProvider 桥接层提取 from_openai / to_openai /
content_to_blocks / blocks_to_content,避免跨 Provider 重复逻辑。

新增 wiremock dev-dependency + 14 个集成测试:
- OpenaiChatProvider:基础文本 / 401 / 500 / 流式 MessageComplete
- AnthropicProvider:基础 / 401 / 529 / 流式 SSE 序列 / max_tokens 默认值
- DeepSeek / Qwen:基础文本响应

171 个测试全部通过(之前 157,新增 14)。
This commit is contained in:
徐涛
2026-07-02 22:24:30 +08:00
parent 7c299f1cfd
commit a74c24b6fe
9 changed files with 2550 additions and 379 deletions
+21 -13
View File
@@ -1,4 +1,6 @@
pub mod anthropic;
pub mod openai;
pub mod openai_compat;
pub mod registry;
use std::pin::Pin;
@@ -57,23 +59,29 @@ pub fn create_provider(
config: ProviderConfig,
) -> Result<Box<dyn LlmProvider>, LlmError> {
match provider_type {
ProviderType::OpenaiChat => Ok(Box::new(openai::OpenaiProvider::new(
ProviderType::OpenaiChat => Ok(Box::new(openai::OpenaiChatProvider::new(
config.base_url,
config.api_key,
config.model,
))),
ProviderType::OpenaiResponse => Err(LlmError::Other(
"OpenaiResponse Provider 在 Phase 1 暂不实现;请使用 OpenaiChat".into(),
)),
ProviderType::Anthropic => Ok(Box::new(anthropic::AnthropicProvider::new(
config.base_url,
config.api_key,
config.model,
))),
ProviderType::DeepSeek => Ok(Box::new(openai_compat::DeepSeekProvider::new(
config.base_url,
config.api_key,
config.model,
))),
ProviderType::Qwen => Ok(Box::new(openai_compat::QwenProvider::new(
config.base_url,
config.api_key,
config.model,
))),
ProviderType::OpenaiResponse => {
unimplemented!("OpenAI Response Provider 将在 Phase 1 引入")
}
ProviderType::Anthropic => {
unimplemented!("Anthropic Provider 将在 Phase 1 引入")
}
ProviderType::DeepSeek => {
unimplemented!("DeepSeek Provider 将在 Phase 1 引入")
}
ProviderType::Qwen => {
unimplemented!("Qwen Provider 将在 Phase 1 引入")
}
}
}