robotEmbedding 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


⚙️ application.yml

Exporta tu API Key como variable de entorno OPENAI_API_KEY.


🏁 ContextIaApplication.java


🧰 config/OpenAiProperties.java


🌐 config/WebConfig.java (CORS para tu frontend)


🧠 core/EmbeddingClient.java


🔤 core/TextNormalizer.java (acentos, minúsculas)


📐 core/SimilarityUtil.java


🎲 game/Game.java


🧮 game/WordPicker.java (set mínimo de palabras)


🧠 game/GameService.java


📦 DTOs game/dto/*.java

CreateGameRequest.java

CreateGameResponse.java

GuessRequest.java

GuessResponse.java


🌍 web/GameController.java


▶️ Cómo ejecutar

  1. Configura tu API Key:

  2. Levanta la app:

  3. 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 WordPicker leyendo 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