| Agente | Estrategia | p50 | p99 | Mejora p50 | Tests | Commits | Estado |
|---|---|---|---|---|---|---|---|
| agent-1 | Redis cache capa servicio | 680ms | 1.10s | −62% | 226/226 | 3 | DONE |
| agent-2 | JOIN masivo + índice BD | 730ms | 1.30s | −59% | 226/226 | 5 | DONE |
| agent-3 ⭐ | Async concurrente asyncio.gather | 412ms | 780ms | −77% | 226/226 | 7 | MERGED ✓ |
| agent-4 | Batch scoring ML joblib | 590ms | 1.80s | −67% | 226/226 | 4 | DESCARTADO |
worktree-agent-1..4recommendation.py — convierte llamadas secuenciales a asyncio.gather()# ANTES (agent-3 worktree): ejecución secuencial → ~1800ms # async def _generate(req): # profile = await db.get_nutrition_profile(req.user_id) # 420ms # history = await db.get_meal_history(req.user_id, n=30) # 310ms # llm_resp = await llm.complete(build_prompt(profile, history)) # 950ms # return parse_recommendation(llm_resp) # DESPUÉS (fusionado en main): asyncio.gather → ~412ms import asyncio from services.llm_client import llm from db.queries import db async def _generate(req: RecommendationRequest) -> RecommendationResponse: """Genera recomendación nutricional con llamadas paralelas.""" # Lanzar BD y warm-up LLM en paralelo profile_task = asyncio.create_task(db.get_nutrition_profile(req.user_id)) history_task = asyncio.create_task(db.get_meal_history(req.user_id, n=30)) # Esperar ambas queries concurrentemente (~420ms, no 730ms) profile, history = await asyncio.gather(profile_task, history_task) # LLM call con contexto completo (no se puede paralelizar, pero ya tenemos contexto) llm_resp = await llm.complete( prompt=build_prompt(profile, history), model="gpt-4o-mini", # agent-3 también bajó de gpt-4o → gpt-4o-mini sin pérdida medible max_tokens=512, temperature=0.3 ) return parse_recommendation(llm_resp) # Resultado: p50 1800ms → 412ms (−77%) · p99 2100ms → 780ms (−63%)