日期: 2026-10-08
状态: 已实现(代码已完成)
优先级: P1
CFC 项目已有舌诊功能的初步实现,但目前依赖 LangGraph Python 服务(cfc-langgraph),在 LangGraph 不可用时使用 mock 数据兜底。
为提供更准确、更丰富的中医舌诊分析,计划接入 aikanshe.com(愛看舌)开放 API,作为备用舌诊服务提供者。
| 方式 | 说明 | 适用场景 |
|---|---|---|
appkey + x-appkey header |
注册后获取的 API Key | 推荐,对接简单 |
| JWT Token | POST /account/login 获取,放入 Authorization: Bearer {token} |
需登录态的场景 |
每个账号默认 25 次免费调用,超额需购买算力包。
| 接口 | 消耗 | 说明 |
|---|---|---|
POST /agency/quanxi |
1 次 | AI 全息舌诊(multipart 上传) |
POST /agency/quanxiWithUrl |
1 次 | AI 全息舌诊(imageUrl 方式) |
POST /agency/quanxiWithReport |
2 次 | 附带网页报告 |
POST /agency/quanxiWithReportAndUnderside |
3 次 | 带舌底 + 网页报告 |
quanxiWithUrl){
"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" // 语言偏好
}
AiQuanxiReportDTO){
"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": {}
}
TongueDiagnosisService.parsePreview()
↓
AIService.sendTongueDiagnosis(imageBytes, filename, userId)
↓
AiGateway.analyzeTongue(imageBytes, filename, userId) ← 调用 LangGraph
↓
LangGraph: POST /api/v1/tongue/diagnose
↓
返回: { overall_assessment, indicators: [{code, value}] }
当 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}] }
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 文件覆盖。
@Value 注入字段(aikansheAppkey, aikansheBaseUrl, aikansheToken, aikansheDesease, aikansheConfidence, aikansheLang)sendTongueDiagnosis():aikanshe.com 优先,失败时回退至 LangGraphcallAikansheTongueDiagnosis():HTTP 调用 aikanshe.com APIparseAikansheIndicators():将 aikanshe 的丰富指标映射到 CFC 标准的 7 类指标isValidTongueColor():验证舌色值合法性makeIndicator():辅助方法| 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 |
气虚质/阴虚质/血瘀质/平和质 |
以下不在本次范围,留待后续迭代:
age/male/name 使用占位值,实际应从 JWT 上下文获取aikanshe.com 优先,LangGraph 兜底:
启动 → 调用 aikanshe.com API
│
├── 成功 → 返回 aikanshe 结果(7类标准指标 + overall_assessment)
│
└── 失败/超时 → 调用 LangGraph /api/v1/tongue/diagnose
│
├── 成功 → 返回 LangGraph 结果
│
└── 失败 → 返回 mockTongueResult() 默认值
AIKANSHE_APPKEY 后自动使用 aikanshe.com;未配置或调用失败时自动回退 LangGraph配置环境变量:
export AIKANSHE_APPKEY="your_appkey_here"
export AIKANSHE_BASE_URL="https://api.aikanshe.com"
启动后端:mvn spring-boot:run
测试端点:POST /api/tongue/diagnose/parse-preview(上传舌象图片)
验证返回结构包含 overall_assessment 和 indicators 数组