Files
Home_assistant/backend/app/fitness/structuring.py
T
2026-06-16 04:38:23 +00:00

103 lines
3.5 KiB
Python

import json
from typing import Any
from app.llm.client import LLMClient
from app.projects.structuring import strip_markdown_json
MEAL_PROMPT = """
Преобразуй описание еды в JSON. Только JSON, без markdown.
Схема:
{
"meal_type": "breakfast|lunch|dinner|snack",
"description": "краткое описание",
"calories": 0,
"protein_g": 0,
"fat_g": 0,
"carbs_g": 0,
"estimated": true
}
Правила:
- Оцени ккал и БЖУ по типичным значениям для России/СНГ.
- Все числа — float/int, метрическая система (г, ккал).
- meal_type угадай из контекста или snack.
- estimated всегда true для LLM-оценки.
""".strip()
WORKOUT_PROMPT = """
Преобразуй описание тренировки в JSON. Только JSON.
Формат:
{
"title": "название",
"activity_type": "ходьба|бег|силовая|велосипед|плавание|йога|hiit|другое",
"duration_min": null,
"active_calories": null,
"met": null,
"total_calories": null,
"steps": null,
"notes": "",
"exercises": [
{"name": "имя упраж", "sets": 3, "reps": 8, "weight_kg": 80}
]
}
Правила:
- weight_kg в кг, округляй разумно.
- active_calories — только если явно указаны в тексте, иначе null.
- duration_min — длительность в минутах, если можно оценить из текста.
- met — MET по Compendium of Physical Activities, если ккал не указаны (ходьба ~3.5, бег ~9.8, силовая ~6, велосипед ~7.5, плавание ~8, йога ~3, hiit ~8).
- activity_type — тип активности для расчёта MET.
- total_calories / steps — если упомянуты в тексте, иначе null.
- Если данных нет — null или пустой массив.
""".strip()
STEPS_PROMPT = """
Преобразуй запись о шагах в JSON. Только JSON.
Формат:
{
"steps": 0,
"active_calories": null,
"notes": ""
}
Правила:
- steps — целое число шагов за день.
- active_calories — только если явно указаны.
""".strip()
async def structure_meal(raw_text: str) -> dict[str, Any]:
llm = LLMClient()
result = await llm.complete(
[
{"role": "system", "content": MEAL_PROMPT},
{"role": "user", "content": raw_text},
],
temperature=0.2,
)
raw = strip_markdown_json(result.get("content") or "")
return json.loads(raw)
async def structure_workout(raw_text: str) -> dict[str, Any]:
llm = LLMClient()
result = await llm.complete(
[
{"role": "system", "content": WORKOUT_PROMPT},
{"role": "user", "content": raw_text},
],
temperature=0.2,
)
raw = strip_markdown_json(result.get("content") or "")
return json.loads(raw)
async def structure_steps(raw_text: str) -> dict[str, Any]:
llm = LLMClient()
result = await llm.complete(
[
{"role": "system", "content": STEPS_PROMPT},
{"role": "user", "content": raw_text},
],
temperature=0.2,
)
raw = strip_markdown_json(result.get("content") or "")
return json.loads(raw)