Commit
·
778c9c3
1
Parent(s):
a02fa5e
feat: add dataset and use our own model
Browse files- README.md +63 -1
- app.py +98 -110
- puzzles.xlsx +0 -3
- requirements.txt +2 -7
- stories.json +27 -0
README.md
CHANGED
@@ -11,4 +11,66 @@ license: apache-2.0
|
|
11 |
python_version: 3.11.9
|
12 |
---
|
13 |
|
14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
python_version: 3.11.9
|
12 |
---
|
13 |
|
14 |
+
# 海龜湯遊戲 (Turtle Soup Game)
|
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 |
+
`BertForMaskedLM`
|
45 |
+
|
46 |
+
- 使用 BERT 預訓練模型,進行 Masked Language Model 推理,判定玩家的提問。
|
47 |
+
- 模型使用 [nycu-ai113-dl-final-project](https://huggingface.co/nycu-ai113-dl-final-project) 中的模型。
|
48 |
+
|
49 |
+
`SentenceTransformer`
|
50 |
+
|
51 |
+
- 用於計算玩家輸入的答案與故事底層邏輯的語義相似度。
|
52 |
+
- 使用模型來自 [thenlper/gte-base-zh](https://huggingface.co/thenlper/gte-base-zh),授權於 MIT。
|
53 |
+
|
54 |
+
## 文件結構
|
55 |
+
|
56 |
+
`app.py`: 主遊戲程式碼。
|
57 |
+
|
58 |
+
`stories.json`: 包含遊戲謎題的故事數據集。
|
59 |
+
|
60 |
+
`README.md`: 本說明文件。
|
61 |
+
|
62 |
+
## 使用方法
|
63 |
+
|
64 |
+
確保安裝所需依賴:
|
65 |
+
|
66 |
+
```shell
|
67 |
+
pip install -r requirements.txt
|
68 |
+
```
|
69 |
+
|
70 |
+
運行遊戲:
|
71 |
+
|
72 |
+
```shell
|
73 |
+
python app.py
|
74 |
+
```
|
75 |
+
|
76 |
+
瀏覽器將自動打開遊戲介面。
|
app.py
CHANGED
@@ -1,163 +1,140 @@
|
|
1 |
import gradio as gr
|
2 |
-
from transformers import BertTokenizerFast,
|
3 |
import torch
|
4 |
-
import pandas as pd
|
5 |
from sentence_transformers import SentenceTransformer
|
6 |
-
from
|
|
|
|
|
7 |
|
8 |
-
|
9 |
-
|
10 |
-
# model = AutoModelForMaskedLM.from_pretrained('bert-base-chinese')
|
11 |
-
|
12 |
-
tokenizer = T5Tokenizer.from_pretrained("google/flan-t5-large")
|
13 |
-
question_judge = T5ForConditionalGeneration.from_pretrained("google/flan-t5-large")
|
14 |
-
|
15 |
-
answer_judge = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
zh_sys_msg="""
|
20 |
-
你是遊戲的裁判,根據提供的<湯麵>和<湯底>理解故事。玩家會根據<湯麵>進行猜測,並要求你判斷猜測是否正確。你只能回答三種答案:對、錯、不知道。
|
21 |
-
|
22 |
-
## 判定規則:
|
23 |
-
1. 玩家猜測正確:回答"對"。
|
24 |
-
2. 玩家猜測錯誤:回答"錯"。
|
25 |
-
3. 無法從<湯麵>和<湯底>得出結論或無法推理的問題:回答"不知道"。
|
26 |
-
|
27 |
-
## 注意:
|
28 |
-
1. 玩家只能看到<湯麵>,所以他是基於<湯麵>進行猜測,即使<湯底>中有其他信息,也不會影響對<湯麵>的判定。
|
29 |
-
2. 如果猜測無法從故事中推理出結論,回答"不知道"。
|
30 |
-
3. 嚴格遵守只回答"對"、"錯"、"不知道"。
|
31 |
-
|
32 |
-
## 題目內容:
|
33 |
-
### 湯麵:
|
34 |
-
一個男人走進一家酒吧,並向酒保要了一杯水。酒保突然拿出一把手槍瞄準他,而男子竟只是笑著說:「謝謝你!」然後從容離開,請問發生了什麼事?
|
35 |
-
### 湯底:
|
36 |
-
男子打嗝,他希望喝一杯水來改善狀況。酒保意識到這一點,選擇拿槍嚇他,男子一緊張之下,打嗝自然消失,因而衷心感謝酒保後就離開了。
|
37 |
-
|
38 |
-
現在,請判斷以下玩家猜測:
|
39 |
-
"""
|
40 |
|
|
|
|
|
41 |
|
|
|
42 |
|
43 |
intro="""
|
44 |
### 玩法介紹
|
45 |
|
46 |
-
|
47 |
|
48 |
這個遊戲的名稱來自於其中一個最經典的題目,海龜湯的故事。由於這類型的遊戲強調水平思考,也就是用非傳統的方式解決問題,這些遊戲就被大家統稱為「海龜湯」,有點像是可樂成為所有碳酸飲料的代名詞。
|
49 |
|
50 |
在遊戲中,你的提問會讓你逐漸接近真相。準備好發揮你的推理能力,讓我們開始吧!
|
51 |
"""
|
52 |
|
53 |
-
|
54 |
class PuzzleGame:
|
55 |
def __init__(self):
|
56 |
"""
|
57 |
初始化遊戲類別。
|
58 |
"""
|
59 |
-
self.
|
60 |
-
self.
|
61 |
-
|
62 |
-
|
63 |
-
|
|
|
64 |
|
65 |
def get_random_puzzle(self):
|
66 |
"""
|
67 |
隨機選擇一個謎題並設定當前謎題的標題、故事和答案。
|
68 |
"""
|
69 |
-
puzzle = self.
|
70 |
self.title = puzzle['title']
|
71 |
-
|
72 |
-
|
73 |
-
self.story = """A man walks into a bar and asks the bartender for a glass of water. The bartender suddenly pulls out a gun and points it at him. The man smiles and says, "Thank you!" then calmly leaves. What happened?"""
|
74 |
-
self.answer = """The man had hiccups and wanted a glass of water to cure them. The bartender realized this and chose to scare him with a gun. The man's hiccups disappeared due to the sudden shock, so he sincerely thanked the bartender before leaving."""
|
75 |
-
|
76 |
-
def get_sample_puzzle(self):
|
77 |
-
"""
|
78 |
-
選擇範例謎題並設定當前謎題的標題、故��和答案。
|
79 |
-
"""
|
80 |
-
self.title = "The Hiccuping Man"
|
81 |
-
self.story = """A man walks into a bar and asks the bartender for a glass of water. The bartender suddenly pulls out a gun and points it at him. The man smiles and says, "Thank you!" then calmly leaves. What happened?"""
|
82 |
-
self.answer = """The man had hiccups and wanted a glass of water to cure them. The bartender realized this and chose to scare him with a gun. The man's hiccups disappeared due to the sudden shock, so he sincerely thanked the bartender before leaving."""
|
83 |
|
84 |
def get_prompt(self):
|
85 |
"""
|
86 |
返回填入謎題故事和答案的 prompt
|
87 |
"""
|
88 |
-
prompt =
|
89 |
-
You are the game referee, and based on the provided story context and background information, you need to understand the story. The player will make guesses based on the story context, and you are required to judge whether the guess is correct. You can only respond with three possible answers: Correct, Incorrect, or I don’t know.
|
90 |
|
91 |
-
|
92 |
-
If the player guesses correctly: Answer "Correct".
|
93 |
-
If the player guesses incorrectly: Answer "Incorrect".
|
94 |
-
If the guess cannot be concluded from the story context and background information, or if it cannot be logically inferred: Answer "I don’t know".
|
95 |
-
|
96 |
-
Notes:
|
97 |
-
The player can only see the story context, so they will make guesses based on the story context. Even if there is other information in the background, it should not influence the judgment of the story context.
|
98 |
-
If the guess cannot be inferred from the story, answer "I don’t know".
|
99 |
-
Strictly follow the answers "Correct", "Incorrect", or "I don’t know".
|
100 |
|
101 |
-
|
102 |
-
|
103 |
|
104 |
-
|
105 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
return prompt
|
111 |
|
|
|
|
|
112 |
|
113 |
-
|
|
|
|
|
|
|
114 |
|
115 |
def restart():
|
|
|
|
|
|
|
|
|
116 |
game.get_random_puzzle()
|
117 |
-
story = [{"role": "assistant", "content": game.
|
118 |
return story
|
119 |
|
120 |
def user(message, history):
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
history.append({"role": "user", "content": message})
|
122 |
return message, history
|
123 |
|
124 |
-
def bot(message, history):
|
125 |
-
inputs = game.get_prompt() + message
|
126 |
-
input_ids = tokenizer(inputs, return_tensors="pt").input_ids
|
127 |
-
|
128 |
-
with torch.no_grad():
|
129 |
-
outputs = question_judge.generate(input_ids)
|
130 |
-
|
131 |
-
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
|
132 |
-
history.append({"role": "assistant", "content": response})
|
133 |
-
|
134 |
-
return "", history
|
135 |
-
|
136 |
def check_question(question, history):
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
147 |
return "", history
|
148 |
|
149 |
-
|
150 |
def check_answer(answer, history):
|
151 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
embeddings = answer_judge.encode(sentences)
|
153 |
|
154 |
-
|
155 |
|
156 |
-
print("相似度: ",
|
157 |
|
158 |
-
|
159 |
-
|
160 |
-
|
|
|
161 |
response = "接近了!再試一次!"
|
162 |
else:
|
163 |
response = "錯誤!再試一次!"
|
@@ -166,26 +143,33 @@ def check_answer(answer, history):
|
|
166 |
|
167 |
return "", history
|
168 |
|
169 |
-
|
170 |
with gr.Blocks() as demo:
|
|
|
171 |
gr.Markdown(intro)
|
172 |
gr.Markdown("---")
|
|
|
|
|
173 |
story = restart()
|
174 |
chatbot = gr.Chatbot(type='messages', value=story, height=600)
|
175 |
|
176 |
-
|
177 |
with gr.Tab("提出問題"):
|
178 |
question_input_box = gr.Textbox(
|
179 |
show_label=False,
|
180 |
placeholder="提問各種可能性的問題...",
|
181 |
-
|
182 |
submit_btn=True,
|
183 |
)
|
184 |
|
|
|
|
|
|
|
|
|
185 |
question_input_box.submit(user, [question_input_box, chatbot], [question_input_box, chatbot]).then(
|
186 |
check_question, [question_input_box, chatbot], [question_input_box, chatbot]
|
187 |
)
|
188 |
|
|
|
189 |
with gr.Tab("輸入答案"):
|
190 |
answer_input_box = gr.Textbox(
|
191 |
show_label=False,
|
@@ -193,14 +177,18 @@ with gr.Blocks() as demo:
|
|
193 |
submit_btn=True,
|
194 |
)
|
195 |
|
|
|
|
|
|
|
|
|
196 |
answer_input_box.submit(user, [answer_input_box, chatbot], [answer_input_box, chatbot]).then(
|
197 |
check_answer, [answer_input_box, chatbot], [answer_input_box, chatbot]
|
198 |
)
|
199 |
|
|
|
200 |
restart_btn = gr.ClearButton(value='重新開始新遊戲', inputs=[question_input_box, chatbot])
|
201 |
restart_btn.click(restart, outputs=[chatbot])
|
202 |
|
203 |
-
|
204 |
-
|
205 |
if __name__ == "__main__":
|
206 |
demo.launch()
|
|
|
1 |
import gradio as gr
|
2 |
+
from transformers import BertTokenizerFast, BertForMaskedLM
|
3 |
import torch
|
|
|
4 |
from sentence_transformers import SentenceTransformer
|
5 |
+
from sentence_transformers.util import cos_sim
|
6 |
+
import random
|
7 |
+
import json
|
8 |
|
9 |
+
model_name = "nycu-ai113-dl-final-project/bert-turtle-soup-pet-zh"
|
10 |
+
dataset_name = "nycu-ai113-dl-final-project/TurtleBench-extended-zh"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
+
model = BertForMaskedLM.from_pretrained(model_name)
|
13 |
+
tokenizer = BertTokenizerFast.from_pretrained(model_name)
|
14 |
|
15 |
+
answer_judge = SentenceTransformer('thenlper/gte-base-zh')
|
16 |
|
17 |
intro="""
|
18 |
### 玩法介紹
|
19 |
|
20 |
+
遊戲一開始,我會給你一個不完整的故事,這個故事通常有很多未知的細節,你需要透過提出問題來探索更多線索。你可以問我各種問題,不過請記住,我只能回答三種答案:「是」、「不是」或「不知道」。你的目標是根據這些有限的答案,逐步推理出故事的完整脈絡,從而揭開事件的真相。
|
21 |
|
22 |
這個遊戲的名稱來自於其中一個最經典的題目,海龜湯的故事。由於這類型的遊戲強調水平思考,也就是用非傳統的方式解決問題,這些遊戲就被大家統稱為「海龜湯」,有點像是可樂成為所有碳酸飲料的代名詞。
|
23 |
|
24 |
在遊戲中,你的提問會讓你逐漸接近真相。準備好發揮你的推理能力,讓我們開始吧!
|
25 |
"""
|
26 |
|
|
|
27 |
class PuzzleGame:
|
28 |
def __init__(self):
|
29 |
"""
|
30 |
初始化遊戲類別。
|
31 |
"""
|
32 |
+
self.template = ' 根據判定規則,此玩家的猜測為[MASK]'
|
33 |
+
self.load_stories('stories.json')
|
34 |
+
|
35 |
+
def load_stories(self, path):
|
36 |
+
with open(path, mode='r', encoding='utf-8') as f:
|
37 |
+
self.stories = json.load(f)
|
38 |
|
39 |
def get_random_puzzle(self):
|
40 |
"""
|
41 |
隨機選擇一個謎題並設定當前謎題的標題、故事和答案。
|
42 |
"""
|
43 |
+
puzzle = random.choice(self.stories)
|
44 |
self.title = puzzle['title']
|
45 |
+
self.surface = puzzle['surface']
|
46 |
+
self.bottom = puzzle['bottom']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
|
48 |
def get_prompt(self):
|
49 |
"""
|
50 |
返回填入謎題故事和答案的 prompt
|
51 |
"""
|
52 |
+
prompt = "你是遊戲的裁判,根據提供的<湯麵>和<湯底>理解故事。玩家會根據<湯麵>進行猜測,並要求你判斷猜測是否正確。你只能回答三種答案:正確、錯誤、不知道。判定規則:1. 玩家猜測正確:回答\"正確\"。2. 玩家猜測錯誤:回答\"錯誤\"。3. 無法從<湯麵>和<湯底>得出結論或無法推理的問題:回答\"不知道\"。注意:1. 玩家只能看到<湯麵>,所以他是基於<湯麵>進行猜測,即使<湯底>中有其他信息,也不會影響對<湯麵>的判定。2. 如果猜測無法從故事中推理出結論,回答\"不知道\"。3. 嚴格遵守只回答\"正確\"、\"錯誤\"、\"不知道\"。<湯麵>{self.surface}<湯底>{self.bottom}請判斷以下玩家猜測:"
|
|
|
53 |
|
54 |
+
return prompt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
|
56 |
+
# 初始化遊戲
|
57 |
+
game = PuzzleGame()
|
58 |
|
59 |
+
def predict_masked_token(text):
|
60 |
+
"""
|
61 |
+
使用模型預測 [MASK] 位置的 token。
|
62 |
+
:param text: 包含 [MASK] 的文本。
|
63 |
+
:return: 預測的 token。
|
64 |
+
"""
|
65 |
+
inputs = tokenizer(text, return_tensors="pt")
|
66 |
+
model.eval()
|
67 |
+
with torch.no_grad():
|
68 |
+
outputs = model(**inputs)
|
69 |
|
70 |
+
# 找到 [MASK] 的位置
|
71 |
+
mask_token_index = (inputs.input_ids == tokenizer.mask_token_id).nonzero(as_tuple=True)[1]
|
|
|
|
|
72 |
|
73 |
+
if mask_token_index.numel() == 0:
|
74 |
+
raise "請確保輸入包含 [MASK]。"
|
75 |
|
76 |
+
# 獲取 [MASK] 位置的 logits 並預測
|
77 |
+
mask_token_logits = outputs.logits[0, mask_token_index, :]
|
78 |
+
predicted_id = torch.argmax(mask_token_logits, dim=-1)
|
79 |
+
return tokenizer.decode(predicted_id)
|
80 |
|
81 |
def restart():
|
82 |
+
"""
|
83 |
+
重新開始遊戲,初始化新的謎題。
|
84 |
+
返回故事的開頭內容。
|
85 |
+
"""
|
86 |
game.get_random_puzzle()
|
87 |
+
story = [{"role": "assistant", "content": game.surface}]
|
88 |
return story
|
89 |
|
90 |
def user(message, history):
|
91 |
+
"""
|
92 |
+
處理用戶輸入的問題或答案,並將其添加到對話歷史中。
|
93 |
+
:param message: 用戶的輸入消息。
|
94 |
+
:param history: 當前的對話歷史。
|
95 |
+
:return: 用戶的消息和更新後的歷史。
|
96 |
+
"""
|
97 |
history.append({"role": "user", "content": message})
|
98 |
return message, history
|
99 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
def check_question(question, history):
|
101 |
+
"""
|
102 |
+
使用 Masked Language Model 檢查用戶提問的問題。
|
103 |
+
:param question: 用戶的提問。
|
104 |
+
:param history: 當前的對話歷史。
|
105 |
+
:return: 空字符串和更新後的歷史。
|
106 |
+
"""
|
107 |
+
# 將問題與遊戲提示和模板結合
|
108 |
+
text = game.get_prompt() + question + game.template
|
109 |
+
predicted = predict_masked_token(text)
|
110 |
+
|
111 |
+
predicted_map = {
|
112 |
+
'是':'是',
|
113 |
+
'否':'不是',
|
114 |
+
'不':'不知道'
|
115 |
+
}
|
116 |
+
|
117 |
+
history.append({"role": "assistant", "content": predicted_map[predicted]})
|
118 |
return "", history
|
119 |
|
|
|
120 |
def check_answer(answer, history):
|
121 |
+
"""
|
122 |
+
使用語義相似度檢查用戶輸入的答案是否正確。
|
123 |
+
:param answer: 用戶的答案。
|
124 |
+
:param history: 當前的對話歷史。
|
125 |
+
:return: 空字符串和更新後的歷史。
|
126 |
+
"""
|
127 |
+
sentences = [answer, game.bottom]
|
128 |
embeddings = answer_judge.encode(sentences)
|
129 |
|
130 |
+
sim = cos_sim([embeddings[0]], [embeddings[1]])
|
131 |
|
132 |
+
print("相似度: ", sim[0][0])
|
133 |
|
134 |
+
# 根據相似度生成回應
|
135 |
+
if sim[0][0] > 0.8:
|
136 |
+
response = "正確!你猜對了! 完整故事:\n" + game.bottom
|
137 |
+
elif sim[0][0] > 0.7:
|
138 |
response = "接近了!再試一次!"
|
139 |
else:
|
140 |
response = "錯誤!再試一次!"
|
|
|
143 |
|
144 |
return "", history
|
145 |
|
146 |
+
# 使用 Gradio 創建界面
|
147 |
with gr.Blocks() as demo:
|
148 |
+
# 頁面介紹
|
149 |
gr.Markdown(intro)
|
150 |
gr.Markdown("---")
|
151 |
+
|
152 |
+
# 初始化故事
|
153 |
story = restart()
|
154 |
chatbot = gr.Chatbot(type='messages', value=story, height=600)
|
155 |
|
156 |
+
# 問題提問功能
|
157 |
with gr.Tab("提出問題"):
|
158 |
question_input_box = gr.Textbox(
|
159 |
show_label=False,
|
160 |
placeholder="提問各種可能性的問題...",
|
|
|
161 |
submit_btn=True,
|
162 |
)
|
163 |
|
164 |
+
# 用戶輸入的文本框
|
165 |
+
# 1. 將用戶輸入的問題提交到 `user` 函數處理,將問題加入到歷史對話中。
|
166 |
+
# 2. 將 `user` 處理的結果(問題和更新後的歷史)傳遞給 `check_question` 函數。
|
167 |
+
# 3. `check_question` 會檢查問題並生成對應的回應,更新對話歷史。
|
168 |
question_input_box.submit(user, [question_input_box, chatbot], [question_input_box, chatbot]).then(
|
169 |
check_question, [question_input_box, chatbot], [question_input_box, chatbot]
|
170 |
)
|
171 |
|
172 |
+
# 答案輸入功能
|
173 |
with gr.Tab("輸入答案"):
|
174 |
answer_input_box = gr.Textbox(
|
175 |
show_label=False,
|
|
|
177 |
submit_btn=True,
|
178 |
)
|
179 |
|
180 |
+
# 用戶輸入的答案框
|
181 |
+
# 1. 將用戶輸入的答案提交到 `user` 函數處理,將答案加入到歷史對話中。
|
182 |
+
# 2. 將 `user` 處理的結果(答案和更新後的歷史)傳遞給 `check_answer` 函數。
|
183 |
+
# 3. `check_answer` 會檢查答案的正確性,生成對應的回應,並更新對話歷史。
|
184 |
answer_input_box.submit(user, [answer_input_box, chatbot], [answer_input_box, chatbot]).then(
|
185 |
check_answer, [answer_input_box, chatbot], [answer_input_box, chatbot]
|
186 |
)
|
187 |
|
188 |
+
# 重新開始按鈕
|
189 |
restart_btn = gr.ClearButton(value='重新開始新遊戲', inputs=[question_input_box, chatbot])
|
190 |
restart_btn.click(restart, outputs=[chatbot])
|
191 |
|
192 |
+
# 啟動應用
|
|
|
193 |
if __name__ == "__main__":
|
194 |
demo.launch()
|
puzzles.xlsx
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:2334e69f0ac1382849365d13a6d50cd17a64df4bcf7ab1ff57a79f8fde70ebb9
|
3 |
-
size 289440
|
|
|
|
|
|
|
|
requirements.txt
CHANGED
@@ -1,9 +1,4 @@
|
|
1 |
-
gradio==5.
|
2 |
-
pandas==2.2.3
|
3 |
-
scikit_learn==1.5.2
|
4 |
sentence_transformers==3.3.1
|
5 |
torch==2.5.1
|
6 |
-
|
7 |
-
transformers==4.46.3
|
8 |
-
sentencepiece==0.2.0
|
9 |
-
openpyxl==3.1.5
|
|
|
1 |
+
gradio==5.9.1
|
|
|
|
|
2 |
sentence_transformers==3.3.1
|
3 |
torch==2.5.1
|
4 |
+
transformers==4.46.3
|
|
|
|
|
|
stories.json
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[
|
2 |
+
{
|
3 |
+
"title":"日記",
|
4 |
+
"surface":"2019 年 2 月,女兒不去上學了,我勸不動她。\n2019 年 6 月,女兒每天盯着電視和電腦看,我怕她眼睛弄壞了。\n2019 年 12 月,女兒好像開朗了一些,看到她經常和朋友語音聊天。\n2020 年 3 月,女兒笑了,說她做了一件大好事,我也很高興。\n2020 年 5 月,女兒的狀態惡化了,整夜不睡覺,她也不和我說話。\n2020 年 6 月,總覺得最近家裏開銷特別大,嗯……?是我糊塗了嗎。\n2020 年 10 月,女兒出門了,最近疫情好些了之後她經常出門,好像朋友也變多了,太好了。\n2021 年 2 月,我收到了一張律師函,上面寫着女兒的名字,怎麼會?!\n2021 年 8 月,我把女兒禁足了",
|
5 |
+
"bottom":"女兒因為一些原因拒絕去上學,6 月陳情令上線,女兒沉迷其中。同年 12 月,女兒混了肖戰的飯圈。這段期間,女兒一直在給肖戰當網路水軍。 20 年 3 月,AO3 被檢舉。 5 月,肖戰遭到大批網友抵制,資本開始審視這個東西是不是值得投資。 6 月光點上線,女兒偷家裡的錢買數字專。疫情好轉後,女兒照例出門參加飯圈活動,漸漸開始認清它的真面目。 21 年 2 月,蕭戰狀告\"黑粉\"。 8 月肖戰勝訴,粉絲被罰 3W,故事中的這位父\/母把女兒徹底禁足了。"
|
6 |
+
},
|
7 |
+
{
|
8 |
+
"title":"打折的零食",
|
9 |
+
"surface":"他在小賣部買了一批折扣零食,感覺自己賺了,暗暗自喜。第二天看新聞時,他被嚇傻了。",
|
10 |
+
"bottom":"他之前在這家店買過一次零食,覺得老闆娘多收了他錢。這次來看到是一個男子在看店,他提到上次可能算錯了錢,男子說這次給他打折作為補償。他覺得自己賺到了便宜很開心。第二天,他從新聞得知這家店的店主夫妻被殺害,而男子是殺人後冒充店主的人。"
|
11 |
+
},
|
12 |
+
{
|
13 |
+
"title":"1237",
|
14 |
+
"surface":"幼兒園的一個小朋友數數總是說\"1,2,3,7\",總是漏掉中間的\"4,5,6\"。可是當我糾正她時,她卻說這是她媽媽教她的,我很疑惑,便提出去她家家訪,家訪結束後我也對她說是\"1,2,3,7\"",
|
15 |
+
"bottom":"身為一個幼師,我發現一個小朋友數數總是錯的,她堅持數「1237」。當我教她正確的數數方式時,她卻說媽媽教的就是「1237」。我提出家訪,她帶我去了醫院。原來她的媽媽患有心臟病,生命所剩無幾。為了陪女兒過最後一個生日,她編織了「3後面是7」的謊言,期望撐到七月。我深受感動,也對她說「3後面確實是7"
|
16 |
+
},
|
17 |
+
{
|
18 |
+
"title":"遺失的手機",
|
19 |
+
"surface":"我的手機不見了,當我找到它時,我嚇了一跳。",
|
20 |
+
"bottom":"我和閨蜜去酒吧蹦迪,喝了一點酒後發現手機不見了。我請閨蜜幫忙撥打我的號碼,電話接通後是個陌生男子的聲音。酒吧太吵,我們還沒聽清楚對方的話,電話就被掛斷了。回家後,我發現手機就在床頭,才猛然想起我根本沒帶手機出門,而且我一直獨自居住,頓時毛骨悚然。"
|
21 |
+
},
|
22 |
+
{
|
23 |
+
"title":"洗衣機",
|
24 |
+
"surface":"夜晚,貧窮的拾荒者撿了一臺洗衣機回家。半夜他從睡夢中驚醒,好像聽到了洗衣機啓動的聲音。",
|
25 |
+
"bottom":"兇手將殺害的受害者肢解後,把屍塊放進洗衣機,並用洗衣機運到郊外拋屍。當兇手挖坑埋屍時,一位拾荒者撿走了洗衣機,開著小三輪離去。兇手跟蹤拾荒者到家後,潛入其家中啟動洗衣機,試圖清洗殘留的血跡。"
|
26 |
+
}
|
27 |
+
]
|