Оркестровка мультиинструментов с генерацией на основе извлечения (RAG)
Оркестровка мультиинструментов с генерацией на основе извлечения (RAG) — это создание интеллектуальных рабочих процессов, которые используют большие языковые модели (LLM) с инструментами, включая веб-поисковые системы или векторные базы данных, для ответа на запросы. При этом LLM автоматически и динамически выбирает, какой инструмент использовать для каждого запроса. Например, веб-поисковый инструмент откроет область актуальной обновлённой информации, а векторная база данных, такая как Pinecone, — контекстно-специфическую информацию.
На практике RAG часто включает в себя определение инструментов вызова функций, таких как веб-поиск или поиск в базе данных, и организацию их работы через API, например Responses API или OpenAI. Это использование инициирует последовательность шагов извлечения и генерации для каждого пользовательского запроса. В результате аспекты возможностей модели переплетаются с текущей информацией.
Что такое RAG?
RAG — это процесс, при котором языковая модель использует извлечённую релевантную внешнюю информацию и включает её в свои выходные данные. Вместо того чтобы быть «закрытой» моделью, которая полагается исключительно на внутренние обучающие данные, модель RAG выполняет явный шаг извлечения. Она просматривает набор документов, таких как векторная база данных или поисковый индекс, и использует эти извлечённые документы для дополнения запроса к LLM.
Чтобы извлечь знания, на которые LLM опирается для предоставления точных ответов на запросы. Таким образом, мы можем рассматривать этот процесс как генерацию в реальном времени с «расширенными» возможностями. Когда LLM может предоставлять контекстуально релевантные, точные ответы на запросы, используя возможности генерации и дополненную информацию посредством извлечения во время вопроса, это позволяет LLM отвечать на вопросы с использованием точных, актуальных, специфичных для домена или проприетарных знаний, которых у него не было бы на этапе обучения.
Ключевые преимущества RAG:
- Актуальные и специфические знания: RAG позволяет модели получать доступ к новым и нестатическим обучающим данным, например, к текущим новостям, внутренним документам, для ответа на запросы.
- Снижение частоты галлюцинаций: RAG минимизирует галлюцинации, поскольку модель отвечает, основываясь на фактических извлечённых фактах.
- Проверяемость: ответ может содержать ссылки на источники извлечённого контента, что повышает прозрачность и достоверность ответа.
RAG позволяет LLM объединять генеративные способности с извлечением знаний. В методе RAG модель извлекает соответствующие фрагменты информации из внешних корпусов, прежде чем дать ответ, и затем выдаёт более точный и обоснованный ответ, используя этот контекст.
Инструменты, такие как веб-поиск и запросы к векторным индексам, имеют решающее значение для RAG, поскольку они обеспечивают компонент извлечения, которого LLM не предоставляет самостоятельно. Когда эти инструменты добавлены, RAG может устранить проблемы, связанные с использованием только сервисов LLM. Например, LLM имеют ограничения по знаниям и могут уверенно выдавать неверную или устаревшую информацию. Поисковый инструмент позволяет системе автоматически получать актуальные факты по запросу. Аналогично векторная база данных, такая как Pinecone, хранит специфичные для домена и проприетарные данные: записи врачей, политику компании и т. д., которые модель иначе не могла бы знать.
Каждый инструмент имеет свои сильные стороны, и использование комбинации инструментов — это мультиинструментальная оркестровка. Например, общий инструмент веб-поиска может отвечать на общие вопросы. Инструмент, подобный PineconeSearchDocuments, может найти нужные записи во внутреннем векторном хранилище, содержащем знания из проприетарного набора информации. Вместе они гарантируют, что любой ответ модели может быть найден в источнике или в любом другом месте, где он имеет наилучшее качество. Общие вопросы могут быть обработаны с помощью полностью функциональных встроенных инструментов, таких как веб-поиск. «Очень специфические» вопросы или медицинские вопросы, использующие внутренние знания системы, решаются посредством извлечения контекста из векторной базы данных. В целом, использование мультиинструментов в конвейерах RAG обеспечивает повышенную достоверность, корректность данных, а также точность и современный контекст.
Пример создания системы RAG с несколькими инструментами
Теперь мы рассмотрим реальный пример создания системы RAG с несколькими инструментами, используя набор данных медицинских вопросов и ответов. Процесс включает в себя встраивание набора данных вопросов и ответов в Pinecone и настройку системы. Модель имеет инструмент веб-поиска и инструмент поиска на основе Pinecone.
Загрузка зависимостей и наборов данных
Сначала мы установим, затем импортируем необходимые библиотеки и, наконец, загрузим набор данных. Для этого потребуется базовое понимание обработки данных, встраивания и Pinecone SDK.
import os, time, random, string
import pandas as pd
from tqdm.auto import tqdm
from sentence_transformers import SentenceTransformer
from pinecone import Pinecone, ServerlessSpec
import openai
from openai import OpenAI
import kagglehub
Далее мы загрузим и загрузим набор данных медицинских вопросов и ответов. В коде мы использовали утилиту Kagglehub для доступа к набору данных QA, ориентированному на медицину:
path = kagglehub.dataset_download("thedevastator/comprehensive-medical-q-a-dataset")
DATASET_PATH = path # local path to downloaded files
df = pd.read_csv(f"{DATASET_PATH}/train.csv")
Для этого примера мы можем взять подмножество, то есть первые 2500 строк. Затем мы добавим префиксы к столбцам «Вопрос:» и «Ответ:» и объединим их в одну текстовую строку. Это будет контекст, который мы будем встраивать. Мы делаем вложения из текста.
df = df[:2500]
df['Question'] = 'Question: ' + df['Question']
df['Answer'] = ' Answer: ' + df['Answer']
df['merged_text'] = df['Question'] + df['Answer']
Создание индекса Pinecone на основе набора данных
Теперь, когда набор данных загружен, мы создадим векторное вложение для каждой из объединённых строк QA. Мы будем использовать модель преобразования предложений «BAAI/bge-small-en» для кодирования текстов:
MODEL = SentenceTransformer("BAAI/bge-small-en")
embeddings = MODEL.encode(df['merged_text'].tolist(), show_progress_bar=True)
df['embedding'] = list(embeddings)
Далее мы создадим новый индекс Pinecone и укажем размерность. Это делается с помощью клиента Python Pinecone:
def upsert_to_pinecone(df, embed_dim, model, api_key, region="us-east-1", batch_size=32):
# Initialize Pinecone and create the index if it doesn't exist
pinecone = Pinecone(api_key=api_key)
spec = ServerlessSpec(cloud="aws", region=region)
index_name = 'pinecone-index-' + ''.join(random.choices(string.ascii_lowercase + string.digits, k=10))
if index_name not in pinecone.list_indexes().names():
pinecone.create_index(
index_name=index_name,
dimension=embed_dim,
metric='dotproduct',
spec=spec
)
# Connect to index
index = pinecone.Index(index_name)
time.sleep(2)
print("Index stats:", index.describe_index_stats())
# Upsert in batches
for i in tqdm(range(0, len(df), batch_size), desc="Upserting to Pinecone"):
i_end = min(i + batch_size, len(df))
# Prepare input and metadata
lines_batch = df['merged_text'].iloc[i:i_end].tolist()
ids_batch = [str(n) for n in range(i, i_end)]
embeds = model.encode(lines_batch, show_progress_bar=False, convert_to_numpy=True)
meta = [
{
"Question": record.get("Question", ""),
"Answer": record.get("Response", "")
}
for record in df.iloc[i:i_end].to_dict("records")
]
# Upsert to index
vectors = list(zip(ids_batch, embeds, meta))
index.upsert(vectors=vectors)
print(f"Upsert complete. Index name: {index_name}")
return index_name
Это то, что загружает наши данные в Pinecone; в терминологии RAG это эквивалентно загрузке внешних авторитетных знаний в векторное хранилище. Как только индекс будет создан, мы будем вставлять все вложения по частям вместе с метаданными, исходным текстом вопроса и ответа для поиска:
index_name = upsert_to_pinecone(
df=df,
embed_dim=384,
model=MODEL,
api_key="your-pinecone-api-key"
)
Здесь каждый вектор сохраняется со своим текстом и метаданными. Индекс Pinecone теперь заполнен нашим набором данных, специфичным для домена.
Запрос индекса Pinecone
Чтобы использовать индекс, мы определяем функцию, которую можно вызвать в индексе с новым вопросом. Функция встраивает текст запроса и вызывает index.query, чтобы вернуть наиболее похожие документы:
def query_pinecone_index(index, model, query_text):
query_embedding = model.encode(query_text, convert_to_numpy=True).tolist()
res = index.query(vector=query_embedding, top_k=5, include_metadata=True)
print("--- Query Results ---")
for match in res['matches']:
question = match['metadata'].get("Question", 'N/A')
answer = match['metadata'].get("Answer", "N/A")
print(f"{match['score']:.2f}: {question} - {answer}")
return res
Например, если мы вызовем query_pinecone_index(index, MODEL, "What is the most common treatment for diabetes?"), мы увидим напечатанные сверху соответствующие пары вопросов и ответов из нашего набора данных. Это часть процесса извлечения: пользовательский запрос получает встраивание, просматривает индекс и возвращает наиболее близкие документы (а также их метаданные). Как только мы получим эти контексты, мы сможем использовать их для формулирования окончательного ответа.
Далее мы определяем инструменты, которые может использовать модель. В этом конвейере мы определяем два инструмента. Предварительный просмотр веб-поиска — это общий веб-поиск фактов из открытого интернета. PineconeSearchDocuments используется для выполнения семантического поиска по нашему индексу Pinecone. Каждый инструмент определяется как объект JSON, который содержит имя, описание и ожидаемые параметры.
Инструмент даёт агенту возможность выполнить веб-поиск, просто введя запрос на естественном языке. Есть необязательные метаданные о местоположении, которые могут повысить специфику релевантности пользователя (например, новости, услуги, специфичные для региона).
web_search_tool = {
"type": "function",
"name": "web_search_preview",
"function": {
"name": "web_search_preview",
"description": "Perform a web search for general queries.",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The search query string"
},
"user_location": {
"type": "object",
"properties": {
"country": {"type": "string", "default": "IN"},
"region": {"type": "string", "default": "Delhi"},
"city": {"type": "string", "default": "New Delhi"}
}}},
"required": ["query"]
}
}
}
Этот инструмент позволяет агенту проводить семантический поиск в векторной базе данных, такой как Pinecone, позволяя системам RAG полагаться на семантику точечного произведения и угла между векторами.
Инструмент принимает запрос и возвращает документы, которые являются наиболее похожими, на основе векторных вложений.
pinecone_tool = {
"type": "function",
"name": "PineconeSearchDocuments",
"function": {
"name": "PineconeSearchDocuments",
"description": "Search for relevant documents based on the user’s question in the vector database.",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The question to search in the vector database."
},
"top_k": {
"type": "integer",
"description": "Number of top results to return.",
"default": 3
}
},
"required": ["query"],
"additionalProperties": False
}
}
}
Это используется, когда агенту необходимо извлечь контекст специфичности из документов, содержащих встроенные контексты.
Теперь мы объединяем оба инструмента в один список, который будет передан агенту.
tools = [web_search_tool, pinecone_tool]
Каждый инструмент включает в себя определение аргументов, которые наша модель должна передать ему при вызове. Например, инструмент поиска в Pinecone ожидает строку запроса на естественном языке, и этот инструмент вернёт верхние K соответствующих документов из нашего индекса.
Вместе с инструментом мы включим набор пользовательских запросов для обработки. Для каждого запроса модель определит, будет ли она вызывать инструмент или отвечать напрямую.
queries = [
{"query": "Who won the cricket world cup in 1983?"},
{"query": "What is the most common cause of death in India?"},
{"query": "A 7-year-old boy with sickle cell disease has knee and hip pain... What is the next step in management according to our internal knowledge base?"}
]
Наконец, мы выполняем поток разговора, в котором модель управляет инструментами от своего имени. Мы предоставляем модели системное приглашение, которое направляет её использовать инструменты в определённом порядке. В этом примере наше приглашение говорит модели: «Каждый раз, когда ей задают вопрос, сначала вызвать инструмент веб-поиска для получения результатов, а затем вызвать PineconeSearchDocuments, чтобы найти соответствующие примеры во внутренней базе знаний».
system_prompt = (
"Every time it's prompted with a question, first call the web search tool for results, "
"then call `PineconeSearchDocuments` to find relevant examples in the internal knowledge base."
)
Мы собираем сообщения и вызываем Responses API с включёнными инструментами для каждого запроса пользователя:
for item in queries:
input_messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": item["query"]}
]
response = openai.responses.create(
model="gpt-4o-mini",
input=input_messages,
tools=tools,
parallel_tool_calls=True
)
Вывод
API возвращает сообщение помощника, которое может включать или не включать вызовы инструментов. Мы проверяем response.output, чтобы увидеть, вызывала ли модель какие-либо инструменты, и если да, мы выполняем эти вызовы и включаем результаты в разговор. Наконец, мы отправляем обновлённый разговор обратно в модель, чтобы получить окончательный ответ.
Вышеописанный поток показывает, как работает мультиинструментальная оркестровка; модель динамически выбирает инструменты для запроса. В примере для общих вопросов, таких как «Что такое астма?», может использоваться инструмент веб-поиска, но для вопросов, связанных с более конкретными ссылками на «астму», может потребоваться контекст Pinecone, на котором будет строиться ответ.
Мы выполняем несколько вызовов инструментов из нашего цикла кода, и после того, как все они будут выполнены, мы вызываем API, чтобы модель могла построить «окончательный» ответ на основе полученных ею подсказок. В целом мы ожидаем получить ответ, который объединит внешние истины из веб-знаний и учтёт контекст из внутренних документов, на основе наших инструкций.
Заключение
Мультиинструментальная оркестровка с RAG создаёт мощную систему вопросов и ответов с множеством опций. Использование генерации модели с инструментами извлечения позволяет нам воспользоваться как пониманием естественного языка модели, так и фактической точностью внешних наборов данных. В нашем случае мы использовали индекс медицинских вопросов и ответов в Pinecone, в котором у нас была возможность вызвать либо веб-поиск, либо этот индекс в качестве опций. Таким образом, наша модель была более обоснована фактическими данными и могла отвечать на вопросы, на которые она не смогла бы ответить иначе.
На практике этот тип конвейера RAG обеспечивает более высокую точность и релевантность ответов, поскольку модель может ссылаться на актуальные источники, охватывать нишевые знания и минимизировать галлюцинации. Будущие итерации могут включать более сложные схемы извлечения или дополнительные инструменты в экосистеме, такие как работа с графами знаний или API, но ядро системы не изменится.
Часто задаваемые вопросы
Q1. В чём будут заключаться основные преимущества RAG по сравнению с традиционными LLM?
A. RAG позволяет LLM получать доступ к внешнему источнику данных, такому как векторные базы данных или веб, для генерации более точных, актуальных и специфичных для домена ответов, чего не могут сделать традиционные «закрытые» модели.
Q2. Какие инструменты чаще всего используются в конвейере RAG?
A. Обычно используются векторные базы данных, такие как Pinecone, FAISS или Weaviate, для семантического извлечения. Веб-поиск с использованием API для получения актуальной информации из интернета. Пользовательские API или функции, которые обеспечивают возможности запросов к графам знаний, SQL-базам данных или хранилищам документов.
Q3. Можно ли использовать RAG в приложениях реального времени, таких как чат-боты?
A. Да. RAG хорошо подходит для приложений, требующих динамичных, фактических ответов, таких как боты поддержки клиентов, медицинские или финансовые помощники. Поскольку ответы основаны на извлекаемых документах или фактах.
