
La era digital nos ha regalado una cantidad inmensa de información almacenada en archivos en formato PDF. Desde documentos académicos hasta manuales técnicos, los PDFs se han convertido en un estándar para la distribución de textos. Pero, ¿qué sucede cuando, por ejemplo, necesitas extraer un fragmento específico de información de un montón de documentos PDF? Aquí es donde entra “Pregunta a tu PDF”, un asistente virtual que, aprovechando todo el potencial de la IA, te ayuda a obtener respuestas directas de tus archivos PDF usando técnicas avanzadas de Procesamiento del Lenguaje Natural (PLN).
🎯 Descripción del Proyecto
El stack tecnológico de “Pregunta a tu PDF” utiliza tecnologías como LangChain, Together AI, Llama2 y Streamlit para crear un asistente de IA que permite a los usuarios cargar un archivo PDF y hacer preguntas sobre su contenido. Utilizando tecnologías de PLN, el asistente responde con precisión a las consultas del usuario.
💡 Características Principales
- Carga de archivos PDF para análisis: Sube tus archivos PDF y haz la consulta.
- Búsqueda semántica en el contenido del PDF: Encuentra información relevante mediante consultas semánticas.
- Capacidad para hacer preguntas abiertas sobre el contenido del PDF: Haz preguntas y obtén respuestas directas del contenido.
- Interfaz de usuario amigable gracias a Streamlit: Una interfaz sencilla y eficaz para interactuar con el asistente.
🛠 Tecnologías Utilizadas
- Python: Lenguaje de programación principal del proyecto.
- Streamlit: Para construir la interfaz de usuario.
- Together AI (LLM Llama2): Modelo de lenguaje utilizado para el procesamiento de consultas a través de esta plataforma cloud.
- HuggingFace: Plataforma a través de la cual utilizamos un algoritmo para la generación de embeddings.
- Chroma DB: Base de datos vectorizada para almacenar embeddings y facilitar búsquedas.
En el siguiente apartado vamos a desglosar y expandir las siguientes secciones:
1. DOC LOADING (Carga de Documento)
2. SPLITTING (División)
3. STORAGE (Almacenamiento)
4. RETRIEVAL (Recuperación)
5. OUTPUT (Salida)
Según el siguiente diagrama, vamos a ver cómo cada parte del código contribuye a las funcionalidades descritas, explicando sus partes más relevantes y el por qué de las tecnologías seleccionadas.

