refactor
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
from typing import Any
|
||||
|
||||
from app.homelab.digest import build_weather_briefing
|
||||
from app.homelab.image_gen import generate_image as run_generate_image
|
||||
from app.homelab.openmeteo import OpenMeteoClient
|
||||
from app.tools._dispatch import NOT_HANDLED, ToolContext
|
||||
|
||||
TOOL_NAMES = frozenset({
|
||||
"get_weather",
|
||||
"get_morning_briefing",
|
||||
"generate_image",
|
||||
})
|
||||
|
||||
TOOL_DEFINITIONS: list[dict[str, Any]] = [
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "get_weather",
|
||||
"description": (
|
||||
"ОБЯЗАТЕЛЬНО для вопросов о погоде, «что на улице», «будет ли дождь», «завтра», «на неделю». "
|
||||
"Текущая погода, почасовой и дневной прогноз."
|
||||
),
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"hours_ahead": {
|
||||
"type": "integer",
|
||||
"description": "Сколько часов почасового прогноза (по умолчанию 12, до 168)",
|
||||
},
|
||||
"days_ahead": {
|
||||
"type": "integer",
|
||||
"description": "Сколько дней дневного прогноза (по умолчанию 7, до 16)",
|
||||
},
|
||||
},
|
||||
"required": [],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "get_morning_briefing",
|
||||
"description": "Утренний брифинг: погода и заголовки новостей.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"include_news": {
|
||||
"type": "boolean",
|
||||
"description": "Включить новости (по умолчанию true)",
|
||||
},
|
||||
},
|
||||
"required": [],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "generate_image",
|
||||
"description": (
|
||||
"Аниме-картинка (Anima). draw_self=true — персонаж из карточки; "
|
||||
"scene_description — поза/кадр/одежда (booru-теги на англ. или короткий запрос: "
|
||||
"full body, sitting, apron). Можно оба параметра: draw_self + scene_description. "
|
||||
"Внешность только из appearance_tags карточки."
|
||||
),
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"draw_self": {
|
||||
"type": "boolean",
|
||||
"description": "Нарисовать персонажа из карточки",
|
||||
},
|
||||
"scene_description": {
|
||||
"type": "string",
|
||||
"description": (
|
||||
"Поза, кадр, одежда, обстановка — booru-теги или запрос "
|
||||
"(full_body, standing, apron, blush). С draw_self=true — уточняет сцену."
|
||||
),
|
||||
},
|
||||
},
|
||||
"required": [],
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
async def execute(name: str, arguments: dict[str, Any], ctx: ToolContext) -> Any:
|
||||
if name not in TOOL_NAMES:
|
||||
return NOT_HANDLED
|
||||
|
||||
if name == "get_weather":
|
||||
hours = max(1, min(int(arguments.get("hours_ahead") or 12), 168))
|
||||
days = max(1, min(int(arguments.get("days_ahead") or 7), 16))
|
||||
client = OpenMeteoClient()
|
||||
weather = client.fetch_forecast(hours_ahead=hours, days_ahead=days)
|
||||
return {
|
||||
"weather": weather,
|
||||
"rain_summary": client.rain_summary(hours_ahead=hours, daily=weather.get("daily")) if weather.get("ok") else "",
|
||||
"daily_summary": client.daily_summary(days_ahead=days) if weather.get("ok") else "",
|
||||
}
|
||||
if name == "get_morning_briefing":
|
||||
include_news = arguments.get("include_news", True)
|
||||
return build_weather_briefing(
|
||||
hours_ahead=12,
|
||||
include_news=bool(include_news),
|
||||
)
|
||||
if name == "generate_image":
|
||||
return await run_generate_image(
|
||||
ctx.db,
|
||||
user_id=ctx.user_id,
|
||||
session_id=ctx.session_id,
|
||||
draw_self=bool(arguments.get("draw_self")),
|
||||
scene_description=arguments.get("scene_description", ""),
|
||||
)
|
||||
return NOT_HANDLED
|
||||
Reference in New Issue
Block a user