Главная / Статьи / Практические заметки: как Qdrant сократил расходы на токены RAG на 67% благодаря встроенному ColBERT

Практические заметки: как Qdrant сократил расходы на токены RAG на 67% благодаря встроенному ColBERT

Пошаговое руководство по практическим рекомендациям: как Qdrant сократил затраты на токены RAG на 67% с использованием ColBERT встроенно: контракты, проверки и готовые блоки кода для команд, внедряющих эту модель.

1929 слов

В следующих примечаниях описывается практический подход к теме «Как Qdrant сократил затраты на токены RAG на 67% с использованием встроенной функции переранжирования ColBERT». Акцент сделан на контрактах, проверках и местах для вставки кода, а не на мотивирующем описании. На этапе обзора сначала запишите контракт: необходимые входные данные, сигнал успешного выполнения и действия при частичной неудаче. Такой чек-лист поможет сохранять честность при последующих изменениях кода. Документируйте как успешный, так и восстановительный пути работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки.

Страница, которая нам не нужна

Модель The Page We Don работает наилучшим образом, когда рассматривается как измеримая структура. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое какого-либо шага причина должна быть связана с конкретной функцией, а не с запутанной цепочкой операций. Установите лимиты на количество токенов за ход и за сессию. Инструменты агентного типа активно расширяют объем контекста; жесткие ограничения предотвращают появление неожиданных счетов.

Почему Qdrant лучше всего остальных?

Этап «Почему Qdrant лучше всего» работает наилучшим образом, если рассматривать его как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Дайте названия всем элементам, определите критерии успеха и не соглашайтесь на молчаливое частичное выполнение задач. Установите лимит токенов на каждый ход и на каждую сессию. Инструменты агентов активно расширяют контекст; строгие ограничения предотвращают появление неожиданных счетов во время демонстраций.

Что мы на самом деле создаём

Этап «Что мы на самом деле делаем» работает лучше всего, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Записывайте временные показатели, а также стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные счета при переходе от демо-версии к общедоступным средам. Установите лимиты на количество токенов за один ход и за сессию. Инструменты агентов активно расширяют контекст; жесткие ограничения не позволяют демо-версиям превращаться в неожиданные счета. Этап «Что мы на самом деле делаем» работает лучше всего, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Документируйте одновременно успешный путь выполнения и путь восстановления. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не элементами последующей доработки.

Краткое резюме показателей стоимости и производительности

На этапе подготовки краткого обзора показателей эффективности затрат необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг, исходя из известной точки контроля, без необходимости угадывать скрытое состояние. Лучше использовать небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага причина должна быть связана с конкретной функцией, а не с запутанной структурой обработки данных. При следующем шаге, представляющем собой код или вызов инструмента, целесообразно использовать структурированные выходные данные с проверкой соответствия шаблону вместо свободного текста.

Настройка схемы сбора данных

На этапе настройки коллекции необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия элементам, определите критерии успеха и не допускайте молчаливого частичного завершения работы. При следующем шаге, представляющем собой код или вызов инструмента, отдавайте предпочтение структурированным выходным данным с проверкой по шаблону перед текстовыми описаниями в свободной форме.

from qdrant_client import QdrantClient, models
# ADDED: Load FastEmbed models locally on CPU
from fastembed import TextEmbedding, LateInteractionTextEmbedding
COLLECTION_NAME = "legal_discovery"
DENSE_DIM = 384  # BAAI/bge-small-en-v1.5
COLBERT_DIM = 128  # colbert-ir/colbertv2.0
# ADDED: Instantiate the vector models
dense_model = TextEmbedding("BAAI/bge-small-en-v1.5")
colbert_model = LateInteractionTextEmbedding("colbert-ir/colbertv2.0")
client = QdrantClient("<http://localhost:6333>")
client.create_collection(
    collection_name=COLLECTION_NAME,
    vectors_config={
        "dense": models.VectorParams(
            size=DENSE_DIM,
            distance=models.Distance.COSINE,
            quantization_config=models.BinaryQuantization(
                binary=models.BinaryQuantizationConfig(always_ram=True),
            ),
        ),
        "colbert": models.VectorParams(
            size=COLBERT_DIM,
            distance=models.Distance.COSINE,
            multivector_config=models.MultiVectorConfig(
                comparator=models.MultiVectorComparator.MAX_SIM
            ),
            on_disk=True,
            hnsw_config=models.HnswConfigDiff(m=0),
        ),
    },
)

