feat(hub): rolling chat summary to cap AI context and prevent mid-session failures

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-11 21:51:34 +08:00
parent 180aff5310
commit 6a1f2608b5
9 changed files with 297 additions and 50 deletions
+53 -9
View File
@@ -49,8 +49,8 @@ CHAT_SYSTEM = """
- 用户口述与快照冲突时,以快照为准并口语说明「我这边看到是空仓/有N仓」。
- 若附带「今日总结摘要」,那是较早生成的缓存,**实盘持仓以【当前多账户快照】里的「实盘持仓总览」为准**,摘要里若提到持仓可能已过时。
- 若用户上传图片,可结合图中可见信息讨论,看不清的明确说看不清。
- **优先接住【用户现在说】和【此前对话】**:用户聊心态、悔单、某笔操作时,先顺着这个话题回应,不要每句都复述账户资金数字。
- **接续对话**:有【此前对话】时须接着聊,不要重复开场白;整段回复必须写完,以句号/问号/感叹号收尾,不得停在半句话;编号列表每条单独一行。
- **优先接住【用户现在说】和【对话核心摘要】**:用户聊心态、悔单、某笔操作时,先顺着这个话题回应,不要每句都复述账户资金数字。
- **接续对话**:有【对话核心摘要】时须接着聊,不要重复开场白;整段回复必须写完,以句号/问号/感叹号收尾,不得停在半句话;编号列表每条单独一行。
- 快照里的盈亏/资金仅在需要核对事实时引用;用户口述与快照冲突时,以快照为准并口语说明。
""".strip()
@@ -73,19 +73,60 @@ CHAT_GENERAL_SYSTEM = """
- 用户未主动聊交易时,不要主动扯合约、仓位、盈亏、盯盘。
- 你没有接入用户的交易账户数据;不要编造持仓、资金或监控状态。若被问到交易事实,说明这边看不到实盘,建议去中控监控区或实例页查看。
- 若用户上传图片或文档,结合可见内容回应;看不清的直说。
- 接续【此前对话】,不要重复开场白;回复须写完整,以句号/问号/感叹号收尾。
- 接续【对话核心摘要】,不要重复开场白;回复须写完整,以句号/问号/感叹号收尾。
""".strip()
ROLLING_SUMMARY_TRADING_SYSTEM = """
你是交易教练的对话记录员。把「此前摘要」与「本轮用户+教练回复」压成一条极短中文摘要。
要求:
- 120~280 字,纯文本一段,不要标题、不要列表、不要寒暄。
- 只保留:用户情绪/困扰、涉及的交易事实、教练核心建议、已达成的共识、待跟进事项。
- 禁止编造未出现的信息;数字与账户名须来自原文。
""".strip()
ROLLING_SUMMARY_GENERAL_SYSTEM = """
你是对话记录员。把「此前摘要」与「本轮用户+助手回复」压成一条极短中文摘要。
要求:
- 100~240 字,纯文本一段,不要标题、不要列表。
- 只保留:话题、用户诉求、助手给出的关键信息、待跟进事项。
""".strip()
def build_rolling_summary_user_prompt(
*,
prior_summary: str,
user_text: str,
assistant_text: str,
) -> str:
parts: list[str] = []
if prior_summary.strip():
parts.extend(["【此前摘要】", prior_summary.strip()])
parts.extend([
"【本轮用户】",
user_text.strip() or "(空)",
"【本轮教练/助手】",
assistant_text.strip() or "(空)",
"请输出更新后的对话核心摘要:",
])
return "\n\n".join(parts)
def build_general_chat_user_prompt(
*,
history_lines: str,
rolling_summary: str = "",
history_lines: str = "",
user_message: str,
attachment_note: str = "",
) -> str:
parts: list[str] = []
if history_lines.strip():
parts.extend(["此前对话(须接续,勿重复开场)】", history_lines.strip()])
if rolling_summary.strip():
parts.extend(["【对话核心摘要(须接续,勿重复开场)】", rolling_summary.strip()])
elif history_lines.strip():
parts.extend(["【最近对话】", history_lines.strip()])
if attachment_note.strip():
parts.extend(["【用户附件说明】", attachment_note.strip()])
parts.extend(["【用户现在说(优先回应这一条)】", user_message.strip()])
@@ -97,13 +138,16 @@ def build_chat_user_prompt(
context_text: str,
trading_day: str,
summary_excerpt: str,
history_lines: str,
rolling_summary: str = "",
history_lines: str = "",
user_message: str,
attachment_note: str = "",
) -> str:
parts = [f"【交易日】{trading_day}"]
if history_lines.strip():
parts.extend(["此前对话(须接续,勿重复开场)】", history_lines.strip()])
if rolling_summary.strip():
parts.extend(["【对话核心摘要(须接续,勿重复开场)】", rolling_summary.strip()])
elif history_lines.strip():
parts.extend(["【最近对话】", history_lines.strip()])
parts.extend([
"【当前多账户快照(事实参考;持仓以「实盘持仓总览」为准)】",
context_text.strip() or "(无监控数据)",