Files
plates-server/docs/nutrition-analysis-api.md
richarjiang 5c2c9dfae8 feat(diet-records): 新增营养成分表图片分析功能
- 添加营养成分表图片识别API接口,支持通过AI模型分析食物营养成分
- 新增NutritionAnalysisService服务,集成GLM-4.5V和Qwen VL视觉模型
- 实现营养成分提取和健康建议生成功能
- 添加完整的API文档和TypeScript类型定义
- 支持多种营养素类型识别,包括热量、蛋白质、脂肪等20+种营养素
2025-10-16 10:03:22 +08:00

8.4 KiB
Raw Blame History

营养成分表分析 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

请求示例

{
  "imageUrl": "https://example.com/nutrition-label.jpg"
}

响应格式

成功响应

{
  "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%,高血压患者需注意控制总钠摄入。"
    }
  ]
}

错误响应

{
  "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 示例

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 示例

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 初始版本,支持营养成分表图片分析功能

技术支持

如有技术问题或集成困难,请联系开发团队获取支持。