Files
crypto_monitor/manual_trading_hub/hub_ai/supervisor.py
T
dekun bfbd6879d6 Add AI trading supervisor with WeChat push and daily session
Proactive monitoring for manual/hub closes and new opens prevents overtrading via in-app alerts, configurable WeChat links, and supervisor chat.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 19:25:01 +08:00

112 lines
3.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""交易监管: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"),
}