Programación Orientada a Objetos · ELO-329

ELOBOT

Asistente Académico Universitario basado en RAG

Arquitectura desacoplada Frontend Java (Swing)  ⇄  Backend Python (FastAPI + MongoDB + Gemini)

Institución: Universidad Técnica Federico Santa María  ·  Asignatura: ELO-329 — Diseño y Programación Orientados a Objetos
Profesor: Agustín González
Equipo: Carlos Ramírez  ·  Nicolás King  ·  Yasin Morales  ·  Martín Pérez
Fecha: Primer Semestre 2026

1. Descripción del Problema

Los estudiantes de la UTFSM deben consultar información dispersa en los programas oficiales de asignatura (requisitos, contenidos, evaluaciones y bibliografía), un proceso manual, lento y propenso a error. ELOBOT resuelve esta necesidad como un asistente conversacional que responde en lenguaje natural sobre 84 asignaturas, apoyándose en la técnica RAG (Retrieval-Augmented Generation) para fundamentar cada respuesta en fuentes reales. El sistema desacopla una interfaz gráfica en Java (Swing) de un motor de recuperación semántica en Python que combina filtrado por metadatos en MongoDB con similitud del coseno sobre vectores de embeddings. El contexto recuperado se entrega a un modelo de lenguaje (Google Gemini 2.5 Flash), instruido para responder únicamente con la información provista y así evitar alucinaciones. La necesidad técnica de ingeniería es construir un producto mantenible, multi-lenguaje e integrable que transforme documentos académicos en conocimiento consultable de forma confiable.

Nota: el prefijo «ELO» del nombre alude al código de asignaturas de Electrónica (p. ej. ELO-329), dominio sobre el que opera el asistente; no corresponde a un sistema de ranking ELO.

2. Análisis del Problema

Definición del Sistema

El sistema ELOBOT es una aplicación cliente–servidor con dos límites bien definidos que se comunican exclusivamente por HTTP:

  • Núcleo Frontend (Java / Swing): aplicación de escritorio de 8 clases (ElobotChat, ElobotApiClient, ChatMessage, Conversation, Theme, RamoCodeNormalizer, AnimatedAvatar, VectorIcon). Es responsable de la interfaz, el modelo de datos en memoria del chat y la orquestación de la interacción con el usuario.
  • Núcleo Backend (Python): tres módulos (api.py, respuestas_bro.py, queries.py) que exponen la API REST, ejecutan la canalización RAG (embeddings + búsqueda vectorial) y orquestan la llamada al LLM.
  • Fuera del límite del sistema: el motor de base de datos MongoDB y el servicio externo de LLM (Google Gemini), consumidos como dependencias de infraestructura.

Entidades y Componentes Participantes

ComponenteTecnologíaResponsabilidad detectada en el código
FrontendJava 17 · SwingVistas, captura de eventos, historial de conversaciones, temas claro/oscuro, normalización del código de ramo.
Backend / APIFastAPI + UvicornEndpoint POST /consultar; valida el cuerpo con Pydantic (Consulta) y delega en la lógica de negocio.
Motor RAGsentence-transformers · NumPyGenera embeddings de la pregunta y calcula similitud del coseno contra los chunks almacenados.
Motor de generaciónGoogle Gemini 2.5 FlashProduce la respuesta final restringida al contexto recuperado.
Actores / UsuariosEl Estudiante (único actor humano) formula preguntas; los servicios MongoDB y Gemini actúan como actores/sistemas externos.
PersistenciaMongoDB (Docker)Colección programas_asignaturas: 840 chunks de 84 asignaturas con su vector de embedding. El estado del chat es volátil (en memoria del Frontend).

Interacciones con el Medio Externo

  • Java → Python (HTTP/REST): ElobotApiClient arma un JSON {"pregunta","codigo_ramo"} y lo envía por HttpClient (HTTP/1.1) al endpoint http://localhost:8001/consultar. La respuesta JSON se parsea manualmente para extraer el campo respuesta.
  • Python → MongoDB (driver PyMongo): conexión autenticada vía MONGO_URI; pre-filtrado por codigo_asignatura antes del cálculo vectorial.
  • Python → Gemini (SDK google-genai): llamada a generate_content con rotación de hasta 4 API keys (fallback ante cuota agotada), configuradas en variables de entorno vía python-dotenv.
  • CORS: el backend habilita CORSMiddleware con orígenes abiertos, permitiendo el consumo desde clientes heterogéneos.
  • Sistema de archivos (Frontend): importación (.txt) como entrada y exportación de transcripciones de la conversación.

3. Definición de Requerimientos y Casos de Uso

Los casos de uso se documentan siguiendo la plantilla revisada en clases, considerando nombre, propósito, actores, precondiciones, evento gatillante, curso normal de eventos, curso alternativo, requerimientos no funcionales y autor. El foco está en describir funcionalidades visibles para el actor principal, evitando detalles internos de implementación.

En este proyecto, el sistema considerado es ELOBOT, un asistente académico universitario para consultar información de asignaturas. El actor principal es el Estudiante, quien interactúa con el sistema mediante una interfaz conversacional.

Diagrama de Casos de Uso del Sistema

Diagrama de casos de uso del sistema ELOBOT
Figura 1. Diagrama de casos de uso del sistema ELOBOT — funcionalidades visibles para el estudiante.
CU-01 · Consultar información de una asignatura
Elemento Descripción
1. Nombre Consultar información de una asignatura.
2. Propósito Permitir que el estudiante obtenga información académica de una asignatura específica, como requisitos, contenidos, evaluaciones o bibliografía.
3. Actores Estudiante.
4. Precondiciones El sistema ELOBOT se encuentra disponible y posee información académica cargada para consulta.
5. Evento El estudiante ingresa un código de asignatura y formula una pregunta sobre ella.
6. Curso normal de eventos Se detalla en la tabla Actor/Sistema presentada a continuación.
7. Curso alternativo de eventos Si el código tiene un formato no estándar, el sistema intenta normalizarlo. Si no existe información suficiente, el sistema informa que no puede responder con los datos disponibles. Si ocurre un error de conexión, el sistema muestra un mensaje de error controlado.
8. Requerimientos no funcionales La respuesta debe ser clara, legible y entregarse en un tiempo razonable para mantener una interacción fluida.
9. Autor Equipo ELOBOT.

Curso normal de eventos

Actor Sistema
1. El estudiante ingresa el código de la asignatura.
2. El estudiante escribe una pregunta sobre la asignatura.
3. El sistema valida y normaliza el código ingresado.
4. El sistema busca información académica relacionada con la consulta.
5. El sistema genera una respuesta basada en la información disponible.
6. El estudiante revisa la respuesta entregada.
CU-02 · Realizar búsqueda temática
Elemento Descripción
1. Nombre Realizar búsqueda temática.
2. Propósito Permitir que el estudiante consulte información académica aunque no conozca el código exacto de una asignatura.
3. Actores Estudiante.
4. Precondiciones El sistema ELOBOT se encuentra disponible y posee información académica cargada.
5. Evento El estudiante realiza una pregunta general sin ingresar un código de asignatura.
6. Curso normal de eventos Se detalla en la tabla Actor/Sistema presentada a continuación.
7. Curso alternativo de eventos Si la consulta es demasiado ambigua, el sistema puede entregar una respuesta general o solicitar mayor precisión. Si no se encuentra información relacionada, el sistema informa que no posee antecedentes suficientes.
8. Requerimientos no funcionales La respuesta debe ser comprensible para el estudiante y consistente con la información académica disponible.
9. Autor Equipo ELOBOT.

Curso normal de eventos

