# llm-connector 简化设计文档
## 项目定位
**llm-connector** 是一个专注于**协议适配**的轻量级 Rust 库。
### 核心职责
- ✅ **协议转换**:将不同 LLM 提供商的 API 转换为统一的 OpenAI 兼容格式
- ✅ **请求/响应标准化**:提供统一的数据结构
- ✅ **流式响应适配**:标准化 SSE 流处理
- ✅ **Provider 抽象**:可扩展的提供商接口
### 明确不做的事情
- ❌ 负载均衡(使用 nginx、HAProxy 等)
- ❌ 健康检查(使用外部监控)
- ❌ 熔断器(使用基础设施解决方案)
- ❌ 复杂路由(保持简单)
- ❌ 指标收集(使用 tracing/metrics)
- ❌ 请求队列/限流(使用专门的中间件)
## 架构设计
```
┌─────────────────────────────────────────┐
│ Client │
├─────────────────────────────────────────┤
│ Provider Registry │
├─────────────────────────────────────────┤
│ OpenAI │ Anthropic │ DeepSeek │ ... │
│ Provider│ Provider │ Provider │ │
└─────────────────────────────────────────┘
```
### 核心组件
1. **Client** - 主要入口点,处理请求分发
2. **Provider Registry** - 管理已注册的提供商
3. **Provider Trait** - 统一的提供商接口
4. **Types** - 标准化的请求/响应类型
## 代码结构
```
src/
├── lib.rs # 库入口
├── client.rs # 主客户端
├── config.rs # 配置管理
├── error.rs # 错误类型
├── types/ # 核心类型定义
│ ├── mod.rs
│ ├── request.rs # 请求类型
│ ├── response.rs # 响应类型
│ └── streaming.rs # 流式类型
├── providers/ # 提供商实现
│ ├── mod.rs
│ ├── base.rs # Provider trait
│ ├── openai.rs # OpenAI 提供商
│ ├── anthropic.rs # Anthropic 提供商
│ ├── deepseek.rs # DeepSeek 提供商
│ └── ...
└── utils/ # 工具函数
├── mod.rs
├── http.rs # HTTP 工具
└── streaming.rs # 流式工具
```
## 核心接口设计
### Provider Trait
```rust
#[async_trait]
pub trait Provider: Send + Sync {
/// 提供商名称
fn name(&self) -> &str;
/// 支持的模型列表
fn supported_models(&self) -> Vec<String>;
/// 同步聊天完成
async fn chat(&self, request: &ChatRequest) -> Result<ChatResponse, LlmConnectorError>;
/// 流式聊天完成
async fn chat_stream(&self, request: &ChatRequest) -> Result<ChatStream, LlmConnectorError>;
/// 检查模型是否支持
fn supports_model(&self, model: &str) -> bool {
self.supported_models().contains(&model.to_string())
}
}
```
### Client 接口
```rust
pub struct Client {
providers: HashMap<String, Box<dyn Provider>>,
config: Config,
}
impl Client {
/// 从环境变量创建客户端
pub fn from_env() -> Self;
/// 从配置创建客户端
pub fn with_config(config: Config) -> Self;
/// 聊天完成
pub async fn chat(&self, request: ChatRequest) -> Result<ChatResponse, LlmConnectorError>;
/// 流式聊天完成
pub async fn chat_stream(&self, request: ChatRequest) -> Result<ChatStream, LlmConnectorError>;
/// 列出支持的模型
pub fn list_models(&self) -> Vec<String>;
}
```
## 模型命名约定
支持两种格式:
1. **显式格式**:`provider/model`
- `openai/gpt-4`
- `anthropic/claude-3-5-sonnet-20241022`
- `deepseek/deepseek-chat`
2. **自动检测**:直接使用模型名
- `gpt-4` → `openai/gpt-4`
- `claude-3-haiku` → `anthropic/claude-3-haiku`
- `deepseek-chat` → `deepseek/deepseek-chat`
## 配置管理
### 环境变量
```bash
# OpenAI
OPENAI_API_KEY=sk-...
OPENAI_BASE_URL=https://api.openai.com/v1
# DeepSeek
DEEPSEEK_API_KEY=sk-...
DEEPSEEK_BASE_URL=https://api.deepseek.com/v1
# Anthropic
ANTHROPIC_API_KEY=sk-ant-...
ANTHROPIC_BASE_URL=https://api.anthropic.com
```
### 代码配置
```rust
let config = Config {
openai: Some(ProviderConfig {
api_key: "sk-...".to_string(),
base_url: Some("https://api.openai.com/v1".to_string()),
}),
deepseek: Some(ProviderConfig {
api_key: "sk-...".to_string(),
base_url: Some("https://api.deepseek.com/v1".to_string()),
}),
..Default::default()
};
```
## 错误处理
```rust
#[derive(thiserror::Error, Debug)]
pub enum LlmConnectorError {
#[error("Authentication failed: {0}")]
AuthenticationError(String),
#[error("Rate limit exceeded: {0}")]
RateLimitError(String),
#[error("Network error: {0}")]
NetworkError(String),
#[error("Invalid request: {0}")]
InvalidRequest(String),
#[error("Unsupported model: {0}")]
UnsupportedModel(String),
#[error("Provider error: {0}")]
ProviderError(String),
#[error("Streaming error: {0}")]
StreamingError(String),
}
```
## 流式处理
统一的流式接口,自动处理不同提供商的 SSE 格式差异:
```rust
let mut stream = client.chat_stream(request).await?;
while let Some(chunk) = stream.next().await {
let chunk = chunk?;
if let Some(content) = chunk.choices[0].delta.content.as_ref() {
print!("{}", content);
}
}
```
## 扩展新提供商
1. 实现 `Provider` trait
2. 注册到客户端
3. 添加配置支持
```rust
struct MyProvider {
config: ProviderConfig,
client: reqwest::Client,
}
#[async_trait]
impl Provider for MyProvider {
fn name(&self) -> &str { "myprovider" }
fn supported_models(&self) -> Vec<String> {
vec!["my-model-1".to_string(), "my-model-2".to_string()]
}
async fn chat(&self, request: &ChatRequest) -> Result<ChatResponse, LlmConnectorError> {
// 实现协议转换逻辑
todo!()
}
async fn chat_stream(&self, request: &ChatRequest) -> Result<ChatStream, LlmConnectorError> {
// 实现流式协议转换逻辑
todo!()
}
}
```
## 设计原则
1. **单一职责**:只做协议适配
2. **最小依赖**:保持依赖树简洁
3. **可组合性**:作为更大系统的构建块
4. **无魔法**:显式配置,清晰错误
5. **提供商平等**:不偏向任何特定提供商
这个设计确保了 llm-connector 专注于其核心价值:协议适配,而将其他复杂功能留给专门的工具和服务。