Open In Colab GitHub Repository

Использование полнотекстового поиска с LlamaIndex и Milvus

Полнотекстовый поиск использует точное соответствие ключевых слов, часто применяя алгоритмы типа BM25 для ранжирования документов по релевантности. В системах Retrieval-Augmented Generation (RAG) этот метод позволяет извлекать релевантный текст для улучшения ответов, генерируемых ИИ.

В то же время семантический поиск интерпретирует контекстное значение для получения более широких результатов. Сочетание обоих подходов позволяет создать гибридный поиск, который улучшает поиск информации - особенно в тех случаях, когда одного метода недостаточно.

Благодаря подходу Sparse-BM25 в Milvus 2.5 необработанный текст автоматически преобразуется в разреженные векторы. Это устраняет необходимость в ручном создании разреженных вкраплений и позволяет использовать гибридную стратегию поиска, которая позволяет сбалансировать семантическое понимание и релевантность ключевых слов.

В этом руководстве вы узнаете, как использовать LlamaIndex и Milvus для создания системы RAG с использованием полнотекстового и гибридного поиска. Мы начнем с реализации только полнотекстового поиска, а затем расширим его, интегрировав семантический поиск для получения более полных результатов.

Прежде чем приступить к этому уроку, убедитесь, что вы знакомы с полнотекстовым поиском и основами использования Milvus в LlamaIndex.

Необходимые условия

Установите зависимости

Прежде чем приступить к работе, убедитесь, что у вас установлены следующие зависимости:

$ $pip install llama-index-vector-stores-milvus
$ $pip install llama-index-embeddings-openai
$ $pip install llama-index-llms-openai

Если вы используете Google Colab, вам может потребоваться перезапустить среду выполнения (перейдите в меню "Runtime" в верхней части интерфейса и выберите "Restart session" из выпадающего меню).

Настройка учетных записей

В этом учебнике используется OpenAI для встраивания текста и генерации ответов. Вам необходимо подготовить ключ API OpenAI.

import openai

openai.api_key = "sk-"

Чтобы использовать векторное хранилище Milvus, укажите свой сервер Milvus URI (и, по желанию, TOKEN). Запустить сервер Milvus можно, следуя руководству по установке Milvus или просто бесплатно попробовав Zilliz Cloud.

Полнотекстовый поиск в настоящее время поддерживается в Milvus Standalone, Milvus Distributed и Zilliz Cloud, но пока не поддерживается в Milvus Lite (планируется к внедрению в будущем). За дополнительной информацией обращайтесь по адресу support@zilliz.com.

URI = "http://localhost:19530"
# TOKEN = ""

Загрузить примеры данных

Выполните следующие команды, чтобы загрузить примеры документов в каталог "data/paul_graham":

$ mkdir -p 'data/paul_graham/'
$ $wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt' -O 'data/paul_graham/paul_graham_essay.txt'
--2025-03-27 07:49:01--  https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 75042 (73K) [text/plain]
Saving to: ‘data/paul_graham/paul_graham_essay.txt’

data/paul_graham/pa 100%[===================>]  73.28K  --.-KB/s    in 0.07s   

2025-03-27 07:49:01 (1.01 MB/s) - ‘data/paul_graham/paul_graham_essay.txt’ saved [75042/75042]

Интеграция полнотекстового поиска в систему RAG позволяет сбалансировать семантический поиск с точным и предсказуемым поиском по ключевым словам. Вы также можете использовать только полнотекстовый поиск, хотя для получения лучших результатов рекомендуется сочетать полнотекстовый поиск с семантическим. Здесь в целях демонстрации мы покажем только полнотекстовый поиск и гибридный поиск.

Для начала воспользуйтесь сайтом SimpleDirectoryReaderLoad, чтобы загрузить эссе Пола Грэма "Над чем я работал":

from llama_index.core import SimpleDirectoryReader

documents = SimpleDirectoryReader("./data/paul_graham/").load_data()

# Let's take a look at the first document
print("Example document:\n", documents[0])
Example document:
 Doc ID: 16b7942f-bf1a-4197-85e1-f31d51ea25a9
Text: What I Worked On  February 2021  Before college the two main
things I worked on, outside of school, were writing and programming. I
didn't write essays. I wrote what beginning writers were supposed to
write then, and probably still are: short stories. My stories were
awful. They had hardly any plot, just characters with strong feelings,
which I ...

Полнотекстовый поиск с BM25

LlamaIndex's MilvusVectorStore поддерживает полнотекстовый поиск, обеспечивая эффективное извлечение информации на основе ключевых слов. Используя встроенную функцию sparse_embedding_function, он применяет скоринг BM25 для ранжирования результатов поиска.

В этом разделе мы покажем, как реализовать RAG-систему, использующую BM25 для полнотекстового поиска.

from llama_index.core import VectorStoreIndex, StorageContext
from llama_index.vector_stores.milvus import MilvusVectorStore
from llama_index.vector_stores.milvus.utils import BM25BuiltInFunction
from llama_index.core import Settings

# Skip dense embedding model
Settings.embed_model = None

