|
|
@@ -0,0 +1,200 @@
|
|
|
+# 舌诊 aikanshe.com API 集成设计方案
|
|
|
+
|
|
|
+**日期**: 2026-10-08
|
|
|
+**状态**: 已实现(代码已完成)
|
|
|
+**优先级**: P1
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 一、背景
|
|
|
+
|
|
|
+CFC 项目已有舌诊功能的初步实现,但目前依赖 LangGraph Python 服务(`cfc-langgraph`),在 LangGraph 不可用时使用 mock 数据兜底。
|
|
|
+为提供更准确、更丰富的中医舌诊分析,计划接入 `aikanshe.com`(愛看舌)开放 API,作为备用舌诊服务提供者。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 二、aikanshe.com API 概览
|
|
|
+
|
|
|
+### 2.1 认证方式
|
|
|
+
|
|
|
+| 方式 | 说明 | 适用场景 |
|
|
|
+|------|------|----------|
|
|
|
+| `appkey` + `x-appkey` header | 注册后获取的 API Key | 推荐,对接简单 |
|
|
|
+| JWT Token | `POST /account/login` 获取,放入 `Authorization: Bearer {token}` | 需登录态的场景 |
|
|
|
+
|
|
|
+每个账号默认 **25 次免费调用**,超额需购买算力包。
|
|
|
+
|
|
|
+### 2.2 核心接口
|
|
|
+
|
|
|
+| 接口 | 消耗 | 说明 |
|
|
|
+|------|------|------|
|
|
|
+| `POST /agency/quanxi` | 1 次 | AI 全息舌诊(multipart 上传) |
|
|
|
+| `POST /agency/quanxiWithUrl` | 1 次 | AI 全息舌诊(imageUrl 方式) |
|
|
|
+| `POST /agency/quanxiWithReport` | 2 次 | 附带网页报告 |
|
|
|
+| `POST /agency/quanxiWithReportAndUnderside` | 3 次 | 带舌底 + 网页报告 |
|
|
|
+
|
|
|
+### 2.3 请求参数(`quanxiWithUrl`)
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "age": 30, // 年龄(小孩 2-16,成人 >15)
|
|
|
+ "male": 1, // 1=男,0=女,2=其他
|
|
|
+ "name": "张三", // 姓名/昵称
|
|
|
+ "imageUrl": "data:image/jpeg;base64,...",
|
|
|
+ "appkey": "xxx", // appkey 或 token 认证
|
|
|
+ "desease": "", // 疾病筛选(拼音,填 all 检测所有)
|
|
|
+ "confidence": 0.2, // 置信度阈值
|
|
|
+ "lang": "zh-CN" // 语言偏好
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 2.4 响应结构(`AiQuanxiReportDTO`)
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "code": "20000",
|
|
|
+ "data": {
|
|
|
+ "id": 123,
|
|
|
+ "name": "张三",
|
|
|
+ "age": 30,
|
|
|
+ "feel": "身体表现...", // 整体评估(映射到 overall_assessment)
|
|
|
+ "recomand": "...", // 调理方案
|
|
|
+ "aijiu": "调理方案:艾灸与按摩",
|
|
|
+ "bagang": "阴阳虚实表里寒热", // 八纲辨证
|
|
|
+ "botai": 0, // 是否有剥苔(0/1)
|
|
|
+ "chagndao": 0, // 肠道是否异常
|
|
|
+ "chagndaoDesc": "...",
|
|
|
+ "chagndaoMean": "...",
|
|
|
+ "chihen": 0, // 是否有齿痕(0/1)
|
|
|
+ "chihenDesc": "...",
|
|
|
+ "chihenMean": "...",
|
|
|
+ "dianci": 0, // 是否有点刺(0/1)
|
|
|
+ "dianciDesc": "...",
|
|
|
+ "fei": 0,
|
|
|
+ "feiDesc": "...",
|
|
|
+ "createTime": "2026-10-08T..."
|
|
|
+ // ... 其他字段
|
|
|
+ },
|
|
|
+ "meta": {}
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 三、现有架构
|
|
|
+
|
|
|
+### 3.1 现有舌诊流程
|
|
|
+
|
|
|
+```
|
|
|
+TongueDiagnosisService.parsePreview()
|
|
|
+ ↓
|
|
|
+AIService.sendTongueDiagnosis(imageBytes, filename, userId)
|
|
|
+ ↓
|
|
|
+AiGateway.analyzeTongue(imageBytes, filename, userId) ← 调用 LangGraph
|
|
|
+ ↓
|
|
|
+LangGraph: POST /api/v1/tongue/diagnose
|
|
|
+ ↓
|
|
|
+返回: { overall_assessment, indicators: [{code, value}] }
|
|
|
+```
|
|
|
+
|
|
|
+### 3.2 新增兜底逻辑
|
|
|
+
|
|
|
+当 LangGraph 不可用时,自动降级到 aikanshe.com API:
|
|
|
+
|
|
|
+```
|
|
|
+AIService.sendTongueDiagnosis(imageBytes, filename, userId)
|
|
|
+ ↓
|
|
|
+AiGateway.analyzeTongue(...) ← 失败则继续
|
|
|
+ ↓ (LangGraph 返回 null)
|
|
|
+callAikansheTongueDiagnosis(imageBytes, filename, userId) ← 新增
|
|
|
+ ↓
|
|
|
+POST https://api.aikanshe.com/agency/quanxi
|
|
|
+ ↓
|
|
|
+parseAikansheIndicators(data) ← 新增:字段映射
|
|
|
+ ↓
|
|
|
+返回: { overall_assessment, indicators: [{code, value}] }
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 四、实现变更
|
|
|
+
|
|
|
+### 4.1 application.yml — 新增配置
|
|
|
+
|
|
|
+```yaml
|
|
|
+aikanshe:
|
|
|
+ appkey: ${AIKANSHE_APPKEY:}
|
|
|
+ base-url: ${AIKANSHE_BASE_URL:https://api.aikanshe.com}
|
|
|
+ token: ${AIKANSHE_TOKEN:}
|
|
|
+ desease: ${AIKANSHE_DISEASE:}
|
|
|
+ confidence: ${AIKANSHE_CONFIDENCE:0.2}
|
|
|
+ lang: ${AIKANSHE_LANG:zh-CN}
|
|
|
+```
|
|
|
+
|
|
|
+环境变量可通过 Docker 部署或 `.env` 文件覆盖。
|
|
|
+
|
|
|
+### 4.2 AIService.java — 新增方法
|
|
|
+
|
|
|
+- 新增 6 个 `@Value` 注入字段(`aikansheAppkey`, `aikansheBaseUrl`, `aikansheToken`, `aikansheDesease`, `aikansheConfidence`, `aikansheLang`)
|
|
|
+- 修改 `sendTongueDiagnosis()`:aikanshe.com 优先,失败时回退至 LangGraph
|
|
|
+- 新增 `callAikansheTongueDiagnosis()`:HTTP 调用 aikanshe.com API
|
|
|
+- 新增 `parseAikansheIndicators()`:将 aikanshe 的丰富指标映射到 CFC 标准的 7 类指标
|
|
|
+- 新增 `isValidTongueColor()`:验证舌色值合法性
|
|
|
+- 新增 `makeIndicator()`:辅助方法
|
|
|
+
|
|
|
+### 4.3 指标映射关系
|
|
|
+
|
|
|
+| aikanshe 字段 | CFC 标准 code | 映射逻辑 |
|
|
|
+|---------------|--------------|---------|
|
|
|
+| `feel` 文本含"舌色" | `tongue_color` | 从 feel 文本中提取 |
|
|
|
+| `botai` = 0/1 | `coating_color` | 有苔/无苔 |
|
|
|
+| `botai` = 0/1 | `coating_texture` | 润/滑腻 |
|
|
|
+| `bagang` 含虚/实 | `fissure` | 有/无 |
|
|
|
+| `chihen` = 0/1 | `teeth_mark` | 有齿痕/无齿痕 |
|
|
|
+| `dianci` = 0/1 | `sublingual_vein` | 有点刺/无点刺 |
|
|
|
+| `desease` 关键词 | `constitution` | 气虚质/阴虚质/血瘀质/平和质 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 五、后续优化建议(YAGNI)
|
|
|
+
|
|
|
+以下不在本次范围,留待后续迭代:
|
|
|
+
|
|
|
+1. **传真实用户信息**:当前 `age/male/name` 使用占位值,实际应从 JWT 上下文获取
|
|
|
+2. **图片存储后传 URL**:当前使用 base64 data URL,建议先上传到 JD Cloud S3,再传 URL 给 aikanshe(减少带宽和延迟)
|
|
|
+3. **完整指标提取**:aikanshe 返回约 50 个字段,可提取更丰富的体质/脏腑信息用于五维能量计算
|
|
|
+4. **调用量监控**:添加调用次数统计和配额告警
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 五、调用优先级
|
|
|
+
|
|
|
+**aikanshe.com 优先,LangGraph 兜底**:
|
|
|
+
|
|
|
+```
|
|
|
+启动 → 调用 aikanshe.com API
|
|
|
+ │
|
|
|
+ ├── 成功 → 返回 aikanshe 结果(7类标准指标 + overall_assessment)
|
|
|
+ │
|
|
|
+ └── 失败/超时 → 调用 LangGraph /api/v1/tongue/diagnose
|
|
|
+ │
|
|
|
+ ├── 成功 → 返回 LangGraph 结果
|
|
|
+ │
|
|
|
+ └── 失败 → 返回 mockTongueResult() 默认值
|
|
|
+```
|
|
|
+
|
|
|
+- 配置 `AIKANSHE_APPKEY` 后自动使用 aikanshe.com;未配置或调用失败时自动回退 LangGraph
|
|
|
+- 最终兜底为 mock 数据,确保业务不中断
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 六、验证步骤
|
|
|
+
|
|
|
+1. 配置环境变量:
|
|
|
+ ```bash
|
|
|
+ export AIKANSHE_APPKEY="your_appkey_here"
|
|
|
+ export AIKANSHE_BASE_URL="https://api.aikanshe.com"
|
|
|
+ ```
|
|
|
+2. 启动后端:`mvn spring-boot:run`
|
|
|
+3. 测试端点:`POST /api/tongue/diagnose/parse-preview`(上传舌象图片)
|
|
|
+4. 验证返回结构包含 `overall_assessment` 和 `indicators` 数组
|