feat(telegram): el bot resuelve clientes por nombre y mide sus propios fallos
Dos de las cuatro mejoras de la auditoría del agente. 1. Las herramientas aceptan cliente_nombre además de cliente_id. De 27 parámetros que eran IDs, 10 eran de cliente. Para cada acción el modelo tenía que encadenar: listar_clientes → leer la respuesta → encontrar la fila → extraer el número → recién ahí llamar a la herramienta. Cuatro pasos, y basta que falle uno para que no se guarde nada — es la explicación más probable de la factura que nunca se creó, porque ese cliente podía no venir en la primera página del listado. Ahora el modelo pasa el nombre y el servidor lo resuelve, con búsqueda completa y no paginada. Si hay varios candidatos devuelve la lista para que el modelo pregunte cuál, en vez de elegir uno: cargarle una factura a la empresa equivocada es peor que preguntar. Una coincidencia exacta gana sobre las parciales, así "Metropolitana" no queda ambiguo solo porque existe "Metropolitana Norte". 2. Contadores de uso y fallo por herramienta, expuestos como estado_herramientas. Cada problema se venía diagnosticando de a un caso, reconstruyendo qué pasó después de que el usuario avisara. Ahora se puede preguntar directamente qué viene fallando y ver si es una herramienta puntual o el modelo eligiendo mal. En memoria a propósito: alcanza para responder eso y no agrega una tabla. Quedan las otras dos: adelgazar el prompt de 5,4 KB moviendo los manuales por dominio a las descripciones de las herramientas, y comparar modelos con un mismo caso. La primera conviene hacerla con el sistema estable, porque toca cómo decide el modelo en todos los flujos a la vez. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
d0c9ed5656
commit
e2440b04f1
@@ -65,3 +65,35 @@ func TestErrorDeTool(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// El id explícito manda: si el modelo ya lo tiene, no hay que ir a la base.
|
||||
// Es el único camino del resolvedor que se puede probar sin datos.
|
||||
func TestResolverClienteIDPrefiereElIDExplicito(t *testing.T) {
|
||||
id, err := ResolverClienteID(42, "cualquier nombre")
|
||||
if err != nil || id != 42 {
|
||||
t.Fatalf("= (%d, %v), esperaba (42, nil)", id, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Sin id ni nombre no se puede adivinar: mejor un error claro que buscar en la
|
||||
// base con la cadena vacía y traer un cliente al azar.
|
||||
func TestResolverClienteIDSinDatos(t *testing.T) {
|
||||
if _, err := ResolverClienteID(0, " "); err == nil {
|
||||
t.Fatal("esperaba error cuando no hay ni id ni nombre")
|
||||
}
|
||||
}
|
||||
|
||||
// Las herramientas que piden cliente deben aceptar también el nombre: es lo
|
||||
// que elimina el ciclo listar_clientes → leer → extraer id, que es donde se
|
||||
// perdía la factura.
|
||||
func TestHerramientasDeClienteAceptanNombre(t *testing.T) {
|
||||
for _, tl := range agentTools() {
|
||||
props := tl.Function.Parameters.Properties
|
||||
if _, pide := props["cliente_id"]; !pide {
|
||||
continue
|
||||
}
|
||||
if _, acepta := props["cliente_nombre"]; !acepta {
|
||||
t.Errorf("%s pide cliente_id pero no acepta cliente_nombre: obliga al modelo a resolver el id por su cuenta", tl.Function.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user