File size: 6,085 Bytes
dda94e6
 
 
 
 
 
 
8617bcb
dda94e6
e2782ab
dda94e6
 
8a87758
dda94e6
8a87758
 
dda94e6
8617bcb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e483d1b
8617bcb
 
 
e483d1b
 
8617bcb
e483d1b
 
8a87758
 
 
dda94e6
 
8a87758
dda94e6
 
e483d1b
 
dda94e6
 
e483d1b
dda94e6
 
e483d1b
dda94e6
e2782ab
dda94e6
 
 
 
 
 
1f96bc8
dda94e6
 
 
 
 
 
 
 
 
 
 
 
ab01137
b33d6d1
 
ab01137
dda94e6
ab01137
 
 
 
 
dda94e6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8617bcb
ab01137
8617bcb
dda94e6
8617bcb
ab01137
 
 
 
 
 
 
 
dda94e6
 
ab01137
 
 
b33d6d1
dda94e6
 
e2782ab
dda94e6
 
 
 
 
 
 
 
 
 
 
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
import time
import json

import pandas as pd
import gradio as gr
import openai

from src.semantle import get_guess, get_secret, get_puzzle_num
from src.functions import get_functions
from src.utils import add_guess

GPT_MODEL = "gpt-3.5-turbo"
TITLE = "やりとりイミトル"

with open("data/rule.md", "r", encoding="utf-8") as f:
    RULEBOOK = "\n".join(f.readlines())

def _execute_function(function_call, chat_messages):
        # Step 3: call the function
        # Note: the JSON response may not always be valid; be sure to handle errors
        available_functions = {
            "guess_word": get_guess,
            "lookup_answer": get_secret,
            "retrive_puzzle": get_puzzle_num
        }
        function_name = function_call["name"]
        function_to_call = available_functions[function_name]
        function_args = json.loads(function_call["arguments"])
        function_response = function_to_call(
            **function_args
        )
        if function_call["name"] == "guess_word":
            print("update guess")
        # Step 4: send the info on the function call and function response to GPT
        chat_messages.append(
            {"role": "function",
             "name": function_name,
             "content": function_response["choices"][0]}
        )   # extend conversation with function response
        next_response = openai.ChatCompletion.create(
            model=GPT_MODEL,
            messages=chat_messages,
        )   # get a new response from GPT where it can se the function response
        chat_messages.append(next_response.choices[0].message.to_dict())
        return next_response, chat_messages

def create_chat(key, user_input):
    openai.api_key = key
    chat_messages = [
        {"role": "system", "content": "あなたはiritoruというゲームの進行役です。ユーザーが答えを言ったり、ゲームに関するリクエストをしたら、短くても丁寧に答えてください。"},
        {"role": "user", "content": user_input}]
    response = openai.ChatCompletion.create(
        model=GPT_MODEL,
        messages=chat_messages,
        functions=get_functions()
    )
    response_message = response.choices[0].message.to_dict()
    chat_messages.append(response_message) # extend conversation with assistant's reply

    # Step 2: check if CPT wanted to call a function
    while response_message.get("function_call"):
        # Step 3: call the function
        # Note: the JSON response may not always be valid; be sure to handle errors
        response_message, chat_messages = _execute_function(response_message["function_call"], chat_messages)
    
    return chat_messages[-1]

with gr.Blocks() as demo:
    with gr.Row():
        gr.Markdown(
            """
            # やりとりSemantle
            [semantle日本語版](https://semantoru.com/)をchatbotと楽しめるspaceです。
            ## ゲームのやり方
            - 正解は一つの単語で、これを答えるとゲームの勝利になります。
            - 推測した単語が正解じゃない場合、類似度スコアと順位が表示されます。それは正解を推測する大事なヒントになります。
            ## chatbotの仕事
            - 単語のスコアとランク以外に他のヒントがもらえます。
            - ゲームに関して困っている時、何か質問してみてください。
            """
        )

    with gr.Row():
        with gr.Column():
            api_key = gr.Textbox(placeholder="sk-...", label="OPENAI_API_KEY", value=None, type="password")
            idx = gr.State(value=0)
            guessed = gr.State(value=set())
            guesses = gr.State(value=list())
            cur_guess = gr.State()
            guesses_table = gr.DataFrame(
                value=pd.DataFrame(columns=["#", "答え", "スコア", "ランク"]),
                headers=["#", "答え", "score", "score"],
                datatype=["number", "str", "number", "str"],
                elem_id="guesses-table",
                interactive=False
            )
        with gr.Column(elem_id="chat_container"):
            msg = gr.Textbox(
                placeholder="ゲームをするため、まずはAPI KEYを入れてください。",
                label="答え",
                interactive=False,
                max_lines=1
            )
            chatbot = gr.Chatbot(elem_id="chatbot")

        def unfreeze():
            return msg.update(interactive=True, placeholder="正解と思う言葉を答えてください。")
        def greet():
            return "", [("[START]", "ゲームを始まります!好きな言葉をひとつだけいってみてください。")]
        
        def respond(key, user_input, chat_messages):
            reply = create_chat(key, user_input)
            chat_messages.append((user_input, reply["content"]))
            time.sleep(2)
            return "", chat_messages
        
        def update_guesses(cur, i, guessed_words, guesses_df):
            if cur[0] not in guessed_words:
                guessed_words.add(cur[0])
                guesses_df.loc[i] = [i+1] + cur
                i += 1
                guesses_df = guesses_df.sort_values(by=["score"], ascending=False)
            return i, guessed_words, guesses_df

        api_key.change(unfreeze, [], [msg]).then(greet, [], [msg, chatbot])
        msg.submit(respond, [api_key, msg, chatbot, cur_guess], [msg, chatbot, cur_guess]).then(
            update_guesses, [cur_guess, idx, guessed, guesses_table], [idx, guessed, guesses_table]
        )
            
    gr.Examples(
        [
            ["猫"],
            ["どんなヒントが貰える?"],
            ["正解と「近い」とはどういう意味?"],
            ["何から始めたらいい?"],
            ["今日の正解は何?"],
        ],
        inputs=msg,
        label="こちらから選んで話すこともできます."
    )

if __name__ == "__main__":
    demo.queue(concurrency_count=20).launch()