2026-05-20 17:50:37 +08:00
|
|
|
|
# ADR-0002: AI 能力通过外部 API 调用实现
|
|
|
|
|
|
|
2026-05-21 17:29:52 +08:00
|
|
|
|
> **状态**: 已决议(2026-05-21 修订)
|
|
|
|
|
|
> **日期**: 2026-05-20
|
|
|
|
|
|
> **修订**: 2026-05-21
|
|
|
|
|
|
> **父决策**: ADR-0001(整体技术栈)
|
2026-05-20 17:50:37 +08:00
|
|
|
|
> **决策者**: 架构评审
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 上下文
|
|
|
|
|
|
|
|
|
|
|
|
平台需要 AI 能力支撑四大核心模块:配方指标预测、NL 搜索、配方生成/推演、颜色推荐。考虑两种实现路径:
|
|
|
|
|
|
|
|
|
|
|
|
- **方案 A**:自建 Python AI 微服务(FastAPI + 自训练模型)
|
|
|
|
|
|
- **方案 B**:通过外部 AI API 调用实现(LLM API + Prompt Engineering)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 决策
|
|
|
|
|
|
|
|
|
|
|
|
**选择方案 B**:所有 AI 能力通过调用外部 LLM API 实现。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 理由
|
|
|
|
|
|
|
|
|
|
|
|
### 方案 B 优势
|
|
|
|
|
|
|
|
|
|
|
|
| 维度 | 方案 A(自建) | 方案 B(外部 API) |
|
|
|
|
|
|
| :--- | :--- | :--- |
|
|
|
|
|
|
| **开发成本** | 需要 ML 工程师训练模型;数据清洗和标注投入大 | Prompt Engineering 即可;无需 ML 专业背景 |
|
|
|
|
|
|
| **运维成本** | GPU 服务器(至少 1 台 A100)+ 模型部署和监控 | 零运维,按调用量付费 |
|
|
|
|
|
|
| **迭代速度** | 重新训练需数天到数周 | 调整 Prompt 即时生效 |
|
|
|
|
|
|
| **模型能力** | 受限于自有数据量和训练资源 | 持续获得最新大模型能力升级 |
|
|
|
|
|
|
| **部署复杂度** | 增加 1 个微服务 + GPU 依赖 + gRPC | 仅 BFF 层 HTTP 调用 |
|
|
|
|
|
|
| **冷启动** | 模型加载需数分钟 | 即用即走 |
|
|
|
|
|
|
|
|
|
|
|
|
### 化妆品配方场景的特殊适配
|
|
|
|
|
|
|
|
|
|
|
|
配方研发的 AI 需求特点:
|
|
|
|
|
|
|
|
|
|
|
|
1. **推理为主,非训练密集型**:预测肤感/稳定性本质是"基于成分知识的推理",LLM 的常识推理 + few-shot learning 可以胜任
|
|
|
|
|
|
2. **数据量小**:企业内部配方数据通常是千到万级,不足以训练专用深度学习模型
|
|
|
|
|
|
3. **领域知识密集**:LLM 已具备化学/化妆品基础知识,通过 Prompt 注入成分数据库即可精准推理
|
|
|
|
|
|
4. **需求多变**:配方推演的约束条件千变万化,API 调用的灵活性远胜固定模型
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-05-21 17:29:52 +08:00
|
|
|
|
## AI Service 架构
|
2026-05-20 17:50:37 +08:00
|
|
|
|
|
|
|
|
|
|
```
|
2026-05-21 17:29:52 +08:00
|
|
|
|
Route Layer (modules/ai/ai.route.ts)
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
AIService (services/ai/index.ts)
|
|
|
|
|
|
├── Provider 抽象层
|
|
|
|
|
|
│ ├── createOpenAIProvider (GPT-4o, base: api.openai.com/v1)
|
|
|
|
|
|
│ └── createDeepSeekProvider (deepseek-chat, base: api.deepseek.com/v1)
|
|
|
|
|
|
├── LRUCache (200 条, 带 TTL)
|
|
|
|
|
|
├── RateLimiter (10 req/s, token bucket)
|
|
|
|
|
|
├── 重试策略 (指数退避, 最多 3 次)
|
|
|
|
|
|
├── Fallback → Mock 模式 (AI_MOCK=true 时返回预设数据)
|
|
|
|
|
|
└── Audit Log → ai_audit_logs 表 (capability, model, tokens, duration)
|
2026-05-20 17:50:37 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-05-21 17:29:52 +08:00
|
|
|
|
> **修订(2026-05-21)**:AI Service 重构为实例属性管理配置(openaiKey/deepseekKey),不再依赖 `process.env` 直读。Provider 通过 `reload(updates)` 热更新。
|
2026-05-20 17:50:37 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-05-21 17:29:52 +08:00
|
|
|
|
## AI 能力清单
|
2026-05-20 17:50:37 +08:00
|
|
|
|
|
2026-05-21 17:29:52 +08:00
|
|
|
|
| Prompt 模板 | 能力 | System Prompt 角色 | 输出格式 |
|
|
|
|
|
|
|-------------|------|--------------------|----------|
|
|
|
|
|
|
| `predictMetricsPrompt` | 预测配方指标 | 资深化妆品配方工程师 | `{sensoryIndex, stabilityScore, costEstimate, confidence, reasoning}` |
|
|
|
|
|
|
| `parseNLQueryPrompt` | 自然语言搜索 | 查询解析器 | `{filters, keywords, vectorQuery}` |
|
|
|
|
|
|
| `generateFormulaPrompt` | 配方推演 | 资深化妆品配方工程师 | `[{name, changes, predictedMetrics, reasoning}]` |
|
|
|
|
|
|
| `recommendColorantsPrompt` | 配色推荐 | 化妆品色彩专家 | `{recommendations: [{colorants, predictedDeltaE, confidence}]}` |
|
|
|
|
|
|
| `extractFormulaPrompt` | 配方文本提取 | 数据结构化提取 | `{ingredients: [{inciName, chineseName, percentage, phase, processNotes}]}` |
|
2026-05-20 17:50:37 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-05-21 17:29:52 +08:00
|
|
|
|
## 配置管理
|
2026-05-20 17:50:37 +08:00
|
|
|
|
|
2026-05-21 17:29:52 +08:00
|
|
|
|
| 配置项 | 存储位置 | 说明 |
|
|
|
|
|
|
|--------|----------|------|
|
|
|
|
|
|
| `AI_MOCK` | `runtime/config.json` | Mock 模式开关(开发环境默认 true) |
|
|
|
|
|
|
| `OPENAI_API_KEY` | `runtime/config.json` | 服务器端持久化,客户端不透传 |
|
|
|
|
|
|
| `DEEPSEEK_API_KEY` | `runtime/config.json` | 同上 |
|
|
|
|
|
|
| `OPENAI_BASE_URL` | `runtime/config.json` | 自定义 endpoint(如 API 代理) |
|
|
|
|
|
|
| `DEEPSEEK_BASE_URL` | `runtime/config.json` | 同上 |
|
2026-05-20 17:50:37 +08:00
|
|
|
|
|
2026-05-21 17:29:52 +08:00
|
|
|
|
> **修订(2026-05-21)**:API Key 从 localStorage 传输改为服务器端文件持久化。前端 SettingsPage 仅显示"已配置/未配置"状态,不展示 Key 内容。
|
2026-05-20 17:50:37 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 后果
|
|
|
|
|
|
|
2026-05-21 17:29:52 +08:00
|
|
|
|
- 依赖外部 API 服务可用性(OpenAI / DeepSeek),API 不可用时自动降级为 Mock 模式
|
|
|
|
|
|
- AI 响应格式严格约束为 JSON,前端不解析自然语言输出
|
|
|
|
|
|
- 每次 AI 调用记录审计日志,用于成本核算和问题排查
|
|
|
|
|
|
- 新增 AI Provider 只需实现 `AIProvider` 接口(`chat` + `chatStream`)
|