Семантичне пошукове забезпечення за допомогою ChromaDB та ембеддингів для мультиагентної платформи
Перехід корпоративної багатоагентної платформи до справжнього семантичного пошуку: розбиття тексту з урахуванням слів, косинусова відстань у ChromaDB, тестові шари та наступний крок RetrievalAgent.
Джерела: Building Real Semantic Retrieval for an Enterprise Multi-Agent AI Platform
У проекті Enterprise Multi-Agent AI Platform досягнуто нової віхи: його механізм пошуку тепер здійснює справжній семантичний пошук за допомогою ембеддингів, збережених у ChromaDB. Архітектура розвинулася від підготовки документів до функціонального маршруту пошуку, який виконує послідовні кроки – SourceDocument, DocumentChunker, EmbeddingService, OpenAI Embeddings, ChromaDB, семантичний пошук та нарешті RetrievedDocument.
Це значуща зміна етапу розвитку. Платформа більше не лише підготовлює документи та створює ембеддинги; вона може зберігати векторизовані корпоративні знання, шукати їх за сенсом, ранжувати відповідні фрагменти та надавати структуровані результати. Під час її розробки також виникло кілька проблем із якістю пошуку, які потрібно було вирішити, перш ніж механізм пошуку можна було приєднати до RetrievalAgent.
Механізм пошуку набуває форми
Архітектура пошуку виглядає ось так:
Enterprise Documents
│
▼
SourceDocument
│
▼
DocumentChunker
│
▼
DocumentChunk[]
│
▼
EmbeddingService
│
▼
OpenAI Embeddings
│
▼
ChromaDB
│
▼
Semantic Search
│
▼
RetrievedDocument[]
│
▼
RetrievalAgent
Кожен шар несе відповідальність за певне завдання, і це робиться навмисно. Метою ніколи не була єдина велика функція RAG, яка б завантажувала файли, розділяла текст, створювала ембеддинги, керувала векторною базою даних, виконувала пошук та формувала відповідь. Натомість система складається з чітко визначених архітектурних меж.
Етап 1: джерельні документи
Усе починається з корпоративних знань. З часом цей контент може надходити з файлів PDF, DOCX та TXT, фінансових звітів, внутрішніх політик, технічної документації, наукових матеріалів та баз знань компанії. Модель SourceDocument надає цьому матеріалу стандартну форму перед тим, як він потрапить у процес обробки. Концептуально це виглядає так:
SourceDocument
├── document_id
├── content
├── source
└── metadata
Принцип, який тут має значення, — це простежуваність. Усе, що буде отримано пізніше, має залишатися пов’язаним із джерелом, звідки воно походить.
Етап 2: розділення на частини
Великі документи зазвичай не слід вбудовувати як один блок. DocumentChunker перетворює кожен SourceDocument на менші частини, готові до отримання:
SourceDocument
│
▼
DocumentChunker
│
├── Chunk 0
├── Chunk 1
├── Chunk 2
└── Chunk N
Кожен фрагмент зберігає свій chunk_id, document_id, content, source, chunk_index та метадані. Таким чином семантичний пошук може працювати з невеликими одиницями інформації, не втрачаючи зв’язку з оригінальним документом.
Покращення якості фрагментів
Під час виконання справжнього процесу пошуку виявилась проблема. Розділення на фрагменти за критерієм символів може розрізати звичайний текст у невдалих місцях, іноді прямо посеред слова. Межа може концептуально створити фрагмент, який закінчується ось так:
...important financial risks for
після чого йде фрагмент, який починається ось так:
the upcoming quarter...
або, у гірших випадках, розщеплення посеред слова. Такі фрагменти є технічно допустимими, проте якість отримання інформації залежить не лише від правильних структур даних. Межі впливають на семантичну якість того, що вбудовується.
Тому стратегія розділення тексту була змінена так, щоб для звичайного прозового тексту віддавати перевагу межам слів, а для тексту без корисних пробілів — використовувати межі символів як альтернативу. Тепер інструмент розділення має два режими роботи:
Normal prose
↓
Prefer word-aware boundaries
Text without whitespace
↓
Fallback to character boundaries
Це дрібний технічний нюанс, який несе важливий архітектурний урок: проходження тестів не означає, що якість отримання даних є гарною, а реальні дані виявляють проблеми, які ізольовані тести одиниць не завжди можуть показати.
Етап 3: ембеддинги
Як тільки фрагменти готові, EmbeddingService перетворює їхній текст на числові вектори.
DocumentChunk
│
▼
EmbeddingService
│
▼
Embedding Model
│
▼
Vector Representation
Сервіс підтримує ембеддинги одного тексту для запитів та пакетні ембеддинги для частин документів. Ранній тест локальної інтеграції підтвердив розмір вектора 1 536. Саме число має менше значення, ніж той факт, що реалізація ембеддингів знаходиться за межами сервісу, тож агент відновлення ніколи не повинен знати, як створюються вектори.
Етап 4: Зберігання векторів у ChromaDB
Наступним етапом є постійне зберігання векторів. Тепер кожну частину можна зберігати разом із її вектором та метаданими. Концептуально:
DocumentChunk
+
Embedding
+
Metadata
│
▼
ChromaDB
│
▼
Persistent Vector Collection
Запис вектора може містити таку інформацію:
Vector Record
├── chunk_id
├── embedding
├── content
├── document_id
├── source
├── chunk_index
└── metadata
Чистий вектор не має жодної користі для решти додатку. Платформі потрібен справжній контент та інформація про те, звідки він походить.
Етап 5: семантичний пошук
Завдяки вбудованим фрагментам у ChromaDB система може здійснювати семантичний пошук. Шлях запиту виглядає так:
User Query
│
▼
EmbeddingService
│
▼
Query Embedding
│
▼
ChromaDB
│
▼
Similarity Search
│
▼
Top-K Relevant Chunks
│
▼
RetrievedDocument[]
Зміна підходу до пошуку полягає у переході від пошуку документів, які містять саме ці слова, до пошуку фрагментів тексту, значення яких найкраще відповідають запиту. Це одна з основних можливостей технології RAG.
Корекція метрики схожості
Під час реальних тестів виявилася ще одна проблема. Векторні бази даних підтримують різні метрики відстані чи схожості, і якщо колекція використовує одну метрику, тоді як програма інтерпретує отриману відстань як іншу, оцінка релевантності стає вводящою в оману. Для цього потоку обробки колекція ChromaDB була спеціально налаштована для використання косинусової відстані, тож шар пошуку може послідовно інтерпретувати результати як схожість, засновану на косинусі.
Query Embedding
│
▼
ChromaDB
│
▼
Cosine Distance
│
▼
Similarity Score
│
▼
Ranked Results
Семантичне пошукове забезпечення — це не лише повернення документів. Це також розуміння того, наскільки вони релевантні.
Реальні результати пошуку
Після розділення на частини та корекції показників схожості систему протестували за допомогою реального запиту щодо фінансових ризиків. Результати, відсортовані за рівнем релевантності, мали показники схожості приблизно 0,6181, 0,5520 та 0,4198, а отриманий контекст містив відповідну інформацію про ризики ліквідності та ринкову волатильність. Таким чином, система пройшла весь цей процес без проблем:
Question
↓
Query Embedding
↓
ChromaDB
↓
Semantic Similarity
↓
Relevant Chunks
↓
Financial Risk Context
У той момент інфраструктура пошуку перестала бути просто етапом налаштування та почала демонструвати справжнє отримання семантичних знань.
Чому важливі справжні тести пошуку
Моковані одиничні тести залишаються надзвичайно корисними. Вони забезпечують швидкість, детермінізм, безпеку у процесах CI, відсутність зовнішніх витрат на API, контрольовані сценарії збоїв та ізоляцію логіки додатку. Однак вони не можуть відповісти на кожне запитання. Мокований тест може підтвердити, що щось працює структурно:
EmbeddingService
↓
Expected Vector
але це не може повністю довести, що наступна ланцюгова структура забезпечує хорошу продуктивність пошуку:
Real Document
↓
Real Chunking
↓
Real Embedding
↓
Real Vector Database
↓
Real Semantic Query
↓
Useful Context
Отже, стратегія тестування розділяє кілька рівнів перевірки.
Стратегія тестування
Платформа розвивається у напрямку трьох взаємодоповнюючих рівнів тестування.
Юніт-тести є швидкими та детерміністичними, і вони мають бути частиною звичайного CI-пайплайну:
Application Logic
↓
Mock External Dependencies
↓
Controlled Results
↓
Assertions
Тести інтеграції перевіряють реальну інфраструктуру та можуть виконуватися окремо від швидкого набору інструментів CI:
Application
↓
Real Embedding Provider
↓
Real ChromaDB
↓
End-to-End Retrieval
З віком платформи стає необхідним проведення тестування продуктивності та стійкості:
Realistic Workload
↓
Concurrent Requests
↓
Latency
Throughput
Rate Limits
Failures
Cost
Scalability
Система ШІ, готова до використання, потребує всіх трьох елементів. Імітація зовнішніх сервісів у тестах одиниць не замінює тестування інтеграції, а тестування інтеграції не замінює тестування продуктивності. Кожний рівень вирішує окреме інженерне завдання.
CI залишається у стані „зеленого“ кольору
Після вдосконалень у процесі отримання даних швидкий набір тестів залишається стабільним: 17 тестів пройшли, а 2 тести інтеграції були відхилені. Це важливо, оскільки конвейер RAG стає все складнішим, при цьому зберігається можливість точної перевірки через CI. Цикл розробки продовжується наступним чином:
Code Change
↓
Fast Unit Tests
↓
Commit
↓
Push
↓
GitHub Actions
↓
CI Validation
↓
Keep Green
Тести з використанням реальних сервісів залишаються доступними як окремий запуск.
Підключення RAG до платформи багатьох агентів
Інфраструктура отримання даних існує не ізольовано. Вона призначена стати шаром знань для більшої системи багатьох агентів, і загальна архітектура розвивається саме в цьому напрямку:
User
│
▼
Supervisor Agent
│
▼
Planning Agent
│
▼
Execution Plan
│
▼
Agent Registry
│
┌────────────┼────────────┐
▼ ▼ ▼
RetrievalAgent ResearchAgent AnalysisAgent
│
▼
RetrievalService
│
▼
EmbeddingService
│
▼
ChromaDB
│
▼
Semantic Search
│
▼
Relevant Context
│
▼
Downstream Agents
Саме тут RAG та оркестрація кількох агентів починають злитися.
Збереження простоти агента зі збору даних
Ключовою метою є змусити RetrievalAgent зосереджуватися лише на виконанні своїх обов’язків. Йому не потрібно знати про алгоритми розділення на частини, реалізацію ембеддингів, розміри векторів, внутрішню структуру ChromaDB, обчислення схожості чи налаштування зберігання. Натомість:
RetrievalAgent
↓
RetrievalService
↓
VectorStoreService
↓
EmbeddingService + ChromaDB
Агент запитує про необхідні знання, а інфраструктура пошуку вирішує, як їх знайти. Таке розділення дозволяє еволюціонувати основній реалізації без необхідності переписування агента.
Наступна віха: заміна тимчасової інфраструктури пошуку
Наступний крок є зрозумілим. Агент пошуку все ще має бути підключений безпосередньо до справжньої інфраструктури пошуку. Наразі це виглядає так:
BEFORE
RetrievalAgent
↓
Temporary Local Documents
А мета є такою:
NEXT
RetrievalAgent
↓
RetrievalService
↓
VectorStoreService
↓
EmbeddingService
↓
ChromaDB
↓
Semantic Search
↓
Enterprise Knowledge
Після цього інтегрування агент перестає повертати тимчасові жорстко закодовані результати та отримує інформацію з справжнього індексованого набору документів.
Від інфраструктури до багатоагентної обробки
Це інтегрування позначає ще один етап переходу. Більшість зусиль досі були спрямовані на створення інфраструктури пошуку. Як тільки RetrievalAgent починає використовувати справжню семантичну систему обробки, архітектура може підтримувати подібні робочі процеси:
User Request
↓
Supervisor
↓
Planning Agent
↓
Execution Plan
↓
Retrieval Agent
↓
Enterprise Knowledge
↓
Analysis Agent
↓
Report Agent
↓
Quality Review
↓
Final Response
RAG стає функціоналом у межах більш широкої системи виконання з кількома агентами, а не окремою функцією пошуку інформації.
Шлях у майбутнє
План розвитку пошуку переходить від базових компонентів до функціоналу, орієнтованого на практичне використання:
Document Contracts ✅
↓
Chunking ✅
↓
Embeddings ✅
↓
ChromaDB Vector Storage ✅
↓
Semantic Search ✅
↓
RetrievalAgent Integration ← NEXT
↓
Reranking
↓
Caching & Cost Controls
↓
Observability & Metrics
↓
Multi-Tenant Isolation
↓
Production Hardening
У пізніших етапах зростає значення цього процесу, оскільки платформа переходить від функціональної архітектури до корпоративних операцій.
Продуктивна платформа RAG потребує більшого, ніж просто пошук
Отримання релевантних даних з ChromaDB є важливою віхою, але не кінцем розробки архітектури. Продуктивна платформа пошуку зрештою мусить вміти обробляти:
- Поновне ранжування, оскільки початкова схожість векторів не завжди забезпечує найкращий порядок даних.
- Кешування, адже повторні використання ембеддингів та пошуки збільшують затримку та витрати.
- Моніторинг, щоб можна було вимірювати затримку пошуку, затримку обробки ембеддингів, кількість документів, їхні оцінки, проблеми та витрати.
- Еволюцію моделей та векторних просторів, оскільки зміна моделей ембеддингів може вимагати версійованих індексів та контрольованого їх переобчислення.
- Керування обмеженнями швидкості, адже зовнішні постачальники ШІ накладають операційні обмеження, які не є детермінованими.
Це має бути частиною плану розвитку, але його елементи слід додавати поступово, забезпечуючи чіткі межі, а не поєднувати все в одну велику реалізацію з самого початку.
Інженерний принцип
Найважливіший урок цього етапу: спочатку розробити абстракцію, перевірити її роботу на реальних даних, а потім удосконалювати її характеристики у міру розвитку архітектури. Такий підхід обраний навмисно:
Data Contract
↓
Chunking
↓
Unit Testing
↓
Embeddings
↓
Mocked Provider Testing
↓
Real Integration Validation
↓
Vector Storage
↓
Semantic Retrieval
↓
Retrieval Quality Improvements
↓
Agent Integration
Кожен етап відкриває новий клас проблем, і саме тому інкрементальна архітектура є ефективною.
Від документів до виконання з багатьох агентів
Більша картина починає прояснюватися:
Enterprise Knowledge
↓
Document Processing
↓
Chunking
↓
Embeddings
↓
Vector Storage
↓
Semantic Retrieval
↓
Retrieval Agent
↓
Multi-Agent Orchestration
↓
Analysis + Research + Reporting
↓
Quality Review
↓
Grounded Enterprise Response
RAG — це не вся платформа. Це інфраструктура знань, яка дозволяє спеціалізованим агентам працювати в межах конкретного корпоративного контексту.
Текущий етап
Що існує зараз: уніфіковані моделі документів, розбиття на частини з урахуванням пробілів та розділових знаків, сервіс вбудовування даних із фейковими тестами одиниць та справжнім запуском перевірки, постійне зберігання в ChromaDB із явним встановленням косинусної схожості, семантичний пошук, який повертає результати з ранжуванням, та швидкий набір з 17 пройдених тестів. Наступним етапом є підключення RetrievalAgent до справжнього потоку семантичного пошуку, після чого система перестане бути лише підсистемою RAG та почне виконувати багатоагентні операції за допомогою RAG.
Корпоративний ШІ — це не просто підключення LLM до векторної бази даних та оголошення про перемогу. Кожен рівень потребує контрактів, контракти — тестів, інтеграції — реальної перевірки, а система — можливостей для розвитку. Ланцюг обробки даних розширився від документів, фрагментів, ембеддингів та векторів до документів, фрагментів, ембеддингів, ChromaDB, семантичного пошуку та відповідного корпоративного контексту. Наступним кроком є передача цього контексту до RetrievalAgent, а потім — до багатоагентної обробки. Робочий цикл залишається незмінним: створювати, тестувати, вимірювати, покращувати, інтегрувати та масштабувати.