Se integra a la apliacion un LLM open source de HuggingFace

This commit is contained in:
mongar 2024-05-01 12:44:57 -05:00
parent 8883868e04
commit 9227a4201f
5 changed files with 329 additions and 31 deletions

2
app.py
View File

@ -57,7 +57,7 @@ if pdf_name:
)
# Cargamos el modelo LLM desde LangChain
llm = langChainTools.load_llm_openai()
llm = langChainTools.load_llm_open_source()
# Creamos la cadena que integra Vectorstroe, el LLM para hacer consultas.
# Para este caso la cadena tene el parametro de memoria.

134
app_2.py Normal file
View File

@ -0,0 +1,134 @@
# import os
# from dotenv import load_dotenv
# from langchain_community.chat_models import ChatOpenAI
import streamlit as st
from chats.streamlit_tools import import_file # ,clear_cache
from streamlit_extras.add_vertical_space import add_vertical_space
from langchain_tools.pdf_tools import PdfLangChain
from langchain_tools.lc_tools import LangChainTools
from chats.chat_tools import MessageManager
from langchain_community.llms import HuggingFaceEndpoint
# App title
st.set_page_config(page_title="LLMOneClusterTeam")
# sidebar
with st.sidebar:
# Cargar el logo (asegúrate de que el archivo de imagen esté en la misma carpeta que tu script)
logo_path = "documents/Logo azulblanco.png"
logo = st.sidebar.image(logo_path, width=200)
# Ajusta el ancho según sea necesario
add_vertical_space(28)
# pdf_name = import_file()
st.markdown("Built by [OneCluster](https://www.onecluster.org/).")
col1, col2 = st.columns([1.1, 1])
with col1:
st.title(
"DocumentAssist",
)
with col2:
logo_2 = st.image("documents/pdfs/logo_1-removebg-preview.png", width=110)
pdf_name = import_file()
if pdf_name:
with st.spinner("Processing the document..."):
# Inicializamos la clase PdfLangChain
pdfLangChain = PdfLangChain(pdf_name)
pdf_name = pdfLangChain.file_name
# Cargamos el documento PDF
docs: list = pdfLangChain.load_pdf()
# Dividimos los documentos en partes mas pequenas
docs_split: list = pdfLangChain.split_docs(docs)
# Instanciamos la clase LangChainTools que contiene herramientras LangChain
langChainTools = LangChainTools()
# Cargamos el modelo de embeddings
embedding_model = langChainTools.load_embedding_opnai()
# Creamos el vector store
docstorage = langChainTools.create_vector_strore(
docs_split, pdf_name, embedding_model
)
# Cargamos el modelo LLM desde LangChain
llm = langChainTools.load_llm_open_source()
# Creamos la cadena que integra Vectorstroe, el LLM para hacer consultas.
# Para este caso la cadena tene el parametro de memoria.
qa = langChainTools.define_retrieval_qa_memory(
llm, docstorage, pdf_name, embedding_model
)
# Store conversation history
if "messages" not in st.session_state.keys():
st.session_state.messages = [
{
"role": "assistant",
"content": "Hola, soy una IA con el que puedes chatear con tu PDF. Haz un pregunta al documento.",
}
]
# Display or clear chat messages
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.write(message["content"])
def clear_chat_history():
st.session_state.messages = [
{
"role": "assistant",
"content": "Hola, soy una IA con el que puedes chatear con tu PDF. Haz un pregunta al documento.",
}
]
st.sidebar.button("Clear chat history", on_click=clear_chat_history)
@st.cache_resource
def get_num_tokens(prompt):
"""Get the number of tokens in a given prompt"""
return len(prompt.split())
# Function for generating Snowflake Arctic response
# User-provided prompt
if prompt := st.chat_input():
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.write(prompt)
# Generate a new response if last message is not from assistant
if st.session_state.messages[-1]["role"] != "assistant":
with st.spinner("Thinking..."):
# Creamos la cadena que integra Vectorstroe, el LLM para hacer consultas.
# Para este caso la cadena tene el parametro de memoria.
qa = langChainTools.define_retrieval_qa_memory(
llm, docstorage, pdf_name, embedding_model
)
input = "\n".join([msg["content"] for msg in st.session_state.messages])
query = qa.invoke({"question": f"{prompt}"}, return_only_outputs=True)
response_text_en = query["answer"]
documents_source = query["source_documents"]
messageManager = MessageManager()
citation: str = messageManager.generate_citations(documents_source)
# st.markdown(citation)
with st.chat_message("assistant"):
st.write(response_text_en)
# st.write(translation)
st.session_state.messages.append(
{"role": "assistant", "content": response_text_en}
)
expander = st.expander("Fuentes")
expander.markdown(citation)

View File

