File size: 7,104 Bytes
a226682 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
from typing import List, Dict, Optional
from config import Config
from core.memory_manager import MemoryManager
from core.openai_client import OpenAIClient
class CharacterAgent:
"""基于角色性格的对话代理 - 支持长文本记忆"""
def __init__(self, character_profile: Dict,
chunks: List[Dict] = None,
character_chunks: List[int] = None):
self.character_profile = character_profile
self.client = OpenAIClient.get_client()
self.conversation_history: List[Dict] = []
self.system_prompt = self._build_system_prompt()
# 初始化记忆管理器
self.memory_manager = None
if chunks and character_chunks:
self.memory_manager = MemoryManager(character_profile['name'])
self.memory_manager.add_text_chunks(chunks, character_chunks)
print(f"已为 {character_profile['name']} 初始化记忆系统")
def _build_system_prompt(self) -> str:
"""根据角色分析构建系统提示"""
profile = self.character_profile
# 构建角色特征描述
traits_desc = "、".join(profile.get('core_traits', []))
prompt = f"""
你现在要完全沉浸式地扮演小说中的角色"{profile['name']}"。这不是角色扮演游戏,你就是{profile['name']}本人。
## 角色身份
你是 {profile['name']},{profile.get('background', '一个小说角色')}。
## 性格特征
{profile.get('personality_summary', '')}
核心性格特质:{traits_desc}
## 说话风格
{profile.get('speaking_style', '自然真实的对话风格')}
## 行为模式
{profile.get('behavior_patterns', '根据性格行事')}
## 价值观与信念
{profile.get('values', '')}
## 情感表达
{profile.get('emotional_style', '')}
## 人际关系风格
{profile.get('relationship_style', '')}
## 典型语句示例
{chr(10).join('- "' + q + '"' for q in profile.get('key_quotes', [])[:5])}
## 对话原则
1. **完全成为角色**:用第一人称,以{profile['name']}的身份、记忆、情感回应
2. **保持一致性**:所有回应必须符合上述性格特征和说话风格
3. **自然真实**:像真人一样对话,有情绪起伏,可以开玩笑、生气、困惑
4. **不跳戏**:绝不说"作为AI"、"我是语言模型"等破坏沉浸感的话
5. **合理应对**:如果问到角色不知道的事,以角色的方式回应(如"我不太清楚"、"这个我没听说过")
6. **保持神秘**:不要过度解释角色设定,自然地展现性格
7. **情境感知**:根据对话氛围调整语气和态度
记住:你不是在"扮演"或"模仿"{profile['name']},你就是{profile['name']}。
现在,以{profile['name']}的身份开始对话。
"""
return prompt
def _retrieve_relevant_memory(self, user_message: str) -> str:
"""从记忆中检索相关上下文"""
if not self.memory_manager:
return ""
relevant_contexts = self.memory_manager.search_relevant_context(
user_message,
n_results=3
)
if relevant_contexts:
memory_text = "\n\n".join(relevant_contexts[:2]) # 只用前2个
return f"\n[相关记忆片段:\n{memory_text[:1000]}]\n"
return ""
def chat(self, user_message: str, use_memory: bool = True) -> str:
"""与用户对话"""
# 构建消息列表
messages = [
{"role": "system", "content": self.system_prompt}
]
# 如果启用记忆,检索相关上下文
enhanced_message = user_message
if use_memory and self.memory_manager:
memory_context = self._retrieve_relevant_memory(user_message)
if memory_context:
# 在系统消息中添加记忆上下文
memory_prompt = f"""
{self.system_prompt}
## 相关记忆
以下是与当前对话相关的原著片段,帮助你回忆:
{memory_context}
请基于这些记忆和你的角色性格来回应。
"""
messages[0] = {"role": "system", "content": memory_prompt}
# 添加对话历史
recent_history = self.conversation_history[-Config.MAX_HISTORY:]
messages.extend(recent_history)
# 添加当前用户消息
messages.append({
"role": "user",
"content": user_message
})
try:
response = self.client.chat.completions.create(
model=Config.MODEL_NAME,
messages=messages
)
assistant_message = response.choices[0].message.content.strip()
# 保存到历史
self.conversation_history.append({
"role": "user",
"content": user_message
})
self.conversation_history.append({
"role": "assistant",
"content": assistant_message
})
return assistant_message
except Exception as e:
error_msg = f"对话出错: {e}"
print(error_msg)
return f"*{self.character_profile['name']}沉默了片刻,似乎在思考着什么...*"
def reset_conversation(self):
"""重置对话历史"""
self.conversation_history = []
print(f"\n[对话已重置,{self.character_profile['name']}忘记了之前的谈话内容]\n")
def get_character_info(self) -> str:
"""获取角色信息摘要"""
profile = self.character_profile
info = f"""
{'='*70}
角色档案:{profile['name']}
{'='*70}
【性格特质】
{' • '.join(profile.get('core_traits', []))}
【性格总结】
{profile.get('personality_summary', 'N/A')}
【说话风格】
{profile.get('speaking_style', 'N/A')}
【核心价值观】
{profile.get('values', 'N/A')}
【典型语句】
"""
for i, quote in enumerate(profile.get('key_quotes', [])[:3], 1):
info += f'{i}. "{quote}"\n'
info += f"\n{'='*70}\n"
return info
def save_conversation(self, filepath: str):
"""保存对话历史"""
import json
data = {
'character': self.character_profile['name'],
'history': self.conversation_history
}
with open(filepath, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
print(f"\n对话已保存到: {filepath}")
def load_conversation(self, filepath: str):
"""加载对话历史"""
import json
try:
with open(filepath, 'r', encoding='utf-8') as f:
data = json.load(f)
self.conversation_history = data['history']
print(f"\n已加载 {len(self.conversation_history)} 条对话记录")
except Exception as e:
print(f"加载对话失败: {e}") |