"""中控 AI:今日总结生成。""" from __future__ import annotations from typing import Any from hub_ai.client import generate_text, model_label from hub_ai.context import ( build_daily_context, collect_closed_trades_snapshot, format_account_remark, format_summary_context_text, summary_context_hash, ) from hub_ai.prompts import SUMMARY_SYSTEM, build_summary_user_prompt from hub_ai.store import append_summary, get_latest_summary, list_summaries def _stats_snapshot_from_ctx(ctx: dict) -> dict: day = ctx.get("trading_day") accounts = ctx.get("accounts") or [] return { "totals": ctx.get("totals"), "closed_trades": collect_closed_trades_snapshot(accounts, today=day), "by_account": { str(ac.get("key") or ac.get("id")): { "key": ac.get("key"), "name": ac.get("name"), "status": ac.get("status"), "funding_usdt": ac.get("funding_usdt"), "trading_usdt": ac.get("trading_usdt"), "available_trading_usdt": ac.get("available_trading_usdt"), "pnl_u": (ac.get("trade_stats") or {}).get("total_pnl_u"), "closed_count": (ac.get("trade_stats") or {}).get("closed_count"), "float_pnl_u": ac.get("float_pnl_u"), "remark": format_account_remark(ac), "monitor_lines": ac.get("monitor_lines") or {}, "issues": ac.get("issues") or [], } for ac in accounts }, } def generate_daily_summary( exchanges: list[dict], *, trading_day: str | None = None, force: bool = False, ) -> dict[str, Any]: ctx = build_daily_context(exchanges, trading_day=trading_day) day = ctx["trading_day"] summary_payload = { "trading_day": day, "totals": ctx.get("totals"), "accounts": ctx.get("accounts"), } summary_text = format_summary_context_text(summary_payload) digest = summary_context_hash(summary_payload) if not force: latest = get_latest_summary(day) if latest and latest.get("context_hash") == digest: return { "ok": True, "cached": True, "trading_day": day, "summary": latest, "model": latest.get("model") or model_label(), } system = SUMMARY_SYSTEM.replace("{trading_day}", day) user = build_summary_user_prompt(summary_text, day) content = generate_text(system=system, user=user, temperature=0.15) if content.startswith("AI 调用失败"): return {"ok": False, "msg": content, "trading_day": day} stats_snapshot = _stats_snapshot_from_ctx(ctx) row = append_summary( trading_day=day, content_md=content, model=model_label(), context_hash=digest, stats_snapshot=stats_snapshot, ) return { "ok": True, "cached": False, "trading_day": day, "summary": row, "model": model_label(), "context": ctx, } def summary_list(trading_day: str | None = None) -> list[dict]: return list_summaries(trading_day=trading_day)