- 添加营养成分表图片识别API接口,支持通过AI模型分析食物营养成分 - 新增NutritionAnalysisService服务,集成GLM-4.5V和Qwen VL视觉模型 - 实现营养成分提取和健康建议生成功能 - 添加完整的API文档和TypeScript类型定义 - 支持多种营养素类型识别,包括热量、蛋白质、脂肪等20+种营养素
295 lines
8.4 KiB
Markdown
295 lines
8.4 KiB
Markdown
# 营养成分表分析 API 文档
|
||
|
||
## 接口概述
|
||
|
||
本接口用于分析食物营养成分表图片,通过AI大模型智能识别图片中的营养成分信息,并为每个营养素提供详细的健康建议。
|
||
|
||
## 接口信息
|
||
|
||
- **接口地址**: `POST /diet-records/analyze-nutrition-image`
|
||
- **请求方式**: POST
|
||
- **内容类型**: `application/json`
|
||
- **认证方式**: Bearer Token (JWT)
|
||
|
||
## 请求参数
|
||
|
||
### Headers
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| Authorization | string | 是 | JWT认证令牌,格式:`Bearer {token}` |
|
||
| Content-Type | string | 是 | 固定值:`application/json` |
|
||
|
||
### Body 参数
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||
|--------|------|------|------|------|
|
||
| imageUrl | string | 是 | 营养成分表图片的URL地址 | `https://example.com/nutrition-label.jpg` |
|
||
|
||
#### 请求示例
|
||
|
||
```json
|
||
{
|
||
"imageUrl": "https://example.com/nutrition-label.jpg"
|
||
}
|
||
```
|
||
|
||
## 响应格式
|
||
|
||
### 成功响应
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": [
|
||
{
|
||
"key": "energy_kcal",
|
||
"name": "热量",
|
||
"value": "840千焦",
|
||
"analysis": "840千焦约等于201卡路里,占成人每日推荐摄入总热量的10%,属于中等热量水平。"
|
||
},
|
||
{
|
||
"key": "protein",
|
||
"name": "蛋白质",
|
||
"value": "12.5g",
|
||
"analysis": "12.5克蛋白质占成人每日推荐摄入量的21%,是良好的蛋白质来源,有助于肌肉修复和生长。"
|
||
},
|
||
{
|
||
"key": "fat",
|
||
"name": "脂肪",
|
||
"value": "6.8g",
|
||
"analysis": "6.8克脂肪含量适中,主要包含不饱和脂肪酸,有助于维持正常的生理功能。"
|
||
},
|
||
{
|
||
"key": "carbohydrate",
|
||
"name": "碳水化合物",
|
||
"value": "28.5g",
|
||
"analysis": "28.5克碳水化合物提供主要能量来源,建议搭配运动以充分利用能量。"
|
||
},
|
||
{
|
||
"key": "sodium",
|
||
"name": "钠",
|
||
"value": "480mg",
|
||
"analysis": "480毫克钠含量适中,约占成人每日推荐摄入量的20%,高血压患者需注意控制总钠摄入。"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 错误响应
|
||
|
||
```json
|
||
{
|
||
"success": false,
|
||
"data": [],
|
||
"message": "错误描述信息"
|
||
}
|
||
```
|
||
|
||
## 响应字段说明
|
||
|
||
### 通用字段
|
||
|
||
| 字段名 | 类型 | 说明 |
|
||
|--------|------|------|
|
||
| success | boolean | 操作是否成功 |
|
||
| data | array | 营养成分分析结果数组 |
|
||
| message | string | 错误信息(仅在失败时返回) |
|
||
|
||
### 营养成分项字段 (data数组中的对象)
|
||
|
||
| 字段名 | 类型 | 说明 | 示例 |
|
||
|--------|------|------|------|
|
||
| key | string | 营养素的唯一标识符 | `energy_kcal` |
|
||
| name | string | 营养素的中文名称 | `热量` |
|
||
| value | string | 从图片中识别的原始值和单位 | `840千焦` |
|
||
| analysis | string | 针对该营养素的详细健康建议 | `840千焦约等于201卡路里...` |
|
||
|
||
## 支持的营养素类型
|
||
|
||
| 营养素 | key值 | 中文名称 |
|
||
|--------|-------|----------|
|
||
| 热量/能量 | energy_kcal | 热量 |
|
||
| 蛋白质 | protein | 蛋白质 |
|
||
| 脂肪 | fat | 脂肪 |
|
||
| 碳水化合物 | carbohydrate | 碳水化合物 |
|
||
| 膳食纤维 | fiber | 膳食纤维 |
|
||
| 钠 | sodium | 钠 |
|
||
| 钙 | calcium | 钙 |
|
||
| 铁 | iron | 铁 |
|
||
| 锌 | zinc | 锌 |
|
||
| 维生素C | vitamin_c | 维生素C |
|
||
| 维生素A | vitamin_a | 维生素A |
|
||
| 维生素D | vitamin_d | 维生素D |
|
||
| 维生素E | vitamin_e | 维生素E |
|
||
| 维生素B1 | vitamin_b1 | 维生素B1 |
|
||
| 维生素B2 | vitamin_b2 | 维生素B2 |
|
||
| 维生素B6 | vitamin_b6 | 维生素B6 |
|
||
| 维生素B12 | vitamin_b12 | 维生素B12 |
|
||
| 叶酸 | folic_acid | 叶酸 |
|
||
| 胆固醇 | cholesterol | 胆固醇 |
|
||
| 饱和脂肪 | saturated_fat | 饱和脂肪 |
|
||
| 反式脂肪 | trans_fat | 反式脂肪 |
|
||
| 糖 | sugar | 糖 |
|
||
|
||
## 错误码说明
|
||
|
||
| HTTP状态码 | 错误信息 | 说明 |
|
||
|------------|----------|------|
|
||
| 400 | 请提供图片URL | 请求体中缺少imageUrl参数 |
|
||
| 400 | 图片URL格式不正确 | 提供的URL格式无效 |
|
||
| 401 | 未授权访问 | 缺少或无效的JWT令牌 |
|
||
| 500 | 营养成分表分析失败,请稍后重试 | AI模型调用失败或服务器内部错误 |
|
||
| 500 | 图片中未检测到有效的营养成分表信息 | 图片中未识别到营养成分表 |
|
||
|
||
## 使用注意事项
|
||
|
||
### 图片要求
|
||
|
||
1. **图片格式**: 支持 JPG、PNG、WebP 格式
|
||
2. **图片内容**: 必须包含清晰的营养成分表
|
||
3. **图片质量**: 建议使用高清、无模糊、光线充足的图片
|
||
4. **URL要求**: 图片URL必须是公网可访问的地址
|
||
|
||
### 最佳实践
|
||
|
||
1. **URL有效性**: 确保提供的图片URL在分析期间保持可访问
|
||
2. **图片预处理**: 建议在客户端对图片进行适当的裁剪,突出营养成分表部分
|
||
3. **错误处理**: 客户端应妥善处理各种错误情况,提供友好的用户提示
|
||
4. **重试机制**: 对于网络或服务器错误,建议实现适当的重试机制
|
||
|
||
### 限制说明
|
||
|
||
1. **调用频率**: 建议客户端控制调用频率,避免过于频繁的请求
|
||
2. **图片大小**: 虽然不直接限制图片大小,但过大的图片可能影响处理速度
|
||
3. **并发限制**: 服务端可能有并发请求限制,建议客户端实现队列机制
|
||
|
||
## 客户端集成示例
|
||
|
||
### JavaScript/TypeScript 示例
|
||
|
||
```typescript
|
||
interface NutritionAnalysisRequest {
|
||
imageUrl: string;
|
||
}
|
||
|
||
interface NutritionAnalysisItem {
|
||
key: string;
|
||
name: string;
|
||
value: string;
|
||
analysis: string;
|
||
}
|
||
|
||
interface NutritionAnalysisResponse {
|
||
success: boolean;
|
||
data: NutritionAnalysisItem[];
|
||
message?: string;
|
||
}
|
||
|
||
async function analyzeNutritionImage(
|
||
imageUrl: string,
|
||
token: string
|
||
): Promise<NutritionAnalysisResponse> {
|
||
try {
|
||
const response = await fetch('/diet-records/analyze-nutrition-image', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'Authorization': `Bearer ${token}`
|
||
},
|
||
body: JSON.stringify({ imageUrl })
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (!response.ok) {
|
||
throw new Error(result.message || '请求失败');
|
||
}
|
||
|
||
return result;
|
||
} catch (error) {
|
||
console.error('营养成分分析失败:', error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
// 使用示例
|
||
const token = 'your-jwt-token';
|
||
const imageUrl = 'https://example.com/nutrition-label.jpg';
|
||
|
||
analyzeNutritionImage(imageUrl, token)
|
||
.then(result => {
|
||
if (result.success) {
|
||
console.log('识别到营养素数量:', result.data.length);
|
||
result.data.forEach(item => {
|
||
console.log(`${item.name}: ${item.value}`);
|
||
console.log(`建议: ${item.analysis}`);
|
||
});
|
||
} else {
|
||
console.error('分析失败:', result.message);
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('请求异常:', error);
|
||
});
|
||
```
|
||
|
||
### Swift 示例
|
||
|
||
```swift
|
||
struct NutritionAnalysisRequest: Codable {
|
||
let imageUrl: String
|
||
}
|
||
|
||
struct NutritionAnalysisItem: Codable {
|
||
let key: String
|
||
let name: String
|
||
let value: String
|
||
let analysis: String
|
||
}
|
||
|
||
struct NutritionAnalysisResponse: Codable {
|
||
let success: Bool
|
||
let data: [NutritionAnalysisItem]
|
||
let message: String?
|
||
}
|
||
|
||
class NutritionAnalysisService {
|
||
func analyzeNutritionImage(imageUrl: String, token: String) async throws -> NutritionAnalysisResponse {
|
||
guard let url = URL(string: "/diet-records/analyze-nutrition-image") else {
|
||
throw URLError(.badURL)
|
||
}
|
||
|
||
var request = URLRequest(url: url)
|
||
request.httpMethod = "POST"
|
||
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
||
|
||
let requestBody = NutritionAnalysisRequest(imageUrl: imageUrl)
|
||
request.httpBody = try JSONEncoder().encode(requestBody)
|
||
|
||
let (data, response) = try await URLSession.shared.data(for: request)
|
||
|
||
guard let httpResponse = response as? HTTPURLResponse else {
|
||
throw URLError(.badServerResponse)
|
||
}
|
||
|
||
guard 200...299 ~= httpResponse.statusCode else {
|
||
throw NSError(domain: "APIError", code: httpResponse.statusCode, userInfo: [NSLocalizedDescriptionKey: "HTTP Error"])
|
||
}
|
||
|
||
let result = try JSONDecoder().decode(NutritionAnalysisResponse.self, from: data)
|
||
return result
|
||
}
|
||
}
|
||
```
|
||
|
||
## 更新日志
|
||
|
||
| 版本 | 日期 | 更新内容 |
|
||
|------|------|----------|
|
||
| 1.0.0 | 2024-10-16 | 初始版本,支持营养成分表图片分析功能 |
|
||
|
||
## 技术支持
|
||
|
||
如有技术问题或集成困难,请联系开发团队获取支持。 |