@ -7,12 +7,11 @@ from langchain.memory.buffer import ConversationBufferMemory
import os
import streamlit as st
from dotenv import load_dotenv
from langchain.chains import (
RetrievalQAWithSourcesChain,
ConversationalRetrievalChain)
from langchain.chains import RetrievalQAWithSourcesChain, ConversationalRetrievalChain
from langchain_community.llms import HuggingFaceEndpoint
class LangChainTools():
class LangChainTools:
"""
Esta clase maneja algunas herramientas integraciones con las que
cuenta LangChain.
@ -27,7 +26,7 @@ class LangChainTools():
# Cargamos la variable que contiene la api_key de OpenAI
load_dotenv()
openai_api_key = os.getenv('api_key')
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')
@ -35,7 +34,9 @@ class LangChainTools():
return self.embedding_model
@st.cache_resource
def create_vector_strore(_self, _docs_split: list, _file_name: str, _embedding_model):
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:
@ -43,7 +44,7 @@ class LangChainTools():
_file_name (str): Nombre del documento
"""
db_name = _file_name.replace('.pdf', '').replace(' ', '_').lower()
db_name = _file_name.replace(".pdf", "").replace(" ", "_").lower()
# Cargamos el modelo de embeddings
# _embedding_model = self._embedding_model
@ -53,13 +54,14 @@ class LangChainTools():
if os.path.exists(persist_directory):
vectordb = Chroma(
persist_directory=persist_directory,
embedding_function=_embedding_model)
persist_directory=persist_directory, embedding_function=_embedding_model
)
else:
vectordb = Chroma.from_documents(
persist_directory=persist_directory,
documents=_docs_split,
embedding=_embedding_model)
embedding=_embedding_model,
)
vectordb.persist()
@ -74,16 +76,44 @@ class LangChainTools():
# Cargamos la variable que contiene la api_key de OpenAI
load_dotenv()
openai_api_key = os.getenv('api_key')
openai_api_key = os.getenv("api_key")
temperature = 0.5
llm_openai = ChatOpenAI(model_name="gpt-3.5-turbo",
llm_openai = ChatOpenAI(
model_name="gpt-3.5-turbo",
temperature=temperature,
openai_api_key=openai_api_key,
max_tokens=1000)
max_tokens=1000,
)
return llm_openai
def load_llm_open_source(self):
"""Esta funcion carga un modelo de LLM OpenSource desde HuggingFace
Returns:
_type_: Retorno a un objetito de tipo LLM de OpenAI
"""
# model_huggingface = "google/gemma-1.1-7b-it" # Es buena y funciona en espanol
# model_huggingface = (
# "google/gemma-1.1-2b-it" # Es buena y funciona en espanol funciona rapido
# )
# model_huggingface = 'tiiuae/falcon-7b-instruct'
# model_huggingface = 'mistralai/Mistral-7B-Instruct-v0.2'
huggingfacehub_api_token = "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"
model_huggingface = "mistralai/Mixtral-8x7B-Instruct-v0.1" # Es buena y funciona en espanol funciona rapido
# Define the LLM
llm = HuggingFaceEndpoint(
repo_id=model_huggingface,
huggingfacehub_api_token=huggingfacehub_api_token,
temperature=0.5,
max_new_tokens=500,
)
return llm
def load_prompt_template(self):
"""Esta funcion construye un prompt template de lanfchain.
@ -97,13 +127,12 @@ class LangChainTools():
Respuesta:"""
prompt_template = PromptTemplate(
template=template, input_variables=["question"])
template=template, input_variables=["question"]
)
return prompt_template
def define_retrieval_qa(
self, _llm, _vectordb, _file_name, _embedding_model
):
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.
@ -120,14 +149,14 @@ class LangChainTools():
y la BDV.
"""
db_name = _file_name.replace('.pdf', '').replace(' ', '_').lower()
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)
persist_directory=persist_directory, embedding_function=_embedding_model
)
# Define the Retrieval QA Chain to integrate the database and LLM
qa = RetrievalQAWithSourcesChain.from_chain_type(
@ -161,28 +190,35 @@ class LangChainTools():
y la BDV.
"""
db_name = _file_name.replace('.pdf', '').replace(' ', '_').lower()
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)
persist_directory=persist_directory, embedding_function=_embedding_model
)
# Configura la memoria
memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True,
output_key='answer')
memory_key="chat_history", return_messages=True, output_key="answer"
)
# 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_source_documents=True # Devuelve los documentos fuente
verbose=True, # Modo verboso
return_source_documents=True, # Devuelve los documentos fuente
)
template = """Utiliza los siguientes fragmentos de contexto para responder la pregunta al final. Si no sabes la respuesta, simplemente di que no sabes, no intentes inventar una respuesta. La respuesta dala con un formateo de markdown. Responde a la pregunta siempre en español.
{context}
Pregunta: {question}
Respuesta:"""
conversation.combine_docs_chain.llm_chain.prompt.template = template
return conversation

