Запуск приложения
- Запустить Milvus:
В файле
cd milvus-docker && docker-compose up -d
docker-compose.ymlвставить авторизационные данные для Gigachat в переменную окруженияGIGACHATприложенияsearch - Запустить приложение
Дополнительно: Запуск с использованием GPU (требуется nvidia container toolkit)
cd .. && docker-compose up -d --build
docker-compose -f docker-compose.yml -f docker-compose.gpu.yml up -d --build
- Проверить запущенные контейнеры можно с помощью команды:
docker-compose ps
- Выполнить скрипт
create_collection.py- создание коллекции - Выполнить скрипт
text_processing.py- заполнение коллекции данными изdataset.json - Выполнить скрипт
test_search.py- получение ответов от приложения search
Пример обращения к сервису, векторизующему текст:
import requests
response = requests.post("http://localhost:8908/embedding", json={"query": "запрос"}).json()Пример обращения к поисковому приложению:
import requests
response = requests.post("http://localhost:8909/search", json={"query": "Запрос"}).json()Была выбрана модель LaBSE, оптимизированная под русский и английский языки. Ориентировался на бенчмарк для русского языка. Интересным вариантом выглядит использование GigaChat Embedding. Гипотеза заключается в том, что GigaChat скорее всего будет давать гораздо более качественное векторное пространство документов + длина контекста у него намного выше, чем у BERT-подобных моделей.
Использовал разбиение больших файлов с помощью RecursiveCharacterTextSplitter. Каждый получившийся кусочек становился отдельным документом в БД.
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=5000,
chunk_overlap=200)Плюсы стратегии:
- Не надо думать, что делать с несколькими эмбеддингами одного большого документа.
- Зачастую в данных важен локальный контекст, а не глобальный -> при достаточном размере сплита ущерба качеству не будет, либо будет незначительный ущерб. Если искомая информация содержится в нескольких частях документа, то вполне вероятно, что поиск найдёт их и они будут добавлены в контекст LLM. При этом нерелевантные части документа не будут съедать контекст.
- Можно настроить систему так, что для любого запроса в контекст LLM всегда влезет несколько документов. Это может помочь диверсифицировать источники данных, чтобы у LLM не было смещения, например, в одну точку зрения по причине наличия в контексте одного огромного документа.
Минусы:
- В моей реализации отсутствует привязка части документа к целому -> не получится вернуть исходный документ полностью. Это можно решить дополнительной таблицей в БД (отношение "many-to-one")
- Возможны случаи или постановки задачи, когда важно учитывать "далёкие" связи (например, исходный код проекта).
- Улучшение поиска
- Механизмы реранжирования выдачи (двухэтапное ранжирование)
- Несколько Retrieval'ов (разные модели векторизации)
- Роутинг запросов.
- Использование библиотек с продвинутыми инструментами по работе с LLM (gigachain/langchain)
- Увеличение скорости работы
- использование GPU ✅
- использование быстрых и функциональных хранилищ, в том числе in-memory.
- Обход цензурных ограничений LLM (очень много отказов у GigaChat), улучшение промпта
- работа с промптом - удаление слов(фраз)-триггеров.
- разные промпты для разных сценариев (зависит от конкретной задачи)
- Улучшение качества базы документов
- очистка от очень коротких текстов
- приведение текста к однородному виду. Например, можно убрать диакритические знаки (ударения) там, где они не нужны.