1. Retriever (Извлекатель)
Retriever (Извлекатель) - это интерфейс, инкапсулированный LangChain, который может возвращать соответствующие документы на основе неструктурированных запросов. Цель дизайна извлекателя - облегчить запрос локальных данных. В качестве базовой реализации извлекателя может использоваться векторное хранилище, и LangChain поддерживает несколько базовых реализаций интерфейса извлекателя.
2. Начало работы с извлекателем (Retriever)
2.1. Установка
Для демонстрации того, как получить извлекатель, мы воспользуемся базой данных векторов Qdrant в качестве примера.
%pip install --upgrade --quiet qdrant-client
2.2. Получение ключа API OpenAI
Прежде чем использовать OpenAIEmbeddings
, нам необходимо получить ключ API OpenAI.
import getpass
import os
os.environ["OPENAI_API_KEY"] = getpass.getpass("Ключ API OpenAI:")
2.3. Импорт данных документа и получение клиента Qdrant
Следующий код демонстрирует, как импортировать данные документа и получить клиент Qdrant для создания извлекателя:
from langchain_community.document_loaders import TextLoader
from langchain_community.vectorstores import Qdrant
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import CharacterTextSplitter
loader = TextLoader("../../modules/state_of_the_union.txt")
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
docs = text_splitter.split_documents(documents)
embeddings = OpenAIEmbeddings()
qdrant = Qdrant.from_documents(
docs,
embeddings,
path="/tmp/local_qdrant",
collection_name="my_documents",
)
2.4. Получение извлекателя
Следующий код демонстрирует, как получить извлекатель из Qdrant:
retriever = qdrant.as_retriever()
retriever
Вы можете запросить документы, связанные с вопросом, так:
docs = retriever.get_relevant_documents("что он сказал о Кетанджи Браун Джексон")
Вы также можете установить порог сходства для извлекателя:
retriever = db.as_retriever(
search_type="similarity_score_threshold", search_kwargs={"score_threshold": 0.5}
)
Кроме того, вы можете установить количество возвращаемых наиболее похожих записей, например, чтобы вернуть 2 наиболее похожие записи:
retriever = db.as_retriever(search_kwargs={"k": 2})
2.5. Использование извлекателя в LCEL
Поскольку извлекатели являются объектами Runnable
(запускаемыми), мы легко можем объединить их с другими объектами Runnable
для оркестрации рабочих процессов:
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
template = """Отвечайте на вопросы только на основе следующего контекста:
{context}
Вопрос: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
model = ChatOpenAI()
def format_docs(docs):
return "\n\n".join([d.page_content for d in docs])
chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| model
| StrOutputParser()
)
chain.invoke("Что президент сказал о технологиях?")
Объяснение процесса:
- Шаг 1: Цель - сгенерировать словарь, содержащий два свойства:
context
иquestion
, для подготовки параметров шаблона запроса. Параметрcontext
генерируется извлекателем на основе параметра, переданного методуinvoke
, который равен "Что президент сказал о технологиях?". Это извлекает документы, похожие на вопрос, затем форматирует массив документов, используя функциюformat_docs
и присваивает его свойствуcontext
. ФункцияRunnablePassthrough
копирует параметр (вопрос пользователя) цепочки в свойствоquestion
. - Шаг 2: Передать словарь, сгенерированный на первом шаге, в шаблон запроса для форматирования.
- Шаг 3: Передать отформатированный запрос из шаблона в модель.
- Шаг 4: Передать результат вызова модели в парсер вывода
StrOutputParser
.
3. Пользовательский извлекатель (Custom Retriever)
4.1. Введение в интерфейс извлекателя (Retriever Interface)
Интерфейс извлекателя очень прост, и мы легко можем написать пользовательские извлекатели.
4.2. Пример настраиваемого ретриевера
Вот пример настраиваемого ретриевера, демонстрирующий, как написать настраиваемый ретриевер и использовать его для извлечения соответствующих документов:
from langchain_core.retrievers import BaseRetriever
from langchain_core.callbacks import CallbackManagerForRetrieverRun
from langchain_core.documents import Document
from typing import List
class CustomRetriever(BaseRetriever):
def _get_relevant_documents(
self, query: str, *, run_manager: CallbackManagerForRetrieverRun
) -> List[Document]:
return [Document(page_content=query]
retriever = CustomRetriever()
retriever.get_relevant_documents("bar")
Изучив вышеуказанные разделы, вы приобретете более глубокое понимание концепции, методов извлечения и настройки ретриеверов.