128
pruebas_open_source.py Normal file
View File

@ -0,0 +1,128 @@
from langchain_community.llms import HuggingFaceEndpoint
from langchain.chains import LLMChain
from langchain.memory import ConversationBufferMemory
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAIEmbeddings
# model_huggingface = 'google/gemma-1.1-7b-it' # Es buena y funciona en espanol
# model_huggingface = 'tiiuae/falcon-7b-instruct'
# model_huggingface = 'mistralai/Mistral-7B-Instruct-v0.2'
# model_huggingface = "google/gemma-7b"
# model_huggingface = (
# "mistralai/Mixtral-8x7B-Instruct-v0.1" # Es muy buena y funciona en espanol
# )
huggingfacehub_api_token = "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"
model_huggingface = (
"google/gemma-1.1-2b-it" # Es buena y funciona en espanol funciona rapido
)
# Define the LLM
llm = HuggingFaceEndpoint(
repo_id=model_huggingface,
huggingfacehub_api_token=huggingfacehub_api_token,
temperature=0.5,
max_new_tokens=500,
)
# for chunk in llm.stream("Como se construye un ensayo?"):
# print(chunk, end="", flush=True)
# question = "Como se construye un ensayo?"
# output = llm.invoke(question)
# print(output)
# prompt = PromptTemplate(
# input_variables=["chat_history", "human_input"], template=template
# )
# memory = ConversationBufferMemory(memory_key="chat_history")
# llm = OpenAI()
# llm_chain = LLMChain(
# llm=llm,
# prompt=promptas st
from langchain_tools.pdf_tools import PdfLangChain
from langchain_tools.lc_tools import LangChainTools
from langchain_community.llms import HuggingFaceEndpoint
from langchain.chains.question_answering import load_qa_chain
from langchain.memory import ConversationBufferMemory
from langchain_core.prompts import PromptTemplate
# Inicializamos la clase PdfLangChain
pdfLangChain = PdfLangChain("1.TC_Malamud, Se está muriendo la democracia.pdf")
pdf_name = pdfLangChain.file_name
# Cargamos el documento PDF
docs: list = pdfLangChain.load_pdf()
# Dividimos los documentos en partes mas pequenas
docs_split: list = pdfLangChain.split_docs(docs)
# Instanciamos la clase LangChainTools que contiene herramientras LangChain
langChainTools = LangChainTools()
# Cargamos el modelo de embeddings
embedding_model = langChainTools.load_embedding_opnai()
# Creamos el vector store
docstorage = langChainTools.create_vector_strore(docs_split, pdf_name, embedding_model)
template = """Tu eres un chatbot y tienes una conversacion con un humano quien te \
hara preguntas y tu deberas responder con base al context y al chat_history. Si no \
conocer la respuesta, solo repsonde que no sabes como responder.
{context}
{chat_history}
Human: {question}
Chatbot:"""
prompt = PromptTemplate(
input_variables=["chat_history", "human_input", "context"], template=template
)
memory = ConversationBufferMemory(memory_key="chat_history", input_key="question")
chain = load_qa_chain(
llm,
chain_type="stuff",
memory=memory,
prompt=prompt,
verbose=True,
)
query = "cuales son los elementos clave del texto?"
# documents = docstorage.similarity_search(query)
# respuesta = chain.invoke(
# {"question": f"{prompt}", "input_documents": documents}, return_only_outputs=False
# )
# chain({"input_documents": documents, "human_input": query}, return_only_outputs=True)
# print(documents)
# print(respuesta["output_text"])
from langchain.chains import RetrievalQAWithSourcesChain, ConversationalRetrievalChain
chain = ConversationalRetrievalChain.from_llm(llm, docstorage.as_retriever())
print(dir(chain))
print(chain)
# template = f"Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer.\n\n{context}\n\nQuestion: {question}\nHelpful Answer:"
template = "Utiliza los siguientes fragmentos de contexto para responder la pregunta al final. Si no sabes la respuesta, simplemente di que no sabes, no intentes inventar una respuesta.\n\n{context}\n\nQuestion: {question}\nRespuesta útil:"
# Define el nuevo template que deseas utilizar
new_template = "Este es un nuevo template que reemplazará al anterior.\n\n{context}\n\nPregunta: {question}\nRespuesta útil:"
# Accede al prompt del LLMChain en combine_docs_chain y actualiza su template
chain.combine_docs_chain.llm_chain.prompt.template = template
print("\n\n")
# Imprime la instancia de clase para verificar que se haya actualizado el template
print(chain)