Единый конвейер запросов

Для этапа «Единый конвейер запросов» необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Регистрируйте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Отображение стоимости заранее помогает избежать неожиданных счетов при переходе от демо-среды к общедоступным средам. При следующем шаге, представляющем собой код или вызов инструмента, предпочтение следует отдавать структурированным выводам с проверкой схемы вместо свободного текста. Для этапа «Единый конвейер запросов» необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо одновременно задокументировать успешный сценарий работы и сценарий восстановления. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не элементами последующей доработки.

# ADDED: Generate query embeddings (ColBERT uses query_embed to add prefix padding)
dense_query = next(dense_model.query_embed(query)).tolist()
colbert_query = next(colbert_model.query_embed(query)).tolist()
# Run the two-stage query in one network round-trip
results = client.query_points(
    collection_name=COLLECTION_NAME,
    prefetch=models.Prefetch(
        query=dense_query,
        using="dense",
        limit=prefetch_limit,
        params=models.SearchParams(
            quantization=models.QuantizationSearchParams(rescore=False),
        ),
    ),
    query=colbert_query,
    using="colbert",
    limit=top_k,
    with_payload=True,
)

Переход от фрагмента к предложению

При работе над этапом перехода от фрагмента к предложению сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает избегать ошибок при последующих изменениях кода. Лучше использовать небольшие, тестируемые единицы кода, чем обширные скрипты. При сбое на каком-либо этапе причина должна быть связана с конкретной функцией, а не с запутанной структурой обработки. Храните в кэше стабильные инструкции системы и схемы инструментов. Повторная отправка одинаковых данных — распространённая причина ресурсозатрат.

import re
import numpy as np
# ADDED: Basic sentence splitter regex
SENTENCE_SPLIT = re.compile(r"(?<=[.;])\s+(?=[A-Z])")
def max_sim(query_vecs: np.ndarray, doc_vecs: np.ndarray) -> float:
    # Compute token-to-token similarity matrix
    sims = query_vecs @ doc_vecs.T  # (num_query_tokens, num_doc_tokens)
    # Sum the maximum similarity scores along the document axis
    return float(sims.max(axis=1).sum())
def isolate_sentences(chunk_text: str, query_vecs: np.ndarray, colbert_model, top_n: int = 1):
    # ADDED: Split chunk text into candidate sentences
    sentences = [s.strip() for s in SENTENCE_SPLIT.split(chunk_text) if len(s.strip()) > 15]
    if not sentences:
        return [(chunk_text, 0.0)]
    # Embed each sentence locally using ColBERT
    sentence_vecs = list(colbert_model.embed(sentences))
    scored = [(sentences[i], max_sim(query_vecs, sentence_vecs[i])) for i in range(len(sentences))]
    scored.sort(key=lambda pair: pair[1], reverse=True)
    return scored[:top_n]
def build_optimized_prompt(query: str, chunk_texts: list[str], colbert_model) -> str:
    query_vecs = next(colbert_model.query_embed(query))
    context_parts = []
for i, text in enumerate(chunk_texts):
        top_sentences = isolate_sentences(text, query_vecs, colbert_model, top_n=1)
        isolated_text = " ".join(s for s, _ in top_sentences)
        context_parts.append(f"[Source Chunk {i+1}]: {isolated_text}")
    context_str = "\n\n".join(context_parts)
    return f"Context:\n{context_str}\n\nQuestion: {query}\nAnswer:"

