Chatbot v2.10 presentado: Elevando la experiencia del usuario con velocidad, escalabilidad y simplicidad mejoradas
Reconstruí mi chatbot con FastAPI y procesamiento asíncrono, reduciendo los tiempos de respuesta mientras simplificaba la interfaz — así es como las optimizaciones específicas transformaron la experiencia del usuario.
Actualización (2026): ¡Este chatbot evolucionó hasta convertirse en Sydney! Después de muchas iteraciones — de Flask a FastAPI, de FAISS a Weaviate a Supabase pgvector — Sydney ahora vive en /ask/ y usa Claude con respuestas en streaming. Los patrones de FastAPI que se describen a continuación fueron un paso intermedio hacia donde estamos ahora.
La publicación original de febrero de 2024 se conserva a continuación para contexto.
Hace dos semanas, compartí la noticia sobre mi chatbot v2, aprovechando el framework LangChain, con FAISS como vector store. Fue una historia cruda sobre cómo salí de las arenas movedizas del código después de meses de trabajo iterativo.
Si bien la versión 2 fue una mejora significativa respecto a la versión 1, todavía tenía muchos problemas con los que no estaba satisfecho. El mayor es probablemente el rendimiento; más concretamente, es demasiado lento :P Además, la interfaz de frontend era demasiado complicada con demasiadas frases de introducción, de modo que el cuadro de chat quedaba muy abajo en la pantalla.
Esta publicación destacará cómo la 2.10 aplica optimizaciones de rendimiento específicas y mejoras de UX para desbloquear una experiencia conversacional más fluida, rápida y capaz.
Transición a FastAPI: Un salto en rendimiento
La columna vertebral del rendimiento mejorado de la v2.10 radica en nuestro cambio a FastAPI. Este moderno framework web no solo acelera los tiempos de respuesta, sino que también introduce una arquitectura más robusta y escalable.
Framework Flask de v2
# Initialize Flask app and Langchain agent
app = Flask(__name__)
CORS(app, resources=\{r"/query_blog": {"origins": "https://www.chandlernguyen.com"\}})
app.debug = False
limiter = Limiter(app=app, key_func=get_remote_address)
Flask nos sirvió bien, proporcionando simplicidad y flexibilidad. Sin embargo, a medida que nuestra base de usuarios creció, la necesidad de una solución con mejor rendimiento se hizo evidente.
Framework FastAPI de v2.1
# FastAPI with advanced CORS and async support
# Initialize FastAPI app
app = FastAPI()
# Configure CORS for production, allowing only your frontend domain
origins = ["https://www.chandlernguyen.com"]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
# allow_origins=["*"],
allow_credentials=True,
allow_methods=["POST"],
allow_headers=["Content-Type"],
)
FastAPI mejora el rendimiento a través del soporte asíncrono.
Procesamiento Asíncrono: Conversaciones más fluidas
Aprovechando las características asíncronas de FastAPI, la v2 introduce el manejo de solicitudes sin bloqueo, lo que permite interacciones de usuario más fluidas y dinámicas. A continuación hay un ejemplo.
# Function to check content with OpenAI Moderation API (sensitive keys are loaded from environment variables)
async def is_flagged_by_moderation(content: str) -> bool:
openai_api_key = os.getenv('OPENAI_API_KEY')
if not openai_api_key:
logging.error("OPENAI_API_KEY not set in environment variables")
raise HTTPException(status_code=500, detail="Server configuration error")
headers = \{"Authorization": f"Bearer {openai_api_key\}"}
data = \{"input": content\}
async with httpx.AsyncClient() as client:
response = await client.post("https://api.openai.com/v1/moderations", json=data, headers=headers)
if response.status_code == 200:
response_json = response.json()
return any(result.get("flagged", False) for result in response_json.get("results", []))
else:
logging.error(f"Moderation API error: {response.status_code} - {response.text}")
return False
Mejoras en la Interfaz de Usuario
El frontend de la v2.10 ha sido rediseñado para mejorar el atractivo visual y la participación del usuario. Con un enfoque en la accesibilidad y la experiencia del usuario, el nuevo diseño es más simple e intuitivo.
Reducción del contenido introductorio excesivo
Este bloque de texto ya no existe.
<div class="container mt-5">
<h2 style="color: #454545; text-align: center;">Welcome to My Expat Life in America Chatbot!</h2>
<h3 style="margin-top: 15px; text-align: center;">
Get Answers to Your Questions on Living, Working, and Thriving in the US
</h3>
<h4 style="margin-top: 10px; text-align: center;">Ask about:</h4>
<ul style="list-style: none; text-align: center; color: #333;">
<li>Adapting to American Culture & Lifestyle</li>
<li>Navigating US Personal Finance & Banking</li>
<li>Tips for Relocation and Settling In</li>
<li>Understanding Healthcare and Insurance</li>
<li>Getting Around - Driving and Transportation</li>
<li>Education Opportunities and Resources</li>
<li>Professional Development and Networking</li>
</ul>
<h5 style="margin-top: 10px; color: grey; text-align: center;">
I'm here to provide helpful info and insights on the expat experience. What would you like to know?
</h5>
<h6 style="margin-top: 5px; color: grey; text-align: center;">
Go ahead, ask me anything! I'll do my best to give a thoughtful response <span style="font-weight: bold; color: #007bff;">in a few seconds.</span>
</h6>
Este es el reemplazo
<h2 style="color: #454545; text-align: center;">Welcome to Chandler's Expat Life Chatbot!</h2>
<p style="text-align: center; margin-bottom: 20px;">Ask me anything about expat life in the US, from culture to finance.</p>
Visualmente, así es como se ve el cambio
Estilos adicionales para reducir el espacio en blanco y mejorar el diseño
<style>
/* Additional styles to reduce white space and improve layout */
body, html \{
height: 100%;
margin: 0;
display: flex;
flex-direction: column;
\}
.container \{
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: center; /* Center vertically in the available space */
\}
#conversation \{
height: 300px; /* Adjust based on your preference */
overflow-y: auto;
border: 1px solid #ccc; /* Add border to conversation box */
padding: 10px;
border-radius: 5px; /* Optional: round corners */
\}
</style>
El estilo del cuadro #conversation con una altura especificada y control de desbordamiento es particularmente efectivo para mantener una interfaz de chat limpia y fácil de usar.
<!-- Area to display the conversation -->
<div id="conversation" aria-live="polite" class="mb-5" style="height: 300px; overflow-y: auto;"></div>
Agregar aria-live="polite" al div de conversación es una adición reflexiva para los usuarios de lectores de pantalla, que les permite ser informados de los cambios de contenido dinámico.
Auto-focus en el campo de entrada
La adición de $('#user-query').focus(); al final de los callbacks de éxito y error de AJAX es una característica fácil de usar, lo que garantiza que el campo de entrada se enfoque automáticamente después de cada envío de mensaje, permitiendo una experiencia de chat más fluida.
Aprovechando Langsmith para monitoreo de rendimiento y observabilidad
Con esta versión 2.10, estoy aprovechando Langsmith. La configuración es bastante fácil y la interfaz del panel es suficientemente intuitiva.
Y cuando noto que una determinada consulta está tardando demasiado, puedo "hacer clic" en ella y entender más exactamente qué parte del recorrido es el problema.
El código de backend completo para la versión 2.1
Como de costumbre, compartí el código de backend completo en GitHub aquí. Está en el mismo repositorio que la versión anterior del chatbot 2.0.
Te invito a que pruebes el chatbot :D Pregúntale cualquier cosa sobre lo que escribí durante los últimos 16 años.
¿Has intentado alguna vez construir un chatbot o migrar entre frameworks? Me encantaría escuchar qué trucos de rendimiento te funcionaron.
Un abrazo,
Chandler








