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}")