Векторные хранилища и ретриверы
В этом разделе вы узнаете, как использовать GigaChain для работы с векторными хранилищам и ретриверами. Ретриверы и векторные хранилища важны для приложений, которые извлекают данные для рассуждений в рамках инференса модели, например, в случае генерации с дополнением извлечения данных или RAG.
Основные понятия
В этом разделе основное внимание уделяется извлечению текстовых данных. Основные понятия:
- документы;
- векторные хранилища;
- ретриверы.
Подготовка к разработке
Jupyter-блокноты
Как и большинство других руководств в документации, этот раздел использует Jupyter-блокнот. Блокноты отлично подходят для изучения работы с LLM-системами, так как предоставляют интерактивную среду для работы с руководствами и позволяют работать с непредвиденными ситуациями, например недоступностью API или нетипичным выводом.
Подробнее об установке Jupyter — в официальной документации.
Установка
Установите пакеты, которые понадобятся для работы с примерами:
pip install langchain-gigachat langchain-chroma
Подробнее об установке GigaChain — в разделе Установка.
Документы
GigaChain реализует класс Document, который представляет единицу текста и связанные с ним метаданные. У этого класса есть два атрибута:
page_content
— строка, представляющая содержимое;metadata
— словарь, содержащий произвольные метаданные.
Атрибут metadata
может содержать данные об источнике документа, его связи с другими документами и другую дополнительную информацию.
Отдельный объект Document
часто представляет фрагмент более крупного документа.
Создайте несколько образцов документов:
from langchain_core.documents import Document
documents = [
Document(
page_content="Собаки — отличные компаньоны, которые известны своей преданностью и дружелюбием.",
metadata={"source": "mammal-pets-doc"},
),
Document(
page_content="Кошки — независимые животные, которым нужно собственное пространство.",
metadata={"source": "mammal-pets-doc"},
),
Document(
page_content="Золотые рыбки — отличные домашние животные для начинающих. За ними достаточно просто ухаживать.",
metadata={"source": "fish-pets-doc"},
),
Document(
page_content="Попугаи — умные птицы, которые способны имитировать человеческую речь.",
metadata={"source": "bird-pets-doc"},
),
Document(
page_content="Кролики — социальные животные, которым нужно много места, чтобы прыгать.",
metadata={"source": "mammal-pets-doc"},
),
]
В примере выше представлено пять документов с дополнительными данными, которые указывают на три различных источника (source
).
Векторные хранилища
Векторный поиск — это распространенный способ поиска по сохраненным неструктурированным данным, например, неструктурированному тексту. В основе поиска лежит работа с сохраненными числовыми векторами, которые ассоциированы с текстом. При запросе к хранилищу, вы можете представить текст запроса в виде вектора той же размерности и использовать метрики векторной схожести для поиска подходящих данных в хранилище.
Объекты VectorStore
предоставляют методы для добавления текста и объектов Document
в хранилище, а так же методы для поиска документов в хранилище с использованием различных метрик схожести.
Как правило, хранилища инициализируются с использованием моделей, которые поддерживают векторное представление текста.
Такие модели определяют, как текстовые данные переводятся в числовые векторы.
GigaChain предоставляет набор интеграций с различными векторными хранилищами. Некоторые из них могут требовать соответствующие учетные данные для использования. Другие, такие как Postgres, работают в отдельной инфраструктуре, которую можно запускать локально или через сторонние сервисы. Какие-то могут работать в памяти и используются для легких нагрузок.
В этом разделе показана работа объектов VectorStore
с использованием Chroma — векторным хранилищем, которое поддерживает работу в памяти.
Как правило, для создания векторного хранилища нужно предоставить модель, которая будет отвечать за векторное представление текста.
Примере для создания векторного представления текста используется модель GigaChat Embeddings.
from langchain_chroma import Chroma
from langchain_gigachat.embeddings.gigachat import GigaChatEmbeddings
vectorstore = Chroma.from_documents(
documents,
embedding=GigaChatEmbeddings(
credentials="ключ_авторизации",
scope="GIGACHAT_API_PERS",
verify_ssl_certs=False,
),
)
Авторизационные данные — строка, полученная в результате кодирования в Base64 клиентского идентификатора (Client ID) и ключа (Client Secret) API. Вы можете использовать готовые данные из личного кабинета или самостоятельно закодировать идентификатор и ключ.
Пример строки авторизационных данных:
MjIzODA0YTktMDU3OC00MTZmLWI4MWYtYzUwNjg3Njk4MzMzOjljMTI2MGQyLTFkNTEtNGRkOS05ZGVhLTBhNjAzZTdjZjQ3Mw==
Идентификатор, ключ и авторизационные данные вы можете получить после создания проекта GigaChat API:
Вызов метода .from_documents
добавляет документы в векторное хранилище.
Объект VectorStore
предоставляет методы для добавления документов, которые также можно вызвать после создания объекта.
Большинство интеграций позволяет подключаться к существующему векторному хранилищу, например, предоставив клиент, название индекса или другую информацию.
После создания объекта VectorStore
с необходимыми документами, вы можете выполнять поиск по ним.
Объект VectorStore включает методы для выполнения запросов:
- синхронно и асинхронно;
- по текстовому запросу и по его вектору;
- с возвращением и без возвращения оценок схожести;
- по схожести и максимальной маржинальной релевантности, которая позволяет сбалансировать схожесть с разнообразием в извлеченных результатах.
В общем случае результат работы методов будет содержать объектов Document.
Примеры
Возврат документов на основе схожести с текстовым запросом:
vectorstore.similarity_search("кошка")
[Document(metadata={'source': 'mammal-pets-doc'}, page_content='Кошки — независимые животные, которым нужно собственное пространство.'),
Document(metadata={'source': 'mammal-pets-doc'}, page_content='Собаки — отличные компаньоны, которые известны своей преданностью и дружелюбием.'),
Document(metadata={'source': 'mammal-pets-doc'}, page_content='Кролики — социальные животные, которым нужно много места, чтобы прыгать.'),
Document(metadata={'source': 'bird-pets-doc'}, page_content='Попугаи — умные птицы, которые способны имитировать человеческую речь.')]
Асинхронный запрос:
await vectorstore.asimilarity_search("кошка")
[Document(metadata={'source': 'mammal-pets-doc'}, page_content='Кошки — независимые животные, которым нужно собственное пространство.'),
Document(metadata={'source': 'mammal-pets-doc'}, page_content='Собаки — отличные компаньоны, которые известны своей преданностью и дружелюбием.'),
Document(metadata={'source': 'mammal-pets-doc'}, page_content='Кролики — социальные животные, которым нужно много места, чтобы прыгать.'),
Document(metadata={'source': 'bird-pets-doc'}, page_content='Попугаи — умные птицы, которые способны имитировать человеческую речь.')]
Оценка схожести запроса и содержимого хранилища:
# Оценка зависит от выбранного векторного хранилища.
# Chroma возвращает метрику расстояния, которая должна варьироваться обратно пропорционально схожести.
vectorstore.similarity_search_with_score("кошка")
[(Document(metadata={'source': 'mammal-pets-doc'}, page_content='Кошки — независимые животные, которым нужно собственное пространство.'),
218.2356719970703),
(Document(metadata={'source': 'mammal-pets-doc'}, page_content='Собаки — отличные компаньоны, которые известны своей преданностью и дружелюбием.'),
319.75384521484375),
(Document(metadata={'source': 'mammal-pets-doc'}, page_content='Кролики — социальные животные, которым нужно много места, чтобы прыгать.'),
349.84930419921875),
(Document(metadata={'source': 'bird-pets-doc'}, page_content='Попугаи — умные птицы, которые способны имитировать человеческую речь.'),
352.6993103027344)]
Возврат документов на основе схожести с запросом, представленным в виде вектора:
embedding = GigaChatEmbeddings(
credentials="ключ_авторизации",
scope="GIGACHAT_API_PERS",
verify_ssl_certs=False,
).embed_query("кошка")
vectorstore.similarity_search_by_vector(embedding)
[Document(metadata={'source': 'mammal-pets-doc'}, page_content='Кошки — независимые животные, которым нужно собственное пространство.'),
Document(metadata={'source': 'mammal-pets-doc'}, page_content='Собаки — отличные компаньоны, которые известны своей преданностью и дружелюбием.'),
Document(metadata={'source': 'mammal-pets-doc'}, page_content='Кролики — социальные животные, которым нужно много места, чтобы прыгать.'),
Document(metadata={'source': 'bird-pets-doc'}, page_content='Попугаи — умные птицы, которые способны имитировать человеческую речь.')]
Больше информации о векторных хранилищах:
Ретриверы
Объекты VectorStore
не являются Runnable-объектами и поэтому их нельзя использовать в LCEL-цепочках напрямую.
В то же время ретриверы GigaChain (Retrievers
) — являются экземплярами Runnable, поэтому они реализуют стандартный набор методов (например, синхронные и асинхронные операции invoke
и batch
) и предназначены для включения в цепочки LCEL.
Вы можете самостоятельно создать ретривер, не прибегая к классу Retriever
.
Для этого нужно выбрать метод, который будет использоваться для извлечения документов, и создать Runnable.
Пример ниже показывает, как создать ретривер, который использует метод similarity_search
, на основе Runnable:
from typing import List
from langchain_core.documents import Document
from langchain_core.runnables import RunnableLambda
retriever = RunnableLambda(vectorstore.similarity_search).bind(
k=1
) # выбор наиболе подходящего результата
retriever.batch(["кошка", "акула"])
[[Document(metadata={'source': 'mammal-pets-doc'}, page_content='Кошки — независимые животные, которым нужно собственное пространство.')],
[Document(metadata={'source': 'mammal-pets-doc'}, page_content='Собаки — отличные компаньоны, которые известны своей преданностью и дружелюбием.')]]
Векторные хранилища предоставляют метод as_retriever
, который создаст экземпляр класса Retriever, а именно VectorStoreRetriever.
Эти ретриверы включают заданные атрибуты search_type
и search_kwargs
, которые определяют, какие методы базового векторного хранилища вызывать и как задавать их параметры.
Так, вы можете повторить функциональность из примера выше с помощью следующего кода:
retriever = vectorstore.as_retriever(
search_type="similarity",
search_kwargs={"k": 1},
)
retriever.batch(["кошка", "акула"])
[[Document(metadata={'source': 'mammal-pets-doc'}, page_content='Кошки — независимые животные, которым нужно собственное пространство.')],
[Document(metadata={'source': 'mammal-pets-doc'}, page_content='Собаки — отличные компаньоны, которые известны своей преданностью и дружелюбием.')]]
VectorStoreRetriever
поддерживает типы поиска "similarity"
(по умолчанию), "mmr"
(maximum marginal relevance, описано выше) и "similarity_score_threshold"
.
Последний тип можно использовать для отсечки документов, выводимых ретривером, на основе оценки схожести.
Ретриверы можно легко включить в более сложные RAG-приложения, которые объединяют заданный вопрос с извлеченным контекстом в промпт для модели.
# | output: false
# | echo: false
from langchain_gigachat.chat_models import GigaChat
model = GigaChat(
credentials="ключ_авторизации",
scope="GIGACHAT_API_PERS",
model="GigaChat-Pro",
verify_ssl_certs=False,
)
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
message = """
Отвечай на вопросы только с помощью полученного контекста.
{question}
Контекст:
{context}
"""
prompt = ChatPromptTemplate.from_messages([("human", message)])
rag_chain = {"context": retriever, "question": RunnablePassthrough()} | prompt | model
response = rag_chain.invoke("Расскажи о кошках")
print(response.content)
Кошки – это независимые животные, которым требуется свое собственное пространство.