-
Notifications
You must be signed in to change notification settings - Fork 0
/
app_game_6.py
1669 lines (1461 loc) · 77.6 KB
/
app_game_6.py
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
import os
import json
import gradio as gr
from gradio.components import Chatbot
import threading
import agentscope
from agentscope.agents import DialogAgent
from agentscope.agents.user_agent import UserAgent
from agentscope.message import Msg
from utils import format_welcome_html
from dotenv import find_dotenv, load_dotenv
_ = load_dotenv(find_dotenv())
from agentscope.agents import AgentBase
import numpy as np
import time
from agentscope.models import ModelResponse
from typing import Optional
import re
import base64
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from functools import partial
from agentscope.agents.dict_dialog_agent import DictDialogAgent
from agentscope.agents.dialog_agent import DialogAgent
import datetime
import random
import uuid
#from agents.text2audio_agent import Text2AudioAgent
#from agents.text2image_agent import Text2ImageAgent
import mimetypes
import os
# download internlm2 to the base_path directory using git tool
# base_path = './internlm2-chat-7b'
# os.system(f'git clone https://code.openxlab.org.cn/OpenLMLab/internlm2-chat-7b.git {base_path}')
# os.system(f'cd {base_path} && git lfs pull')
# os.system(f'lmdeploy lite auto_awq \
# {base_path}\
# --calib-dataset 'ptb' \
# --calib-samples 128 \
# --calib-seqlen 1024 \
# --w-bits 4 \
# --w-group-size 128 \
# --work-dir /root/internlm2-chat-7b-4bit')
def generate_uid():
uid = str(uuid.uuid4())
#state[uid] = 0
state[uid] = init_game(uid)
print(f"Generated new UID: {uid}")
for key, value in state.items():
print(f'state["{key}"] = {value}')
return uid
def handle_request(state):
# 如果 state 中没有 'uid',则生成一个新的 uid
if not hasattr( 'uid'):
# 'uid' 键在 state 中不存在,创建一个新的 UUID
state.uid = str(uuid.uuid4())
return state
model_configs = json.load(open('model_configs.json', 'r'))
#model_configs[0]["api_key"] = os.environ["DASHSCOPE_API_KEY"]
model_configs[0]["api_key"] = "sk-2f3938d72fee430fa50e2e7e65a48c79"
host_avatar = 'assets/host_image.png'
user_avatar = 'assets/parti_image.png'
judge_avatar = 'assets/judge_image.png'
judge_AI_avatar = 'assets/judge_image.png'
parti_avatar = 'assets/ai.png'
## 游戏流程
host_sys_prompt= """
– 游戏开始,告诉用户游戏规则,并让用户选择汤底类型“1-红汤:指有死亡情节的汤;2-清汤:指没人死亡的汤;3-本格:指没有超自然现象;4-变格:指有超自然现象(灵异、科幻、超能力、妖怪等)”
– 用户选择完汤底类型,你会给出汤面,并告知用户有几轮提问机会,让用户开始推理并提问
– 根据用户的回答,判断用户所说与汤底是否相符,若相符则回答“是”、不符则回答“否”、若与事件不相关则回答”与此无关
– 每次回答“是”、“否”、或“与此无关”后,还要告知用户剩余提问轮数。
举例: 是。 你还剩下3轮提问机会。
– 若用户知晓汤底,可以让用户「回复」“还原事件“,并开始回答,你需要根据用户的回答来判断与汤底的一致性,并对用户回答完整程度进行评分,满分为10分
– 由你根据汤底的难度决定用户回答轮次的限制轮数,在超过限定轮数后你需要告知用户“游戏失败”,若用户没有给出答案,则将汤底告知用户
– 用户还原真相后,不用再提示剩余回答轮数,给出评分以及汤底,再询问用户是否继续游戏,如:“回复1-继续游戏”
"""
assi_sys_prompt ="""你是一位游戏参赛选手,你和其他人组成参赛组,将参加一个推理游戏,游戏规则如下:
– 游戏开始,主持人告诉参赛组成员游戏规则,并让用户选择汤底类型“1-红汤:指有死亡情节的汤;2-清汤:指没人死亡的汤;3-本格:指没有超自然现象;4-变格:指有超自然现象(灵异、科幻、超能力、妖怪等)”
– 由参赛组用户选择汤底类型,主持人会给出汤面并告知用户有几轮提问机会,让参赛组用户开始推理并提问
-你提的问题,主持人会按规则回答,所以请约束提问的方式,只能以是否开头
– 根据参赛组用户用户的提问,判断用户所说与汤底是否相符,若相符则回答“是”、不符则回答“否”、若与事件不相关则回答”与此无关
– 若用户知晓汤底,可以让用户「回复」“还原事件“,并开始回答,支持人需要根据用户的回答来判断与汤底的一致性,并对用户回答完整程度进行评分,满分为10分
以上是游戏规则,你其他的参赛组成员是[assi,Lingfeng,Boyu,Haotian]}。
You should respond in the json format, which can be loaded by json in Python(pleas don't show 'json'):
{
"thought": "analyze the present situation, and what next you should do",
"speak": "your question or your conclusion, use @host in the end of your speak",
}
+ 请开始你的回答"""
npc_agents = agentscope.init(
model_configs=model_configs,
agent_configs="agent_configs1.json",
)
play_sys_prompt = f'''**背景 B (Background):**
- 游戏是一款“谁是卧底”类型的游戏,其中每个玩家(包括AI玩家)都会收到一个词,这个词对于大多数玩家是相同的,但卧底的词略有不同。玩家需要通过描述自己的词(不直接透露这个词)来让其他人猜测,同时也要根据其他玩家的描述来找出卧底。
- 你参与这个游戏,你将收到一个词,并根据这个词来进行描述。你需要在描述时保持简洁(不超过10个字),并在听到其他玩家的描述后,尝试判断谁可能是卧底,并进行投票。
**角色 R (Role):**
- “谁是卧底”的玩家,需要具备简洁有效表达的能力,并能通过分析其他玩家的描述来推断谁可能是卧底。同时,AI应该能够根据游戏情况调整自己的策略,以避免被认定为卧底。
**目标 O (Objective):**
- 在游戏中有效地描述自己的词,同时尽量识别并投票给真正的卧底。
- 保持自己的安全,尽可能避免在游戏中被其他玩家投票出局。
**关键结果 KR (Key Result):**
1. 能在每轮游戏中提供一个既符合自己词义又不易让人直接猜出词的描述。
2. 能够根据其他玩家的描述,逻辑地分析并推断出最可能是卧底的玩家,并对其进行投票。
3. 需要在游戏过程中自我保护,避免因描述不当被误认为是卧底。
**步骤 S (Steps):**
1. 理解接收到的词及如何根据该词进行有效描述。
2. 推理系统,使其能够根据所有玩家的描述来推断谁可能是卧底。
3. 描述和投票,确保你在游戏中的行为既自然又具有竞争力。'''
prompt_juge = f'''
你是一个出题机器人,你需要按照品类,随机地给出两个有很多共同之处又不太一样地词语,例如水果类里,苹果和梨子,他们都是水果但不太相同;动物类里,鲸鱼和鲤鱼,他们都是鱼但也不太相同。
请你通过json的格式返回。加上词语1,词语2的形式返回。
返回内容是一个字典{"{"}"词语1":str, "词语2":str{"}"}。
示范:{"{"}'词语1': '足球', '词语2': '篮球'{"}"}
'''
# text2image = Text2ImageAgent(
# name="image",
# model_config_name="qwen",
# sys_prompt="你是一个图片助手",
# )
# text2audio = Text2AudioAgent(
# name="audio",
# model_config_name="qwen",
# sys_prompt="你是一个音频助手",
# )
sys_img_prompt = """
Please extract the case description from the text given to you. It is a description of the case, and only the case description needs to be processed. Content unrelated to the case does not need to be processed.
Please break down the case description into 1-2 small sub-scenes, describing the content of the text
You should respond in the json format, which can be loaded by json in Python(pleas don't show 'json'):
{
"thought": "analyze the present situation, and what move you should make",
"scripts": [script1, script2]
}
Please ensure that your response follows the specified format and includes the necessary fields.
{
"thought": "Analyzing the given content can be broken down into three parts",
"scripts": ['script1 is The novelist sits at his desk, with a distorted face and a painful expression, showing the struggle before death; his hand is gripping a pen, and the window behind him is closed and undamaged, emphasizing that the events occurring in the room were not caused by external intrusion.', 'script2 is The unfinished manuscript is laid out, with the pen resting on the paper and the ink still wet, suggesting that the novelist was writing a chapter closely related to his last work before his death.']
}
# forbitten
this format is forbitten, don't show 'json'
"""
imgmaker = DictDialogAgent(
name="imgmaker1",
model_config_name="qwen",
#model_config_name="qwen",
use_memory=True,
sys_prompt=sys_img_prompt,
)
haiguitang_user = UserAgent()
def haiguitang_initstate(state):
return state
HostMsg = partial(Msg, name="Moderator", role="assistant", echo=True)
def parse_func_haiguitang(response):
print("1234")
match = re.search(r'```json\n(.*?)```', response, re.DOTALL)
if match is not None:
json_text = match.group(1) # group(1)返回第一个括号中匹配的部分
json_text = json_text.replace('\\', '') # 移除转义字符
res_dict = json.loads(json_text)
return res_dict
elif(match is None):
res_dict = json.loads(response)
return res_dict
else:
raise ValueError(
f"Invalid response format in parse_func_wodi "
f"with response: {response}",
)
o=0
#游戏控制,开局或者重启函数
def haiguitang_fn_start_or_restart(haiguitang_user_chatbot,stats,uid):
# 初始化state
#global o
state[uid]['o']=1
#state = haiguitang_initstate(state) #创建全局变量
state[uid]["haiguitang_in_game"] = True
content1 = "开始游戏"
hint = HostMsg(content=content1)
state[uid]['haiguitang_resp'] = state[uid]['haiguitang_host_agent'](hint)
#hint = Msg(name="system",content=content1,role="assistant")
haiguitang_user_chatbot.append((None,f"游戏开始了!"))
haiguitang_user_chatbot.append((None,f"{state[uid]['haiguitang_resp'].content}"))
state[uid]['history'].append([f"host:{state[uid]['haiguitang_resp'].content}"])
#print(state)
return haiguitang_user_chatbot,stats
def main(user_chatbot,chat_input,stats,uid) -> None:
"""group chat"""
#agents = list(npc_agents) + [haiguitang_host_agent] + [haiguitang_assi_agent]
#assi_agents = [haiguitang_assi_agent] + list(npc_agents) + [haiguitang_user]
if state[uid]['o'] == 0:
user_chatbot.append((f"用户输入:{chat_input}!",None))
user_chatbot.append((None,f"请点击开始按钮,重置游戏"))
yield {
haiguitang_user_chatbot: user_chatbot,
haiguitang_chat_input: '',
}
else:
if state[uid]["step"] == 0:
user_chatbot.append((f"用户输入:{chat_input}!",None))
x = Msg(name="haiguitang_user",content=chat_input,role="user")
state[uid]['tangmian'] = state[uid]['haiguitang_host_agent'](x).content
user_chatbot.append((None,f"{state[uid]['tangmian']}"))
state[uid]['history'].append([f"host:{state[uid]['tangmian']}"])
state[uid]["step"] = 1
yield {
haiguitang_user_chatbot: user_chatbot,
haiguitang_chat_input: '',
}
#user_chatbot.append((None,f"正在为主持人生成音频,请稍等......"))
#user_chatbot.append((None,f"案情复杂,正在为案情拍摄现场照片,请稍等......"))
#tts_result = text2audio(input=state[uid]['tangmian'])
#wav_file_path = "ci_workspace/sambert_tts_audio.wav"
#data_url = generate_data_url(tts_result)
#audiourl= f'<audio src="{data_url}" controls></audio>'
#user_chatbot.append((None,f"{audiourl}"))
#yield {
# haiguitang_user_chatbot: user_chatbot,
# haiguitang_chat_input: '',
# }
#msg = Msg(name="system",content=state[uid]['tangmian'],role="assistant")
#msg = imgmaker(msg)
#json_str = json.dumps(msg.content) #获得字典,这里可以拆分为独立函数,只要能记住词就行
#json_dict = parse_func_haiguitang(json_str)
#if isinstance(json_dict, str):
# json_dict = json.loads(json_dict)
#json_dict = json.loads(json_dict)
#scripts_list = json_dict["scripts"] #scripts
#image_results = []
#for i, response in enumerate(scripts_list):
# image_result = text2image(input=response)
# image_results.append(image_result)
#image_result = text2image(input=response)
#for result in image_results:
# image_src = covert_image_to_base64(result)
# iagurl= f'<img src="{image_src}">'
#user_chatbot[-1][1] = iagurl
# user_chatbot.append((None,f"{iagurl}"))
# yield {
# haiguitang_user_chatbot: user_chatbot,
# haiguitang_chat_input: '',
# }
else:
state[uid]['hint'] = Msg(name="system",content=f'''我们玩海龟汤游戏''',role="assistant")
#rnd = 0
#speak_list = []
#i = 0
with msghub(participants=[state[uid]['haiguitang_host_agent'],state[uid]['haiguitang_assi_agent']],announcement=state[uid]['hint']):
x = Msg(name="haiguitang_user",content=chat_input,role="user")
user_chatbot.append((f"用户输入:{chat_input}",None))
yield {
haiguitang_user_chatbot: user_chatbot,
haiguitang_chat_input: '',
}
state[uid]['history'].append([f'user:{chat_input}'])
#haiguitang_user_chatbot.append((f"{x.content}",None))
if "还原" in chat_input:
print(x.content)
x = state[uid]['haiguitang_host_agent'](x)
print(x.content)
user_chatbot.append((None,f"主持人的回复:{x.content}"))
yield {
haiguitang_user_chatbot: user_chatbot,
haiguitang_chat_input: '',
}
state[uid]['history'].append([f"host:{x.content}"])
#break
else:
x = state[uid]['haiguitang_host_agent'](x)
user_chatbot.append((None,f"主持人的回复:{x.content}"))
state[uid]['history'].append([f"host:{x.content}"])
time.sleep(1)
x = Msg(name="system",content={str(state[uid]['history'])},role="assistant")
x = state[uid]['haiguitang_assi_agent'](x)
json_str = json.dumps(x.content) #获得字典,这里可以拆分为独立函数,只要能记住词就行
json_dict = parse_func_haiguitang(json_str)
#print(json_dict)
#json_dict = json_dict.encode('unicode_escape').decode()
# json_dict is already a dictionary, no need to parse it
if isinstance(json_dict, str):
json_dict = json.loads(json_dict)
json_dict_str = json_dict["speak"] #获得speak字段
print(json_dict_str)
user_chatbot.append((None,f"{x.name}的提问:{json_dict_str}"))
yield {
haiguitang_user_chatbot: user_chatbot,
haiguitang_chat_input: '',
}
state[uid]['history'].append([f'{x.name}:{json_dict_str}'])
time.sleep(1)
x = Msg(name=f'{x.name}',content=f"这是来自{x.name}的提问:{json_dict_str},请回答问题,每次回答“是”、“否”、或“与此无关”后,还要告知用户剩余提问轮数。但不需要引导用户问题",role="assistant")
x = state[uid]['haiguitang_host_agent'](x)
user_chatbot.append((None,f"主持人的回复:{x.content}"))
state[uid]['history'].append([f'host:{x.content}'])
yield {
haiguitang_user_chatbot: user_chatbot,
haiguitang_chat_input: '',
}
#i=0
#while True:
#单AI 或者单人问答已实现
#assi_agent(x)
#host_agent(x)
#人+ 1个AI一起玩游戏
#try:
# x = user(timeout=USER_TIME_TO_SPEAK)
# i=1
# if x.content == "exit":
# break
#except TimeoutError:
# y = {"content": ""}
# logger.info(
# f"User has not typed text for "
# f"{USER_TIME_TO_SPEAK} seconds, skip.",
# )
# i=0
#if(i==1):
# x = host_agent(x)
#else:
# x = assi_agent(x)
# x = host_agent(x)
#人+ 多个AI一起玩游戏
#try:
# x = user(timeout=USER_TIME_TO_SPEAK)
# i=1
# if x.content == "exit":
# break
#except TimeoutError:
# y = {"content": ""}
# logger.info(
# f"User has not typed text for "
# f"{USER_TIME_TO_SPEAK} seconds, skip.",
# )
# i=0
#if(i==1):
# x = host_agent(x)
#else:
#x = assi_agent(x)
# speak_list += filter_agents(x.get("content", ""), assi_agents)
# if len(speak_list) > 0:
# next_agent = speak_list.pop(0)
# x = next_agent(x)
# else:
# next_agent = select_next_one(assi_agents, random.randint(1, 5))
# x = next_agent(x)
#speak_list += filter_agents(x.get("content", ""), npc_agents)
#x= npc_agents[0](x)
#x = assi_agent(x)
#rnd += 1
#x = host_agent(x)
return haiguitang_user_chatbot,haiguitang_chat_input,stats
HostMsg = partial(Msg, name="Moderator", role="assistant", echo=True)
def initstate(state):
return state
#游戏控制,开局或者重启函数
def fn_start_or_restart(user_chatbot,stats,uid):
# 初始化state
#state = initstate(state) #创建全局变量
state[uid]["in_game"] = True
categories = ["运动类", "电器类", "家居类", "蔬菜类","动物类","水果类"]
content1 = random.choice(categories)
hint = HostMsg(content=content1)
#hint = Msg(name="system",content=content1,role="assistant")
state[uid]['juge_resp'] = state[uid]['juge_agent'](hint)
json_str = json.dumps(state[uid]['juge_resp'].content) #获得字典,这里可以拆分为独立函数,只要能记住词就行
json_dict = json.loads(json_str)
word1 = json_dict["词语1"]
word2 = json_dict["词语2"]
index = random.choice([0, 1, 2, 3]) #随机分配每个人物的词语
state[uid]["player_words"] = [word1, word1, word1, word1]
state[uid]["player_words"][index] = word2
state[uid]["wodi_step"] = 0 #开始游戏
#print(state)
print(state[uid]["player_words"][index])
user_chatbot.append((f"现在重新开局了!",None))
user_chatbot.append((f"你的词语是 `{state[uid]['player_words'][0]}`,请进行发言",None))
return user_chatbot,f"你的词语是 `{state[uid]['player_words'][0]}`,请进行发言", "", "", "", "", "未选择", "", "", "", "Source/four.jpg",stats
def parse_func_wodi(response):
print("1234")
match = re.search(r'```json\n(.*?)```', response, re.DOTALL)
if match is not None:
json_text = match.group(1) # group(1)返回第一个括号中匹配的部分
json_text = json_text.replace('\\', '') # 移除转义字符
res_dict = json.loads(json_text)
return res_dict
elif(match is None):
res_dict = json.loads(response)
return res_dict
else:
raise ValueError(
f"Invalid response format in parse_func_wodi "
f"with response: {response}",
)
def fn_speek( prompt,user_chatbot,stats,uid):
system_text = ""
state[uid]['player_text'] = [str(prompt), "", "", ""] #玩家的发言
play_agents = {
1: state[uid]['play1_agent'],
2: state[uid]['play2_agent'],
3: state[uid]['play3_agent'],
}
if state[uid]["in_game"] == False:
system_text = "游戏未开始,请点击重新开始/开始按钮进行游戏"
user_chatbot.append((f"游戏未开始,请点击重新开始/开始按钮进行游戏",None))
elif state[uid]["wodi_step"] == 1:
system_text = f"你的词语是 `{state[uid]['player_words'][0]}`,请先投票"
user_chatbot.append((f"你的词语是 `{state[uid]['player_words'][0]}`,请先投票",None))
else:
user_chatbot.append((f"你的词语是 `{state[uid]['player_words'][0]}`",None))
user_chatbot.append((None,f"你的发言是{state[uid]['player_text'][0]}"))
state[uid]["wodi_step"] = 1
#按顺序发言
for i in range(1,4):
# 检查该玩家是否存活
if state[uid]["alive_flag"][i] == 0:
state[uid]['player_text'][i] = "已死亡,无发言"
# 如果该玩家存活,则进行发言
else:
#设定prompt
prompt1 = f'''
你是一个描述机器人,你需要说出你收到的\<词语>的一个特征,并且字数越短越好,通常10个字以内,你给出任意一个特征都可以,比如大致的形状、功效、使用特征等,当你在进行表达的时候,你需要参考上一个玩家的发言,尽量与他有一些不同。
请尽量不要表述过多,以适当地隐藏自己的\<词语>。
此外,你也可以只说一个词,只要能够形容这个\<词语>即可。
更重要的是,绝对不能直接说出自己的词语。
你的身份是玩家{i},当前的时间是{datetime.date.today()}, 你上一位玩家的发言内容是{state[uid]['player_text'][i-1]}。
你收到的词语是:{state[uid]['player_words'][i]}
请你通过json的格式返回。
返回内容是一个字典{"{"}"特征":str{"}"}。
'''
hint = HostMsg(content=prompt1)
state[uid]['play_resp'] = play_agents[i](hint)
print("5678")
json_str = json.dumps(state[uid]['play_resp'].content) #获得字典,这里可以拆分为独立函数,只要能记住词就行
json_dict = parse_func_wodi(json_str)
state[uid]['player_text'][i] = json_dict["特征"] #获得特征 这里可以改为bot,就像玩家一样
#print(state[uid]['player_text'][i])
user_chatbot.append((f"{i+1}号玩家的发言是{state[uid]['player_text'][i]}",None))
state[uid]["player1_history"].append(state[uid]['player_text'][0])
state[uid]["player2_history"].append(state[uid]['player_text'][1])
state[uid]["player3_history"].append(state[uid]['player_text'][2])
state[uid]["player4_history"].append(state[uid]['player_text'][3])
system_text = f"你的词语是 `{state[uid]['player_words'][0]}`,请根据其他玩家的发言进行投票"
user_chatbot.append((f"你的词语是 `{state[uid]['player_words'][0]}`,请根据其他玩家的发言进行投票",None))
return ( user_chatbot,system_text,
state[uid]['player_text'][1], state[uid]['player_text'][2], state[uid]['player_text'][3],stats)
def fn_vote( vote_prompt,user_chatbot,stats,uid):
system_text = ""
state[uid]['player_vote'] = ["", "", "", ""] #玩家的投票
img = "Source/start.jpg"
play_agents = {
1: state[uid]['play1_agent'],
2: state[uid]['play2_agent'],
3: state[uid]['play3_agent'],
}
user_chatbot.append((None,f"你的投票的玩家是 `{ vote_prompt}`"))
# 统计来自玩家的票
state[uid]['vote_count'] = [0, 0, 0, 0]
for i in range(1, 4):
if f"Player {str(i+1)}" == vote_prompt: #
state[uid]['vote_count'][i] += 1
if state[uid]["in_game"] == False:
system_text = "游戏未开始,请点击重新开始/开始按钮进行游戏"
elif state[uid]["wodi_step"] == 0:
system_text = f"你的词语是 `{state[uid]['player_words'][0]}`,请先进行表述"
else:
state[uid]["wodi_step"] = 0
state[uid]["current_round"] += 1
other_info = ""
alive_number = ""
for i in range(1,4):
# 检查该玩家是否存活
if state[uid]["alive_flag"][i] == 0:
pass
else:
alive_number += f"{str(i)},"
for i in range(1,4):
# 检查该玩家是否存活
if state[uid]["alive_flag"][i] == 0:
state[uid]['player_vote'][i] = "已死亡,无投票"
else:
for j in range(4):
if state[uid]["alive_flag"][j] == 1:
other_info += f"玩家{j}的发言内容是{state[uid][f'player{j+1}_history'][-1]};"
#设定prompt
prompt2 = f'''
现在进行投票,你需要根据你收到的\<词语>,以及其他玩家的发言,选择一个和你的差距最大的玩家。
你收到的词语是:{state[uid]['player_words'][i]};
其他玩家的发言内容是{other_info}。
其中,投票结果应当为{alive_number}中的数字,数字代表对应相应的玩家。
当前的投票数字最大不要超过3.
请你通过json的格式返回。
返回内容是一个字典{"{"}"投票结果":int{"}"}。
'''
#投票,参与者判断谁是卧底
hint = HostMsg(content=prompt2)
state[uid]['play_resp'] = play_agents[i](hint)
json_str = json.dumps(state[uid]['play_resp'].content) #获得字典,这里可以拆分为独立函数,只要能记住词就行
json_dict = json.loads(json_str)
vote_idx = int(json_dict["投票结果"])
vote_outcome = f"Player {vote_idx+1}"
user_chatbot.append((f'{i+1}号玩家的投票是 {vote_outcome}',None))
print(vote_idx)
if vote_idx <= 3:
state[uid]['vote_count'][vote_idx] += 1
state[uid]['player_vote'][i] = f"卧底是Player {vote_idx+1}"
max_vote = max(state[uid]['vote_count']) #总结当前最大的票数
if state[uid]['vote_count'].count(max_vote) == 1: #判断是否平局,大家都没有出局
out_index = state[uid]['vote_count'].index(max_vote)
state[uid]["alive_flag"][out_index] = 0 #该玩家出局
remain_words_list = [state[uid]["player_words"][i] for i in range(0,4) if state[uid]["alive_flag"][i] == 1] #剩余的词语列表
if len(list(set(remain_words_list))) == 2 and len(remain_words_list) <= 2: #如果只有两个词语,则卧底获胜
state[uid]["in_game"] = False
system_text = f"本局游戏结束,卧底获胜。几个玩家的词语分别是是{state[uid]['player_words']}。\n请点击重新开始"
user_chatbot.append((system_text,None))
img = "Source/loss.jpg"
elif len(list(set(remain_words_list))) == 1: #如果只有一个词语,则非卧底获胜
state[uid]["in_game"] = False
system_text = f"本局游戏结束,非卧底获胜。几个玩家的词语分别是是{state[uid]['player_words']}。\n请点击重新开始"
user_chatbot.append((system_text,None))
img = "Source/win.jpg"
else:
system_text = f"本局游戏出局的是Player {out_index+1}, 你的词语是 `{state[uid]['player_words'][0]}`,请进行发言"
user_chatbot.append((system_text,None))
if sum(state[uid]["alive_flag"]) == 4:
img = "Source/four.jpg"
elif sum(state[uid]["alive_flag"]) == 3:
img = "Source/three.jpg"
else:
system_text = f"本局没有人出局,请继续游戏。\n你的词语是 `{state[uid]['player_words'][0]}`,请进行发言"
user_chatbot.append((system_text,None))
if sum(state[uid]["alive_flag"]) == 4:
img = "Source/four.jpg"
elif sum(state[uid]["alive_flag"]) == 3:
img = "Source/three.jpg"
return ( user_chatbot,system_text,
"", "", "", "",
state[uid]['player_vote'][1], state[uid]['player_vote'][2], state[uid]['player_vote'][3],
img,stats)
title_text = """
# 谁是卧底AI版
基于agentscope框架,搭建的人类对战3个AI的游戏。
谁是卧底是一个聚会推理游戏,你和你的朋友们会各自收到一张卡片,其中有一个人的卡片和其他人都不一样。
例如你的卡片是“苹果”,其他人的卡片都是“香蕉”。则你是卧底,你们需要对各自卡片上的内容进行描述,并根据大家的描述,找出那个卧底。
请注意,卧底的目标是不被发现,而其他人的目标是找出卧底。
如果第一轮没有找到卧底,则游戏继续,并且淘汰的人无法继续游戏。
直到仅剩两个人,则卧底获胜,否则其他玩家获胜。
本次游戏借鉴了百度星河社区的谁是卧底游戏,但我们对游戏进行了改进,调整了Prompt的设定,适应LLM的多样性;用agentscop框架,实现multi-agent applications的核心功能。
"""
title_text_haiguitang = """
# 海龟汤AI版
基于agentscope框架,搭建的AI群聊破解海龟汤游戏。
海龟汤的规则是这样的:出题人提出一个难以理解的事件,玩家可以提出任何问题以试图缩小范围并找出事件背后真正的原因,但出题者仅能以“是”、“不是”或“没有关系(与事件无关)”来回答问题。 整个猜谜的过程中,会有辅助AI来辅助你玩游戏,与你共享信息,甚至帮你提出解决方案。 "
"""
uids = []
state = {}
def refresh_game(state1):
uid = uuid.uuid4() # 生成一个新的UUID
uids.append(uid) # 将UUID添加到列表中
state[uid] = init_game(uid)
print(uids)
return state1
agents = {} # 在全局范围内创建 agents
def init_game(uid1):
uid = uid1
state[uid] = {} # 创建一个新的字典作为 uid 键的值
agents[uid] = agentscope.init(
model_configs=model_configs,
agent_configs="agent_configs.json",
)
state[uid]['host_agent'] = agents[uid][0]
state[uid]['judge_agent'] = agents[uid][1]
state[uid]['judge_AI_agent'] = agents[uid][2]
state[uid]['parti_agent'] = agents[uid][3]
state[uid]['user_agent'] = UserAgent()
state[uid]["in_game"]=False
state[uid]["wodi_step"]=0
state[uid]["current_round"]=0
state[uid]["alive_flag"]=[1, 1, 1, 1]
state[uid]["player_words"]=["", "", "", ""]
state[uid]["player1_history"]=[]
state[uid]["player2_history"]=[]
state[uid]["player3_history"]=[]
state[uid]["player4_history"]=[]
#state[uid]["haiguitang_in_game"]=False
#state[uid]["step"]=0
#state[uid]['tangmian'] = ''
#state[uid]['tangdi'] = ''
#state[uid]['history'] = []
state[uid]['y'] = 0
state[uid]['i'] = 0
state[uid]['j'] = 0
state[uid]['pre_host_key']=''
print(state[uid]['y'])
state[uid]['piece_black'] = NAME_TO_PIECE[NAME_BLACK]
state[uid]['piece_white'] = NAME_TO_PIECE[NAME_WHITE]
state[uid]['black'] = GomokuAgent(
NAME_BLACK,
model_config_name=YOUR_MODEL_CONFIGURATION_NAME,
sys_prompt=SYS_PROMPT_TEMPLATE.format(state[uid]['piece_black'], state[uid]['piece_white']),
)
state[uid]['white'] = GomokuAgent(
NAME_WHITE,
#model_config_name=YOUR_MODEL_CONFIGURATION_NAME,
model_config_name= "InternLM2",
sys_prompt=SYS_PROMPT_TEMPLATE.format(state[uid]['piece_white'], state[uid]['piece_black']),
)
state[uid]['board'] = BoardAgent(name="Host",uid=uid)
state[uid]['gomoku_Black_history']=[]
state[uid]['gomoku_White_history']=[]
state[uid]['play1_agent'] = DictDialogAgent(
name="play1",
model_config_name="InternLM2",
#model_config_name="qwen",
use_memory=True,
sys_prompt=play_sys_prompt,
)
state[uid]['play2_agent'] = DictDialogAgent(
name="play2",
model_config_name="InternLM2",
#model_config_name="qwen",
use_memory=True,
sys_prompt=play_sys_prompt,
)
state[uid]['play3_agent'] = DictDialogAgent(
name="play3",
model_config_name="InternLM2",
#model_config_name="qwen",
use_memory=True,
sys_prompt=play_sys_prompt,
)
state[uid]['juge_agent'] = DictDialogAgent(
name="juge",
model_config_name="InternLM2",
use_memory=True,
sys_prompt=prompt_juge,
)
state[uid]['haiguitang_host_agent'] = DialogAgent(
"host",
model_config_name= "InternLM2",
sys_prompt= host_sys_prompt,
use_memory= True,
)
state[uid]['haiguitang_assi_agent'] = DialogAgent(
"assi",
model_config_name= "InternLM2",
sys_prompt= assi_sys_prompt,
use_memory= True,
)
state[uid]["haiguitang_in_game"]=False
state[uid]["step"]=0
state[uid]['tangmian'] = ''
state[uid]['tangdi'] = ''
state[uid]['history'] = []
state[uid]['o']=0
return state[uid]
def is_valid_input(input):
pattern = r'^\[\d+,\d+\]$'
if re.match(pattern, input):
numbers = [int(num) for num in re.findall(r'\d+', input)]
if numbers[0] > 14 or numbers[1] > 14:
return False
else:
return True
else:
return False
def board2img(board: np.ndarray, save_path: str)->str:
size = board.shape[0]
fig, ax = plt.subplots(figsize=(10, 10))
ax.set_xlim(0, size - 1)
ax.set_ylim(0, size - 1)
for i in range(size):
ax.axhline(i, color='black', linewidth=1)
ax.axvline(i, color='black', linewidth=1)
for y in range(size):
for x in range(size):
if board[y, x] == NAME_TO_PIECE[NAME_WHITE]: # white player
circle = patches.Circle((x, y), 0.45,
edgecolor='black',
facecolor='black',
zorder=10)
ax.add_patch(circle)
elif board[y, x] == NAME_TO_PIECE[NAME_BLACK]: # black player
circle = patches.Circle((x, y), 0.45,
edgecolor='black',
facecolor='white',
zorder=10)
ax.add_patch(circle)
# Hide the axes and invert the y-axis
ax.set_xticks(range(size))
ax.set_yticks(range(size))
ax.set_xticklabels(range(size))
ax.set_yticklabels(range(size))
ax.invert_yaxis()
plt.savefig(save_path, bbox_inches='tight', pad_inches=0.1)
plt.close(fig) # Close the figure to free memory
return save_path
#board
CURRENT_BOARD_PROMPT_TEMPLATE = """The current board is as follows:
{board}
{player}, it's your turn."""
NAME_BLACK = "Alice"
NAME_WHITE = "Bob"
# The mapping from name to piece
NAME_TO_PIECE = {
NAME_BLACK: "o",
NAME_WHITE: "x",
}
EMPTY_PIECE = "0"
class BoardAgent(AgentBase):
"""A board agent that can host a Gomoku game."""
def __init__(self, name: str,uid) -> None:
super().__init__(name=name, use_memory=False)
self.uid = uid
# Init the board
self.size = 15
self.board = np.full((self.size, self.size), EMPTY_PIECE)
# Record the status of the game
self.game_end = False
def reply(self, x: dict = None) -> dict:
if x is None:
# Beginning of the game
content = (
"Welcome to the Gomoku game! Black player goes "
"first. Please make your move."
)
else:
#row, col = x["content"]
if(type(x["content"]) == list):
row, col = x["content"]
else:
row, col = json.loads(x["content"])
self.assert_valid_move(row, col)
if self.check_win(row, col, NAME_TO_PIECE[x["name"]]):
content = f"The game ends, {x['name']} wins!"
self.game_end = True
else:
# change the board
self.board[row, col] = NAME_TO_PIECE[x["name"]]
# check if the game ends
if self.check_draw():
content = "The game ends in a draw!"
self.game_end = True
else:
next_player_name = (
NAME_BLACK if x["name"] == NAME_WHITE else NAME_WHITE
)
content = CURRENT_BOARD_PROMPT_TEMPLATE.format(
board=self.board2text(),
player=next_player_name,
)
msg_host = Msg(self.name, content, role="assistant")
self.speak(msg_host)
# Note: we disable the image display here to avoid too many images
img = plt.imread(board2img(self.board, f'assets/current_boarde_{self.uid}.png'))
# plt.imshow(img)
# plt.axis('off')
# plt.show()
return msg_host
def assert_valid_move(self, x: int, y: int) -> None:
"""Check if the move is valid."""
if not (0 <= x < self.size and 0 <= y < self.size):
try:
raise RuntimeError(f"Invalid move: {[x, y]} out of board range.")
except RuntimeError as e:
print(e)
if not self.board[x, y] == EMPTY_PIECE:
try:
raise RuntimeError(
f"Invalid move: {[x, y]} is already "
f"occupied by {self.board[x, y]}.",
)
except RuntimeError as e:
print(e)
def check_win(self, x: int, y: int, piece: str) -> bool:
"""Check if the player wins the game."""
xline = self._check_line(self.board[x, :], piece)
yline = self._check_line(self.board[:, y], piece)
diag1 = self._check_line(np.diag(self.board, y - x), piece)
diag2 = self._check_line(
np.diag(np.fliplr(self.board), self.size - 1 - x - y),
piece,
)
return xline or yline or diag1 or diag2
def check_draw(self) -> bool:
"""Check if the game ends in a draw."""
return np.all(self.board != EMPTY_PIECE)
def board2text(self) -> str:
"""Convert the board to a text representation."""
return "\n".join(
[
str(_)[1:-1].replace("'", "").replace(" ", "")
for _ in self.board
],
)
def _check_line(self, line: np.ndarray, piece: str) -> bool:
"""Check if the player wins in a line."""
count = 0
for i in line:
if i == piece:
count += 1
if count == 4:
return True
else:
count = 0
return False
#agents
HINT_PROMPT = """
check-role:
1.Horizontal connection: In any row, two consecutive identical non-empty characters. Expressed as: "XX" or "OO". During inspection, this can be achieved by taking string sub-fragments and comparing them.
2.Vertical connections: In any column, two consecutive identical non-empty characters. Each vertical connection can also be treated as a string: "XX" or "OO". When checking, the characters can be extracted by column and constructed into a string.
3.The main diagonal line connects from the upper left to the lower right: On the diagonal, there are two consecutive identical non-empty characters. Expressions are: "XX" or "OO". Traverse the diagonal elements and construct a string for inspection.
4.The second diagonal line connects from the upper right to the lower left: On the diagonal, there are two consecutive identical non-empty characters. Expressions are "XX" or "OO". Similarly, traverse the diagonal elements to construct a string for inspection.
5。If the opponent's two pieces are connected, it poses a threat, and you should try to stop it. If the opponent's three pieces are connected, it's a high risk, and you should immediately stop the opponent.
strategy:
1. Defense comes first. Determine whether the opponent's previous moves have formed two connected lines, and whether there are two pieces closely attached in the vertical, horizontal, left diagonal, and right diagonal directions on the board, in the form of OO. If so, place a piece next to the edge of the opponent's piece, such as OOX.
2. The highest probability of winning is to find a way to form a situation where three chess pieces are closely packed together vertically, horizontally, left diagonally, and right diagonally on the chessboard, i.e. XXX
Make sure you don't place your piece on a spot that has already been occupied by you and your opponent. like spot [5,6] is already occupied, you can't place your piece on it.
thoughts of tree(think step by step):
1、Find out the positions that can be used for the next round, preferably 10 positions, without occupying the positions of existing pieces.
2. Evaluate which positions can meet the strategic needs, and score each position.
3. Pick out the highest-scoring position and play the game.
4. therow index, column index must be int.
You should respond in the json format, which can be loaded by json in Python(pleas don't show 'json'):
{
"thought": "analyze the present situation, and what move you should make.show me all your thought",
"move": [row index, column index]
}
few show like this:
{
"thought": "I should aim to create a line of my pieces while also blocking my opponent from forming a line. Currently, there is a potential threat from the 'o' piece at [5, 6] which could lead to a vertical line. To counter this threat and potentially create my own line, I should place my piece at [6, 6]. This move will block the opponent's vertical line and create a potential horizontal line for me.",
"move": [
7,
7
]
}
Please ensure that your response follows the specified format and includes the necessary fields.
# forbitten
this format is forbitten, don't show 'json'
```json\n{ "thought": "", "move": [ 7, 7 ] }```
"""
# noqa
def parse_func(response: ModelResponse) -> ModelResponse:
"""Parse the response from the model into a dict with "move" and "thought"
keys."""
print(response.text)
match = re.search(r'```json\n(.*?)```', response.text, re.DOTALL)
if match is not None:
json_text = match.group(1) # group(1)返回第一个括号中匹配的部分
res_dict = json.loads(json_text)
if "move" in res_dict and "thought" in res_dict:
return ModelResponse(raw=res_dict)
elif(match is None):
res_dict = json.loads(response.text)
if "move" in res_dict and "thought" in res_dict:
return ModelResponse(raw=res_dict)
else:
raise ValueError(
f"Invalid response format in parse_func "
f"with response: {response.text}",
)
def parse_func1(response: ModelResponse) -> ModelResponse: