Embedding y LLM’s en acción: un laboratorio practico con Java y OpenIA
Este es un MVP de un juego tipo context.me usando Java + Spring Boot y OpenAI Embeddings para calcular la cercanía semántica entre la palabra oculta y los intentos del jugador.
🚀 Endpoints
POST /api/games→ crea una partida nueva.Body opcional:
{ "topic": "animales" }(por ahora solo informativo para elegir palabra de un set básico)Respuesta:
{ id, startedAt, topic }
POST /api/games/{id}/guess→ envía un intento.Body:
{ "word": "gato" }Respuesta:
{ similarity, percentage, hint, solved }
GET /api/games/{id}→ estado de la partida (debug simple, sin revelar la palabra).
Regla de victoria (MVP): se considera acertado con similarity ≥ 0.95 y/o cuando la palabra coincide exactamente (case-insensitive, acentos normalizados).
🧩 Estructura de paquetes
com.example.contextia
├─ ContextIaApplication.java
├─ config
│ ├─ OpenAiProperties.java
│ └─ WebConfig.java
├─ core
│ ├─ EmbeddingClient.java
│ ├─ SimilarityUtil.java
│ └─ TextNormalizer.java
├─ game
│ ├─ Game.java
│ ├─ GameService.java
│ ├─ WordPicker.java
│ └─ dto
│ ├─ CreateGameRequest.java
│ ├─ CreateGameResponse.java
│ ├─ GuessRequest.java
│ └─ GuessResponse.java
└─ web
└─ GameController.java🧱 pom.xml
pom.xml⚙️ application.yml
application.ymlExporta tu API Key como variable de entorno
OPENAI_API_KEY.
🏁 ContextIaApplication.java
ContextIaApplication.java🧰 config/OpenAiProperties.java
config/OpenAiProperties.java🌐 config/WebConfig.java (CORS para tu frontend)
config/WebConfig.java (CORS para tu frontend)🧠 core/EmbeddingClient.java
core/EmbeddingClient.java🔤 core/TextNormalizer.java (acentos, minúsculas)
core/TextNormalizer.java (acentos, minúsculas)📐 core/SimilarityUtil.java
core/SimilarityUtil.java🎲 game/Game.java
game/Game.java🧮 game/WordPicker.java (set mínimo de palabras)
game/WordPicker.java (set mínimo de palabras)🧠 game/GameService.java
game/GameService.java📦 DTOs game/dto/*.java
game/dto/*.javaCreateGameRequest.java
CreateGameResponse.java
GuessRequest.java
GuessResponse.java
🌍 web/GameController.java
web/GameController.java▶️ Cómo ejecutar
Configura tu API Key:
Levanta la app:
Prueba con cURL/Postman:
💡 Notas de diseño
Cache de embeddings en memoria para evitar llamadas repetidas.
Normalización de texto: minúsculas y sin acentos para comparaciones exactas.
Umbral de victoria ajustable (0.93–0.97 suele ir bien con
text-embedding-3-small).Temas/Dominios: amplía
WordPickerleyendo un diccionario desde BD o archivo.Anti-trampas: filtra intentos iguales consecutivos y limita 3–5 rps por usuario.
Internacionalización: usa el mismo modelo; embeddings funcionan bien en español.
🧭 Extensiones siguientes
Ranking global (persistencia con Postgres).
Historial por partida (lista de intentos con puntaje y ordenado por cercanía).
"Pistas inteligentes" usando un LLM (opcional) para generar hints temáticos según proximidad.
Frontend (Angular/React) con barra de progreso y top-10 intentos más cercanos.
¿Quieres que agregue persistencia con JPA (PostgreSQL) y un historial de intentos + leaderboard? También puedo dejarte un Dockerfile y docker-compose para levantar todo con una base en segundos.
Última actualización