//! LLM Provider 抽象接口 —— trait 定义与能力元数据。 //! //! 独立于具体 provider 实现(OpenAI / Anthropic / DeepSeek / Qwen / Ollama), //! 仅依赖 `llm` feature,不引入 `reqwest`。纯 Mock 场景可仅启用 `llm` feature。 use std::pin::Pin; use futures_core::Stream; use serde::{Deserialize, Serialize}; use crate::llm::error::LlmError; use crate::llm::types::request_v2::MessageRequest; use crate::llm::types::response_v2::{MessageResponse, StreamEvent}; /// Provider 能力描述 —— 静态元信息,调用方据此决定可用特性。 /// /// 设计依据(见 `docs/10-llm-provider-refinement.md` §4 任务 6 决策): /// `ProviderCapabilities` 与 trait 同文件,不分散到类型目录。 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ProviderCapabilities { /// 人类可读的 Provider 名(如 `"openai"` / `"anthropic"`)。 pub provider_name: &'static str, /// 支持的模型列表(`None` 表示"未列举全部")。 pub supported_models: Option>, /// 详细功能开关。 pub features: ProviderFeatures, } /// Provider 功能开关集合。 #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct ProviderFeatures { /// 是否支持流式响应。 pub streaming: bool, /// 是否支持 thinking / 推理。 pub thinking: bool, /// 是否支持图片输入。 pub vision: bool, /// 是否支持音频输入。 pub audio_input: bool, /// 是否支持工具调用。 pub tool_use: bool, /// 是否支持并行工具调用。 pub parallel_tool_calls: bool, /// system prompt 是否放在 messages 中(`true`)还是顶层 `system` 字段(`false`)。 pub system_prompt_in_messages: bool, /// 模型上下文窗口(tokens);`0` 表示未知。 pub max_context_window: u32, } /// LLM Provider 抽象接口。 /// /// 所有具体的 LLM 后端实现(OpenAI、Anthropic、DeepSeek、Qwen 等) /// 均需实现此 trait,以实现可插拔替换。 /// /// 修订(Phase 0):签名由 `chat(ChatRequest) → ChatResponse` 切换为 /// `chat(MessageRequest) → MessageResponse`,`chat_stream` 返回新 `StreamEvent` 流, /// 新增 `capabilities()` 方法。 #[async_trait::async_trait] pub trait LlmProvider: Send + Sync { /// 发送聊天请求并返回完整响应。 async fn chat(&self, request: MessageRequest) -> Result; /// 流式聊天请求 —— 返回新 IR `StreamEvent` 流。 async fn chat_stream( &self, request: MessageRequest, ) -> Result> + Send>>, LlmError>; /// 返回 Provider 静态能力描述。 fn capabilities(&self) -> ProviderCapabilities; }