1. DOC LOADING (Carga de Documento):
El proceso comienza con la carga de un documento PDF. Para esta tarea, se utiliza la biblioteca PyPDF2
que permite leer y extraer información de archivos PDF.
Los datos, y en este caso, los documentos en PDF, son la base para las operaciones de procesamiento de lenguaje natural que seguirán. Es algo crucial, sin información estos modelos no nos proporcionarán las respuestas que esperamos.
En esta etapa, el objetivo es cargar el archivo PDF proporcionado por el usuario en el sistema y prepararlo para su procesamiento posterior.
from PyPDF2 import PdfReader
...
def generate_response(uploaded_file, query_text):
...
loader = PyPDFLoader(file_path)
documents = loader.load()
...
Explicación detallada:
- Importación de la Biblioteca PyPDF2:
from PyPDF2 import PdfReader
: PyPDF2 es una biblioteca de Python utilizada para leer y manipular archivos PDF. En este proyecto, se utiliza para cargar el contenido del archivo PDF proporcionado por el usuario.
2. Creación de una Instancia de PyPDFLoader:
loader = PyPDFLoader(file_path)
: Aquí, se crea una instancia de una clase personalizada llamadaPyPDFLoader
, pasando la ruta del archivo PDF como argumento. Esta clase se encarga de la carga inicial del archivo PDF.
3. Carga del Documento:
documents = loader.load()
: El métodoload()
de la instancialoader
se invoca para cargar el archivo PDF. Una vez cargado, el contenido del archivo PDF se almacena en la variabledocuments
, que luego se pasará a las etapas posteriores para su procesamiento.
2. SPLITTING (División):
Después de cargar el documento, el texto se divide (splits) en fragmentos más manejables (chunks) para su procesamiento posterior. Esto se hace para asegurar que el texto sea manejable para el procesamiento de lenguaje natural posterior.
from langchain.text_splitter import RecursiveCharacterTextSplitter
...
text_splitter = RecursiveCharacterTextSplitter(chunk_size=2000, chunk_overlap=200)
docs = text_splitter.split_documents(documents)
...
Explicación detallada:
- Importación de RecursiveCharacterTextSplitter:
from langchain.text_splitter import RecursiveCharacterTextSplitter
: Se importa la claseRecursiveCharacterTextSplitter
de la bibliotecalangchain
, que proporciona funcionalidades para dividir textos en fragmentos.
2. Creación de una Instancia de RecursiveCharacterTextSplitter:
text_splitter = RecursiveCharacterTextSplitter(chunk_size=2000, chunk_overlap=200)
: Se crea una instancia deRecursiveCharacterTextSplitter
, especificando un tamaño de fragmento de 2000 caracteres y un solapamiento de 200 caracteres entre fragmentos.
Es importante encontrar el equilibrio entre el tamaño de fragmento y el solapamiento para que cuando se extraiga el contexto mediante la búsqueda semántica el modelo tenga la suficiente información para dar una respuesta correcta.
3. División de Documentos:
docs = text_splitter.split_documents(documents)
: Se invoca el métodosplit_documents()
para dividir el texto del documento en fragmentos. Estos fragmentos se almacenan en la variabledocs
, que luego se utilizará para generar embeddings.
En este caso se han seleccionado estas tecnologías:
- LangChain proporciona la estructura y las herramientas necesarias para configurar y ejecutar la recuperación de información, facilitando la integración con el almacenamiento de vectores y el modelo de lenguaje.
3. STORAGE (Almacenamiento):
Una vez dividido, se generan embeddings para cada fragmento de texto utilizando el modelo “BAAI/bge-base-en” a través de Hugging Face. Los embeddings son representaciones vectoriales del texto que facilitan la búsqueda semánticas. Se almacenarán en una base de datos vectorizada que facilitará una recuperación eficiente.from langchain.vectorstores import Chroma
from langchain.embeddings import HuggingFaceEmbeddings
...
model_name = "BAAI/bge-base-en"
embeddings = HuggingFaceEmbeddings(model_name=model_name)
...
db_name = f"./data/chroma_db_{session_uuid}.db"
db = Chroma.from_documents(docs, embedding=embeddings, persist_directory=db_name)
Explicación detallada:
- Generación de Embeddings:
embeddings = HuggingFaceEmbeddings(model_name=model_name)
: Se utiliza el modelo “BAAI/bge-base-en” para generar embeddings del texto que capturan la semántica del contenido.
2. Creación de una base de datos vectorizada:
db = Chroma.from_documents(docs, embedding=embeddings, persist_directory=db_name)
: Se utiliza Chroma DB, una base de datos nativa open-source para guardar los embeddings generados. Esto facilita la recuperación eficiente de información en las etapas posteriores.
En este caso se han seleccionado estas tecnologías:
- Hugging Face esconocido por sus robustos modelos de procesamiento de lenguaje natural. Utilizar esta biblioteca para generar embeddings asegura una representación semántica precisa del contenido del documento.
- Chroma DB proporciona una forma eficaz de almacenar y recuperar embeddings y permite trabajar con bases de datos en local.
4. RETRIEVAL (Recuperación):
Con los embeddings almacenados, se utiliza LangChain para recuperar información relevante basada en la consulta del usuario.
from langchain.chains import RetrievalQA
...
qa = RetrievalQA.from_chain_type(
llm=tog_llm,
chain_type="stuff",
retriever=db.as_retriever(search_kwargs={"k": 3}),
chain_type_kwargs=chain_type_kwargs,
return_source_documents=True
)
...
llm_response = qa(query_text)
Explicación detallada:
- Creación de la Instancia de Recuperación:
qa = RetrievalQA.from_chain_type(...)
: Se crea una instancia deRetrievalQA
, una clase diseñada para la recuperación de información, utilizando la funciónfrom_chain_type
. Se pasa una referencia al modelo de lenguaje, el almacenamiento de vectores, y otros argumentos necesarios para configurar la recuperación.
2. Ejecución de la Recuperación:
llm_response = qa(query_text)
: Se invoca el método de la instanciaqa
con la consulta del usuario como argumento. Este método lleva a cabo la recuperación de información, buscando en los embeddings almacenados para encontrar los fragmentos de texto más relevantes en respuesta a la consulta.
La recuperación eficaz de información es crucial para proporcionar respuestas precisas y útiles a las consultas del usuario. Un sistema de recuperación bien configurado y eficiente mejora la experiencia del usuario al proporcionar respuestas rápidas y relevantes.
En nuestra aplicación, la configuración de los parámetros de recuperación, como el número de documentos a recuperar (k: 3
en este caso), afecta directamente a la precisión y la eficacia de la recuperación que está relacionado con la división de fragmentos y solapamiento que hemos comentado antes.
Una elección adecuada de estos parámetros es crucial para el éxito del proyecto.
“La sinergia entre el stack tecnológico propuesto permite una interacción fluida y precisa con los documentos PDF, facilitando la extracción de información relevante a través de consultas de lenguaje natural.”
5. OUTPUT (Salida):
Finalmente, la información recuperada se procesa y se presenta al usuario a través de una interfaz web construida con Streamlit.
Esta etapa se centra en procesar y presentar la información recuperada a los usuarios a través de una interfaz interactiva. La salida se genera en respuesta a las preguntas del usuario basadas en la información recuperada de los documentos.
import streamlit as st
...
class TogetherLLM(LLM):
...
def _call(self, prompt, **kwargs):
...
return text
...
response = generate_response(uploaded_file, query_text)
...
if len(result):
st.success(response)
Explicación detallada:
- Procesamiento de Respuesta:
class TogetherLLM(LLM)
: Se define una clase que extiende la claseLLM
de LangChain para procesar las preguntas del usuario y generar respuestas utilizando el modelo LLM (Llama2) a través del servicio de cloud Together AI.def _call(self, prompt, **kwargs)
: Este método define cómo se procesan las preguntas y se genera una respuesta. La respuesta procesada se devuelve como texto.
2. Generación de Respuesta:
response = generate_response(uploaded_file, query_text)
: Se invoca la funcióngenerate_response
para procesar la pregunta del usuario y generar una respuesta basada en la información recuperada de los documentos.
3. Presentación de Respuesta:
if len(result): st.success(response)
: Finalmente, si se genera una respuesta, se presenta al usuario a través de la interfaz de Streamlit.
En este caso se han seleccionado estas tecnologías:
- Streamlit proporciona una plataforma para crear interfaces de usuario interactivas y presentar información de manera clara y efectiva.
- Together AI (LLM Llama2) proporciona el servicio para ejecutar el modelo de lenguaje Llama2 para procesar preguntas y generar respuestas precisas.

