first commit
This commit is contained in:
0
langchain_tools/__init__.py
Normal file
0
langchain_tools/__init__.py
Normal file
BIN
langchain_tools/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
langchain_tools/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
langchain_tools/__pycache__/lc_tools.cpython-311.pyc
Normal file
BIN
langchain_tools/__pycache__/lc_tools.cpython-311.pyc
Normal file
Binary file not shown.
BIN
langchain_tools/__pycache__/pdf_tools.cpython-311.pyc
Normal file
BIN
langchain_tools/__pycache__/pdf_tools.cpython-311.pyc
Normal file
Binary file not shown.
BIN
langchain_tools/__pycache__/tools.cpython-311.pyc
Normal file
BIN
langchain_tools/__pycache__/tools.cpython-311.pyc
Normal file
Binary file not shown.
185
langchain_tools/lc_tools.py
Normal file
185
langchain_tools/lc_tools.py
Normal 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
|
||||
61
langchain_tools/pdf_tools.py
Normal file
61
langchain_tools/pdf_tools.py
Normal 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
202
langchain_tools/tools.py
Normal 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
|
||||
Reference in New Issue
Block a user