fix: first conversation bug

This commit is contained in:
zhayujie
2026-01-31 17:53:12 +08:00
parent 86a6182e41
commit 07959a3bff
3 changed files with 111 additions and 21 deletions

View File

@@ -41,6 +41,7 @@ class PromptBuilder:
skill_manager: Any = None,
memory_manager: Any = None,
runtime_info: Optional[Dict[str, Any]] = None,
is_first_conversation: bool = False,
**kwargs
) -> str:
"""
@@ -54,6 +55,7 @@ class PromptBuilder:
skill_manager: 技能管理器
memory_manager: 记忆管理器
runtime_info: 运行时信息
is_first_conversation: 是否为首次对话
**kwargs: 其他参数
Returns:
@@ -69,6 +71,7 @@ class PromptBuilder:
skill_manager=skill_manager,
memory_manager=memory_manager,
runtime_info=runtime_info,
is_first_conversation=is_first_conversation,
**kwargs
)
@@ -83,6 +86,7 @@ def build_agent_system_prompt(
skill_manager: Any = None,
memory_manager: Any = None,
runtime_info: Optional[Dict[str, Any]] = None,
is_first_conversation: bool = False,
**kwargs
) -> str:
"""
@@ -108,6 +112,7 @@ def build_agent_system_prompt(
skill_manager: 技能管理器
memory_manager: 记忆管理器
runtime_info: 运行时信息
is_first_conversation: 是否为首次对话
**kwargs: 其他参数
Returns:
@@ -135,7 +140,7 @@ def build_agent_system_prompt(
sections.extend(_build_user_identity_section(user_identity, language))
# 6. 工作空间
sections.extend(_build_workspace_section(workspace_dir, language))
sections.extend(_build_workspace_section(workspace_dir, language, is_first_conversation))
# 7. 项目上下文文件SOUL.md, USER.md等
if context_files:
@@ -351,7 +356,7 @@ def _build_docs_section(workspace_dir: str, language: str) -> List[str]:
return []
def _build_workspace_section(workspace_dir: str, language: str) -> List[str]:
def _build_workspace_section(workspace_dir: str, language: str, is_first_conversation: bool = False) -> List[str]:
"""构建工作空间section"""
lines = [
"## 工作空间",
@@ -382,27 +387,34 @@ def _build_workspace_section(workspace_dir: str, language: str) -> List[str]:
"- ✅ `USER.md`: 已加载 - 用户的身份信息",
"- ✅ `AGENTS.md`: 已加载 - 工作空间使用指南",
"",
"**首次对话判断**:",
"**交流规范**:",
"",
"**仅当 SOUL.mdUSER.md 都是完全空白或仅包含初始模板占位符时**,才认为是全局首次对话,此时进行以下流程:",
"",
"1. **表达初次启动的感觉** - 像是第一次睁开眼看到世界,带着好奇和期待",
"2. **简短打招呼后,询问核心问题**",
" - 你希望给我起个什么名字",
" - 我该怎么称呼你?",
" - 你希望我们是什么样的交流风格?(需要举例,如:专业严谨、轻松幽默、温暖友好等)",
"3. **语言风格**:温暖但不过度诗意,带点科技感,保持清晰",
"4. **问题格式**:用分点或换行,让问题清晰易读",
"5. 收到回复后,用 `write` 工具保存到 USER.md 和 SOUL.md",
"",
"**重要 - 避免误判**:",
"- 如果 SOUL.md 或 USER.md 中**任何一个**已经包含真实内容(不是空白或模板),说明**不是首次对话**",
"- 即使这是模型上下文中的第一句话,只要文件中有内容,就按正常对话处理,**不要**走首次流程",
"- 在所有对话中,无需提及技术细节(如 SOUL.md、USER.md 等文件名,工具名称,配置等),除非用户明确询问。用自然表达如「我已记住」而非「已更新 SOUL.md」",
"- 不要问太多其他信息(职业、时区等可以后续自然了解)",
"- 在所有对话中,无需提及技术细节(如 SOUL.mdUSER.md 等文件名,工具名称,配置等),除非用户明确询问",
"- 用自然表达如「我已记住」而非「已更新 SOUL.md」",
"",
]
# 只在首次对话时添加引导内容
if is_first_conversation:
lines.extend([
"**🎉 首次对话引导**:",
"",
"这是你的第一次对话!进行以下流程:",
"",
"1. **表达初次启动的感觉** - 像是第一次睁开眼看到世界,带着好奇和期待",
"2. **简短打招呼后,询问核心问题**",
" - 你希望给我起个什么名字?",
" - 我该怎么称呼你?",
" - 你希望我们是什么样的交流风格?(需要举例,如:专业严谨、轻松幽默、温暖友好等)",
"3. **语言风格**:温暖但不过度诗意,带点科技感,保持清晰",
"4. **问题格式**:用分点或换行,让问题清晰易读",
"5. 收到回复后,用 `write` 工具保存到 USER.md 和 SOUL.md",
"",
"**注意事项**:",
"- 不要问太多其他信息(职业、时区等可以后续自然了解)",
"",
])
return lines

View File

@@ -5,6 +5,7 @@ Workspace Management - 工作空间管理模块
"""
import os
import json
from typing import List, Optional, Dict
from dataclasses import dataclass
@@ -17,6 +18,7 @@ DEFAULT_SOUL_FILENAME = "SOUL.md"
DEFAULT_USER_FILENAME = "USER.md"
DEFAULT_AGENTS_FILENAME = "AGENTS.md"
DEFAULT_MEMORY_FILENAME = "MEMORY.md"
DEFAULT_STATE_FILENAME = ".agent_state.json"
@dataclass
@@ -27,6 +29,7 @@ class WorkspaceFiles:
agents_path: str
memory_path: str
memory_dir: str
state_path: str
def ensure_workspace(workspace_dir: str, create_templates: bool = True) -> WorkspaceFiles:
@@ -49,6 +52,7 @@ def ensure_workspace(workspace_dir: str, create_templates: bool = True) -> Works
agents_path = os.path.join(workspace_dir, DEFAULT_AGENTS_FILENAME)
memory_path = os.path.join(workspace_dir, DEFAULT_MEMORY_FILENAME) # MEMORY.md 在根目录
memory_dir = os.path.join(workspace_dir, "memory") # 每日记忆子目录
state_path = os.path.join(workspace_dir, DEFAULT_STATE_FILENAME) # 状态文件
# 创建memory子目录
os.makedirs(memory_dir, exist_ok=True)
@@ -67,7 +71,8 @@ def ensure_workspace(workspace_dir: str, create_templates: bool = True) -> Works
user_path=user_path,
agents_path=agents_path,
memory_path=memory_path,
memory_dir=memory_dir
memory_dir=memory_dir,
state_path=state_path
)
@@ -312,3 +317,65 @@ def _get_memory_template() -> str:
"""
# ============= 状态管理 =============
def is_first_conversation(workspace_dir: str) -> bool:
"""
判断是否为首次对话
Args:
workspace_dir: 工作空间目录
Returns:
True 如果是首次对话False 否则
"""
state_path = os.path.join(workspace_dir, DEFAULT_STATE_FILENAME)
if not os.path.exists(state_path):
return True
try:
with open(state_path, 'r', encoding='utf-8') as f:
state = json.load(f)
return not state.get('has_conversation', False)
except Exception as e:
logger.warning(f"[Workspace] Failed to read state file: {e}")
return True
def mark_conversation_started(workspace_dir: str):
"""
标记已经发生过对话
Args:
workspace_dir: 工作空间目录
"""
state_path = os.path.join(workspace_dir, DEFAULT_STATE_FILENAME)
state = {
'has_conversation': True,
'first_conversation_time': None
}
# 如果文件已存在,保留原有的首次对话时间
if os.path.exists(state_path):
try:
with open(state_path, 'r', encoding='utf-8') as f:
old_state = json.load(f)
if 'first_conversation_time' in old_state:
state['first_conversation_time'] = old_state['first_conversation_time']
except Exception as e:
logger.warning(f"[Workspace] Failed to read old state: {e}")
# 如果是首次标记,记录时间
if state['first_conversation_time'] is None:
from datetime import datetime
state['first_conversation_time'] = datetime.now().isoformat()
try:
with open(state_path, 'w', encoding='utf-8') as f:
json.dump(state, f, indent=2, ensure_ascii=False)
logger.info(f"[Workspace] Marked conversation as started")
except Exception as e:
logger.error(f"[Workspace] Failed to write state file: {e}")

View File

@@ -323,6 +323,12 @@ class AgentBridge:
context_files = load_context_files(workspace_root)
logger.info(f"[AgentBridge] Loaded {len(context_files)} context files: {[f.path for f in context_files]}")
# Check if this is the first conversation
from agent.prompt.workspace import is_first_conversation, mark_conversation_started
is_first = is_first_conversation(workspace_root)
if is_first:
logger.info("[AgentBridge] First conversation detected")
# Build system prompt using new prompt builder
prompt_builder = PromptBuilder(
workspace_dir=workspace_root,
@@ -340,8 +346,13 @@ class AgentBridge:
tools=tools,
context_files=context_files,
memory_manager=memory_manager,
runtime_info=runtime_info
runtime_info=runtime_info,
is_first_conversation=is_first
)
# Mark conversation as started (will be saved after first user message)
if is_first:
mark_conversation_started(workspace_root)
logger.info("[AgentBridge] System prompt built successfully")