• Updated:
  • Featured post

How LLMs generate the next token

(este post es una explicación de la teoría. dejo aquí otro post con el detalle práctico de como usar la temperature, top_k y top_p a efectos prácticos)

Explicación más en detalle de cómo obtienen los LLMs las probabilidades para generar el siguiente token

Sampling

En cada posición el modelo tiene una bolsa con miles de tokens posibles. Sampling es el proceso de no coger siempre el token más probable, si no de orientarlo a coger respuestas con determinadas características.

Si el modelo escogiera siempre el token con más probabilidades, obtendríamos respuestas aburridas y repetitivas.

Logits

Para generar el siguiente token, una red neuronal calcula primero los vectores de logits, donde cada logit corresponde a un valor posible. El tamaño de estos vectores de logits es tan grande como el vocabulario completo del modelo.

(representación de vectores de logits)

flowchart LR
	N1["What's your favorite color?"]:::note --> Z
	Z --> A1 --> A
	Z --> B1 --> B
	Z --> C1 --> C
	Z --> D1 --> D
	
	Z["Neural network"]
    A["a"]
    A1["(-0.5)"]
    B["green"]
    B1["(0.7)"]
    C["red"]
    C1["(0.5)"]
    D["the"]
    D1["(-1.2)"]
    
    classDef note fill:none,stroke:none,color:#777;    

Los logits NO representan probabilidades ya que no suman 1 y pueden incluso ser negativos (la probabilidades no pueden). Para convertir logits a probabilidades se usa una Softmax layer

Temperature

La temperatura es una constante que se aplica a los logits antes de la transformación de la Softmax layer. Se usa para ajustar la creatividad del modelo y redistribuir la probabilidad de los valores. Una temperatura más alta hace que el modelo sea más creativo ya que aumenta las posibilidades de elegir tokens menos probables.

xychart-beta
  title "Temperatura vs Probabilidad"
  x-axis "Temperatura (T)" [0.1, 0.2, 0.5, 1, 2, 5]
  y-axis "Probabilidad" 0 --> 1
  line "P(token1)" [0.9999546, 0.9933071, 0.8807971, 0.7310586, 0.6224593, 0.5498340]
  line "P(token2)" [0.0000454, 0.0066929, 0.1192029, 0.2689414, 0.3775407, 0.4501660]

Ejemplos de temperaturas:

  • Low (0.2-0.3): El modelo es cauto y elige las palabras más probables. Output factual y predecible.
  • Medium (0.5-0.7): Un mix de confiabilidad y engagement
  • High (0.9-1.0): Toma riesgos y es impredecible

Read More

  • Updated:

Github Copilot (Visual Studio) Advanced Features

Agent Mode

Sirve para especificar una task a alto nivel. La IA crea un plan, hace ediciones de código, ejecuta comandos, invoca herramientas y aplica cambios a lo largo de tu codebase. Monitorea o construye resultados, unit tests e itera según se necesita.

A contrario del modo Conversación, el modo agente no para después de dar una respuesta. Se sigue ejecutando y refinando hasta que se consigue el objetivo del prompt o se necesita más input.

Selective Context

access agents with @

@workspace I need to create a Dockerfile for this project, can you generate one that will help me package it?

Code review agentica

Se pueden realizar code reviews agenticas desde el propio Visual Studio.

Abrimos la ventana Cambios de GIT. Alli podemos ver los cambios que tenemos hechos en la rama antes de hacer un commit. Las reviews agenticas se lanzan mediante este botón

(TODO: añadir captura botón)

Copilot custom instructions

En Visual Studio es posible customizar las instrucciones a nivel de repositorio. También se pueden usar prompt files para reutilizar prompts con contexto o hacer reviews agenticas repetibles.

Reference(s)

https://learn.microsoft.com/en-us/visualstudio/ide/copilot-agent-mode?view=visualstudio GitHub Copilot features - GitHub Docs

  • Updated:

Cursor (Bugbot, Reviews Agénticas, Skills, MCP, Subagents)

Cursor es un IDE con IA integrada basado en un fork de Visual Studio Code. Para desarrollo personal obtengo una experiencia parecida a usar Visual Studio con Github Copilot para .NET.

Cursor overview

Conviene destacar los siguientes modos de uso de la IA:

  • Agent - modo principal para programar cambios. Lanza subagentes en un loop hasta completar la tarea. Se le dan tareas granuladas y despiezadas y él investiga, hace cambios y comprueba que compile (en caso necesario) con subagentes.
  • Plan - el modelo escanea tu base de código, te hace preguntas para clarificar lo que quieres hacer y genera un plan paso a paso, el cual puedes editar antes de comenzar y se encarga de seguirlo él mismo. Recomendado para cambios grandes o no tan granulados.
  • Debug - le describes los síntomas del bug que percibes y te ayuda a encontrarlo y reproducirlo de manera fiable. Le puedes pasar logs y otros tipos de información. Útil para cuando sabes que hay un problema pero no eres capaz de reproducirlo. Para bugs simples y rápidos usar el modo agente. Este es para casos complejos. (!) Para casos de debug muy complejos Cursor permite ejecutar múltiples modelos en paralelo, ya que cada modelo puede encontrar diferentes problemas (!)

Referenciar chats

Si empezamos a llenar la ventana de contexto y necesitamos empezar una conversación nueva, pero todavía estamos a medias o la tarea está relacionada con la conversación previa, se pueden referenciar conversaciones con @Past Chats y obtiene un resumen de la conversación para poder seguir.

Bugbot

Integración de Crusor (modo agentes en background) con Github. Son $40/mes extra. Es muy útil pero (en mi caso de uso personal) no merece la pena por su precio, teniendo en cuenta que Cursor son $20/mes con esto pasamos a $60/mes por todo. No hace nada que no puedas automatizar con agentes o reviews agénticas por tu cuenta.

Ejemplo mío de una PR con Bugbot

Cuando creas una PR de una rama en Github se encarga de:

  • añadirle descripción analizando los cambios que se han hecho
  • hace un análisis de código buscando vulnerabilidades y problemas potenciales

Bugbot overview

Reviews Agénticas

Una alternativa si no quieres pagar por BugBot son las reviews agénticas. Una vez el agente ha acabado de hacer los cambios:

  • Revisamos nosotros primero los cambios de código manualmente. Usar agentes no quita que tengamos que prestar atención
  • Cursor tiene un botón Review o Find Issues que busca posibles problemas en las líneas que ha modificado
  • Si abrimos la pestaña Source Control, podemos ejecutar una Agent Review para comparar la rama en la que estamos vs develop o master. De este modo busca problemas en comparando el set completo de cambios

Estos modos son simplemente atajos. Por debajo todo lo que hacen es mandar un prompt específico al agente para hacer una review de los cambios. Aún sin estos botones o Cursor, podemos hacer exactamente lo mismo con cualquier otro LLM integrado.

Read More

Claude Code

Claude Code es una herramienta agentica que lee el código de tu proyecto, edita ficheros, ejecuta comandos e integra herramientas de desarrollo. Funciona como un agente fire and forget.

Se le piden las tareas de manera descriptiva, las ejecuta y presenta los resultados. El usuario se ve menos involucrado en los detalles de la implementación respecto a Cursor (overview de cómo usarlo).

Características

  • Por defecto tiene acceso a Git y puede crear commits y PRs.
  • Se puede integrar con MCPs.
  • Se puede customizar con instrucciones, skills y hooks
  • Las skills sirven para crear custom commands /review-pr para acciones repetibles
  • Tiene persistencia con memoria y auto-memoria
  • Se pueden crear múltiples subagentes

Uso en CLI

Como Claude Code se puede usar en CLI, se puede usar en pipes para procesar el output de comandos.

# analizar log output
tail -200 app.log | claude -p "Message me if you see any anomalies"

# bulk operations across files
git diff main --name-only | claude -p "review these changed files for security issues"

Read More

Git normalize line endings (.gitattributes)

Esto soluciona el problema con Git que a veces Gitkraken me muestra ficheros en la lista de cambios como si hubieran sido modificados, pero realmente no los tienen y genera ruido.

Añadir .gitattributes al repo con el siguiente contenido

# Normaliza texto automáticamente
* text=auto

# Markdown SIEMPRE en LF
*.md text eol=lf

# Scripts Unix
*.sh text eol=lf

# Binarios
*.png binary
*.jpg binary
*.pdf binary

ir a la carpeta del repo. Ejecutar lo siguiente.

git add --renormalize .
git status

hacer un commit con los contenidos normalizados.

Rob Pike's 5 Rules of Programming

  • Rule 1. You can’t tell where a program is going to spend its time. Bottlenecks occur in surprising places, so don’t try to second guess and put in a speed hack until you’ve proven that’s where the bottleneck is.
  • Rule 2. Measure. Don’t tune for speed until you’ve measured, and even then don’t unless one part of the code overwhelms the rest.
  • Rule 3. Fancy algorithms are slow when n is small, and n is usually small. Fancy algorithms have big constants. Until you know that n is frequently going to be big, don’t get fancy. (Even if n does get big, use Rule 2 first.)
  • Rule 4. Fancy algorithms are buggier than simple ones, and they’re much harder to implement. Use simple algorithms as well as simple data structures.
  • Rule 5. Data dominates. If you’ve chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming.

Takeaways

  • Premature optimization is the root of all evil. Don’t do it until it’s necessary and then measure before and after.
  • Don’t try to be fancy. When in doubt, use brute force (KISS)
  • Improve my data knowledge.

Source(s)

https://www.cs.unc.edu/~stotts/COMP590-059-f24/robsrules.html
https://news.ycombinator.com/item?id=47423647

LangChain

LangChain es un framework open-source implementado en Python. Es un orquestador de aplicaciones basadas en LLMs que proporciona diferentes abstracciones de alto nivel para construir pipelines sobre LLMs.

La gran ventaja que nos introduce es abstraernos de la manera de consumir los diferentes LLMs para no tener que reinventar el código cada vez que queramos cambiar de modelo.

Ahora mismo LangChain dispone de 6 módulos diferentes

  • Model I/O - Handle input/output ops related to the model
  • Retrieval - Retrieves relevant texts for the LLM
  • Chains (Runnables) - Enables construction of sequences of LLM operations or function calls
  • Agents - Allows chains to make decisions on which tools to use based on high-level instructions
  • Memory - perstist the state of an application between different runs of a chain
  • Callbacks - for running additional code on specific events

Install

poetry add langchain
poetry add langchain-openai
poetry add openai # this is in case we want to use OpenAI's models

ChatModels

We have the following classes to interact with LLMs in the context of LangChain

  • SystemMessage - instructions for the AI System (Behaviour)
  • HumanMessage - messages coming from an human to interact with the LLM (questions, commands…)
  • AIMessage - information coming from the AI itself. This is typically the AI’s response

AI EU Legislation

European Regulation 2024/1689

La IA se clasifica por riesgos:

riesgo medidas ejemplo
inaceptable prohibido social scoring systems; manipulative AI
alto riesgo regulado  
riesgo limitado obligaciones de transparencia; los usuarios finales deben tener conocimiento que interactuan con un sistema de IA chatbots; deepfakes
riesgo mínimo sin regular juegos; filtros de spam;

Sobre todo establece obligaciones para providers (developers) de sistemas de alto riesgo que operen en EU, independientemente de dónde se encuentren localizados.

RAG implementation

El código para mi implementación está aquí en GitHub

Requerimientos

  • LangChain
  • Un modelo de embeddings (text-embedding-3-large)
  • Un modelo de chat (gpt-4.1)
  • Una base de datos vectorial (CosmosDB)
  • PyPDF (libreria para chunking inteligente)
  • Documentos como base de conocimiento para el RAG (documentos sobre una herramienta propietaria)

Sobre CosmosDB for NoSQL: Se puede usar como una base NoSQL tradicional pero también soporta búsqueda nativa con vectores (hay que habilitarlo primero y establecer una policy vectorial). Yo la uso en vez de ChromaDB por estar en Azure y ser entorno Microsoft ya que personalmente me entra dentro del tier gratuito. Si no, ChromaDB es una buena opción gratuita.

Implementación

Se divide en tres procesos:

Habilitar búsqueda vectorial para CosmosDB. Tras hacer el siguiente paso, podemos ejecutar el script para recrear el contenedor con una policy para vectores

(dentro de CosmsoDB) Settings < Features < Vector Search for NoSQL API < Enable

Cargar documentos en CosmosDB:

  • Cargamos los documentos en memoria
  • Los dividimos en chunks
  • Limpiamos los chunks de caracteres especiales (\n, \t, \r)
  • Creamos los embeddings en batches
  • Para cada chunk subimos el original y su embeddings

