{"id":1210,"date":"2026-06-16T07:27:00","date_gmt":"2026-06-16T05:27:00","guid":{"rendered":"https:\/\/www.pinguytaz.net\/?p=1210"},"modified":"2026-06-03T20:26:35","modified_gmt":"2026-06-03T18:26:35","slug":"construyendo-un-agente-de-ia-nativo-con-c-y-llama-cpp-iv","status":"publish","type":"post","link":"https:\/\/www.pinguytaz.net\/index.php\/2026\/06\/16\/construyendo-un-agente-de-ia-nativo-con-c-y-llama-cpp-iv\/","title":{"rendered":"Construyendo un Agente de IA Nativo con C y Llama.cpp (IV)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">El contexto nos permite tener un historico de lo preguntado, y as\u00ed adaptar nuestra respuesta pero este es limitado, seg\u00fan lo definamos como hemos podido ver al crearlo.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>context_t *iniciaContexto(modelo_t *modelo)\n{\n   paramContext_t parametrosContexto = llama_context_default_params();\n   \/\/ Optimizaci\u00f3n para OpenBLAS en CPU\n   \/\/parametrosContexto.n_ctx = 2048;  \/\/ Tama\u00f1o contexto\n   \/\/parametrosContexto.n_batch = 2048; \/\/ Tokes a procesar para llama_decodee.\n   parametrosContexto.n_ctx = 512;  \/\/ Tama\u00f1o contexto\n   parametrosContexto.n_batch = 512; \/\/ Tokes a procesar para llama_decodee.\n\n   \/\/ Crear el contexto ligado al modelo\n   return  llama_init_from_model(modelo, parametrosContexto);\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Vemos en el c\u00f3digo que ser\u00e1n 2048 bytes, pero seg\u00fan vamos realizando iteracciones se va llenando, as\u00ed que llegado ese momento <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Analizamos el espacio del contexto\nint n_ctx = llama_n_ctx(contexto);\nint n_ctx_usada = llama_memory_seq_pos_max(llama_get_memory(contexto), 0) + 1;\nif (n_ctx_usada + miBatch.n_tokens &gt; n_ctx)   \/\/ Sobrepasamos el contexto, por lo que debemos limpiar o restructurar.<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Una vez que vemos que no disponemos de m\u00e1s contexto podemos realizar tres cosas:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Salir del programa porque no tenemos m\u00e1s espacio, no es lo m\u00e1s normal a utilizar.<\/li>\n\n\n\n<li>Limpiar el contexto por completo, acordandonos de poner el rol del sistema para que se vuelva a comportar con el ROL definicdo.<\/li>\n\n\n\n<li>Rotar perdiendo solo lo m\u00e1s antiguo \u00abVentana Deslizante\u00bb <\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">La primera opci\u00f3n es muy sencilla, pues valdr\u00e1 con realizar un <strong>exit(x)<\/strong> el segundo tambi\u00e9n es sencillo y sera limpiar el \u00e1rea del contexto por completo y reiniciar la inferencia desde el principio.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>llama_memory_seq_rm(llama_get_memory(contexto), 0, -1, -1); \/\/ Borra todo el \u00e1rea del contexto.\nfree(prompt_formateado);  \/\/ Limpia volvemos a inferir\ninferencia(rolSystem, prompt, modelo, contexto, miSampler,vocab);  \/\/ Volvemos a realizar la inferencia.<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">La tercera opci\u00f3n y la que consideramos m\u00e1s apropiada pues no es compleja y nos da mucho juego es la t\u00e9cnica de la Ventana Deslizante (Sliding Window) que en lugar de borrar todo cuando el contexto llega a su l\u00edmite, aplicamos una poda selectiva:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Preservamos el ROL:<\/strong> Los primeros tokens (instrucciones del sistema) nunca se borran.<\/li>\n\n\n\n<li><strong>Rotaci\u00f3n:<\/strong> Borramos un bloque intermedio y desplazamos los mensajes recientes hacia atr\u00e1s usando \u00abllama_memory_seq_add\u00bb <\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"409\" height=\"74\" src=\"https:\/\/www.pinguytaz.net\/wp-content\/uploads\/2026\/06\/imagen.png\" alt=\"\" class=\"wp-image-1214\" srcset=\"https:\/\/www.pinguytaz.net\/wp-content\/uploads\/2026\/06\/imagen.png 409w, https:\/\/www.pinguytaz.net\/wp-content\/uploads\/2026\/06\/imagen-300x54.png 300w\" sizes=\"auto, (max-width: 409px) 100vw, 409px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Lo primero es conocer los Tokens que utiliza la definici\u00f3n del Rol-System ya que muchas veces es peque\u00f1a o nula, pero por ejemplo en la creaci\u00f3n de un agente como veremos m\u00e1s adelante es bastante amplia.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Antes de nada debemos saber cuanto ocupa el Rol del sistema.\nmensajeChat_t rol_System&#91;] = {{\"system\", rolSystem }};\n\n\/\/ Calculamos los tokens del ROL, \nint32_t bytes_ROL = llama_chat_apply_template(llama_model_chat_template(modelo, NULL), rol_System, 1, false, NULL, 0); \n\/\/ Buffer temporal para el ROL formateado\nchar * prompt_ROL = malloc(bytes_ROL + 1);\nllama_chat_apply_template(llama_model_chat_template(modelo, NULL), rol_System, 1, false, prompt_ROL, bytes_ROL); \nprompt_ROL&#91;bytes_ROL] = '\\0';\nContamos TOKENS usamos NULL en el buffer de tokens y 0 solo cuenta\nint32_t <strong>tokens_ROL<\/strong> = llama_tokenize( vocab, prompt_ROL, bytes_ROL, NULL, 0, true, true ); \/\/ add_especial es true porque el ROL abre la secuencia.\nfree(prompt_ROL); \/\/ Limpiamos memoria temporal del ROL que no sera necesaria<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Con el dato de los tokens del Rol-System ya podemos realizar una rotaci\u00f3n, antes definiremos tambi\u00e9n cuantos se echan hacia atr\u00e1s, podemos ver un ejemplo grafico de 2 tokens para el ROL y 10 en total.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ESTADO 1: Contexto Lleno\n&#91; S1 | S2 | T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 ]  &lt;-- \u00a1Lleno!\n  ^----^    ^--------------------------------^\n  SYSTEM          HISTORIAL DE CHAT\n\nESTADO 2: Aplicando Sliding Window (Borramos el 20% antiguo)\n&#91; S1 | S2 | -- | -- | T3 | T4 | T5 | T6 | T7 | T8 ]\n            ^-- Hueco creado (borramos T1 y T2)\n\nESTADO 3: Compactaci\u00f3n y Desplazamiento (Shift)\n&#91; S1 | S2 | T3 | T4 | T5 | T6 | T7 | T8 | N1 | N2 ]\n                                          ^----^\n                                      NUEVOS TOKENS<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">En c\u00f3digo quedar\u00eda de la siguiente forma<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ T\u00e9cnica avanzada de \"Sliding Window\" (Ventana Deslizable).\nint32_t n_tokens_a_borrar = 256;                 \/\/ Definimos bloque a borrar\n\/\/ L\u00edmites de la \"poda\" p0(Despues del ROL) p1 + borrado\nint32_t p0 = tokens_ROL;   \/\/Los TOKENs necesarios para el ROL, desde donde borraremos\nint32_t p1 = tokens_ROL + n_tokens_a_borrar;   \/\/ Hasta donde borramos\nllama_memory_seq_rm(llama_get_memory(contexto), 0, p0, p1);\n\/\/ Movemos lo que qued\u00f3 al final hacia atr\u00e1s para cerrar el hueco\nllama_memory_seq_add(llama_get_memory(contexto), 0, p1, -1, -n_tokens_a_borrar);\n\n\/\/ Continuamos con la inferencia llamando a llama_decode.<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Y ya nos queda que lo dejamos para el pr\u00f3ximo la generaci\u00f3n del agente, que veremos que lo \u00fanico que a\u00f1adiremos es una definici\u00f3n correcta del Rol-System, y las funciones agenticas.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>El contexto nos permite tener un historico de lo preguntado, y as\u00ed adaptar nuestra respuesta pero este es limitado, seg\u00fan lo definamos como hemos podido ver al crearlo. Vemos en el c\u00f3digo que ser\u00e1n 2048 bytes, pero seg\u00fan vamos realizando iteracciones se va llenando, as\u00ed que llegado ese momento Una vez que vemos que no [&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":[221,222,215,219],"class_list":["post-1210","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-llama-cpp-ia","tag-c","tag-contexto","tag-llama-cpp","tag-modelo"],"_links":{"self":[{"href":"https:\/\/www.pinguytaz.net\/index.php\/wp-json\/wp\/v2\/posts\/1210","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=1210"}],"version-history":[{"count":5,"href":"https:\/\/www.pinguytaz.net\/index.php\/wp-json\/wp\/v2\/posts\/1210\/revisions"}],"predecessor-version":[{"id":1217,"href":"https:\/\/www.pinguytaz.net\/index.php\/wp-json\/wp\/v2\/posts\/1210\/revisions\/1217"}],"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=1210"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pinguytaz.net\/index.php\/wp-json\/wp\/v2\/categories?post=1210"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pinguytaz.net\/index.php\/wp-json\/wp\/v2\/tags?post=1210"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}