· NERVICO · inteligencia-artificial  · 13 min read

RAG para documentación técnica interna: implementación paso a paso

Guía práctica para implementar un sistema RAG sobre tu codebase y documentación interna: arquitectura, bases de datos vectoriales, estrategias de chunking y patrones de implementación.

Guía práctica para implementar un sistema RAG sobre tu codebase y documentación interna: arquitectura, bases de datos vectoriales, estrategias de chunking y patrones de implementación.

La documentación técnica interna de la mayoría de empresas de software tiene dos problemas. El primero es que está desactualizada. El segundo es que nadie la encuentra. Los nuevos desarrolladores pasan días buscando cómo funciona un sistema. Los senior responden las mismas preguntas una y otra vez. Y cuando alguien actualiza la documentación, el conocimiento ya ha cambiado.

Un sistema RAG (Retrieval-Augmented Generation) sobre tu documentación técnica interna y tu codebase puede resolver estos problemas. No porque la IA sea mágica, sino porque combina búsqueda semántica (encontrar la información correcta) con generación de lenguaje natural (explicarla de forma útil). El resultado es un asistente que entiende tu código, tu documentación y tus procesos internos.

Este artículo explica cómo construir un sistema RAG para documentación técnica paso a paso: qué arquitectura necesitas, cómo procesar tu código y documentación, qué base de datos vectorial elegir, cómo optimizar la calidad de las respuestas y qué errores evitar.

Por qué RAG para documentación técnica

El problema que resuelve

Cada equipo de desarrollo acumula conocimiento en múltiples fuentes:

  • Código fuente: La verdad última sobre cómo funciona el sistema
  • Documentación: READMEs, wikis, Confluence, Notion
  • PRs y commits: Decisiones de diseño, contexto de cambios
  • Mensajes de Slack/Teams: Explicaciones informales, decisiones rápidas
  • Tickets de Jira/Linear: Requisitos, bugs, decisiones de producto

Un desarrollador nuevo que necesita entender cómo funciona el sistema de autenticación tiene que buscar en todas estas fuentes. Un senior que sabe la respuesta podría responder en 2 minutos, pero interrumpir a un senior cada vez que alguien tiene una pregunta no escala.

RAG centraliza el acceso a este conocimiento distribuido. Un desarrollador pregunta “cómo funciona la autenticación con OAuth en nuestro sistema” y obtiene una respuesta basada en el código real, la documentación actual y las decisiones de diseño documentadas en PRs.

Por qué no vale con solo un chat de IA

Un modelo de lenguaje como Claude o GPT no conoce tu código ni tu documentación. Si le preguntas sobre tu sistema de autenticación, inventará una respuesta genérica basada en cómo funcionan los sistemas de autenticación en general.

RAG resuelve esto en dos pasos:

  1. Retrieval: Busca en tu documentación y código los fragmentos relevantes a la pregunta
  2. Generation: Pasa esos fragmentos al modelo de lenguaje junto con la pregunta para generar una respuesta fundamentada

El modelo no inventa. Responde basándose en tus datos reales.

Arquitectura de un sistema RAG para documentación técnica

Los componentes fundamentales

┌──────────────────────────────────────────────────────────┐
│                    Pipeline de ingestión                   │
│                                                            │
│  Código fuente ──┐                                        │
│  Documentación ──┼──► Chunking ──► Embeddings ──► Vector DB│
│  PRs/Commits ────┤                                        │
│  Wiki/Confluence ─┘                                        │
└──────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────┐
│                    Pipeline de consulta                    │
│                                                            │
│  Pregunta ──► Embedding ──► Búsqueda vectorial ──►        │
│              Fragmentos relevantes + Pregunta ──► LLM ──► │
│              Respuesta con fuentes                         │
└──────────────────────────────────────────────────────────┘

Componente 1: Pipeline de ingestión

Procesa tus fuentes de información y las convierte en embeddings almacenados en una base de datos vectorial. Este pipeline se ejecuta de forma periódica (cada commit, cada noche, o bajo demanda) para mantener los datos actualizados.

