Explicación de RAG vs Fine-Tuning: qué hacen realmente y cuándo usar cada uno

He escrito bastante sobre RAG, comenzando con la Guía del autoestopista RAG con ChatGPT API y LangChain, y luego explorando varios temas relacionados con RAG y la IA, como fragmentación, búsqueda híbrida, reclasificación, recuperación contextual y una serie de tres partes sobre la evaluación de la calidad de la recuperación. En otras palabras, hemos cubierto mucho terreno en el lado del RAG.

De lo que no hemos hablado tan explícitamente es de la otra técnica importante que la gente utiliza cuando quiere mejorar una aplicación LLM para un dominio específico. Eso es afinar. Y, en particular, no hemos hablado de lo que sucede cuando pones los dos uno al lado del otro y tratas de descubrir cuál necesitas realmente.

Si busca “RAG vs ajuste fino” en línea, encontrará una gran cantidad de contenido que trata esto como una competencia con un ganador. Para algunos, RAG gana porque es más barato de configurar, para otros, gana el ajuste fino porque produce mejores resultados, y así sucesivamente. El problema con este encuadre es que es fundamentalmente engañoso, ya que RAG y el ajuste fino no son técnicas en competencia, sino técnicas que resuelven diferentes problemas en diferentes capas de una aplicación de IA. Comprender lo que realmente hace cada uno es el requisito previo para tomar una buena decisión.

Entonces, ¡echemos un vistazo!

🍨 DataCream es un boletín sobre inteligencia artificial, datos y tecnología. Si estás interesado en estos temas, ¡suscríbete aquí!

¿Qué es RAG y qué hace realmente?

Si has seguido esta serie, ya tienes una sólida intuición sobre RAG. Pero digámoslo una vez más, porque la definición precisa es importante para la comparación con el ajuste fino que sigue.

Entonces, RAG, o generación aumentada de recuperación, es una técnica que mejora la respuesta de un LLM al recuperar información externa relevante en el momento de la inferencia e inyectarla en el mensaje. El modelo en sí no cambia de ninguna manera. Lo que cambia es lo que ve como entrada.

La tubería se parece a esto:

En primer lugar, los documentos externos (la base de conocimientos que queremos utilizar) se procesan en incrustaciones de vectores y se almacenan en una base de datos de vectores. Cuando un usuario envía una consulta, la consulta también se convierte en una incrustación y los fragmentos de documentos semánticamente más similares se recuperan de la base de datos. Luego, esos fragmentos se pasan al LLM junto con la consulta del usuario, para que el modelo pueda generar una respuesta basada en ese contexto recuperado específico.

Y eso es todo.

A continuación se muestra un ejemplo de RAG mínimo utilizando la API OpenAI:

from openai import OpenAI import numpy as np client = OpenAI(api_key=”your_api_key”) # nuestros pequeños documentos de base de conocimientos = [
“pialgorithms is an AI-powered document management platform.”,
“pialgorithms allows teams to search, extract, and automate document workflows.”,
“pialgorithms was founded in Athens, Greece.”,
]

# incrustar la base de conocimientos def embed(texts): respuesta = client.embeddings.create( model=”text-embedding-3-small”, input=texts ) return [r.embedding for r in response.data]

doc_embeddings = embed(documents) # incrustar la consulta del usuario y recuperar la consulta fragmentada más relevante = “¿Dónde se basan los pialgoritmos?” query_embedding = incrustar([query])[0]

# similitud de coseno def cosine_similarity(a, b): return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)) similitudes = [cosine_similarity(query_embedding, doc_emb) for doc_emb in doc_embeddings]
best_match = documentos[np.argmax(similarities)]

# inyectar el contexto recuperado en la respuesta inmediata = client.chat.completions.create( model=”gpt-4o-mini”, mensajes=[
{
“role”: “system”,
“content”: f”Answer the user’s question using only the following context:\n\n{best_match}”
},
{
“role”: “user”,
“content”: query
}
]
) imprimir(respuesta.opciones[0].message.content) # pialgorithms tiene su sede en Atenas, Grecia.

Tomémonos un momento para entender lo que realmente está sucediendo aquí. Por supuesto, el modelo no tiene idea de qué son los pialgoritmos a partir de su entrenamiento, pero debido a que recuperamos el fragmento de documento correcto y lo inyectamos en el mensaje, el modelo puede responder con precisión. El conocimiento proviene de fuera del modelo, en el momento de la consulta, y el modelo en sí permanece intacto.

Este es el núcleo de lo que hace RAG: le da al modelo acceso a conocimiento externo en el que nunca fue entrenado, dinámicamente, en el momento de la inferencia.

Y según su forma de funcionar, RAG se desempeña bien en tipos específicos de tareas, como por ejemplo:

Responder preguntas sobre documentos, bases de conocimientos o datos que el modelo nunca ha visto Mantenerse actualizado sin volver a capacitarse, ya que la base de conocimientos se puede actualizar de forma independiente en cualquier momento Proporcionar respuestas rastreables y citables, ya que se sabe exactamente qué fragmento de documento se recuperó Manejar información privada o de propiedad exclusiva de forma segura, sin incluir esa información en el modelo

