Главная / Статьи

Семантическое поиск с ChromaDB и векторными представлениями для многопроцессного платформенного решения

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

Издатель: REACTAPP.TOP10 мин чтения2308 слов

Источники: 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

В тот момент инфраструктура поиска перестала быть просто этапом настройки и начала демонстрировать настоящий поиск семантических знаний.

Почему важны реальные тесты поиска

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

EmbeddingService
      ↓
Expected Vector

но это не может полностью доказать, что следующая цепочка обеспечивает хорошую производительность поиска:

Real Document
      ↓
Real Chunking
      ↓
Real Embedding
      ↓
Real Vector Database
      ↓
Real Semantic Query
      ↓
Useful Context

Таким образом, стратегия тестирования разделяет несколько уровней проверки.

Стратегия тестирования

Платформа развивается в направлении трех взаимодополняющих уровней тестирования.

Единичные тесты выполняются быстро и детерминированно, поэтому они входят в обычную циклическую процедуру интеграции:

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.

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