Componente 2: Base de datos vectorial

Almacena los embeddings y permite búsqueda por similitud semántica. Cuando un desarrollador hace una pregunta, el sistema convierte la pregunta en un embedding y busca los fragmentos más similares.

Componente 3: Pipeline de consulta

Recibe la pregunta, busca los fragmentos relevantes, los combina con la pregunta en un prompt y envía todo al modelo de lenguaje para generar la respuesta.

Componente 4: Interfaz

Donde los desarrolladores hacen preguntas. Puede ser un chat integrado en Slack, una extensión de VS Code, una interfaz web o un endpoint de API.

Paso 1: preparar las fuentes de datos

Código fuente

El código es la fuente de verdad más importante pero también la más difícil de procesar para RAG. El desafío es que el código tiene estructura (funciones, clases, módulos) que no se puede dividir arbitrariamente.

Estrategia de procesamiento:

# Ejemplo conceptual de procesamiento de código
# Extraer funciones y clases como unidades semánticas

import ast

def extract_code_units(file_path: str) -> list[dict]:
    """Extrae funciones y clases como unidades de documentación."""
    with open(file_path) as f:
        tree = ast.parse(f.read())

    units = []
    for node in ast.walk(tree):
        if isinstance(node, (ast.FunctionDef, ast.ClassDef)):
            unit = {
                'type': type(node).__name__,
                'name': node.name,
                'file': file_path,
                'line_start': node.lineno,
                'docstring': ast.get_docstring(node) or '',
                'source': ast.get_source_segment(
                    open(file_path).read(), node
                ),
            }
            units.append(unit)
    return units

Qué incluir:

  • Funciones y clases con su docstring y código
  • Archivos de configuración (con comentarios explicativos)
  • Tests (revelan cómo se espera que funcione el código)
  • Esquemas de base de datos

Qué excluir:

  • Archivos generados automáticamente
  • Dependencias (node_modules, vendor)
  • Archivos binarios
  • Código de terceros que no has modificado

Documentación

La documentación es más fácil de procesar pero suele estar desactualizada. La estrategia principal es mantener metadata de cuándo se actualizó cada documento para ponderar la relevancia.

Fuentes comunes:

  • Markdown/MDX en el repositorio
  • Confluence/Notion exportado
  • Archivos README
  • Runbooks de operaciones
  • ADRs (Architecture Decision Records)

Pull requests y commits

Los PRs y commits contienen contexto valioso que no existe en ningún otro sitio: por qué se tomó una decisión, qué alternativas se consideraron, qué limitaciones existían.

# Ejemplo de extracción de contexto de PRs
def process_pull_request(pr: dict) -> dict:
    """Procesa un PR para extracción de conocimiento."""
    return {
        'title': pr['title'],
        'description': pr['body'],
        'files_changed': [f['filename'] for f in pr['files']],
        'comments': [c['body'] for c in pr['comments']],
        'date': pr['merged_at'],
        'author': pr['user']['login'],
        'metadata': {
            'type': 'pull_request',
            'number': pr['number'],
            'url': pr['html_url'],
        }
    }

Paso 2: estrategias de chunking

Por qué el chunking importa

El chunking es cómo divides tu documentación en fragmentos. Es el factor más importante en la calidad de un sistema RAG, y es donde la mayoría de implementaciones fallan.

Chunking demasiado pequeño: El fragmento no contiene suficiente contexto para ser útil. “returns user” no dice nada sin saber qué función es y en qué servicio está.

Chunking demasiado grande: El fragmento contiene demasiada información irrelevante. Un archivo de 500 líneas donde solo 10 son relevantes diluye la señal.

Estrategias de chunking para código

Por unidad semántica: Cada función, clase o módulo es un chunk. Es la estrategia más efectiva para código porque respeta la estructura lógica.