La salida completa el flujo de trabajo del proyecto, y proporciona una interfaz interactiva y fácil de usar para que los usuarios interactúen con el sistema y obtengan respuestas a sus preguntas basadas en el contenido de los documentos PDF cargados.

- Stack tecnológico: El proyecto ha logrado integrar diversas tecnologías como LangChain, Together AI, Hugging Face, Streamlit y Chroma DB de manera eficaz para crear un asistente de IA robusto.
- Resolución de Problemas Reales: La idea de crear un sistema que facilite la extracción de información de documentos PDF responde a un problema real y frecuente. Es un paso hacia la automatización de la recuperación de información, lo que puede ahorrar tiempo y esfuerzo significativos en el día a día.
- Experiencia de Usuario: La interfaz de usuario amigable y la capacidad de proporcionar respuestas precisas a las preguntas hacen de este proyecto una herramienta potencialmente valiosa para los usuarios.
🚀 Cómo ejecutar el proyecto
Sigue estos pasos para configurar y ejecutar el proyecto:
- Clonar el repositorio:
git clone https://github.com/albertgilopez/streamlit
2. Instalar las dependencias:
pip install -r requirements.txt
3. Ejecutar el archivo de Streamlit:
streamlit run app.py
Abre tu navegador y visita http://localhost:8501 para interactuar con el asistente. Si no estás familiarizado con Streamlit puedes empezar por aquí.
🖥 Uso
- Sube un archivo PDF mediante la interfaz de usuario.
- Una vez cargado el archivo, se activará un campo de texto.
- Escribe tu pregunta en el campo de texto.
- Haz clic en el botón “Preguntar” para obtener tu respuesta.
Cada nueva iteración eliminará el contenido anterior. La aplicación no guarda ningún documento, sesión o interacción que se pueda asociar contigo.
🤝 Contribuir
Si deseas contribuir al proyecto, sigue estos pasos:
- Haz un fork del repositorio.
- Crea una nueva rama con nuevas características o corrección de errores.
- Envía una solicitud de extracción.
📜 Licencia
Este proyecto está bajo la Licencia MIT.
El código fuente para este proyecto está disponible en GitHub.
Si te interesa aprender como explotar la IA, conocer algunas de las tecnologías que más se están utilizando actualmente y cómo se puede aplicar a este caso de uso específico este proyecto es un buen inicio.
GitHub – albertgilopez/streamlit
Contribute to albertgilopez/streamlit development by creating an account on GitHub.github.com
La integración de Streamlit facilita la interacción con el asistente y es una manera rápida de construir y compartir aplicaciones. También, el uso PLN proporcionan una experiencia de usuario de 10.
El proyecto supone una base para explorar futuras mejoras y nuevos casos de uso, por ejemplo, trabajar con diferentes tipos de documentos y formatos, y la incorporación de características adicionales que pueden enriquecer aún más la experiencia del usuario.
Estos serán algunos de los siguientes puntos en los que estaré trabajando:
1. Soporte para Más Formatos de Documento: Ampliar la compatibilidad para incluir otros formatos de documentos populares como DOCX, TXT, CSV, etc.
2. Mejora de la Precisión de la Búsqueda: Continuar mejorando la precisión de las respuestas mediante la optimización del modelo de lenguaje y la lógica de recuperación de información.
3. Integración con Servicios en la Nube: Permitir la carga y el procesamiento de documentos almacenados en servicios de almacenamiento en la nube como Google Drive o Dropbox.
4. Funcionalidad de Resumen Automático: Añadir una función que permita generar resúmenes automáticos de los documentos cargados.
5. Interfaz de Usuario Mejorada: Mejorar la interfaz de usuario para una experiencia más intuitiva y agradable, posiblemente añadiendo una funcionalidad de arrastrar y soltar para la carga de documentos, y una visualización mejorada de las respuestas.
6. Autenticación y Seguridad: Implementar características de autenticación y seguridad para proteger la información del usuario y los documentos cargados.
7. Escalabilidad y Rendimiento: Optimizar el rendimiento y la escalabilidad del sistema para manejar un mayor número de usuarios y consultas simultáneas.
8. Feedback de Usuario: Implementar una funcionalidad que permita a los usuarios proporcionar feedback sobre la precisión y utilidad de las respuestas proporcionadas, y utilizar este feedback para mejorar el sistema.
9. Historial de Consultas: Permitir a los usuarios revisar y volver a las consultas anteriores.
10. Implementación de Chatbot: Implementar una funcionalidad de chatbot para una interacción más dinámica con los usuarios.
11. Análisis y Visualización de Datos: Proporcionar características de análisis y visualización de datos para ayudar a los usuarios a entender el contenido de sus documentos a un nivel más profundo.
12. Documentación y Tutoriales Mejorados: Proporcionar documentación completa y tutoriales para ayudar a los usuarios a entender y utilizar todas las características del sistema.
Aquí te dejo de nuevo el proyecto para que puedas probarlo:

Úsalo y dime que te parece.
Algunas referencias que he utilizado para el proyecto:
🦜️ LangChain + Streamlit🔥+ Llama 🦙: Bringing Conversational AI to Your Local Machine 🤯
Integrating Open Source LLMs and LangChain for Free Generative Question Answering (No API Key required)ai.plainenglish.io
Prompt Engineering with Llama 2: Four Practical Projects using Python, Langchain, and Pinecone
💡 This Llama 2 Prompt Engineering course helps you stay on the right side of change. In today’s fast-paced…academy.finxter.com