Skip to content

Источники (Sources)

Source — это способность получать информацию. Векторный поиск — одна из стратегий, не единственная: файловая система, CSV и веб (WebSource) уже такие же первоклассные, а эмбеддинги не обязательны. Протокол Source (reactifact/sources.py) специально маленький, чтобы этот список рос добавлением реализаций, а не изменением абстракции — прямой API, поиск по ключевым словам и SQL-источники в роадмапе, но ещё не реализованы (см. roadmap); не рассчитывайте на них, пока не появятся. Источники живут в Context.resources.sources.

from reactifact import Context, RuntimeResources
from reactifact.sources import CSVSource, EmbeddingSource, FileSystemSource, WebSource

ctx = Context(
    resources=RuntimeResources(
        sources={
            "docs": FileSystemSource("./docs"),                 # по ключевым словам по умолчанию
            "catalog": CSVSource("data/"),                      # каталог с .csv-файлами
            "rag": EmbeddingSource("data/", embedder=embedder),  # векторный поиск требует embedder
            "web": WebSource(["https://example.com/docs"]),     # страницы тянутся лениво
        }
    )
)

SourceRef

Общий результат любого поиска — SourceRef: ранжированный, скоупированный указатель:

class SourceRef(BaseModel):
    source_id: str         # какой источник его произвёл
    locator: str           # стабильный локатор внутри источника (путь / URL / id)
    metadata: dict         # owner_id-скоуп, флаг structured, доп. контекст
    score: float | None    # ранг/оценка совпадения, если источник скорирует
    title: str             # опциональный заголовок
    excerpt: str           # маленький превью-фрагмент
    query_id: str          # запрос, который его нашёл

SourceRef.stable_id() позволяет строить детерминированные id артефактов (ref:{stable_id}:{owner_id} в fan_out_sources), так что повторные поиски идемпотентны.

Четыре встроенных источника

Источник Назначение Примечания
FileSystemSource поиск по ключевым словам по локальным файлам scorer опционален; по умолчанию — пересечение слов
EmbeddingSource векторный поиск по подготовленному корпусу нужен EmbeddingProvider
CSVSource запрос к каталогу/таблице, возвращает структурированные строки детерминированно, без эмбеддингов
WebSource живой веб: поиск + ленивое разрешение страниц тянет обещанные документы по требованию

Ленивая материализация

WebSource (и удалённые источники вообще) возвращают ссылки, а не содержимое. Разрешение документа — явное и ленивое: демо research тянет только те страницы, которые решило использовать, и связывает полученный документ с референсом:

SourceRef --materialized_from--> TypedDoc

Рецепт materialize_doc кодирует ровно этот поток.

Типовые стадии поиска в демо

query ──► fan_out_sources ──► SourceRefs (ранжированные, скоуп на владельца)
                                   │
                                   ▼  (выбор релевантных + ленивое разрешение для web)
                              TypedDoc / строки
                                   │
                                   ▼
                            Evidence (извлечённое, со скоупом)

Пример: CSVSource для детерминированных чисел

Цены каталога никогда не идут через LLM. CSV-источник возвращает точные строки; стадия оценки в примере repair умножает количества на цены из каталога детерминированно:

catalog = CSVSource("data/price.csv", key="name")
rows = await catalog.asearch("штукатурка", limit=20)

Можно указывать CSVSource на любую структурированную таблицу и искать по ключевым словам, получая нужные строки для вычислений.