Una vez que tenemos la respuesta del LLM, si todo ha ido bien llegara información de las funciones a llamar con FUNC(…) como lo hemos definido, realizaremos el análisis de la respuesta, en nuestro caso usaremos expresiones regulares.
regex_t regex;
regmatch_t matches[3];
const char *patron = "FUNC\\(([^:)]+):?([^)]*)\\)";
regcomp(®ex, patron, REG_EXTENDED) ;
// Bucle en el que recogemos las funciones encontradas y se invocan.
while (regexec(®ex, cursor, 3, matches, 0) == 0)
{
char func_nombre[64] = {0};
char params[256] = {0};
// Extraer Nombre
int len_f = matches[1].rm_eo - matches[1].rm_so;
strncpy(func_nombre, cursor + matches[1].rm_so, len_f);
// Extraer Parámetros (si los hay)
int len_p = matches[2].rm_eo - matches[2].rm_so;
if (len_p > 0) // Si tiene paramentros
{
strncpy(params, cursor + matches[2].rm_so, len_p);
}
// Ejecutamos La función con sus respectivos parametros
}
regfree(®ex); // Libera estructura
La explicación del patrón es muy sencilla
Formato FUNC(Accion:Parametro)
FUNC\\( ([^:)]+) :? ([^)]*) \\)
^ ^ ^ ^ ^
| | | | |
| | | | L----Cierre ")"
| | | L------------Grupo captura parámetros opcional fin ")"
| | L---------------":" opcional
| L-------------------------Grupo captura función hasta ":"
L---------------------------------Apertura "FUNC("
Una vez analizada la respuesta vemos a que función y con que parámetros los llamamos. Deberemos tener entonces nuestra caja de herramientas con las funciones que las definiremos también en un array para realizar un puntero a función.
// Toda función de acción de agente tendra esta forma
typedef void (*AgenteAccion)(const char *params);
/************* Funciones de la caja de herramientas *******/
void cmd_elTiempo(const char *p) { printf("Vemos el tiempo en: %s\n", p); }
void cmd_laFecha(const char *p) { printf("Damos la fecha y hora...\n"); }
// Estructura de la herramienta: nombre función y argumentos
typedef struct
{
const char *nombre;
AgenteAccion ejecutar;
} Herramienta_t;
// ARRAY DE HERRAMIENTAS (Tu "caja de herramientas")
Herramienta_t catalogo[] =
{
{"elTiempo", cmd_elTiempo},
{"laFecha", cmd_laFecha}
};
#define NUM_HERRAMIENTAS (sizeof(catalogo) / sizeof(Herramienta_t))
La llamada sera muy sencilla, se recorre el array de posibles funciones, sino error de funcion no encontrada y se traduce a una llamada de puntero a función.
// En func_nombre tendremos la funcion a ejecutar y en params los parametros.
bool encontrada = false;
for (int i = 0; i < NUM_HERRAMIENTAS ; i++)
{
if (strcmp(func_nombre, catalogo[i].nombre) == 0)
{
encontrada = true;
catalogo[i].ejecutar(params);
break;
}
}
if(!encontrada) printf("No implementada %s parametros %s\n",func_nombre,params);
Con este resumen de como programar un agente terminamos, te recomiendo veas el código completo en https://github.com/pinguytaz/IA/tree/main/Llama.cpp/src/Agente.
