ai-plays-jackbox 0.4.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. ai_plays_jackbox/__init__.py +0 -0
  2. ai_plays_jackbox/bot/__init__.py +0 -0
  3. ai_plays_jackbox/bot/bot_base.py +219 -0
  4. ai_plays_jackbox/bot/bot_factory.py +31 -0
  5. ai_plays_jackbox/bot/bot_personality.py +111 -0
  6. ai_plays_jackbox/bot/jackbox5/__init__.py +0 -0
  7. ai_plays_jackbox/bot/jackbox5/bot_base.py +26 -0
  8. ai_plays_jackbox/bot/jackbox5/mad_verse_city.py +121 -0
  9. ai_plays_jackbox/bot/jackbox5/patently_stupid.py +168 -0
  10. ai_plays_jackbox/bot/jackbox6/__init__.py +0 -0
  11. ai_plays_jackbox/bot/jackbox6/bot_base.py +20 -0
  12. ai_plays_jackbox/bot/jackbox6/dictionarium.py +105 -0
  13. ai_plays_jackbox/bot/jackbox6/joke_boat.py +105 -0
  14. ai_plays_jackbox/bot/jackbox7/__init__.py +0 -0
  15. ai_plays_jackbox/bot/jackbox7/bot_base.py +20 -0
  16. ai_plays_jackbox/bot/jackbox7/quiplash3.py +108 -0
  17. ai_plays_jackbox/bot/jackbox8/__init__.py +0 -0
  18. ai_plays_jackbox/bot/jackbox8/bot_base.py +20 -0
  19. ai_plays_jackbox/bot/jackbox8/job_job.py +205 -0
  20. ai_plays_jackbox/bot/standalone/__init__.py +0 -0
  21. ai_plays_jackbox/bot/standalone/drawful2.py +159 -0
  22. ai_plays_jackbox/cli/__init__.py +0 -0
  23. ai_plays_jackbox/cli/main.py +117 -0
  24. ai_plays_jackbox/constants.py +4 -0
  25. ai_plays_jackbox/llm/__init__.py +1 -0
  26. ai_plays_jackbox/llm/chat_model.py +39 -0
  27. ai_plays_jackbox/llm/chat_model_factory.py +35 -0
  28. ai_plays_jackbox/llm/gemini_model.py +86 -0
  29. ai_plays_jackbox/llm/ollama_model.py +53 -0
  30. ai_plays_jackbox/llm/openai_model.py +86 -0
  31. ai_plays_jackbox/room/__init__.py +0 -0
  32. ai_plays_jackbox/room/room.py +87 -0
  33. ai_plays_jackbox/run.py +23 -0
  34. ai_plays_jackbox/scripts/lint.py +18 -0
  35. ai_plays_jackbox/ui/__init__.py +0 -0
  36. ai_plays_jackbox/ui/main.py +12 -0
  37. ai_plays_jackbox/ui/startup.py +271 -0
  38. ai_plays_jackbox-0.4.1.dist-info/METADATA +158 -0
  39. ai_plays_jackbox-0.4.1.dist-info/RECORD +42 -0
  40. ai_plays_jackbox-0.4.1.dist-info/WHEEL +4 -0
  41. ai_plays_jackbox-0.4.1.dist-info/entry_points.txt +4 -0
  42. ai_plays_jackbox-0.4.1.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,20 @@
