shukdevdatta123's picture
Create app.py
7d42197 verified
import gradio as gr
import openai
import json
import os
from datetime import datetime
# Default configurations
SUPPORTED_LANGUAGES = {
"English": "en",
"Spanish": "es",
"French": "fr",
"German": "de",
"Chinese": "zh",
"Japanese": "ja",
"Italian": "it",
"Portuguese": "pt",
"Russian": "ru",
"Arabic": "ar"
}
PROFICIENCY_LEVELS = ["Beginner", "Intermediate", "Advanced"]
# Tracks conversation history and user stats
class LearningSession:
def __init__(self):
self.conversation_history = []
self.vocabulary = set()
self.session_start = datetime.now()
self.api_key = None
self.language = "Spanish"
self.language_code = "es"
self.proficiency = "Beginner"
self.thinking_mode = False
def add_message(self, role, content):
self.conversation_history.append({"role": role, "content": content})
if role == "assistant":
# Extract vocabulary from assistant responses
words = content.lower().replace('.', ' ').replace(',', ' ').replace('!', ' ').replace('?', ' ').split()
self.vocabulary.update(words)
def get_messages(self):
# Format for display
formatted = []
for msg in self.conversation_history:
if msg["role"] == "system":
continue
speaker = "πŸ‘€ You:" if msg["role"] == "user" else f"πŸ€– {self.language} Tutor:"
formatted.append(f"{speaker} {msg['content']}")
return "\n\n".join(formatted)
def get_openai_messages(self):
# Add system message for context
system_prompt = self._generate_system_prompt()
messages = [{"role": "system", "content": system_prompt}]
# Add conversation history (limit to last 10 messages to save tokens)
messages.extend(self.conversation_history[-10:])
return messages
def _generate_system_prompt(self):
if self.thinking_mode:
mode_instruction = (
"Use a thinking/reasoning mode where you carefully analyze the user's language, "
"provide corrections, and explain grammar concepts in detail."
)
else:
mode_instruction = (
"Maintain a natural conversational flow. Only correct critical errors that "
"would impede understanding, and do so gently within the conversation."
)
language_level_map = {
"Beginner": "Use simple vocabulary and short sentences. Frequently introduce basic vocabulary and simple grammar constructions.",
"Intermediate": "Use moderate vocabulary and varied sentence structures. Introduce idioms occasionally and more complex grammar patterns.",
"Advanced": "Use rich vocabulary, complex sentences, idioms, and cultural references. Challenge the learner with sophisticated language constructs."
}
level_instruction = language_level_map[self.proficiency]
return f"""You are a friendly and patient {self.language} language tutor.
IMPORTANT: You must respond ONLY in {self.language} except when explaining grammar concepts in thinking mode.
{mode_instruction}
{level_instruction}
Keep conversations engaging, diverse, and natural. Ask questions about the learner's interests, daily life, or opinions.
Occasionally introduce culturally relevant topics about countries where {self.language} is spoken.
Remember that you are helping someone learn {self.language}, so maintain an encouraging tone.
"""
# Initialize session
session = LearningSession()
def set_api_key(api_key):
"""Validate and set the OpenRouter API key."""
if not api_key.strip():
return "❌ Please enter your OpenRouter API key"
# Store API key in session
session.api_key = api_key
# Simple validation (just checking if it looks like a valid key format)
if len(api_key) < 20:
return "❌ API key looks too short. Please check it and try again."
return "βœ… API key set! You can now start your language learning session."
def update_settings(language, proficiency, thinking_mode):
"""Update session settings."""
session.language = language
session.language_code = SUPPORTED_LANGUAGES[language]
session.proficiency = proficiency
session.thinking_mode = thinking_mode
return f"Settings updated: Learning {language} at {proficiency} level. Thinking mode: {'On' if thinking_mode else 'Off'}"
def get_ai_response(user_message):
"""Get response from Qwen3 0.6B via OpenRouter API."""
if not session.api_key:
return "Please set your OpenRouter API key first."
if not user_message.strip():
return "Please enter a message."
try:
# Add user message to history
session.add_message("user", user_message)
# Create OpenAI client with OpenRouter base URL
client = openai.OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=session.api_key
)
# Get conversation history formatted for API
messages = session.get_openai_messages()
# Make API request
completion = client.chat.completions.create(
extra_headers={
"HTTP-Referer": "Language Learning Companion App",
"X-Title": "Language Learning App with Qwen3"
},
model="qwen/qwen3-0.6b-04-28:free",
messages=messages
)
# Extract response
ai_response = completion.choices[0].message.content
# Add to history
session.add_message("assistant", ai_response)
# Return full conversation history
return session.get_messages()
except Exception as e:
return f"Error: {str(e)}"
def reset_conversation():
"""Reset the conversation history."""
session.conversation_history = []
return "Conversation has been reset."
def get_vocabulary_list():
"""Get the current vocabulary list."""
if not session.vocabulary:
return "No vocabulary collected yet."
vocab_list = sorted(list(session.vocabulary))
return ", ".join(vocab_list)
def get_session_stats():
"""Get statistics about the current session."""
duration = datetime.now() - session.session_start
hours, remainder = divmod(duration.seconds, 3600)
minutes, seconds = divmod(remainder, 60)
stats = {
"Language": session.language,
"Proficiency Level": session.proficiency,
"Session Duration": f"{hours}h {minutes}m {seconds}s",
"Messages Exchanged": len(session.conversation_history),
"Vocabulary Words": len(session.vocabulary)
}
return json.dumps(stats, indent=2)
# Create Gradio interface
with gr.Blocks(title="Language Learning Companion") as app:
gr.Markdown("# 🌍 Language Learning Companion")
gr.Markdown("Learn languages through natural conversation with AI powered by Qwen3 0.6B")
with gr.Accordion("Setup", open=True):
api_key_input = gr.Textbox(
label="OpenRouter API Key",
placeholder="Enter your OpenRouter API key...",
type="password"
)
api_submit = gr.Button("Set API Key")
api_status = gr.Textbox(label="API Status", interactive=False)
api_submit.click(set_api_key, inputs=api_key_input, outputs=api_status)
with gr.Accordion("Learning Settings", open=True):
with gr.Row():
language_dropdown = gr.Dropdown(
choices=list(SUPPORTED_LANGUAGES.keys()),
value="Spanish",
label="Language to Learn"
)
proficiency_dropdown = gr.Dropdown(
choices=PROFICIENCY_LEVELS,
value="Beginner",
label="Proficiency Level"
)
thinking_checkbox = gr.Checkbox(
label="Enable Thinking Mode (Grammar Explanations)",
value=False
)
settings_submit = gr.Button("Update Settings")
settings_status = gr.Textbox(label="Settings Status", interactive=False)
settings_submit.click(
update_settings,
inputs=[language_dropdown, proficiency_dropdown, thinking_checkbox],
outputs=settings_status
)
with gr.Row():
with gr.Column(scale=2):
chat_output = gr.Textbox(
label="Conversation",
placeholder="Your conversation will appear here...",
lines=15,
interactive=False
)
user_input = gr.Textbox(
label="Your message",
placeholder=f"Type your message in any language...",
lines=2
)
with gr.Row():
submit_btn = gr.Button("Send", variant="primary")
reset_btn = gr.Button("Reset Conversation")
with gr.Column(scale=1):
with gr.Accordion("Vocabulary", open=True):
vocab_output = gr.Textbox(
label="Words Encountered",
lines=10,
interactive=False
)
vocab_btn = gr.Button("Show Vocabulary")
with gr.Accordion("Session Stats", open=True):
stats_output = gr.JSON(label="Learning Statistics")
stats_btn = gr.Button("Update Stats")
# Set up button actions
submit_btn.click(get_ai_response, inputs=user_input, outputs=chat_output)
reset_btn.click(reset_conversation, outputs=chat_output)
vocab_btn.click(get_vocabulary_list, outputs=vocab_output)
stats_btn.click(get_session_stats, outputs=stats_output)
# Allow pressing Enter to submit
user_input.submit(get_ai_response, inputs=user_input, outputs=chat_output)
# Launch the app
if __name__ == "__main__":
app.launch()