Actor Sistema
1. El estudiante escribe una consulta general sobre un tema académico.
2. El sistema interpreta la consulta sin restringirla a una asignatura específica.
3. El sistema busca información académica relacionada con la pregunta.
4. El sistema entrega una respuesta con la información más relevante encontrada.
5. El estudiante revisa la respuesta y puede realizar una nueva consulta.
CU-03 · Revisar historial de conversaciones
Elemento Descripción
1. Nombre Revisar historial de conversaciones.
2. Propósito Permitir que el estudiante retome consultas realizadas durante la sesión de uso.
3. Actores Estudiante.
4. Precondiciones El estudiante ha realizado al menos una consulta durante la sesión actual.
5. Evento El estudiante selecciona una conversación desde el historial o inicia una nueva conversación.
6. Curso normal de eventos Se detalla en la tabla Actor/Sistema presentada a continuación.
7. Curso alternativo de eventos Si no existen conversaciones previas, el sistema muestra el historial vacío. Si el estudiante inicia una nueva conversación, el sistema limpia el área actual y conserva la conversación anterior durante la sesión.
8. Requerimientos no funcionales El historial debe ser simple de usar y no debe interferir con la consulta principal del estudiante.
9. Autor Equipo ELOBOT.

Curso normal de eventos

Actor Sistema
1. El estudiante realiza una consulta en el chat.
2. El sistema registra la conversación activa durante la sesión.
3. El estudiante selecciona una conversación previa desde el historial.
4. El sistema carga los mensajes asociados a esa conversación.
5. El estudiante revisa la conversación o continúa realizando nuevas consultas.

4. Diseño de Alto Nivel (Arquitectura UML)

Arquitectura de la Solución (Multi-lenguaje)

ELOBOT adopta una arquitectura desacoplada cliente–servidor. El Frontend Java desconoce por completo la lógica RAG: solo invoca callApi(pregunta, codigo) y recibe texto. El contrato de integración es un único endpoint REST con carga JSON, lo que permite evolucionar cada capa de forma independiente (alta adaptabilidad y portabilidad).

Diagrama de arquitectura de ELOBOT
Figura 2. Diagrama de arquitectura general de ELOBOT — comunicación entre Frontend Java, Backend Python, MongoDB y Gemini.
Frontend Java Backend Python Persistencia (MongoDB) Servicio externo (Gemini)

Diagrama de Clases

El Frontend aplica composición (la ventana «tiene un» cliente HTTP), agregación (la ventana «tiene muchas» conversaciones y mensajes), el patrón Singleton (Theme) y una clase de utilidad sin estado (RamoCodeNormalizer). El Backend se organiza como módulos funcionales con dependencias unidireccionales.

Diagrama de clases UML del sistema ELOBOT
Figura 3. Diagrama de clases UML — Frontend Java (Swing) y módulos del Backend Python, con sus relaciones de composición, agregación, dependencia y herencia.
▾ Complemento textual: diccionario de clases y tabla de relaciones (respaldo legible de la Figura 1)

Frontend (Java · Swing) Estructura orientada a objetos

ElobotChat
«JFrame · Vista principal»
- apiClient : ElobotApiClient
- currentMessages : List<ChatMessage>
- conversationHistory : List<Conversation>
- activeConversation : Conversation
+ sendMessage()
- addBotMessage() / addUserMessage()
- archiveCurrentIfNeeded()
- toggleTheme() / rebuildContent()
ElobotApiClient
«Cliente HTTP»
- ENDPOINT : String
+ callApi(pregunta, codigoRamo) : String
- parseRespuesta(json) : String
- esc(s) : String
ChatMessage
«Modelo de dominio»
- text : String
- user : boolean
- time : String
+ getText() / isUser() / getTime()
Conversation
«Modelo de dominio»
- title : String
- codigo : String
- messages : List<ChatMessage>
+ getTitle() / getCodigo() / getMessages()
Theme
«Singleton»
- INSTANCE : Theme {static}
- dark : boolean
- bg, fg, accent... : Color
+ getInstance() : Theme {static}
+ toggle() / isDark()
RamoCodeNormalizer
«Utilidad · final»
- PATTERN : Pattern {static}
+ normalize(input) : String {static}
+ normalizeOrEmpty(raw,ph) : String {static}
AnimatedAvatar
«JLabel · Componente visual»
- pulsing : boolean
- timers : Timer[]
+ setPulsing(p)
# paintComponent(g)
VectorIcon
«implements Icon»
- type : String
- size : int
+ paintIcon(c,g,x,y)
+ getIconWidth() / getIconHeight()

