[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"portal-settings:stajic:es":3,"public-menus:all":38,"post:where-does-an-llm-get-its-data-rag-data-sources-in-python:es":205,"related:post:where-does-an-llm-get-its-data-rag-data-sources-in-python:es:1":1405},{"statusCode":4,"data":5,"message":37},200,{"tenantId":6,"lang":7,"defaultLang":8,"siteUrl":9,"contactEmail":10,"brandName":11,"logoUrl":12,"siteName":11,"siteDescription":13,"ogImage":10,"robotsIndex":14,"socialLinks":10,"reservedSlugs":10,"seoPolicy":15},"stajic","es","de","https:\u002F\u002Fstajic.de",null,"Stajic Platform","\u002FLogo_Planet.svg","Stajic Portal",true,{"branding":16,"relatedContent":17,"crossDomainLinks":18},{"logoUrl":12},{"enabled":14},[19,22,25,28,31,34],{"url":20,"label":21,"isActive":14,"showInFooter":14,"includeInSameAs":14},"https:\u002F\u002Ffigure.rocks","figure.rocks",{"url":23,"label":24,"isActive":14,"showInFooter":14,"includeInSameAs":14},"https:\u002F\u002Floving.rocks","loving.rocks",{"url":26,"label":27,"isActive":14,"showInFooter":14,"includeInSameAs":14},"https:\u002F\u002Fbazify.com","bazify.com",{"url":29,"label":30,"isActive":14,"showInFooter":14,"includeInSameAs":14},"https:\u002F\u002Fbazify.de","bazify.de",{"url":32,"label":33,"isActive":14,"showInFooter":14,"includeInSameAs":14},"https:\u002F\u002Fbazify.at","bazify.at",{"url":35,"label":36,"isActive":14,"showInFooter":14,"includeInSameAs":14},"https:\u002F\u002Fbazify.ba","bazify.ba","Portal settings resolved",[39,45],{"id":40,"name":41,"location":42,"isActive":14,"isDefault":43,"items":44},1,"main-navigation","header",false,[],{"id":46,"name":47,"location":48,"isActive":14,"isDefault":14,"items":49},4,"main-menu","sidebar",[50,66,79,93,103,118,133],{"id":51,"title":52,"url":60,"target":61,"icon":62,"isActive":14,"type":63,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":64,"portfolioId":10,"children":65},"item-18",{"de":53,"en":54,"es":55,"fr":56,"it":54,"ru":57,"sr":58,"zh":59},"Startseite","Home","Inicio","Accueil","Главная","Почетна","首页","\u002Ffull-stack-web-developer-munich-performance-seo-and-maintainable-builds","_self","i-lucide-home","page",111,[],{"id":67,"title":68,"url":75,"target":61,"icon":76,"isActive":14,"type":63,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":77,"portfolioId":10,"children":78},"item-22",{"de":69,"en":69,"es":70,"fr":69,"it":71,"ru":72,"sr":73,"zh":74},"Vision","Visión","Visione","Видение","Визија","想象","\u002Fueber-uns-webdesign-muenchen-webaplikation","i-lucide-eye",113,[],{"id":80,"title":81,"url":89,"target":61,"icon":90,"isActive":14,"type":63,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":91,"portfolioId":10,"children":92},"item-19",{"de":82,"en":83,"es":84,"fr":83,"it":85,"ru":86,"sr":87,"zh":88},"Leistungen","Services","Servicios","Servizi","Услуги","Услуге","服务","\u002Fservices-dienstleistungen-muenchen","i-lucide-wrench",116,[],{"id":94,"title":95,"url":99,"target":61,"icon":100,"isActive":14,"type":63,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":101,"portfolioId":10,"children":102},"item-23",{"de":96,"en":96,"es":96,"fr":96,"it":96,"ru":97,"sr":97,"zh":98},"Blog","Блог","博客","\u002Fblog","i-lucide-book-open",112,[],{"id":104,"title":105,"url":114,"target":61,"icon":115,"isActive":14,"type":63,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":116,"portfolioId":10,"children":117},"item-32",{"de":106,"en":107,"es":108,"fr":109,"it":110,"ru":111,"sr":112,"zh":113},"Neue Technologien","New Technologies","Nuevas tecnologías","Nouvelles technologies","Nuove tecnologie","Новые технологии","Нове технологије","新技术！","\u002Fneue-webtechnologien","i-lucide-sparkles",122,[],{"id":119,"title":120,"url":129,"target":61,"icon":130,"isActive":14,"type":63,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":131,"portfolioId":10,"children":132},"item-20",{"de":121,"en":122,"es":123,"fr":124,"it":125,"ru":126,"sr":127,"zh":128},"Kontakt","Contact us!","Contacto","Contact","Contatto","Контакт","Контактирајте нас","联系我们！","\u002Fcontact","i-lucide-mail",115,[],{"id":134,"title":135,"url":144,"target":61,"icon":145,"isActive":14,"type":63,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":146,"portfolioId":10,"children":147},"item-21",{"de":136,"en":137,"es":138,"fr":139,"it":140,"ru":141,"sr":142,"zh":143},"Unsere Arbeit","Our Work","Nuestro trabajo","Nos réalisations","I nostri lavori","Наши работы","Наши радови","文件夹","\u002Fportfolio","i-lucide-briefcase",114,[148,161,175,181,193],{"id":149,"title":150,"url":144,"target":61,"icon":159,"isActive":14,"type":63,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":146,"portfolioId":10,"children":160},"item-24",{"de":151,"en":152,"es":153,"fr":154,"it":155,"ru":156,"sr":157,"zh":158},"Alle Projekte","All Projects","Todos los proyectos","Tous les projets","Tutti i progetti","Все проекты","Сви пројекти","所有项目","i-lucide-grid-3x3",[],{"id":162,"title":163,"url":171,"target":61,"icon":172,"isActive":14,"type":173,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":10,"portfolioId":10,"children":174},"item-29",{"de":164,"en":165,"es":166,"fr":167,"it":168,"ru":169,"sr":170,"zh":143},"Local Roots, Global Reach","Local Roots - Global Reach","Empresa local ","Entreprise locale","Azienda locale","Местная компания","Локално предузеће глобално тржиште","\u002Fportfolio\u002Flocal-roots-global-reach-communication-media-systems-for-modern-business","i-lucide-folder","custom",[],{"id":176,"title":177,"url":179,"target":61,"icon":172,"isActive":14,"type":173,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":10,"portfolioId":10,"children":180},"item-28",{"de":178,"en":178,"es":178,"fr":178,"it":178,"ru":178,"sr":178,"zh":178},"Solr Suggester","\u002Fportfolio\u002Fsolr-fuzzy-suggester-und-solr-infix-suggester-abfrage-ueber-ajax-und-filterung",[],{"id":182,"title":183,"url":191,"target":61,"icon":172,"isActive":14,"type":173,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":10,"portfolioId":10,"children":192},"item-27",{"de":184,"en":185,"es":186,"fr":187,"it":188,"ru":189,"sr":190,"zh":185},"Firmenwebseite SEO","Company Website SEO","Sitio web corporativo SEO","Site web d’entreprise SEO","Sito web aziendale SEO","Корпоративный сайт SEO","Пословна веб-страница SEO","\u002Fportfolio\u002Fseo-sem-branding-mobile-webseite-muenchen",[],{"id":194,"title":195,"url":203,"target":61,"icon":172,"isActive":14,"type":173,"productId":10,"categoryId":10,"shopCategoryId":10,"articleId":10,"pageId":10,"portfolioId":10,"children":204},"item-31",{"de":196,"en":197,"es":198,"fr":199,"it":200,"ru":201,"sr":202,"zh":197},"Digitalisierungsportal","Digitalization Portal","Portal de digitalización","Portail de numérisation","Portale di digitalizzazione","Портал цифровизации","Портал за дигитализацију","\u002Fportfolio\u002Fdigitalisierungsportal-archiv-museum-bibliothek-ead-lido-mets-mods",[],{"statusCode":4,"data":206,"message":1404},{"id":207,"title":208,"slug":209,"content":210,"contentJson":211,"excerpt":677,"featuredImage":678,"featuredImageAlt":679,"featuredImageCaption":10,"featuredImageTitle":10,"featuredImageCopyright":10,"featuredImageAuthor":10,"featuredImageSourceUrl":10,"featuredImageLicense":10,"featuredImageIsAiGenerated":43,"status":680,"publishedAt":681,"createdAt":682,"updatedAt":683,"seoLocalePaths":684,"categories":693,"author":694,"translations":699},"479","¿De dónde obtiene sus datos un LLM? Fuentes de datos RAG en Python","where-does-an-llm-get-its-data-rag-data-sources-in-python","\u003Cp>El artículo anterior, \u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fes\u002Fblog\u002Fwhat-is-rag-the-simplest-explanation-of-how-it-works\">¿Qué es RAG? La explicación más simple de cómo funciona\u003C\u002Fa>, estableció el modelo mental: el LLM escribe, RAG recupera conocimiento útil, la aplicación posee el estado actual y las herramientas realizan acciones. Este artículo da el siguiente paso: \u003Cb>¿de dónde vienen realmente los datos y cómo se ve la recuperación en Python?\u003C\u002Fb>\u003C\u002Fp>\n\u003Cp>La sorpresa importante es que una \"fuente de datos para un LLM\" normalmente no es nada exótico. Puede ser un archivo de texto, una carpeta de documentos Markdown, una base de datos SQL, una respuesta de API, un catálogo de productos, un sistema de soporte o un índice vectorial derivado de esas fuentes. La IA no conoce estos sistemas mágicamente. Tu aplicación tiene que cargar, consultar, buscar o recuperar los datos relevantes y colocar el resultado en el contexto del modelo.\u003C\u002Fp>\n\u003Cblockquote class=\"border-l-4 border-gray-300 pl-4 italic\">Fuente de datos = dónde vive la información. Recuperación = cómo la aplicación encuentra información útil. Contexto = la información seleccionada que se entrega al modelo. LLM = el componente que interpreta ese contexto y genera una respuesta.\u003Ccite class=\"block mt-2 text-sm\">— El modelo de cuatro partes utilizado a lo largo de este artículo\u003C\u002Fcite>\u003C\u002Fblockquote>\n\u003Ch2 id=\"section-4\">Pregunta\u003C\u002Fh2>\n\u003Cp>¿Cómo utiliza un LLM datos externos como archivos, bases de datos o API, y cómo puede un pequeño programa en Python implementar los pasos esenciales de RAG sin ocultarlos detrás de un framework?\u003C\u002Fp>\n\u003Ch2 id=\"section-6\">Qué significa esto realmente\u003C\u002Fh2>\n\u003Cp>Cuando los desarrolladores dicen que un LLM está \"conectado a los datos de la empresa\", varias operaciones diferentes pueden estar ocultas detrás de esa frase. Una aplicación puede ejecutar SQL. Otra puede llamar a una API. Otra puede ejecutar búsqueda de texto completo. Otra puede calcular la similitud de embeddings sobre fragmentos de documentos. Todas ellas pueden proporcionar información externa a un LLM, pero no son el mismo método de recuperación y no deben tratarse como intercambiables.\u003C\u002Fp>\n\u003Cp>Esta distinción importa porque el mejor método de recuperación depende de la forma de la pregunta. \"¿Cuál es nuestra política de reembolsos?\" es un problema de recuperación de documentos. \"¿Cuál es el estado actual del pedido 4711?\" suele ser una consulta a una base de datos estructurada. \"¿Qué párrafo trata sobre la recuperación de cuentas?\" puede ser búsqueda por palabras clave o semántica. RAG es más útil cuando el sistema debe \u003Cb>descubrir conocimiento relevante antes de la generación\u003C\u002Fb>.\u003C\u002Fp>\n\u003Ch2 id=\"section-9\">Ejemplo más simple\u003C\u002Fh2>\n\u003Cp>Comienza con tres cadenas en Python normal. Todavía no hay base de datos vectorial, ni framework, ni LLM. Solo queremos hacer visible el paso de recuperación.\u003C\u002Fp>\n\u003Cpre class=\"code-block\">\u003Ccode>documents = [\n    &quot;The AKM uses 7.62 mm ammunition.&quot;,\n    &quot;A Med Kit restores health.&quot;,\n    &quot;A 4x scope can be attached to several compatible weapons.&quot;\n]\n\nquestion = &quot;Which ammunition does the AKM use?&quot;\n\nfor document in documents:\n    if &quot;AKM&quot; in document:\n        print(document)\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>El programa imprime la primera frase porque contiene el término que buscamos. Esta es una recuperación primitiva, pero la arquitectura ya es visible: \u003Cb>pregunta → búsqueda → texto relevante\u003C\u002Fb>. RAG añade un paso más importante: pasar el texto recuperado a un modelo de lenguaje junto con la pregunta.\u003C\u002Fp>\n\u003Cp>Una versión un poco más general clasifica los documentos por términos de consulta superpuestos:\u003C\u002Fp>\n\u003Cpre class=\"code-block\">\u003Ccode>import re\n\ndocuments = [\n    {&quot;id&quot;: &quot;weapon-akm&quot;, &quot;text&quot;: &quot;The AKM uses 7.62 mm ammunition.&quot;},\n    {&quot;id&quot;: &quot;healing-medkit&quot;, &quot;text&quot;: &quot;A Med Kit restores health.&quot;},\n    {&quot;id&quot;: &quot;scope-4x&quot;, &quot;text&quot;: &quot;A 4x scope can be attached to several compatible weapons.&quot;},\n]\n\ndef words(text):\n    return set(re.findall(r&quot;[a-zA-Z0-9.]+&quot;, text.lower()))\n\ndef retrieve(question, documents, top_k=2):\n    query_terms = words(question)\n    ranked = []\n\n    for document in documents:\n        score = len(query_terms &amp; words(document[&quot;text&quot;]))\n        if score &gt; 0:\n            ranked.append((score, document))\n\n    ranked.sort(key=lambda item: item[0], reverse=True)\n    return [document for _, document in ranked[:top_k]]\n\nquestion = &quot;Which ammunition does the AKM use?&quot;\nhits = retrieve(question, documents)\n\nfor hit in hits:\n    print(hit[&quot;id&quot;], &quot;-&gt;&quot;, hit[&quot;text&quot;])\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Esto no es un motor de búsqueda de producción. Ignora la morfología, los sinónimos, las variantes ortográficas, la longitud de los documentos y muchas señales de clasificación. Su valor es educativo: \u003Cb>RAG no comienza con una base de datos vectorial. Comienza con la recuperación.\u003C\u002Fb>\u003C\u002Fp>\n\u003Ch2 id=\"section-16\">Dónde deja de funcionar el ejemplo\u003C\u002Fh2>\n\u003Cp>La coincidencia exacta o léxica se vuelve débil cuando la pregunta y la fuente usan palabras diferentes. Un documento puede decir \"mantenimiento del vehículo\", mientras que el usuario pregunta \"¿cómo reparo mi coche?\". Un recuperador léxico puede pasar por alto la relación aunque un humano la vea de inmediato. La recuperación semántica aborda esto representando el texto como vectores y comparando el significado en lugar de solo los tokens exactos.\u003C\u002Fp>\n\u003Cp>Los archivos largos crean otro problema. Buscar en un manual completo de 80 páginas como una sola unidad es demasiado grueso, pero dividir cada frase puede destruir contexto útil. Por lo tanto, los sistemas RAG reales necesitan decisiones sobre análisis, fragmentación, metadatos, clasificación, actualidad, permisos y procedencia.\u003C\u002Fp>\n\u003Cp>El ejemplo tampoco dice nada sobre hechos estructurados en vivo. Si el usuario pregunta por el estado actual del pedido 4711 y la aplicación ya tiene una clave de base de datos, la búsqueda semántica suele ser la herramienta inicial incorrecta. Es mejor una consulta determinista a la base de datos.\u003C\u002Fp>\n\u003Ch2 id=\"section-20\">Respuesta directa\u003C\u002Fh2>\n\u003Cp>Una fuente de datos para un LLM es cualquier sistema externo del que una aplicación pueda obtener información para el modelo: archivos, bases de datos, API, índices de búsqueda, almacenes vectoriales o estado de la aplicación en vivo. RAG es el patrón de \u003Cb>recuperar conocimiento relevante de dichas fuentes antes de la generación\u003C\u002Fb>.\u003C\u002Fp>\n\u003Cp>En Python, el pipeline esencial puede ser muy pequeño: \u003Cb>cargar datos → crear unidades recuperables → encontrar evidencia relevante → ensamblar el contexto → llamar al LLM\u003C\u002Fb>. El método de recuperación debe coincidir con la fuente y la pregunta. Use SQL para hechos estructurados exactos, búsqueda de texto completo para coincidencia léxica, embeddings para similitud semántica y recuperación híbrida cuando varias señales sean valiosas.\u003C\u002Fp>\n\u003Ch2 id=\"section-23\">Por qué es así\u003C\u002Fh2>\n\u003Cp>Un modelo de lenguaje no recibe automáticamente el contenido de su sistema de archivos, base de datos PostgreSQL, CRM, API privada o documento recién editado. La aplicación decide qué información externa es accesible y qué se coloca en el contexto actual del modelo.\u003C\u002Fp>\n\u003Cp>El trabajo original de Generación Aumentada por Recuperación de Lewis et al. combinó un modelo generativo con memoria externa no paramétrica recuperada de un índice vectorial denso. La idea arquitectónica más amplia sobrevive más allá de esa implementación específica: la evidencia externa puede recuperarse en el momento de la inferencia en lugar de esperar que todo el conocimiento útil esté codificado en los parámetros del modelo.\u003C\u002Fp>\n\u003Cp>Esto crea una separación útil de responsabilidades: la fuente almacena información, el recuperador selecciona evidencia, el contexto lleva esa evidencia a la solicitud y el modelo la interpreta. Mantener visibles esos límites hace que los fallos sean mucho más fáciles de diagnosticar.\u003C\u002Fp>\n\u003Ch2 id=\"section-27\">Contexto: los principales tipos de fuentes de datos\u003C\u002Fh2>\n\u003Cdiv class=\"overflow-x-auto\">\u003Ctable class=\"w-full border-collapse\">\u003Cthead>\u003Ctr>\u003Cth class=\"border border-gray-300 px-4 py-2 text-left font-semibold\">Fuente\u003C\u002Fth>\u003Cth class=\"border border-gray-300 px-4 py-2 text-left font-semibold\">Método de recuperación típico\u003C\u002Fth>\u003Cth class=\"border border-gray-300 px-4 py-2 text-left font-semibold\">Bueno para\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">TXT \u002F Markdown \u002F HTML\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Análisis + búsqueda léxica o semántica\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Documentación, manuales, artículos, notas\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">PDF \u002F DOCX\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Extracción consciente de la estructura + búsqueda\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Políticas, informes, contratos, manuales\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Base de datos SQL\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Consulta SQL o recuperación filtrada\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Pedidos, usuarios, productos, registros estructurados\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">API REST \u002F GraphQL\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Solicitud HTTP con parámetros\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Sistemas remotos y datos de servicios en vivo\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Índice de búsqueda\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">BM25 \u002F texto completo \u002F búsqueda híbrida\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Grandes colecciones de texto\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Índice vectorial\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Similitud de embeddings\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Recuperación semántica de documentos\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Estado de la aplicación\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Lectura directa del estado o llamada a herramienta\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Lo que es verdad en este momento\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Cp>Un índice vectorial merece especial atención. En muchas arquitecturas \u003Cb>no es la fuente canónica de verdad\u003C\u002Fb>. Es un índice de recuperación derivado de documentos o registros. El documento autoritativo puede residir en almacenamiento de objetos, un CMS, Git, PostgreSQL u otro sistema, mientras que los embeddings y metadatos se almacenan por separado para una búsqueda semántica rápida. Algunos sistemas sí usan un almacén vectorial como almacenamiento primario, pero eso es una elección arquitectónica más que un requisito de RAG.\u003C\u002Fp>\n\u003Cp>Si el límite entre recuperación, memoria persistente, estado actual y contexto del modelo aún no está claro, consulte \u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fes\u002Fblog\u002Fai-agent-memory-is-not-rag-how-to-separate-memory-retrieval-state-and-context\">La memoria del agente de IA no es RAG\u003C\u002Fa>. Esas capas pueden usar algunas de las mismas tecnologías de almacenamiento y aun así tener reglas de corrección diferentes.\u003C\u002Fp>\n\u003Ch2 id=\"section-31\">Supuestos\u003C\u002Fh2>\n\u003Cul>\u003Cli>La aplicación tiene permitido acceder a la fuente externa.\u003C\u002Fli>\u003Cli>La fuente relevante contiene suficiente información para responder la pregunta.\u003C\u002Fli>\u003Cli>Los datos pueden analizarse o consultarse en una forma que la capa de recuperación pueda usar.\u003C\u002Fli>\u003Cli>La información recuperada es lo suficientemente reciente para la decisión solicitada.\u003C\u002Fli>\u003Cli>El modelo recibe la evidencia seleccionada en su contexto.\u003C\u002Fli>\u003Cli>La autorización se aplica antes de que la evidencia protegida llegue al modelo.\u003C\u002Fli>\u003Cli>El modelo de generación aún puede equivocarse incluso cuando la recuperación es correcta.\u003C\u002Fli>\u003C\u002Ful>\n\u003Cp>Estos supuestos importan porque la recuperación no puede compensar evidencia faltante, versiones obsoletas de la fuente, analizadores defectuosos o acceso no autorizado. Un pipeline RAG solo puede ser tan confiable como la ruta de evidencia que lo alimenta.\u003C\u002Fp>\n\u003Ch2 id=\"section-34\">Variables\u003C\u002Fh2>\n\u003Cdiv class=\"overflow-x-auto\">\u003Ctable class=\"w-full border-collapse\">\u003Cthead>\u003Ctr>\u003Cth class=\"border border-gray-300 px-4 py-2 text-left font-semibold\">Variable\u003C\u002Fth>\u003Cth class=\"border border-gray-300 px-4 py-2 text-left font-semibold\">Por qué cambia el diseño\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Estructura de la fuente\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Una tabla SQL, un PDF legal y un repositorio de código fuente necesitan estrategias de recuperación diferentes\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Tipo de pregunta\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">La búsqueda exacta, la búsqueda conceptual y la investigación de múltiples saltos son tareas diferentes\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Requisito de actualidad\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">El estado en vivo puede necesitar consultas directas en lugar de índices reconstruidos periódicamente\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Tamaño del corpus\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">La búsqueda en memoria puede funcionar para cientos de fragmentos, pero no para colecciones muy grandes\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Idioma\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">La recuperación multilingüe requiere modelos y tokenización adecuados para los idiomas reales\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Permisos\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">La recuperación debe filtrar según los derechos de acceso del usuario actual\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Latencia y costo\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Más etapas de recuperación pueden mejorar la calidad, pero añaden costo de ejecución e infraestructura\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Necesidad de procedencia\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Los sistemas de alta confianza necesitan IDs de fuente, versiones y evidencia trazable\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Ch2 id=\"section-36\">Método de diagnóstico \u002F decisión\u003C\u002Fh2>\n\u003Cp>La primera decisión no es \"¿Qué base de datos vectorial debería instalar?\" Es: \u003Cb>¿Qué tipo de hecho estoy tratando de recuperar?\u003C\u002Fb>\u003C\u002Fp>\n\u003Cdiv class=\"overflow-x-auto\">\u003Ctable class=\"w-full border-collapse\">\u003Cthead>\u003Ctr>\u003Cth class=\"border border-gray-300 px-4 py-2 text-left font-semibold\">Tipo de pregunta\u003C\u002Fth>\u003Cth class=\"border border-gray-300 px-4 py-2 text-left font-semibold\">Enfoque preferido inicial\u003C\u002Fth>\u003Cth class=\"border border-gray-300 px-4 py-2 text-left font-semibold\">Razón\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">ID exacto o registro actual\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">SQL \u002F búsqueda por clave \u002F API\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Acceso estructurado determinista\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Redacción exacta, códigos, nombres\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Búsqueda de texto completo o por palabra clave\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Precisión léxica\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Pregunta conceptual sobre documentos\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Búsqueda vectorial semántica\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">El significado puede diferir de la redacción\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Conocimiento empresarial mixto\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Recuperación híbrida + filtros de metadatos\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Combina señales léxicas y semánticas\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Estado actual de la aplicación\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">Acceso directo al estado\u002Fherramienta\u003C\u002Ftd>\u003Ctd class=\"border border-gray-300 px-4 py-2\">La frescura importa más que la similitud de documentos\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Cp>Una prueba útil es: \u003Cb>¿Ya sé qué registro necesito, o el sistema debe descubrir qué pasaje es relevante?\u003C\u002Fb> Si el registro se conoce, consúltalo directamente. Si la relevancia debe descubrirse, la búsqueda cobra mayor importancia.\u003C\u002Fp>\n\u003Cp>Cuando una respuesta es incorrecta, diagnostica el pipeline en orden en lugar de cambiar inmediatamente el LLM:\u003C\u002Fp>\n\u003Col>\u003Cli>\u003Cb>1. Cobertura de fuentes:\u003C\u002Fb> ¿Existe la información correcta en el conjunto de fuentes accesibles?\u003C\u002Fli>\u003Cli>\u003Cb>2. Frescura:\u003C\u002Fb> ¿Es esa versión lo suficientemente actual para la pregunta?\u003C\u002Fli>\u003Cli>\u003Cb>3. Análisis:\u003C\u002Fb> ¿Se extrajo correctamente el contenido relevante?\u003C\u002Fli>\u003Cli>\u003Cb>4. Fragmentación:\u003C\u002Fb> ¿Permaneció la evidencia junto con las condiciones que le dan significado?\u003C\u002Fli>\u003Cli>\u003Cb>5. Recuperación:\u003C\u002Fb> ¿Aparece el fragmento correcto entre los candidatos?\u003C\u002Fli>\u003Cli>\u003Cb>6. Clasificación:\u003C\u002Fb> ¿Están las fuentes más sólidas clasificadas por encima de las más débiles o conflictivas?\u003C\u002Fli>\u003Cli>\u003Cb>7. Ensamblaje del contexto:\u003C\u002Fb> ¿Envió realmente la aplicación la evidencia seleccionada al modelo?\u003C\u002Fli>\u003Cli>\u003Cb>8. Generación:\u003C\u002Fb> ¿Utilizó el LLM fielmente la evidencia proporcionada?\u003C\u002Fli>\u003Cli>\u003Cb>9. Atribución:\u003C\u002Fb> ¿Se puede rastrear cada afirmación importante hasta una fuente?\u003C\u002Fli>\u003C\u002Fol>\n\u003Cp>Para un método más profundo de depuración en producción, consulta \u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fes\u002Fblog\u002Frag-failed-but-which-layer-actually-failed-a-diagnostic-method\">RAG Failed — But Which Layer Actually Failed? A Diagnostic Method\u003C\u002Fa>, que amplía esta cadena en capas de fallo comprobables de forma independiente.\u003C\u002Fp>\n\u003Ch2 id=\"section-43\">Evidencia\u003C\u002Fh2>\n\u003Cp>El artículo de RAG de Lewis et al. formalizó la generación que se condiciona a la memoria externa recuperada en lugar de depender solo de los parámetros del modelo. Eso proporciona la base conceptual para separar el generador de una fuente de conocimiento recuperable.\u003C\u002Fp>\n\u003Cp>Sentence Transformers documenta la búsqueda semántica como incrustar el corpus y la consulta en un espacio vectorial y recuperar elementos con alta similitud semántica. Su API actual también distingue la codificación de consultas de la codificación de documentos para tareas de recuperación.\u003C\u002Fp>\n\u003Cp>SQLite FTS5 demuestra el otro lado del espectro: la recuperación de texto completo madura puede clasificar documentos sin incrustaciones. Esto importa porque la búsqueda léxica sigue siendo valiosa para identificadores, terminología exacta y muchos diseños de recuperación híbrida.\u003C\u002Fp>\n\u003Cp>La documentación de incrustaciones de OpenAI describe las incrustaciones como representaciones vectoriales numéricas utilizadas para la relación y la búsqueda. Esta es una ruta de implementación para la recuperación semántica, no la definición de RAG en sí.\u003C\u002Fp>\n\u003Ch2 id=\"section-48\">Ejemplo real 1: Una carpeta de archivos de texto\u003C\u002Fh2>\n\u003Cp>Supongamos que un directorio llamado \u003Ccode>knowledge\u002F\u003C\u002Fcode> contiene archivos de texto ordinarios. Python puede cargarlos sin ninguna biblioteca de IA.\u003C\u002Fp>\n\u003Cpre class=\"code-block\">\u003Ccode>from pathlib import Path\n\ndef load_text_files(folder=&quot;knowledge&quot;):\n    documents = []\n\n    for path in Path(folder).glob(&quot;*.txt&quot;):\n        documents.append({\n            &quot;source&quot;: path.name,\n            &quot;text&quot;: path.read_text(encoding=&quot;utf-8&quot;)\n        })\n\n    return documents\n\ndocuments = load_text_files()\n\nfor document in documents:\n    print(document[&quot;source&quot;], len(document[&quot;text&quot;]))\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>El sistema de archivos es la fuente de datos. La siguiente pregunta es cuánto texto debe convertirse en una unidad recuperable. Para documentos largos, buscar un archivo completo suele ser demasiado grueso. Por eso los pipelines de RAG comúnmente crean fragmentos.\u003C\u002Fp>\n\u003Ch3 id=\"section-52\">Un fragmentador muy simple\u003C\u002Fh3>\n\u003Cpre class=\"code-block\">\u003Ccode>def chunk_text(text, max_chars=800):\n    paragraphs = [p.strip() for p in text.split(&quot;\\n\\n&quot;) if p.strip()]\n\n    chunks = []\n    current = &quot;&quot;\n\n    for paragraph in paragraphs:\n        candidate = f&quot;{current}\\n\\n{paragraph}&quot;.strip()\n\n        if current and len(candidate) &gt; max_chars:\n            chunks.append(current)\n            current = paragraph\n        else:\n            current = candidate\n\n    if current:\n        chunks.append(current)\n\n    return chunks\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Este ejemplo agrupa párrafos hasta alcanzar un límite aproximado de caracteres. Es intencionalmente comprensible en lugar de óptimo. Los sistemas de producción a menudo fragmentan por tokens, encabezados, secciones, límites de oraciones o estructura del documento. Las tablas, el código fuente, los contratos y la documentación de API pueden necesitar estrategias diferentes.\u003C\u002Fp>\n\u003Ch3 id=\"section-55\">Preservar la procedencia al dividir en fragmentos\u003C\u002Fh3>\n\u003Cpre class=\"code-block\">\u003Ccode>def build_chunks(documents):\n    chunks = []\n\n    for document in documents:\n        for index, text in enumerate(chunk_text(document[&quot;text&quot;])):\n            chunks.append({\n                &quot;id&quot;: f&#39;{document[&quot;source&quot;]}:{index}&#39;,\n                &quot;source&quot;: document[&quot;source&quot;],\n                &quot;chunk&quot;: index,\n                &quot;text&quot;: text,\n            })\n\n    return chunks\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Un fragmento útil lleva más que texto. El nombre de la fuente, el ID del documento, la URL, la marca de tiempo, la versión o la sección pueden respaldar más adelante la citación, la depuración y las comprobaciones de actualidad. Si la procedencia se pierde durante la ingesta, resulta mucho más difícil explicar por qué se produjo una respuesta concreta.\u003C\u002Fp>\n\u003Ch2 id=\"section-58\">Ejemplo real 2: Datos estructurados — Use SQL cuando SQL es la herramienta adecuada\u003C\u002Fh2>\n\u003Cp>No todo hecho externo debe pasar por la búsqueda semántica. Si la pregunta solicita un registro actual exacto, una consulta directa a la base de datos suele ser más clara y más determinista.\u003C\u002Fp>\n\u003Cpre class=\"code-block\">\u003Ccode>import sqlite3\n\ndef get_order_status(order_id):\n    connection = sqlite3.connect(&quot;shop.db&quot;)\n    cursor = connection.cursor()\n\n    cursor.execute(\n        &quot;SELECT status, total, currency FROM orders WHERE id = ?&quot;,\n        (order_id,)\n    )\n\n    row = cursor.fetchone()\n    connection.close()\n\n    if row is None:\n        return None\n\n    return {\n        &quot;order_id&quot;: order_id,\n        &quot;status&quot;: row[0],\n        &quot;total&quot;: row[1],\n        &quot;currency&quot;: row[2],\n    }\n\nprint(get_order_status(4711))\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Si la aplicación ya sabe que el usuario está preguntando por el pedido 4711, incrustar toda la tabla de pedidos y pedirle a la búsqueda semántica que redescubra esa fila normalmente añade complejidad sin beneficio. Una regla de diseño sólida es: \u003Cb>recupere hechos estructurados con consultas estructuradas; recupere conocimiento no estructurado con búsqueda.\u003C\u002Fb>\u003C\u002Fp>\n\u003Cp>La fila de base de datos devuelta aún puede colocarse en el contexto del modelo para que el LLM pueda explicarla en lenguaje natural. Pero el acceso directo al estado o a un registro es conceptualmente diferente de buscar en un corpus de conocimiento.\u003C\u002Fp>\n\u003Ch2 id=\"section-63\">Ejemplo real 3: Búsqueda de texto completo antes de las incrustaciones\u003C\u002Fh2>\n\u003Cp>Entre un bucle ingenuo de Python y la búsqueda vectorial se encuentra una clase madura de sistemas de recuperación léxica. SQLite incluye FTS5 para búsqueda de texto completo, incluido el ranking BM25.\u003C\u002Fp>\n\u003Cpre class=\"code-block\">\u003Ccode>import sqlite3\n\nconnection = sqlite3.connect(&quot;knowledge.db&quot;)\ncursor = connection.cursor()\n\ncursor.execute(\n    &quot;CREATE VIRTUAL TABLE IF NOT EXISTS docs USING fts5(title, body)&quot;\n)\n\ncursor.execute(\n    &quot;INSERT INTO docs(title, body) VALUES (?, ?)&quot;,\n    (&quot;AKM&quot;, &quot;The AKM uses 7.62 mm ammunition.&quot;)\n)\n\nconnection.commit()\n\nquery = &quot;AKM ammunition&quot;\n\nrows = cursor.execute(\n    &quot;SELECT title, body, bm25(docs) AS score &quot;\n    &quot;FROM docs WHERE docs MATCH ? &quot;\n    &quot;ORDER BY score LIMIT 5&quot;,\n    (query,)\n).fetchall()\n\nfor row in rows:\n    print(row)\n\nconnection.close()\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>La búsqueda léxica es especialmente útil cuando importan la terminología exacta, los códigos de producto, los nombres, los identificadores o las palabras específicas del dominio. La búsqueda semántica no es automáticamente mejor. Los sistemas de producción a menudo combinan ambas señales.\u003C\u002Fp>\n\u003Ch2 id=\"section-67\">Ejemplo real 4: Recuperación semántica con incrustaciones\u003C\u002Fh2>\n\u003Cp>Las incrustaciones convierten el texto en vectores numéricos para que los pasajes semánticamente relacionados puedan compararse incluso cuando no usan una redacción idéntica. Sentence Transformers proporciona una implementación local sencilla.\u003C\u002Fp>\n\u003Cpre class=\"code-block\">\u003Ccode># pip install sentence-transformers\n\nfrom sentence_transformers import SentenceTransformer, util\n\ndocuments = [\n    &quot;The AKM uses 7.62 mm ammunition.&quot;,\n    &quot;A Med Kit restores health.&quot;,\n    &quot;Vehicle maintenance includes checking oil, brakes and tires.&quot;,\n    &quot;Account recovery requires access to the registered email address.&quot;\n]\n\nmodel = SentenceTransformer(\n    &quot;sentence-transformers\u002Fmulti-qa-mpnet-base-cos-v1&quot;\n)\n\ndocument_embeddings = model.encode_document(\n    documents,\n    convert_to_tensor=True\n)\n\nquestion = &quot;How do I repair my car?&quot;\n\nquery_embedding = model.encode_query(\n    question,\n    convert_to_tensor=True\n)\n\nhits = util.semantic_search(\n    query_embedding,\n    document_embeddings,\n    top_k=2\n)[0]\n\nfor hit in hits:\n    print(round(float(hit[&quot;score&quot;]), 3), documents[hit[&quot;corpus_id&quot;]])\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>La consulta no contiene la frase “mantenimiento de vehículos”, pero un modelo semántico aún puede clasificar ese pasaje en un puesto alto porque los conceptos están relacionados. Esta es la razón práctica por la que las incrustaciones son comunes en los sistemas RAG.\u003C\u002Fp>\n\u003Cp>Para colecciones pequeñas, las incrustaciones pueden permanecer en memoria. Los sistemas más grandes normalmente las persisten en un índice o base de datos con capacidad vectorial y realizan allí la búsqueda de vecinos más cercanos. El almacenamiento cambia, pero la lógica permanece: codificar la pregunta, encontrar representaciones de documentos relevantes, devolver la mejor evidencia.\u003C\u002Fp>\n\u003Ch2 id=\"section-72\">Ejemplo real 5: Construir el contexto para el LLM\u003C\u002Fh2>\n\u003Cp>Un recuperador debe devolver evidencia. El LLM debe entonces recibir la pregunta más esa evidencia. Mantener la recuperación y la generación separadas hace que ambas sean más fáciles de inspeccionar y probar.\u003C\u002Fp>\n\u003Cpre class=\"code-block\">\u003Ccode>def build_prompt(question, retrieved_documents):\n    context = &quot;\\n\\n&quot;.join(\n        f&#39;[{doc[&quot;id&quot;]}] {doc[&quot;text&quot;]}&#39;\n        for doc in retrieved_documents\n    )\n\n    return f&quot;&quot;&quot;\nAnswer the question using the supplied context.\n\nRules:\n- Do not invent facts that are not supported by the context.\n- If the context is insufficient, say so.\n- Cite the source IDs you used.\n\nQuestion:\n{question}\n\nContext:\n{context}\n&quot;&quot;&quot;.strip()\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>La instrucción no hace que el modelo sea infalible. Simplemente crea un límite de evidencia explícito. El modelo aún puede malinterpretar buena evidencia, ignorar una condición o generalizar en exceso. Por eso la calidad de la recuperación y la calidad de la generación deben evaluarse por separado.\u003C\u002Fp>\n\u003Ch2 id=\"section-76\">Ejemplo real 6: Un pipeline mínimo completo\u003C\u002Fh2>\n\u003Cpre class=\"code-block\">\u003Ccode>def answer_question(question, all_documents, call_llm):\n    # 1. Retrieve evidence\n    retrieved = retrieve(question, all_documents, top_k=3)\n\n    # 2. Build model context\n    prompt = build_prompt(question, retrieved)\n\n    # 3. Generate the answer\n    answer = call_llm(prompt)\n\n    return {\n        &quot;answer&quot;: answer,\n        &quot;sources&quot;: [doc[&quot;id&quot;] for doc in retrieved]\n    }\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>La función recibe \u003Ccode>call_llm\u003C\u002Fcode> como dependencia a propósito. A la recuperación no debería importarle si la generación la realiza un modelo en la nube, un modelo local u otro proveedor. La ruta de datos pertenece a la aplicación.\u003C\u002Fp>\n\u003Ch3 id=\"section-79\">Generador opcional: API de Responses de OpenAI\u003C\u002Fh3>\n\u003Cp>Un generador posible es la API de Responses de OpenAI. Mantener el nombre del modelo en una variable de entorno evita codificar de forma rígida un modelo concreto en la arquitectura RAG.\u003C\u002Fp>\n\u003Cpre class=\"code-block\">\u003Ccode># pip install openai\n\nimport os\nfrom openai import OpenAI\n\nclient = OpenAI()\n\ndef call_llm(prompt):\n    response = client.responses.create(\n        model=os.environ[&quot;OPENAI_MODEL&quot;],\n        input=prompt,\n    )\n    return response.output_text\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>El mismo pipeline de recuperación puede conectarse a un servidor de inferencia local. Este es un punto arquitectónico importante: \u003Cb>RAG no es propiedad del proveedor del LLM.\u003C\u002Fb> La aplicación es dueña de la fuente, la recuperación y el ensamblaje del contexto.\u003C\u002Fp>\n\u003Ch3 id=\"section-83\">Toda la arquitectura en una vista\u003C\u002Fh3>\n\u003Cpre class=\"code-block\">\u003Ccode>USER QUESTION\n     |\n     v\n+-------------+\n|  Retriever  |\n+-------------+\n   |       |\n   |       +----&gt; SQL \u002F API \u002F state query\n   |\n   +------------&gt; keyword \u002F full-text search\n   |\n   +------------&gt; embedding \u002F vector search\n                     |\n                     v\n              relevant evidence\n                     |\n                     v\n+-----------------------------------+\n| question + evidence + instructions |\n+-----------------------------------+\n                     |\n                     v\n                   LLM\n                     |\n                     v\n                  answer\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Este modelo de flujo de datos es más duradero que memorizar un framework. Las bibliotecas, las bases de datos y los proveedores de modelos cambiarán; los límites de responsabilidad permanecen.\u003C\u002Fp>\n\u003Ch2 id=\"section-86\">Conceptos erróneos comunes y modos de fallo\u003C\u002Fh2>\n\u003Ch3 id=\"section-87\">“RAG significa base de datos vectorial.”\u003C\u002Fh3>\n\u003Cp>No. La búsqueda vectorial es un método de recuperación. RAG puede usar búsqueda de texto completo, SQL, API, grafos de conocimiento, búsqueda vectorial o combinaciones de ellos. El patrón que lo define es la recuperación de información externa para la generación.\u003C\u002Fp>\n\u003Ch3 id=\"section-89\">“Si los datos están en PostgreSQL, debo incrustar toda la base de datos.”\u003C\u002Fh3>\n\u003Cp>No. Los registros estructurados normalmente deben seguir siendo consultables como registros estructurados. Los embeddings son útiles para la relevancia semántica, no como reemplazo de consultas deterministas.\u003C\u002Fp>\n\u003Ch3 id=\"section-91\">“Más fragmentos significa una mejor respuesta.”\u003C\u002Fh3>\n\u003Cp>No necesariamente. El contexto adicional puede introducir ruido, versiones en conflicto y material irrelevante. La recuperación debe optimizar para evidencia útil, no para el volumen máximo.\u003C\u002Fp>\n\u003Ch3 id=\"section-93\">“Una puntuación de similitud alta demuestra la respuesta.”\u003C\u002Fh3>\n\u003Cp>No. La similitud mide la relevancia, no la verdad ni la aplicabilidad. Un pasaje altamente similar puede estar desactualizado, provenir de la versión incorrecta del producto o ser válido solo bajo condiciones que no coinciden con la pregunta.\u003C\u002Fp>\n\u003Ch3 id=\"section-95\">“Una vez que se recupera el fragmento correcto, la alucinación está resuelta.”\u003C\u002Fh3>\n\u003Cp>No. La recuperación mejora el anclaje pero no garantiza un razonamiento fiel. La generación aún necesita evaluación, y los flujos de trabajo de alto riesgo pueden requerir validación determinista o revisión humana.\u003C\u002Fp>\n\u003Ch3 id=\"section-97\">“El modelo falló, así que cambia el modelo.”\u003C\u002Fh3>\n\u003Cp>No necesariamente. La fuente correcta puede haber faltado, haberse analizado incorrectamente, dividido mal, filtrado, clasificado demasiado bajo u omitido del contexto ensamblado. El reemplazo del modelo no debería ser el primer paso de diagnóstico.\u003C\u002Fp>\n\u003Ch2 id=\"section-99\">Casos límite\u003C\u002Fh2>\n\u003Cul>\u003Cli>\u003Cb>Documentos en conflicto:\u003C\u002Fb> dos fuentes pueden discrepar porque las versiones, jurisdicciones o productos difieren.\u003C\u002Fli>\u003Cli>\u003Cb>Hechos sensibles al tiempo:\u003C\u002Fb> una fuente semánticamente relevante puede ya estar obsoleta.\u003C\u002Fli>\u003Cli>\u003Cb>Permisos:\u003C\u002Fb> un recuperador no debe devolver documentos a los que el usuario actual no está autorizado a acceder.\u003C\u002Fli>\u003Cli>\u003Cb>Colecciones multilingües:\u003C\u002Fb> el modelo de incrustación y la estrategia de recuperación deben admitir los idiomas realmente utilizados.\u003C\u002Fli>\u003Cli>\u003Cb>Tablas y código fuente:\u003C\u002Fb> la división en párrafos simples puede destruir la estructura que es esencial para la respuesta.\u003C\u002Fli>\u003Cli>\u003Cb>Identificadores muy cortos:\u003C\u002Fb> la recuperación semántica puede ser más débil que la coincidencia exacta para SKU, ID, códigos de error o acrónimos.\u003C\u002Fli>\u003Cli>\u003Cb>Preguntas largas que requieren varios hechos:\u003C\u002Fb> la recuperación puede necesitar descomposición, varias búsquedas o reclasificación en lugar de una sola consulta top-k.\u003C\u002Fli>\u003Cli>\u003Cb>Jerarquía de fuentes:\u003C\u002Fb> una política oficial actual puede necesitar superar a un documento de discusión más antiguo pero semánticamente más cercano.\u003C\u002Fli>\u003C\u002Ful>\n\u003Ch2 id=\"section-101\">Limitaciones\u003C\u002Fh2>\n\u003Cp>Los ejemplos de Python optimizan intencionalmente la transparencia, no la escala. El recuperador de palabras clave es ingenuo, el fragmentador usa longitud de caracteres, los ejemplos de SQLite no incluyen gestión de conexiones de producción, y el ejemplo semántico mantiene todas las incrustaciones en memoria.\u003C\u002Fp>\n\u003Cp>Un sistema de producción puede requerir índices vectoriales, reclasificadores, recuperación híbrida, analizadores de documentos, almacenamiento en caché, indexación incremental, versionado de fuentes, filtros de control de acceso, observabilidad, conjuntos de datos de evaluación y manejo de fallos. Ninguna de esas adiciones cambia la arquitectura central; hacen que cada límite sea más confiable.\u003C\u002Fp>\n\u003Cp>RAG tampoco puede crear evidencia que esté ausente del conjunto de fuentes. Si la fuente es incorrecta, incompleta u obsoleta, un mejor modelo de incrustación no puede convertirla en conocimiento autorizado.\u003C\u002Fp>\n\u003Ch2 id=\"section-105\">¿Qué cambiaría esta respuesta?\u003C\u002Fh2>\n\u003Cp>La arquitectura cambia cuando la tarea requiere más que una búsqueda de conocimiento. Un estado de pedido en vivo necesita el estado actual. Un cálculo financiero puede necesitar código determinista. Una tarea de investigación web puede necesitar búsqueda activa. Un flujo de trabajo puede necesitar herramientas que puedan escribir datos de vuelta a otro sistema. Un agente autónomo puede necesitar planificación, permisos y control de ejecución además de la recuperación.\u003C\u002Fp>\n\u003Cp>Por lo tanto, RAG se entiende mejor como \u003Cb>una capa de adquisición de evidencia dentro de un sistema de IA más grande\u003C\u002Fb>. Es poderoso precisamente porque tiene un trabajo limitado: encontrar información externa útil y colocarla en el contexto de trabajo del modelo.\u003C\u002Fp>\n\u003Ch2 id=\"section-108\">Conclusión\u003C\u002Fh2>\n\u003Cp>RAG se vuelve mucho más fácil de entender cuando se eliminan los nombres de las tecnologías. Un archivo es una fuente. Una base de datos es una fuente. Una API es una fuente. Una función de búsqueda recupera evidencia. Un prompt lleva esa evidencia al modelo. El LLM luego la interpreta y produce lenguaje.\u003C\u002Fp>\n\u003Cp>La parte difícil de RAG en producción no es llamar a un modelo de embeddings. Es construir una ruta de evidencia confiable desde la fuente original hasta la afirmación final: preservar la procedencia, seleccionar el método de recuperación adecuado, mantener la información actualizada, controlar el acceso, evaluar la recuperación por separado de la generación y saber cuándo una llamada directa a una base de datos o a una herramienta es mejor que la búsqueda semántica.\u003C\u002Fp>\n\u003Cp>Esa es la continuación práctica del modelo básico de RAG: \u003Cb>primero entender los roles, luego hacer explícita la ruta de datos.\u003C\u002Fb>\u003C\u002Fp>\n\u003Ch2 id=\"section-112\">Fuentes primarias\u003C\u002Fh2>\n\u003Cul>\u003Cli>\u003Ca href=\"https:\u002F\u002Farxiv.org\u002Fabs\u002F2005.11401\">Lewis et al. — Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks\u003C\u002Fa> — el artículo de 2020 que introdujo la formulación de RAG que combina la generación con memoria no paramétrica recuperada.\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fwww.sbert.net\u002Fexamples\u002Fsentence_transformer\u002Fapplications\u002Fsemantic-search\u002FREADME.html\">Sentence Transformers — Semantic Search\u003C\u002Fa> — documentación oficial para la recuperación semántica, embeddings de consultas y embeddings de documentos.\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Fguides\u002Fembeddings\">OpenAI — Vector Embeddings\u003C\u002Fa> — documentación oficial que describe los embeddings como representaciones numéricas utilizadas para la relación y la búsqueda.\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fwww.sqlite.org\u002Ffts5.html\">SQLite — FTS5 Extension\u003C\u002Fa> — documentación oficial para la búsqueda de texto completo y la clasificación BM25 en SQLite.\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Flibraries\">OpenAI — SDKs and CLI\u003C\u002Fa> — ejemplo oficial del SDK de Python para la API de Responses utilizado en el ejemplo opcional del generador.\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fes\u002Fblog\u002Fwhat-is-rag-the-simplest-explanation-of-how-it-works\">What Is RAG? The Simplest Explanation of How It Works\u003C\u002Fa> — la primera parte conceptual de esta serie.\u003C\u002Fli>\u003C\u002Ful>",{"time":212,"blocks":213,"version":676},1790517338272,[214,218,221,227,231,234,237,240,243,246,249,253,256,259,262,265,268,271,274,277,280,283,286,289,292,295,298,301,337,340,343,346,358,361,364,394,397,400,426,429,432,445,448,451,454,457,460,463,466,469,472,475,479,482,485,488,491,494,497,500,503,506,509,512,515,518,521,524,527,530,533,536,539,542,545,548,551,554,557,560,563,566,569,572,575,578,581,584,587,590,593,596,599,602,605,608,611,614,617,620,631,634,637,640,643,646,649,652,655,658,661,664,667],{"data":215,"type":217},{"text":216},"El artículo anterior, \u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fes\u002Fblog\u002Fwhat-is-rag-the-simplest-explanation-of-how-it-works\">¿Qué es RAG? La explicación más simple de cómo funciona\u003C\u002Fa>, estableció el modelo mental: el LLM escribe, RAG recupera conocimiento útil, la aplicación posee el estado actual y las herramientas realizan acciones. Este artículo da el siguiente paso: \u003Cb>¿de dónde vienen realmente los datos y cómo se ve la recuperación en Python?\u003C\u002Fb>","paragraph",{"data":219,"type":217},{"text":220},"La sorpresa importante es que una \"fuente de datos para un LLM\" normalmente no es nada exótico. Puede ser un archivo de texto, una carpeta de documentos Markdown, una base de datos SQL, una respuesta de API, un catálogo de productos, un sistema de soporte o un índice vectorial derivado de esas fuentes. La IA no conoce estos sistemas mágicamente. Tu aplicación tiene que cargar, consultar, buscar o recuperar los datos relevantes y colocar el resultado en el contexto del modelo.",{"data":222,"type":226},{"text":223,"caption":224,"alignment":225},"Fuente de datos = dónde vive la información. Recuperación = cómo la aplicación encuentra información útil. Contexto = la información seleccionada que se entrega al modelo. LLM = el componente que interpreta ese contexto y genera una respuesta.","El modelo de cuatro partes utilizado a lo largo de este artículo","left","quote",{"data":228,"type":42},{"text":229,"level":230},"Pregunta",2,{"data":232,"type":217},{"text":233},"¿Cómo utiliza un LLM datos externos como archivos, bases de datos o API, y cómo puede un pequeño programa en Python implementar los pasos esenciales de RAG sin ocultarlos detrás de un framework?",{"data":235,"type":42},{"text":236,"level":230},"Qué significa esto realmente",{"data":238,"type":217},{"text":239},"Cuando los desarrolladores dicen que un LLM está \"conectado a los datos de la empresa\", varias operaciones diferentes pueden estar ocultas detrás de esa frase. Una aplicación puede ejecutar SQL. Otra puede llamar a una API. Otra puede ejecutar búsqueda de texto completo. Otra puede calcular la similitud de embeddings sobre fragmentos de documentos. Todas ellas pueden proporcionar información externa a un LLM, pero no son el mismo método de recuperación y no deben tratarse como intercambiables.",{"data":241,"type":217},{"text":242},"Esta distinción importa porque el mejor método de recuperación depende de la forma de la pregunta. \"¿Cuál es nuestra política de reembolsos?\" es un problema de recuperación de documentos. \"¿Cuál es el estado actual del pedido 4711?\" suele ser una consulta a una base de datos estructurada. \"¿Qué párrafo trata sobre la recuperación de cuentas?\" puede ser búsqueda por palabras clave o semántica. RAG es más útil cuando el sistema debe \u003Cb>descubrir conocimiento relevante antes de la generación\u003C\u002Fb>.",{"data":244,"type":42},{"text":245,"level":230},"Ejemplo más simple",{"data":247,"type":217},{"text":248},"Comienza con tres cadenas en Python normal. Todavía no hay base de datos vectorial, ni framework, ni LLM. Solo queremos hacer visible el paso de recuperación.",{"data":250,"type":252},{"code":251},"documents = [\n    \"The AKM uses 7.62 mm ammunition.\",\n    \"A Med Kit restores health.\",\n    \"A 4x scope can be attached to several compatible weapons.\"\n]\n\nquestion = \"Which ammunition does the AKM use?\"\n\nfor document in documents:\n    if \"AKM\" in document:\n        print(document)","code",{"data":254,"type":217},{"text":255},"El programa imprime la primera frase porque contiene el término que buscamos. Esta es una recuperación primitiva, pero la arquitectura ya es visible: \u003Cb>pregunta → búsqueda → texto relevante\u003C\u002Fb>. RAG añade un paso más importante: pasar el texto recuperado a un modelo de lenguaje junto con la pregunta.",{"data":257,"type":217},{"text":258},"Una versión un poco más general clasifica los documentos por términos de consulta superpuestos:",{"data":260,"type":252},{"code":261},"import re\n\ndocuments = [\n    {\"id\": \"weapon-akm\", \"text\": \"The AKM uses 7.62 mm ammunition.\"},\n    {\"id\": \"healing-medkit\", \"text\": \"A Med Kit restores health.\"},\n    {\"id\": \"scope-4x\", \"text\": \"A 4x scope can be attached to several compatible weapons.\"},\n]\n\ndef words(text):\n    return set(re.findall(r\"[a-zA-Z0-9.]+\", text.lower()))\n\ndef retrieve(question, documents, top_k=2):\n    query_terms = words(question)\n    ranked = []\n\n    for document in documents:\n        score = len(query_terms & words(document[\"text\"]))\n        if score > 0:\n            ranked.append((score, document))\n\n    ranked.sort(key=lambda item: item[0], reverse=True)\n    return [document for _, document in ranked[:top_k]]\n\nquestion = \"Which ammunition does the AKM use?\"\nhits = retrieve(question, documents)\n\nfor hit in hits:\n    print(hit[\"id\"], \"->\", hit[\"text\"])",{"data":263,"type":217},{"text":264},"Esto no es un motor de búsqueda de producción. Ignora la morfología, los sinónimos, las variantes ortográficas, la longitud de los documentos y muchas señales de clasificación. Su valor es educativo: \u003Cb>RAG no comienza con una base de datos vectorial. Comienza con la recuperación.\u003C\u002Fb>",{"data":266,"type":42},{"text":267,"level":230},"Dónde deja de funcionar el ejemplo",{"data":269,"type":217},{"text":270},"La coincidencia exacta o léxica se vuelve débil cuando la pregunta y la fuente usan palabras diferentes. Un documento puede decir \"mantenimiento del vehículo\", mientras que el usuario pregunta \"¿cómo reparo mi coche?\". Un recuperador léxico puede pasar por alto la relación aunque un humano la vea de inmediato. La recuperación semántica aborda esto representando el texto como vectores y comparando el significado en lugar de solo los tokens exactos.",{"data":272,"type":217},{"text":273},"Los archivos largos crean otro problema. Buscar en un manual completo de 80 páginas como una sola unidad es demasiado grueso, pero dividir cada frase puede destruir contexto útil. Por lo tanto, los sistemas RAG reales necesitan decisiones sobre análisis, fragmentación, metadatos, clasificación, actualidad, permisos y procedencia.",{"data":275,"type":217},{"text":276},"El ejemplo tampoco dice nada sobre hechos estructurados en vivo. Si el usuario pregunta por el estado actual del pedido 4711 y la aplicación ya tiene una clave de base de datos, la búsqueda semántica suele ser la herramienta inicial incorrecta. Es mejor una consulta determinista a la base de datos.",{"data":278,"type":42},{"text":279,"level":230},"Respuesta directa",{"data":281,"type":217},{"text":282},"Una fuente de datos para un LLM es cualquier sistema externo del que una aplicación pueda obtener información para el modelo: archivos, bases de datos, API, índices de búsqueda, almacenes vectoriales o estado de la aplicación en vivo. RAG es el patrón de \u003Cb>recuperar conocimiento relevante de dichas fuentes antes de la generación\u003C\u002Fb>.",{"data":284,"type":217},{"text":285},"En Python, el pipeline esencial puede ser muy pequeño: \u003Cb>cargar datos → crear unidades recuperables → encontrar evidencia relevante → ensamblar el contexto → llamar al LLM\u003C\u002Fb>. El método de recuperación debe coincidir con la fuente y la pregunta. Use SQL para hechos estructurados exactos, búsqueda de texto completo para coincidencia léxica, embeddings para similitud semántica y recuperación híbrida cuando varias señales sean valiosas.",{"data":287,"type":42},{"text":288,"level":230},"Por qué es así",{"data":290,"type":217},{"text":291},"Un modelo de lenguaje no recibe automáticamente el contenido de su sistema de archivos, base de datos PostgreSQL, CRM, API privada o documento recién editado. La aplicación decide qué información externa es accesible y qué se coloca en el contexto actual del modelo.",{"data":293,"type":217},{"text":294},"El trabajo original de Generación Aumentada por Recuperación de Lewis et al. combinó un modelo generativo con memoria externa no paramétrica recuperada de un índice vectorial denso. La idea arquitectónica más amplia sobrevive más allá de esa implementación específica: la evidencia externa puede recuperarse en el momento de la inferencia en lugar de esperar que todo el conocimiento útil esté codificado en los parámetros del modelo.",{"data":296,"type":217},{"text":297},"Esto crea una separación útil de responsabilidades: la fuente almacena información, el recuperador selecciona evidencia, el contexto lleva esa evidencia a la solicitud y el modelo la interpreta. Mantener visibles esos límites hace que los fallos sean mucho más fáciles de diagnosticar.",{"data":299,"type":42},{"text":300,"level":230},"Contexto: los principales tipos de fuentes de datos",{"data":302,"type":336},{"content":303,"withHeadings":14},[304,308,312,316,320,324,328,332],[305,306,307],"Fuente","Método de recuperación típico","Bueno para",[309,310,311],"TXT \u002F Markdown \u002F HTML","Análisis + búsqueda léxica o semántica","Documentación, manuales, artículos, notas",[313,314,315],"PDF \u002F DOCX","Extracción consciente de la estructura + búsqueda","Políticas, informes, contratos, manuales",[317,318,319],"Base de datos SQL","Consulta SQL o recuperación filtrada","Pedidos, usuarios, productos, registros estructurados",[321,322,323],"API REST \u002F GraphQL","Solicitud HTTP con parámetros","Sistemas remotos y datos de servicios en vivo",[325,326,327],"Índice de búsqueda","BM25 \u002F texto completo \u002F búsqueda híbrida","Grandes colecciones de texto",[329,330,331],"Índice vectorial","Similitud de embeddings","Recuperación semántica de documentos",[333,334,335],"Estado de la aplicación","Lectura directa del estado o llamada a herramienta","Lo que es verdad en este momento","table",{"data":338,"type":217},{"text":339},"Un índice vectorial merece especial atención. En muchas arquitecturas \u003Cb>no es la fuente canónica de verdad\u003C\u002Fb>. Es un índice de recuperación derivado de documentos o registros. El documento autoritativo puede residir en almacenamiento de objetos, un CMS, Git, PostgreSQL u otro sistema, mientras que los embeddings y metadatos se almacenan por separado para una búsqueda semántica rápida. Algunos sistemas sí usan un almacén vectorial como almacenamiento primario, pero eso es una elección arquitectónica más que un requisito de RAG.",{"data":341,"type":217},{"text":342},"Si el límite entre recuperación, memoria persistente, estado actual y contexto del modelo aún no está claro, consulte \u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fes\u002Fblog\u002Fai-agent-memory-is-not-rag-how-to-separate-memory-retrieval-state-and-context\">La memoria del agente de IA no es RAG\u003C\u002Fa>. Esas capas pueden usar algunas de las mismas tecnologías de almacenamiento y aun así tener reglas de corrección diferentes.",{"data":344,"type":42},{"text":345,"level":230},"Supuestos",{"data":347,"type":357},{"items":348,"style":356},[349,350,351,352,353,354,355],"La aplicación tiene permitido acceder a la fuente externa.","La fuente relevante contiene suficiente información para responder la pregunta.","Los datos pueden analizarse o consultarse en una forma que la capa de recuperación pueda usar.","La información recuperada es lo suficientemente reciente para la decisión solicitada.","El modelo recibe la evidencia seleccionada en su contexto.","La autorización se aplica antes de que la evidencia protegida llegue al modelo.","El modelo de generación aún puede equivocarse incluso cuando la recuperación es correcta.","unordered","list",{"data":359,"type":217},{"text":360},"Estos supuestos importan porque la recuperación no puede compensar evidencia faltante, versiones obsoletas de la fuente, analizadores defectuosos o acceso no autorizado. Un pipeline RAG solo puede ser tan confiable como la ruta de evidencia que lo alimenta.",{"data":362,"type":42},{"text":363,"level":230},"Variables",{"data":365,"type":336},{"content":366,"withHeadings":14},[367,370,373,376,379,382,385,388,391],[368,369],"Variable","Por qué cambia el diseño",[371,372],"Estructura de la fuente","Una tabla SQL, un PDF legal y un repositorio de código fuente necesitan estrategias de recuperación diferentes",[374,375],"Tipo de pregunta","La búsqueda exacta, la búsqueda conceptual y la investigación de múltiples saltos son tareas diferentes",[377,378],"Requisito de actualidad","El estado en vivo puede necesitar consultas directas en lugar de índices reconstruidos periódicamente",[380,381],"Tamaño del corpus","La búsqueda en memoria puede funcionar para cientos de fragmentos, pero no para colecciones muy grandes",[383,384],"Idioma","La recuperación multilingüe requiere modelos y tokenización adecuados para los idiomas reales",[386,387],"Permisos","La recuperación debe filtrar según los derechos de acceso del usuario actual",[389,390],"Latencia y costo","Más etapas de recuperación pueden mejorar la calidad, pero añaden costo de ejecución e infraestructura",[392,393],"Necesidad de procedencia","Los sistemas de alta confianza necesitan IDs de fuente, versiones y evidencia trazable",{"data":395,"type":42},{"text":396,"level":230},"Método de diagnóstico \u002F decisión",{"data":398,"type":217},{"text":399},"La primera decisión no es \"¿Qué base de datos vectorial debería instalar?\" Es: \u003Cb>¿Qué tipo de hecho estoy tratando de recuperar?\u003C\u002Fb>",{"data":401,"type":336},{"content":402,"withHeadings":14},[403,406,410,414,418,422],[374,404,405],"Enfoque preferido inicial","Razón",[407,408,409],"ID exacto o registro actual","SQL \u002F búsqueda por clave \u002F API","Acceso estructurado determinista",[411,412,413],"Redacción exacta, códigos, nombres","Búsqueda de texto completo o por palabra clave","Precisión léxica",[415,416,417],"Pregunta conceptual sobre documentos","Búsqueda vectorial semántica","El significado puede diferir de la redacción",[419,420,421],"Conocimiento empresarial mixto","Recuperación híbrida + filtros de metadatos","Combina señales léxicas y semánticas",[423,424,425],"Estado actual de la aplicación","Acceso directo al estado\u002Fherramienta","La frescura importa más que la similitud de documentos",{"data":427,"type":217},{"text":428},"Una prueba útil es: \u003Cb>¿Ya sé qué registro necesito, o el sistema debe descubrir qué pasaje es relevante?\u003C\u002Fb> Si el registro se conoce, consúltalo directamente. Si la relevancia debe descubrirse, la búsqueda cobra mayor importancia.",{"data":430,"type":217},{"text":431},"Cuando una respuesta es incorrecta, diagnostica el pipeline en orden en lugar de cambiar inmediatamente el LLM:",{"data":433,"type":357},{"items":434,"style":444},[435,436,437,438,439,440,441,442,443],"\u003Cb>1. Cobertura de fuentes:\u003C\u002Fb> ¿Existe la información correcta en el conjunto de fuentes accesibles?","\u003Cb>2. Frescura:\u003C\u002Fb> ¿Es esa versión lo suficientemente actual para la pregunta?","\u003Cb>3. Análisis:\u003C\u002Fb> ¿Se extrajo correctamente el contenido relevante?","\u003Cb>4. Fragmentación:\u003C\u002Fb> ¿Permaneció la evidencia junto con las condiciones que le dan significado?","\u003Cb>5. Recuperación:\u003C\u002Fb> ¿Aparece el fragmento correcto entre los candidatos?","\u003Cb>6. Clasificación:\u003C\u002Fb> ¿Están las fuentes más sólidas clasificadas por encima de las más débiles o conflictivas?","\u003Cb>7. Ensamblaje del contexto:\u003C\u002Fb> ¿Envió realmente la aplicación la evidencia seleccionada al modelo?","\u003Cb>8. Generación:\u003C\u002Fb> ¿Utilizó el LLM fielmente la evidencia proporcionada?","\u003Cb>9. Atribución:\u003C\u002Fb> ¿Se puede rastrear cada afirmación importante hasta una fuente?","ordered",{"data":446,"type":217},{"text":447},"Para un método más profundo de depuración en producción, consulta \u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fes\u002Fblog\u002Frag-failed-but-which-layer-actually-failed-a-diagnostic-method\">RAG Failed — But Which Layer Actually Failed? A Diagnostic Method\u003C\u002Fa>, que amplía esta cadena en capas de fallo comprobables de forma independiente.",{"data":449,"type":42},{"text":450,"level":230},"Evidencia",{"data":452,"type":217},{"text":453},"El artículo de RAG de Lewis et al. formalizó la generación que se condiciona a la memoria externa recuperada en lugar de depender solo de los parámetros del modelo. Eso proporciona la base conceptual para separar el generador de una fuente de conocimiento recuperable.",{"data":455,"type":217},{"text":456},"Sentence Transformers documenta la búsqueda semántica como incrustar el corpus y la consulta en un espacio vectorial y recuperar elementos con alta similitud semántica. Su API actual también distingue la codificación de consultas de la codificación de documentos para tareas de recuperación.",{"data":458,"type":217},{"text":459},"SQLite FTS5 demuestra el otro lado del espectro: la recuperación de texto completo madura puede clasificar documentos sin incrustaciones. Esto importa porque la búsqueda léxica sigue siendo valiosa para identificadores, terminología exacta y muchos diseños de recuperación híbrida.",{"data":461,"type":217},{"text":462},"La documentación de incrustaciones de OpenAI describe las incrustaciones como representaciones vectoriales numéricas utilizadas para la relación y la búsqueda. Esta es una ruta de implementación para la recuperación semántica, no la definición de RAG en sí.",{"data":464,"type":42},{"text":465,"level":230},"Ejemplo real 1: Una carpeta de archivos de texto",{"data":467,"type":217},{"text":468},"Supongamos que un directorio llamado \u003Ccode>knowledge\u002F\u003C\u002Fcode> contiene archivos de texto ordinarios. Python puede cargarlos sin ninguna biblioteca de IA.",{"data":470,"type":252},{"code":471},"from pathlib import Path\n\ndef load_text_files(folder=\"knowledge\"):\n    documents = []\n\n    for path in Path(folder).glob(\"*.txt\"):\n        documents.append({\n            \"source\": path.name,\n            \"text\": path.read_text(encoding=\"utf-8\")\n        })\n\n    return documents\n\ndocuments = load_text_files()\n\nfor document in documents:\n    print(document[\"source\"], len(document[\"text\"]))",{"data":473,"type":217},{"text":474},"El sistema de archivos es la fuente de datos. La siguiente pregunta es cuánto texto debe convertirse en una unidad recuperable. Para documentos largos, buscar un archivo completo suele ser demasiado grueso. Por eso los pipelines de RAG comúnmente crean fragmentos.",{"data":476,"type":42},{"text":477,"level":478},"Un fragmentador muy simple",3,{"data":480,"type":252},{"code":481},"def chunk_text(text, max_chars=800):\n    paragraphs = [p.strip() for p in text.split(\"\\n\\n\") if p.strip()]\n\n    chunks = []\n    current = \"\"\n\n    for paragraph in paragraphs:\n        candidate = f\"{current}\\n\\n{paragraph}\".strip()\n\n        if current and len(candidate) > max_chars:\n            chunks.append(current)\n            current = paragraph\n        else:\n            current = candidate\n\n    if current:\n        chunks.append(current)\n\n    return chunks",{"data":483,"type":217},{"text":484},"Este ejemplo agrupa párrafos hasta alcanzar un límite aproximado de caracteres. Es intencionalmente comprensible en lugar de óptimo. Los sistemas de producción a menudo fragmentan por tokens, encabezados, secciones, límites de oraciones o estructura del documento. Las tablas, el código fuente, los contratos y la documentación de API pueden necesitar estrategias diferentes.",{"data":486,"type":42},{"text":487,"level":478},"Preservar la procedencia al dividir en fragmentos",{"data":489,"type":252},{"code":490},"def build_chunks(documents):\n    chunks = []\n\n    for document in documents:\n        for index, text in enumerate(chunk_text(document[\"text\"])):\n            chunks.append({\n                \"id\": f'{document[\"source\"]}:{index}',\n                \"source\": document[\"source\"],\n                \"chunk\": index,\n                \"text\": text,\n            })\n\n    return chunks",{"data":492,"type":217},{"text":493},"Un fragmento útil lleva más que texto. El nombre de la fuente, el ID del documento, la URL, la marca de tiempo, la versión o la sección pueden respaldar más adelante la citación, la depuración y las comprobaciones de actualidad. Si la procedencia se pierde durante la ingesta, resulta mucho más difícil explicar por qué se produjo una respuesta concreta.",{"data":495,"type":42},{"text":496,"level":230},"Ejemplo real 2: Datos estructurados — Use SQL cuando SQL es la herramienta adecuada",{"data":498,"type":217},{"text":499},"No todo hecho externo debe pasar por la búsqueda semántica. Si la pregunta solicita un registro actual exacto, una consulta directa a la base de datos suele ser más clara y más determinista.",{"data":501,"type":252},{"code":502},"import sqlite3\n\ndef get_order_status(order_id):\n    connection = sqlite3.connect(\"shop.db\")\n    cursor = connection.cursor()\n\n    cursor.execute(\n        \"SELECT status, total, currency FROM orders WHERE id = ?\",\n        (order_id,)\n    )\n\n    row = cursor.fetchone()\n    connection.close()\n\n    if row is None:\n        return None\n\n    return {\n        \"order_id\": order_id,\n        \"status\": row[0],\n        \"total\": row[1],\n        \"currency\": row[2],\n    }\n\nprint(get_order_status(4711))",{"data":504,"type":217},{"text":505},"Si la aplicación ya sabe que el usuario está preguntando por el pedido 4711, incrustar toda la tabla de pedidos y pedirle a la búsqueda semántica que redescubra esa fila normalmente añade complejidad sin beneficio. Una regla de diseño sólida es: \u003Cb>recupere hechos estructurados con consultas estructuradas; recupere conocimiento no estructurado con búsqueda.\u003C\u002Fb>",{"data":507,"type":217},{"text":508},"La fila de base de datos devuelta aún puede colocarse en el contexto del modelo para que el LLM pueda explicarla en lenguaje natural. Pero el acceso directo al estado o a un registro es conceptualmente diferente de buscar en un corpus de conocimiento.",{"data":510,"type":42},{"text":511,"level":230},"Ejemplo real 3: Búsqueda de texto completo antes de las incrustaciones",{"data":513,"type":217},{"text":514},"Entre un bucle ingenuo de Python y la búsqueda vectorial se encuentra una clase madura de sistemas de recuperación léxica. SQLite incluye FTS5 para búsqueda de texto completo, incluido el ranking BM25.",{"data":516,"type":252},{"code":517},"import sqlite3\n\nconnection = sqlite3.connect(\"knowledge.db\")\ncursor = connection.cursor()\n\ncursor.execute(\n    \"CREATE VIRTUAL TABLE IF NOT EXISTS docs USING fts5(title, body)\"\n)\n\ncursor.execute(\n    \"INSERT INTO docs(title, body) VALUES (?, ?)\",\n    (\"AKM\", \"The AKM uses 7.62 mm ammunition.\")\n)\n\nconnection.commit()\n\nquery = \"AKM ammunition\"\n\nrows = cursor.execute(\n    \"SELECT title, body, bm25(docs) AS score \"\n    \"FROM docs WHERE docs MATCH ? \"\n    \"ORDER BY score LIMIT 5\",\n    (query,)\n).fetchall()\n\nfor row in rows:\n    print(row)\n\nconnection.close()",{"data":519,"type":217},{"text":520},"La búsqueda léxica es especialmente útil cuando importan la terminología exacta, los códigos de producto, los nombres, los identificadores o las palabras específicas del dominio. La búsqueda semántica no es automáticamente mejor. Los sistemas de producción a menudo combinan ambas señales.",{"data":522,"type":42},{"text":523,"level":230},"Ejemplo real 4: Recuperación semántica con incrustaciones",{"data":525,"type":217},{"text":526},"Las incrustaciones convierten el texto en vectores numéricos para que los pasajes semánticamente relacionados puedan compararse incluso cuando no usan una redacción idéntica. Sentence Transformers proporciona una implementación local sencilla.",{"data":528,"type":252},{"code":529},"# pip install sentence-transformers\n\nfrom sentence_transformers import SentenceTransformer, util\n\ndocuments = [\n    \"The AKM uses 7.62 mm ammunition.\",\n    \"A Med Kit restores health.\",\n    \"Vehicle maintenance includes checking oil, brakes and tires.\",\n    \"Account recovery requires access to the registered email address.\"\n]\n\nmodel = SentenceTransformer(\n    \"sentence-transformers\u002Fmulti-qa-mpnet-base-cos-v1\"\n)\n\ndocument_embeddings = model.encode_document(\n    documents,\n    convert_to_tensor=True\n)\n\nquestion = \"How do I repair my car?\"\n\nquery_embedding = model.encode_query(\n    question,\n    convert_to_tensor=True\n)\n\nhits = util.semantic_search(\n    query_embedding,\n    document_embeddings,\n    top_k=2\n)[0]\n\nfor hit in hits:\n    print(round(float(hit[\"score\"]), 3), documents[hit[\"corpus_id\"]])",{"data":531,"type":217},{"text":532},"La consulta no contiene la frase “mantenimiento de vehículos”, pero un modelo semántico aún puede clasificar ese pasaje en un puesto alto porque los conceptos están relacionados. Esta es la razón práctica por la que las incrustaciones son comunes en los sistemas RAG.",{"data":534,"type":217},{"text":535},"Para colecciones pequeñas, las incrustaciones pueden permanecer en memoria. Los sistemas más grandes normalmente las persisten en un índice o base de datos con capacidad vectorial y realizan allí la búsqueda de vecinos más cercanos. El almacenamiento cambia, pero la lógica permanece: codificar la pregunta, encontrar representaciones de documentos relevantes, devolver la mejor evidencia.",{"data":537,"type":42},{"text":538,"level":230},"Ejemplo real 5: Construir el contexto para el LLM",{"data":540,"type":217},{"text":541},"Un recuperador debe devolver evidencia. El LLM debe entonces recibir la pregunta más esa evidencia. Mantener la recuperación y la generación separadas hace que ambas sean más fáciles de inspeccionar y probar.",{"data":543,"type":252},{"code":544},"def build_prompt(question, retrieved_documents):\n    context = \"\\n\\n\".join(\n        f'[{doc[\"id\"]}] {doc[\"text\"]}'\n        for doc in retrieved_documents\n    )\n\n    return f\"\"\"\nAnswer the question using the supplied context.\n\nRules:\n- Do not invent facts that are not supported by the context.\n- If the context is insufficient, say so.\n- Cite the source IDs you used.\n\nQuestion:\n{question}\n\nContext:\n{context}\n\"\"\".strip()",{"data":546,"type":217},{"text":547},"La instrucción no hace que el modelo sea infalible. Simplemente crea un límite de evidencia explícito. El modelo aún puede malinterpretar buena evidencia, ignorar una condición o generalizar en exceso. Por eso la calidad de la recuperación y la calidad de la generación deben evaluarse por separado.",{"data":549,"type":42},{"text":550,"level":230},"Ejemplo real 6: Un pipeline mínimo completo",{"data":552,"type":252},{"code":553},"def answer_question(question, all_documents, call_llm):\n    # 1. Retrieve evidence\n    retrieved = retrieve(question, all_documents, top_k=3)\n\n    # 2. Build model context\n    prompt = build_prompt(question, retrieved)\n\n    # 3. Generate the answer\n    answer = call_llm(prompt)\n\n    return {\n        \"answer\": answer,\n        \"sources\": [doc[\"id\"] for doc in retrieved]\n    }",{"data":555,"type":217},{"text":556},"La función recibe \u003Ccode>call_llm\u003C\u002Fcode> como dependencia a propósito. A la recuperación no debería importarle si la generación la realiza un modelo en la nube, un modelo local u otro proveedor. La ruta de datos pertenece a la aplicación.",{"data":558,"type":42},{"text":559,"level":478},"Generador opcional: API de Responses de OpenAI",{"data":561,"type":217},{"text":562},"Un generador posible es la API de Responses de OpenAI. Mantener el nombre del modelo en una variable de entorno evita codificar de forma rígida un modelo concreto en la arquitectura RAG.",{"data":564,"type":252},{"code":565},"# pip install openai\n\nimport os\nfrom openai import OpenAI\n\nclient = OpenAI()\n\ndef call_llm(prompt):\n    response = client.responses.create(\n        model=os.environ[\"OPENAI_MODEL\"],\n        input=prompt,\n    )\n    return response.output_text",{"data":567,"type":217},{"text":568},"El mismo pipeline de recuperación puede conectarse a un servidor de inferencia local. Este es un punto arquitectónico importante: \u003Cb>RAG no es propiedad del proveedor del LLM.\u003C\u002Fb> La aplicación es dueña de la fuente, la recuperación y el ensamblaje del contexto.",{"data":570,"type":42},{"text":571,"level":478},"Toda la arquitectura en una vista",{"data":573,"type":252},{"code":574},"USER QUESTION\n     |\n     v\n+-------------+\n|  Retriever  |\n+-------------+\n   |       |\n   |       +----> SQL \u002F API \u002F state query\n   |\n   +------------> keyword \u002F full-text search\n   |\n   +------------> embedding \u002F vector search\n                     |\n                     v\n              relevant evidence\n                     |\n                     v\n+-----------------------------------+\n| question + evidence + instructions |\n+-----------------------------------+\n                     |\n                     v\n                   LLM\n                     |\n                     v\n                  answer",{"data":576,"type":217},{"text":577},"Este modelo de flujo de datos es más duradero que memorizar un framework. Las bibliotecas, las bases de datos y los proveedores de modelos cambiarán; los límites de responsabilidad permanecen.",{"data":579,"type":42},{"text":580,"level":230},"Conceptos erróneos comunes y modos de fallo",{"data":582,"type":42},{"text":583,"level":478},"“RAG significa base de datos vectorial.”",{"data":585,"type":217},{"text":586},"No. La búsqueda vectorial es un método de recuperación. RAG puede usar búsqueda de texto completo, SQL, API, grafos de conocimiento, búsqueda vectorial o combinaciones de ellos. El patrón que lo define es la recuperación de información externa para la generación.",{"data":588,"type":42},{"text":589,"level":478},"“Si los datos están en PostgreSQL, debo incrustar toda la base de datos.”",{"data":591,"type":217},{"text":592},"No. Los registros estructurados normalmente deben seguir siendo consultables como registros estructurados. Los embeddings son útiles para la relevancia semántica, no como reemplazo de consultas deterministas.",{"data":594,"type":42},{"text":595,"level":478},"“Más fragmentos significa una mejor respuesta.”",{"data":597,"type":217},{"text":598},"No necesariamente. El contexto adicional puede introducir ruido, versiones en conflicto y material irrelevante. La recuperación debe optimizar para evidencia útil, no para el volumen máximo.",{"data":600,"type":42},{"text":601,"level":478},"“Una puntuación de similitud alta demuestra la respuesta.”",{"data":603,"type":217},{"text":604},"No. La similitud mide la relevancia, no la verdad ni la aplicabilidad. Un pasaje altamente similar puede estar desactualizado, provenir de la versión incorrecta del producto o ser válido solo bajo condiciones que no coinciden con la pregunta.",{"data":606,"type":42},{"text":607,"level":478},"“Una vez que se recupera el fragmento correcto, la alucinación está resuelta.”",{"data":609,"type":217},{"text":610},"No. La recuperación mejora el anclaje pero no garantiza un razonamiento fiel. La generación aún necesita evaluación, y los flujos de trabajo de alto riesgo pueden requerir validación determinista o revisión humana.",{"data":612,"type":42},{"text":613,"level":478},"“El modelo falló, así que cambia el modelo.”",{"data":615,"type":217},{"text":616},"No necesariamente. La fuente correcta puede haber faltado, haberse analizado incorrectamente, dividido mal, filtrado, clasificado demasiado bajo u omitido del contexto ensamblado. El reemplazo del modelo no debería ser el primer paso de diagnóstico.",{"data":618,"type":42},{"text":619,"level":230},"Casos límite",{"data":621,"type":357},{"items":622,"style":356},[623,624,625,626,627,628,629,630],"\u003Cb>Documentos en conflicto:\u003C\u002Fb> dos fuentes pueden discrepar porque las versiones, jurisdicciones o productos difieren.","\u003Cb>Hechos sensibles al tiempo:\u003C\u002Fb> una fuente semánticamente relevante puede ya estar obsoleta.","\u003Cb>Permisos:\u003C\u002Fb> un recuperador no debe devolver documentos a los que el usuario actual no está autorizado a acceder.","\u003Cb>Colecciones multilingües:\u003C\u002Fb> el modelo de incrustación y la estrategia de recuperación deben admitir los idiomas realmente utilizados.","\u003Cb>Tablas y código fuente:\u003C\u002Fb> la división en párrafos simples puede destruir la estructura que es esencial para la respuesta.","\u003Cb>Identificadores muy cortos:\u003C\u002Fb> la recuperación semántica puede ser más débil que la coincidencia exacta para SKU, ID, códigos de error o acrónimos.","\u003Cb>Preguntas largas que requieren varios hechos:\u003C\u002Fb> la recuperación puede necesitar descomposición, varias búsquedas o reclasificación en lugar de una sola consulta top-k.","\u003Cb>Jerarquía de fuentes:\u003C\u002Fb> una política oficial actual puede necesitar superar a un documento de discusión más antiguo pero semánticamente más cercano.",{"data":632,"type":42},{"text":633,"level":230},"Limitaciones",{"data":635,"type":217},{"text":636},"Los ejemplos de Python optimizan intencionalmente la transparencia, no la escala. El recuperador de palabras clave es ingenuo, el fragmentador usa longitud de caracteres, los ejemplos de SQLite no incluyen gestión de conexiones de producción, y el ejemplo semántico mantiene todas las incrustaciones en memoria.",{"data":638,"type":217},{"text":639},"Un sistema de producción puede requerir índices vectoriales, reclasificadores, recuperación híbrida, analizadores de documentos, almacenamiento en caché, indexación incremental, versionado de fuentes, filtros de control de acceso, observabilidad, conjuntos de datos de evaluación y manejo de fallos. Ninguna de esas adiciones cambia la arquitectura central; hacen que cada límite sea más confiable.",{"data":641,"type":217},{"text":642},"RAG tampoco puede crear evidencia que esté ausente del conjunto de fuentes. Si la fuente es incorrecta, incompleta u obsoleta, un mejor modelo de incrustación no puede convertirla en conocimiento autorizado.",{"data":644,"type":42},{"text":645,"level":230},"¿Qué cambiaría esta respuesta?",{"data":647,"type":217},{"text":648},"La arquitectura cambia cuando la tarea requiere más que una búsqueda de conocimiento. Un estado de pedido en vivo necesita el estado actual. Un cálculo financiero puede necesitar código determinista. Una tarea de investigación web puede necesitar búsqueda activa. Un flujo de trabajo puede necesitar herramientas que puedan escribir datos de vuelta a otro sistema. Un agente autónomo puede necesitar planificación, permisos y control de ejecución además de la recuperación.",{"data":650,"type":217},{"text":651},"Por lo tanto, RAG se entiende mejor como \u003Cb>una capa de adquisición de evidencia dentro de un sistema de IA más grande\u003C\u002Fb>. Es poderoso precisamente porque tiene un trabajo limitado: encontrar información externa útil y colocarla en el contexto de trabajo del modelo.",{"data":653,"type":42},{"text":654,"level":230},"Conclusión",{"data":656,"type":217},{"text":657},"RAG se vuelve mucho más fácil de entender cuando se eliminan los nombres de las tecnologías. Un archivo es una fuente. Una base de datos es una fuente. Una API es una fuente. Una función de búsqueda recupera evidencia. Un prompt lleva esa evidencia al modelo. El LLM luego la interpreta y produce lenguaje.",{"data":659,"type":217},{"text":660},"La parte difícil de RAG en producción no es llamar a un modelo de embeddings. Es construir una ruta de evidencia confiable desde la fuente original hasta la afirmación final: preservar la procedencia, seleccionar el método de recuperación adecuado, mantener la información actualizada, controlar el acceso, evaluar la recuperación por separado de la generación y saber cuándo una llamada directa a una base de datos o a una herramienta es mejor que la búsqueda semántica.",{"data":662,"type":217},{"text":663},"Esa es la continuación práctica del modelo básico de RAG: \u003Cb>primero entender los roles, luego hacer explícita la ruta de datos.\u003C\u002Fb>",{"data":665,"type":42},{"text":666,"level":230},"Fuentes primarias",{"data":668,"type":357},{"items":669,"style":356},[670,671,672,673,674,675],"\u003Ca href=\"https:\u002F\u002Farxiv.org\u002Fabs\u002F2005.11401\">Lewis et al. — Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks\u003C\u002Fa> — el artículo de 2020 que introdujo la formulación de RAG que combina la generación con memoria no paramétrica recuperada.","\u003Ca href=\"https:\u002F\u002Fwww.sbert.net\u002Fexamples\u002Fsentence_transformer\u002Fapplications\u002Fsemantic-search\u002FREADME.html\">Sentence Transformers — Semantic Search\u003C\u002Fa> — documentación oficial para la recuperación semántica, embeddings de consultas y embeddings de documentos.","\u003Ca href=\"https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Fguides\u002Fembeddings\">OpenAI — Vector Embeddings\u003C\u002Fa> — documentación oficial que describe los embeddings como representaciones numéricas utilizadas para la relación y la búsqueda.","\u003Ca href=\"https:\u002F\u002Fwww.sqlite.org\u002Ffts5.html\">SQLite — FTS5 Extension\u003C\u002Fa> — documentación oficial para la búsqueda de texto completo y la clasificación BM25 en SQLite.","\u003Ca href=\"https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Flibraries\">OpenAI — SDKs and CLI\u003C\u002Fa> — ejemplo oficial del SDK de Python para la API de Responses utilizado en el ejemplo opcional del generador.","\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fes\u002Fblog\u002Fwhat-is-rag-the-simplest-explanation-of-how-it-works\">What Is RAG? The Simplest Explanation of How It Works\u003C\u002Fa> — la primera parte conceptual de esta serie.","2.31","Un LLM no conoce mágicamente tus archivos, bases de datos o APIs. Esta continuación práctica de la serie RAG muestra, con Python sencillo, cómo los datos externos se convierten en evidencia recuperable: desde archivos de texto y SQL hasta búsqueda de texto completo, embeddings, ensamblaje de contexto y la llamada final al LLM.","\u002Fuploads\u002F2026\u002F09\u002Fwhere-does-an-llm-get-its-data-rag-data-sources-in-python-1790517200521-nfsi5i.webp","where-does-an-llm-get-its-data-rag-data-sources-in-python-1790517200521-nfsi5i","PUBLISHED","2026-09-27T09:51:00.000Z","2026-09-27T13:51:43.843Z","2026-09-27T13:58:03.762Z",{"en":685,"de":686,"sr":687,"es":688,"fr":689,"it":690,"ru":691,"zh":692},"\u002Fblog\u002Fwhere-does-an-llm-get-its-data-rag-data-sources-in-python","\u002Fde\u002Fblog\u002Fwhere-does-an-llm-get-its-data-rag-data-sources-in-python","\u002Fsr\u002Fblog\u002Fwhere-does-an-llm-get-its-data-rag-data-sources-in-python","\u002Fes\u002Fblog\u002Fwhere-does-an-llm-get-its-data-rag-data-sources-in-python","\u002Ffr\u002Fblog\u002Fwhere-does-an-llm-get-its-data-rag-data-sources-in-python","\u002Fit\u002Fblog\u002Fwhere-does-an-llm-get-its-data-rag-data-sources-in-python","\u002Fru\u002Fblog\u002Fwhere-does-an-llm-get-its-data-rag-data-sources-in-python","\u002Fzh\u002Fblog\u002Fwhere-does-an-llm-get-its-data-rag-data-sources-in-python",[],{"id":695,"login":696,"email":697,"displayName":698},"20","rooth8233","aleksandar@stajic.de","Aleksandar Stajić",[700,1145],{"lang":701,"title":702,"content":703,"contentJson":704,"excerpt":1144},"en","Where Does an LLM Get Its Data? RAG Data Sources in Python","{\"time\":1790516400000,\"blocks\":[{\"data\":{\"text\":\"The previous article, \u003Ca href=\\\"https:\u002F\u002Fstajic.de\u002Fblog\u002Fwhat-is-rag-the-simplest-explanation-of-how-it-works\\\">What Is RAG? The Simplest Explanation of How It Works\u003C\u002Fa>, established the mental model: the LLM writes, RAG retrieves useful knowledge, the application owns current state, and tools perform actions. This article takes the next step: \u003Cb>where does the data actually come from, and what does retrieval look like in Python?\u003C\u002Fb>\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"The important surprise is that an “LLM data source” is usually nothing exotic. It can be a text file, a folder of Markdown documents, a SQL database, an API response, a product catalog, a support system, or a vector index derived from those sources. The AI does not magically know these systems. Your application has to load, query, search, or retrieve the relevant data and place the result into the model’s context.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Data source = where information lives. Retrieval = how the application finds useful information. Context = the selected information given to the model. LLM = the component that interprets that context and generates an answer.\",\"caption\":\"The four-part model used throughout this article\",\"alignment\":\"left\"},\"type\":\"quote\"},{\"data\":{\"text\":\"Question\",\"level\":2},\"type\":\"header\"},{\"data\":{\"text\":\"How does an LLM use external data such as files, databases or APIs, and how can a small Python program implement the essential RAG steps without hiding them behind a framework?\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"What This Really Means\",\"level\":2},\"type\":\"header\"},{\"data\":{\"text\":\"When developers say that an LLM is “connected to company data,” several different operations may be hidden behind that sentence. One application may execute SQL. Another may call an API. Another may run full-text search. Another may calculate embedding similarity over document chunks. All of them can provide external information to an LLM, but they are not the same retrieval method and they should not be treated as interchangeable.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"This distinction matters because the best retrieval method depends on the shape of the question. “What is our refund policy?” is a document-retrieval problem. “What is order 4711’s current status?” is usually a structured database lookup. “Which paragraph discusses account recovery?” can be keyword or semantic search. RAG is most useful when the system must \u003Cb>discover relevant knowledge before generation\u003C\u002Fb>.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Simplest Example\",\"level\":2},\"type\":\"header\"},{\"data\":{\"text\":\"Start with three strings in ordinary Python. There is no vector database, no framework, and no LLM yet. We only want to make the retrieval step visible.\"},\"type\":\"paragraph\"},{\"data\":{\"code\":\"documents = [\\n    \\\"The AKM uses 7.62 mm ammunition.\\\",\\n    \\\"A Med Kit restores health.\\\",\\n    \\\"A 4x scope can be attached to several compatible weapons.\\\"\\n]\\n\\nquestion = \\\"Which ammunition does the AKM use?\\\"\\n\\nfor document in documents:\\n    if \\\"AKM\\\" in document:\\n        print(document)\"},\"type\":\"code\"},{\"data\":{\"text\":\"The program prints the first sentence because it contains the term we searched for. This is primitive retrieval, but the architecture is already visible: \u003Cb>question → search → relevant text\u003C\u002Fb>. RAG adds one more major step: pass the retrieved text to a language model together with the question.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"A slightly more general version ranks documents by overlapping query terms:\"},\"type\":\"paragraph\"},{\"data\":{\"code\":\"import re\\n\\ndocuments = [\\n    {\\\"id\\\": \\\"weapon-akm\\\", \\\"text\\\": \\\"The AKM uses 7.62 mm ammunition.\\\"},\\n    {\\\"id\\\": \\\"healing-medkit\\\", \\\"text\\\": \\\"A Med Kit restores health.\\\"},\\n    {\\\"id\\\": \\\"scope-4x\\\", \\\"text\\\": \\\"A 4x scope can be attached to several compatible weapons.\\\"},\\n]\\n\\ndef words(text):\\n    return set(re.findall(r\\\"[a-zA-Z0-9.]+\\\", text.lower()))\\n\\ndef retrieve(question, documents, top_k=2):\\n    query_terms = words(question)\\n    ranked = []\\n\\n    for document in documents:\\n        score = len(query_terms & words(document[\\\"text\\\"]))\\n        if score > 0:\\n            ranked.append((score, document))\\n\\n    ranked.sort(key=lambda item: item[0], reverse=True)\\n    return [document for _, document in ranked[:top_k]]\\n\\nquestion = \\\"Which ammunition does the AKM use?\\\"\\nhits = retrieve(question, documents)\\n\\nfor hit in hits:\\n    print(hit[\\\"id\\\"], \\\"->\\\", hit[\\\"text\\\"])\"},\"type\":\"code\"},{\"data\":{\"text\":\"This is not a production search engine. It ignores morphology, synonyms, spelling variants, document length and many ranking signals. Its value is educational: \u003Cb>RAG does not begin with a vector database. It begins with retrieval.\u003C\u002Fb>\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Where the Example Stops Working\",\"level\":2},\"type\":\"header\"},{\"data\":{\"text\":\"Exact or lexical matching becomes weak when the question and the source use different words. A document may say “vehicle maintenance,” while the user asks “how do I repair my car?” A lexical retriever can miss the relationship even though a human sees it immediately. Semantic retrieval addresses this by representing text as vectors and comparing meaning rather than only exact tokens.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Long files create another problem. Searching an entire 80-page manual as one unit is too coarse, but splitting every sentence can destroy useful context. Real RAG systems therefore need decisions about parsing, chunking, metadata, ranking, freshness, permissions and provenance.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"The example also says nothing about structured live facts. If the user asks for the current status of order 4711 and the application already has a database key, semantic search is usually the wrong first tool. A deterministic database query is better.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Direct Answer\",\"level\":2},\"type\":\"header\"},{\"data\":{\"text\":\"An LLM data source is any external system from which an application can obtain information for the model: files, databases, APIs, search indexes, vector stores or live application state. RAG is the pattern of \u003Cb>retrieving relevant knowledge from such sources before generation\u003C\u002Fb>.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"In Python, the essential pipeline can be very small: \u003Cb>load data → create retrievable units → find relevant evidence → assemble context → call the LLM\u003C\u002Fb>. The retrieval method should match the source and the question. Use SQL for exact structured facts, full-text search for lexical matching, embeddings for semantic similarity, and hybrid retrieval when several signals are valuable.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Why This Is So\",\"level\":2},\"type\":\"header\"},{\"data\":{\"text\":\"A language model does not automatically receive the contents of your filesystem, PostgreSQL database, CRM, private API or newly edited document. The application decides what external information is accessible and what is placed into the model’s current context.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"The original Retrieval-Augmented Generation work by Lewis et al. combined a generative model with external non-parametric memory retrieved from a dense vector index. The broader architectural idea survives beyond that specific implementation: external evidence can be retrieved at inference time instead of expecting all useful knowledge to be encoded in model parameters.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"This creates a useful separation of responsibilities: the source stores information, the retriever selects evidence, the context carries that evidence into the request, and the model interprets it. Keeping those boundaries visible makes failures much easier to diagnose.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Context: The Main Types of Data Sources\",\"level\":2},\"type\":\"header\"},{\"data\":{\"content\":[[\"Source\",\"Typical retrieval method\",\"Good for\"],[\"TXT \u002F Markdown \u002F HTML\",\"Parsing + lexical or semantic search\",\"Documentation, manuals, articles, notes\"],[\"PDF \u002F DOCX\",\"Structure-aware extraction + search\",\"Policies, reports, contracts, manuals\"],[\"SQL database\",\"SQL query or filtered retrieval\",\"Orders, users, products, structured records\"],[\"REST \u002F GraphQL API\",\"HTTP request with parameters\",\"Remote systems and live service data\"],[\"Search index\",\"BM25 \u002F full-text \u002F hybrid search\",\"Large text collections\"],[\"Vector index\",\"Embedding similarity\",\"Semantic document retrieval\"],[\"Application state\",\"Direct state read or tool call\",\"What is true right now\"]],\"withHeadings\":true},\"type\":\"table\"},{\"data\":{\"text\":\"A vector index deserves special attention. In many architectures it is \u003Cb>not the canonical source of truth\u003C\u002Fb>. It is a retrieval index derived from documents or records. The authoritative document may live in object storage, a CMS, Git, PostgreSQL or another system, while embeddings and metadata are stored separately for fast semantic lookup. Some systems do use a vector store as primary storage, but that is an architectural choice rather than a requirement of RAG.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"If the boundary between retrieval, persistent memory, current state and model context is still unclear, see \u003Ca href=\\\"https:\u002F\u002Fstajic.de\u002Fblog\u002Fai-agent-memory-is-not-rag-how-to-separate-memory-retrieval-state-and-context\\\">AI Agent Memory Is Not RAG\u003C\u002Fa>. Those layers can use some of the same storage technologies while still having different correctness rules.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Assumptions\",\"level\":2},\"type\":\"header\"},{\"data\":{\"items\":[\"The application is allowed to access the external source.\",\"The relevant source contains enough information to answer the question.\",\"The data can be parsed or queried in a form the retrieval layer can use.\",\"The retrieved information is fresh enough for the requested decision.\",\"The model receives the selected evidence in its context.\",\"Authorization is enforced before protected evidence reaches the model.\",\"The generation model can still be wrong even when retrieval is correct.\"],\"style\":\"unordered\"},\"type\":\"list\"},{\"data\":{\"text\":\"These assumptions matter because retrieval cannot compensate for missing evidence, stale source versions, broken parsers or unauthorized access. A RAG pipeline can only be as trustworthy as the evidence path that feeds it.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Variables\",\"level\":2},\"type\":\"header\"},{\"data\":{\"content\":[[\"Variable\",\"Why it changes the design\"],[\"Source structure\",\"A SQL table, legal PDF and source-code repository need different retrieval strategies\"],[\"Question type\",\"Exact lookup, conceptual search and multi-hop research are different tasks\"],[\"Freshness requirement\",\"Live state may need direct queries instead of periodically rebuilt indexes\"],[\"Corpus size\",\"In-memory search may work for hundreds of chunks but not for very large collections\"],[\"Language\",\"Multilingual retrieval requires models and tokenization suitable for the actual languages\"],[\"Permissions\",\"Retrieval must filter by the current user’s access rights\"],[\"Latency and cost\",\"More retrieval stages can improve quality but add runtime and infrastructure cost\"],[\"Need for provenance\",\"High-trust systems need source IDs, versions and traceable evidence\"]],\"withHeadings\":true},\"type\":\"table\"},{\"data\":{\"text\":\"Diagnostic \u002F Decision Method\",\"level\":2},\"type\":\"header\"},{\"data\":{\"text\":\"The first decision is not “Which vector database should I install?” It is: \u003Cb>What kind of fact am I trying to retrieve?\u003C\u002Fb>\"},\"type\":\"paragraph\"},{\"data\":{\"content\":[[\"Question type\",\"Preferred first approach\",\"Reason\"],[\"Exact ID or current record\",\"SQL \u002F key lookup \u002F API\",\"Deterministic structured access\"],[\"Exact wording, codes, names\",\"Full-text or keyword search\",\"Lexical precision\"],[\"Conceptual question over documents\",\"Semantic vector search\",\"Meaning can differ from wording\"],[\"Mixed enterprise knowledge\",\"Hybrid retrieval + metadata filters\",\"Combines lexical and semantic signals\"],[\"Current application state\",\"Direct state\u002Ftool access\",\"Freshness matters more than document similarity\"]],\"withHeadings\":true},\"type\":\"table\"},{\"data\":{\"text\":\"A useful test is: \u003Cb>Do I already know which record I need, or must the system discover which passage is relevant?\u003C\u002Fb> If the record is known, query it directly. If relevance must be discovered, search becomes more important.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"When an answer is wrong, diagnose the pipeline in order instead of immediately changing the LLM:\"},\"type\":\"paragraph\"},{\"data\":{\"items\":[\"\u003Cb>1. Source coverage:\u003C\u002Fb> Does the correct information exist in the accessible source set?\",\"\u003Cb>2. Freshness:\u003C\u002Fb> Is that version current enough for the question?\",\"\u003Cb>3. Parsing:\u003C\u002Fb> Was the relevant content extracted correctly?\",\"\u003Cb>4. Chunking:\u003C\u002Fb> Did the evidence stay together with the conditions that give it meaning?\",\"\u003Cb>5. Retrieval:\u003C\u002Fb> Does the correct chunk appear among the candidates?\",\"\u003Cb>6. Ranking:\u003C\u002Fb> Are stronger sources ranked above weaker or conflicting ones?\",\"\u003Cb>7. Context assembly:\u003C\u002Fb> Did the application actually send the selected evidence to the model?\",\"\u003Cb>8. Generation:\u003C\u002Fb> Did the LLM faithfully use the supplied evidence?\",\"\u003Cb>9. Attribution:\u003C\u002Fb> Can each important claim be traced to a source?\"],\"style\":\"ordered\"},\"type\":\"list\"},{\"data\":{\"text\":\"For a deeper production-debugging method, see \u003Ca href=\\\"https:\u002F\u002Fstajic.de\u002Fblog\u002Frag-failed-but-which-layer-actually-failed-a-diagnostic-method\\\">RAG Failed — But Which Layer Actually Failed? A Diagnostic Method\u003C\u002Fa>, which expands this chain into independently testable failure layers.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Evidence\",\"level\":2},\"type\":\"header\"},{\"data\":{\"text\":\"The RAG paper by Lewis et al. formalized generation that conditions on retrieved external memory rather than relying only on model parameters. That provides the conceptual foundation for separating the generator from a retrievable knowledge source.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Sentence Transformers documents semantic search as embedding the corpus and the query into a vector space and retrieving items with high semantic similarity. Its current API also distinguishes query encoding from document encoding for retrieval tasks.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"SQLite FTS5 demonstrates the other side of the spectrum: mature full-text retrieval can rank documents without embeddings. This matters because lexical search remains valuable for identifiers, exact terminology and many hybrid retrieval designs.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"OpenAI’s embeddings documentation describes embeddings as numerical vector representations used for relatedness and search. This is one implementation path for semantic retrieval, not the definition of RAG itself.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Real Example 1: A Folder of Text Files\",\"level\":2},\"type\":\"header\"},{\"data\":{\"text\":\"Suppose a directory named \u003Ccode>knowledge\u002F\u003C\u002Fcode> contains ordinary text files. Python can load them with no AI library at all.\"},\"type\":\"paragraph\"},{\"data\":{\"code\":\"from pathlib import Path\\n\\ndef load_text_files(folder=\\\"knowledge\\\"):\\n    documents = []\\n\\n    for path in Path(folder).glob(\\\"*.txt\\\"):\\n        documents.append({\\n            \\\"source\\\": path.name,\\n            \\\"text\\\": path.read_text(encoding=\\\"utf-8\\\")\\n        })\\n\\n    return documents\\n\\ndocuments = load_text_files()\\n\\nfor document in documents:\\n    print(document[\\\"source\\\"], len(document[\\\"text\\\"]))\"},\"type\":\"code\"},{\"data\":{\"text\":\"The filesystem is the data source. The next question is how much text should become one retrievable unit. For long documents, searching one complete file is often too coarse. This is why RAG pipelines commonly create chunks.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"A Very Simple Chunker\",\"level\":3},\"type\":\"header\"},{\"data\":{\"code\":\"def chunk_text(text, max_chars=800):\\n    paragraphs = [p.strip() for p in text.split(\\\"\\\\n\\\\n\\\") if p.strip()]\\n\\n    chunks = []\\n    current = \\\"\\\"\\n\\n    for paragraph in paragraphs:\\n        candidate = f\\\"{current}\\\\n\\\\n{paragraph}\\\".strip()\\n\\n        if current and len(candidate) > max_chars:\\n            chunks.append(current)\\n            current = paragraph\\n        else:\\n            current = candidate\\n\\n    if current:\\n        chunks.append(current)\\n\\n    return chunks\"},\"type\":\"code\"},{\"data\":{\"text\":\"This example groups paragraphs until a rough character limit is reached. It is intentionally understandable rather than optimal. Production systems often chunk by tokens, headings, sections, sentence boundaries or document structure. Tables, source code, contracts and API documentation may need different strategies.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Preserve Provenance While Chunking\",\"level\":3},\"type\":\"header\"},{\"data\":{\"code\":\"def build_chunks(documents):\\n    chunks = []\\n\\n    for document in documents:\\n        for index, text in enumerate(chunk_text(document[\\\"text\\\"])):\\n            chunks.append({\\n                \\\"id\\\": f'{document[\\\"source\\\"]}:{index}',\\n                \\\"source\\\": document[\\\"source\\\"],\\n                \\\"chunk\\\": index,\\n                \\\"text\\\": text,\\n            })\\n\\n    return chunks\"},\"type\":\"code\"},{\"data\":{\"text\":\"A useful chunk carries more than text. Source name, document ID, URL, timestamp, version or section can later support citation, debugging and freshness checks. If provenance is lost during ingestion, it becomes much harder to explain why a particular answer was produced.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Real Example 2: Structured Data — Use SQL When SQL Is the Right Tool\",\"level\":2},\"type\":\"header\"},{\"data\":{\"text\":\"Not every external fact should go through semantic search. If the question asks for an exact current record, a direct database query is usually clearer and more deterministic.\"},\"type\":\"paragraph\"},{\"data\":{\"code\":\"import sqlite3\\n\\ndef get_order_status(order_id):\\n    connection = sqlite3.connect(\\\"shop.db\\\")\\n    cursor = connection.cursor()\\n\\n    cursor.execute(\\n        \\\"SELECT status, total, currency FROM orders WHERE id = ?\\\",\\n        (order_id,)\\n    )\\n\\n    row = cursor.fetchone()\\n    connection.close()\\n\\n    if row is None:\\n        return None\\n\\n    return {\\n        \\\"order_id\\\": order_id,\\n        \\\"status\\\": row[0],\\n        \\\"total\\\": row[1],\\n        \\\"currency\\\": row[2],\\n    }\\n\\nprint(get_order_status(4711))\"},\"type\":\"code\"},{\"data\":{\"text\":\"If the application already knows that the user is asking about order 4711, embedding the entire orders table and asking semantic search to rediscover that row usually adds complexity without benefit. A strong design rule is: \u003Cb>retrieve structured facts with structured queries; retrieve unstructured knowledge with search.\u003C\u002Fb>\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"The returned database row can still be placed into the model context so the LLM can explain it in natural language. But direct state or record access is conceptually different from searching a knowledge corpus.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Real Example 3: Full-Text Search Before Embeddings\",\"level\":2},\"type\":\"header\"},{\"data\":{\"text\":\"Between a naive Python loop and vector search lies a mature class of lexical retrieval systems. SQLite includes FTS5 for full-text search, including BM25 ranking.\"},\"type\":\"paragraph\"},{\"data\":{\"code\":\"import sqlite3\\n\\nconnection = sqlite3.connect(\\\"knowledge.db\\\")\\ncursor = connection.cursor()\\n\\ncursor.execute(\\n    \\\"CREATE VIRTUAL TABLE IF NOT EXISTS docs USING fts5(title, body)\\\"\\n)\\n\\ncursor.execute(\\n    \\\"INSERT INTO docs(title, body) VALUES (?, ?)\\\",\\n    (\\\"AKM\\\", \\\"The AKM uses 7.62 mm ammunition.\\\")\\n)\\n\\nconnection.commit()\\n\\nquery = \\\"AKM ammunition\\\"\\n\\nrows = cursor.execute(\\n    \\\"SELECT title, body, bm25(docs) AS score \\\"\\n    \\\"FROM docs WHERE docs MATCH ? \\\"\\n    \\\"ORDER BY score LIMIT 5\\\",\\n    (query,)\\n).fetchall()\\n\\nfor row in rows:\\n    print(row)\\n\\nconnection.close()\"},\"type\":\"code\"},{\"data\":{\"text\":\"Lexical search is especially useful when exact terminology, product codes, names, identifiers or domain-specific words matter. Semantic search is not automatically better. Production systems often combine both signals.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Real Example 4: Semantic Retrieval With Embeddings\",\"level\":2},\"type\":\"header\"},{\"data\":{\"text\":\"Embeddings turn text into numerical vectors so semantically related passages can be compared even when they do not use identical wording. Sentence Transformers provides a straightforward local implementation.\"},\"type\":\"paragraph\"},{\"data\":{\"code\":\"# pip install sentence-transformers\\n\\nfrom sentence_transformers import SentenceTransformer, util\\n\\ndocuments = [\\n    \\\"The AKM uses 7.62 mm ammunition.\\\",\\n    \\\"A Med Kit restores health.\\\",\\n    \\\"Vehicle maintenance includes checking oil, brakes and tires.\\\",\\n    \\\"Account recovery requires access to the registered email address.\\\"\\n]\\n\\nmodel = SentenceTransformer(\\n    \\\"sentence-transformers\u002Fmulti-qa-mpnet-base-cos-v1\\\"\\n)\\n\\ndocument_embeddings = model.encode_document(\\n    documents,\\n    convert_to_tensor=True\\n)\\n\\nquestion = \\\"How do I repair my car?\\\"\\n\\nquery_embedding = model.encode_query(\\n    question,\\n    convert_to_tensor=True\\n)\\n\\nhits = util.semantic_search(\\n    query_embedding,\\n    document_embeddings,\\n    top_k=2\\n)[0]\\n\\nfor hit in hits:\\n    print(round(float(hit[\\\"score\\\"]), 3), documents[hit[\\\"corpus_id\\\"]])\"},\"type\":\"code\"},{\"data\":{\"text\":\"The query does not contain the phrase “vehicle maintenance,” but a semantic model can still rank that passage highly because the concepts are related. This is the practical reason embeddings are common in RAG systems.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"For small collections, embeddings can stay in memory. Larger systems usually persist them in a vector-capable index or database and perform nearest-neighbor search there. The storage changes, but the logic remains: encode the question, find relevant document representations, return the best evidence.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Real Example 5: Build the Context for the LLM\",\"level\":2},\"type\":\"header\"},{\"data\":{\"text\":\"A retriever should return evidence. The LLM should then receive the question plus that evidence. Keeping retrieval and generation separate makes both easier to inspect and test.\"},\"type\":\"paragraph\"},{\"data\":{\"code\":\"def build_prompt(question, retrieved_documents):\\n    context = \\\"\\\\n\\\\n\\\".join(\\n        f'[{doc[\\\"id\\\"]}] {doc[\\\"text\\\"]}'\\n        for doc in retrieved_documents\\n    )\\n\\n    return f\\\"\\\"\\\"\\nAnswer the question using the supplied context.\\n\\nRules:\\n- Do not invent facts that are not supported by the context.\\n- If the context is insufficient, say so.\\n- Cite the source IDs you used.\\n\\nQuestion:\\n{question}\\n\\nContext:\\n{context}\\n\\\"\\\"\\\".strip()\"},\"type\":\"code\"},{\"data\":{\"text\":\"The instruction does not make the model infallible. It simply creates an explicit evidence boundary. The model can still misunderstand good evidence, ignore a condition or overgeneralize. That is why retrieval quality and generation quality must be evaluated separately.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Real Example 6: A Complete Minimal Pipeline\",\"level\":2},\"type\":\"header\"},{\"data\":{\"code\":\"def answer_question(question, all_documents, call_llm):\\n    # 1. Retrieve evidence\\n    retrieved = retrieve(question, all_documents, top_k=3)\\n\\n    # 2. Build model context\\n    prompt = build_prompt(question, retrieved)\\n\\n    # 3. Generate the answer\\n    answer = call_llm(prompt)\\n\\n    return {\\n        \\\"answer\\\": answer,\\n        \\\"sources\\\": [doc[\\\"id\\\"] for doc in retrieved]\\n    }\"},\"type\":\"code\"},{\"data\":{\"text\":\"The function receives \u003Ccode>call_llm\u003C\u002Fcode> as a dependency on purpose. Retrieval should not care whether generation is performed by a cloud model, a local model or another provider. The data path belongs to the application.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Optional Generator: OpenAI Responses API\",\"level\":3},\"type\":\"header\"},{\"data\":{\"text\":\"One possible generator is the OpenAI Responses API. Keeping the model name in an environment variable avoids hard-coding a particular model into the RAG architecture.\"},\"type\":\"paragraph\"},{\"data\":{\"code\":\"# pip install openai\\n\\nimport os\\nfrom openai import OpenAI\\n\\nclient = OpenAI()\\n\\ndef call_llm(prompt):\\n    response = client.responses.create(\\n        model=os.environ[\\\"OPENAI_MODEL\\\"],\\n        input=prompt,\\n    )\\n    return response.output_text\"},\"type\":\"code\"},{\"data\":{\"text\":\"The same retrieval pipeline can be connected to a local inference server. This is an important architectural point: \u003Cb>RAG is not owned by the LLM provider.\u003C\u002Fb> The application owns the source, retrieval and context assembly.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"The Whole Architecture in One View\",\"level\":3},\"type\":\"header\"},{\"data\":{\"code\":\"USER QUESTION\\n     |\\n     v\\n+-------------+\\n|  Retriever  |\\n+-------------+\\n   |       |\\n   |       +----> SQL \u002F API \u002F state query\\n   |\\n   +------------> keyword \u002F full-text search\\n   |\\n   +------------> embedding \u002F vector search\\n                     |\\n                     v\\n              relevant evidence\\n                     |\\n                     v\\n+-----------------------------------+\\n| question + evidence + instructions |\\n+-----------------------------------+\\n                     |\\n                     v\\n                   LLM\\n                     |\\n                     v\\n                  answer\"},\"type\":\"code\"},{\"data\":{\"text\":\"This data-flow model is more durable than memorizing one framework. Libraries, databases and model vendors will change; the responsibility boundaries remain.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Common Misconceptions and Failure Modes\",\"level\":2},\"type\":\"header\"},{\"data\":{\"text\":\"“RAG means vector database.”\",\"level\":3},\"type\":\"header\"},{\"data\":{\"text\":\"No. Vector search is one retrieval method. RAG can use full-text search, SQL, APIs, knowledge graphs, vector search or combinations of them. The defining pattern is retrieval of external information for generation.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"“If the data is in PostgreSQL, I must embed the whole database.”\",\"level\":3},\"type\":\"header\"},{\"data\":{\"text\":\"No. Structured records should usually remain queryable as structured records. Embeddings are useful for semantic relevance, not as a replacement for deterministic queries.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"“More chunks means a better answer.”\",\"level\":3},\"type\":\"header\"},{\"data\":{\"text\":\"Not necessarily. Extra context can introduce noise, conflicting versions and irrelevant material. Retrieval should optimize for useful evidence, not maximum volume.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"“A high similarity score proves the answer.”\",\"level\":3},\"type\":\"header\"},{\"data\":{\"text\":\"No. Similarity measures relevance, not truth or applicability. A highly similar passage can be outdated, from the wrong product version or valid only under conditions that do not match the question.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"“Once the correct chunk is retrieved, hallucination is solved.”\",\"level\":3},\"type\":\"header\"},{\"data\":{\"text\":\"No. Retrieval improves grounding but does not guarantee faithful reasoning. Generation still needs evaluation, and high-risk workflows may require deterministic validation or human review.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"“The model failed, so change the model.”\",\"level\":3},\"type\":\"header\"},{\"data\":{\"text\":\"Not necessarily. The correct source may have been missing, parsed incorrectly, split badly, filtered out, ranked too low or omitted from the assembled context. Model replacement should not be the first diagnostic step.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Edge Cases\",\"level\":2},\"type\":\"header\"},{\"data\":{\"items\":[\"\u003Cb>Conflicting documents:\u003C\u002Fb> two sources may disagree because versions, jurisdictions or products differ.\",\"\u003Cb>Time-sensitive facts:\u003C\u002Fb> a semantically relevant source may already be stale.\",\"\u003Cb>Permissions:\u003C\u002Fb> a retriever must not return documents the current user is not authorized to access.\",\"\u003Cb>Multi-language collections:\u003C\u002Fb> the embedding model and retrieval strategy must support the languages actually used.\",\"\u003Cb>Tables and source code:\u003C\u002Fb> plain paragraph chunking can destroy structure that is essential to the answer.\",\"\u003Cb>Very short identifiers:\u003C\u002Fb> semantic retrieval can be weaker than exact matching for SKUs, IDs, error codes or acronyms.\",\"\u003Cb>Long questions requiring several facts:\u003C\u002Fb> retrieval may need decomposition, several searches or reranking rather than one top-k query.\",\"\u003Cb>Source hierarchy:\u003C\u002Fb> an official current policy may need to outrank an older but semantically closer discussion document.\"],\"style\":\"unordered\"},\"type\":\"list\"},{\"data\":{\"text\":\"Limitations\",\"level\":2},\"type\":\"header\"},{\"data\":{\"text\":\"The Python examples intentionally optimize for transparency, not scale. The keyword retriever is naive, the chunker uses character length, the SQLite examples do not include production connection management, and the semantic example keeps all embeddings in memory.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"A production system may require vector indexes, rerankers, hybrid retrieval, document parsers, caching, incremental indexing, source versioning, access-control filters, observability, evaluation datasets and failure handling. None of those additions change the core architecture; they make each boundary more reliable.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"RAG also cannot create evidence that is absent from the source set. If the source is wrong, incomplete or stale, a better embedding model cannot turn it into authoritative knowledge.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"What Would Change This Answer?\",\"level\":2},\"type\":\"header\"},{\"data\":{\"text\":\"The architecture changes when the task requires more than knowledge lookup. A live order status needs current state. A financial calculation may need deterministic code. A web-research task may need active search. A workflow may need tools that can write data back to another system. An autonomous agent may need planning, permissions and execution control in addition to retrieval.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"RAG is therefore best understood as \u003Cb>one evidence-acquisition layer inside a larger AI system\u003C\u002Fb>. It is powerful precisely because it has a narrow job: find useful external information and place it in the model’s working context.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Conclusion\",\"level\":2},\"type\":\"header\"},{\"data\":{\"text\":\"RAG becomes much easier to understand when the technology names are removed. A file is a source. A database is a source. An API is a source. A search function retrieves evidence. A prompt carries that evidence to the model. The LLM then interprets it and produces language.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"The hard part of production RAG is not calling an embedding model. It is building a trustworthy evidence path from the original source to the final claim: preserving provenance, selecting the right retrieval method, keeping information current, controlling access, evaluating retrieval separately from generation, and knowing when a direct database or tool call is better than semantic search.\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"That is the practical continuation of the basic RAG model: \u003Cb>first understand the roles, then make the data path explicit.\u003C\u002Fb>\"},\"type\":\"paragraph\"},{\"data\":{\"text\":\"Primary Sources\",\"level\":2},\"type\":\"header\"},{\"data\":{\"items\":[\"\u003Ca href=\\\"https:\u002F\u002Farxiv.org\u002Fabs\u002F2005.11401\\\">Lewis et al. — Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks\u003C\u002Fa> — the 2020 paper introducing the RAG formulation that combines generation with retrieved non-parametric memory.\",\"\u003Ca href=\\\"https:\u002F\u002Fwww.sbert.net\u002Fexamples\u002Fsentence_transformer\u002Fapplications\u002Fsemantic-search\u002FREADME.html\\\">Sentence Transformers — Semantic Search\u003C\u002Fa> — official documentation for semantic retrieval, query embeddings and document embeddings.\",\"\u003Ca href=\\\"https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Fguides\u002Fembeddings\\\">OpenAI — Vector Embeddings\u003C\u002Fa> — official documentation describing embeddings as numerical representations used for relatedness and search.\",\"\u003Ca href=\\\"https:\u002F\u002Fwww.sqlite.org\u002Ffts5.html\\\">SQLite — FTS5 Extension\u003C\u002Fa> — official documentation for full-text search and BM25 ranking in SQLite.\",\"\u003Ca href=\\\"https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Flibraries\\\">OpenAI — SDKs and CLI\u003C\u002Fa> — official Python SDK example for the Responses API used in the optional generator example.\",\"\u003Ca href=\\\"https:\u002F\u002Fstajic.de\u002Fblog\u002Fwhat-is-rag-the-simplest-explanation-of-how-it-works\\\">What Is RAG? The Simplest Explanation of How It Works\u003C\u002Fa> — the conceptual first part of this series.\"],\"style\":\"unordered\"},\"type\":\"list\"}],\"version\":\"2.31.0\"}",{"time":705,"blocks":706,"version":1143},1790516400000,[707,710,713,717,720,723,726,729,732,735,738,740,743,746,748,751,754,757,760,763,766,769,772,775,778,781,784,787,820,823,826,829,839,842,844,873,876,879,905,908,911,923,926,929,932,935,938,941,944,947,949,952,955,957,960,963,965,968,971,974,976,979,982,985,988,990,993,996,999,1001,1004,1007,1010,1013,1015,1018,1021,1023,1026,1029,1032,1034,1037,1040,1042,1045,1048,1051,1054,1057,1060,1063,1066,1069,1072,1075,1078,1081,1084,1087,1098,1101,1104,1107,1110,1113,1116,1119,1122,1125,1128,1131,1134],{"data":708,"type":217},{"text":709},"The previous article, \u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fblog\u002Fwhat-is-rag-the-simplest-explanation-of-how-it-works\">What Is RAG? The Simplest Explanation of How It Works\u003C\u002Fa>, established the mental model: the LLM writes, RAG retrieves useful knowledge, the application owns current state, and tools perform actions. This article takes the next step: \u003Cb>where does the data actually come from, and what does retrieval look like in Python?\u003C\u002Fb>",{"data":711,"type":217},{"text":712},"The important surprise is that an “LLM data source” is usually nothing exotic. It can be a text file, a folder of Markdown documents, a SQL database, an API response, a product catalog, a support system, or a vector index derived from those sources. The AI does not magically know these systems. Your application has to load, query, search, or retrieve the relevant data and place the result into the model’s context.",{"data":714,"type":226},{"text":715,"caption":716,"alignment":225},"Data source = where information lives. Retrieval = how the application finds useful information. Context = the selected information given to the model. LLM = the component that interprets that context and generates an answer.","The four-part model used throughout this article",{"data":718,"type":42},{"text":719,"level":230},"Question",{"data":721,"type":217},{"text":722},"How does an LLM use external data such as files, databases or APIs, and how can a small Python program implement the essential RAG steps without hiding them behind a framework?",{"data":724,"type":42},{"text":725,"level":230},"What This Really Means",{"data":727,"type":217},{"text":728},"When developers say that an LLM is “connected to company data,” several different operations may be hidden behind that sentence. One application may execute SQL. Another may call an API. Another may run full-text search. Another may calculate embedding similarity over document chunks. All of them can provide external information to an LLM, but they are not the same retrieval method and they should not be treated as interchangeable.",{"data":730,"type":217},{"text":731},"This distinction matters because the best retrieval method depends on the shape of the question. “What is our refund policy?” is a document-retrieval problem. “What is order 4711’s current status?” is usually a structured database lookup. “Which paragraph discusses account recovery?” can be keyword or semantic search. RAG is most useful when the system must \u003Cb>discover relevant knowledge before generation\u003C\u002Fb>.",{"data":733,"type":42},{"text":734,"level":230},"Simplest Example",{"data":736,"type":217},{"text":737},"Start with three strings in ordinary Python. There is no vector database, no framework, and no LLM yet. We only want to make the retrieval step visible.",{"data":739,"type":252},{"code":251},{"data":741,"type":217},{"text":742},"The program prints the first sentence because it contains the term we searched for. This is primitive retrieval, but the architecture is already visible: \u003Cb>question → search → relevant text\u003C\u002Fb>. RAG adds one more major step: pass the retrieved text to a language model together with the question.",{"data":744,"type":217},{"text":745},"A slightly more general version ranks documents by overlapping query terms:",{"data":747,"type":252},{"code":261},{"data":749,"type":217},{"text":750},"This is not a production search engine. It ignores morphology, synonyms, spelling variants, document length and many ranking signals. Its value is educational: \u003Cb>RAG does not begin with a vector database. It begins with retrieval.\u003C\u002Fb>",{"data":752,"type":42},{"text":753,"level":230},"Where the Example Stops Working",{"data":755,"type":217},{"text":756},"Exact or lexical matching becomes weak when the question and the source use different words. A document may say “vehicle maintenance,” while the user asks “how do I repair my car?” A lexical retriever can miss the relationship even though a human sees it immediately. Semantic retrieval addresses this by representing text as vectors and comparing meaning rather than only exact tokens.",{"data":758,"type":217},{"text":759},"Long files create another problem. Searching an entire 80-page manual as one unit is too coarse, but splitting every sentence can destroy useful context. Real RAG systems therefore need decisions about parsing, chunking, metadata, ranking, freshness, permissions and provenance.",{"data":761,"type":217},{"text":762},"The example also says nothing about structured live facts. If the user asks for the current status of order 4711 and the application already has a database key, semantic search is usually the wrong first tool. A deterministic database query is better.",{"data":764,"type":42},{"text":765,"level":230},"Direct Answer",{"data":767,"type":217},{"text":768},"An LLM data source is any external system from which an application can obtain information for the model: files, databases, APIs, search indexes, vector stores or live application state. RAG is the pattern of \u003Cb>retrieving relevant knowledge from such sources before generation\u003C\u002Fb>.",{"data":770,"type":217},{"text":771},"In Python, the essential pipeline can be very small: \u003Cb>load data → create retrievable units → find relevant evidence → assemble context → call the LLM\u003C\u002Fb>. The retrieval method should match the source and the question. Use SQL for exact structured facts, full-text search for lexical matching, embeddings for semantic similarity, and hybrid retrieval when several signals are valuable.",{"data":773,"type":42},{"text":774,"level":230},"Why This Is So",{"data":776,"type":217},{"text":777},"A language model does not automatically receive the contents of your filesystem, PostgreSQL database, CRM, private API or newly edited document. The application decides what external information is accessible and what is placed into the model’s current context.",{"data":779,"type":217},{"text":780},"The original Retrieval-Augmented Generation work by Lewis et al. combined a generative model with external non-parametric memory retrieved from a dense vector index. The broader architectural idea survives beyond that specific implementation: external evidence can be retrieved at inference time instead of expecting all useful knowledge to be encoded in model parameters.",{"data":782,"type":217},{"text":783},"This creates a useful separation of responsibilities: the source stores information, the retriever selects evidence, the context carries that evidence into the request, and the model interprets it. Keeping those boundaries visible makes failures much easier to diagnose.",{"data":785,"type":42},{"text":786,"level":230},"Context: The Main Types of Data Sources",{"data":788,"type":336},{"content":789,"withHeadings":14},[790,794,797,800,804,808,812,816],[791,792,793],"Source","Typical retrieval method","Good for",[309,795,796],"Parsing + lexical or semantic search","Documentation, manuals, articles, notes",[313,798,799],"Structure-aware extraction + search","Policies, reports, contracts, manuals",[801,802,803],"SQL database","SQL query or filtered retrieval","Orders, users, products, structured records",[805,806,807],"REST \u002F GraphQL API","HTTP request with parameters","Remote systems and live service data",[809,810,811],"Search index","BM25 \u002F full-text \u002F hybrid search","Large text collections",[813,814,815],"Vector index","Embedding similarity","Semantic document retrieval",[817,818,819],"Application state","Direct state read or tool call","What is true right now",{"data":821,"type":217},{"text":822},"A vector index deserves special attention. In many architectures it is \u003Cb>not the canonical source of truth\u003C\u002Fb>. It is a retrieval index derived from documents or records. The authoritative document may live in object storage, a CMS, Git, PostgreSQL or another system, while embeddings and metadata are stored separately for fast semantic lookup. Some systems do use a vector store as primary storage, but that is an architectural choice rather than a requirement of RAG.",{"data":824,"type":217},{"text":825},"If the boundary between retrieval, persistent memory, current state and model context is still unclear, see \u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fblog\u002Fai-agent-memory-is-not-rag-how-to-separate-memory-retrieval-state-and-context\">AI Agent Memory Is Not RAG\u003C\u002Fa>. Those layers can use some of the same storage technologies while still having different correctness rules.",{"data":827,"type":42},{"text":828,"level":230},"Assumptions",{"data":830,"type":357},{"items":831,"style":356},[832,833,834,835,836,837,838],"The application is allowed to access the external source.","The relevant source contains enough information to answer the question.","The data can be parsed or queried in a form the retrieval layer can use.","The retrieved information is fresh enough for the requested decision.","The model receives the selected evidence in its context.","Authorization is enforced before protected evidence reaches the model.","The generation model can still be wrong even when retrieval is correct.",{"data":840,"type":217},{"text":841},"These assumptions matter because retrieval cannot compensate for missing evidence, stale source versions, broken parsers or unauthorized access. A RAG pipeline can only be as trustworthy as the evidence path that feeds it.",{"data":843,"type":42},{"text":363,"level":230},{"data":845,"type":336},{"content":846,"withHeadings":14},[847,849,852,855,858,861,864,867,870],[368,848],"Why it changes the design",[850,851],"Source structure","A SQL table, legal PDF and source-code repository need different retrieval strategies",[853,854],"Question type","Exact lookup, conceptual search and multi-hop research are different tasks",[856,857],"Freshness requirement","Live state may need direct queries instead of periodically rebuilt indexes",[859,860],"Corpus size","In-memory search may work for hundreds of chunks but not for very large collections",[862,863],"Language","Multilingual retrieval requires models and tokenization suitable for the actual languages",[865,866],"Permissions","Retrieval must filter by the current user’s access rights",[868,869],"Latency and cost","More retrieval stages can improve quality but add runtime and infrastructure cost",[871,872],"Need for provenance","High-trust systems need source IDs, versions and traceable evidence",{"data":874,"type":42},{"text":875,"level":230},"Diagnostic \u002F Decision Method",{"data":877,"type":217},{"text":878},"The first decision is not “Which vector database should I install?” It is: \u003Cb>What kind of fact am I trying to retrieve?\u003C\u002Fb>",{"data":880,"type":336},{"content":881,"withHeadings":14},[882,885,889,893,897,901],[853,883,884],"Preferred first approach","Reason",[886,887,888],"Exact ID or current record","SQL \u002F key lookup \u002F API","Deterministic structured access",[890,891,892],"Exact wording, codes, names","Full-text or keyword search","Lexical precision",[894,895,896],"Conceptual question over documents","Semantic vector search","Meaning can differ from wording",[898,899,900],"Mixed enterprise knowledge","Hybrid retrieval + metadata filters","Combines lexical and semantic signals",[902,903,904],"Current application state","Direct state\u002Ftool access","Freshness matters more than document similarity",{"data":906,"type":217},{"text":907},"A useful test is: \u003Cb>Do I already know which record I need, or must the system discover which passage is relevant?\u003C\u002Fb> If the record is known, query it directly. If relevance must be discovered, search becomes more important.",{"data":909,"type":217},{"text":910},"When an answer is wrong, diagnose the pipeline in order instead of immediately changing the LLM:",{"data":912,"type":357},{"items":913,"style":444},[914,915,916,917,918,919,920,921,922],"\u003Cb>1. Source coverage:\u003C\u002Fb> Does the correct information exist in the accessible source set?","\u003Cb>2. Freshness:\u003C\u002Fb> Is that version current enough for the question?","\u003Cb>3. Parsing:\u003C\u002Fb> Was the relevant content extracted correctly?","\u003Cb>4. Chunking:\u003C\u002Fb> Did the evidence stay together with the conditions that give it meaning?","\u003Cb>5. Retrieval:\u003C\u002Fb> Does the correct chunk appear among the candidates?","\u003Cb>6. Ranking:\u003C\u002Fb> Are stronger sources ranked above weaker or conflicting ones?","\u003Cb>7. Context assembly:\u003C\u002Fb> Did the application actually send the selected evidence to the model?","\u003Cb>8. Generation:\u003C\u002Fb> Did the LLM faithfully use the supplied evidence?","\u003Cb>9. Attribution:\u003C\u002Fb> Can each important claim be traced to a source?",{"data":924,"type":217},{"text":925},"For a deeper production-debugging method, see \u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fblog\u002Frag-failed-but-which-layer-actually-failed-a-diagnostic-method\">RAG Failed — But Which Layer Actually Failed? A Diagnostic Method\u003C\u002Fa>, which expands this chain into independently testable failure layers.",{"data":927,"type":42},{"text":928,"level":230},"Evidence",{"data":930,"type":217},{"text":931},"The RAG paper by Lewis et al. formalized generation that conditions on retrieved external memory rather than relying only on model parameters. That provides the conceptual foundation for separating the generator from a retrievable knowledge source.",{"data":933,"type":217},{"text":934},"Sentence Transformers documents semantic search as embedding the corpus and the query into a vector space and retrieving items with high semantic similarity. Its current API also distinguishes query encoding from document encoding for retrieval tasks.",{"data":936,"type":217},{"text":937},"SQLite FTS5 demonstrates the other side of the spectrum: mature full-text retrieval can rank documents without embeddings. This matters because lexical search remains valuable for identifiers, exact terminology and many hybrid retrieval designs.",{"data":939,"type":217},{"text":940},"OpenAI’s embeddings documentation describes embeddings as numerical vector representations used for relatedness and search. This is one implementation path for semantic retrieval, not the definition of RAG itself.",{"data":942,"type":42},{"text":943,"level":230},"Real Example 1: A Folder of Text Files",{"data":945,"type":217},{"text":946},"Suppose a directory named \u003Ccode>knowledge\u002F\u003C\u002Fcode> contains ordinary text files. Python can load them with no AI library at all.",{"data":948,"type":252},{"code":471},{"data":950,"type":217},{"text":951},"The filesystem is the data source. The next question is how much text should become one retrievable unit. For long documents, searching one complete file is often too coarse. This is why RAG pipelines commonly create chunks.",{"data":953,"type":42},{"text":954,"level":478},"A Very Simple Chunker",{"data":956,"type":252},{"code":481},{"data":958,"type":217},{"text":959},"This example groups paragraphs until a rough character limit is reached. It is intentionally understandable rather than optimal. Production systems often chunk by tokens, headings, sections, sentence boundaries or document structure. Tables, source code, contracts and API documentation may need different strategies.",{"data":961,"type":42},{"text":962,"level":478},"Preserve Provenance While Chunking",{"data":964,"type":252},{"code":490},{"data":966,"type":217},{"text":967},"A useful chunk carries more than text. Source name, document ID, URL, timestamp, version or section can later support citation, debugging and freshness checks. If provenance is lost during ingestion, it becomes much harder to explain why a particular answer was produced.",{"data":969,"type":42},{"text":970,"level":230},"Real Example 2: Structured Data — Use SQL When SQL Is the Right Tool",{"data":972,"type":217},{"text":973},"Not every external fact should go through semantic search. If the question asks for an exact current record, a direct database query is usually clearer and more deterministic.",{"data":975,"type":252},{"code":502},{"data":977,"type":217},{"text":978},"If the application already knows that the user is asking about order 4711, embedding the entire orders table and asking semantic search to rediscover that row usually adds complexity without benefit. A strong design rule is: \u003Cb>retrieve structured facts with structured queries; retrieve unstructured knowledge with search.\u003C\u002Fb>",{"data":980,"type":217},{"text":981},"The returned database row can still be placed into the model context so the LLM can explain it in natural language. But direct state or record access is conceptually different from searching a knowledge corpus.",{"data":983,"type":42},{"text":984,"level":230},"Real Example 3: Full-Text Search Before Embeddings",{"data":986,"type":217},{"text":987},"Between a naive Python loop and vector search lies a mature class of lexical retrieval systems. SQLite includes FTS5 for full-text search, including BM25 ranking.",{"data":989,"type":252},{"code":517},{"data":991,"type":217},{"text":992},"Lexical search is especially useful when exact terminology, product codes, names, identifiers or domain-specific words matter. Semantic search is not automatically better. Production systems often combine both signals.",{"data":994,"type":42},{"text":995,"level":230},"Real Example 4: Semantic Retrieval With Embeddings",{"data":997,"type":217},{"text":998},"Embeddings turn text into numerical vectors so semantically related passages can be compared even when they do not use identical wording. Sentence Transformers provides a straightforward local implementation.",{"data":1000,"type":252},{"code":529},{"data":1002,"type":217},{"text":1003},"The query does not contain the phrase “vehicle maintenance,” but a semantic model can still rank that passage highly because the concepts are related. This is the practical reason embeddings are common in RAG systems.",{"data":1005,"type":217},{"text":1006},"For small collections, embeddings can stay in memory. Larger systems usually persist them in a vector-capable index or database and perform nearest-neighbor search there. The storage changes, but the logic remains: encode the question, find relevant document representations, return the best evidence.",{"data":1008,"type":42},{"text":1009,"level":230},"Real Example 5: Build the Context for the LLM",{"data":1011,"type":217},{"text":1012},"A retriever should return evidence. The LLM should then receive the question plus that evidence. Keeping retrieval and generation separate makes both easier to inspect and test.",{"data":1014,"type":252},{"code":544},{"data":1016,"type":217},{"text":1017},"The instruction does not make the model infallible. It simply creates an explicit evidence boundary. The model can still misunderstand good evidence, ignore a condition or overgeneralize. That is why retrieval quality and generation quality must be evaluated separately.",{"data":1019,"type":42},{"text":1020,"level":230},"Real Example 6: A Complete Minimal Pipeline",{"data":1022,"type":252},{"code":553},{"data":1024,"type":217},{"text":1025},"The function receives \u003Ccode>call_llm\u003C\u002Fcode> as a dependency on purpose. Retrieval should not care whether generation is performed by a cloud model, a local model or another provider. The data path belongs to the application.",{"data":1027,"type":42},{"text":1028,"level":478},"Optional Generator: OpenAI Responses API",{"data":1030,"type":217},{"text":1031},"One possible generator is the OpenAI Responses API. Keeping the model name in an environment variable avoids hard-coding a particular model into the RAG architecture.",{"data":1033,"type":252},{"code":565},{"data":1035,"type":217},{"text":1036},"The same retrieval pipeline can be connected to a local inference server. This is an important architectural point: \u003Cb>RAG is not owned by the LLM provider.\u003C\u002Fb> The application owns the source, retrieval and context assembly.",{"data":1038,"type":42},{"text":1039,"level":478},"The Whole Architecture in One View",{"data":1041,"type":252},{"code":574},{"data":1043,"type":217},{"text":1044},"This data-flow model is more durable than memorizing one framework. Libraries, databases and model vendors will change; the responsibility boundaries remain.",{"data":1046,"type":42},{"text":1047,"level":230},"Common Misconceptions and Failure Modes",{"data":1049,"type":42},{"text":1050,"level":478},"“RAG means vector database.”",{"data":1052,"type":217},{"text":1053},"No. Vector search is one retrieval method. RAG can use full-text search, SQL, APIs, knowledge graphs, vector search or combinations of them. The defining pattern is retrieval of external information for generation.",{"data":1055,"type":42},{"text":1056,"level":478},"“If the data is in PostgreSQL, I must embed the whole database.”",{"data":1058,"type":217},{"text":1059},"No. Structured records should usually remain queryable as structured records. Embeddings are useful for semantic relevance, not as a replacement for deterministic queries.",{"data":1061,"type":42},{"text":1062,"level":478},"“More chunks means a better answer.”",{"data":1064,"type":217},{"text":1065},"Not necessarily. Extra context can introduce noise, conflicting versions and irrelevant material. Retrieval should optimize for useful evidence, not maximum volume.",{"data":1067,"type":42},{"text":1068,"level":478},"“A high similarity score proves the answer.”",{"data":1070,"type":217},{"text":1071},"No. Similarity measures relevance, not truth or applicability. A highly similar passage can be outdated, from the wrong product version or valid only under conditions that do not match the question.",{"data":1073,"type":42},{"text":1074,"level":478},"“Once the correct chunk is retrieved, hallucination is solved.”",{"data":1076,"type":217},{"text":1077},"No. Retrieval improves grounding but does not guarantee faithful reasoning. Generation still needs evaluation, and high-risk workflows may require deterministic validation or human review.",{"data":1079,"type":42},{"text":1080,"level":478},"“The model failed, so change the model.”",{"data":1082,"type":217},{"text":1083},"Not necessarily. The correct source may have been missing, parsed incorrectly, split badly, filtered out, ranked too low or omitted from the assembled context. Model replacement should not be the first diagnostic step.",{"data":1085,"type":42},{"text":1086,"level":230},"Edge Cases",{"data":1088,"type":357},{"items":1089,"style":356},[1090,1091,1092,1093,1094,1095,1096,1097],"\u003Cb>Conflicting documents:\u003C\u002Fb> two sources may disagree because versions, jurisdictions or products differ.","\u003Cb>Time-sensitive facts:\u003C\u002Fb> a semantically relevant source may already be stale.","\u003Cb>Permissions:\u003C\u002Fb> a retriever must not return documents the current user is not authorized to access.","\u003Cb>Multi-language collections:\u003C\u002Fb> the embedding model and retrieval strategy must support the languages actually used.","\u003Cb>Tables and source code:\u003C\u002Fb> plain paragraph chunking can destroy structure that is essential to the answer.","\u003Cb>Very short identifiers:\u003C\u002Fb> semantic retrieval can be weaker than exact matching for SKUs, IDs, error codes or acronyms.","\u003Cb>Long questions requiring several facts:\u003C\u002Fb> retrieval may need decomposition, several searches or reranking rather than one top-k query.","\u003Cb>Source hierarchy:\u003C\u002Fb> an official current policy may need to outrank an older but semantically closer discussion document.",{"data":1099,"type":42},{"text":1100,"level":230},"Limitations",{"data":1102,"type":217},{"text":1103},"The Python examples intentionally optimize for transparency, not scale. The keyword retriever is naive, the chunker uses character length, the SQLite examples do not include production connection management, and the semantic example keeps all embeddings in memory.",{"data":1105,"type":217},{"text":1106},"A production system may require vector indexes, rerankers, hybrid retrieval, document parsers, caching, incremental indexing, source versioning, access-control filters, observability, evaluation datasets and failure handling. None of those additions change the core architecture; they make each boundary more reliable.",{"data":1108,"type":217},{"text":1109},"RAG also cannot create evidence that is absent from the source set. If the source is wrong, incomplete or stale, a better embedding model cannot turn it into authoritative knowledge.",{"data":1111,"type":42},{"text":1112,"level":230},"What Would Change This Answer?",{"data":1114,"type":217},{"text":1115},"The architecture changes when the task requires more than knowledge lookup. A live order status needs current state. A financial calculation may need deterministic code. A web-research task may need active search. A workflow may need tools that can write data back to another system. An autonomous agent may need planning, permissions and execution control in addition to retrieval.",{"data":1117,"type":217},{"text":1118},"RAG is therefore best understood as \u003Cb>one evidence-acquisition layer inside a larger AI system\u003C\u002Fb>. It is powerful precisely because it has a narrow job: find useful external information and place it in the model’s working context.",{"data":1120,"type":42},{"text":1121,"level":230},"Conclusion",{"data":1123,"type":217},{"text":1124},"RAG becomes much easier to understand when the technology names are removed. A file is a source. A database is a source. An API is a source. A search function retrieves evidence. A prompt carries that evidence to the model. The LLM then interprets it and produces language.",{"data":1126,"type":217},{"text":1127},"The hard part of production RAG is not calling an embedding model. It is building a trustworthy evidence path from the original source to the final claim: preserving provenance, selecting the right retrieval method, keeping information current, controlling access, evaluating retrieval separately from generation, and knowing when a direct database or tool call is better than semantic search.",{"data":1129,"type":217},{"text":1130},"That is the practical continuation of the basic RAG model: \u003Cb>first understand the roles, then make the data path explicit.\u003C\u002Fb>",{"data":1132,"type":42},{"text":1133,"level":230},"Primary Sources",{"data":1135,"type":357},{"items":1136,"style":356},[1137,1138,1139,1140,1141,1142],"\u003Ca href=\"https:\u002F\u002Farxiv.org\u002Fabs\u002F2005.11401\">Lewis et al. — Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks\u003C\u002Fa> — the 2020 paper introducing the RAG formulation that combines generation with retrieved non-parametric memory.","\u003Ca href=\"https:\u002F\u002Fwww.sbert.net\u002Fexamples\u002Fsentence_transformer\u002Fapplications\u002Fsemantic-search\u002FREADME.html\">Sentence Transformers — Semantic Search\u003C\u002Fa> — official documentation for semantic retrieval, query embeddings and document embeddings.","\u003Ca href=\"https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Fguides\u002Fembeddings\">OpenAI — Vector Embeddings\u003C\u002Fa> — official documentation describing embeddings as numerical representations used for relatedness and search.","\u003Ca href=\"https:\u002F\u002Fwww.sqlite.org\u002Ffts5.html\">SQLite — FTS5 Extension\u003C\u002Fa> — official documentation for full-text search and BM25 ranking in SQLite.","\u003Ca href=\"https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Flibraries\">OpenAI — SDKs and CLI\u003C\u002Fa> — official Python SDK example for the Responses API used in the optional generator example.","\u003Ca href=\"https:\u002F\u002Fstajic.de\u002Fblog\u002Fwhat-is-rag-the-simplest-explanation-of-how-it-works\">What Is RAG? The Simplest Explanation of How It Works\u003C\u002Fa> — the conceptual first part of this series.","2.31.0","An LLM does not magically know your files, databases or APIs. This practical continuation of the RAG series shows, with simple Python, how external data becomes retrievable evidence: from text files and SQL to full-text search, embeddings, context assembly and the final LLM call.",{"lang":7,"title":208,"content":210,"contentJson":1146,"excerpt":677},{"time":212,"blocks":1147,"version":676},[1148,1150,1152,1154,1156,1158,1160,1162,1164,1166,1168,1170,1172,1174,1176,1178,1180,1182,1184,1186,1188,1190,1192,1194,1196,1198,1200,1202,1213,1215,1217,1219,1222,1224,1226,1238,1240,1242,1251,1253,1255,1258,1260,1262,1264,1266,1268,1270,1272,1274,1276,1278,1280,1282,1284,1286,1288,1290,1292,1294,1296,1298,1300,1302,1304,1306,1308,1310,1312,1314,1316,1318,1320,1322,1324,1326,1328,1330,1332,1334,1336,1338,1340,1342,1344,1346,1348,1350,1352,1354,1356,1358,1360,1362,1364,1366,1368,1370,1372,1374,1377,1379,1381,1383,1385,1387,1389,1391,1393,1395,1397,1399,1401],{"data":1149,"type":217},{"text":216},{"data":1151,"type":217},{"text":220},{"data":1153,"type":226},{"text":223,"caption":224,"alignment":225},{"data":1155,"type":42},{"text":229,"level":230},{"data":1157,"type":217},{"text":233},{"data":1159,"type":42},{"text":236,"level":230},{"data":1161,"type":217},{"text":239},{"data":1163,"type":217},{"text":242},{"data":1165,"type":42},{"text":245,"level":230},{"data":1167,"type":217},{"text":248},{"data":1169,"type":252},{"code":251},{"data":1171,"type":217},{"text":255},{"data":1173,"type":217},{"text":258},{"data":1175,"type":252},{"code":261},{"data":1177,"type":217},{"text":264},{"data":1179,"type":42},{"text":267,"level":230},{"data":1181,"type":217},{"text":270},{"data":1183,"type":217},{"text":273},{"data":1185,"type":217},{"text":276},{"data":1187,"type":42},{"text":279,"level":230},{"data":1189,"type":217},{"text":282},{"data":1191,"type":217},{"text":285},{"data":1193,"type":42},{"text":288,"level":230},{"data":1195,"type":217},{"text":291},{"data":1197,"type":217},{"text":294},{"data":1199,"type":217},{"text":297},{"data":1201,"type":42},{"text":300,"level":230},{"data":1203,"type":336},{"content":1204,"withHeadings":14},[1205,1206,1207,1208,1209,1210,1211,1212],[305,306,307],[309,310,311],[313,314,315],[317,318,319],[321,322,323],[325,326,327],[329,330,331],[333,334,335],{"data":1214,"type":217},{"text":339},{"data":1216,"type":217},{"text":342},{"data":1218,"type":42},{"text":345,"level":230},{"data":1220,"type":357},{"items":1221,"style":356},[349,350,351,352,353,354,355],{"data":1223,"type":217},{"text":360},{"data":1225,"type":42},{"text":363,"level":230},{"data":1227,"type":336},{"content":1228,"withHeadings":14},[1229,1230,1231,1232,1233,1234,1235,1236,1237],[368,369],[371,372],[374,375],[377,378],[380,381],[383,384],[386,387],[389,390],[392,393],{"data":1239,"type":42},{"text":396,"level":230},{"data":1241,"type":217},{"text":399},{"data":1243,"type":336},{"content":1244,"withHeadings":14},[1245,1246,1247,1248,1249,1250],[374,404,405],[407,408,409],[411,412,413],[415,416,417],[419,420,421],[423,424,425],{"data":1252,"type":217},{"text":428},{"data":1254,"type":217},{"text":431},{"data":1256,"type":357},{"items":1257,"style":444},[435,436,437,438,439,440,441,442,443],{"data":1259,"type":217},{"text":447},{"data":1261,"type":42},{"text":450,"level":230},{"data":1263,"type":217},{"text":453},{"data":1265,"type":217},{"text":456},{"data":1267,"type":217},{"text":459},{"data":1269,"type":217},{"text":462},{"data":1271,"type":42},{"text":465,"level":230},{"data":1273,"type":217},{"text":468},{"data":1275,"type":252},{"code":471},{"data":1277,"type":217},{"text":474},{"data":1279,"type":42},{"text":477,"level":478},{"data":1281,"type":252},{"code":481},{"data":1283,"type":217},{"text":484},{"data":1285,"type":42},{"text":487,"level":478},{"data":1287,"type":252},{"code":490},{"data":1289,"type":217},{"text":493},{"data":1291,"type":42},{"text":496,"level":230},{"data":1293,"type":217},{"text":499},{"data":1295,"type":252},{"code":502},{"data":1297,"type":217},{"text":505},{"data":1299,"type":217},{"text":508},{"data":1301,"type":42},{"text":511,"level":230},{"data":1303,"type":217},{"text":514},{"data":1305,"type":252},{"code":517},{"data":1307,"type":217},{"text":520},{"data":1309,"type":42},{"text":523,"level":230},{"data":1311,"type":217},{"text":526},{"data":1313,"type":252},{"code":529},{"data":1315,"type":217},{"text":532},{"data":1317,"type":217},{"text":535},{"data":1319,"type":42},{"text":538,"level":230},{"data":1321,"type":217},{"text":541},{"data":1323,"type":252},{"code":544},{"data":1325,"type":217},{"text":547},{"data":1327,"type":42},{"text":550,"level":230},{"data":1329,"type":252},{"code":553},{"data":1331,"type":217},{"text":556},{"data":1333,"type":42},{"text":559,"level":478},{"data":1335,"type":217},{"text":562},{"data":1337,"type":252},{"code":565},{"data":1339,"type":217},{"text":568},{"data":1341,"type":42},{"text":571,"level":478},{"data":1343,"type":252},{"code":574},{"data":1345,"type":217},{"text":577},{"data":1347,"type":42},{"text":580,"level":230},{"data":1349,"type":42},{"text":583,"level":478},{"data":1351,"type":217},{"text":586},{"data":1353,"type":42},{"text":589,"level":478},{"data":1355,"type":217},{"text":592},{"data":1357,"type":42},{"text":595,"level":478},{"data":1359,"type":217},{"text":598},{"data":1361,"type":42},{"text":601,"level":478},{"data":1363,"type":217},{"text":604},{"data":1365,"type":42},{"text":607,"level":478},{"data":1367,"type":217},{"text":610},{"data":1369,"type":42},{"text":613,"level":478},{"data":1371,"type":217},{"text":616},{"data":1373,"type":42},{"text":619,"level":230},{"data":1375,"type":357},{"items":1376,"style":356},[623,624,625,626,627,628,629,630],{"data":1378,"type":42},{"text":633,"level":230},{"data":1380,"type":217},{"text":636},{"data":1382,"type":217},{"text":639},{"data":1384,"type":217},{"text":642},{"data":1386,"type":42},{"text":645,"level":230},{"data":1388,"type":217},{"text":648},{"data":1390,"type":217},{"text":651},{"data":1392,"type":42},{"text":654,"level":230},{"data":1394,"type":217},{"text":657},{"data":1396,"type":217},{"text":660},{"data":1398,"type":217},{"text":663},{"data":1400,"type":42},{"text":666,"level":230},{"data":1402,"type":357},{"items":1403,"style":356},[670,671,672,673,674,675],"Post erfolgreich abgerufen",{"items":1406,"source":1489,"manualIds":1490,"manualMatchedIds":1491},[1407,1414,1421,1428,1435,1442,1449,1454,1461,1468,1475,1482],{"id":1408,"slug":1409,"title":1410,"excerpt":1411,"featuredImage":1412,"publishedAt":1413},"456","zbt-z8102ax-hardware-packaging-review","Reseña de hardware y embalaje del ZBT Z8102AX: Router fuerte, caja débil","El ZBT Z8102AX causa una primera impresión sólida como un delgado router OpenWrt 5G de metal negro con múltiples conectores de antena, ranuras para doble SIM, puertos USB, LAN\u002FWAN y un práctico juego de accesorios. El hardware se siente útil y serio, pero el embalaje es claramente el punto débil.","\u002Fuploads\u002F2026\u002F06\u002Fopenwrt-router-review-dual-sim-02-1781620590938-y33j4b.webp","2026-06-16T04:40:00.000Z",{"id":1415,"slug":1416,"title":1417,"excerpt":1418,"featuredImage":1419,"publishedAt":1420},"435","ultimate-guide-to-acceptance-criteria-for-llm-adoption-in-enterprise-playbooks","Guía Definitiva de Criterios de Aceptación para la Adopción de LLM en Playbooks Empresariales","Domina el arte de definir criterios de aceptación precisos para garantizar una integración exitosa de LLM en tu entorno empresarial. Esta guía integral proporciona marcos accionables, ejemplos y mejores prácticas adaptados para la adopción impulsada por playbooks.","\u002Fuploads\u002F2026\u002F09\u002Fultimate-guide-to-acceptance-criteria-for-llm-adoption-in-enterprise-playbooks-1788540267775-zgr6mm.webp","2026-09-06T11:50:00.000Z",{"id":1422,"slug":1423,"title":1424,"excerpt":1425,"featuredImage":1426,"publishedAt":1427},"3","postfixadmin-enterprise-grade-management-for-postfix-mail-systems-anno-2026","PostfixAdmin: Gestión de Grado Empresarial para Sistemas de Correo Postfix — Anno 2026","PostfixAdmin es una interfaz de administración centrada en bases de datos diseñada para sistemas de correo Postfix profesionales. En lugar de ocultar la complejidad, proporciona un control preciso sobre dominios, buzones, alias y permisos de remitente. Este artículo explica por qué PostfixAdmin sigue siendo una solución empresarial de confianza en 2026 y cómo encaja en las infraestructuras de correo modernas y centradas en la seguridad.","\u002Fuploads\u002F2026\u002F01\u002Fpostfixadmin-enterprise-grade-management-for-postfix-mail-systems-anno-2026-1768311098693-w36cpk.webp","2026-01-13T07:58:00.000Z",{"id":1429,"slug":1430,"title":1431,"excerpt":1432,"featuredImage":1433,"publishedAt":1434},"10","portal-development-a-scalable-platform-for-performance-multilingual-support-and-extensibility","Desarrollo de Portales: Una Plataforma Escalable para Rendimiento, Soporte Multilingüe y Extensibilidad","Se construye un portal web moderno, escalable y de alto rendimiento, con soporte multilingüe y","\u002Fuploads\u002F2026\u002F01\u002Fportal-development-a-scalable-platform-for-performance-multilingual-support-and-extensibility-1769006690165-vklvij.webp","2026-01-21T10:32:00.000Z",{"id":1436,"slug":1437,"title":1438,"excerpt":1439,"featuredImage":1440,"publishedAt":1441},"382","a-practical-monorepo-architecture-next-js-platform-admin-fastify-api-prisma-and-nginx","Una Arquitectura Monorepo Práctica con Next.js, Fastify, Prisma y NGINX","Explora una arquitectura monorepo práctica utilizando Next.js, Fastify, Prisma y NGINX, destacando la integración y el flujo de trabajo en el mundo real.","\u002Fuploads\u002F2026\u002F01\u002Fa-practical-monorepo-architecture-next-js-platform-admin-fastify-api-prisma-and-nginx-1769885526116-q1100n.webp","2026-01-31T08:18:00.000Z",{"id":1443,"slug":1444,"title":1445,"excerpt":1446,"featuredImage":1447,"publishedAt":1448},"464","falsification-for-ai-reasoning-from-answers-to-tested-hypotheses","Falsación para el razonamiento de IA: De respuestas a hipótesis comprobadas","Los modelos de IA pueden generar evidencia convincente para casi cualquier hipótesis plausible. Una metodología más fiable plantea la pregunta opuesta: ¿qué evidencia debilitaría, contradiría o nos obligaría a abandonar la conclusión? Este artículo desarrolla un razonamiento orientado a la falsación para los LLM utilizando hipótesis rivales, pruebas discriminantes, contraevidencia y criterios de rechazo explícitos.","\u002Fuploads\u002F2026\u002F09\u002Ffalsification-for-ai-reasoning-from-answers-to-tested-hypotheses-1789811137616-3hce1b.webp","2026-09-19T01:11:00.000Z",{"id":1450,"slug":1451,"title":1451,"excerpt":10,"featuredImage":1452,"publishedAt":1453},"369","git-with-automatic-upload-and-synchronization-to-a-production-server","\u002Fuploads\u002F2024\u002F05\u002Fstep-by-step-guide-illustration-showing-the-process-of-setting-up-Git-with-auto-upload-and-synchronization-to-a-production-server-large.webp","2024-05-28T22:48:00.000Z",{"id":1455,"slug":1456,"title":1457,"excerpt":1458,"featuredImage":1459,"publishedAt":1460},"449","google-io-2026-agentic-products-search-workspace-and-shopping","Google I\u002FO 2026: Productos agénticos en Búsqueda, Workspace y Shopping","Google I\u002FO 2026 demostró que la IA agéntica está yendo más allá de las demostraciones de modelos y las herramientas para desarrolladores hacia las superficies de productos cotidianos. Este artículo desglosa cómo Search, Workspace, Gemini Spark y Universal Cart apuntan hacia un nuevo modelo de producto donde los agentes de Google ayudan a los usuarios a investigar, trabajar, comprar y actuar a través de servicios conectados.","\u002Fuploads\u002F2026\u002F05\u002Fgoogle-io-2026-agentic-products-search-workspace-and-shopping-1779228004340-9mqs07.webp","2026-05-21T11:09:00.000Z",{"id":1462,"slug":1463,"title":1464,"excerpt":1465,"featuredImage":1466,"publishedAt":1467},"470","what-should-an-ai-agent-remember-forget-recompute-or-retrieve-again","¿Qué debería recordar, olvidar, recalcular o volver a recuperar un agente de IA?","Los agentes de larga duración no deberían recordarlo todo. Este artículo proporciona un modelo práctico de ciclo de vida para decidir qué pertenece a la memoria duradera, qué se debería recuperar de nuevo, qué es más seguro recalcular y qué debería expirar o ser sustituido.","\u002Fuploads\u002F2026\u002F09\u002Fwhat-should-an-ai-agent-remember-forget-recompute-or-retrieve-again-1790351131087-iehz28.webp","2026-09-25T09:43:00.000Z",{"id":1469,"slug":1470,"title":1471,"excerpt":1472,"featuredImage":1473,"publishedAt":1474},"475","managed-agent-harness-vs-self-hosted-agent-loop-what-you-gain-what-you-lose","Harness de agente gestionado vs. bucle de agente autohospedado: lo que ganas, lo que pierdes","“Agente autoalojado” puede significar arquitecturas muy diferentes. Esta guía separa el arnés gestionado, el entorno de ejecución autoalojado y el bucle de agente totalmente autooperado—y muestra qué límite de control necesitan realmente los equipos.","\u002Fuploads\u002F2026\u002F09\u002Fmanaged-agent-harness-vs-self-hosted-agent-loop-what-you-gain-what-you-lose-1790352403475-kj10jh.webp","2026-09-25T12:05:00.000Z",{"id":1476,"slug":1477,"title":1478,"excerpt":1479,"featuredImage":1480,"publishedAt":1481},"445","qwen-3-6-in-production-release-runbook-ai-rollback-and-llmops-versioning","Qwen 3.6 en producción: Runbook de lanzamiento, rollback de IA y versionado de LLMOps","Qwen 3.6 no es solo otra actualización de modelo. Es un evento de lanzamiento, un escenario de reversión y un problema de versionado al mismo tiempo. Este artículo explica cómo debe manejarse Qwen 3.6 en producción a través de la disciplina de LLMOps, la trazabilidad de prompts y modelos, el despliegue controlado y la preparación para la reversión basada en evidencia.","\u002Fuploads\u002F2026\u002F02\u002Fnew-qwen-3-5-plus-1771515512741-dcbi9p.webp","2026-05-04T02:49:00.000Z",{"id":1483,"slug":1484,"title":1485,"excerpt":1486,"featuredImage":1487,"publishedAt":1488},"1","welcome-to-nuxtwo-multilang-theme","Welcome to NuxtWP Multilang Theme","Introduction to the NuxtWP Multilang Theme - a modern multilingual CMS built with Nuxt 4.","\u002Fuploads\u002F2014\u002F09\u002FSEO-Mobile-Webapplikation-Muenchen-www.stajic.de_3.webp","2025-10-31T11:31:14.829Z","fallback",[],[]]