# Chunk = función completa con contexto
{
    'content': '''
    # File: src/services/auth.py
    # Class: AuthService

    def validate_token(self, token: str) -> User:
        """Validates JWT token and returns the associated user.

        Args:
            token: JWT token string

        Returns:
            User object if token is valid

        Raises:
            InvalidTokenError: If token is expired or malformed
        """
        try:
            payload = jwt.decode(token, self.secret_key, algorithms=['HS256'])
            user = self.user_repo.find_by_id(payload['user_id'])
            if not user:
                raise InvalidTokenError('User not found')
            return user
        except jwt.ExpiredSignatureError:
            raise InvalidTokenError('Token expired')
    ''',
    'metadata': {
        'file': 'src/services/auth.py',
        'class': 'AuthService',
        'function': 'validate_token',
        'type': 'code',
    }
}

Por sección con overlap: Para documentos largos, divide por secciones (headers en markdown) con un overlap de 2-3 párrafos. El overlap garantiza que el contexto no se pierde en los límites de los chunks.

Estrategias de chunking para documentación

Por sección de heading: Divide el documento en secciones definidas por los headers H2/H3. Cada sección mantiene el título del documento y la jerarquía de headers como contexto.

def chunk_markdown(content: str, file_path: str) -> list[dict]:
    """Divide un archivo markdown en chunks por secciones."""
    sections = split_by_headers(content)
    chunks = []

    for section in sections:
        chunk = {
            'content': f"# {get_document_title(content)}\n\n"
                      f"## {section['heading']}\n\n"
                      f"{section['content']}",
            'metadata': {
                'file': file_path,
                'section': section['heading'],
                'type': 'documentation',
                'last_updated': get_file_date(file_path),
            }
        }
        chunks.append(chunk)

    return chunks

Tamaño recomendado de chunks

Tipo de contenidoTamaño recomendadoOverlap
Código (funciones)50-200 líneasNo necesario
Código (clases)100-500 líneasNo necesario
Documentación500-1500 tokens100-200 tokens
PRs/commitsCompleto (sin dividir)N/A
FAQsPregunta + respuesta completaN/A

Paso 3: elegir la base de datos vectorial

Opciones disponibles

Base de datosTipoPrecioMejor para
PineconeManagedDesde $0 (free tier)Equipos que quieren gestión cero
WeaviateSelf-hosted o managedOpen source / managedEquipos que necesitan búsqueda híbrida
QdrantSelf-hosted o managedOpen source / managedAlto rendimiento, buen filtrado
ChromaSelf-hostedOpen sourcePrototipado rápido, proyectos pequeños
pgvectorExtensión PostgreSQLIncluido en PostgreSQLEquipos que ya usan PostgreSQL

Recomendación por caso

Para empezar rápido: Chroma. Se instala con pip, no necesita infraestructura y funciona bien para prototipos y equipos pequeños (menos de 100.000 documentos).

Para producción con gestión mínima: Pinecone. Managed, escala automáticamente y tiene un free tier generoso. La desventaja es vendor lock-in.

Para equipos que ya usan PostgreSQL: pgvector. No necesitas otra base de datos. La calidad de búsqueda es buena para volúmenes moderados y la integración con tu stack existente es inmediata.

Para alto rendimiento y control: Qdrant o Weaviate. Ambos ofrecen búsqueda híbrida (vectorial + keyword), filtrado avanzado y control total sobre la infraestructura.

Paso 4: generar embeddings

Modelos de embedding

El modelo de embedding convierte texto en vectores numéricos que capturan el significado semántico. La elección del modelo afecta directamente a la calidad de búsqueda.

Opciones principales:

  • OpenAI text-embedding-3-large: Buena calidad general, fácil de usar, coste por uso
  • Cohere embed-v3: Buen rendimiento en búsqueda, soporta múltiples idiomas
  • Voyage AI: Modelos especializados para código (voyage-code-3) con rendimiento superior en búsqueda de código
  • Modelos open source (nomic-embed, BGE): Sin coste de API, requieren infraestructura para hosting

Recomendación para documentación técnica: Voyage AI para código y OpenAI para documentación en lenguaje natural. Si necesitas un solo modelo para ambos, OpenAI text-embedding-3-large es el mejor equilibrio.