Por otro lado, esto es lo que RAG no hará: no cambiará el comportamiento, el tono, el estilo de razonamiento o el desempeño de la tarea del modelo. Si su modelo tiende a ser detallado, RAG no lo hará más conciso. Si tiene problemas con un formato de salida en particular, RAG no lo solucionará.

¿Qué es el ajuste fino y para qué sirve realmente?

El ajuste es el proceso de tomar un modelo previamente entrenado y continuar entrenándolo en un nuevo conjunto de datos específico de la tarea, actualizando sus pesos en el proceso. Para decirlo de otra manera, mientras RAG cambia las entradas del modelo, el ajuste fino cambia el modelo en sí.

Más específicamente, un modelo base como GPT-4o-mini está preentrenado en un conjunto de datos generales masivo. El ajuste fino toma ese modelo y ejecuta un ciclo de entrenamiento adicional más corto en ejemplos específicos relevantes para nuestro caso de uso específico. Esos ejemplos suelen tener la forma de pares entrada-salida. De esta manera, las ponderaciones del modelo se ajustan para que produzca resultados que se parezcan más a esos pares de ejemplo.

Así es como se vería un trabajo de ajuste utilizando la API OpenAI:

from openai import OpenAI import json client = OpenAI(api_key=”your_api_key”) # Paso 1: preparar los datos de entrenamiento como un archivo JSONL # cada ejemplo es una conversación con el resultado deseado Training_examples = [
{
“messages”: [
{“role”: “system”, “content”: “You are a concise technical assistant. Always respond in one sentence.”},
{“role”: “user”, “content”: “What is a vector database?”},
{“role”: “assistant”, “content”: “A vector database stores and retrieves data as high-dimensional numerical vectors, enabling fast semantic similarity search.”}
]
}, { “mensajes”: [
{“role”: “system”, “content”: “You are a concise technical assistant. Always respond in one sentence.”},
{“role”: “user”, “content”: “What is chunking in RAG?”},
{“role”: “assistant”, “content”: “Chunking is the process of splitting large documents into smaller pieces before embedding them, so they fit within model context limits and improve retrieval precision.”}
]
}, # en la práctica querrías al menos 50-100 ejemplos ]# guardar como JSONL con open(“training_data.jsonl”, “w”) como f: por ejemplo en Training_examples: f.write(json.dumps(example) + “\n”) # cargar el archivo de entrenamiento con open(“training_data.jsonl”, “rb”) como f: Training_file = client.files.create(file=f, propósito=”fine-tune”) # crear el trabajo de ajuste fino fine_tune_job = client.fine_tuning.jobs.create(training_file=training_file.id, model=”gpt-4o-mini-2024-07-18″ ) print(fine_tune_job.id)

Una vez que se completa el trabajo de ajuste, OpenAI devuelve un identificador de modelo único para su modelo recién ajustado, en el formato ft:base-model:your-org:your-suffix:unique-id. Este es ahora un modelo distinto que reside en su cuenta OpenAI, separado del gpt-4o-mini básico.

Al imprimir, obtendríamos una identificación para ese modelo ajustado, con un aspecto similar a este:

ft:gpt-4o-mini-2024-07-18:tu-org:tu-sufijo:abc123

Luego podemos llamarlo exactamente como cualquier otro modelo, simplemente pasando ese identificador en el parámetro del modelo:

# una vez que se complete el trabajo, use el modelo ajustado respuesta = client.chat.completions.create( model=”ft:gpt-4o-mini-2024-07-18:your-org:your-suffix:abc123″, mensajes=[
{“role”: “user”, “content”: “What is prompt caching?”}
]
) imprimir(respuesta.opciones[0].mensaje.contenido)

La diferencia es que este modelo ya ha internalizado el comportamiento en el que lo entrenamos: en nuestro ejemplo, ahora responderá consistentemente en una oración concisa, sin que tengamos que indicarle que lo haga en cada mensaje del sistema. Ese es el tipo de cosas en las que el ajuste es realmente bueno: formato consistente, tono específico, adherencia a una estructura de salida particular o rendimiento mejorado en un tipo de tarea muy específico. Y eso, en esencia, es lo que hace el ajuste fino.

Observe cómo el ajuste fino no tiene ningún impacto en la incorporación de información específica en el modelo. A diferencia de lo que uno podría suponer intuitivamente, ajustar un modelo en los documentos de su empresa no hará que el modelo “aprenda” esa información y sea capaz de responder preguntas sobre ella de manera confiable. De hecho, puede resultar en que el modelo memorice hechos específicos de ejemplos de entrenamiento aquí y allá, pero esta memorización es frágil y poco confiable. El resultado más probable sería un modelo que alucina sobre temas que aparecen en los ejemplos de capacitación, en lugar de un modelo que recuerda con precisión detalles específicos que aparecen en esos ejemplos. Por lo tanto, si lo que necesita es recuperar conocimientos, RAG es la herramienta adecuada, no un ajuste fino.

