sim-so commited on
Commit
ab01137
1 Parent(s): b33d6d1

add functions

Browse files
Files changed (5) hide show
  1. app.py +26 -42
  2. base.py +13 -11
  3. src/functions.py +59 -7
  4. src/prompts.py +17 -13
  5. src/semantle.py +10 -7
app.py CHANGED
@@ -14,37 +14,15 @@ from src.utils import add_guess
14
  GPT_MODEL = "gpt-3.5-turbo"
15
  TITLE = "やりとりSemantle"
16
 
17
- task_background = f"""今から言葉をします。ユーザがゲームすることを手伝ってください。
18
-
19
- """
20
- task_description=f"""まず、ユーザーからの話を聞いて、答えるのか、ヒントを欲しがっているのか、やめようといるのかを判断してください。
21
- ユーザーが答えする場合、答えの点数を評価してください。そのあと結果を一言に要約してください。
22
- ユーザーがヒントを欲しがっている場合、正解に関する間接的な情報を提供してください。
23
- ユーザーが正解を聞いたりやめると言いたりする場合、やめてもいいかをもう一度確認してください。
24
- そのほか話は答えないでください。
25
-
26
- ゲームのルール:
27
- 正解は一つの言葉である。ユーザーはどんな言葉が正解か推測して、単語を一つずつ答えする。答えた単語のスコアが100点で、正解と一致すると成功としてゲームが終わる。
28
- """
29
-
30
- # guessed = set()
31
- # guesses = pd.DataFrame(columns=["#", "答え", "スコア", "ランク"])
32
-
33
  system_content = task_background+task_description
34
  system_message = [{"role": "system", "content": system_content}]
35
- chat_history = []
36
- n_history = 8
37
-
38
- def update_guess(guess_result, guessed_words, guesses_df):
39
- result, guessed, guesses = add_guess(guess_result, guessed_words, guesses_df)
40
- return result
41
 
42
  def create_chat(user_input, chat_history, api_key):
43
  openai.api_key = api_key
44
  chat_messages = [{"role": "user", "content": user_input}]
45
  response = openai.ChatCompletion.create(
46
  model=GPT_MODEL,
47
- messages=system_message+chat_history+chat_messages,
48
  functions=get_functions()
49
  )
50
  response_message = response.choices[0].message
@@ -54,7 +32,8 @@ def create_chat(user_input, chat_history, api_key):
54
  # Step 3: call the function
55
  # Note: the JSON response may not always be valid; be sure to handle errors
56
  available_functions = {
57
- "evaluate_guess": get_guess,
 
58
  }
59
  function_name = response_message["function_call"]["name"]
60
  function_to_call = available_functions[function_name]
@@ -107,18 +86,16 @@ with gr.Blocks() as demo:
107
  with gr.Row():
108
  with gr.Column():
109
  api_key = gr.Textbox(placeholder="sk-...", label="OPENAI_API_KEY", value=None, type="password")
110
- idx = gr.State(value=1)
111
  guessed = gr.State(value=set())
112
  guesses = gr.State(value=list())
113
- cur_guess_table = gr.DataFrame(
114
- value=[],
115
- elem_id="cur-guesses-table"
116
- )
117
  guesses_table = gr.DataFrame(
118
- value=[],
119
- headers=["#", "答え", "スコア", "ランク"],
120
- datatype=["number", "str", "str", "str"],
121
- elem_id="guesses-table"
 
122
  )
123
  with gr.Column(elem_id="chat_container"):