Relaciones UML del Frontend

RelaciónOrigen → DestinoTipo y multiplicidad
◆──ElobotChat → ElobotApiClientComposición (1 → 1): colaborador final creado por la ventana.
◇──ElobotChat → ConversationAgregación (1 → 0..*): historial de conversaciones.
◇──ElobotChat / Conversation → ChatMessageAgregación (1 → 0..*): lista de mensajes.
 - ->ElobotChat → RamoCodeNormalizerDependencia: uso de métodos estáticos.
 - ->Todos → ThemeDependencia: acceso global vía Theme.getInstance().
──▷VectorIcon ⊳ IconRealización de interfaz; AnimatedAvatar ⊳ JLabel y ElobotChat ⊳ JFrame: herencia.

Backend (Python) Módulos y dependencias

Diagrama de módulos y dependencias del backend Python
Figura 4. Diagrama de módulos del backend Python — relación entre api.py, respuestas_bro.py y queries.py, junto con sus dependencias principales.

Diagrama de Secuencia — CU-01 (interacción Java ⇄ Python)

Escenario representativo del caso de uso CU-01: el estudiante consulta información de una asignatura. El diagrama muestra la interacción temporal entre el actor, la interfaz del sistema y los componentes responsables de obtener y presentar la respuesta. Se omiten detalles internos de implementación para mantener el foco en la dinámica funcional del sistema.

Diagrama de secuencia UML del caso de uso CU-01 de ELOBOT Figura 5. Diagrama de secuencia UML del CU-01 — consulta de información académica de una asignatura.

5. Documentación de la Implementación

Estándar de documentación: el código fuente está auto-documentado en los archivos originales.

  • Java: comentarios estructurados tipo Javadoc a nivel de clase y de método (véanse ElobotApiClient, ChatMessage, Conversation, Theme, RamoCodeNormalizer), documentando responsabilidades, patrones aplicados y relaciones de composición/agregación.
  • Python: docstrings (PEP 257) en los módulos y funciones clave (recuperar_contexto_rag, armar_prompt_llm, consultar_asistente_universitario), describiendo los pasos del pipeline RAG y la estrategia de fallback de claves.

Nota de entrega: siguiendo las instrucciones de la cátedra, se omiten los archivos HTML redundantes generados automáticamente por herramientas de Javadoc; el entregable se mantiene limpio y contiene solo el código fuente y esta documentación.

6. Pruebas, Dificultades y Control de Errores

Resultados de Pruebas

Despliegue de la interfaz ELOBOT
Prueba 01 — Despliegue del Frontend.

Prueba 01 — Despliegue del Frontend. Verifica que ElobotChat.main inicializa la ventana Swing sin decoración, aplica el look-and-feel del sistema y renderiza el saludo (GREETING) junto al avatar animado, el sidebar de historial y las preguntas rápidas. Valida la construcción correcta de la vista (CU-03) antes de cualquier interacción de red.

Pregunta con código de asignatura ELO-329
Prueba 02 — Consulta con código de asignatura específico.

Prueba 02 — Procesamiento en el Backend. Se ingresa el código ELO-329 junto a la pregunta. El backend filtra los chunks en MongoDB por codigo_asignatura, calcula similitud coseno y envía el prompt a Gemini con rotación de claves. Valida el flujo RAG completo de CU-01.

Respuesta del sistema para ELO-329
Prueba 03 — Validación extremo a extremo con código específico.

Prueba 03 — Validación extremo a extremo. Con el backend activo, se envía una pregunta desde la interfaz Java y se verifica que la respuesta fundamentada aparece en pantalla, que el código se normalizó a ELO-329 y que la conversación queda disponible en el historial. Confirma la integración Java ⇄ Python y los criterios de aceptación de CU-01 y CU-02.