1
+ from abc import ABC
2
+
3
+ from ai_plays_jackbox.bot.bot_base import JackBoxBotBase
4
+
5
+
6
+ class JackBox6BotBase(JackBoxBotBase, ABC):
7
+
8
+ @property
9
+ def _player_operation_key(self):
10
+ return f"bc:customer:"
11
+
12
+ def _is_player_operation_key(self, operation_key: str) -> bool:
13
+ return self._player_operation_key in operation_key
14
+
15
+ @property
16
+ def _room_operation_key(self):
17
+ return "bc:room"
18
+
19
+ def _is_room_operation_key(self, operation_key: str) -> bool:
20
+ return operation_key == self._room_operation_key
@@ -0,0 +1,105 @@
1
+ import random
2
+
3
+ from loguru import logger
4
+
5
+ from ai_plays_jackbox.bot.jackbox6.bot_base import JackBox6BotBase
6
+
7
+ _DEFINITION_PROMPT_TEMPLATE = """
8
+ You are playing Dictionarium.
9
+
10
+ {prompt}
11
+
12
+ When generating your response, follow these rules:
13
+ - Your personality is: {personality}
14
+ - You response must be {max_length} characters or less.
15
+ - Do not include quotes in your response.
16
+ """
17
+
18
+ _SYNONYM_PROMPT_TEMPLATE = """
19
+ You are playing Dictionarium.
20
+
21
+ {prompt}
22
+
23
+ When generating your response, follow these rules:
24
+ - Your personality is: {personality}
25
+ - You response must be {max_length} characters or less.
26
+ - Do not include quotes in your response.
27
+ """
28
+
29
+ _SENTENCE_PROMPT_TEMPLATE = """
30
+ You are playing Dictionarium. You need to use a made up word in a sentence.
31
+
32
+ {prompt}
33
+
34
+ When generating your response, follow these rules:
35
+ - Your personality is: {personality}
36
+ - You response must be {max_length} characters or less.
37
+ - Do not include quotes in your response.
38
+ """
39
+
40
+
41
+ class DictionariumBot(JackBox6BotBase):
42
+ def __init__(self, *args, **kwargs):
43
+ super().__init__(*args, **kwargs)
44
+
45
+ def _handle_welcome(self, data: dict):
46
+ pass
47
+
48
+ def _handle_player_operation(self, data: dict):
49
+ if not data:
50
+ return
51
+ room_state = data.get("state", None)
52
+ if not room_state:
53
+ return
54
+
55
+ prompt = data.get("prompt", {})
56
+ prompt_html = prompt.get("html", "")
57
+ clean_prompt = self._html_to_text(prompt_html)
58
+ max_length = data.get("maxLength", 150)
59
+
60
+ match room_state:
61
+ case "EnterSingleText":
62
+ entry = data.get("entry", None)
63
+ entry_id = data.get("entryId", "")
64
+ print(data)
65
+ if not entry:
66
+ if entry_id == "Definition":
67
+ logger.info("Generating definition...")
68
+ template = _DEFINITION_PROMPT_TEMPLATE
69
+ elif entry_id == "Synonym":
70
+ logger.info("Generating synonym...")
71
+ template = _SYNONYM_PROMPT_TEMPLATE
72
+ elif entry_id == "Sentence":
73
+ logger.info("Generating sentence...")
74
+ template = _SENTENCE_PROMPT_TEMPLATE
75
+ else:
76
+ return
77
+
78
+ formatted_prompt = template.format(
79
+ personality=self._personality,
80
+ prompt=clean_prompt,
81
+ max_length=max_length,
82
+ )
83
+ submission = self._chat_model.generate_text(
84
+ formatted_prompt,
85
+ "",
86
+ temperature=self._chat_model._chat_model_temperature,
87
+ top_p=self._chat_model._chat_model_top_p,
88
+ )
89
+ submission = submission[: max_length - 1]
90
+ self._client_send({"action": "write", "entry": submission})
91
+
92
+ case "MakeSingleChoice":
93
+ choice_type = data.get("choiceType", "")
94
+ if (
95
+ choice_type == "ChooseDefinition"
96
+ or choice_type == "ChooseSynonym"
97
+ or choice_type == "ChooseSentence"
98
+ ):
99
+ choices: list[dict] = data.get("choices", [])
100
+ choice_indexes = [i for i in range(0, len(choices))]
101
+ selected_choice = random.choice(choice_indexes)
102
+ self._client_send({"action": "choose", "choice": selected_choice})
103
+
104
+ def _handle_room_operation(self, data: dict):
105
+ pass
@@ -0,0 +1,105 @@
1
+ import random
2
+
3
+ from loguru import logger
4
+
5
+ from ai_plays_jackbox.bot.jackbox6.bot_base import JackBox6BotBase
6
+
7
+ _TOPIC_PROMPT_TEMPLATE = """
8
+ You are playing Joke Boat.
9
+
10
+ You are being asked to come up with a topic that is {placeholder}.
11
+
12
+ When generating your response, follow these rules:
13
+ - Your personality is: {personality}
14
+ - You response must be {max_length} characters or less
15
+ - Your response should be a single word.
16
+ - Do not include quotes in your response or any newlines, just the response itself
17
+ """
18
+
19
+ _PUNCHLINE_INSTRUCTIONS_TEMPLATE = """
20
+ You are playing Joke Boat. You need to fill in the given prompt with a punchline.
21
+
22
+ When generating your response, follow these rules:
23
+ - Your personality is: {personality}
24
+ - You response must be {max_length} characters or less
25
+ - Do not include quotes in your response or any newlines, just the response itself
26
+ """
27
+
28
+
29
+ class JokeBoatBot(JackBox6BotBase):
30
+ def __init__(self, *args, **kwargs):
31
+ super().__init__(*args, **kwargs)
32
+
33
+ def _handle_welcome(self, data: dict):
34
+ pass
35
+
36
+ def _handle_player_operation(self, data: dict):
37
+ if not data:
38
+ return
39
+ room_state = data.get("state", None)
40
+ if not room_state:
41
+ return
42
+
43
+ prompt = data.get("prompt", {})
44
+ prompt_html = prompt.get("html", "")
45
+ clean_prompt = self._html_to_text(prompt_html)
46
+
47
+ match room_state:
48
+ case "MakeSingleChoice":
49
+ choices: list[dict] = data.get("choices", [])
50
+ choice_type = data.get("choiceType", "")
51
+ choice_indexes = [i for i in range(0, len(choices))]
52
+ selected_choice = random.choice(choice_indexes)
53
+
54
+ if choice_type == "ChooseAuthorReady":
55
+ selected_choice = 1
56
+ if choice_type == "Skip":
57
+ selected_choice = 0
58
+
59
+ if data.get("chosen", None) is None:
60
+ self._client_send({"action": "choose", "choice": selected_choice})
61
+
62
+ case "EnterSingleText":
63
+ if "Write as many topics as you can." in clean_prompt:
64
+ placeholder = data.get("placeholder", "")
65
+ max_length = data.get("maxLength", 42)
66
+ topic = self._generate_topic(placeholder, max_length)
67
+ self._client_send({"action": "write", "entry": topic})
68
+ if "Write your punchline" in clean_prompt or "Write the punchline to this joke" in clean_prompt:
69
+ max_length = data.get("maxLength", 80)
70
+ punchline = self._generate_punchline(clean_prompt, max_length)
71
+ self._client_send({"action": "write", "entry": punchline})
72
+
73
+ def _handle_room_operation(self, data: dict):
74
+ pass
75
+
76
+ def _generate_topic(self, placeholder: str, max_length: int) -> str:
77
+ logger.info("Generating topic...")
78
+ formatted_prompt = _TOPIC_PROMPT_TEMPLATE.format(
79
+ personality=self._personality,
80
+ placeholder=placeholder,
81
+ max_length=max_length,
82
+ )
83
+
84
+ topic = self._chat_model.generate_text(
85
+ formatted_prompt,
86
+ "",
87
+ temperature=self._chat_model._chat_model_temperature,
88
+ top_p=self._chat_model._chat_model_top_p,
89
+ )
90
+ return topic[:max_length]
91
+
92
+ def _generate_punchline(self, prompt: str, max_length: int) -> str:
93
+ logger.info("Generating punchline...")
94
+ formatted_instructions = _PUNCHLINE_INSTRUCTIONS_TEMPLATE.format(
95
+ personality=self._personality,
96
+ prompt=prompt,
97
+ max_length=max_length,
98
+ )
99
+ punchline = self._chat_model.generate_text(
100
+ prompt,
101
+ formatted_instructions,
102
+ temperature=self._chat_model._chat_model_temperature,
103
+ top_p=self._chat_model._chat_model_top_p,
104
+ )
105
+ return punchline[:max_length]
File without changes
@@ -0,0 +1,20 @@
1
+ from abc import ABC
2
+
3
+ from ai_plays_jackbox.bot.bot_base import JackBoxBotBase
4
+
5
+
6
+ class JackBox7BotBase(JackBoxBotBase, ABC):
7
+
8
+ @property
9
+ def _player_operation_key(self) -> str:
10
+ return f"player:{self._player_id}"
11
+
12
+ def _is_player_operation_key(self, operation_key: str) -> bool:
13
+ return operation_key == self._player_operation_key
14
+
15
+ @property
16
+ def _room_operation_key(self) -> str:
17
+ return "room"
18
+
19
+ def _is_room_operation_key(self, operation_key: str) -> bool:
20
+ return operation_key == self._room_operation_key
@@ -0,0 +1,108 @@
1
+ import random
2
+
3
+ from loguru import logger
4
+
5
+ from ai_plays_jackbox.bot.jackbox7.bot_base import JackBox7BotBase
6
+
7
+ _QUIP_PROMPT_INSTRUCTIONS_TEMPLATE = """
8
+ You are playing Quiplash 3. You need to fill in the given prompt.
9
+
10
+ When generating your response, follow these rules:
11
+ - Your personality is: {personality}
12
+ - You response must be 45 letters or less.
13
+ - Do not include quotes in your response.
14
+ """
15
+
16
+ _FINAL_QUIP_PROMPT_INSTRUCTIONS_TEMPLATE = """
17
+ You are playing Quiplash 3 and it is the final round. The prompt will include three blanks, all of which you need to fill in.
18
+
19
+ When generating your response, follow these rules:
20
+ - Your personality is: {personality}
21
+ - Separate your answers by the character '|', for example 'Apple|Orange|Banana'.
22
+ - Each answer must be 45 letters or less.
23
+ - Do not include quotes in your response.
24
+ """
25
+
26
+ _QUIP_CHOICE_PROMPT_INSTRUCTIONS_TEMPLATE = """
27
+ You are playing Quiplash 3 and you need to vote for your favorite response to the prompt "{prompt}".
28
+ Choose your favorite by responding with the number next to your choice. Only respond with the number and nothing else.
29
+ """
30
+
31
+
32
+ class Quiplash3Bot(JackBox7BotBase):
33
+ _selected_avatar: bool = False
34
+
35
+ def __init__(self, *args, **kwargs):
36
+ super().__init__(*args, **kwargs)
37
+
38
+ def _handle_welcome(self, data: dict):
39
+ pass
40
+
41
+ def _handle_player_operation(self, data: dict):
42
+ if not data:
43
+ return
44
+ room_state = data.get("state", None)
45
+ if not room_state:
46
+ return
47
+ prompt = data.get("prompt")
48
+ prompt_text = self._html_to_text(prompt.get("html", "")) if prompt is not None else ""
49
+ text_key = data.get("textKey", "")
50
+ match room_state:
51
+ case "EnterSingleText":
52
+ if not data["entry"]:
53
+ quip = self._generate_quip(prompt_text)
54
+ self._send_ws("text/update", {"key": text_key, "val": quip})
55
+ case "EnterTextList":
56
+ if not data["entries"]:
57
+ quip = self._generate_quip(prompt_text, final_round=True)
58
+ self._send_ws("text/update", {"key": text_key, "val": "\n".join(quip.split("|"))})
59
+ case "MakeSingleChoice":
60
+ choice = self._choose_favorite(prompt_text, data["choices"])
61
+ self._client_send({"action": "choose", "choice": choice})
62
+
63
+ def _handle_room_operation(self, data: dict):
64
+ if self._selected_avatar:
65
+ return
66
+ available_characters = [c["name"] for c in data["characters"] if c["available"]]
67
+ selected_character = random.choice(available_characters)
68
+ self._client_send({"action": "avatar", "name": selected_character})
69
+ self._selected_avatar = True
70
+
71
+ def _generate_quip(self, prompt: str, final_round: bool = False) -> str:
72
+ max_tokens = 10
73
+ instructions = _QUIP_PROMPT_INSTRUCTIONS_TEMPLATE.format(personality=self._personality)
74
+ if final_round:
75
+ max_tokens = 32
76
+ instructions = _FINAL_QUIP_PROMPT_INSTRUCTIONS_TEMPLATE.format(personality=self._personality)
77
+ quip = self._chat_model.generate_text(
78
+ prompt,
79
+ instructions,
80
+ max_tokens=max_tokens,
81
+ temperature=self._chat_model._chat_model_temperature,
82
+ top_p=self._chat_model._chat_model_top_p,
83
+ )
84
+ return quip
85
+
86
+ def _choose_favorite(self, prompt: str, choices: list[dict]) -> int:
87
+ choices_str = "\n".join([f"{i+1}. {v['html']}" for i, v in enumerate(choices)])
88
+ instructions = _QUIP_CHOICE_PROMPT_INSTRUCTIONS_TEMPLATE.format(prompt=prompt)
89
+ response = self._chat_model.generate_text(
90
+ f"Vote for your favorite response. Your options are: {choices_str}",
91
+ instructions,
92
+ max_tokens=1,
93
+ )
94
+ try:
95
+ choosen_prompt = int(response)
96
+ except ValueError:
97
+ logger.warning(f"Can't choose favorite since response was not an int: {response}")
98
+ return self._choose_random_favorite(choices)
99
+
100
+ if choosen_prompt < 1 or choosen_prompt > len(choices):
101
+ logger.warning(f"Can't choose favorite since response was not a valid value: {response}")
102
+ return self._choose_random_favorite(choices)
103
+ else:
104
+ return choosen_prompt - 1
105
+
106
+ def _choose_random_favorite(self, choices: list[dict]) -> int:
107
+ choices_as_ints = [i for i in range(0, len(choices))]
108
+ return random.choice(choices_as_ints)
File without changes
@@ -0,0 +1,20 @@
1
+ from abc import ABC
2
+
3
+ from ai_plays_jackbox.bot.bot_base import JackBoxBotBase
4
+
5
+
6
+ class JackBox8BotBase(JackBoxBotBase, ABC):
7
+
8
+ @property
9
+ def _player_operation_key(self) -> str:
10
+ return f"player:{self._player_id}"
11
+
12
+ def _is_player_operation_key(self, operation_key: str) -> bool:
13
+ return operation_key == self._player_operation_key
14
+
15
+ @property
16
+ def _room_operation_key(self) -> str:
17
+ return "room"
18
+
19
+ def _is_room_operation_key(self, operation_key: str) -> bool:
20
+ return operation_key == self._room_operation_key
@@ -0,0 +1,205 @@
1
+ import random
2
+ import string
3
+
4
+ from loguru import logger
5
+
6
+ from ai_plays_jackbox.bot.jackbox8.bot_base import JackBox8BotBase
7
+
8
+ _RESPONSE_PROMPT_TEMPLATE = """
9
+ You are playing Job Job. You need response to the given prompt.
10
+
11
+ When generating your response, follow these rules:
12
+ - Your personality is: {personality}
13
+ - Your response must be {max_length} letters or less.
14
+ - Your response must have a minimum of {min_words} words.
15
+ - Do not include quotes in your response.
16
+
17
+ {instruction}
18
+
19
+ Your prompt is:
20
+
21
+ {prompt}
22
+ """
23
+
24
+ _COMPOSITION_PROMPT_TEMPLATE = """
25
+ You are playing Job Job. You must create a response to a interview question using only specific words given.
26
+
27
+ When generating your response, follow these rules:
28
+ - Your personality is: {personality}
29
+ - Your response must only use the allowed words or characters, nothing else
30
+ - If you decide to use a character, you must have it separated by a space from any words
31
+ - You can select a maximum of {max_words} words
32
+
33
+ Your interview question is:
34
+
35
+ {prompt}
36
+
37
+ Your allowed words or characters are:
38
+
39
+ {all_possible_words_str}
40
+ """
41
+
42
+
43
+ class JobJobBot(JackBox8BotBase):
44
+ def __init__(self, *args, **kwargs):
45
+ super().__init__(*args, **kwargs)
46
+
47
+ def _handle_welcome(self, data: dict):
48
+ pass
49
+
50
+ def _handle_player_operation(self, data: dict):
51
+ if not data:
52
+ return
53
+
54
+ kind = data.get("kind", "")
55
+ has_controls = data.get("hasControls", False)
56
+ response_key = data.get("responseKey", "")
57
+ done_key = data.get("doneKey", "")
58
+
59
+ if has_controls:
60
+ if "skip:" in response_key:
61
+ self._object_update(response_key, {"action": "skip"})
62
+ return
63
+
64
+ match kind:
65
+ case "writing":
66
+ instruction = data.get("instruction", "")
67
+ prompt = data.get("prompt", "")
68
+ max_length = data.get("maxLength", 128)
69
+ min_words = data.get("minWords", 5)
70
+ text_key = data.get("textKey", "")
71
+ response = self._generate_response(instruction, prompt, max_length, min_words)
72
+ self._text_update(text_key, response)
73
+ self._object_update(done_key, {"done": True})
74
+
75
+ case "magnets":
76
+ prompt = data.get("prompt", "")
77
+ answer_key = data.get("answerKey", "")
78
+ stash = data.get("stash", [[]])
79
+ max_words = data.get("maxWords", 12)
80
+ composition_list = self._generate_composition_list(prompt, stash, max_words)
81
+ self._object_update(
82
+ answer_key,
83
+ {
84
+ "final": True,
85
+ "text": composition_list,
86
+ },
87
+ )
88
+
89
+ case "resumagents":
90
+ prompt = data.get("prompt", "")
91
+ answer_key = data.get("answerKey", "")
92
+ stash = data.get("stash", [[]])
93
+ max_words = data.get("maxWords", 12)
94
+ max_words_per_answer = data.get("maxWordsPerAnswer", 8)
95
+ num_answers = data.get("numAnswers", 8)
96
+ resume_composition_list = self._generate_resume_composition_list(
97
+ prompt, stash, max_words, max_words_per_answer, num_answers
98
+ )
99
+ self._object_update(
100
+ answer_key,
101
+ {
102
+ "final": True,
103
+ "text": resume_composition_list,
104
+ },
105
+ )
106
+
107
+ case "voting":
108
+ choices: list[dict] = data.get("choices", [])
109
+ choice_indexes = [i for i in range(0, len(choices))]
110
+ selected_choice = random.choice(choice_indexes)
111
+ self._object_update(response_key, {"action": "choose", "choice": selected_choice})
112
+
113
+ def _handle_room_operation(self, data: dict):
114
+ pass
115
+
116
+ def _generate_response(self, instruction: str, prompt: str, max_length: int, min_words: int) -> str:
117
+ formatted_prompt = _RESPONSE_PROMPT_TEMPLATE.format(
118
+ personality=self._personality,
119
+ max_length=max_length,
120
+ min_words=min_words,
121
+ instruction=instruction,
122
+ prompt=prompt,
123
+ )
124
+ response = self._chat_model.generate_text(
125
+ formatted_prompt,
126
+ "",
127
+ temperature=self._chat_model._chat_model_temperature,
128
+ top_p=self._chat_model._chat_model_top_p,
129
+ )
130
+ if len(response) > max_length:
131
+ response = response[: max_length - 1]
132
+ return response
133
+
134
+ def _generate_composition_list(
135
+ self,
136
+ prompt: str,
137
+ stash: list[list[str]],
138
+ max_words: int,
139
+ ) -> list[dict]:
140
+
141
+ possible_word_choices = []
142
+
143
+ for stash_entry in stash:
144
+ for word in stash_entry:
145
+ possible_word_choices.append(word)
146
+
147
+ all_possible_words_str = "\n".join([word for word in possible_word_choices])
148
+ formatted_prompt = _COMPOSITION_PROMPT_TEMPLATE.format(
149
+ personality=self._personality,
150
+ all_possible_words_str=all_possible_words_str,
151
+ max_words=max_words,
152
+ prompt=prompt,
153
+ )
154
+ response = self._chat_model.generate_text(
155
+ formatted_prompt,
156
+ "",
157
+ temperature=self._chat_model._chat_model_temperature,
158
+ top_p=self._chat_model._chat_model_top_p,
159
+ )
160
+
161
+ ## Listen, I know this is isn't the fastest way to search
162
+ ## It's 12 words, bite me with your Big O notation
163
+ composition_list = []
164
+ response_list = response.split(" ")
165
+ for response_word in response_list:
166
+ found_word = False
167
+ response_word = response_word.strip()
168
+ if not all(char in string.punctuation for char in response_word):
169
+ response_word = response_word.translate(str.maketrans("", "", string.punctuation)).lower()
170
+
171
+ if not found_word:
172
+ for stash_index, stash_entry in enumerate(stash):
173
+ for check_word_index, check_word in enumerate(stash_entry):
174
+ if response_word == check_word.lower():
175
+ composition_list.append(
176
+ {
177
+ "index": stash_index,
178
+ "word": check_word_index,
179
+ }
180
+ )
181
+ found_word = True
182
+ break
183
+ if found_word:
184
+ break
185
+
186
+ if not found_word:
187
+ logger.warning(f"Word not found in choices: {response_word}")
188
+
189
+ if len(composition_list) > max_words:
190
+ composition_list = composition_list[: max_words - 1]
191
+ return composition_list
192
+
193
+ def _generate_resume_composition_list(
194
+ self,
195
+ prompt: str,
196
+ stash: list[list[str]],
197
+ max_words: int,
198
+ max_words_per_answers: int,
199
+ num_of_answers: int,
200
+ ) -> list[list[dict]]:
201
+ # TODO Figure this out
202
+ resume_composition_list = []
203
+ for _ in range(0, num_of_answers):
204
+ resume_composition_list.append([{"index": 0, "word": 0}])
205
+ return resume_composition_list
File without changes