diff --git a/Dockerfile b/Dockerfile index 8c92027..fe05a1b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,6 +17,7 @@ COPY pages pages RUN python -m venv venv ENV PATH="/app/venv/bin:$PATH" +# Install dependencies RUN pip3 install --no-cache-dir -r requirements.txt # Specify the command to run the app diff --git a/README.md b/README.md index c1b823b..93ba579 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ # practice-a-language -Practice speaking a language in different settings + +Practice speaking a language in different settings at [https://practicealanguage.xyz](https://practicealanguage.xyz) diff --git a/app.py b/app.py index b5ce426..4c795c8 100644 --- a/app.py +++ b/app.py @@ -29,7 +29,7 @@ def serve_sitemap(): app.index_string = """ - + @@ -40,6 +40,19 @@ def serve_sitemap(): gtag('config', 'G-THNE3MSS49'); + + + + + + + + + + + + + {%metas%} {%title%} {%favicon%} @@ -70,6 +83,10 @@ def serve_sitemap(): @server.route("/save_audio_recording", methods=["POST"]) def save_audio_recording(): + """ + Save the audio that the user has recorded so that it can be sent + to OpenAI's Whisper-1 API. + """ try: data = request.get_json() audio_data = data["audio_data"] diff --git a/assets/app.css b/assets/app.css index cbba35e..61da9e6 100644 --- a/assets/app.css +++ b/assets/app.css @@ -141,6 +141,9 @@ body { margin: 0px 0px 30px; width: 100%; } +#user-response-buttons { + width: 42px; +} #user-response-text { height: 80px; margin-right: 10px; diff --git a/assets/chat_request.py b/assets/chat_request.py index 706e349..0a22d22 100755 --- a/assets/chat_request.py +++ b/assets/chat_request.py @@ -89,7 +89,7 @@ def _chat_completion_request(messages: List[Dict[str, str]]) -> Dict: json_data = { "model": "gpt-3.5-turbo-0613", "messages": messages, - "temperature": 1.5, + "temperature": 1.5, # Higher values provide more varied responses } try: response = requests.post( diff --git a/assets/footer.css b/assets/footer.css index 8c8d259..0b78b80 100644 --- a/assets/footer.css +++ b/assets/footer.css @@ -29,7 +29,7 @@ } #footer a, #footer p { display: block; - margin: 0px auto 5px; + margin: 0px auto 10px; } .footer-pipe { display: none; diff --git a/callbacks/display_components.py b/callbacks/display_components.py index 5d36de0..847ccd9 100644 --- a/callbacks/display_components.py +++ b/callbacks/display_components.py @@ -5,7 +5,7 @@ @callback( Output("help-highlight-for-translation", "style"), - Output("help-translate-language-known", "style"), + Output("user-response-helper-icons", "style"), Input("conversation", "children"), ) def display_conversation_helpers( @@ -19,14 +19,16 @@ def display_conversation_helpers( Returns: The style value for the highlight-to-translate text - The style value for the translate-language-known icon. + The style value for the user-response-helper-icons div. """ if conversation: return ( {"display": "block"}, { + "display": "flex", "margin": "20px 0px 0px", + "justify-content": "space-between", }, ) diff --git a/pages/home.py b/pages/home.py index 2e01fa4..2e39b3d 100644 --- a/pages/home.py +++ b/pages/home.py @@ -31,18 +31,22 @@ layout = html.Div( children=[ + # Header section html.Div( id="header", children=[ html.H1(id="title", children="Practice a Language"), ], ), + # Content section html.Div( id="content", children=[ + # Language selection section html.Div( className="languages", children=[ + # Known language dropdown html.Div( id="language-menu-known", children=[ @@ -54,6 +58,7 @@ ), ], ), + # Learn language dropdown html.Div( id="language-menu-learn", children=[ @@ -67,9 +72,11 @@ ), ], ), + # Conversation setting section html.Div( className="conversation-setting-wrapper", children=[ + # Conversation setting dropdown html.Div( className="conversation-setting-menu", children=[ @@ -99,6 +106,7 @@ ), ], ), + # Custom conversation setting input html.Div( className="conversation-setting-custom-input", children=[ @@ -111,6 +119,7 @@ ), ], ), + # Toggle to play audio of new messages html.P( id="toggle-play-audio-wrapper", children=[ @@ -118,26 +127,31 @@ "Play audio of new message", id="toggle-play-audio-text" ), daq.ToggleSwitch( - id="toggle-play-audio", value=True, color="#322CA1" + id="toggle-play-audio", value=True, color="#322CA1", ), ], ), + # Button to start a conversation dbc.Button( "Start a new conversation", id="button-start-conversation", n_clicks=0, disabled=True, ), + # Conversation section html.Div( id="conversation-div", children=[ + # Helper text to highlight for translation html.P( "Highlight text to see the translation.", id="help-highlight-for-translation", style={"display": "none"}, ), + # Show translated text that is highlighted DashSelectable(id="conversation"), html.Div(id="translation"), + # Icons to show when loading a new message html.Div( id="loading", children=[ @@ -161,20 +175,37 @@ ), ], ), - html.I( - className="bi bi-question-circle", - id="help-translate-language-known", - style={"display": "none"}, - ), - dbc.Tooltip( - id="tooltip-translate-language-known", - target="help-translate-language-known", - ), + # Helper icons and tooltip about writing and recording user response + html.Div(id="user-response-helper-icons", children=[ + html.Div(children=[ + html.I( + className="bi bi-question-circle", + id="help-translate-language-known", + ), + dbc.Tooltip( + id="tooltip-translate-language-known", + target="help-translate-language-known", + ), + ]), + html.Div(children=[ + html.I( + className="bi bi-question-circle", + id="help-change-microphone-setting", + ), + dbc.Tooltip( + id="tooltip-change-microphone-setting", + target="help-change-microphone-setting", + children="If you are unable to record audio, you might need to change your device's microphone settings." + ), + ]), + ]), + # User response section html.Div( id="user-response", children=[ dbc.Textarea(id="user-response-text"), html.Div( + id="user-response-buttons", children=[ dbc.Button( html.I(className="bi bi-mic-fill"), @@ -420,9 +451,7 @@ def play_newest_message( if conversation and toggle_audio: - newest_message = conversation[-1]["props"]["children"][0]["props"]["children"][ - 0 - ] + newest_message = conversation[-1]["props"]["children"][0]["props"]["children"][0] language_learn_abbreviation = LANGUAGES_DICT[language_learn] return get_audio_file(newest_message, language_learn_abbreviation) diff --git a/requirements.txt b/requirements.txt index 42a30ed..d971388 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -dash==2.11.1 +dash==2.12.1 dash-bootstrap-components==1.4.2 dash-daq==0.5.0 dash-selectable==0.0.1 @@ -7,4 +7,5 @@ Flask==2.2.5 gTTS==2.3.2 langdetect==1.0.9 openai==0.27.8 +orjson==3.9.5 tenacity==8.2.2 diff --git a/robots.txt b/robots.txt index 5dac3e1..ab20cd3 100644 --- a/robots.txt +++ b/robots.txt @@ -1,2 +1,2 @@ User-agent: * -Sitemap: https://statisticalstories.xyz/sitemap.xml +Sitemap: https://practicealanguage.xyz/sitemap.xml diff --git a/sitemap.xml b/sitemap.xml index ec1c1c9..55dd747 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,7 +2,7 @@ https://practicealanguage.xyz/ - 2023-08-14 + 2023-08-23 monthly 1.0