Realizar una query:

  • Obtenemos los embeddings para la query (tiene que ser el mismo modelo que se usó para crear los embeddings de los ficheros)
  • Hacer una búsqueda vectorial en CosmosDB para sacar el texto original de los chunks con contexto relevante a nuestra query
  • Invocar el modelo de chat a través de LangChain, pasándole ambos pregunta y chunks con contexto en la misma llamada

Conceptos aprendidos

Calidad del dato

La calidad del dato es de máxima importancia. Hay que revisar manualmente los datos que se meten y ver que sean aporten valor. Si metemos datos que no aporten, solo generamos ruido.

También hay que revisar que los PDFs sean texto puro, ya que si son puramente imágenes o contienen imágenes importantes habrá que pasarlos por algún tipo de OCR para extraer texto.

Chunking

La parte de dónde y cómo hacer chunking es complicada. Lo importante es que haya un buen overlap entre chunks para que la respuesta a tu pregunta no caiga en tierra de nadie. Yo estoy probando con un chunk_size de 500 tokens y un overlap de 100 tokens.

Limpiar los chunks después de partirlos es igual de importante. En mis primeras pruebas se metían en cosmos muchos caracteres como \n o \t y esto genera mucho ruido.

Para sistemas grandes o genéricos puede ser importante meter metadatos junto a los chunks para filtrar luego al buscar. Cosas como el nombre del documento al que pertenece un chunk o la fecha de creación del documento ayudan a filtrar luego y favorecer documentación reciente o saber de dónde viene algún dato erróneo o con menor calidad.

Debilidades BBDD Vectorial

Una base de datos vectorial es muy buena para hacer búsquedas relacionadas o búsquedas semánticas, pero se queda corta para hacer búsquedas por keywords. En esas situaciones se puede implementar una búsqueda híbrida (algoritmo BM25).

Referencia(s)

RAG Systems in 5 Levels of Difficulty (With Full Code) | Data Science Collective *RAG vs Fine Tuning. The Great LLM Showdown | by Agneya Pathare | Medium

C# parallelize code

Example on how to write parallel code

public List<string> ProcessX(CancellationToken cancToken = default)
{
	// sequential code
	// ...
	
	// list that we want to be able to process faster
	List<Animal> animals = // ... 
	
	// multithread safe collection
	var animalsDTO = new ConcurrentBag<AnimalDTO>();
	var options = new ParallelOptions
	{
		CancellationToken = cancToken,
		MaxDegreeOfParallelism = GetMaxDegreeOfParallelism()
	};
	
	Parallel.ForEach(animals, options, animal => 
	{
		// process single animal
		// this is just an example to map animal to animalDTO
		// ...
		animalsDTO.Add(Map(animal));
	});
}

private int GetMaxDegreeOfParallelism()
{
	string configured = config["ANIMALS_PARALLELISM"] ?? "4";
	int degree;
	if(!int.TryParse(configured, out degree))
	{
		degree = 4;
	}
	return degree;
}

AI (my own) Prompt Templates

Github Copilot IDE

Modificar código

– solution proposal x

– requirements Please before you do anything I want you to read and understand [PLANNING]. When coding please take [RESTRICTIONS] into account

[PLANNING] I want you to think deeply about my problem and proposed solution before doing any change. First of all:

  • analyse my code
  • read my problem
  • read my proposed solution
  • check its viability
  • make an index and a plan of what you’re going to do
  • follow and execute it
  • once you’re done, please go back and check that the code changes you made compile, make sense and solve the problem I have

[RESTRICTIONS]

  • don’t use var instead of string
  • don’t use arrays. use List instead

Standalone Copilot

Aprender sobre [TEMA]

Estoy aprendiendo sobre [TEMA]. Investiga fuentes de datos fiables y hazme primero un resumen de que es. Quiero saber para que sirve y que problema soluciona. Luego haz varias búsquedas y agrega los resultados para decirme que es importante o que debo saber sobre [TEMA] para poder comenzar a trabajar con ello. Por último hazme un plan paso a paso de un par de días de los puntos que tengo que estudiar o aprender para poder trabajar bien con [TEMA]

[TEMA]
LangChain

Read More