Autores: @hi_im_isaac_, @learnwdaniel, @gaozenghao
nota: la versión interactiva del blog técnico completo está disponible en: https://www.cerebras.ai/blog/how-we-built-our-knowledge-base
Los empleados hacen más de 15,000 preguntas al día a nuestra base de conocimiento interna. Desde su lanzamiento hace tres meses, se ha convertido en una de las herramientas internas más adoptadas en la empresa. La usan personas, automatizaciones y agentes.
En Cerebras, nuestros equipos trabajan en operaciones de centros de datos, diseño de chips, hardware, entrenamiento, inferencia, plataforma en la nube y más. Con cientos de nuevos empleados cada año, nuestros canales de comunicación se llenaban de las mismas preguntas:
- «¿Dónde encuentro X?»
- «¿Quién es el experto en Y?»
- «¿Qué es Z?»

Creamos Cerebras Knowledge para ayudar a las personas a conectar a otras personas y sistemas con información útil.
Conectando con los datos donde viven
Encontrar información dentro de una organización es difícil. Los datos están dispersos en varias herramientas, y cada trimestre alguien propone la misma solución brillante: registrar todo en una única plataforma para que toda la información esté en un solo lugar. El sueño de una única fuente de verdad, por supuesto, rara vez funciona en la práctica.
La información se genera donde sea más conveniente y ergonómico: ediciones sugeridas en un documento, hilos en Slack, referencias de código en GitHub y metadatos de estado en Jira. Estas plataformas están diseñadas a medida para sus dominios específicos, optimizadas tras años de ingeniería de producto y análisis. Discutir una solicitud de cambio en Google Docs sería una experiencia terrible.
Por eso nos propusimos diseñar un sistema que requiriera cambios mínimos en el comportamiento existente. En el lado de la recolección de datos, esto significaba extraer datos directamente de cada plataforma.
Anatomía de una base de conocimiento
Nuestra base de conocimiento ofrece tres cosas:
- Una plataforma para recolectar y almacenar datos internos.
- Una plataforma para consultar esos datos.
- Una capa que aplica autenticación y autorización, con auditoría y análisis.
En el núcleo hay una sola tabla de Postgres que contiene embeddings, resúmenes en bruto y metadatos de muchas fuentes. El sistema ingiere datos continuamente de toda la empresa y mantiene un almacén de datos listo para consultas.
Queríamos una interfaz de datos simple pero que funcionara con la mayoría de los formatos de datos. También queríamos que otros desarrolladores en Cerebras pudieran crear conectores personalizados. El resultado es deliberadamente simple: cada fuente, desde hilos de Slack hasta netlists, llega a la misma tabla de embeddings, y cualquier cosa en esa tabla es inmediatamente consultable a través de la misma interfaz:

Cada fuente de datos define qué son los datos, cómo conectarse a ellos y con qué frecuencia deben obtenerse. Cada fila de embedding resultante sigue la misma interfaz, independientemente de si proviene de Slack, un repositorio de código, un sistema de documentos o una base de datos personalizada.
Cómo procesamos conversaciones no estructuradas de Slack
Slack era la fuente de datos más importante para la que teníamos que diseñar. Es donde ocurren las discusiones de ingeniería más actualizadas en toda la empresa.

