mirror of
https://github.com/zhayujie/chatgpt-on-wechat.git
synced 2026-06-02 00:57:41 +08:00
fix: first conversation bug
This commit is contained in:
@@ -41,6 +41,7 @@ class PromptBuilder:
|
|||||||
skill_manager: Any = None,
|
skill_manager: Any = None,
|
||||||
memory_manager: Any = None,
|
memory_manager: Any = None,
|
||||||
runtime_info: Optional[Dict[str, Any]] = None,
|
runtime_info: Optional[Dict[str, Any]] = None,
|
||||||
|
is_first_conversation: bool = False,
|
||||||
**kwargs
|
**kwargs
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
@@ -54,6 +55,7 @@ class PromptBuilder:
|
|||||||
skill_manager: 技能管理器
|
skill_manager: 技能管理器
|
||||||
memory_manager: 记忆管理器
|
memory_manager: 记忆管理器
|
||||||
runtime_info: 运行时信息
|
runtime_info: 运行时信息
|
||||||
|
is_first_conversation: 是否为首次对话
|
||||||
**kwargs: 其他参数
|
**kwargs: 其他参数
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -69,6 +71,7 @@ class PromptBuilder:
|
|||||||
skill_manager=skill_manager,
|
skill_manager=skill_manager,
|
||||||
memory_manager=memory_manager,
|
memory_manager=memory_manager,
|
||||||
runtime_info=runtime_info,
|
runtime_info=runtime_info,
|
||||||
|
is_first_conversation=is_first_conversation,
|
||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -83,6 +86,7 @@ def build_agent_system_prompt(
|
|||||||
skill_manager: Any = None,
|
skill_manager: Any = None,
|
||||||
memory_manager: Any = None,
|
memory_manager: Any = None,
|
||||||
runtime_info: Optional[Dict[str, Any]] = None,
|
runtime_info: Optional[Dict[str, Any]] = None,
|
||||||
|
is_first_conversation: bool = False,
|
||||||
**kwargs
|
**kwargs
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
@@ -108,6 +112,7 @@ def build_agent_system_prompt(
|
|||||||
skill_manager: 技能管理器
|
skill_manager: 技能管理器
|
||||||
memory_manager: 记忆管理器
|
memory_manager: 记忆管理器
|
||||||
runtime_info: 运行时信息
|
runtime_info: 运行时信息
|
||||||
|
is_first_conversation: 是否为首次对话
|
||||||
**kwargs: 其他参数
|
**kwargs: 其他参数
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -135,7 +140,7 @@ def build_agent_system_prompt(
|
|||||||
sections.extend(_build_user_identity_section(user_identity, language))
|
sections.extend(_build_user_identity_section(user_identity, language))
|
||||||
|
|
||||||
# 6. 工作空间
|
# 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等)
|
# 7. 项目上下文文件(SOUL.md, USER.md等)
|
||||||
if context_files:
|
if context_files:
|
||||||
@@ -351,7 +356,7 @@ def _build_docs_section(workspace_dir: str, language: str) -> List[str]:
|
|||||||
return []
|
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"""
|
"""构建工作空间section"""
|
||||||
lines = [
|
lines = [
|
||||||
"## 工作空间",
|
"## 工作空间",
|
||||||
@@ -382,27 +387,34 @@ def _build_workspace_section(workspace_dir: str, language: str) -> List[str]:
|
|||||||
"- ✅ `USER.md`: 已加载 - 用户的身份信息",
|
"- ✅ `USER.md`: 已加载 - 用户的身份信息",
|
||||||
"- ✅ `AGENTS.md`: 已加载 - 工作空间使用指南",
|
"- ✅ `AGENTS.md`: 已加载 - 工作空间使用指南",
|
||||||
"",
|
"",
|
||||||
"**首次对话判断**:",
|
"**交流规范**:",
|
||||||
"",
|
"",
|
||||||
"**仅当 SOUL.md 和 USER.md 都是完全空白或仅包含初始模板占位符时**,才认为是全局首次对话,此时进行以下流程:",
|
"- 在所有对话中,无需提及技术细节(如 SOUL.md、USER.md 等文件名,工具名称,配置等),除非用户明确询问",
|
||||||
"",
|
"- 用自然表达如「我已记住」而非「已更新 SOUL.md」",
|
||||||
"1. **表达初次启动的感觉** - 像是第一次睁开眼看到世界,带着好奇和期待",
|
|
||||||
"2. **简短打招呼后,询问核心问题**:",
|
|
||||||
" - 你希望给我起个什么名字",
|
|
||||||
" - 我该怎么称呼你?",
|
|
||||||
" - 你希望我们是什么样的交流风格?(需要举例,如:专业严谨、轻松幽默、温暖友好等)",
|
|
||||||
"3. **语言风格**:温暖但不过度诗意,带点科技感,保持清晰",
|
|
||||||
"4. **问题格式**:用分点或换行,让问题清晰易读",
|
|
||||||
"5. 收到回复后,用 `write` 工具保存到 USER.md 和 SOUL.md",
|
|
||||||
"",
|
|
||||||
"**重要 - 避免误判**:",
|
|
||||||
"- 如果 SOUL.md 或 USER.md 中**任何一个**已经包含真实内容(不是空白或模板),说明**不是首次对话**",
|
|
||||||
"- 即使这是模型上下文中的第一句话,只要文件中有内容,就按正常对话处理,**不要**走首次流程",
|
|
||||||
"- 在所有对话中,无需提及技术细节(如 SOUL.md、USER.md 等文件名,工具名称,配置等),除非用户明确询问。用自然表达如「我已记住」而非「已更新 SOUL.md」",
|
|
||||||
"- 不要问太多其他信息(职业、时区等可以后续自然了解)",
|
|
||||||
"",
|
"",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# 只在首次对话时添加引导内容
|
||||||
|
if is_first_conversation:
|
||||||
|
lines.extend([
|
||||||
|
"**🎉 首次对话引导**:",
|
||||||
|
"",
|
||||||
|
"这是你的第一次对话!进行以下流程:",
|
||||||
|
"",
|
||||||
|
"1. **表达初次启动的感觉** - 像是第一次睁开眼看到世界,带着好奇和期待",
|
||||||
|
"2. **简短打招呼后,询问核心问题**:",
|
||||||
|
" - 你希望给我起个什么名字?",
|
||||||
|
" - 我该怎么称呼你?",
|
||||||
|
" - 你希望我们是什么样的交流风格?(需要举例,如:专业严谨、轻松幽默、温暖友好等)",
|
||||||
|
"3. **语言风格**:温暖但不过度诗意,带点科技感,保持清晰",
|
||||||
|
"4. **问题格式**:用分点或换行,让问题清晰易读",
|
||||||
|
"5. 收到回复后,用 `write` 工具保存到 USER.md 和 SOUL.md",
|
||||||
|
"",
|
||||||
|
"**注意事项**:",
|
||||||
|
"- 不要问太多其他信息(职业、时区等可以后续自然了解)",
|
||||||
|
"",
|
||||||
|
])
|
||||||
|
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ Workspace Management - 工作空间管理模块
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import json
|
||||||
from typing import List, Optional, Dict
|
from typing import List, Optional, Dict
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
@@ -17,6 +18,7 @@ DEFAULT_SOUL_FILENAME = "SOUL.md"
|
|||||||
DEFAULT_USER_FILENAME = "USER.md"
|
DEFAULT_USER_FILENAME = "USER.md"
|
||||||
DEFAULT_AGENTS_FILENAME = "AGENTS.md"
|
DEFAULT_AGENTS_FILENAME = "AGENTS.md"
|
||||||
DEFAULT_MEMORY_FILENAME = "MEMORY.md"
|
DEFAULT_MEMORY_FILENAME = "MEMORY.md"
|
||||||
|
DEFAULT_STATE_FILENAME = ".agent_state.json"
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -27,6 +29,7 @@ class WorkspaceFiles:
|
|||||||
agents_path: str
|
agents_path: str
|
||||||
memory_path: str
|
memory_path: str
|
||||||
memory_dir: str
|
memory_dir: str
|
||||||
|
state_path: str
|
||||||
|
|
||||||
|
|
||||||
def ensure_workspace(workspace_dir: str, create_templates: bool = True) -> WorkspaceFiles:
|
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)
|
agents_path = os.path.join(workspace_dir, DEFAULT_AGENTS_FILENAME)
|
||||||
memory_path = os.path.join(workspace_dir, DEFAULT_MEMORY_FILENAME) # MEMORY.md 在根目录
|
memory_path = os.path.join(workspace_dir, DEFAULT_MEMORY_FILENAME) # MEMORY.md 在根目录
|
||||||
memory_dir = os.path.join(workspace_dir, "memory") # 每日记忆子目录
|
memory_dir = os.path.join(workspace_dir, "memory") # 每日记忆子目录
|
||||||
|
state_path = os.path.join(workspace_dir, DEFAULT_STATE_FILENAME) # 状态文件
|
||||||
|
|
||||||
# 创建memory子目录
|
# 创建memory子目录
|
||||||
os.makedirs(memory_dir, exist_ok=True)
|
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,
|
user_path=user_path,
|
||||||
agents_path=agents_path,
|
agents_path=agents_path,
|
||||||
memory_path=memory_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}")
|
||||||
|
|
||||||
|
|||||||
@@ -323,6 +323,12 @@ class AgentBridge:
|
|||||||
context_files = load_context_files(workspace_root)
|
context_files = load_context_files(workspace_root)
|
||||||
logger.info(f"[AgentBridge] Loaded {len(context_files)} context files: {[f.path for f in context_files]}")
|
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
|
# Build system prompt using new prompt builder
|
||||||
prompt_builder = PromptBuilder(
|
prompt_builder = PromptBuilder(
|
||||||
workspace_dir=workspace_root,
|
workspace_dir=workspace_root,
|
||||||
@@ -340,8 +346,13 @@ class AgentBridge:
|
|||||||
tools=tools,
|
tools=tools,
|
||||||
context_files=context_files,
|
context_files=context_files,
|
||||||
memory_manager=memory_manager,
|
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")
|
logger.info("[AgentBridge] System prompt built successfully")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user