diff --git a/prompts/title_generation_prompt.txt b/prompts/title_generation_prompt.txt new file mode 100644 index 0000000..dd360fc --- /dev/null +++ b/prompts/title_generation_prompt.txt @@ -0,0 +1,13 @@ +### 任务: +生成一个简洁的、3-5个词的标题,并包含一个emoji,用于总结聊天内容。 + +### 指导原则: +- 标题应清晰代表主要话题 +- 使用与话题相关且单个的emoji +- 保持简洁(3-5个词) +- 清晰度优先于创意 +- 使用用户输入的语言回复 +- 不需要回答用户的问题,不需要补充任何信息,只需要生成标题 + +### 输出格式: +仅输出标题本身,不要附加解释。 diff --git a/utils/conversation_manager.py b/utils/conversation_manager.py index 4b56014..8beea35 100644 --- a/utils/conversation_manager.py +++ b/utils/conversation_manager.py @@ -334,6 +334,9 @@ class ConversationManager: return False data["title"] = title data["updated_at"] = datetime.now().isoformat() + meta = data.get("metadata", {}) or {} + meta["title_locked"] = True + data["metadata"] = meta self._save_conversation_file(conversation_id, data) self._update_index(conversation_id, data) if self.current_conversation_id == conversation_id: @@ -431,10 +434,12 @@ class ConversationManager: existing_data["messages"] = messages existing_data["updated_at"] = datetime.now().isoformat() - # 更新标题(如果消息发生变化) - new_title = self._extract_title_from_messages(messages) - if new_title != "新对话": - existing_data["title"] = new_title + # 更新标题(如未锁定自动标题时,仍按首条消息回退) + title_locked = existing_data.get("metadata", {}).get("title_locked", False) + if not title_locked: + new_title = self._extract_title_from_messages(messages) + if new_title != "新对话": + existing_data["title"] = new_title # 更新元数据 if project_path is not None: diff --git a/web_server.py b/web_server.py index 5c0305d..83d0656 100644 --- a/web_server.py +++ b/web_server.py @@ -181,18 +181,7 @@ LAST_ACTIVE_FILE = Path(LOGS_DIR).expanduser().resolve() / "last_active.json" _last_active_lock = threading.Lock() _last_active_cache: Dict[str, float] = {} _idle_reaper_started = False -TITLE_PROMPT = """### 任务: -生成一个简洁的、3-5个词的标题,并包含一个emoji,用于总结聊天内容。 - -### 指导原则: -- 标题应清晰代表主要话题 -- 使用与话题相关且单个的emoji -- 保持简洁(3-5个词) -- 清晰度优先于创意 -- 使用用户输入的语言回复 - -### 输出格式: -仅输出标题本身,不要附加解释。""" +TITLE_PROMPT_PATH = Path(__file__).resolve().parent / "prompts" / "title_generation_prompt.txt" def sanitize_filename_preserve_unicode(filename: str) -> str: @@ -303,8 +292,12 @@ async def _generate_title_async(user_message: str) -> Optional[str]: if not user_message: return None client = DeepSeekClient(thinking_mode=False, web_mode=True) + try: + prompt_text = TITLE_PROMPT_PATH.read_text(encoding="utf-8") + except Exception: + prompt_text = "生成一个简洁的、3-5个词的标题,并包含单个emoji,使用用户的语言,直接输出标题。" messages = [ - {"role": "system", "content": TITLE_PROMPT}, + {"role": "system", "content": prompt_text}, {"role": "user", "content": user_message} ] try: