feat: auto-selección en dynamic_list cuando NLU extrae el grupo/filtro

- handleDynamicList: si __nlu_entities contiene un valor que coincide
  con el label de un ítem, lo auto-selecciona y navega al next_node
  sin mostrar la lista interactiva
- AiBot: NLU prompt ahora pide explícitamente grupos y filtros en entities

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-07-05 21:57:22 -05:00
co-authored by Claude Sonnet 4.6
parent 54a93adea9
commit 3d04be14bc
2 changed files with 44 additions and 4 deletions
+1 -1
View File
@@ -446,7 +446,7 @@ PROMPT;
. "Analiza el mensaje y determina si se refiere claramente a una opción.\n\n"
. "Si sí → responde SOLO este JSON (sin markdown):\n"
. "{\"action\":\"route\",\"key\":\"<key_exacto>\",\"entities\":{\"campo\":\"valor\",...}}\n\n"
. "En 'entities' incluye los datos que el usuario ya mencionó (nombre de finca, fecha, valor numérico, etc.).\n"
. "En 'entities' incluye los datos que el usuario ya mencionó: nombre de finca, grupo, filtro, fecha, valor numérico, etc. Usa el nombre tal como lo dijo el usuario.\n"
. "Si no mencionó datos extra, omite entities o usa {}.\n\n"
. "Si no está claro o no hay opción correspondiente → responde SOLO:\n"
. "{\"action\":\"chat\",\"text\":\"<respuesta corta en español, máx 2 oraciones>\"}\n\n"
+43 -3
View File
@@ -193,10 +193,50 @@ class NormalBot
}
$valueField = $flow['value_field'] ?? 'id';
$labelField = $flow['label_field'] ?? 'name';
$group = $flow['meta_group'] ?? '';
$key = $flow['meta_key'] ?? '';
$nextNode = $flow['next_node'] ?? null;
// Si el NLU extrajo entities, intentar auto-seleccionar sin mostrar lista
$entities = $meta['__nlu_entities'] ?? [];
unset($meta['__nlu_entities']);
if (!empty($entities)) {
$matchedId = null;
foreach ($entities as $ev) {
$evNorm = self::normalize((string)$ev);
foreach ($items as $item) {
if (self::normalize((string)($item[$labelField] ?? '')) === $evNorm) {
$matchedId = (string)($item[$valueField] ?? '');
break 2;
}
}
}
if ($matchedId !== null) {
$formData = $meta[$group] ?? [];
$formData[$key] = $matchedId;
$meta[$group] = $formData;
ConversationContext::updateMetadata($ctxId, $meta);
if ($nextNode !== null) {
ConversationContext::updateNode($ctxId, $nextNode);
$config = json_decode($company['config_json'] ?? '{}', true);
$flows = $config['flows'] ?? [];
$menus = $config['menus'] ?? [];
if (isset($flows[$nextNode])) {
return self::handleFlow($flows[$nextNode], $context, $company, $ctxId, $menus);
}
}
ConversationContext::updateNode($ctxId, null);
return null;
}
// Sin match: continuar mostrando la lista normal
ConversationContext::updateMetadata($ctxId, $meta);
}
$meta['collecting'] = [
'meta_group' => $flow['meta_group'] ?? '',
'meta_key' => $flow['meta_key'] ?? '',
'next_node' => $flow['next_node'] ?? null,
'meta_group' => $group,
'meta_key' => $key,
'next_node' => $nextNode,
'__valid_ids' => array_column($items, $valueField),
];
ConversationContext::updateMetadata($ctxId, $meta);