# Build Milvus vector store creating a new collection
vector_store = MilvusVectorStore(
    uri=URI,
    # token=TOKEN,
    enable_dense=False,
    enable_sparse=True,  # Only enable sparse to demo full text search
    sparse_embedding_function=BM25BuiltInFunction(),
    overwrite=True,
)

# Store documents in Milvus
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
Embeddings have been explicitly disabled. Using MockEmbedding.

Приведенный выше код вставляет примеры документов в Milvus и строит индекс, чтобы включить ранжирование BM25 для полнотекстового поиска. Он отключает плотное встраивание и использует BM25BuiltInFunction с параметрами по умолчанию.

Вы можете указать поля ввода и вывода в параметрах BM25BuiltInFunction:

  • input_field_names (str): Входное текстовое поле (по умолчанию: "text"). Оно указывает, к какому текстовому полю применяется алгоритм BM25. Измените это значение, если используете собственную коллекцию с другим именем текстового поля.
  • output_field_names (str): Поле, в котором хранятся выходы данной функции BM25 (по умолчанию: "sparse_embedding").

После того как векторное хранилище настроено, вы можете выполнять полнотекстовые поисковые запросы с помощью Milvus с режимом запроса "sparse" или "text_search":

import textwrap

query_engine = index.as_query_engine(
    vector_store_query_mode="sparse", similarity_top_k=5
)
answer = query_engine.query("What did the author learn at Viaweb?")
print(textwrap.fill(str(answer), 100))
The author learned several important lessons at Viaweb. They learned about the importance of growth
rate as the ultimate test of a startup, the value of building stores for users to understand retail
and software usability, and the significance of being the "entry level" option in a market.
Additionally, they discovered the accidental success of making Viaweb inexpensive, the challenges of
hiring too many people, and the relief felt when the company was acquired by Yahoo.

Настройка анализатора текста

Анализаторы играют важную роль в полнотекстовом поиске, разбивая предложения на лексемы и выполняя лексическую обработку, например, стемминг и удаление стоп-слов. Как правило, они зависят от конкретного языка. Для получения более подробной информации обратитесь к Руководству по анализаторам Milvus.

Milvus поддерживает два типа анализаторов: Встроенные анализаторы и Пользовательские анализаторы. По умолчанию на сайте BM25BuiltInFunction используется стандартный встроенный анализатор, который выполняет токенизацию текста на основе пунктуации.

Чтобы использовать другой анализатор или настроить существующий, вы можете передать значение аргументу analyzer_params:

bm25_function = BM25BuiltInFunction(
    analyzer_params={
        "tokenizer": "standard",
        "filter": [
            "lowercase",  # Built-in filter
            {"type": "length", "max": 40},  # Custom cap size of a single token
            {"type": "stop", "stop_words": ["of", "to"]},  # Custom stopwords
        ],
    },
    enable_match=True,
)

Гибридный поиск с реранкером

Гибридная система поиска сочетает в себе семантический и полнотекстовый поиск, оптимизируя производительность поиска в системе RAG.

В следующем примере используется вставка OpenAI для семантического поиска и BM25 для полнотекстового поиска:

# Create index over the documnts
vector_store = MilvusVectorStore(
    uri=URI,
    # token=TOKEN,
    # enable_dense=True,  # enable_dense defaults to True
    dim=1536,
    enable_sparse=True,
    sparse_embedding_function=BM25BuiltInFunction(),
    overwrite=True,
    # hybrid_ranker="RRFRanker",  # hybrid_ranker defaults to "RRFRanker"
    # hybrid_ranker_params={},  # hybrid_ranker_params defaults to {}
)

storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(
    documents,
    storage_context=storage_context,
    embed_model="default",  # "default" will use OpenAI embedding
)

Как это работает

При этом подходе документы хранятся в коллекции Milvus с обоими векторными полями:

  • embedding: : Плотные вкрапления, сгенерированные моделью вкраплений OpenAI для семантического поиска.
  • sparse_embedding: : разреженными вкраплениями, вычисленными с помощью BM25BuiltInFunction для полнотекстового поиска.

Кроме того, мы применили стратегию ранжирования с помощью "RRFRanker" с параметрами по умолчанию. Чтобы настроить реранкер, вы можете сконфигурировать hybrid_ranker и hybrid_ranker_params, следуя руководству Milvus Reranking Guide.

Теперь давайте протестируем систему RAG на примере запроса:

# Query
query_engine = index.as_query_engine(
    vector_store_query_mode="hybrid", similarity_top_k=5
)
answer = query_engine.query("What did the author learn at Viaweb?")
print(textwrap.fill(str(answer), 100))
The author learned several important lessons at Viaweb. These included the importance of
understanding growth rate as the ultimate test of a startup, the impact of hiring too many people,
the challenges of being at the mercy of investors, and the relief experienced when Yahoo bought the
company. Additionally, the author learned about the significance of user feedback, the value of
building stores for users, and the realization that growth rate is crucial for the long-term success
of a startup.

Этот гибридный подход обеспечивает более точные, учитывающие контекст ответы в системе RAG за счет использования как семантического поиска, так и поиска по ключевым словам.

Попробуйте Managed Milvus бесплатно

Zilliz Cloud работает без проблем, поддерживается Milvus и в 10 раз быстрее.

Начать
Обратная связь

Была ли эта страница полезной?