Búsqueda global sin código de ramo
Prueba 04 — Búsqueda global en todos los programas.

Prueba 04 — Búsqueda global. Con el campo de código vacío, el sistema busca en los 840 chunks sin filtro, aplica deduplicación por asignatura y retorna los ramos más relevantes al tema consultado. Valida el modo de búsqueda global descrito en CU-02.

Dificultades Superadas

Desafío multi-lenguajeSolución adoptada en el código
Integración Java ↔ Python sin acoplamientoFrontera REST/JSON única (POST /consultar); ElobotApiClient es la única clase que conoce el endpoint.
Serialización de datos entre entornosEscape manual de JSON (esc) al enviar y parser específico (parseRespuesta) que interpreta \n, \t y comillas al recibir.
Bloqueo de la interfaz durante la espera de redLa llamada se ejecuta en un Thread aparte y la UI se actualiza con SwingUtilities.invokeLater.
Cuotas agotadas del LLMRotación secuencial de hasta 4 API keys con fallback y mensaje de error controlado.
Alucinaciones del modeloPrompt restrictivo que obliga a responder solo con el contexto recuperado.
Inconsistencia en el código del ramoRamoCodeNormalizer unifica variantes (elo329, ELO329…) al formato ELO-329 mediante expresión regular.

Listado de Bugs Presentes

No se registran bugs críticos en la versión actual de evaluación. Se documentan, por transparencia de ingeniería, las siguientes condiciones de borde menores:

  • El parsing de JSON en ElobotApiClient es manual y por posición; asume un único campo respuesta bien formado. Un cambio en el esquema del backend requeriría ajustarlo.
  • El historial de conversaciones es volátil (solo en memoria): no se persiste al cerrar la aplicación.
  • La configuración de conexión a MongoDB y el host del endpoint están fijados en el código (localhost), lo que limita el despliegue en otros entornos sin recompilar.

7. Acceso al Código Fuente y Estructura del Entregable

Código fuente completo del proyecto, comprimido para navegación portable:

⬇ Descargar ELO-BOT.zip ⎇ Ver en GitHub

Contenido del Paquete

ElementoDescripción
frontend/Código fuente Java (8 clases Swing) desarrollado por el equipo.
api.py · queries.py · respuestas_bro.pyBackend Python: API REST y motor RAG.
docker-compose.ymlAutomatización del despliegue de MongoDB.
requirements.txtDependencias Python declaradas formalmente.
README.mdInstrucciones de instalación, despliegue y ejecución.
.env.examplePlantilla de variables de entorno (claves de Gemini).
RAMOS_Y_PREGUNTAS.mdCatálogo de las 84 asignaturas y preguntas de prueba.

Dependencias Externas

Declaradas formalmente en README.md y requirements.txt con sus guías de obtención:

DependenciaRolConsideración de licencia (según cátedra)
FastAPI · Uvicorn · PydanticAPI REST del backendMIT/BSD — permisiva (usar con aviso de copyright).
PyMongo · MongoDBPersistencia vectorialApache 2.0 (driver) — permisiva.
sentence-transformers · NumPyEmbeddings y álgebraApache 2.0 / BSD — permisivas.
google-genai (Gemini)Generación de respuestasSDK Apache 2.0; el servicio requiere API key y términos de uso propios.
Java SE / Swing (JDK 17)Interfaz gráficaGPL con Classpath Exception (OpenJDK) — apta para el uso académico.

Herramientas de instalación referenciadas en el README.md: Docker Desktop, Python 3.10+ y JDK 17 (winget install Microsoft.OpenJDK.17).

Exclusiones del Entregable

  • Se garantiza la ausencia de código compilado: archivos .class, .o o binarios intermedios (excluidos vía .gitignore).
  • No se incluyen archivos temporales del IDE ni documentación HTML redundante generada por Javadoc.
  • El archivo .env con claves reales se excluye; solo se entrega la plantilla .env.example.