Files
color_full/docs/adr/0002-ai-api-strategy.md
qichi.liang 23e5cb4006 feat: AI 驱动的配方研发智能平台 v0.1
核心功能:
- M3 配方记录: 创建/编辑/详情/可视化编辑/AI提取/版本历史/版本对比
- M1 颜色引擎: D3.js 色相环/滑条微调/ΔE计算/取色棒/AI配色推荐
- M2 可视化编辑器: ECharts饼图/成分滑条/AI预测/雷达图/仪表盘
- M4 配方推演: 约束设置/SSE推演/方案对比/散点图
- 平台: NL智能搜索/项目管理/CSV导出/JWT认证/全局搜索

技术栈:
- 前端: React + Vite + Tailwind CSS 4 + Zustand + TanStack Query
- 后端: Fastify 5 + Prisma 7 + PostgreSQL + pgvector
- AI: OpenAI/DeepSeek API 调用 + Prompt模板 + 缓存/降级/限流
- 测试: Vitest 42 tests (26 API集成 + 16 色彩模块)
2026-05-20 17:50:37 +08:00

11 KiB
Raw Blame History

ADR-0002: AI 能力通过外部 API 调用实现

状态: 已决议 日期: 2026-05-20 父决策: ADR-0001整体技术栈 决策者: 架构评审


上下文

平台需要 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 调用的灵活性远胜固定模型

BFF 层 AI 调用架构

┌─────────────────────────────────────────────────────────┐
│  Fastify BFF                                            │
│                                                         │
│  ┌────────────────────────────────────────────────────┐ │
│  │  AI Service Module                                 │ │
│  │                                                    │ │
│  │  ┌──────────┐  ┌──────────┐  ┌───────────────┐   │ │
│  │  │ Cache    │  │ Rate     │  │ Fallback      │   │ │
│  │  │ Layer    │  │ Limiter  │  │ Handler       │   │ │
│  │  └──────────┘  └──────────┘  └───────────────┘   │ │
│  │                                                    │ │
│  │  ┌────────────────────────────────────────────┐   │ │
│  │  │  Prompt Templates (per capability)         │   │ │
│  │  │  - predictFormulaMetrics                   │   │ │
│  │  │  - parseNLQuery                             │   │ │
│  │  │  - generateFormulaOptions                   │   │ │
│  │  │  - recommendColorants                       │   │ │
│  │  │  - extractFormulaStructure                  │   │ │
│  │  └────────────────────────────────────────────┘   │ │
│  │                                                    │ │
│  │  ┌────────────────────────────────────────────┐   │ │
│  │  │  AI API Client                              │   │ │
│  │  │  - streaming (SSE proxy)                    │   │ │
│  │  │  - retry with backoff                       │   │ │
│  │  │  - timeout (30s default, 120s streaming)    │   │ │
│  │  └────────────────────────────────────────────┘   │ │
│  └────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘

核心模块

模块 职责
Prompt Templates 每种 AI 能力对应独立的 Prompt 模板,包含 system prompt + 结构化输出指令
Cache Layer LRU 缓存相同/相似查询的 AI 响应(基于 query hashTTL 5min~1h
Rate Limiter 令牌桶 + 并发控制,保护 API 配额
Fallback Handler API 不可用时返回缓存结果或友好降级提示
AI API Client 统一的 HTTP 客户端,处理 streaming、重试、超时

各 AI 能力的 API 调用策略

1. 配方指标预测

POST /api/ai/predict

BFF 流程:
1. 从 PostgreSQL 检索该成分组合的历史相似配方pgvector 向量搜索)
2. 构建 Prompt
   - System: 化妆品配方专家角色 + 指标定义
   - Context: 历史相似配方的指标数据few-shot examples
   - User: 当前配方的成分列表和比例
3. 调用 AI API非 streaming预期 < 5s
4. 缓存结果key: 成分+比例 hash

2. NL 搜索解析

POST /api/formulas/search?q=不含酒精的高保湿精华

BFF 流程:
1. 调用 AI API 将 NL 转为结构化查询:
   {
     "filters": { "exclude_ingredients": ["alcohol", "ethanol"], "category": "精华液" },
     "vector_query": "高保湿、补水、滋润配方",
     "sort": "保湿指数 DESC"
   }
2. filters → PostgreSQL WHERE 子句
3. vector_query → pgvector embedding → HNSW 相似搜索
4. 合并结果返回

3. 配方推演

POST /api/ai/explore