Más específicamente, el ajuste fino funciona bien en lo siguiente:

“Enseñar” al modelo un formato, tono o estilo de salida coherente. Mejorar el rendimiento en un tipo de tarea específico y limitado (por ejemplo, generar siempre JSON válido, resumir siempre en tres viñetas, etc.) Reducir la necesidad de indicaciones largas y repetitivas del sistema integrando esas instrucciones en el modelo. Adaptar el modelo a un lenguaje o terminología de dominio específico, para que comprenda y utilice el vocabulario correcto.

Sin embargo, el ajuste fino no funciona tan bien en:

Al agregar conocimiento fáctico confiable, el modelo puede recordar con precisión Mantener el modelo actualizado con información cambiante Proporcionar respuestas rastreables y citables

Entonces, ¿cuándo usamos cada uno y cuándo usamos ambos?

Ahora que entendemos lo que realmente hace cada técnica, la pregunta “RAG versus ajuste fino” se vuelve mucho más fácil de responder, porque en la mayoría de los casos no es realmente una pregunta del tipo “vs”.

RAG y el ajuste fino operan en diferentes capas de una aplicación de IA. RAG opera en la capa de conocimiento, lo que significa que controla a qué información tiene acceso el modelo. Por otro lado, el ajuste fino opera en la capa de comportamiento, lo que significa que define la forma en que el modelo procesa la información proporcionada y genera respuestas. Estas dos capas son independientes entre sí, lo que significa que puede usar RAG, ajuste fino o ambos, dependiendo de lo que intente lograr.

Entonces, aquí hay un marco de decisión práctico para decidir qué usar:

El escenario en el que utilizamos tanto RAG como ajuste fino es en realidad el más común en los sistemas de producción reales. La forma más sencilla de mantener las dos cosas claras es ésta: ajustar el comportamiento, utilizar RAG para el conocimiento.

Imaginemos, por ejemplo, que estamos creando un asistente de atención al cliente para un producto de software y lo necesitamos para:

Responder siempre en un tono y formato específico, consistente con nuestra marca de software. Tener conocimiento preciso y actualizado de la documentación de nuestro producto.

Para tal tarea, necesitaríamos utilizar tanto RAG como ajuste. En particular, el ajuste manejaría el primer requisito al permitir que el modelo aprenda de ejemplos de respuestas ideales de atención al cliente, enseñándole el tono correcto, el nivel correcto de detalle y el formato de salida correcto. El segundo requisito lo cubriría RAG: en el momento de la inferencia, la información más relevante de la documentación del producto se recupera y se inyecta en el mensaje, lo que permite que el modelo proporcione respuestas confiables basadas en la documentación.

Entonces, en la práctica, podemos combinar el ajuste fino y RAG llamando a un modelo ajustado de la misma manera que llamaríamos a cualquier otro modelo, pero también inyectar el contexto recuperado en el indicador del sistema, exactamente como lo haríamos en una canalización RAG estándar.

# combinando un modelo ajustado con respuesta RAG = client.chat.completions.create( model=”ft:gpt-4o-mini-2024-07-18:your-org:support-style:abc123″, # ajustado para mensajes de tono/formato=[
{
“role”: “system”,
“content”: f”You are a helpful support assistant for pialgorithms. ”
f”Use only the following documentation to answer:\n\n{retrieved_context}” # RAG context
},
{
“role”: “user”,
“content”: user_question
}
]
)

El ajuste fino hace que el modelo sepa cómo responder adecuadamente y RAG le dice qué decir. Por lo tanto, esta no es una cuestión de “ajuste versus RAG”, sino que el ajuste y RAG se complementan entre sí y hacen cosas diferentes.

en mi mente

Lo que encuentro más interesante sobre el debate entre RAG y el ajuste fino es la frecuencia con la que se formula como una pregunta sobre qué técnica es mejor, cuando la pregunta más útil es qué problema se está intentando resolver realmente.

RAG y el ajuste fino abordan diferentes modos de falla de un LLM base. Si un modelo base falla porque no sabe algo, eso es un problema de conocimiento y RAG lo resuelve. Si un modelo base falla porque se comporta de manera inconsistente o produce resultados en el formato incorrecto, eso es un problema de comportamiento y el ajuste fino lo resuelve. Si su modelo falla por ambas razones a la vez, es posible que realmente necesite ambas.

✨ ¡Gracias por leer! ✨

Si llegó hasta aquí, es posible que le resulten útiles los pialgoritmos: una plataforma que hemos estado creando y que ayuda a los equipos a gestionar de forma segura el conocimiento organizacional en un solo lugar.

¿Te encantó esta publicación? Únase a mí en 💌 Substack y 💼 LinkedIn

Todas las imágenes del autor, salvo que se indique lo contrario.