Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import emoji | |
| import os | |
| from openai import OpenAI | |
| from random import shuffle | |
| from loguru import logger | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| from retry import retry | |
| from typing import List, Dict | |
| client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) | |
| # | |
| # -- llm.py -- | |
| # | |
| load_dotenv() | |
| country = {"nl": {"language":"Dutch", "country":"Netherlands"}, | |
| "de": {"language":"German", "country":"Germany"}, | |
| "se": {"language":"Swedish", "country":"Sweden"}, | |
| "en": {"language":"English", "country":"England"} | |
| } | |
| levels = {"easy": [3, 6], | |
| "medium": [5, 12], | |
| "hard": [12, 20]} | |
| def get_languages(): | |
| return list(country.keys()) | |
| def get_level_names(): | |
| return list(levels.keys()) | |
| def parse_response(response:dict, min_length:int=10) -> List[Dict[str, str]]: | |
| logger.debug(f"{response = }") | |
| logger.info(f"Parsing response from OpenAI API.") | |
| text = response.choices[0].message.content | |
| tokens = text.split("Sentence ") | |
| logger.debug(f"Number of tokens: {len(tokens)}") | |
| logger.debug(f"{tokens = }") | |
| qas = [] | |
| for token in tokens: | |
| if len(token) == 0: | |
| continue | |
| lines = token.split("\n") | |
| #print(f"{lines = }") | |
| original = lines[0][3:] | |
| true_trans = "" | |
| for line in lines: | |
| if line.startswith("True: "): | |
| true_trans = line[6:] | |
| # get line starting with "False: " | |
| false_trans = "" | |
| for line in lines: | |
| if line.startswith("False: "): | |
| false_trans = line[7:] | |
| # get line starting with "Funny: " | |
| funny_trans = "" | |
| for line in lines: | |
| if line.startswith("Funny: "): | |
| funny_trans = line[7:] | |
| qa = {"original": original, "true": true_trans, "false": false_trans, "funny": funny_trans} | |
| logger.debug(f"------------------------") | |
| logger.debug(f"{qa = }") | |
| logger.debug(f"------------------------") | |
| if len(qa["original"]) > min_length and len(qa["true"]) > min_length and len(qa["false"]) > min_length and len(qa["funny"]) > min_length: | |
| qas.append(qa) | |
| logger.info(f"Returning {len(qas)} valid QA pairs.") | |
| return qas | |
| def generate(n:int, input_country:str, target_country:str, level:str, temperature:float=0.80) -> Dict[str, str]: | |
| print(level_names) | |
| input_length = levels[level] | |
| logger.info(f"Generating {str(n)} QA pairs for {country[input_country]['language']} to {country[target_country]['language']} with level: {level}.") | |
| assert temperature >= 0.0 and temperature <= 1.0, "temperature must be between 0 and 1" | |
| response = client.chat.completions.create(model="gpt-3.5-turbo", | |
| messages=[ | |
| {"role": "system", "content": | |
| f"You are a helpful assistant at creating a translation game.\ | |
| You create sentences in {str(country[input_country]['language'])} with a length that is exactly between {str(input_length[0])} to {str(input_length[1])} words.\ | |
| You create translations in {str(country[target_country]['language'])}.\ | |
| Formulate your answer in exactly this format: Sentence N: [X],\True: [A],\nFalse: [B],\nFunny: [C]."}, | |
| {"role": "assistant", "content": | |
| f"Create original sentences with words, locations, concepts and phrases are typical for {str(country[input_country]['country'])} ."}, | |
| {"role": "user", "content": | |
| f"Generate {str(n)} funny sentences. You create 1 correct translation, 1 incorrect translations, and 1 which very wrong and funny."}, | |
| ], | |
| temperature=temperature) | |
| return response | |
| # n = 10 | |
| # input_country = "nl" | |
| # target_country = "de" | |
| # input_length = "easy" | |
| def get_QAs(n:int, input_country:str, target_country:str, level:str, temperature:float, debug:bool): | |
| if debug: | |
| return [ {"original": "The Netherlands is a country in Europe.", | |
| "true": "Nederland is een land in Europa.", | |
| "false": "Nederland is een land in Azië.", | |
| "funny": "Nederland is een aap in Europa."}, | |
| {"original": "Aap, noot, mies.", | |
| "true": "Aap.", | |
| "false": "Noot.", | |
| "funny": "Mies."} ] | |
| else: | |
| return parse_response(generate(n=n, input_country=input_country, target_country=target_country, level=level, temperature=temperature)) | |
| # | |
| # -- gui.py -- | |
| # | |
| languages = get_languages() | |
| level_names = get_level_names() | |
| global input_language | |
| input_language = "en" | |
| global target_language | |
| target_language = "nl" | |
| global level | |
| level = "medium" | |
| global temperature | |
| temperature = 0.80 | |
| global debug | |
| debug = False | |
| global share | |
| share = False | |
| qas = get_QAs(n=2, input_country=input_language, target_country=target_language, level=level, temperature=temperature, debug=debug) | |
| def get_qa(n:int=1, input_country:str=input_language, target_country:str=target_language, level:str=level, debug:bool=debug): | |
| logger.info(f"QAs left: {len(qas)}") | |
| qa = qas.pop(0) | |
| if len(qas) < 1: | |
| gr.Info("Generating new QAs...") | |
| logger.info(f"Generating new QAs...") | |
| logger.debug(f"{debug = }") | |
| qas.extend(get_QAs(n=n, | |
| input_country=input_country, | |
| target_country=target_country, | |
| level=level, | |
| temperature=temperature, | |
| debug=debug)) | |
| question_md = f"## {qa['original']}" | |
| options = [qa["true"], qa["false"], qa["funny"]] | |
| true = qa["true"] | |
| shuffle(options) | |
| options_md = f"""### A: {options[0]}\n\n### B: {options[1]}\n\n### C: {options[2]}""" | |
| global correct_answer | |
| correct_answer = [letter for letter, option in zip(["A", "B", "C"], options) if option == true][0] # set global | |
| logger.info(f"get_qa()") | |
| logger.info(f"Question: {question_md}") | |
| logger.info(f"Options: {options}") | |
| logger.info(f"Correct answer: {correct_answer}") | |
| return question_md, options_md | |
| def update(answer): | |
| # check answer | |
| logger.info(f"Checking answer \"{answer}\" against \"{correct_answer}\"") | |
| result = answer == correct_answer | |
| # display output | |
| gr.Info(emoji.emojize(":thumbs_up:"), ) if result else gr.Info(emoji.emojize(":thumbs_down:")) | |
| #output = emoji.emojize("# :thumbs_up:") if result else emoji.emojize("# :thumbs_down:") | |
| # update question | |
| question, options = get_qa() | |
| logger.info(f"update()") | |
| logger.info(f"Question: {question}") | |
| logger.info(f"Options: {options}") | |
| return question, options | |
| def update_settings(new_input_language, new_target_language, new_level, new_temperature): | |
| logger.info(f"update_settings()") | |
| logger.info(f"{new_input_language = }") | |
| logger.info(f"{new_target_language = }") | |
| logger.info(f"{new_level = }") | |
| logger.info(f"{new_temperature = }") | |
| global input_language | |
| global target_language | |
| global level | |
| global temperature | |
| changed = False | |
| if new_input_language != input_language: | |
| input_language = new_input_language | |
| changed = True | |
| if new_target_language != target_language: | |
| target_language = new_target_language | |
| changed = True | |
| if new_level != level: | |
| level = new_level | |
| changed = True | |
| if new_temperature != temperature: | |
| temperature = new_temperature | |
| changed = True | |
| logger.info(f"update_settings()") | |
| logger.info(f"{input_language = }") | |
| logger.info(f"{target_language = }") | |
| logger.info(f"{level = }") | |
| if changed: | |
| logger.info(f"Generating new QAs...") | |
| gr.Info("Generating new QAs...") | |
| qas = get_QAs(n=2, input_country=input_language, target_country=target_language, level=level, temperature=temperature, debug=debug) | |
| # update question | |
| question, options = get_qa() | |
| return question, options | |
| def get_interface(question, options): | |
| with gr.Blocks() as blocks: | |
| with gr.Tab("Game"): | |
| with gr.Column(): | |
| # show question | |
| question_md = gr.Markdown(question) | |
| # show answers | |
| answers_md = gr.Markdown(options) | |
| # add radio buttons | |
| radio = gr.Radio(choices=["A", "B", "C"], value=None, label=None, show_label=False, info=None) | |
| # add submit button | |
| button = gr.Button("Submit") | |
| # # show output box | |
| # output = gr.Markdown() | |
| # event listener | |
| button.click(fn=update, inputs=radio, outputs=[question_md, answers_md], scroll_to_output=True) | |
| with gr.Tab("Settings"): | |
| # Settings | |
| input_language = gr.Radio(languages, label="Input language", interactive=True) | |
| target_language = gr.Radio(languages, label="Output language", interactive=True) | |
| level = gr.Radio(level_names, label="Level", interactive=True) | |
| temperature = gr.Slider(minimum=0.0, maximum=0.85, step=0.01, value=0.80, label="Temperature", interactive=True) | |
| button = gr.Button("Update", interactive=True) | |
| button.click(fn=update_settings, inputs=[input_language, target_language, level, temperature], outputs=[question_md, answers_md], scroll_to_output=True) | |
| return blocks.queue().launch(share=share, debug=debug) | |
| question, options = get_qa(n=1, input_country=input_language, target_country=target_language, level=level, debug=debug) | |
| interface = get_interface(question, options) | |