Inicialmente probamos si los simples embeddings sobre texto sin procesar rendían lo suficiente. Rápidamente nos dimos cuenta de que la búsqueda vectorial por sí sola era insuficiente para encontrar todos los datos relevantes.
Los mensajes de Slack presentan varios desafíos:
- La densidad de información varía enormemente: «hey, sí, claro, Mike» y una explicación detallada del kernel son ambos mensajes.
- Las longitudes de los mensajes varían, y los mensajes más cortos suelen superar a los más largos y detallados en similitud coseno.
- El significado de un mensaje a menudo depende de la conversación circundante.
Necesitábamos un enfoque híbrido. Construimos la ingesta de Slack para que cada hilo sea recuperable a través de varias técnicas de búsqueda a la vez, donde cada técnica compensa las debilidades de las demás:
- La búsqueda de texto completo captura los tokens exactos que los embeddings difuminan: cadenas de error, nombres de flags, nombres de host. Cuando un ingeniero pega un mensaje de error literal, una coincidencia léxica exacta es casi siempre la mejor evidencia, y ninguna cantidad de similitud semántica debería superarla.
- La búsqueda por embeddings captura las paráfrasis. La persona que pregunta «restore hangs after manifest load» y la que respondió «checkpoint stalls on the NFS mount» quizás nunca compartan vocabulario. La similitud vectorial es lo que conecta una pregunta con una respuesta escrita en palabras diferentes.(1)
- La frecuencia inversa de documento separa la señal del ruido. Un mensaje corto construido en torno a tokens raros, como un flag de configuración oscuro, merece clasificarse alto. «¡suena bien, gracias!» está cerca de muchas consultas en el espacio de embeddings, pero puntúa casi cero una vez que se tiene en cuenta la rareza de los términos.
- La decadencia por antigüedad codifica que las respuestas de Slack caducan. Dos hilos pueden responder a la misma pregunta, y el de hace seis meses puede describir una infraestructura que ya no existe. Cuando la relevancia es igual por lo demás, gana el hilo más nuevo.

Ningún puntuador individual es confiable por sí solo. Cada técnica produce su propia vista clasificada del mismo corpus, y esas vistas se fusionan en el momento de la consulta (véase Reordenamiento).
Modo Socket
Para recolectar datos en tiempo real, instalamos un bot de Slack en nuestro espacio de trabajo y lo ejecutamos en Modo Socket. Slack nos envía cada evento de mensaje a través de un WebSocket persistente, por lo que recibimos actualizaciones en tiempo real sin tener que sondeando la API web y quemar sus límites de tasa.
Cuando llega un evento, lo reconocemos inmediatamente, lo desduplicamos usando el ID de evento estable y marcamos el mensaje para el consumidor de ingesta.
El consumidor de ingesta no guarda un mensaje nuevo de forma aislada. Resuelve el hilo al que pertenece el mensaje y vuelve a obtener toda la conversación, incluido el mensaje padre y todas las respuestas, desde la API de Slack. Luego escribe todo el hilo de vuelta como una sola fila. Una respuesta a un hilo existente, por lo tanto, vuelve a traer el padre y todos los hermanos, de modo que el contenido almacenado, la lista de participantes y la marca de tiempo de última actividad siempre reflejen la conversación completa.
Cada canal de Slack en nuestro sistema tiene su propia fuente de datos. Esto proporciona un ajuste fino para la frescura de los datos. Un equipo puede optar por ingerir un canal de incidentes ocupado con más frecuencia, por ejemplo.
Hilos y mensajes
El texto bruto de Slack es buscable por palabras clave tan pronto como llega porque mantenemos un índice de texto completo (GIN) de Postgres sobre el contenido bruto. Sin embargo, para habilitar una búsqueda vectorial útil, hacemos un procesamiento adicional.(8)
Durante la destilación, un LLM extrae datos estructurados del hilo completo:
- Una pregunta de una línea que un ingeniero buscaría realmente.
- Un resumen breve.
- La resolución.
- Los sistemas y referencias de código mencionados.

