{"id":1225,"date":"2026-06-23T08:18:00","date_gmt":"2026-06-23T06:18:00","guid":{"rendered":"https:\/\/www.pinguytaz.net\/?p=1225"},"modified":"2026-06-03T20:27:51","modified_gmt":"2026-06-03T18:27:51","slug":"construyendo-un-agente-de-ia-nativo-con-c-y-llama-cpp-y-vi","status":"publish","type":"post","link":"https:\/\/www.pinguytaz.net\/index.php\/2026\/06\/23\/construyendo-un-agente-de-ia-nativo-con-c-y-llama-cpp-y-vi\/","title":{"rendered":"Construyendo un Agente de IA Nativo con C y Llama.cpp (y VI)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Una vez que tenemos la respuesta del LLM, si todo ha ido bien llegara informaci\u00f3n de las funciones a llamar con FUNC(&#8230;) como lo hemos definido, realizaremos el an\u00e1lisis de la respuesta, en nuestro caso usaremos expresiones regulares.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>regex_t regex;\nregmatch_t matches&#91;3];\n\nconst char *patron = \"FUNC\\\\((&#91;^:)]+):?(&#91;^)]*)\\\\)\";\nregcomp(&amp;regex, patron, REG_EXTENDED) ;\n\n\/\/ Bucle en el que recogemos las funciones encontradas y se invocan.\nwhile (regexec(&amp;regex, cursor, 3, matches, 0) == 0) \n{\n   char func_nombre&#91;64] = {0};\n   char params&#91;256] = {0};\n\n   \/\/ Extraer Nombre\n   int len_f = matches&#91;1].rm_eo - matches&#91;1].rm_so;\n   strncpy(func_nombre, cursor + matches&#91;1].rm_so, len_f);\n\n   \/\/ Extraer Par\u00e1metros (si los hay)\n   int len_p = matches&#91;2].rm_eo - matches&#91;2].rm_so;\n   if (len_p > 0)  \/\/ Si tiene paramentros\n   {\n      strncpy(params, cursor + matches&#91;2].rm_so, len_p);\n   }\n\n   \/\/ Ejecutamos  La funci\u00f3n con sus respectivos parametros\n  \n}\nregfree(&amp;regex);  \/\/ Libera estructura\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">La explicaci\u00f3n del patr\u00f3n es muy sencilla<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Formato FUNC(Accion:Parametro)\n\n\tFUNC\\\\( (&#91;^:)]+) :? (&#91;^)]*) \\\\) \n\t^   \t^  \t ^  ^       ^  \n\t|   \t|  \t |  |       |\n\t|   \t|  \t |  |       L----Cierre \")\"\n\t|       |        |  L------------Grupo captura par\u00e1metros opcional fin \")\"\n\t|   \t|  \t L---------------\":\" opcional\n\t|\tL-------------------------Grupo captura funci\u00f3n hasta \":\"\n\tL---------------------------------Apertura \"FUNC(\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Una vez analizada la respuesta vemos a que funci\u00f3n y con que par\u00e1metros los llamamos. Deberemos tener entonces nuestra caja de herramientas con las funciones que las definiremos tambi\u00e9n en un array para realizar un puntero a funci\u00f3n.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Toda funci\u00f3n de acci\u00f3n de agente tendra esta forma\ntypedef void (*AgenteAccion)(const char *params);\n\n\/*************  Funciones de la caja de herramientas *******\/\nvoid cmd_elTiempo(const char *p) { printf(\"Vemos el tiempo en: %s\\n\", p); }\nvoid cmd_laFecha(const char *p)  { printf(\"Damos la fecha y hora...\\n\"); }\n\n\/\/  Estructura de la herramienta: nombre funci\u00f3n y argumentos\ntypedef struct \n{\n    const char *nombre;\n    AgenteAccion ejecutar;\n} Herramienta_t;\n\n\n\/\/ ARRAY DE HERRAMIENTAS (Tu \"caja de herramientas\")\nHerramienta_t catalogo&#91;] = \n{\n   {\"elTiempo\",   cmd_elTiempo},\n   {\"laFecha\",  cmd_laFecha}\n};\n#define NUM_HERRAMIENTAS (sizeof(catalogo) \/ sizeof(Herramienta_t))\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">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\u00f3n.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ En func_nombre tendremos la funcion a ejecutar y en params los parametros.\nbool encontrada = false;\nfor (int i = 0; i &lt; NUM_HERRAMIENTAS ; i++)\n{\n    if (strcmp(func_nombre, catalogo&#91;i].nombre) == 0) \n\t{\n\t   encontrada = true;\n       catalogo&#91;i].ejecutar(params);\n       break;\n    }\n}\nif(!encontrada) printf(\"No implementada %s parametros %s\\n\",func_nombre,params);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Con este resumen de como programar un agente terminamos, te recomiendo veas el c\u00f3digo completo en <a href=\"https:\/\/github.com\/pinguytaz\/IA\/tree\/main\/Llama.cpp\/src\/Agente\">https:\/\/github.com\/pinguytaz\/IA\/tree\/main\/Llama.cpp\/src\/Agente<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Una vez que tenemos la respuesta del LLM, si todo ha ido bien llegara informaci\u00f3n de las funciones a llamar con FUNC(&#8230;) como lo hemos definido, realizaremos el an\u00e1lisis de la respuesta, en nuestro caso usaremos expresiones regulares. La explicaci\u00f3n del patr\u00f3n es muy sencilla Una vez analizada la respuesta vemos a que funci\u00f3n y [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1197,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"site-container-style":"default","site-container-layout":"default","site-sidebar-layout":"default","disable-article-header":"default","disable-site-header":"default","disable-site-footer":"default","disable-content-area-spacing":"default","footnotes":""},"categories":[212],"tags":[224,225],"class_list":["post-1225","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-llama-cpp-ia","tag-agente","tag-puntero-a-funcion"],"_links":{"self":[{"href":"https:\/\/www.pinguytaz.net\/index.php\/wp-json\/wp\/v2\/posts\/1225","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pinguytaz.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pinguytaz.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pinguytaz.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pinguytaz.net\/index.php\/wp-json\/wp\/v2\/comments?post=1225"}],"version-history":[{"count":2,"href":"https:\/\/www.pinguytaz.net\/index.php\/wp-json\/wp\/v2\/posts\/1225\/revisions"}],"predecessor-version":[{"id":1227,"href":"https:\/\/www.pinguytaz.net\/index.php\/wp-json\/wp\/v2\/posts\/1225\/revisions\/1227"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.pinguytaz.net\/index.php\/wp-json\/wp\/v2\/media\/1197"}],"wp:attachment":[{"href":"https:\/\/www.pinguytaz.net\/index.php\/wp-json\/wp\/v2\/media?parent=1225"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pinguytaz.net\/index.php\/wp-json\/wp\/v2\/categories?post=1225"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pinguytaz.net\/index.php\/wp-json\/wp\/v2\/tags?post=1225"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}