124
  msg = gr.Textbox(
@@ -134,19 +111,26 @@ with gr.Blocks() as demo:
134
  def greet():
135
  return "", [("[START]", "ゲームを始まります!好きな言葉をひとつだけいってみてください。")]
136
 
137
- def respond(user_input, chatbot, api_key):
138
- reply = create_chat(user_input, chat_history, api_key)
 
 
139
  chatbot.append((user_input, reply["content"]))
140
  time.sleep(2)
141
- return "", chatbot
142
- def update_guesses(i, guessed_words, guess_history):
143
- i += 1
144
- guessed_words.add()
145
- return guesses_table.update(value=guess_history)
 
 
 
 
146
 
147
  api_key.change(unfreeze, [], [msg]).then(greet, [], [msg, chatbot])
148
- msg.submit(respond, [msg, chatbot, api_key], [msg, chatbot]
149
- ).then(update_guesses, [idx, guessed, guesses], [idx, guessed, guesses, cur_guess_table])
 
150
 
151
  gr.Examples(
152
  [
 
14
  GPT_MODEL = "gpt-3.5-turbo"
15
  TITLE = "やりとりSemantle"
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  system_content = task_background+task_description
18
  system_message = [{"role": "system", "content": system_content}]
 
 
 
 
 
 
19
 
20
  def create_chat(user_input, chat_history, api_key):
21
  openai.api_key = api_key
22
  chat_messages = [{"role": "user", "content": user_input}]
23
  response = openai.ChatCompletion.create(
24
  model=GPT_MODEL,
25
+ messages=system_message+chat_messages,
26
  functions=get_functions()
27
  )
28
  response_message = response.choices[0].message
 
32
  # Step 3: call the function
33
  # Note: the JSON response may not always be valid; be sure to handle errors
34
  available_functions = {
35
+ "evaluate_score": get_guess,
36
+ "get_data_for_hint": get_play_data,
37
  }
38
  function_name = response_message["function_call"]["name"]
39
  function_to_call = available_functions[function_name]
 
86
  with gr.Row():
87
  with gr.Column():
88
  api_key = gr.Textbox(placeholder="sk-...", label="OPENAI_API_KEY", value=None, type="password")
89
+ idx = gr.State(value=0)
90
  guessed = gr.State(value=set())
91
  guesses = gr.State(value=list())
92
+ cur_guess = gr.State()
 
 
 
93
  guesses_table = gr.DataFrame(
94
+ value=pd.DataFrame(columns=["#", "答え", "スコア", "ランク"]),
95
+ headers=["#", "答え", "score", "score"],
96
+ datatype=["number", "str", "number", "str"],
97
+ elem_id="guesses-table",
98
+ interactive=False
99
  )
100
  with gr.Column(elem_id="chat_container"):
101
  msg = gr.Textbox(
 
111
  def greet():
112
  return "", [("[START]", "ゲームを始まります!好きな言葉をひとつだけいってみてください。")]
113
 
114
+ def respond(key, user_input, chat_history, cur):
115
+ reply = create_chat(key, user_input)
116
+ if isinstance(reply["content"], list):
117
+ cur = reply["content"]
118
  chatbot.append((user_input, reply["content"]))
119
  time.sleep(2)
120
+ return "", chatbot, cur
121
+
122
+ def update_guesses(cur, i, guessed_words, guesses_df):
123
+ if cur[0] not in guessed_words:
124
+ guessed_words.add(cur[0])
125
+ guesses_df.loc[i] = [i+1] + cur
126
+ i += 1
127
+ guesses_df = guesses_df.sort_values(by=["score"], ascending=False)
128
+ return i, guessed_words, guesses_df
129
 
130
  api_key.change(unfreeze, [], [msg]).then(greet, [], [msg, chatbot])
131
+ msg.submit(respond, [api_key, msg, chatbot, cur_guess], [msg, chatbot, cur_guess]).then(
132
+ update_guesses, [cur_guess, idx, guessed, guesses_table], [idx, guessed, guesses_table]
133
+ )
134
 
135
  gr.Examples(
136
  [
base.py CHANGED
@@ -1,17 +1,19 @@
1
- from typing import List
2
 
3
- class Tool:
4
- description: str = ""
5
- name: str = ""
6
 
7
- inputs: List[str] = ""
8
- outputs: List[str] = ""
9
 
10
- def __init__(self, *args, **kwargs):
11
- pass
12
 
13
- def __call__(self, *args, **kwargs):
14
- args = [arg for arg in args]
15
- kwargs = {k: v for k, v in kwargs.items()}
 
 
16
 
17
 
 
1
+ # from typing import List
2
 
3
+ # class Tool:
4
+ # description: str = "Calculate a score and a rank of the guess word, which indicate a distance from the secret word."
5
+ # name: str = "evaluate_score"
6
 
7
+ # inputs: List[str] = ["word", "puzzle_num"]
8
+ # required: List[str] = ["word", "puzzle_num"]
9
 
10
+ # def __init__(self, *args, **kwargs):
11
+ # pass
12
 
13
+ # def setup(self):
14
+
15
+ # def __call__(self, *args, **kwargs):
16
+ # args = [arg for arg in args]
17
+ # kwargs = {k: v for k, v in kwargs.items()}
18
 
19
 
src/functions.py CHANGED
@@ -1,20 +1,72 @@
1
- evaluate_guess = {"name": "evaluate_guess",
2
- "description": "Calculate the score of a guess word and get the rank among the 1,000 words.",
3
  "parameters": {
4
  "type": "object",
5
  "properties": {
6
  "word": {
7
  "type": "string",
8
- "description": "A single Japanese word, which is can be a noun, verb, adverb or adjective. e.g. 空, 近い, 行く, etc."
9
  },
10
- "puzzle": {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  "type": "object",
12
- "description": "A class containing information about the puzzle; a secret word and scores/ranks for other words."
13
  }
14
  },
15
- "required": ["word", "puzzle"]
16
  }}
17
 
 
18
  def get_functions():
19
- functions = [evaluate_guess]
20
  return functions
 
1
+ guess_word = {"name": "guess_word",
2
+ "description": "Use this function to check if a guessed word is the correct answer or not, and if incorrect, calculate a score and a rank of the guess word.",
3
  "parameters": {
4
  "type": "object",
5
  "properties": {
6
  "word": {
7
  "type": "string",
8
+ "description": "A single Japanese word to guess, which is can be a noun, verb, adverb or adjective. e.g. 空, 近い, 行く, etc."
9
  },
10
+ "puzzle_num": {
11
+ "type": "integer",
12
+ "description": "An index indicating today's puzzle."
13
+ }
14
+ },
15
+ "required": ["word", "puzzle_num"]
16
+ }}
17
+
18
+ prepare_hint = {"name": "prepare_hint",
19
+ "description": "Use this function to retrieve information for hint.",
20
+ "parameters": {
21
+ "type": "object",
22
+ "properties": {
23
+ "puzzle_num": {
24
+ "type": "interger",
25
+ "description": "An index for today's puzzle set."
26
+ }
27
+ },
28
+ "required": ["puzzle_num"]
29
+ }}
30
+
31
+ get_secret = {"name": "get_secret",
32
+ "description": "You can check what the correct answer of today's puzzle is by this function.",
33
+ "parameters": {
34
+ "type": "object",
35
+ "properties": {
36
+ "puzzle_num": {
37
+ "type": "integer",
38
+ "description": "An index indicating today's puzzle."
39
+ }
40
+ },
41
+ "required": ["puzzle_num"]
42
+ }}
43
+
44
+ get_puzzle_num = {"name": "get_puzzle_num",
45
+ "description": "Use this function to check today's puzzle number.",
46
+ "parameters": {
47
+ "type": "object",
48
+ "properties": {}
49
+ },
50
+ }
51
+
52
+ update_history = {"name": "update_history",
53
+ "description": "Use this function to add current guess to a table for a user's guess history.",
54
+ "parameters": {
55
+ "type": "object",
56
+ "properties": {
57
+ "current_guess": {
58
+ "type": "json",
59
+ "description": "A currently guessed word and its score and rank."
60
+ },
61
+ "guess_history": {
62
  "type": "object",
63
+ "description": "A dataframe containing the guessed words and its xore and rank in a row."
64
  }
65
  },
66
+ "required": ["current_guess", "guess_history"]
67
  }}
68
 
69
+
70
  def get_functions():
71
+ functions = [guess_word]
72
  return functions
src/prompts.py CHANGED
@@ -1,8 +1,5 @@
1
  import re
2
 
3
- CHAT_MESSAGE_PROMPT = """
4
-
5
- """
6
  INITIAL_PROMPT = """今ユーザーは単語を当てるゲームをしている。ゲームの正解は1つの単語になっている。
7
  続くユーザーのメッセージからユーザーの意図を理解し、それに合った対応をする。ユーザーの行動は下記の一つになる。
8
  1. 正解と推測する言葉を答えている
@@ -10,7 +7,7 @@ INITIAL_PROMPT = """今ユーザーは単語を当てるゲームをしている
10
  [対応] 今答えた言葉が正解とどれぐらい近いかを計算する。
11
  2. ヒントを欲しがっている
12
  [例] `何かヒントを欲しい`,`正解と先の単語と何の関係がある?`,`正解の例文をください`,`ゲームのやり方を分からない`など
13
- [対応] 提供可能なヒントを用意しておく。
14
  3. 正解を聞く、またはやめると言う
15
  [例] `正解は何?`,`もうやめよう`,`正解を教えて`など
16
  [対応] 正解を聞くとゲームが終わるので、ゲームを辞めてもいいかをもう一度確認する。
@@ -20,15 +17,22 @@ INITIAL_PROMPT = """今ユーザーは単語を当てるゲームをしている
20
 
21
  RULE = """正解は一つの言葉である。ユーザーはどんな言葉が正解か推測して、単語を一つずつ答えする。答えた単語のスコアが100点で、正解と正に一致すると成功としてゲームが終わる。"""
22
 
23
- task_background = f"""今から言葉をします。ユーザがゲームすることを手伝ってください。
24
-
 
 
 
25
  """
26
- task_description=f"""まず、ユーザーからの話を聞いて、答えるのか、ヒントを欲しがっているのか、やめようといるのかを判断してください。
27
- ユーザーが答えする場合、答えの点数を評価してください。そのあと結果を一言に要約してください。
28
- ユーザーがヒントを欲しがっている場合、正解に関する間接的な情報を提供してください。
29
- ユーザーが正解を聞いたりやめると言いたりする場合、やめてもいいかをもう一度確認してください。
30
- そのほか話は答えないでください。
31
 
32
- ゲームのルール:
33
- 正解は一つの言葉である。ユーザーはどんな言葉が正解か推測して、単語を一つずつ答えする。答えた単語のスコアが100点で、正解と一致すると成功としてゲームが終わる。
 
 
 
 
 
 
 
 
 
34
  """
 
1
  import re
2
 
 
 
 
3
  INITIAL_PROMPT = """今ユーザーは単語を当てるゲームをしている。ゲームの正解は1つの単語になっている。
4
  続くユーザーのメッセージからユーザーの意図を理解し、それに合った対応をする。ユーザーの行動は下記の一つになる。
5
  1. 正解と推測する言葉を答えている
 
7
  [対応] 今答えた言葉が正解とどれぐらい近いかを計算する。
8
  2. ヒントを欲しがっている
9
  [例] `何かヒントを欲しい`,`正解と先の単語と何の関係がある?`,`正解の例文をください`,`ゲームのやり方を分からない`など
10
+ [対応] ヒントを出すため必要な情報を用意する。
11
  3. 正解を聞く、またはやめると言う
12
  [例] `正解は何?`,`もうやめよう`,`正解を教えて`など
13
  [対応] 正解を聞くとゲームが終わるので、ゲームを辞めてもいいかをもう一度確認する。
 
17
 
18
  RULE = """正解は一つの言葉である。ユーザーはどんな言葉が正解か推測して、単語を一つずつ答えする。答えた単語のスコアが100点で、正解と正に一致すると成功としてゲームが終わる。"""
19
 
20
+ SUBTASK_1 = """下記の答えた結果を見て、れまでの結果や全体の単語の数に比べて今の評価を出す。
21
+ - 答えた結果: <cur_guess>
22
+ - これまで推測した結果: <guess_history>
23
+ - データベースの総単語数: <n_total_words>
24
+ ランクが1,000位以外の場合、またはデータベースにいない単語はランクが表示していない。
25
  """
 
 
 
 
 
26
 
27
+ SUBTASK_2 = """ユーザーの要求に合わせてヒントを出す。
28
+ もしヒントの形が明確にならない場合、例の可能なヒントから一つ選んでそれを出す。
29
+ [プレイ情報]
30
+ - これまで推測した単語: <guessed_list>
31
+ - これまで最後点数の単語: <best_score_word>
32
+ - 正解: <secret>
33
+ [例]
34
+ - 正解単語を使って文章をひとつ作る。正し、正解単語は必ず隠すこと。
35
+ - これまで推測した単語の中、あなたが正解と一番近いと思う単語と選び、その理由とともに話す。
36
+ - これまでの最高点数の単語と正解の間の意味、文法、話用論的な共通点をひとつ教える。
37
+ - これまでの最高点数の単語と正解、両方意味的に関係がある単語をひとつ選んでそれを出す。
38
  """
src/semantle.py CHANGED
@@ -1,3 +1,5 @@
 
 
1
  import requests
2
 
3
  def get_secret(puzzle_num: int):
@@ -6,18 +8,19 @@ def get_secret(puzzle_num: int):
6
  if response.status_code == 200:
7
  return response.content
8
  else:
9
- print("Not found error.")
10
 
11
  def get_guess(word: str, puzzle_num: int):
12
  request_url = f"https://semantoru.com/guess/{puzzle_num}/{word}"
13
  response = requests.get(request_url)
14
  print(response.status_code)
15
  if response.status_code == 200:
16
- output = response.json()
17
- return output["guess"], output["sim"], output["rank"]
18
  else:
19
- return word, None, None
 
 
20
 
21
- def get_valid_hints():
22
-
23
- pass
 
1
+ from datetime import date, datetime
2
+ from pytz import utc, timezone
3
  import requests
4
 
5
  def get_secret(puzzle_num: int):
 
8
  if response.status_code == 200:
9
  return response.content
10
  else:
11
+ return "Not found error."
12
 
13
  def get_guess(word: str, puzzle_num: int):
14
  request_url = f"https://semantoru.com/guess/{puzzle_num}/{word}"
15
  response = requests.get(request_url)
16
  print(response.status_code)
17
  if response.status_code == 200:
18
+ return response.json()
 
19
  else:
20
+ return {"guess": word,
21
+ "sim": None,
22
+ "rank": None}
23
 
24
+ def get_puzzle_num():
25
+ FIRST_DAY = date(2023, 4, 2)
26
+ return (utc.localize(datetime.utcnow()).astimezone(timezone('Asia/Tokyo')).date() - FIRST_DAY).days