# Ejemplo de generación de embeddings
from openai import OpenAI

client = OpenAI()

def generate_embedding(text: str) -> list[float]:
    """Genera un embedding para un fragmento de texto."""
    response = client.embeddings.create(
        input=text,
        model="text-embedding-3-large"
    )
    return response.data[0].embedding

Optimización de embeddings para código

El código tiene características especiales que requieren tratamiento:

  • Incluye contexto en el chunk: No hagas embedding de una función aislada. Incluye el nombre del archivo, la clase y el docstring
  • Normaliza nombres de variables: Los nombres crípticos (x, tmp, foo) reducen la calidad semántica
  • Separa código de comentarios: Genera embeddings adicionales para los comentarios por separado, vinculados al chunk de código

Paso 5: implementar el pipeline de consulta

Búsqueda con reranking

La búsqueda vectorial pura devuelve los chunks más similares semánticamente a la pregunta. Pero la similitud semántica no siempre equivale a relevancia. Un reranker mejora los resultados ordenando los chunks recuperados por relevancia real.

# Pipeline de consulta con reranking
def query_rag(question: str, top_k: int = 10, final_k: int = 5):
    """Pipeline completo de consulta RAG."""

    # 1. Generar embedding de la pregunta
    query_embedding = generate_embedding(question)

    # 2. Búsqueda vectorial: recuperar candidatos
    candidates = vector_db.search(
        vector=query_embedding,
        limit=top_k
    )

    # 3. Reranking: ordenar por relevancia real
    reranked = reranker.rank(
        query=question,
        documents=[c['content'] for c in candidates]
    )

    # 4. Seleccionar los top-k finales
    top_chunks = reranked[:final_k]

    # 5. Generar respuesta con LLM
    context = "\n\n---\n\n".join([c['content'] for c in top_chunks])

    response = llm.generate(
        prompt=build_prompt(question, context),
        model="claude-sonnet-4"
    )

    return {
        'answer': response,
        'sources': [c['metadata'] for c in top_chunks]
    }

El prompt del sistema

El prompt que envías al LLM determina la calidad de las respuestas. Un prompt efectivo para documentación técnica:

Eres un asistente técnico que responde preguntas sobre la
documentación y el código de [nombre del proyecto].

Reglas:
1. Responde SOLO basándote en los fragmentos proporcionados
2. Si la información no está en los fragmentos, di "No tengo
   información suficiente para responder"
3. Cita siempre el archivo fuente de la información
4. Si el código mostrado difiere de la documentación, prioriza
   el código (es la fuente de verdad)
5. Incluye ejemplos de código cuando sea relevante

Fragmentos de contexto:
{context}

Pregunta del usuario:
{question}

Búsqueda híbrida

Para documentación técnica, la búsqueda puramente semántica no es suficiente. Un desarrollador que busca “JWT validation” necesita una coincidencia exacta de keywords además de similitud semántica.

La búsqueda híbrida combina:

  • Búsqueda vectorial: Para preguntas en lenguaje natural (“cómo funciona la autenticación”)
  • Búsqueda por keywords: Para términos técnicos específicos (“JWT”, “AuthService”, “validate_token”)

Weaviate y Qdrant soportan búsqueda híbrida nativa. Con pgvector, puedes combinar búsqueda vectorial con full-text search de PostgreSQL.

Paso 6: mantener el sistema actualizado

Pipeline de actualización

El mayor riesgo de un sistema RAG es que los datos se desactualicen. Un RAG con documentación obsoleta es peor que no tener RAG, porque genera respuestas incorrectas con alta confianza.

Estrategia recomendada:

  • Código: Reindexar en cada merge a la rama principal. Usar un hook de CI/CD
  • Documentación: Reindexar cuando cambia un archivo. Usar file watchers o webhooks
  • PRs: Indexar cuando se mergean
  • Versiones de documentos: Mantener metadata de fecha de última actualización y mostrarla en las respuestas

Evaluación de calidad