BFF 流程:
1. 用户设置约束(目标成本、保留成分、禁止成分、目标指标)
2. 检索当前配方 + 相关历史配方作为 context
3. 构建 Prompt → 调用 AI APIstreaming 模式)
4. BFF 转发 SSE 流到前端,逐步展示生成的候选方案
5. 每个候选方案附带置信度和变更说明

4. 颜色推荐

POST /api/color/recommend

BFF 流程:
1. 前端传入目标颜色 Lab 值
2. 在 PostgreSQL 中检索 ΔE < 3.0 的历史颜色配方pgvector
3. 将目标色 + 最近匹配配方作为 context调用 AI API 推荐色浆组合
4. 返回推荐色浆 + 预测比例 + 预测 ΔE

5. 配方结构化提取

POST /api/formulas/extract

BFF 流程:
1. 用户粘贴配方文本(或上传 Excel
2. 调用 AI API with function calling / structured output
3. 提取:成分 INCI 名、中文名、比例、所属相、工艺备注
4. 与成分目录ingredients 表)模糊匹配校验
5. 返回结构化 JSON前端展示确认

AI API 选型

主选

API 优势 适用场景
OpenAI GPT-4o / GPT-4.1 推理能力最强structured output 原生streaming 稳定 配方推演、NL 解析、结构化提取
Anthropic Claude 4 长上下文200K化工领域知识强 配方生成(需大量 context、复杂推理
DeepSeek V3 性价比高;中文能力强 指标预测(高频调用)、批量处理

推荐策略

场景 模型 理由
配方推演(流式,低频,高质量) GPT-4o streaming 体验最好,推理质量最高
指标预测(非流式,高频,需快) DeepSeek V3 便宜、快、中文好
NL 搜索解析(高频,需结构化输出) GPT-4o-mini / DeepSeek V3 便宜 + function calling
配方结构化提取(批量,需准确) GPT-4o structured output 精度最高
颜色推荐(低频,需领域知识) GPT-4o 需要强推理

API 配置抽象

// BFF 层多 provider 抽象
interface AIProvider {
  chat(messages: Message[], options: ChatOptions): Promise<ChatResponse>;
  chatStream(messages: Message[], options: ChatOptions): AsyncIterable<ChatChunk>;
}

const providers: Record<string, AIProvider> = {
  openai: new OpenAIProvider({ apiKey: env.OPENAI_API_KEY }),
  deepseek: new DeepSeekProvider({ apiKey: env.DEEPSEEK_API_KEY }),
  // 预留其他 provider
};

所有 AI 调用通过统一的 AIService 模块,根据场景路由到对应 provider上层业务不感知具体模型。


降级策略

场景 降级行为
AI API 超时5s 指标预测:返回"无法预测,请手动评估"NL 搜索:降级为基础关键词搜索
AI API 不可用(连续失败) 全部能力降级为提示模式,告知用户"AI 服务暂不可用"
配额耗尽 限流 + 排队;高频能力(指标预测)优先缓存命中

缓存策略

缓存内容 TTL Key
指标预测结果 1 小时 成分列表 + 比例的 hash
NL 搜索解析 5 分钟 原始查询文本 hash
颜色推荐 30 分钟 目标 Lab 值 + 允许 ΔE
成分结构化提取 永久(除非成分库更新) 原料名称 hash

使用 Redis 存储。BFF 启动时无需依赖 Redis降级为内存 LRU 缓存。


安全考虑

  • API Key 管理:环境变量注入(非代码硬编码),支持 vault/secret manager
  • 数据脱敏:发送给 AI API 的 prompt 不包含公司敏感配方全量数据,仅发送 necesary context
  • Prompt 注入防护用户输入NL 搜索词)经过清洗后嵌入 prompt 模板
  • 审计日志:所有 AI 调用记录请求摘要、token 消耗、耗时)存储到 PostgreSQL audit 表

后果

正向

  • 零 ML 基础设施投入,开发周期缩短 50%+
  • 部署仅需 4 个服务,运维复杂度极低
  • 模型能力随 API 升级自动提升,无迁移成本
  • 成本可控:按调用量付费,低用量时几乎为零
  • BFF 层可独立开发和测试mock AI 响应)

风险和缓解

风险 缓解
API 延迟影响用户体验 缓存 + streaming + 降级;预测 API 设置 5s 超时
外部 API 数据隐私 Prompt 中不发送完整配方;仅发送必要上下文
供应商锁定 多 provider 抽象层;标准化 prompt 模板可跨模型复用
LLM 幻觉(生成不合理配方) 结果后处理校验(比例总和 100%、成分存在性检查)

参考