Incoporamos estos puntos de datos y los escribimos en la tabla de embeddings compartida. La transcripción original no se incopora directamente. En nuestros experimentos, la precisión aumentó significativamente cuando el hilo se normalizó en un formato consistente.(7,9) Los metadatos adicionales también le dan a la coincidencia semántica una señal más útil.
Ráfagas
En este punto, la búsqueda en Slack era buena, pero seguíamos encontrando el mismo problema: los mensajes importantes dentro de hilos largos no siempre estaban representados en el resumen a nivel de hilo.
Para aumentar la señal de los mensajes individuales, usamos ráfagas. Una ráfaga es una secuencia de mensajes consecutivos del mismo autor. Incoporamos ráfagas individuales con el tema del hilo antepuesto como contexto(2) porque a veces la respuesta vive en un mensaje tangente cuyo vocabulario nunca llega al resumen del hilo. Los embeddings de ráfagas hacen que ese mensaje sea encontrable por sí mismo.
Para evitar que los datos de baja señal lleguen a la base de datos, cada ráfaga se puntúa contra una combinación ponderada de señales y debe superar un umbral antes de ser incrustada:
- Contiene un token relativamente raro en el corpus, con un IDF de al menos 4.0.
- La ráfaga combinada tiene al menos 200 caracteres.
- Uno o más mensajes de la ráfaga contienen reacciones, lo que proporciona un impulso social.

Después de la destilación, las ráfagas que califican se incrustan y almacenan en la tabla de embeddings junto con el registro a nivel de hilo.
Repositorios de código
Inicialmente debatimos si era necesario incrustar repositorios de código. Con el auge de Claude Code y otras herramientas de línea de comandos, crear incrustaciones de código parecía contradictorio cuando parecía que «grep es todo lo que necesitas». Después de hablar con otros en la industria y leer los hallazgos de Cursor sobre la búsqueda semántica en grandes bases de código, decidimos intentarlo.
Tenemos muchos repositorios internos, algunos de más de 40 GB. Nuestra principal preocupación era cómo mantenerlos actualizados de manera eficiente.
Uso de @cocoindex_io para mantener incrustaciones de código
Después de varios experimentos, nos decidimos por CocoIndex, un marco de código abierto para incrustar documentos que se especializa en vectorizar bases de código.
Para cada repositorio, dividimos el código usando límites de expresiones regulares específicos del lenguaje, ordenados de grueso a fino. El divisor intenta primero los límites de nivel superior, como las clases. Si el fragmento resultante sigue siendo demasiado grande, recurre a los límites de métodos y luego a bloques más pequeños. Incrustamos los fragmentos resultantes y escribimos los vectores en Postgres. Un solo archivo puede generar múltiples incrustaciones a diferentes niveles de especificidad, como registros a nivel de archivo y a nivel de función.

CocoIndex rastrea los metadatos de sincronización en Postgres. En cada commit, vuelve a incrustar y exportar solo los fragmentos de código modificados, en lugar de volver a calcular todo el repositorio. Esto funcionó especialmente bien para nosotros porque el estado de sincronización y el almacén de incrustaciones viven en la misma base de datos.
A medida que crecía el número de bases de código, trasladamos la incorporación de repositorios a archivos de configuración que los equipos pueden enviar por sí mismos, incluyendo listas de permitidos y denegados a nivel de ruta de archivo.
Fuentes de datos personalizadas
Algunos equipos ya tenían sus propias bases de datos y no querían mover datos a Slack o a un sistema de documentos solo para participar en la base de conocimiento. Querían la misma superficie de consulta sobre sus tablas existentes.
Para apoyar esto, tratamos las fuentes personalizadas como scripts de plugin. Un equipo abre una solicitud de cambio con un pequeño módulo de Python que sabe cómo leer desde su sistema y emitir filas con la forma de nuestra tabla de embeddings, más una entrada de fuente de datos correspondiente.
Mientras el script escriba en la base de datos compartida usando el mismo esquema que cualquier otra fila de embedding, el resto de la pila funciona sin cambios. Los datos se vuelven consultables junto con Slack, código y documentos, sin necesidad de un manejo especial en ningún otro lugar del sistema.
Planificación y distribución de herramientas
Para cada consulta, primero ejecutamos una pasada de planificación corta donde un LLM decide qué herramientas y fuentes de datos probablemente importan. Las principales herramientas:
- subsystem_index: resúmenes por archivo de LLM.
- search: el pipeline vectorial unificado a través de Slack, wiki, código y otras fuentes indexadas, fusionado y reordenado internamente.
- search_slack: recuperación directa de Slack.
- search_code: ripgrep sobre repositorios fuente.
- recent_prs: solicitudes de cambio recientes relevantes para la pregunta.
- who_knows: personas con experiencia demostrada en un tema.
El planificador trabaja sobre una descripción compacta de lo que tenemos indexado: qué proyectos existen, qué fuentes están disponibles en cada proyecto y para qué sirve cada fuente. Dada la consulta del usuario y el ámbito activo, emite selecciones de herramientas que el ejecutor distribuye en paralelo, normaliza en un formato de evidencia común y pasa a un LLM de síntesis final.(4)

