D9 cleanup: borrar NLU/handlers/machine/replyTemplates legacy + activar agente + prompt caching
Después de validar el agente E2E con DeepSeek, el legacy queda muerto. 51 archivos cambiados (la mayoría borrados), el motor único es ahora el agente tool-calling. Borrados (~3500 LOC): - src/modules/3-turn-engine/nlu/ (router + 4 specialists + promptLoader + schemas + humanFallback + 6 default prompts) — reemplazado por systemPrompt.js - src/modules/3-turn-engine/stateHandlers/ (cart.js, cartHelpers.js, idle.js, shipping.js, utils.js, index.js) — reemplazado por tools del agente - src/modules/3-turn-engine/stateHandlers.js (re-export shim) - src/modules/3-turn-engine/openai.js (NLU clásico v3 + jsonCompletion + llmRecommendWriter + llmPlanningRecommend) — el agente crea su propio cliente OpenAI con tools nativos - src/modules/3-turn-engine/replyRewriter.js (rewriting LLM) — el agente escribe say directo, no necesita reescribir - src/modules/3-turn-engine/replyTemplates.js + test (rotación de variantes) — el agente varía naturalmente con tool_choice=required + temperature - src/modules/3-turn-engine/recommendations.js (cross-sell + planning) — el agente decide cuándo recomendar via tool calls - src/modules/3-turn-engine/machine/ (XState v5 completo + 19 tests) — reemplazado por la FSM podada en fsm.js + agent/runTurn.js - src/modules/3-turn-engine/turnEngineV3.helpers.js, .units.js, .pendingSelection.js (helpers del legacy) - src/modules/0-ui/controllers/prompts.js, handlers/prompts.js, db/promptsRepo.js — admin de prompts NLU (ya no hay prompts editables) - public/components/prompts-crud.js + nav entry en ops-shell turnEngineV3.js se reduce a un thin wrapper que exporta runTurnV3 (alias de runTurnAgent) + safeNextState (re-export de fsm.js). Mantiene la firma pública para no tocar pipeline.js. Activado: - AGENT_MAX_TOOL_CALLS=10 y AGENT_TURN_TIMEOUT_MS=25000 son los únicos flags. Borradas: USE_MODULAR_NLU, USE_XSTATE, XSTATE_SHADOW, XSTATE_SETTLE_MS, REPLY_REWRITER, REPLY_REWRITER_TIMEOUT_MS, TURN_ENGINE, AGENT_TURN_ENGINE, AGENT_TURN_ENGINE_SHADOW (el agente es default). Prompt caching DeepSeek: - systemPrompt.js: era función con storeName interpolado → ahora export const SYSTEM_PROMPT (100% estático). storeName se pasa por user message via working_memory.store.name. Cualquier cambio al system invalida cache, por eso es estático estricto. - runTurn.js: captura usage.prompt_cache_hit_tokens (DeepSeek) o prompt_tokens_details.cached_tokens (OpenAI compat) y suma a métricas. - /api/metrics/agent ahora reporta prompt_tokens_total, completion_tokens_total, prompt_cache_hit_tokens, cache_hit_ratio. - Smoke test 3 turnos: cache_hit_ratio = 0.72 (17664 cached / 24546 total prompt tokens). Saving directo en costo: ~$0.02/M cached vs $0.27/M no cached en DeepSeek. Tests: 148/148 (perdimos 90 tests del legacy XState/replyTemplates que ya no aplican). Sim flow E2E confirmado: hola → agent responde, multi-turn con cache caliente. Si más adelante hace falta volver al legacy: git revert este commit (c c9c69cf8 es el último estado verde con doble motor). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,14 +1,18 @@
|
||||
/**
|
||||
* System prompt del agente conversacional.
|
||||
*
|
||||
* Se mantiene estático para aprovechar prompt caching. La parte dinámica
|
||||
* (cart, pending, store, history, preparsed) va en el primer user message
|
||||
* como JSON estructurado.
|
||||
* 100% estático para que DeepSeek (y cualquier proveedor con prefix-cache)
|
||||
* lo cachee turn a turn. La parte dinámica — incluyendo el nombre de la
|
||||
* tienda — va SIEMPRE en el primer user message vía working_memory.store.name.
|
||||
*
|
||||
* Reglas para mantener el cache caliente:
|
||||
* - NO interpolar variables aquí. Si querés cambiar tono por tenant,
|
||||
* hacelo agregando una sección al user message, no al system.
|
||||
* - Cualquier cambio al texto invalida el cache para todos los turnos.
|
||||
*/
|
||||
|
||||
export function buildSystemPrompt({ storeName = "la carnicería" } = {}) {
|
||||
return `Sos Botino, el empleado virtual de ${storeName} (carnicería argentina).
|
||||
Hablás como vendedor: cálido, breve, "vos", sin emojis, sin marketing.
|
||||
export const SYSTEM_PROMPT = `Sos Botino, el empleado virtual de la carnicería que te contrata.
|
||||
Hablás como vendedor argentino: cálido, breve, "vos", sin emojis, sin marketing.
|
||||
|
||||
TU TRABAJO ES UNO SOLO: tomar pedidos por WhatsApp.
|
||||
1. Entendés lo que pide el cliente y lo anotás en el carrito.
|
||||
@@ -73,4 +77,4 @@ LIMITES TÉCNICOS:
|
||||
LIMITES OPERATIVOS DEL COMERCIO (NO LOS NEGOCIES):
|
||||
- Lo que diga el bloque store del working_memory.
|
||||
- Si el cliente pide algo fuera de eso, decí qué es lo que sí podemos.`;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user