agente IA que enseña inglés. CONFIGURACIÓN INICIAL Carrusel imágenes: escenarios Selectbox: roles agente Selectbox: situaciones Botón "Start Conversation" CONVERSACIÓN (3 columnas, layout="wide") Izq (25%): Info escenario + gamificación (puntos, nivel, insignias, racha) Centro (50%): Chat con burbujas + input texto + botones (Send, Clear, New Topic) Der (25%): Correcciones tiempo real: errores (rojo), correcciones (verde), alternativas (azul) + retroalimentación español DASHBOARD KPIs: conversaciones, precisión%, palabras aprendidas, tiempo práctica Gráficos: progreso semanal, escenarios practicados, tipos errores Sistema insignias SIDEBAR: SESIONES Lista conversaciones guardadas (Ver, Continuar, Eliminar) Botones: New Conversation, Save Session GAMIFICACIÓN Puntos: +10 correcta, +20 vocabulario avanzado, +5 corrección Niveles: Beginner/Intermediate/Advanced/Expert Challenges diarios
To upload files, please first save the app
import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
from datetime import datetime, timedelta
import random
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Text, Float
from sqlalchemy.orm import DeclarativeBase, Session
# Database setup
class Base(DeclarativeBase):
pass
class Conversation(Base):
__tablename__ = "conversations"
id = Column(Integer, primary_key=True)
title = Column(String(100))
scenario = Column(String(50))
role = Column(String(50))
situation = Column(String(50))
messages = Column(Text)
created_at = Column(DateTime, default=datetime.now)
points = Column(Integer, default=0)
errors = Column(Integer, default=0)
corrections = Column(Integer, default=0)
engine = create_engine("sqlite:///english_ai.db")
Base.metadata.create_all(bind=engine)
# Set page config
st.set_page_config(
page_title="LinguaVerse - AI English Teacher",
page_icon="🎓",
layout="wide",
initial_sidebar_state="expanded"
)
# Initialize session state
if "current_page" not in st.session_state:
st.session_state.current_page = "setup"
if "messages" not in st.session_state:
st.session_state.messages = []
if "user_points" not in st.session_state:
st.session_state.user_points = 0
if "user_level" not in st.session_state:
st.session_state.user_level = "Beginner"
if "streak" not in st.session_state:
st.session_state.streak = 0
if "badges" not in st.session_state:
st.session_state.badges = []
if "selected_scenario" not in st.session_state:
st.session_state.selected_scenario = None
if "selected_role" not in st.session_state:
st.session_state.selected_role = None
if "selected_situation" not in st.session_state:
st.session_state.selected_situation = None
if "corrections" not in st.session_state:
st.session_state.corrections = []
# Scenarios data
scenarios = {
"Restaurant": {
"image": "🍽️",
"description": "Practice ordering food and dining conversations",
"roles": ["Customer", "Waiter", "Chef"],
"situations": ["Ordering food", "Complaining about food", "Making reservations", "Asking for the bill"]
},
"Airport": {
"image": "✈️",
"description": "Learn travel-related vocabulary and situations",
"roles": ["Passenger", "Flight attendant", "Security officer"],
"situations": ["Check-in", "Security check", "Boarding", "Customs"]
},
"Office": {
"image": "🏢",
"description": "Professional communication and workplace English",
"roles": ["Employee", "Manager", "Client"],
"situations": ["Job interview", "Meeting", "Presentation", "Networking"]
},
"Coffee Shop": {
"image": "☕",
"description": "Casual conversations and ordering drinks",
"roles": ["Customer", "Barista", "Friend"],
"situations": ["Ordering coffee", "Meeting friends", "Working remotely", "First date"]
}
}
def get_level_from_points(points):
if points < 100:
return "Beginner"
elif points < 300:
return "Intermediate"
elif points < 600:
return "Advanced"
else:
return "Expert"
def add_points(points):
st.session_state.user_points += points
st.session_state.user_level = get_level_from_points(st.session_state.user_points)
def simulate_ai_response(user_message):
# Simulate AI response with corrections
responses = [
"That's great! I understand what you mean.",
"Interesting point! Can you tell me more about that?",
"I see what you're saying. Let me help you with that.",
"Perfect! Your English is improving.",
"Good attempt! Let me help you with the grammar."
]
# Simulate corrections
corrections = []
if len(user_message.split()) > 5:
corrections.append({
"type": "grammar",
"original": "I go to store yesterday",
"correction": "I went to the store yesterday",
"explanation": "Use past tense 'went' for past actions"
})
return random.choice(responses), corrections
def save_conversation():
if st.session_state.messages:
with Session(engine) as session:
conv = Conversation(
title=f"{st.session_state.selected_scenario} - {datetime.now().strftime('%Y-%m-%d %H:%M')}",
scenario=st.session_state.selected_scenario,
role=st.session_state.selected_role,
situation=st.session_state.selected_situation,
messages=str(st.session_state.messages),
points=st.session_state.user_points,
errors=len([c for c in st.session_state.corrections if c["type"] == "error"]),
corrections=len(st.session_state.corrections)
)
session.add(conv)
session.commit()
st.success("Conversation saved!")
def load_conversations():
with Session(engine) as session:
return session.query(Conversation).order_by(Conversation.created_at.desc()).all()
# Sidebar
with st.sidebar:
st.title("🎓 LinguaVerse")
st.markdown("---")
# Navigation
if st.button("🏠 Home", use_container_width=True):
st.session_state.current_page = "setup"
if st.button("💬 Conversation", use_container_width=True):
st.session_state.current_page = "conversation"
if st.button("📊 Dashboard", use_container_width=True):
st.session_state.current_page = "dashboard"
st.markdown("---")
# Saved Sessions
st.subheader("📝 Saved Sessions")
conversations = load_conversations()
for conv in conversations[:5]: # Show last 5 conversations
with st.expander(f"{conv.scenario} - {conv.created_at.strftime('%m/%d')}"):
st.write(f"**Role:** {conv.role}")
st.write(f"**Points:** {conv.points}")
if st.button(f"Load", key=f"load_{conv.id}"):
st.session_state.selected_scenario = conv.scenario
st.session_state.selected_role = conv.role
st.session_state.selected_situation = conv.situation
st.session_state.current_page = "conversation"
st.rerun()
if st.button("💾 Save Current Session", use_container_width=True):
save_conversation()
if st.button("🆕 New Conversation", use_container_width=True):
st.session_state.messages = []
st.session_state.corrections = []
st.session_state.current_page = "setup"
st.rerun()
# Main content
if st.session_state.current_page == "setup":
st.title("🎓 Practice English with AI")
st.markdown("Choose a scenario, select your role, and start practicing your English conversation skills with an AI tutor!")
# Hero section
st.markdown("""
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 2rem; border-radius: 10px; text-align: center; margin: 2rem 0;">
<h2 style="color: white; margin: 0;">🌟 Welcome to LinguaVerse</h2>
<p style="color: white; margin: 1rem 0;">
Practice conversational English with AI in realistic scenarios.
Get real-time feedback and improve your English skills!
</p>
</div>
""", unsafe_allow_html=True)
# Scenario selection
st.subheader("🎭 Choose a Scenario")
cols = st.columns(4)
for i, (scenario, details) in enumerate(scenarios.items()):
with cols[i]:
if st.button(
f"{details['image']}\n\n**{scenario}**\n\n{details['description']}",
key=f"scenario_{scenario}",
use_container_width=True
):
st.session_state.selected_scenario = scenario
if st.session_state.selected_scenario:
st.success(f"Selected scenario: {st.session_state.selected_scenario}")
# Role and situation selection
col1, col2 = st.columns(2)
with col1:
st.subheader("👤 Select Your Role")
role = st.selectbox(
"Choose your role:",
scenarios[st.session_state.selected_scenario]["roles"],
key="role_select"
)
st.session_state.selected_role = role
with col2:
st.subheader("🎯 Select Situation")
situation = st.selectbox(
"Choose a situation:",
scenarios[st.session_state.selected_scenario]["situations"],
key="situation_select"
)
st.session_state.selected_situation = situation
# Start conversation button
if st.button("🚀 Start Conversation", type="primary", use_container_width=True):
st.session_state.current_page = "conversation"
st.session_state.messages = []
st.session_state.corrections = []
# Add initial AI message
initial_message = f"Hello! I'm your AI English tutor. We're in a {st.session_state.selected_scenario.lower()} scenario. You are a {st.session_state.selected_role.lower()} and we're going to practice '{st.session_state.selected_situation.lower()}'. Let's start!"
st.session_state.messages.append({"role": "assistant", "content": initial_message})
st.rerun()
elif st.session_state.current_page == "conversation":
if not st.session_state.selected_scenario:
st.warning("Please select a scenario first!")
st.session_state.current_page = "setup"
st.rerun()
# Three-column layout
col1, col2, col3 = st.columns([1, 2, 1])
# Left column - Scenario info and gamification
with col1:
st.markdown(f"### {scenarios[st.session_state.selected_scenario]['image']} {st.session_state.selected_scenario}")
st.markdown(f"**Role:** {st.session_state.selected_role}")
st.markdown(f"**Situation:** {st.session_state.selected_situation}")
st.markdown("---")
st.markdown("### 🎮 Gamification")
st.metric("Points", st.session_state.user_points)
st.metric("Level", st.session_state.user_level)
st.metric("Streak", st.session_state.streak)
# Badges
st.markdown("### 🏆 Badges")
if st.session_state.user_points >= 100:
st.markdown("🥉 First Century")
if st.session_state.user_points >= 300:
st.markdown("🥈 Intermediate Master")
if st.session_state.user_points >= 600:
st.markdown("🥇 Advanced Speaker")
# Center column - Chat interface
with col2:
st.markdown("### 💬 Conversation")
# Chat messages
chat_container = st.container()
with chat_container:
for message in st.session_state.messages:
if message["role"] == "user":
st.markdown(f"""
<div style="background-color: #e3f2fd; padding: 1rem; border-radius: 10px; margin: 0.5rem 0; margin-left: 2rem;">
<strong>You:</strong> {message["content"]}
</div>
""", unsafe_allow_html=True)
else:
st.markdown(f"""
<div style="background-color: #f3e5f5; padding: 1rem; border-radius: 10px; margin: 0.5rem 0; margin-right: 2rem;">
<strong>AI Tutor:</strong> {message["content"]}
</div>
""", unsafe_allow_html=True)
# Input area
user_input = st.text_area("Type your message:", height=100, key="user_input")
col_send, col_clear, col_topic = st.columns(3)
with col_send:
if st.button("📤 Send", type="primary", use_container_width=True):
if user_input.strip():
# Add user message
st.session_state.messages.append({"role": "user", "content": user_input})
# Get AI response and corrections
ai_response, corrections = simulate_ai_response(user_input)
st.session_state.messages.append({"role": "assistant", "content": ai_response})
# Add corrections to session state
st.session_state.corrections.extend(corrections)
# Add points
add_points(10)
# Clear input
st.rerun()
with col_clear:
if st.button("🗑️ Clear", use_container_width=True):
st.session_state.messages = []
st.session_state.corrections = []
st.rerun()
with col_topic:
if st.button("🔄 New Topic", use_container_width=True):
st.session_state.current_page = "setup"
st.rerun()
# Right column - Real-time corrections
with col3:
st.markdown("### ✏️ Real-time Feedback")
# Errors (red)
if st.session_state.corrections:
st.markdown("#### 🔴 Corrections")
for correction in st.session_state.corrections[-3:]: # Show last 3
st.markdown(f"""
<div style="background-color: #ffebee; padding: 0.5rem; border-radius: 5px; margin: 0.5rem 0; border-left: 3px solid #f44336;">
<strong>Original:</strong> {correction.get('original', 'Error detected')}<br>
<strong>Correction:</strong> {correction.get('correction', 'See explanation')}<br>
<small>{correction.get('explanation', 'Grammar correction')}</small>
</div>
""", unsafe_allow_html=True)
# Alternatives (blue)
st.markdown("#### 🔵 Alternatives")
alternatives = [
"Instead of 'good', try 'excellent' or 'fantastic'",
"Use 'I would like' instead of 'I want' for politeness",
"Try 'Could you please' instead of 'Can you'"
]
for alt in alternatives[:2]:
st.markdown(f"""
<div style="background-color: #e3f2fd; padding: 0.5rem; border-radius: 5px; margin: 0.5rem 0; border-left: 3px solid #2196f3;">
{alt}
</div>
""", unsafe_allow_html=True)
# Spanish feedback
st.markdown("#### 🇪🇸 Retroalimentación")
st.markdown("""
<div style="background-color: #f3e5f5; padding: 0.5rem; border-radius: 5px; margin: 0.5rem 0;">
<small>Recuerda usar el pasado simple para acciones completadas en el pasado.</small>
</div>
""", unsafe_allow_html=True)
elif st.session_state.current_page == "dashboard":
st.title("📊 Dashboard")
# KPIs
col1, col2, col3, col4 = st.columns(4)
with col1:
st.metric("Conversations", len(load_conversations()))
with col2:
accuracy = 85 + random.randint(-10, 10)
st.metric("Accuracy", f"{accuracy}%")
with col3:
words_learned = st.session_state.user_points // 5
st.metric("Words Learned", words_learned)
with col4:
practice_time = st.session_state.user_points * 2
st.metric("Practice Time", f"{practice_time} min")
# Charts
col1, col2 = st.columns(2)
with col1:
st.subheader("📈 Weekly Progress")
# Generate sample data
dates = [datetime.now() - timedelta(days=i) for i in range(7, 0, -1)]
points = [random.randint(10, 50) for _ in range(7)]
fig = px.line(
x=dates,
y=points,
title="Points Earned Per Day",
labels={"x": "Date", "y": "Points"}
)
st.plotly_chart(fig, use_container_width=True)
with col2:
st.subheader("🎭 Scenarios Practiced")
scenario_data = pd.DataFrame({
'Scenario': list(scenarios.keys()),
'Sessions': [random.randint(1, 10) for _ in scenarios.keys()]
})
fig = px.pie(
scenario_data,
values='Sessions',
names='Scenario',
title="Distribution of Practice Sessions"
)
st.plotly_chart(fig, use_container_width=True)
# Error types
st.subheader("❌ Common Error Types")
error_data = {
'Error Type': ['Grammar', 'Vocabulary', 'Pronunciation', 'Fluency'],
'Count': [15, 8, 12, 5],
'Improvement': ['+2', '-1', '+3', '0']
}
error_df = pd.DataFrame(error_data)
st.dataframe(error_df, use_container_width=True)
# Badge system
st.subheader("🏆 Achievement System")
badges_data = [
{"name": "First Steps", "description": "Complete your first conversation", "earned": True},
{"name": "Chatterbox", "description": "Send 100 messages", "earned": st.session_state.user_points >= 100},
{"name": "Grammar Guru", "description": "Make 10 corrections", "earned": len(st.session_state.corrections) >= 10},
{"name": "Vocabulary Master", "description": "Learn 50 new words", "earned": st.session_state.user_points >= 250},
{"name": "Consistency King", "description": "Practice 7 days in a row", "earned": st.session_state.streak >= 7},
]
cols = st.columns(3)
for i, badge in enumerate(badges_data):
with cols[i % 3]:
if badge["earned"]:
st.success(f"🏆 {badge['name']}")
else:
st.info(f"🔒 {badge['name']}")
st.caption(badge["description"])
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?