Золотое правило размера фрагментов: почему границы фрагментов важны для точности

При работе над этапом «Золотое правило» сначала запишите контракт: необходимые входные данные, сигнал успешного выполнения и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия создаваемым элементам, определите критерии успешности и не допускайте молчаливого частичного выполнения задачи. Храните в кэше стабильные системные инструкции и схемы инструментов. Пересылка одинаковых данных является распространенной причиной избыточных ресурсов.

Компромисс говорит сам за себя

При работе над этапом «The Tradeoff Speaks for» сначала запишите условия взаимодействия: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Записывайте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Очевидность затрат с самого начала предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды. Храните в кэше стабильные инструкции системы и схемы инструментов. Повторная отправка одинаковых данных — распространённая причина избыточных затрат. При работе над этапом «The Tradeoff Speaks for» сначала запишите условия взаимодействия: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Документируйте одновременно успешный сценарий работы и сценарий восстановления. Повторные попытки, проверки со стороны людей и обработка некорректных сообщений являются частью продукта, а не элементами последующей доработки.

Каков финансовый эффект?

Модель «Что такое финансовый этап» работает наилучшим образом, когда рассматривается как измеримая структура. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое какого-либо шага причина должна быть связана с конкретной ответственностью, а не с запутанной цепочкой операций. Установите лимиты на количество операций за раз и за сессию. Инструменты агентов активно расширяют объем обрабатываемой информации; жесткие ограничения предотвращают появление неожиданных счетов.

Выводы по дизайну для производственной среды

Принципы дизайна на этапе производства работают наилучшим образом, если рассматривать их как измеримые показатели. Соберите один эталонный пример успешного результата, один пример сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Дайте названия всем элементам, определите критерии успеха и не соглашайтесь на молчаливое частичное выполнение задач. Установите лимиты на количество операций за раз и за сессию. Инструменты с автономным управлением активно расширяют объем обрабатываемой информации; жесткие ограничения предотвращают появление неожиданных счетов.

GitHub

Сцена GitHub работает наилучшим образом, когда рассматривается как измеримая среда. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Записывайте временные показатели, а также стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные счета при переходе от демо-версии к общедоступным средам. Установите лимиты на количество токенов за одну попытку и за сессию. Инструменты типа агентов активно расширяют объем данных; жесткие ограничения не позволяют демо-версиям превращаться в неожиданные счета. Сцена GitHub работает наилучшим образом, когда рассматривается как измеримая среда. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Документируйте одновременно успешный и восстановительный пути работы. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не элементами последующей доработки.

Ссылки

На этапе разработки ссылок необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Лучше использовать небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага причина должна быть связана с конкретной функцией, а не с запутанной структурой обработки. При следующем шаге, представляющем собой код или вызов инструмента, лучше использовать структурированные выходные данные с проверкой соответствия шаблону вместо свободного текста.

Чек-лист операций

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

Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код.

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

Оценивайте уровень воспроизводимости на фиксированном наборе вопросов перед настройкой подсказок. Изменение подсказок редко помогает улучшить слабую систему поиска информации.

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

Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия элементам, определите критерии успеха и откажитесь от молчаливого частичного выполнения задачи.

Перед внедрением стека заморозьте версии, сделайте копию «золотого» транскрипта для критической цепочки операций и уточните шаги возврата к предыдущему состоянию. В совместных средах необходимы ограничения по частоте запросов, проверки принадлежности пользователя и четко определенный ответственный за обновление секретов. Лучше выбирать надежность, чем креативные одноразовые демонстрации.

Примечание для версии 98b4b4d4d553: не храните ключи поставщика в репозитории, установите лимит токенов на сессию и сохраняйте транскрипты рядом с фиксами для оценки, чтобы последующие замены моделей оставались сопоставимыми.