Reordenamiento
Un documento puede aparecer cerca de la parte superior simplemente porque comparte vocabulario con la consulta mientras responde a una pregunta diferente. Antes de reordenar, combinamos las listas de resultados incompatibles de los recuperadores con fusión de rango recíproco, o RRF. Para cada documento, añadimos peso / (60 + rango) por cada lista en la que aparece, con un peso predeterminado de 1.0 y una constante de suavizado de 60.

La constante de suavizado hace que el consenso importe más que un solo voto fuerte: un documento que aparece cerca de la parte superior en varios recuperadores puede vencer a uno que ocupa el primer lugar en solo uno de ellos. Luego fusionamos los fragmentos duplicados de vuelta a una fuente, limitamos cuántos resultados puede aportar cada archivo y terminamos con un top veinte más diverso.
Enviamos la consulta original y esos candidatos a un modelo de reordenamiento pequeño. Asigna a cada documento una puntuación de cero a diez, y nos quedamos con los diez mejores.(6)
Una vez que la clasificación es final, añadimos contexto de vuelta a los ganadores. Por ejemplo, si coincidimos con una sección de la wiki, traemos las dos secciones vecinas para que no se pierdan el encabezado, las condiciones previas y las advertencias que la división en fragmentos separó. Esto le da a los lectores un fragmento completo en lugar de un párrafo solitario que carece de contexto importante.
Por lo tanto, la salida de la búsqueda es un paquete rico de evidencia: resultados fusionados de diferentes recuperadores, desduplicados a nivel de fuente, reordenados contra la pregunta real, y solo entonces expandidos con contexto circundante.
MCP
En la integración MCP, exponemos los bloques de construcción de recuperación como herramientas directas en lugar de ocultarlos detrás de un único punto final de «responder esta pregunta». Estas herramientas son intencionalmente simples y lo más libres de LLM posible para que los clientes puedan consultarlas de manera rápida y económica.(5)
Cada herramienta MCP corresponde a un primitivo de recuperación subyacente, como search_slack, search_code, search o who_knows. Las entradas y salidas de las herramientas son estrechas, estructuradas y estables, lo que facilita su llamada desde cualquier cliente o agente sin necesidad de incorporar lógica de orquestación adicional dentro de la propia herramienta.
La mayoría de las herramientas ejecutan un pipeline de consulta, como búsqueda vectorial, búsqueda léxica o ripgrep, aplican heurísticas de puntuación ligeras y devuelven filas de evidencia sin procesar.
Claude Code, o cualquier agente compatible con MCP, se convierte en el motor de orquestación. Decide qué herramientas llamar, en qué orden y cómo ensamblar los resultados en una respuesta final o edición de código. La capa de recuperación en sí misma no depende de esas decisiones del LLM para atender las solicitudes.
Interfaz web
En la interfaz web, las mismas herramientas existen, pero están conectadas a un pipeline de consulta completo que se ejecuta de principio a fin para cada pregunta del usuario. El agente de la interfaz posee los pasos de planificador y ejecutor.
- Planificador: una pasada ligera de LLM inspecciona la consulta y el proyecto activo, luego elige qué herramientas de recuperación invocar, como search, search_slack y subsystem_index.
- Ejecutor: el sistema distribuye esas llamadas de herramientas en paralelo, recoge los resultados y los normaliza en un esquema de evidencia compartido con puntuaciones, actualidad y pistas de origen.
- Síntesis: una pasada final de LLM toma el paquete de evidencia tipado y la pregunta original, luego produce la respuesta que se muestra en la interfaz, incluyendo citas, advertencias y síntesis entre fuentes.
Desde la perspectiva del usuario, la interfaz web es simplemente «haz una pregunta y obtén una respuesta». Bajo el capó, ejecuta el mismo patrón de planificador → ejecutor → sintetizador que los clientes MCP pueden recrear explícitamente.

