diff --git a/server/deep_compression.py b/server/deep_compression.py index 0fc346d..23f5888 100644 --- a/server/deep_compression.py +++ b/server/deep_compression.py @@ -19,7 +19,7 @@ SUMMARY_PROMPT = ( "请使用中文,结构清晰,尽量具体,不要省略关键上下文。" ) -GUIDE_USER_MESSAGE_TEMPLATE = "当前对话已经被自动压缩,请阅读{path}并继续工作" +GUIDE_USER_MESSAGE_TEMPLATE = "当前对话已经被自动压缩(第{count}次)。请阅读{path}并继续工作" def _emit(sender, event_type: str, payload: Dict[str, Any]): @@ -31,6 +31,54 @@ def _emit(sender, event_type: str, payload: Dict[str, Any]): pass +def _normalize_deep_compression_records(metadata: Dict[str, Any]) -> List[Dict[str, Any]]: + records = metadata.get("deep_compression_records") + if not isinstance(records, list): + return [] + normalized: List[Dict[str, Any]] = [] + for item in records: + if not isinstance(item, dict): + continue + try: + count = int(item.get("count", 0) or 0) + except Exception: + count = 0 + path = str(item.get("compact_file") or "").strip() + if count <= 0 or not path: + continue + normalized.append({ + "count": count, + "compact_file": path, + "created_at": item.get("created_at"), + "source_conversation_id": item.get("source_conversation_id"), + "compressed_conversation_id": item.get("compressed_conversation_id"), + }) + normalized.sort(key=lambda x: (int(x.get("count") or 0), str(x.get("created_at") or ""))) + deduped: List[Dict[str, Any]] = [] + seen = set() + for rec in normalized: + key = (int(rec.get("count") or 0), str(rec.get("compact_file") or "")) + if key in seen: + continue + seen.add(key) + deduped.append(rec) + return deduped + + +def _build_guide_message(*, compression_index: int, compact_file: str, previous_records: List[Dict[str, Any]]) -> str: + base = GUIDE_USER_MESSAGE_TEMPLATE.format(count=compression_index, path=compact_file) + if not previous_records: + return base + lines = [base, "", "此前压缩摘要文件位置:"] + for rec in previous_records: + count = int(rec.get("count") or 0) + path = str(rec.get("compact_file") or "").strip() + if count <= 0 or not path: + continue + lines.append(f"- 第{count}次:{path}") + return "\n".join(lines).strip() + + def _extract_text_only(content: Any) -> str: if content is None: return "" @@ -202,7 +250,9 @@ async def run_deep_compression( old_title = conv_data.get("title") or "未命名" compression_count = int(metadata.get("compression_count", 0) or 0) - target_count = compression_count + 1 + previous_records = _normalize_deep_compression_records(metadata) + previous_max_count = max([int(item.get("count") or 0) for item in previous_records], default=0) + target_count = max(compression_count, previous_max_count) + 1 job_id = f"cmp_{datetime.now().strftime('%Y%m%d_%H%M%S_%f')}" cm.set_compression_state( in_progress=True, @@ -271,9 +321,29 @@ async def run_deep_compression( "skip_auto_title_generation": True, } ) + current_record = { + "count": target_count, + "compact_file": relative_compact_path, + "created_at": datetime.now().isoformat(), + "source_conversation_id": conversation_id, + "compressed_conversation_id": new_conv_id, + } + all_records = previous_records + [current_record] + cm.conversation_manager.update_conversation_metadata( + new_conv_id, + { + "compression_count": target_count, + "deep_compression_records": all_records, + "last_deep_compression_record": current_record, + }, + ) cm.conversation_manager.update_conversation_title(new_conv_id, f"{old_title}对话 压缩后") web_terminal.load_conversation(new_conv_id) - guide_message = GUIDE_USER_MESSAGE_TEMPLATE.format(path=relative_compact_path) + guide_message = _build_guide_message( + compression_index=target_count, + compact_file=relative_compact_path, + previous_records=previous_records, + ) # 清理旧对话压缩状态 cm.conversation_manager.update_conversation_metadata( diff --git a/utils/conversation_manager.py b/utils/conversation_manager.py index b11143e..a3ad417 100644 --- a/utils/conversation_manager.py +++ b/utils/conversation_manager.py @@ -395,6 +395,8 @@ class ConversationManager: "compression_job_id": None, "compression_error": None, "compression_resume_payload": None, + "deep_compression_records": [], + "last_deep_compression_record": None, "skip_auto_title_generation": False, } if isinstance(metadata_overrides, dict):