Files
AI-Health/backend/src/Health.Infrastructure/Diets/DietImageAnalyzer.cs
MingNian 7a93237069 feat: AI 对话附件上下文解析 + 历史会话归档 + 多页面 UI 重构
- 后端: 新增 AttachmentContextBuilder 解析图片/PDF 摘要并拼入 LLM 上下文; ai_chat_endpoints 扩展附件接口; 新增 ReportAnalysisService
- 前端: 新增历史会话页与 conversation_history_provider; chat 链路支持附件展示与回放
- UI: 重构 medication_checkin / notification_center / profile / health_drawer 等多页面
- 配置: api_client baseUrl 适配当前 WiFi IP
2026-07-06 12:44:59 +08:00

72 lines
3.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Health.Application.Diets;
using Health.Infrastructure.AI;
namespace Health.Infrastructure.Diets;
public sealed class DietImageAnalyzer(VisionClient vision) : IDietImageAnalyzer
{
private readonly VisionClient _vision = vision;
public async Task<DietImageAnalysisResult> AnalyzeAsync(DietImageAnalysisJob job, CancellationToken ct)
{
var imageUrls = new List<string>();
foreach (var filePath in job.FilePaths)
{
if (!File.Exists(filePath))
return new DietImageAnalysisResult(false, 40004, null, "待识别图片不存在");
var bytes = await File.ReadAllBytesAsync(filePath, ct);
var base64 = Convert.ToBase64String(bytes);
if (base64.Length > 7 * 1024 * 1024)
return new DietImageAnalysisResult(false, 40001, null, "图片过大,请压缩后重新上传");
var extension = Path.GetExtension(filePath).ToLowerInvariant();
var mime = extension switch
{
".png" => "image/png",
".heic" => "image/heic",
_ => "image/jpeg"
};
imageUrls.Add($"data:{mime};base64,{base64}");
}
var prompt = """
JSON
##
** []**
##
[{"name":"食物名","portion":"具体克数","calories":数字}]
##
- (11cm)200g250g250g100g
- (14cm)400ml200ml
- (23cm)300g150g
- /250ml200ml
- 150g1100g180g115g
- 1100g1200g1120g
- 80-120g1100g1()300g
## 仿
{"name":"米饭","portion":"约200g","calories":230}
{"name":"红烧肉","portion":"约150g","calories":420}
{"name":"豆浆","portion":"约250ml","calories":80}
{"name":"米饭","portion":"一碗","calories":230} portion
{"name":"汤","portion":"一份","calories":80} portion
{"name":"水果","portion":"少许","calories":50} portion
##
1. []
2. portion + (g ml)
3. 使/"约"("约80-120g")
4. calories
JSON
""";
var response = await _vision.VisionAsync(prompt, imageUrls, userText: null, maxTokens: 8192, ct: ct);
var result = response.Choices?.FirstOrDefault()?.Message?.Content ?? "[]";
return new DietImageAnalysisResult(true, 0, result, null);
}
}