Organización
A medida que el corpus crecía, «buscar todo en todas partes» dejó rápidamente de ser útil. Los ingenieros de los equipos de compiladores no querían manuales de infraestructura en sus resultados, y viceversa. Los proyectos son la forma en que hacemos que la búsqueda sea relevante por defecto.
Proyectos y búsqueda con ámbito
Introdujimos los proyectos como la forma principal de organizar el espacio de trabajo sobre el que se ejecuta una consulta. Un proyecto es un conjunto nombrado de fuentes de datos: canales de Slack específicos, repositorios de código, bases de datos internas y espacios de documentos relevantes para un equipo o iniciativa.
Los proyectos son intencionalmente ligeros. La misma fuente de datos, como un canal de incidentes compartido o un repositorio de plataforma central, puede ser referenciada por múltiples proyectos en lugar de duplicarse.

Incorporación y valores predeterminados
Durante la incorporación, se solicita a los usuarios que seleccionen o creen un proyecto predeterminado que coincida con su forma de trabajar, como infraestructura de entrenamiento de ML, Compilador u Operaciones del Centro de Datos.
Ese proyecto predeterminado se almacena en el perfil del usuario y limita las consultas automáticamente. Un nuevo ingeniero obtiene respuestas de alta señal sin tener que aprender primero qué canales de Slack, repositorios o espacios de documentos son importantes.
Reflexiones finales
Al final, la base de conocimiento funciona porque se encuentra con las personas donde ya vive la información, en lugar de forzar todo en un sistema rígido. Al combinar varias técnicas de búsqueda, podemos sacar a la luz evidencia rápidamente. El resultado es una experiencia de búsqueda que se mantiene lo suficientemente flexible para los datos reales de la empresa, pero lo suficientemente estructurada para seguir siendo útil a medida que Cerebras sigue creciendo.
Si has llegado hasta aquí y esto te resulta interesante, el equipo de ai/growth está contratando. Ponte en contacto si te interesa @learnwdaniel
Referencias
- Malkov y Yashunin, Búsqueda eficiente y robusta del vecino más cercano aproximado utilizando gráficos de mundo pequeño navegables jerárquicos, arXiv:1603.09320 / IEEE TPAMI 2018.
- Anthropic, Presentación de la Recuperación Contextual, 2024.
- Cormack, Clarke y Büttcher, La Fusión de Rangos Recíprocos Supera a los Métodos de Aprendizaje de Rangos Condorcet e Individuales, SIGIR 2009.
- Li et al., Search-o1: Modelos de Razonamiento Mejorados con Búsqueda Agentiva, arXiv:2501.05366, 2025.
- Anthropic, Ejecución de Código con MCP, 2025.
- Liu et al., Perdido en el Medio: Cómo los Modelos de Lenguaje Usan Contextos Largos, arXiv:2307.03172, 2023.
- Anthropic, Usa Etiquetas XML.
- Salesforce/Slack Engineering, Cómo la IA de Slack Procesa Miles de Millones de Mensajes.
- Improving Agents, Mejor Formato de Datos Anidados.
- Cursor, Mejorando el Agente con Búsqueda Semántica, 2025.





