Окно Gemini на 1M заменило мне векторное хранилище, но латентность и происхождение ответов возразили
Сравнение полного контекста и RAG на 500 вопросах поддержки: точность, задержка и стоимость, почему важно происхождение ответа и какая гибридная схема сохранила плюсы обоих подходов.
Удаляем векторную таблицу
Представьте ассистента поддержки, которым пользуются девять тысяч сотрудников компании. Любой его ответ человек может переслать клиенту, поэтому ошибка или ответ без объяснения обходятся дорого.
Под ним работает слой поиска: чанкер, задача по построению эмбеддингов, векторное хранилище и в самом конце реранкер, который подкручивали столько раз, что никто уже не может обосновать его параметры.
user ─► embed ─► vector db ─► rerank ─► 4k ctx ─► model ─► answer
▲
chunker
▲
nightly reindex
Эксплуатация — это четыре сервиса и два дежурных алерта, плюс повторяющийся баг, когда футер PDF тихо портит половину чанков. При этом сам путь запроса крошечный:
q = embed(text)
hits = db.search(q, k=8)
ctx = "\n".join(h.doc for h in hits)
ans = llm(f"{ctx}\n\nQ: {text}")
Вся боль живёт вокруг этих четырёх строк.
И тут напрашивается соблазнительная мысль. Gemini принимает миллион токенов и почти идеально их помнит, а весь корпус занимает всего 640 000 токенов. Он помещается. Поэтому во вторник вечером кто-то удаляет таблицу на 2,3 миллиона эмбеддингов и заменяет весь пайплайн вот этим:
docs = load_all()
ans = gem(f"{docs}\n\nQ: {text}")
Ни чанкера, ни задачи переиндексации, ни реранкера с константой, которую никто не может объяснить. Это работает, и часов шесть ощущение такое, будто списал на экзамене и не попался.
Что показало следующее утро
Задержка растёт примерно пропорционально размеру входа. Это не секрет, но по-настоящему это чувствуешь, только когда начинает жаловаться поддержка. Для сравнения через каждую схему прогнали 500 реальных вопросов. Точность оценивала вторая модель, сверяя каждый ответ с эталоном, написанным вручную, а шестьдесят таких оценок перепроверили руками, чтобы убедиться, что судья не подсуживает.
setup p50 p95 cost/query accuracy
-----------------------------------------------------------
RAG, 4k ctx 1.9s 3.4s $0.004 71%
full stuff, 640k 28.7s 41.2s $0.81 74%
cached, 640k 9.4s 15.1s $0.11 74%
Медиана в 28 секунд — долгое ожидание для окна чата. Кэширование промптов это время сокращает, и пользоваться им стоит, но у него есть ограничения: минимальный размер промпта, время жизни кэша, за поддержание которого вы платите, и одна слабость, которая здесь ударила больнее всего. Корпус меняется примерно сорок раз в день, каждая правка сбрасывает кэш, и целый день ушёл на то, чтобы платить за повторную сборку 640 000 токенов.
Вопрос, который оказался важнее
Точность выросла на три пункта, и это почти скрыло настоящую проблему. Руководитель поддержки задала простой вопрос: откуда взялся этот ответ?
Поиск даёт конкретный ответ: чанк 4112 на девятой странице, последняя правка в марте. С полным окном модель выдаёт уверенный абзац, собранный где-то внутри 640 000 токенов, и показать ей нечего. Назовём это проверкой происхождения. Вопрос не в том, может ли модель ответить, а в том, можете ли вы доказать, откуда взялся ответ. Это проблема продукта, а не модели, из тех, что заканчивают карьеры, а не спринты.
Может, просто реранкер был плохой?
Кто-нибудь сразу возразит: настройте реранкер, возьмите тариф подешевле, режьте на чанки умнее. Справедливо, реранкер и правда был посредственным. Но даже хорошо настроенный реранкер передаёт дальше восемь фрагментов и надеется на лучшее, а никакая настройка не даст ссылку на источник из окна, которое проглотило всё разом.
Схема, которая прижилась
Векторная база вернулась, а реранкер нет.
ids = db.search(embed(q), k=40)
docs = fetch(ids)
ans = gem(f"{docs}\n\nQ: {q}", cache=c)
Поиск больше не ищет ответ. Его задачей стало сузить круг, а читает уже длинное окно.
user ─► embed ─► vector db (k=40, no rerank)
│
▼
~90k ctx + cached policy docs
│
▼
model ─► answer + doc ids
Те же 500 вопросов прошли через того же судью:
hybrid, 90k ctx 3.1s 5.2s $0.021 88%
Сорок не слишком отфильтрованных чанков оставляют модели пространство для рассуждений, тогда как реранкеру пришлось бы угадывать идеальную восьмёрку. И каждый ответ несёт идентификаторы того, на что он опирался.
Большие окна не убили поиск, они покончили с поиском, где всё решает точность. Старая задача была мучительной: найти восемь идеальных чанков, потому что бюджет позволял только восемь. С этой задачей покончено, и скучать по ней никто не должен.