Mide la calidad de tu sistema RAG periódicamente:

  • Relevancia de retrieval: De los chunks recuperados, qué porcentaje es relevante para la pregunta
  • Exactitud de respuestas: Las respuestas generadas son correctas según la documentación
  • Cobertura: Qué porcentaje de preguntas puede responder el sistema (vs “no tengo información”)
  • Latencia: Tiempo desde la pregunta hasta la respuesta

Un conjunto de preguntas de evaluación (50-100 preguntas con respuestas conocidas) permite medir estas métricas de forma consistente.

Errores comunes

Error 1: chunks demasiado pequeños

Si divides el código línea por línea o la documentación en frases individuales, los chunks no tienen suficiente contexto. El retrieval devuelve fragmentos que son técnicamente similares pero inútiles para responder la pregunta.

Error 2: no incluir metadata

Sin metadata (archivo fuente, fecha, tipo de contenido), el sistema no puede filtrar por relevancia ni citar fuentes. La metadata es tan importante como el contenido.

Error 3: ignorar la calidad del embedding

No todos los modelos de embedding son iguales para código. Un modelo optimizado para texto general puede producir embeddings de baja calidad para código. Usa modelos especializados cuando sea posible.

Error 4: no evaluar periódicamente

La calidad de un sistema RAG se degrada con el tiempo si no se mantiene. Los cambios en el código, la nueva documentación y la evolución del proyecto requieren reindexación y ajuste.

Error 5: esperar perfección desde el día uno

Un sistema RAG es un producto iterativo. La primera versión no será perfecta. Lanza con un subconjunto de datos (el código más consultado, la documentación más importante) y expande basándote en feedback real.

Coste de implementación

Costes iniciales

ComponenteCoste estimado
Desarrollo del pipeline2-4 semanas de ingeniería
Base de datos vectorial$0-100/mes (según volumen)
Modelo de embedding$10-50/mes (según volumen)
LLM para generación$50-200/mes (según consultas)
Interfaz de usuario1-2 semanas de desarrollo

Coste operativo mensual

Para un equipo de 20 desarrolladores con un codebase de 200.000 líneas y documentación moderada:

  • Base de datos vectorial: $25-50/mes
  • Embeddings: $15-30/mes (reindexación semanal)
  • LLM: $100-300/mes (según volumen de consultas)
  • Infraestructura: $20-50/mes
  • Total: $160-430/mes

El ROI se justifica si el sistema ahorra al equipo más de 10-15 horas al mes en búsqueda de documentación e interrupciones a senior developers.

Conclusión

Un sistema RAG sobre tu documentación técnica interna no es un proyecto trivial, pero tampoco requiere un equipo de IA dedicado. Con las herramientas disponibles en 2026, un ingeniero backend puede implementar un sistema funcional en 2-4 semanas.

La clave del éxito está en tres factores:

  1. Calidad del chunking: Respeta la estructura semántica de tu código y documentación. No dividas arbitrariamente.
  2. Mantenimiento continuo: Un RAG desactualizado es peor que no tener RAG. Automatiza la reindexación.
  3. Evaluación periódica: Mide la calidad con preguntas de evaluación y ajusta basándote en datos reales.

El resultado es un asistente que conoce tu codebase, tu documentación y tus decisiones de diseño. No reemplaza la comunicación entre desarrolladores, pero reduce las interrupciones por preguntas rutinarias y acelera significativamente el onboarding de nuevos miembros del equipo.


¿Quieres implementar un sistema RAG sobre tu documentación técnica?

En NERVICO ayudamos a equipos de desarrollo a construir sistemas de conocimiento con IA:

  • Diseño de arquitectura RAG: Definimos la arquitectura correcta para tu volumen de datos y equipo
  • Implementación de agentes de IA: Construimos el pipeline completo de ingestión, búsqueda y generación
  • Integración con tu stack: Conectamos el sistema con Slack, VS Code o la interfaz que tu equipo prefiera

Solicitar auditoría gratuita — Evaluaremos tu documentación y codebase para diseñar un sistema RAG que aporte valor real a tu equipo.

Back to Blog

Related Posts

View All Posts »