"""交易监管:AI 评语与用户回聊。""" from __future__ import annotations from typing import Any, Optional from hub_ai.client import generate_text, model_label from hub_ai.config import ( CHAT_MAX_OUTPUT_TOKENS, CHAT_TEMPERATURE, trading_day_reset_hour, ) from hub_ai.context import build_chat_context, format_chat_context_for_chat from hub_ai.prompts import SUPERVISOR_SYSTEM, build_supervisor_ai_prompt, build_supervisor_chat_prompt from hub_ai.supervisor_store import ( append_supervisor_ai_message, ensure_supervisor_session, get_supervisor_session_state, ) from hub_ai.store import append_chat_message from hub_trades_lib import current_trading_day def generate_supervisor_ai_reply( *, event: dict, warnings: list[dict], trading_day: str, session_id: str, exchanges: list[dict], ) -> str: ctx = build_chat_context(exchanges, trading_day=trading_day) brief = format_chat_context_for_chat(ctx, max_chars=6000) user_prompt = build_supervisor_ai_prompt( context_text=brief, trading_day=trading_day, event=event, warnings=warnings, ) return generate_text( system=SUPERVISOR_SYSTEM, user=user_prompt, temperature=min(0.35, CHAT_TEMPERATURE), max_tokens=min(512, CHAT_MAX_OUTPUT_TOKENS), max_continuations=1, ) def make_supervisor_ai_reply_fn(exchanges: list[dict]): def _fn(*, event: dict, warnings: list[dict], trading_day: str, session_id: str) -> str: return generate_supervisor_ai_reply( event=event, warnings=warnings or [], trading_day=trading_day, session_id=session_id, exchanges=exchanges, ) return _fn def send_supervisor_chat( exchanges: list[dict], message: str, *, trading_day: str | None = None, ) -> dict[str, Any]: text = (message or "").strip() if not text: return {"ok": False, "msg": "消息不能为空"} day = (trading_day or "").strip()[:10] or current_trading_day( reset_hour=trading_day_reset_hour() ) session = ensure_supervisor_session(day) sid = str(session.get("id") or "") prior = session.get("messages") or [] ctx = build_chat_context(exchanges, trading_day=day) brief = format_chat_context_for_chat(ctx, max_chars=6000) recent = [] for m in prior[-8:]: role = m.get("role") if role not in ("user", "assistant", "system"): continue label = {"user": "用户", "assistant": "监管", "system": "系统"}.get(role, role) recent.append(f"{label}:{str(m.get('content') or '').strip()}") user_prompt = build_supervisor_chat_prompt( context_text=brief, trading_day=day, history_lines="\n".join(recent), user_message=text, ) reply = generate_text( system=SUPERVISOR_SYSTEM, user=user_prompt, temperature=min(0.4, CHAT_TEMPERATURE), max_tokens=min(768, CHAT_MAX_OUTPUT_TOKENS), max_continuations=1, ) if not reply or reply.strip().startswith("AI "): return {"ok": False, "msg": reply or "AI 生成失败", "session_id": sid} append_chat_message(sid, "user", text) session = append_supervisor_ai_message(sid, reply.strip()) state = get_supervisor_session_state(day) return { "ok": True, "trading_day": day, "session": session, "reply": reply.strip(), "model": model_label(), "message_count": state.get("message_count"), "unread_system": state.get("unread_system"), }