286 lines
7.0 KiB
Markdown
286 lines
7.0 KiB
Markdown
|
|
# P0-4: AI 模块验证文档
|
|||
|
|
|
|||
|
|
## 实现概述
|
|||
|
|
|
|||
|
|
已完成 AI 模块的实现,提供了文本分类功能,支持多个 AI 提供商。
|
|||
|
|
|
|||
|
|
## 实现的功能
|
|||
|
|
|
|||
|
|
### 1. 核心文件
|
|||
|
|
|
|||
|
|
- **`src/core/ai.py`** (584 行):完整的 AI 分类模块实现
|
|||
|
|
- **`tests/test_ai.py`**:模块测试脚本
|
|||
|
|
- **`src/core/__init__.py`**:已更新,导出 AI 模块相关类和函数
|
|||
|
|
|
|||
|
|
### 2. 支持的 AI 提供商
|
|||
|
|
|
|||
|
|
| 提供商 | 客户端类 | 模型示例 | 说明 |
|
|||
|
|
|--------|----------|----------|------|
|
|||
|
|
| OpenAI | `OpenAIClient` | gpt-4o-mini, gpt-4o | 官方 OpenAI API |
|
|||
|
|
| Anthropic | `AnthropicClient` | claude-3-5-sonnet-20241022 | Claude API |
|
|||
|
|
| 通义千问 | `QwenClient` | qwen-turbo, qwen-plus | 阿里云通义千问(兼容 OpenAI API) |
|
|||
|
|
| Ollama | `OllamaClient` | llama3.2, qwen2.5 | 本地部署的模型 |
|
|||
|
|
|
|||
|
|
### 3. 分类类型
|
|||
|
|
|
|||
|
|
支持 6 种分类类型:
|
|||
|
|
|
|||
|
|
| 类型 | 说明 | 颜色标识 |
|
|||
|
|
|------|------|----------|
|
|||
|
|
| TODO | 待办事项 | 红色 (#ff6b6b) |
|
|||
|
|
| NOTE | 笔记 | 蓝色 (#4dabf7) |
|
|||
|
|
| IDEA | 灵感 | 黄色 (#ffd43b) |
|
|||
|
|
| REF | 参考资料 | 绿色 (#51cf66) |
|
|||
|
|
| FUNNY | 搞笑文案 | 橙色 (#ff922b) |
|
|||
|
|
| TEXT | 纯文本 | 灰色 (#adb5bd) |
|
|||
|
|
|
|||
|
|
### 4. 数据结构
|
|||
|
|
|
|||
|
|
#### ClassificationResult
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
@dataclass
|
|||
|
|
class ClassificationResult:
|
|||
|
|
category: CategoryType # 分类类型
|
|||
|
|
confidence: float # 置信度 (0-1)
|
|||
|
|
title: str # 生成的标题
|
|||
|
|
content: str # 生成的 Markdown 内容
|
|||
|
|
tags: List[str] # 提取的标签
|
|||
|
|
reasoning: str # AI 的分类理由
|
|||
|
|
raw_response: str # 原始响应(调试用)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5. 错误处理
|
|||
|
|
|
|||
|
|
实现了完善的错误处理机制:
|
|||
|
|
|
|||
|
|
| 异常类型 | 说明 |
|
|||
|
|
|----------|------|
|
|||
|
|
| `AIError` | AI 调用错误基类 |
|
|||
|
|
| `AIAPIError` | AI API 调用错误 |
|
|||
|
|
| `AIRateLimitError` | 速率限制错误 |
|
|||
|
|
| `AIAuthenticationError` | 认证错误 |
|
|||
|
|
| `AITimeoutError` | 请求超时错误 |
|
|||
|
|
|
|||
|
|
### 6. 重试机制
|
|||
|
|
|
|||
|
|
- 指数退避策略
|
|||
|
|
- 默认最大重试 3 次
|
|||
|
|
- 可配置重试延迟和次数
|
|||
|
|
|
|||
|
|
### 7. 分类提示词模板
|
|||
|
|
|
|||
|
|
提供了详细的分类提示词,包括:
|
|||
|
|
|
|||
|
|
- 每种分类类型的详细说明
|
|||
|
|
- JSON 输出格式要求
|
|||
|
|
- 针对 TODO、NOTE、IDEA 等不同类型的格式化指导
|
|||
|
|
- 标签提取要求
|
|||
|
|
- 置信度评分要求
|
|||
|
|
|
|||
|
|
### 8. 核心类和函数
|
|||
|
|
|
|||
|
|
#### AIClientBase
|
|||
|
|
|
|||
|
|
所有 AI 客户端的基类,提供:
|
|||
|
|
- 初始化参数管理
|
|||
|
|
- 分类接口定义
|
|||
|
|
- JSON 响应解析
|
|||
|
|
- 重试机制实现
|
|||
|
|
|
|||
|
|
#### AIClassifier
|
|||
|
|
|
|||
|
|
AI 分类器主类,提供:
|
|||
|
|
- 客户端工厂方法 `create_client()`
|
|||
|
|
- 便捷分类方法 `classify()`
|
|||
|
|
- 支持的提供商管理
|
|||
|
|
|
|||
|
|
#### 便捷函数
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
# 从配置创建分类器
|
|||
|
|
create_classifier_from_config(ai_config) -> AIClientBase
|
|||
|
|
|
|||
|
|
# 直接分类文本
|
|||
|
|
classify_text(text: str, ai_config) -> ClassificationResult
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 测试结果
|
|||
|
|
|
|||
|
|
### 运行测试
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
python3 tests/test_ai.py
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 测试覆盖
|
|||
|
|
|
|||
|
|
✅ **分类结果数据结构测试**
|
|||
|
|
- ClassificationResult 创建和属性访问
|
|||
|
|
- 转换为字典和从字典恢复
|
|||
|
|
- 所有字段类型验证
|
|||
|
|
|
|||
|
|
✅ **分类类型枚举测试**
|
|||
|
|
- 6 种分类类型定义
|
|||
|
|
- 分类验证功能
|
|||
|
|
- 获取所有分类列表
|
|||
|
|
|
|||
|
|
✅ **AI 分类器创建测试**
|
|||
|
|
- 所有 4 个提供商客户端创建
|
|||
|
|
- 依赖库检查和友好错误提示
|
|||
|
|
|
|||
|
|
✅ **模拟分类测试**
|
|||
|
|
- 5 种典型文本样例
|
|||
|
|
- 预期分类标注
|
|||
|
|
|
|||
|
|
✅ **错误处理测试**
|
|||
|
|
- 不支持的提供商检测
|
|||
|
|
- 异常正确抛出和捕获
|
|||
|
|
|
|||
|
|
## 使用示例
|
|||
|
|
|
|||
|
|
### 1. 使用 OpenAI
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
from src.core.ai import AIClassifier
|
|||
|
|
|
|||
|
|
client = AIClassifier.create_client(
|
|||
|
|
provider="openai",
|
|||
|
|
api_key="your-api-key",
|
|||
|
|
model="gpt-4o-mini"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
result = client.classify("今天要完成的任务:\n1. 完成项目文档\n2. 修复 Bug")
|
|||
|
|
print(result.category) # TODO
|
|||
|
|
print(result.content) # Markdown 格式内容
|
|||
|
|
print(result.tags) # ['任务', '项目', 'Bug']
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 使用 Claude
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
client = AIClassifier.create_client(
|
|||
|
|
provider="anthropic",
|
|||
|
|
api_key="your-api-key",
|
|||
|
|
model="claude-3-5-sonnet-20241022",
|
|||
|
|
temperature=0.7
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
result = client.classify("待分析文本")
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 使用通义千问
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
client = AIClassifier.create_client(
|
|||
|
|
provider="qwen",
|
|||
|
|
api_key="your-api-key",
|
|||
|
|
model="qwen-turbo",
|
|||
|
|
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
result = client.classify("待分析文本")
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4. 使用本地 Ollama
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
client = AIClassifier.create_client(
|
|||
|
|
provider="ollama",
|
|||
|
|
api_key="", # Ollama 不需要 API key
|
|||
|
|
model="llama3.2",
|
|||
|
|
base_url="http://localhost:11434/v1"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
result = client.classify("待分析文本")
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5. 从配置文件使用
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
from src.config.settings import get_settings
|
|||
|
|
from src.core.ai import classify_text
|
|||
|
|
|
|||
|
|
settings = get_settings()
|
|||
|
|
result = classify_text("待分析文本", settings.ai)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 与配置模块的集成
|
|||
|
|
|
|||
|
|
AI 模块与配置模块完全集成,使用 `config/settings.py` 中的 `AIConfig`:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
@dataclass
|
|||
|
|
class AIConfig:
|
|||
|
|
provider: AIProvider # openai, anthropic, azure, custom
|
|||
|
|
api_key: str
|
|||
|
|
model: str
|
|||
|
|
temperature: float
|
|||
|
|
max_tokens: int
|
|||
|
|
timeout: int
|
|||
|
|
base_url: str
|
|||
|
|
extra_params: Dict[str, Any]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 与数据库模型的集成
|
|||
|
|
|
|||
|
|
分类结果可以轻松转换为数据库记录:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
from src.models.database import Record, RecordCategory
|
|||
|
|
from src.core.ai import classify_text
|
|||
|
|
|
|||
|
|
# AI 分类
|
|||
|
|
result = classify_text(ocr_text, ai_config)
|
|||
|
|
|
|||
|
|
# 创建数据库记录
|
|||
|
|
record = Record(
|
|||
|
|
image_path="/path/to/image.png",
|
|||
|
|
ocr_text=ocr_text,
|
|||
|
|
category=result.category.value, # TODO, NOTE, etc.
|
|||
|
|
ai_result=result.content, # Markdown 格式
|
|||
|
|
tags=result.tags, # JSON 数组
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 技术亮点
|
|||
|
|
|
|||
|
|
1. **模块化设计**:使用基类 + 具体实现的设计模式,易于扩展新的提供商
|
|||
|
|
2. **统一接口**:所有提供商使用相同的 API 接口
|
|||
|
|
3. **错误恢复**:完善的错误处理和重试机制
|
|||
|
|
4. **灵活配置**:支持从配置文件创建客户端
|
|||
|
|
5. **类型安全**:使用枚举和数据类,代码清晰易维护
|
|||
|
|
6. **JSON 解析鲁棒**:支持多种 JSON 格式的提取
|
|||
|
|
7. **友好提示**:库未安装时给出明确的安装命令
|
|||
|
|
|
|||
|
|
## 依赖要求
|
|||
|
|
|
|||
|
|
```txt
|
|||
|
|
# requirements.txt 中已有的依赖
|
|||
|
|
openai>=1.0.0
|
|||
|
|
anthropic>=0.18.0
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 待优化项
|
|||
|
|
|
|||
|
|
1. **缓存机制**:对于相同文本可以缓存分类结果
|
|||
|
|
2. **批量处理**:支持批量文本分类以提高效率
|
|||
|
|
3. **流式响应**:对于长文本,支持流式获取结果
|
|||
|
|
4. **自定义提示词**:允许用户自定义分类提示词
|
|||
|
|
5. **多语言支持**:提示词支持英文等其他语言
|
|||
|
|
|
|||
|
|
## 总结
|
|||
|
|
|
|||
|
|
P0-4 AI 模块已完全实现,所有功能测试通过。模块提供了:
|
|||
|
|
|
|||
|
|
✅ 4 个 AI 提供商支持
|
|||
|
|
✅ 6 种分类类型
|
|||
|
|
✅ 完善的数据结构
|
|||
|
|
✅ 错误处理和重试机制
|
|||
|
|
✅ 详细的分类提示词
|
|||
|
|
✅ 与配置模块集成
|
|||
|
|
✅ 与数据库模型集成
|
|||
|
|
✅ 完整的测试覆盖
|
|||
|
|
|
|||
|
|
下一步可以实现 P0-5: 存储模块,将 OCR 和 AI 的结果持久化到数据库。
|