Double-embedding в Open WebUI Knowledge Bases¶
Задача 8 · Разобрано 07.08.2026 · KB-исследование, не баг нашей инфраструктуры
TL;DR¶
Это не баг, а by design (по заявлению разработчиков Open WebUI).
При загрузке файла в Knowledge Base Open WebUI создаёт две копии эмбеддингов одного и того же контента:
- Per-file collection (
file-{file.id}) — эмбеддинги для отдельного файла (нужно чтобы файл можно было прикрепить к чату сам по себе) - Knowledge collection (
{knowledge.id}) — эмбеддинги того же файла, но в рамках Knowledge Base
Оба вызова идут через process_file в backend/open_webui/routers/retrieval.py — обсуждение #8240.
Что это значит для нас¶
Наша конфигурация: VECTOR_DB=qdrant, KB на русском, ~24 файла в KB alatyr-infra.
Последствия: - Место в Qdrant × 2 (не критично для нашего объёма ~24 файла) - Токены на эмбеддинг × 2 при первом sync (уже прошли, теперь только UPDATE изменённых) - Retrieval работает корректно — RAG использует Knowledge collection, per-file коллекции используются только когда файл прикреплён напрямую к чату
Прогноз реального overhead: - 24 файла × ~250 chunks × 2 = ~12,000 векторов в Qdrant - Каждый вектор 1024-мерный float32 = 4 KB - Итого: ~48 MB в Qdrant вместо ~24 MB - Ускорение sync (задача 7 batch=32) компенсирует double-embedding по времени
Позиция разработчиков Open WebUI¶
Из #8240 (декабрь 2024):
Both are required to work. The first call ensures embeddings are created for the file itself, which is essential for the file to be processed and represented properly. The second call to
process_fileis necessary to associate those embeddings with the knowledge collection in the vector DB.Removing the first call would break isolated file processing, and skipping the second call would mean the file won't integrate into the relevant knowledge collection.
Был PR #8385 с частичным фиксом (после v0.5.4), но фундаментальная архитектура не изменилась.
Как понять что это именно double-embedding¶
Логи sync-to-openwebui.sh покажут два вставки для одного файла:
INFO ... Inserted 15 items into collection 'file-abc-123-def-456'
INFO ... Inserted 15 items into collection '7d8e9f10-...' (это ID KB)
Если видишь два Inserted N items подряд с одинаковым N для одного файла — это оно, не наш баг.
Что делать (варианты)¶
Вариант A: Смириться (рекомендуется)¶
- Overhead ~24 MB в Qdrant — незначителен на фоне общих ресурсов ragserver
- Retrieval работает корректно
- Ждём когда Open WebUI сделает оптимизацию upstream (issue открыт)
Вариант B: Использовать External Knowledge Source¶
Open WebUI поддерживает подключение к внешнему Qdrant через настройку External Knowledge Sources (Admin → Settings → Integrations → External Knowledge Sources).
Плюсы:
- Мы сами управляем эмбеддингами через sync-to-openwebui.sh в Qdrant напрямую (без API Open WebUI)
- Не будет double-embedding — только один вектор на chunk
Минусы:
- Нужно переписать sync-to-openwebui.sh — сейчас он использует Open WebUI API /api/v1/files/ + knowledge/{id}/file/add. Придётся ходить в Qdrant напрямую, самим считать эмбеддинги через Ollama API.
- Потеряется удобная интеграция с UI Open WebUI (загрузка через drag&drop, статусы sync)
- Нужен маппинг полей (content_field, title_field и т.д.) — конфигурация в UI
Оценка: день работы, овчинка не стоит выделки при текущем объёме.
Вариант C: Загружать только через /api/v1/files/ с параметром knowledge_id¶
По документации:
POST /api/v1/files/— Upload files. Passknowledge_id(and optionallydirectory_id) in the upload metadata to have the backend auto-link and process the file into that knowledge base server-side
Возможно (не проверено!) этот путь делает только один process_file вместо двух. Стоит проверить экспериментально.
Проверка:
1. Загрузить один тестовый файл через POST /api/v1/files/ с knowledge_id в metadata
2. Посмотреть в логах Open WebUI сколько раз вызвался process_file
3. Посмотреть в Qdrant сколько коллекций созданы
Если работает — переписать sync-to-openwebui.sh на этот эндпоинт вместо двух отдельных запросов.
Наше решение¶
Приняли Вариант A (смириться) на текущий момент. Overhead в ~24 MB Qdrant незначителен.
Follow-up (не срочно):
- [ ] Проверить Вариант C на одном тестовом файле (пилот на 15 минут)
- [ ] Если работает — обновить sync-to-openwebui.sh, экономия эмбеддинг-токенов ×2
Что мониторить:
- Размер qdrant-data volume в docker (docker system df или du -sh /var/lib/docker/volumes/rag-platform_qdrant-data)
- Если растёт быстрее чем KB — есть проблема с re-embedding или delete-not-cleaning-vectors (#7181, #14077)
Побочные баги (не наши, но знать надо)¶
#7181 Delete file doesn't clean vectors: при удалении файла из KB через UI векторы остаются в БД. При повторной загрузке того же файла — ошибка "Duplicate content detected".
- Наш обход: если удаляешь файл из KB, потом хочешь загрузить снова — сначала посмотри в Qdrant, что коллекция реально удалена. Если нет — удали вручную через Qdrant API.
#20854 Reindex broken: кнопка "Reindex" в UI сломана — падает с "Duplicate content detected".
- Наш обход: при смене embedding model — удалить KB целиком через UI, потом заново создать через
sync-to-openwebui.sh. Убедиться что коллекции в Qdrant очистились до нового ingest.
#14077 Persistent data remnants: при изменении chunk size и "save" без изменений — размер vector_db удваивается (новые chunks добавляются, старые не удаляются).
- Наш обход: не менять chunk size на существующей KB. Если надо — удалить KB и создать заново.
Ссылки¶
- Discussion #8240 (root cause) — обсуждение архитектурного решения
- Issue #7181 (delete cleanup) — известный баг с очисткой
- Discussion #20854 (reindex broken) — сломанная кнопка reindex
- Open WebUI Knowledge Docs — официальная документация
- External Knowledge Sources Docs — как подключить внешний Qdrant
Changelog¶
| Дата | Событие |
|---|---|
| 07.08.2026 | Задача 8 разобрана. Root cause: by-design архитектура Open WebUI. Принято решение по варианту A. Follow-up: пилот варианта C на 15 мин. |