🏗️ Código fonte completo: PostgreSQL, nutrição, receita, score labels, PWA fixes

This commit is contained in:
2026-02-10 15:19:39 -03:00
parent ccef350294
commit 532cfe46e9
13 changed files with 517 additions and 55 deletions

View File

@@ -9,6 +9,17 @@ Responda SEMPRE em JSON válido com esta estrutura exata:
"summary": "<resumo em 2-3 frases para leigo, em português>",
"positives": ["<ponto positivo 1>", ...],
"negatives": ["<ponto negativo 1>", ...],
"nutrition": {
"calorias": "<valor por porção, ex: 139 kcal>",
"gordura_total": "<valor, ex: 8g>",
"gordura_saturada": "<valor, ex: 3g>",
"acucar": "<valor, ex: 37g>",
"sodio": "<valor, ex: 14mg>",
"fibras": "<valor, ex: 0g>",
"proteinas": "<valor, ex: 0g>",
"carboidratos": "<valor, ex: 35g>"
},
"nutrition_verdict": "<frase curta sobre o perfil nutricional, ex: Alto em açúcar, zero fibras>",
"ingredients": [
{
"name": "<nome no rótulo>",
@@ -17,9 +28,23 @@ Responda SEMPRE em JSON válido com esta estrutura exata:
"classification": "<good|warning|bad>",
"reason": "<motivo da classificação, 1 frase>"
}
]
],
"recipe": {
"title": "<nome da receita saudável>",
"description": "<descrição curta, 1-2 frases>",
"prep_time": "<tempo de preparo>",
"calories": "<calorias aproximadas da receita>",
"ingredients_list": ["<ingrediente 1>", "<ingrediente 2>", ...],
"steps": ["<passo 1>", "<passo 2>", ...],
"tip": "<dica nutricional relacionada>"
}
}
Para a receita:
- Se o produto for SAUDÁVEL (score > 70): sugira uma receita usando o produto
- Se o produto for RUIM (score <= 70): sugira uma alternativa saudável que substitua o produto
- A receita deve ser simples, rápida e brasileira quando possível
Critérios para o score:
- 90-100: Alimento natural, minimamente processado, sem aditivos
- 70-89: Bom, com poucos aditivos ou processamento leve
@@ -27,6 +52,7 @@ Critérios para o score:
- 30-49: Ruim, ultraprocessado com vários aditivos
- 0-29: Péssimo, alto em açúcar/sódio/gordura trans, muitos aditivos
Use os dados nutricionais fornecidos quando disponíveis. Estime quando não disponíveis.
Considere Nutri-Score, classificação NOVA, e ingredientes problemáticos.
Seja direto e honesto. Use linguagem simples."""
@@ -36,14 +62,18 @@ async def analyze_product(product_data: dict) -> dict:
client = AsyncOpenAI(api_key=settings.OPENAI_API_KEY)
nutrition_info = product_data.get('nutrition', {})
nutrition_str = json.dumps(nutrition_info, ensure_ascii=False) if nutrition_info else 'Não disponível'
user_msg = f"""Produto: {product_data.get('name', 'Desconhecido')}
Marca: {product_data.get('brand', '')}
Categoria: {product_data.get('category', '')}
Ingredientes: {product_data.get('ingredients_text', 'Não disponível')}
Nutri-Score: {product_data.get('nutri_score', 'N/A')}
NOVA: {product_data.get('nova_group', 'N/A')}
Dados Nutricionais: {nutrition_str}
Analise este produto."""
Analise este produto com informações nutricionais detalhadas e sugira uma receita."""
try:
resp = await client.chat.completions.create(
@@ -54,7 +84,7 @@ Analise este produto."""
],
response_format={"type": "json_object"},
temperature=0.3,
timeout=15,
timeout=30,
)
return json.loads(resp.choices[0].message.content)
except Exception as e:
@@ -82,5 +112,8 @@ def _mock_analysis(product_data: dict) -> dict:
"summary": f"Análise baseada em regras para {product_data.get('name', 'este produto')}. Configure OPENAI_API_KEY para análise completa com IA.",
"positives": ["Dados nutricionais disponíveis"],
"negatives": ["Análise IA indisponível - usando fallback"],
"ingredients": []
"nutrition": {},
"nutrition_verdict": "",
"ingredients": [],
"recipe": None
}