# 功能规范：统一 LLM API 路由 (Unified LLM API Router)

**功能分支**: `001-unified-api-router`  
**创建日期**: 2026-01-12  
**状态**: 草稿 (Draft)  
**输入**: 用户描述: "llm-api-router 开发文档... (略)" 以及补充要求 "脚本中的注释都要使用简体中文,其次你总是使用中文与我沟通,包括spec,requirements,plan,tasks 都要使用中文"

## 用户场景与测试 *(必填)*

### 用户故事 1 - 基础提供商集成 (优先级: P1)

作为一名使用 `llm-api-router` 库的开发者，我希望能够使用统一的配置模式初始化一个标准提供商（如 OpenAI）的客户端，以便我可以发送基本的补全请求，而无需处理原始 HTTP 请求或特定的提供商 SDK。

**优先级理由**: 这是核心功能。如果没有基本的请求处理能力，路由库就没有任何价值。

**独立测试**: 可以通过配置一个模拟提供商并成功接收标准化的文本响应来进行完整测试。

**验收场景**:

1. **给定** 一个有效的 API 密钥和 OpenAI 的 `ProviderConfig`，**当** 我初始化 `Client` 并调用 `chat.completions.create` 时，**那么** 我会收到一个包含生成文本的 `UnifiedResponse` 对象。
2. **给定** 一个无效的 API 密钥，**当** 我尝试相同的调用时，**那么** 系统会抛出一个统一的 `AuthenticationError`（而不是原始的 HTTP 401 错误）。

---

### 用户故事 2 - 零代码模型切换 (优先级: P1)

作为一名开发者，我希望仅通过更改配置就能将后端模型从一个提供商（例如 OpenAI）切换到另一个（例如 Azure OpenAI 或 Anthropic），以便我的应用程序逻辑与特定的模型提供商保持严格解耦。

**优先级理由**: 这解决了项目“统一”和“屏蔽差异”的目标。

**独立测试**: 定义两个具有不同原始 API 模式的模拟提供商。为提供商 A 配置客户端，运行请求。重新配置为提供商 B，运行相同的请求。两者都应成功并返回相同的结构。

**验收场景**:

1. **给定** 一个与提供商 A 正常工作的应用程序集成，**当** 我更新配置以指向提供商 B 时，**那么** `chat.completions.create` 调用应该成功，且无需更改任何代码参数。
2. **给定** 一个带有标准参数（例如 `temperature=0.7`）的请求，**当** 发送到使用不同参数名称的提供商（如果有）时，**那么** 路由库会自动正确映射参数。

---

### 用户故事 3 - 统一流式支持 (优先级: P2)

作为一名构建聊天界面的开发者，我希望使用标准的 Python 迭代器（异步/同步）来消费流式响应，这样我就不必为每个提供商编写不同的流解析逻辑（例如解析 SSE 行与 JSON 块）。

**优先级理由**: 流式传输对于“适用场景”中提到的现代 LLM 用户体验（聊天、RAG）至关重要。

**独立测试**: 模拟流式 API 响应（Server-Sent Events）。验证客户端是否生成 `UnifiedChunk` 对象。

**验收场景**:

1. **给定** 一个带有 `stream=True` 的请求，**当** 我迭代响应时，**那么** 我会收到一系列标准化的块对象。
2. **给定** 一个流中断，**当** 连接断开时，**那么** 会抛出一个统一的 `StreamError`。

---

### 用户故事 4 - 异步支持 (优先级: P2)

作为一名构建高并发应用程序的开发者，我希望使用带有 `await` 语法的 `AsyncClient`，以便我可以并发处理多个 LLM 请求而不阻塞主线程。

**优先级理由**: “技术选型”中的明确要求 (`asyncio`, `httpx.AsyncClient`)。

**独立测试**: 在 `asyncio.gather` 中运行多个请求。

**验收场景**:

1. **给定** 一个 `AsyncClient`，**当** 我 await `chat.completions.create` 时，**那么** 执行不会阻塞事件循环。

## 需求 *(必填)*

### 功能需求

- **FR-001**: 系统**必须**暴露同步 (`Client`) 和异步 (`AsyncClient`) 客户端接口，以支持多种并发模型。
- **FR-002**: 系统**必须**提供统一的配置机制，用于设置不同提供商的 API 密钥、Base URL 和模型 ID。
- **FR-003**: 系统**必须**实现一个“聊天补全 (Chat Completion)”接口，该接口需镜像行业标准（类 OpenAI）的 API 设计。
- **FR-004**: 系统**必须**在所有支持的提供商之间归一化请求参数，包括 `messages`、`model`、`temperature`、`max_tokens` 和 `stream`。
- **FR-005**: 系统**必须**将响应体归一化为标准化的对象结构，包含 `id`、`created`、`model`、`choices`（包含 `message` 和 `finish_reason`）以及 `usage`。
- **FR-006**: 系统**必须**将提供商特定的 HTTP 状态码和错误体映射到统一的异常层级结构。
- **FR-007**: 系统**必须**支持 Server-Sent Events (SSE) 处理以用于流式响应，并将块归一化为一致的格式。
- **FR-008**: 系统**必须**具有可扩展性，允许通过插件或子类模式添加新的提供商，而无需修改核心路由逻辑。
- **FR-009**: 系统**不得**绑定具体的业务逻辑；它必须保持作为一个通用的工具库。
- **FR-010**: 系统**必须**确保代码库中的所有注释均为简体中文（根据用户补充要求）。

### 技术约束

- **TC-001**: 必须兼容 Python 3.10 或更高版本。
- **TC-002**: 必须使用 `httpx` 进行底层 HTTP 通信，以确保与现有异步生态系统的兼容性。
- **TC-003**: 必须支持 `asyncio` 进行异步执行。

### 关键实体 *(如果功能涉及数据)*

- **ProviderAdapter (提供商适配器)**: 负责将统一请求转换为特定于提供商的 HTTP 请求，反之亦然的抽象层。
- **UnifiedRequest (统一请求)**: LLM 调用的标准化内部表示。
- **UnifiedResponse (统一响应)**: LLM 结果的标准化内部表示。
- **RouterConfig (路由配置)**: 定义活动提供商和连接设置的配置对象。

## 成功标准 *(必填)*

### 可衡量的结果

- **SC-001**: 开发者可以通过仅更改配置值，在至少 2 个不同的提供商实现（例如 MockOpenAI 和 MockAnthropic）之间进行切换。
- **SC-002**: 开发者获得所有公共接口的完整 IDE 自动完成和静态分析支持（确保接口稳定性）。
- **SC-003**: 90% 的常见 HTTP 错误（401, 429, 500, 503）被正确映射到特定的、统一的 Python 异常类。
- **SC-004**: 路由引入的流式传输延迟开销每块小于 5ms。

### 边界情况

- **EC-001**: 处理不支持特定参数的提供商（例如，如果提供商忽略 `temperature`）。
- **EC-002**: 处理来自提供商的格式错误的 JSON 响应。
- **EC-003**: 网络超时和重试（应该可能是可配置的）。
