TravelContentCreator/docs/REFACTORING_IMPLEMENTATION.md

11 KiB
Raw Blame History

技术债务重构实施文档

本文档记录技术债务改进的具体实施过程


实施计划

# 改进项 状态 完成时间
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 端时,传递完整数据:

{
  "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. 定义新的参数 Schema
  2. 创建 V2 引擎接收完整对象
  3. 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 或路径。

新的接口协议

{
  "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. 修改引擎支持 URL 下载
  2. 添加图片下载工具 (aiohttp)
  3. 更新 Java 端传参方式 (待 Java 端配合)

已实现

PosterGenerateEngineV2 支持三种图片来源:

  • image_urls - 从 URL 下载 (推荐)
  • image_paths - 从本地路径读取
  • images_base64 - Base64 (兼容旧接口)

3. 放弃 ppid

目标

不再使用 ppidJava 端直接传递解析后的完整数据。

改动

  • 移除 Python 端的 resolve_ppid() 逻辑
  • 移除 ProductPackageRepository
  • 引擎参数 Schema 中移除 ppid

实施步骤

  1. V2 引擎不包含 ppid 参数
  2. V2 引擎不访问 ProductPackageRepository
  3. 参数 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. 创建 domain/prompt/ 模块
  2. 实现 PromptRegistry
  3. 迁移现有 prompt 到 YAML
  4. 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

使用示例

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. 创建 Container
  2. 实现服务注册和获取
  3. 逐步迁移现有依赖获取方式 (渐进式)

已创建文件

  • domain/container.py - Container 实现

使用示例

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 引擎 (旧)

{
  "engine": "topic_generate",
  "params": {
    "ppid": 12345,
    "num_topics": 5
  }
}

V2 引擎 (新)

{
  "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 (待确认无其他依赖)
  • 两端协调 ppid 废弃方案

6-12 问题改进记录

6. 临时文件清理

创建清理脚本 scripts/cleanup_temp_files.py

# 预览要删除的文件
python scripts/cleanup_temp_files.py --dry-run

# 清理 7 天前的临时文件
python scripts/cleanup_temp_files.py --days 7

# 清理指定目录
python scripts/cleanup_temp_files.py --dir result --days 3

7. 统一配置

创建 core/unified_config.py

from core import get_unified_config

config = get_unified_config()

# 获取配置值
db_host = config.get("database.host")

# 获取配置组
db_config = config.database
ai_config = config.ai_model

支持环境变量覆盖:

  • DATABASE_HOST, DATABASE_PORT, DATABASE_USER, DATABASE_PASSWORD
  • AI_MODEL_API_KEY, AI_MODEL_BASE_URL

8. 统一异常

创建 core/exceptions.py,定义标准异常类:

异常类 用途 HTTP 状态码
ValidationError 参数验证失败 400
ResourceNotFoundError 资源未找到 404
EngineError 引擎执行错误 500
AIError AI 服务错误 502
AIRateLimitError AI 限流 429

10. 重复目录统一

core/document/ 重定向到 document/,保持兼容性。

12. 日志配置

创建 core/logging_config.py

from core import setup_logging, get_logger

# 初始化日志
setup_logging(level="INFO", log_dir="logs")

# 获取日志器
logger = get_logger(__name__)

特性:

  • 控制台 + 文件输出
  • 日志滚动 (10MB/文件保留5个)
  • 错误日志单独文件
  • 第三方库日志静默

Prompt 查询 API

新增 V2 接口:

接口 方法 说明
/prompt/v2/list GET 列出所有 prompt
/prompt/v2/{name} GET 获取 prompt 详情
/prompt/v2/{name}/versions GET 列出版本
/prompt/v2/{name}/preview GET 预览原始模板
/prompt/v2/render POST 渲染 prompt

已迁移的 Prompt

名称 版本 说明
topic_generate v1.0.0 选题生成
content_generate v1.0.0 内容生成
content_judge v1.0.0 内容审核
poster_generate v1.0.0 海报文案
integration v1.0.0 资料整理
style/gonglue v1.0.0 攻略风风格
style/tuijian v1.0.0 极力推荐风风格
audience/qinzi v1.0.0 亲子向人群
audience/zhoubianyou v1.0.0 周边游人群
audience/gaoshe v1.0.0 高奢酒店人群

V1 引擎废弃说明

V1 引擎已废弃V2 引擎现在使用默认名称:

旧 engine_id 新 engine_id 说明
topic_generate_v2 topic_generate 选题生成
content_generate_v2 content_generate 内容生成
poster_generate_v2 poster_generate 海报生成

Java 端直接使用 topic_generatecontent_generateposter_generate 即可。


后端对接文档

详见 API_INTEGRATION.md