Update app.py
Browse files
app.py
CHANGED
|
@@ -192,104 +192,132 @@ class SpyAgent(BasicAgent):
|
|
| 192 |
def detect_spy_word(self):
|
| 193 |
"""分析历史发言,尝试识别卧底词(平民使用)"""
|
| 194 |
# 如果自己是卧底或者没有足够发言,跳过
|
| 195 |
-
if self.identity_identify() <= 0 or self.get_prior_speaker_count() <
|
| 196 |
return None
|
| 197 |
-
|
| 198 |
speak_history = self.memory.load_variable('speak_history')
|
| 199 |
if not speak_history:
|
| 200 |
return None
|
| 201 |
|
| 202 |
-
#
|
|
|
|
|
|
|
|
|
|
| 203 |
prompt = []
|
| 204 |
-
prompt.append('你
|
| 205 |
-
prompt.append(
|
| 206 |
prompt.append('游戏规则:6名玩家中,5人拿到相同的平民词,1人拿到与平民词相关但不同的卧底词。')
|
| 207 |
-
prompt.append('
|
| 208 |
-
prompt.append('请仔细分析以下玩家发言,寻找与平民词描述不一致的地方:\n')
|
| 209 |
|
| 210 |
-
# 添加玩家发言
|
| 211 |
for name, speaks in speak_history.items():
|
| 212 |
if name != self.memory.load_variable('name'):
|
| 213 |
-
for speak in speaks:
|
| 214 |
-
prompt.append(f"{name}: {speak}\n")
|
| 215 |
|
| 216 |
-
prompt.append('\n你
|
| 217 |
-
prompt.append('1.
|
| 218 |
-
prompt.append('2.
|
| 219 |
-
prompt.append('3.
|
| 220 |
-
prompt.append('\n
|
| 221 |
|
| 222 |
spy_word = self.llm_caller(''.join(prompt))
|
| 223 |
logger.info(f"卧底词推理原始返回: '{spy_word}'")
|
| 224 |
|
| 225 |
-
# 处理返回结果
|
| 226 |
if spy_word:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 227 |
cleaned_word = spy_word.strip().strip('"\'[]()()""「」『』').strip()
|
| 228 |
|
| 229 |
-
#
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
|
| 234 |
logger.info(f"成功推理出卧底词: '{cleaned_word}'")
|
| 235 |
return cleaned_word
|
| 236 |
|
| 237 |
return None
|
| 238 |
def detect_civilian_word(self):
|
| 239 |
-
"""分析历史发言,尝试识别平民词"""
|
| 240 |
speak_history = self.memory.load_variable('speak_history')
|
| 241 |
if not speak_history:
|
| 242 |
return None
|
| 243 |
|
| 244 |
-
|
|
|
|
| 245 |
prompt = []
|
| 246 |
-
prompt.append('你是《谁是卧底》游戏的
|
| 247 |
-
prompt.append(f'
|
| 248 |
-
prompt.append('
|
| 249 |
-
prompt.append('请
|
| 250 |
-
|
|
|
|
| 251 |
for name, speaks in speak_history.items():
|
| 252 |
if name != self.memory.load_variable('name'):
|
| 253 |
-
for speak in speaks:
|
| 254 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 255 |
|
| 256 |
-
prompt.append('\n推理步骤:')
|
| 257 |
-
prompt.append('1. 分析每个玩家发言中描述的特征')
|
| 258 |
-
prompt.append('2. 找出发言中的共同特征')
|
| 259 |
-
prompt.append('3. 根据这些特征,推测最可能的词语')
|
| 260 |
-
prompt.append('4. 考虑这个词与已知词"'+self.memory.load_variable("word")+'"的关系,两者应该相似但有明显区别')
|
| 261 |
-
prompt.append('\n请直接回答你推理出的词语(单词)。如果实在无法推理,只回答"未知"。')
|
| 262 |
-
# 调用LLM进行推理
|
| 263 |
civilian_word = self.llm_caller(''.join(prompt))
|
| 264 |
logger.info(f"平民词推理原始返回: '{civilian_word}'")
|
| 265 |
|
| 266 |
-
#
|
| 267 |
if civilian_word:
|
| 268 |
-
#
|
| 269 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 270 |
|
| 271 |
-
#
|
| 272 |
-
|
| 273 |
-
lines = cleaned_word.strip().split("\n")
|
| 274 |
-
for line in reversed(lines):
|
| 275 |
-
if line.strip() and len(line.strip()) < 30: # 找到最后一个非空且较短的行
|
| 276 |
-
cleaned_word = line.strip()
|
| 277 |
-
break
|
| 278 |
-
|
| 279 |
-
# 清理常见的格式符号和修饰语
|
| 280 |
-
cleaned_word = cleaned_word.strip().strip('"\'[]()()""「」『』').strip()
|
| 281 |
|
| 282 |
-
#
|
| 283 |
if ":" in cleaned_word or ":" in cleaned_word:
|
| 284 |
parts = re.split(r'[::]', cleaned_word)
|
| 285 |
cleaned_word = parts[-1].strip()
|
| 286 |
-
|
| 287 |
logger.info(f"清理后的平民词推理结果: '{cleaned_word}'")
|
| 288 |
|
| 289 |
-
# 验证
|
| 290 |
-
reject_words = ["未知", "不清楚", "无法
|
| 291 |
-
if (not any(reject in cleaned_word for reject in reject_words) and
|
| 292 |
-
len(cleaned_word)
|
| 293 |
cleaned_word != self.memory.load_variable("word")):
|
| 294 |
|
| 295 |
logger.info(f"成功推理出平民词: '{cleaned_word}'")
|
|
|
|
| 192 |
def detect_spy_word(self):
|
| 193 |
"""分析历史发言,尝试识别卧底词(平民使用)"""
|
| 194 |
# 如果自己是卧底或者没有足够发言,跳过
|
| 195 |
+
if self.identity_identify() <= 0 or self.get_prior_speaker_count() < 2: # 改为2个就可以尝试推测
|
| 196 |
return None
|
| 197 |
+
|
| 198 |
speak_history = self.memory.load_variable('speak_history')
|
| 199 |
if not speak_history:
|
| 200 |
return None
|
| 201 |
|
| 202 |
+
# 获取自己的词和可能的平民词
|
| 203 |
+
my_word = self.memory.load_variable("word")
|
| 204 |
+
|
| 205 |
+
# 构建更直接的推理提示
|
| 206 |
prompt = []
|
| 207 |
+
prompt.append(f'你正在玩《谁是卧底》游戏,你拿到的词是"{my_word}",你是平民。')
|
| 208 |
+
prompt.append('作为平民,你需要找出谁可能是卧底以及他们的卧底词是什么。')
|
| 209 |
prompt.append('游戏规则:6名玩家中,5人拿到相同的平民词,1人拿到与平民词相关但不同的卧底词。')
|
| 210 |
+
prompt.append(f'请分析以下玩家发言,判断谁可能拿到了与"{my_word}"相近但不同的词:\n')
|
|
|
|
| 211 |
|
| 212 |
+
# 添加玩家发言,并标记轮次以便分析
|
| 213 |
for name, speaks in speak_history.items():
|
| 214 |
if name != self.memory.load_variable('name'):
|
| 215 |
+
for i, speak in enumerate(speaks):
|
| 216 |
+
prompt.append(f"[轮次{i+1}] {name}: {speak}\n")
|
| 217 |
|
| 218 |
+
prompt.append('\n请先判断是否有玩家的发言与你的词不符合:')
|
| 219 |
+
prompt.append('1. 列出可疑的描述特征')
|
| 220 |
+
prompt.append('2. 考虑与你的词"' + my_word + '"最相近但有关键区别的可能卧底词')
|
| 221 |
+
prompt.append('3. 最后直接回答你认为的卧底词(单词或短词)')
|
| 222 |
+
prompt.append('\n如果所有玩家都在描述同一个词,且你确定无法判断卧底词,只回答"未知"。')
|
| 223 |
|
| 224 |
spy_word = self.llm_caller(''.join(prompt))
|
| 225 |
logger.info(f"卧底词推理原始返回: '{spy_word}'")
|
| 226 |
|
| 227 |
+
# 处理返回结果
|
| 228 |
if spy_word:
|
| 229 |
+
# 先检查是否包含长分析,提取最后一段或冒号后内容
|
| 230 |
+
if len(spy_word) > 50 and "\n" in spy_word:
|
| 231 |
+
# 尝试从最后几行提取答案
|
| 232 |
+
lines = spy_word.strip().split("\n")
|
| 233 |
+
for line in reversed(lines):
|
| 234 |
+
if len(line.strip()) < 30 and line.strip() and not line.strip().startswith("1.") and not line.strip().startswith("2."):
|
| 235 |
+
spy_word = line.strip()
|
| 236 |
+
break
|
| 237 |
+
|
| 238 |
+
# 清理格式符号
|
| 239 |
cleaned_word = spy_word.strip().strip('"\'[]()()""「」『』').strip()
|
| 240 |
|
| 241 |
+
# 处理冒号
|
| 242 |
+
if ":" in cleaned_word or ":" in cleaned_word:
|
| 243 |
+
parts = re.split(r'[::]', cleaned_word)
|
| 244 |
+
cleaned_word = parts[-1].strip()
|
| 245 |
+
|
| 246 |
+
# 扩大拒绝词列表
|
| 247 |
+
reject_patterns = ["未知", "不清楚", "无法确定", "不确定", "无法判断", "无法推理",
|
| 248 |
+
"无法识别", "难以确定", "没有足够", "不能确定"]
|
| 249 |
+
|
| 250 |
+
# 更灵活的验证条件
|
| 251 |
+
if (not any(pattern in cleaned_word.lower() for pattern in reject_patterns) and
|
| 252 |
+
len(cleaned_word) < 25 and len(cleaned_word) > 1 and
|
| 253 |
+
cleaned_word != my_word):
|
| 254 |
|
| 255 |
logger.info(f"成功推理出卧底词: '{cleaned_word}'")
|
| 256 |
return cleaned_word
|
| 257 |
|
| 258 |
return None
|
| 259 |
def detect_civilian_word(self):
|
| 260 |
+
"""分析历史发言,尝试识别平民词(卧底使用)"""
|
| 261 |
speak_history = self.memory.load_variable('speak_history')
|
| 262 |
if not speak_history:
|
| 263 |
return None
|
| 264 |
|
| 265 |
+
|
| 266 |
+
# 构建更清晰的提示
|
| 267 |
prompt = []
|
| 268 |
+
prompt.append('你是《谁是卧底》游戏中的卧底,需要推测出大多数玩家拿到的词语。')
|
| 269 |
+
prompt.append(f'你拿到的卧底词是"{self.memory.load_variable("word")}"。')
|
| 270 |
+
prompt.append('游戏规则:6名玩家中,5人拿到相同的平民词,1人(你)拿到不同的卧底词。')
|
| 271 |
+
prompt.append('请分析以下玩家发言,找出大多数玩家最可能在描述的共同词语:\n')
|
| 272 |
+
|
| 273 |
+
# 添加玩家发言
|
| 274 |
for name, speaks in speak_history.items():
|
| 275 |
if name != self.memory.load_variable('name'):
|
| 276 |
+
for i, speak in enumerate(speaks):
|
| 277 |
+
if speak.strip():
|
| 278 |
+
prompt.append(f"[轮次{i+1}] {name}: {speak}\n")
|
| 279 |
+
|
| 280 |
+
prompt.append('\n请分析步骤:')
|
| 281 |
+
prompt.append('1. 找出发言中的共同主题和特征')
|
| 282 |
+
prompt.append('2. 考虑这些特征最可能对应的词语')
|
| 283 |
+
prompt.append('3. 考虑这个词与你的词"'+self.memory.load_variable("word")+'"的关系')
|
| 284 |
+
prompt.append('\n请直接输出你认为大多数玩家在描述的词语(单个词)。不要输出分析过程。')
|
| 285 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 286 |
civilian_word = self.llm_caller(''.join(prompt))
|
| 287 |
logger.info(f"平民词推理原始返回: '{civilian_word}'")
|
| 288 |
|
| 289 |
+
# 增强的结果处理
|
| 290 |
if civilian_word:
|
| 291 |
+
# 如果是长回答,尝试提取最后一句或最简短的句子
|
| 292 |
+
if len(civilian_word) > 30:
|
| 293 |
+
if "\n" in civilian_word:
|
| 294 |
+
lines = [line for line in civilian_word.strip().split("\n") if line.strip()]
|
| 295 |
+
for line in reversed(lines):
|
| 296 |
+
if 1 < len(line.strip()) < 30:
|
| 297 |
+
civilian_word = line.strip()
|
| 298 |
+
break
|
| 299 |
+
# 如果包含句号,尝试提取最后一句
|
| 300 |
+
elif "。" in civilian_word:
|
| 301 |
+
sentences = civilian_word.split("。")
|
| 302 |
+
for sentence in reversed(sentences):
|
| 303 |
+
if 1 < len(sentence.strip()) < 30:
|
| 304 |
+
civilian_word = sentence.strip()
|
| 305 |
+
break
|
| 306 |
|
| 307 |
+
# 清理格式标记
|
| 308 |
+
cleaned_word = civilian_word.strip().strip('"\'[]()()""「」『』').strip()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 309 |
|
| 310 |
+
# 处理冒号
|
| 311 |
if ":" in cleaned_word or ":" in cleaned_word:
|
| 312 |
parts = re.split(r'[::]', cleaned_word)
|
| 313 |
cleaned_word = parts[-1].strip()
|
| 314 |
+
|
| 315 |
logger.info(f"清理后的平民词推理结果: '{cleaned_word}'")
|
| 316 |
|
| 317 |
+
# 更宽松的验证条件
|
| 318 |
+
reject_words = ["未知", "不清楚", "无法", "不确定", "难以"]
|
| 319 |
+
if (not any(reject in cleaned_word.lower() for reject in reject_words) and
|
| 320 |
+
len(cleaned_word) > 1 and len(cleaned_word) < 25 and
|
| 321 |
cleaned_word != self.memory.load_variable("word")):
|
| 322 |
|
| 323 |
logger.info(f"成功推理出平民词: '{cleaned_word}'")
|