TravelContentCreator/docs/REFACTORING_IMPLEMENTATION.md

350 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 技术债务重构实施文档
> 本文档记录技术债务改进的具体实施过程
---
## 实施计划
| # | 改进项 | 状态 | 完成时间 |
|---|-------|------|---------|
| 1 | 数据库访问改接口 | ✅ 完成 | 2024-12-08 |
| 2 | 图片传输改 URL | ✅ 完成 | 2024-12-08 |
| 3 | 放弃 ppid | ✅ 完成 | 2024-12-08 |
| 4 | Prompt Registry | ✅ 完成 | 2024-12-08 |
| 5 | 依赖注入统一 | ✅ 完成 | 2024-12-08 |
---
## 1. 数据库访问改接口
### 目标
Python 端不再直接连接数据库,所有数据由 Java 端通过 HTTP 接口传递。
### 改动前架构
```
┌─────────────┐ ┌─────────────┐
│ Java 端 │ │ Python 端 │
└──────┬──────┘ └──────┬──────┘
│ │
│ 各自连接 │ 各自连接
▼ ▼
┌─────────────────────────┐
│ MySQL │
└─────────────────────────┘
```
### 改动后架构
```
┌─────────────┐ ┌─────────────┐
│ Java 端 │ ──── HTTP ────────>│ Python 端 │
└──────┬──────┘ (完整数据) └─────────────┘
│ │
│ 唯一数据源 │ 无数据库访问
▼ │
┌─────────────────────────┐ │
│ MySQL │ X
└─────────────────────────┘
```
### 新的接口协议
Java 端调用 Python 端时,传递完整数据:
```json
{
"engine": "topic_generate",
"params": {
"num_topics": 5,
"month": "2024-12",
// 直接传完整对象,而不是 ID
"scenic_spot": {
"id": 1,
"name": "天津冒险湾",
"description": "主题乐园...",
"location": "天津市"
},
"product": {
"id": 10,
"name": "门票套餐",
"price": 299,
"description": "..."
},
"style": {
"id": 5,
"name": "攻略风",
"description": "实用性强..."
},
"audience": {
"id": 3,
"name": "亲子家庭",
"description": "..."
}
}
}
```
### 实施步骤
1. [x] 定义新的参数 Schema
2. [x] 创建 V2 引擎接收完整对象
3. [x] V2 引擎不访问数据库
4. [ ] 更新 Java 端调用方式 (待 Java 端配合)
### 已创建文件
- `domain/aigc/engines/topic_generate_v2.py` - 选题生成 V2
- `domain/aigc/engines/content_generate_v2.py` - 内容生成 V2
- `domain/aigc/engines/poster_generate_v2.py` - 海报生成 V2
---
## 2. 图片传输改 URL
### 目标
不再传递 Base64改为传递图片 URL 或路径。
### 新的接口协议
```json
{
"engine": "poster_generate",
"params": {
"template_id": "vibrant",
// 方式1: S3 URL
"image_urls": [
"https://s3.xxx.com/bucket/image1.jpg",
"https://s3.xxx.com/bucket/image2.jpg"
],
// 方式2: 本地路径 (如果共享存储)
"image_paths": [
"/data/images/123.jpg"
],
// 方式3: 素材 ID (Python 自行获取)
"material_ids": [123, 456]
}
}
```
### 实施步骤
1. [x] 修改引擎支持 URL 下载
2. [x] 添加图片下载工具 (aiohttp)
3. [ ] 更新 Java 端传参方式 (待 Java 端配合)
### 已实现
`PosterGenerateEngineV2` 支持三种图片来源:
- `image_urls` - 从 URL 下载 (推荐)
- `image_paths` - 从本地路径读取
- `images_base64` - Base64 (兼容旧接口)
---
## 3. 放弃 ppid
### 目标
不再使用 ppidJava 端直接传递解析后的完整数据。
### 改动
- 移除 Python 端的 `resolve_ppid()` 逻辑
- 移除 `ProductPackageRepository`
- 引擎参数 Schema 中移除 `ppid`
### 实施步骤
1. [x] V2 引擎不包含 ppid 参数
2. [x] V2 引擎不访问 ProductPackageRepository
3. [x] 参数 Schema 只接收完整对象
### 说明
V2 引擎的参数 Schema 中没有 `ppid`,只接收:
- `scenic_spot` - 完整景区对象
- `product` - 完整产品对象
- `style` - 完整风格对象
- `audience` - 完整受众对象
Java 端需要在调用前解析 ppid 并传递完整数据。
---
## 4. Prompt Registry
### 目标
集中管理 Prompt支持版本化。
### 目录结构
```
prompts/
├── topic_generate/
│ └── v1.0.0.yaml
├── content_generate/
│ └── v1.0.0.yaml
└── content_judge/
└── v1.0.0.yaml
```
### 实施步骤
1. [x] 创建 `domain/prompt/` 模块
2. [x] 实现 `PromptRegistry`
3. [x] 迁移现有 prompt 到 YAML
4. [x] V2 引擎使用新 Registry
### 已创建文件
**模块:**
- `domain/prompt/__init__.py`
- `domain/prompt/registry.py` - PromptRegistry 实现
**Prompt 配置:**
- `prompts/topic_generate/v1.0.0.yaml`
- `prompts/content_generate/v1.0.0.yaml`
- `prompts/content_judge/v1.0.0.yaml`
### 使用示例
```python
from domain.prompt import PromptRegistry
registry = PromptRegistry('prompts')
# 渲染 prompt
system, user = registry.render(
'content_generate',
context={'style_content': '...', 'demand_content': '...', ...},
version='latest'
)
# 获取模型参数
config = registry.get('content_generate')
params = config.get_model_params() # {'temperature': 0.3, ...}
```
---
## 5. 依赖注入统一
### 目标
统一使用容器模式管理依赖。
### 实施步骤
1. [x] 创建 `Container`
2. [x] 实现服务注册和获取
3. [ ] 逐步迁移现有依赖获取方式 (渐进式)
### 已创建文件
- `domain/container.py` - Container 实现
### 使用示例
```python
from domain.container import Container, get_service, inject
# 方式1: 直接获取
from core.config import ConfigManager
config = Container.get(ConfigManager)
# 方式2: 便捷函数
from domain import get_service
config = get_service(ConfigManager)
# 方式3: 装饰器注入
@inject(ConfigManager, AIAgent)
def my_function(config, agent, other_param):
...
```
### 说明
Container 采用渐进式迁移策略:
- 新代码使用 Container
- 旧代码保持不变,逐步迁移
- V2 引擎内部使用延迟加载,兼容两种方式
---
## 变更日志
| 日期 | 改动 | 文件 |
|-----|------|------|
| 2024-12-08 | 创建实施文档 | docs/REFACTORING_IMPLEMENTATION.md |
| 2024-12-08 | 创建 PromptRegistry | domain/prompt/registry.py |
| 2024-12-08 | 创建 Container | domain/container.py |
| 2024-12-08 | 创建 V2 引擎 | domain/aigc/engines/*_v2.py |
| 2024-12-08 | 迁移 Prompt 到 YAML | prompts/*.yaml |
---
## 新旧引擎对比
| 特性 | V1 引擎 | V2 引擎 |
|-----|--------|--------|
| 数据库访问 | ✅ 直接访问 | ❌ 不访问 |
| ppid 支持 | ✅ 自动解析 | ❌ 不支持 |
| 图片传输 | Base64 | URL/路径/Base64 |
| Prompt 管理 | 文件模板 | PromptRegistry |
| 依赖注入 | 延迟加载 | Container |
## Java 端调用示例
### V1 引擎 (旧)
```json
{
"engine": "topic_generate",
"params": {
"ppid": 12345,
"num_topics": 5
}
}
```
### V2 引擎 (新)
```json
{
"engine": "topic_generate_v2",
"params": {
"num_topics": 5,
"month": "2024-12",
"scenic_spot": {
"id": 1,
"name": "天津冒险湾",
"description": "..."
},
"product": {
"id": 10,
"name": "门票套餐",
"price": 299
}
}
}
```
---
## 待办事项
- [ ] Java 端更新调用方式,使用 V2 引擎
- [ ] 验证 V2 引擎功能正确性
- [ ] 清理 V1 引擎中的数据库访问代码 (可选)
- [ ] 删除 Python 端的 database_service.py (待确认无其他依赖)