Tier 1: chat quality — fuzzy aliases, reply templates, dedup, rewriter
Foco: matar repetición y adaptar respuestas. Los handlers tenían ~30 strings hardcodeadas (3-7 lugares cada una). Aliases hacían substring exacto. - pg_trgm + GIN indexes en product_aliases / alias_product_mappings. Captura plurales, diminutivos, typos sin reglas. catalogRetrieval re-busca el snapshot con normalized_alias cuando el query original no rinde (vasio→vacio→Vacío). - reply_templates table + replyTemplates.js. 20 keys, 2-3 variantes c/u con DEFAULTS hardcodeados como fallback. pickVariant excluye las usadas en context.recent_replies (FIFO cap 8). Wired en idle/cart/cartHelpers/ shipping/payment/waiting. - failed_searches counter en context. count>=3 escala via humanFallback. Reset en cada add_to_cart exitoso. - storeContext.js: vars derivadas de getStoreConfig (delivery_zones, hours, zonas) listas para inyectar en templates cuando los datos se carguen. - replyRewriter.js: LLM call opcional (REPLY_REWRITER=1) que adapta el template al hilo conversacional. 1.5s timeout, fallback al template puro. Sólo activo en 8 slots semánticamente importantes. - 12 unit tests para replyTemplates (rotation, recency, FIFO, vars). 208 tests totales pasando. Plan completo: ~/.claude/plans/ok-creo-que-tiene-humming-sutton.md Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
|
||||
import { ConversationState } from "../fsm.js";
|
||||
import { createEmptyOrder, formatCartForDisplay } from "../orderModel.js";
|
||||
import { renderReply } from "../replyTemplates.js";
|
||||
|
||||
/**
|
||||
* Detecta si el usuario pregunta por horarios/días de entrega
|
||||
@@ -41,7 +42,7 @@ function isPickupInfoQuestion(text) {
|
||||
/**
|
||||
* Maneja el estado WAITING_WEBHOOKS (esperando confirmación de pago)
|
||||
*/
|
||||
export async function handleWaitingState({ tenantId, text, nlu, order, audit, storeConfig = {} }) {
|
||||
export async function handleWaitingState({ tenantId, text, nlu, order, audit, storeConfig = {}, recentReplies }) {
|
||||
const intent = nlu?.intent || "other";
|
||||
const currentOrder = order || createEmptyOrder();
|
||||
|
||||
@@ -118,18 +119,15 @@ export async function handleWaitingState({ tenantId, text, nlu, order, audit, st
|
||||
}
|
||||
|
||||
// Default
|
||||
const reply = currentOrder.payment_type === "link"
|
||||
? "Tu pedido está en proceso. Avisame si necesitás algo más o esperá la confirmación de pago."
|
||||
: "Tu pedido está listo. Avisame si necesitás algo más.";
|
||||
|
||||
const r = await renderReply({ tenantId, templateKey: "waiting.in_progress", recentReplies });
|
||||
return {
|
||||
plan: {
|
||||
reply,
|
||||
reply: r.reply,
|
||||
next_state: ConversationState.WAITING_WEBHOOKS,
|
||||
intent: "other",
|
||||
missing_fields: [],
|
||||
order_action: "none",
|
||||
},
|
||||
decision: { actions: [], order: currentOrder, audit },
|
||||
decision: { actions: [], order: currentOrder, audit, template_ids_used: [r.template_id] },
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user