Creación de Cadenas de Preguntas y Respuestas con Modelos de Lenguaje
Resumen
¿Cómo construir una cadena de utilidad para responder preguntas?
La creación de cadenas de utilidad, específicamente diseñadas para resolver preguntas a partir de documentos, es un enfoque que combina técnicas de inteligencia artificial con la manipulación de datos. Utilizando bibliotecas de Python, como chains.retrieval.qa, podemos construir estas cadenas que realizan un proceso de "question answering" o QA, aprovechando la información almacenada en bases de datos específicas.
¿Qué es retrieval.qa y cómo se utiliza?
retrieval.qa es una característica crucial de la librería de cadenas que nos permite crear una cadena para resolver preguntas a partir de un modelo de lenguaje y una base de datos. Aquí, "retrieval" implica la obtención de información, y "QA" se refiere a la resolución de preguntas. Con esta herramienta, podemos recuperar información relevante desde una base de datos vectorial previamente definida, como una almacenada con Chroma.
Para utilizar retrieval.qa, seguimos estos pasos:
Definir el modelo de lenguaje (LLM):
En el ejemplo, utilizamos el modelo gpt3-5, específicamente el gpt3.5 turbo de OpenAI.
Este modelo es cargado y gestionado a través de herramientas de homogeneización de modelos como Langstan, que nos permiten mantener una clase uniforme para distintos tipos de modelos de IA, facilitando la interconectividad y sustituibilidad sin modificar la cadena.
Definir el tipo de cadena:
Usamos el tipo de cadena ChainType Stuff, que permite procesar el texto que cabe completamente en el prompt del modelo.
Este enfoque evita iterar a través de grandes volúmenes de texto, como haría un enfoque MapReduce.
Incorporación de un Retriever:
Un Retriever es esencial en este proceso ya que actúa como la base de datos de donde nuestros modelos de cadena extraerán la información.
En este caso, nuestra base de datos es Chroma, y utilizamos el VectorStore que almacena documentos, como un PDF de un artículo de investigación.
from chains.retrieval.qa import RetrievalQA
# Definir modelo de lenguajellm ='gpt3-5'# Inicializar cadenacadena_resolver = RetrievalQA.from_chain_type( llm=llm, chain_type='Stuff', retriever=VectorStore
)
¿Qué rol juega el búsqueda y el contexto en la resolución de preguntas?
La finalidad de configurar correctamente las búsquedas y contextos es optimizar la precisión y relevancia de las respuestas generadas. A medida que las capacidades de almacenamiento y procesamiento de las bases de datos crecen, estas configuraciones permiten que el sistema adquiera un mayor conocimiento y contexto al resolver preguntas complejas.
Parámetros de búsqueda (SearchQuarks):
Estas son configuraciones importantes que determinan qué fragmentos de texto serán considerados relevantes al responder una pregunta.
En el ejemplo proporcionado, se usa un ajuste que restringe a dos fragmentos de texto. Este número busca equilibrar el contexto proporcionado y el tamaño máximo del prompt aceptado por el modelo.
Balance de contexto:
Al aumentar la cantidad de fragmentos, el modelo tiene un mayor contexto para basar sus respuestas, mejorando su exactitud.
Sin embargo, la limitación sigue siendo el tamaño del prompt que el modelo puede procesar, que actualmente es restringido pero se espera mejore en el futuro.
¿Cómo se ejecuta la cadena para resolver una pregunta?
Una vez que la cadena está correctamente inicializada y configurada con sus parámetros, podemos realizar consultas específicas. Por ejemplo, para evaluar la relevancia de la criptografía de llave pública, simplemente ejecutamos la cadena con la pregunta deseada y obtenemos no solo la respuesta, sino también el contexto relevante del contenido original.
# Ejecutar preguntarespuesta = cadena_resolver.run( pregunta='¿Cuál es la relevancia de la criptografía de llave pública?')print(respuesta)
Con estas herramientas y metodologías, estamos bien posicionados para enfrentar cualquier desafío en el ámbito del "question answering", y con la evolución continua de la tecnología, el potencial solo seguirá creciendo. Mantente al tanto de estas innovaciones y sigue explorando las aplicaciones del aprendizaje automático y procesamiento del lenguaje natural.
No hablo español, pero he podido seguir el curso perfectamente por su didáctica y facilidad de comprensión en portugués. ¡Felicidades!
🚚 Recuperadores (Retrievers)
.
ℹ️ Summary
Esta guía proporciona un caso de uso sobre Recuperadores QA (Retrievers QA), sobre documentos combinados sobre cadenas en un almacenamiento vectorial local, HNSWLib.
.
🗂️ Background
Un recuperador es una interfaz que devuelve documentos a partir de una consulta no estructurada. Es más general que un almacén vectorial.
.
Un recuperador no necesita ser capaz de almacenar documentos, sólo de devolverlos (o recuperarlos). Los almacenes vectoriales pueden utilizarse como columna vertebral de un recuperador, pero también existen otros tipos de recuperadores.
.
Enlaces auxiliares:
Recuperadores (Retrievers)
Almacén vectorial HNSWLib
Recuperadores QA (Retrievers QA)
.
🎯 Problem
Implementar una "Utility Chain" en LangChain utilizando TypeScript para implementar una tarea específica, por ejemplo, procesar y analizar datos textuales para extraer información QA.
.
🚧 Solution
LangChain permite incorporar prompts como parte de un flujo de procesamiento de una aplicación a un concentrado documental, para posteriormente la extracción específica información mediante RetrievalQAChain.
import { RetrievalQAChain } from 'langchain/chains'
Posteriormente, se genera una chain para efectuar un query sobre un nicho de información, por ejemplo una pregunta What time will the meeting be?.
const chain = RetrievalQAChain.fromLLM(llm, vectorStore.asRetriever({ k: 1 }))
const response = await chain.call({
query: 'What time will the meeting be?',
})
Sin embargo, RetrievalQAChain emplea un VectorStore para poder mezclar y seccionar la información.
.
HNSWLib es un almacén de vectores en memoria, o local, que puede guardarse en un archivo. Instalable como dependencia mediante hnswlib-node.
.
Cada almacenamiento vectorial requiere de Incrustaciones (Embeddings), los cuales son un medio para representar información en un formato numérico.
import { OpenAIEmbeddings } from 'langchain/embeddings/openai'
import { HNSWLib } from 'langchain/vectorstores/hnswlib'
const embeddings = new OpenAIEmbeddings({
openAIApiKey: API_TOKEN,
})
const vectorStore = await HNSWLib.fromDocuments(docs, embeddings)
🍻 Discussion
A distintos tipos de Embeddings, configurables para usarlos con LangChain. Dependiendo de caso de uso y la instalación, serán más ajustables para resolver los requerimientos de nuestro producto.
.
Cabe mencionar, que los Embeddings permiten procesar documentos, para permitirnos enfocar en la generación, refinamiento u optimización de nuestros prompts.
import { RetrievalQAChain } from 'langchain/chains'
import { OpenAIEmbeddings } from 'langchain/embeddings/openai'
import { OpenAI } from 'langchain/llms/openai'
import { TextLoader } from 'langchain/document_loaders/fs/text'
import { HNSWLib } from 'langchain/vectorstores/hnswlib'
const API_TOKEN = // 👈 Enter the API Token from OpenAI
const loader = new TextLoader('tmp/conversation.txt')
const docs = await loader.load()
const llm = new OpenAI({
maxTokens: -1,
modelName: 'gpt-4',
temperature: 0,
openAIApiKey: API_TOKEN,
})
const embeddings = new OpenAIEmbeddings({
openAIApiKey: API_TOKEN,
})
const vectorStore = await HNSWLib.fromDocuments(docs, embeddings)
const chain = RetrievalQAChain.fromLLM(llm, vectorStore.asRetriever({ k: 1 }))
const response = await chain.call({
query: 'What time will the meeting be?',
})
console.log(response)
Impecable aporte compa, gracias!
Ya no es necesario utilizar chain_type porque RetrievalQA ya es una cadena completa en sí misma. La clase RetrievalQA combina un modelo de lenguaje y un recuperador de datos para generar respuestas basadas en la información recuperada.
El uso de chain_type es más relevante cuando se trabaja con cadenas más complejas que involucran múltiples pasos o componentes. Por ejemplo, si deseas combinar RetrievalQA con otro tipo de cadena, como una cadena de generación de lenguaje, puedes utilizar chain_type para especificar cómo se conectan y se comunican entre sí.
Genial puntualidad brother para aclarar el tema.
RetrievalQA fue deprecado en langchain V1 is fur transladada a la libreria langchain-classic. Para lograr el mismo resultado se puede usar LCEL (Langchain Expressiong Language).
Ejemplo 1:
"""this example will retrieves the full documents content from the 2 selected embeddings vectors based on semantic meaning"""from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
# Add a propt template specify answer question based on contextretriever_question_and_answer_prompt = ChatPromptTemplate.from_template("""Answer based on context:
{context}
Question: {question}""")# define the LCEL chain.chain_that_qa_complete_document_content =({"context": vectorstore.as_retriever(search_kwargs={"k":2}),"question":lambda x: x}| retriever_question_and_answer_prompt
| llm
| StrOutputParser())answer = chain_that_qa_complete_document_content.invoke("Cual es la relevancia de la criptografia de llave publica?")
Ejemplo 2:
"""This example will retrieves a summarize of the page content for the 2 found embeddings based on the provided questions and the context.
chain steps:
1. Found embeddings, based kn semantic meaning
2. get a resume from each found page content
3. ask the question to LLM
4. Retireve llm response as string output text
"""from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableLambda
from langchain_openai import ChatOpenAI
defsummarize_documents(docs):"""Summarize each retrieved document"""print(f"Retrieved: {len(docs)} documents") summaries =[]for doc in docs:# Create a summarization chain summary_prompt = ChatPromptTemplate.from_template("Summarize this document in 2-3 sentences:\n\n{content}") summary_chain = summary_prompt | llm | StrOutputParser() doc_summary = summary_chain.invoke({"content": doc.page_content}) summaries.append(doc_summary)return"\n\n".join(summaries)retriever_question_and_answer_prompt = ChatPromptTemplate.from_template("""Answer based on context:
{context}
Question: {question}""")# Modified chain that summarizes before answeringchain_with_summaries =({"context": vectorstore.as_retriever(search_kwargs={"k":2})| RunnableLambda(summarize_documents),"question":lambda x: x
}| retriever_question_and_answer_prompt
| llm
| StrOutputParser())
Este curso esta muy deprecated! Leemos muchas docs como programadores, pero aun asi seria bueno actualizarlo.
Saludos
Si la pregunta fue en español, por qué la respuesta fue en inglés?
O más sencillo, como puedo hacer que me responda en español?
Podria ser usando un prompt personalizado como en el caso anterior, y que muestre la respuesta en español
basta con que al final de la pregunta le pongas dame la respuesta en español y ya entiende que contestar y lo condicionas a que te conteste en español
Saludos comunidad. Tengo una inquietud para quien me la pueda responder. He cargado un saldo de 10US en OpenAI para irlos consumiendo con las consulas de mi API KEY. En la seccion de uso de mi cuenta figura el siguiente grafico:
Cuando dicen que tengo un credito de 28US y que expira a final de este mes, ¿Que significa?.
¿Tengo que consumir mis 10US, antes de que expiren?
¿Esos 28US son un limite o me los van a cobrar cual si fuese un plan postpago de telefonia?
Yo nisiquiera tengo la cuenta PLUS, solo cargue 10US y genere mi API JEY.
Muy agradecido por las respuesta!
Nueva forma de hacerlo para 9/6/25
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
system_prompt =("Usa el siguiente contexto para responder la pregunta del usuario. ""Si no puedes encontrar la respuesta en el contexto, simplemente di que no lo sabes. ""\n\nContexto: {context}"#El contexto es el texto que se obtendrá del retriever)prompt = ChatPromptTemplate.from_messages([("system", system_prompt),("human","{input}"),])cadena_qa = create_stuff_documents_chain( llm = llm_gpt3_5, prompt = prompt
)cadena_que_resuelve_preguntas = create_retrieval_chain( vectorstore.as_retriever(search_kwargs={"k":2}), cadena_qa
)resultado = cadena_que_resuelve_preguntas.invoke({"input":"¿Cuál es la relevancia de la criptografía de llave pública?"})print(resultado["answer"])
en donde estas viendo todo eso? esta super interesante como uno puede hacer de muchas maneras una misma cosa
El curso deberian quitarlo de la parrilla de cursos hasta que lo actualicen, a ver estoy aprendiendo unicamente corrigiendo los errores de funciones deprecated que usa el instructor.. osea pura documentacion
Este curso está demasiado desactualizado lastimosamente. Muy buen contenido, pero todo el código de los notebooks hay que corregirlos, cambiarlos y pasar demasiado tiempo viendo qué está mal. Ya hace falta que en la ruta de AI Software Engineering haya un curso actualizado de langchain.
Hola, saben si hay forma de hacer esto con CSV? por ejemplo si tengo una columna con textos cortos (Tweets) y quiero que el modelo responda una pregunta para cada tweet de la columna determinada del CSV
Puedes leerlo con Pandas y crearte una vectorstore con los tweets
Imprtante saber que podemos contar con funciones como esta.