first commit

This commit is contained in:
mongar
2024-04-25 16:01:27 -05:00
parent 324bae0939
commit 337f054a35
50 changed files with 25266 additions and 0 deletions

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

185
langchain_tools/lc_tools.py Normal file
View File

@@ -0,0 +1,185 @@
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_community.llms import OpenAI
from langchain_community.chat_models import ChatOpenAI
from langchain_core.prompts import PromptTemplate
from langchain.memory.buffer import ConversationBufferMemory
import os
import streamlit as st
from dotenv import load_dotenv
from langchain.chains import (
RetrievalQAWithSourcesChain,
ConversationalRetrievalChain)
class LangChainTools():
"""
Esta clase maneja algunas herramientas integraciones con las que
cuenta LangChain.
"""
def load_embedding_opnai(self):
"""Esta funcion carga un modelo de embedding de OpenAI
Returns:
_type_: Retorno a un objetito de tipo embedding de OpenAI
"""
# Cargamos la variable que contiene la api_key de OpenAI
load_dotenv()
openai_api_key = os.getenv('api_key')
# Define an OpenAI embeddings model
self.embedding_model = OpenAIEmbeddings(openai_api_key=openai_api_key)
# st.success('El modelo de embeddins de OpneAI se ha cargado')
return self.embedding_model
@st.cache_resource
def create_vector_strore(_self, _docs_split: list, _file_name: str, _embedding_model):
"""Esta funcion construye un vector store a partir de un documento
Args:
_docs_split (list): Lista de documentos divididos
_file_name (str): Nombre del documento
"""
db_name = _file_name.replace('.pdf', '').replace(' ', '_').lower()
# Cargamos el modelo de embeddings
# _embedding_model = self._embedding_model
# Verificamos si existe la vector strore
persist_directory = f"embeddings/{db_name}"
if os.path.exists(persist_directory):
vectordb = Chroma(
persist_directory=persist_directory,
embedding_function=_embedding_model)
else:
vectordb = Chroma.from_documents(
persist_directory=persist_directory,
documents=_docs_split,
embedding=_embedding_model)
vectordb.persist()
return vectordb
def load_llm_openai(self):
"""Esta funcion carga un modelo de LLM de OpenAI
Returns:
_type_: Retorno a un objetito de tipo LLM de OpenAI
"""
# Cargamos la variable que contiene la api_key de OpenAI
load_dotenv()
openai_api_key = os.getenv('api_key')
temperature = 0.5
llm_openai = ChatOpenAI(model_name="gpt-3.5-turbo",
temperature=temperature,
openai_api_key=openai_api_key,
max_tokens=1000)
return llm_openai
def load_prompt_template(self):
"""Esta funcion construye un prompt template de lanfchain.
Returns:
_type_: Retorno a un prompt template de LangChain.
"""
template = """Responde a la siguiente pregunta utilizando los documentos proporcionados y citando las fuentes relevantes entre corchetes []:
Pregunta: {question}
Respuesta:"""
prompt_template = PromptTemplate(
template=template, input_variables=["question"])
return prompt_template
def define_retrieval_qa(
self, _llm, _vectordb, _file_name, _embedding_model
):
"""Esta función integra un LLM y una base de datos vectorial en una
chain de LangChain para hacer requerimientos. Este modelo no integra memoria.
Args:
_llm (_type_): <Modelo Largo de Lenguaje.
_vectordb (_type_): Base de datos vectorial.
_file_name (_type_): Nombre del archvio con la que se crea la BDV
para cargarla si existe.
_embedding_model (_type_): Modelo de embedding.
Returns:
_type_: Retorna un objeto RetrievalQAWithSourcesChain con el quie
se pueden hacer requerimientos a la chain que integra el modelo
y la BDV.
"""
db_name = _file_name.replace('.pdf', '').replace(' ', '_').lower()
# Verificamos si existe la vector strore
persist_directory = f"embeddings/{db_name}"
_vectordb = Chroma(
persist_directory=persist_directory,
embedding_function=_embedding_model)
# Define the Retrieval QA Chain to integrate the database and LLM
qa = RetrievalQAWithSourcesChain.from_chain_type(
_llm,
retriever=_vectordb.as_retriever(),
return_source_documents=True, # Devuelve los documentos fuente
max_tokens_limit=1000, # Límite máximo de tokens para el LLM
reduce_k_below_max_tokens=True, # Reduce k si los tokens exceden el límite
verbose=True, # Modo verboso
)
return qa
@st.cache_resource
def define_retrieval_qa_memory(
_self, _llm, _vectordb, _file_name, _embedding_model
):
"""Esta función integra un LLM y una base de datos vectorial en una
chain de LangChain para hacer requerimientos. Este modelo integra memoria.
Args:
_llm (_type_): <Modelo Largo de Lenguaje.
_vectordb (_type_): Base de datos vectorial.
_file_name (_type_): Nombre del archvio con la que se crea la BDV
para cargarla si existe.
_embedding_model (_type_): Modelo de embedding.
Returns:
_type_: Retorna un objeto RetrievalQAWithSourcesChain con el quie
se pueden hacer requerimientos a la chain que integra el modelo
y la BDV.
"""
db_name = _file_name.replace('.pdf', '').replace(' ', '_').lower()
# Verificamos si existe la vector strore
persist_directory = f"embeddings/{db_name}"
_vectordb = Chroma(
persist_directory=persist_directory,
embedding_function=_embedding_model)
# Configura la memoria
memory = ConversationBufferMemory(
memory_key="chat_history", return_messages=True)
# Define the Retrieval QA Chain to integrate the database and LLM
conversation = ConversationalRetrievalChain.from_llm(
_llm,
retriever=_vectordb.as_retriever(),
memory=memory,
verbose=False # Modo verboso
)
return conversation

View File

@@ -0,0 +1,61 @@
import os
from langchain_community.document_loaders.pdf import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
import streamlit as st
class PdfLangChain:
"""Clase para menejar documentos pdf con LangChain.
.
Attributes:
file_name (str): Nombre del archivo PDF.
file_path (str): Ruta del archivo PDF.
"""
def __init__(self, file_name: str) -> None:
"""
Inicializa la clase.
Args:
file_name (str): Nombre del archivo PDF.
"""
self.file_name = file_name
self.file_path = os.path.join('documents', 'pdfs', self.file_name)
# Verificar si el directorio exist, sino, crearlo
if not os.path.exists(self.file_path):
os.mkdir(self.file_path)
@st.cache_resource
def load_pdf(_self):
"""Carga el documento PDF.
Returns:
_type_: Lista de documentos cargados.
"""
loader = PyPDFLoader(_self.file_path)
_self.docs = loader.load()
return _self.docs
def split_docs(self, data: list) -> list:
"""Divide los documentos en fragmentos más pequeños.
Args:
data (list): Listra de docuemntos cargador
Returns:
_type_: Retrorna una lista con fragmentos mas pequeños
del documento.
"""
chunk_size = 2000
chunk_overlap = 300
splitter = RecursiveCharacterTextSplitter(
chunk_size=chunk_size,
chunk_overlap=chunk_overlap)
self.docs_split = splitter.split_documents(data)
return self.docs_split

202
langchain_tools/tools.py Normal file
View File

@@ -0,0 +1,202 @@
from langchain_community.document_loaders.pdf import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_community.llms import OpenAI
from langchain_community.chat_models import ChatOpenAI
from langchain import PromptTemplate
from langchain.chains import RetrievalQAWithSourcesChain, ConversationalRetrievalChain
import os
from dotenv import load_dotenv
import streamlit as st
from langchain.prompts import BasePromptTemplate
from langchain.memory.buffer import ConversationBufferMemory
def pdf_load(file_name: str):
# Cargar el archivo PDF utilizando el modelo rápido de PDF
pdf_path = os.path.join('documents/pdfs', file_name)
loader = PyPDFLoader(
pdf_path
)
# Cargar el contenido del PDF en una lista de documentos
docs = loader.load()
return docs
def split_docs(_data: list):
chunk_size = 1000
chunk_overlap = 200
# Split the quote using RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=chunk_size,
chunk_overlap=chunk_overlap)
docs_split = splitter.split_documents(_data)
# st.success('El pdf se ha dividido')
return docs_split
def load_embedding_opnai():
# Cargamos la variable que contiene la api_key de OpenAI
load_dotenv()
openai_api_key = os.getenv('api_key')
# Define an OpenAI embeddings model
embedding_model = OpenAIEmbeddings(openai_api_key=openai_api_key)
# st.success('El modelo de embeddins de OpneAI se ha cargado')
return embedding_model
# @st.cache_resource
def create_vector_strore(_docs_split, file_name):
db_name = file_name.replace('.pdf', '').replace(' ', '_').lower()
# Cargamos el modelo de embeddings
embedding_model = load_embedding_opnai()
# Verificamos si existe la vector strore
persist_directory = f"./{db_name}"
if os.path.exists(persist_directory):
vectordb = Chroma(
persist_directory=persist_directory,
embedding_function=embedding_model)
else:
vectordb = Chroma.from_documents(
persist_directory=persist_directory,
documents=_docs_split,
embedding=embedding_model)
vectordb.persist()
# vectordb.persist()
return vectordb
# @st.cache_resource
def load_llm_openai():
# Cargamos la variable que contiene la api_key de OpenAI
load_dotenv()
openai_api_key = os.getenv('api_key')
# llm_openai = OpenAI(model_name="gpt-3.5-turbo-instruct",
# temperature=0.0,
# openai_api_key=openai_api_key,
# max_tokens=1000)
llm_openai = ChatOpenAI(model_name="gpt-3.5-turbo",
temperature=0.0,
openai_api_key=openai_api_key,
max_tokens=1000)
# st.success('El modelo LLM de OpneAI se ha cargado')
return llm_openai
# @st.cache_resource
def load_prompt_template():
template = """Responde a la siguiente pregunta utilizando los documentos proporcionados y citando las fuentes relevantes entre corchetes []:
Pregunta: {question}
Respuesta:"""
prompt_template = PromptTemplate(
template=template, input_variables=["question"])
return prompt_template
# def define_retrieval_qa(_llm, vectordb, file_name, embedding_model):
#
# db_name = file_name.replace('.pdf', '').replace(' ', '_').lower()
#
# # Verificamos si existe la vector strore
# persist_directory = f"./{db_name}"
#
# vectordb = Chroma(
# persist_directory=persist_directory,
# embedding_function=embedding_model)
#
# memory = ConversationBufferMemory(
# memory_key="chat_history", return_messages=True)
#
# # Define the Retrieval QA Chain to integrate the database and LLM
# qa = RetrievalQAWithSourcesChain.from_chain_type(
# _llm,
# memory=memory,
# retriever=vectordb.as_retriever(),
# return_source_documents=True, # Devuelve los documentos fuente
# max_tokens_limit=1000, # Límite máximo de tokens para el LLM
# reduce_k_below_max_tokens=True, # Reduce k si los tokens exceden el límite
# verbose=True, # Modo verboso
# )
#
# return qa
def define_retrieval_qa(_llm, vectordb, file_name, embedding_model):
db_name = file_name.replace('.pdf', '').replace(' ', '_').lower()
# Verificamos si existe la vector strore
persist_directory = f"./{db_name}"
vectordb = Chroma(
persist_directory=persist_directory,
embedding_function=embedding_model)
memory = ConversationBufferMemory(
memory_key="chat_history", return_messages=True)
# Define the Retrieval QA Chain to integrate the database and LLM
qa = RetrievalQAWithSourcesChain.from_chain_type(
_llm,
retriever=vectordb.as_retriever(),
return_source_documents=True, # Devuelve los documentos fuente
max_tokens_limit=1000, # Límite máximo de tokens para el LLM
reduce_k_below_max_tokens=True, # Reduce k si los tokens exceden el límite
verbose=True, # Modo verboso
)
return qa
def define_retrieval_qa_memory(_llm, vectordb, file_name, embedding_model):
db_name = file_name.replace('.pdf', '').replace(' ', '_').lower()
# Verificamos si existe la vector strore
persist_directory = f"./{db_name}"
vectordb = Chroma(
persist_directory=persist_directory,
embedding_function=embedding_model)
# Configura la memoria
memory = ConversationBufferMemory(
memory_key="chat_history", return_messages=True)
# Define the Retrieval QA Chain to integrate the database and LLM
conversation = ConversationalRetrievalChain.from_llm(
_llm,
retriever=vectordb.as_retriever(),
memory=memory,
verbose=True # Modo verboso
)
# result = conversation({"query": query, "chat_history": chat_history})
return conversation