Skip to content

Руководство по точкам расширения ​

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

Обзор точек расширения ​

Большая часть точек расширения на стороне Go сосредоточена в регистрационном центре internal/container/container.go (контейнер внедрения зависимостей):

  • Регистрация движков поиска: initRetrieveEngineRegistry()
  • Регистрация веб-поисковиков: registerWebSearchProviders()
  • Регистрация IM-адаптеров: registerIMAdapters()
  • Регистрация источников данных: registerDataSourceProviders()
  • Регистрация инструментов агента: registerTools() / маршрутизация инструментов
  • Регистрация бэкендов хранения: initStorageRegistry()

В Python-части docreader/ парсеры объединены в реестр (docreader/parser/registry.py), подключение — там же. Адаптеры и движки, специфичные для доменов, помечены в списке ниже по конкретным файлам.


Добавление нового парсера документов (docreader, Python) ​

Определение интерфейса ​

Базовый класс — docreader/parser/base_parser.py. После упрощения рефакторинга BaseParser отвечает только за преобразование документа в markdown-текст + ссылки на исходные изображения (разбиение, сохранение изображений, OCR, генерация подписей VLM выполняются на стороне Go):

python
class BaseParser(ABC):
    name: str
    engine: str
    ext: list[str]

    def parse_into_text(self, content: bytes) -> Document:
        ...

Возвращаемый Document (docreader/models/document.py, pydantic-модель) содержит ключевые поля content: str (markdown) и images: Dict[str, str] (путь → base64).

Механизм регистрации ​

docreader/parser/registry.py содержит ParserEngineRegistry с двухуровневым отображением «имя движка → {расширение файла → класс парсера}». Если запрошенный движок не поддерживает тип файла, автоматически используется fallback на движок builtin. Реестр по умолчанию строится в _build_default_registry().

При инициализации модуля выполняется:

python
# docreader/parser/__init__.py
REGISTRY = ParserEngineRegistry(_build_default_registry())

Существующие реализации ​

ДвижокПарсерФайл
builtinDocx2Parser, DocParser, PDFParser, MarkdownParser, ExcelParser, EPUBParser, HTMLParser, MHTMLParser, ImageParser (jpg/png/jpeg/jpg2/jpeg2/webp/bmp/tif/tiff), TextParser, CSVParser, JSONParser, XMLParser, RTFParser, NumPyParserdocreader/parser/builtin_parser.py
markitdownMarkitdownParser (Microsoft MarkItDown, многоформатный)docreader/parser/markitdown_parser.py
opendataloaderOpenDataLoaderParser (анализ верстки PDF, требует Java 11+, проверка доступности check_available)docreader/parser/opendataloader_parser.py

Шаги добавления ​

  1. Создать docreader/parser/my_parser.py, унаследовать BaseParser, реализовать parse_into_text(content: bytes) -> Document.
  2. Точка регистрации: docreader/parser/registry.py — добавить в _build_default_registry():
python
  "myengine": {
      ".pdf": MyParser,
      ".docx": MyParser,
      ...
  }
  1. При необходимости добавить зависимость в docreader/pyproject.toml (или системный пакет), описать работу в docs/06-development/01-dev-guide.md.
  2. Проверить: make lint-docreader / запустить локально парсинг тестового файла через HTTP API docreader.

Добавление стратегии разбиения на фрагменты (chunking) ​

Интерфейс ​

Стратегии разбиения определены в internal/application/chunking/. Базовый интерфейс: ChunkStrategy:

go
type ChunkStrategy interface {
    Name() string
    Split(ctx context.Context, text string, cfg *types.ChunkingConfig) ([]*types.Chunk, error)
}

Конфигурация разбиения: types.ChunkingConfig (internal/types/knowledge.go), включая ChunkingStrategy, ChunkSize, ChunkOverlap, Separator, RagMaxContextSize, прочие параметры, специфичные для стратегии.

Регистрация ​

Фабрика/реестр: internal/application/chunking/factory.go (или registry.go).

go
func GetStrategy(name string) ChunkStrategy {
    switch strings.ToLower(name) {
    case "recursive":
        return NewRecursiveChunker()
    case "semantic":
        return NewSemanticChunker()
    case "layout":
        return NewLayoutChunker()
    ...
    default:
        return NewRecursiveChunker()
    }
}

Существующие реализации ​

СтратегияФайл
recursive (рекурсивный по разделителям)internal/application/chunking/recursive.go
semantic (семантическое разбиение, с эмбеддингом/кластерами)internal/application/chunking/semantic.go
layout (с учётом разметки/таблиц)internal/application/chunking/layout.go
none / прочие по конфигурациисм. фабрику

Шаги добавления ​

  1. Создать internal/application/chunking/mystrategy.go, реализовать ChunkStrategy.
  2. Добавить кейс в фабрику GetStrategy.
  3. По необходимости расширить types.ChunkingConfig и валидацию в internal/validation/....
  4. Обновить документацию по разбиению на блоки.
  5. Прогнать тесты: go test ./internal/application/chunking/....

Добавление движка поиска (retrieval engine) ​

Движки поиска подключаются для гибридного/векторного/полнотекстового поиска в БЗ.

Интерфейс ​

В internal/application/retrieval/ (или internal/retrieval/) общий интерфейс, обычно:

go
type Engine interface {
    Name() string
    Init(ctx context.Context, cfg *config.Config, deps ...any) error
    Search(ctx context.Context, req *types.SearchRequest) (*types.SearchResult, error)
    // при наличии: Upsert/Delete, Health
}

Также есть Registry для выбора движка по названию (config.KnowledgeBase.IndexingStrategy.RetrieveEngine или глобально).

Регистрация ​

Центр регистрации: internal/container/container.go → initRetrieveEngineRegistry().

go
registry := retrieval.NewRegistry()
registry.Register("weaviate", weaviate.New())
registry.Register("qdrant", qdrant.New())
registry.Register("milvus", milvus.New())
registry.Register("paradedb", paradedb.New())
registry.Register("pgvector", pgvector.New())
// ...
container.SetRetrieveEngineRegistry(registry)

Существующие реализации ​

ДвижокФайл/пакет
weaviateinternal/retrieval/weaviate/
qdrantinternal/retrieval/qdrant/
milvusinternal/retrieval/milvus/
paradedbinternal/retrieval/paradedb/
pgvector (Postgres + pgvector)internal/retrieval/pgvector/
opensearch (при наличии)см. контейнер/реестр

Шаги добавления ​

  1. Реализовать пакет internal/retrieval/<engine>/ с реализацией интерфейса Engine.
  2. Зарегистрировать в initRetrieveEngineRegistry() контейнера.
  3. Добавить конфигурацию в internal/config/ (knowledge.retrieval.<engine>.*), маппинг в YAML/ENV.
  4. Обновить поисковые движки.
  5. Интеграционные тесты: go test ./internal/retrieval/<engine>/... (при наличии тестового стенда).

Добавление поставщика моделей (provider) ​

Модели (chat/embedding/rerank/vision/asr/tts и др.) подключаются через провайдерский интерфейс.

Интерфейс ​

В internal/models/provider/ общий интерфейс Provider (ключевые методы зависят от типа модели):

go
type Provider interface {
    ID() string
    Name() string
    Capabilities() []Capability
    CreateChatCompletion(ctx context.Context, req *ChatRequest) (*ChatResponse, error)
    CreateChatCompletionStream(ctx context.Context, req *ChatRequest, w StreamWriter) error
    // для embedding/rerank — отдельные интерфейсы или методы
}

Также используются Registry и фабрика по provider_id.

Регистрация ​

  • Статическая регистрация провайдеров: internal/models/provider/registry.go (или init() каждого пакета)
  • Либо через контейнер: internal/container/container.go при инициализации модели-системы
  • Администрирование через UI/API: провайдеры также могут быть добавлены через config/models.json (наложение развёртывания) — см. Управление моделями

Типичный шаблон регистрации:

go
func init() {
    registry.Register("openai", NewOpenAIProvider)
    registry.Register("anthropic", NewAnthropicProvider)
    registry.Register("ollama", NewOllamaProvider)
    // ...
}

Существующие реализации ​

См. пакеты в internal/models/provider/: openai, anthropic, azure_openai, ollama, deepseek, qwen, moonshot, siliconflow, zhipu, minimax, mistral, google, volcengine, baidu, cohere, huggingface, vllm, lmdeploy, xinference, xai, groq, fireworks, together, openrouter и др.

Шаги добавления ​

  1. Создать internal/models/provider/myprovider/, реализовать Provider (и при необходимости EmbeddingProvider, RerankProvider).
  2. Зарегистрировать в реестре провайдеров (registry.Register("myprovider", ...)).
  3. Добавить дефолты в internal/config/models_defaults.go или через config/models.json для конкретного стенда.
  4. Обновить Управление моделями (список встроенных провайдеров, compat-переопределения при необходимости).
  5. Тесты: go test ./internal/models/provider/myprovider/....

Добавление поисковика (web search provider) ​

Веб-поиск используется агентом/функциями при необходимости поиска в интернете.

Интерфейс ​

В internal/websearch/ (или internal/application/websearch/):

go
type Provider interface {
    Name() string
    Search(ctx context.Context, query string, opts *SearchOptions) ([]*SearchResult, error)
    IsAvailable(ctx context.Context) bool
}

SearchOptions включает Count, Country, Language, таймауты и др.

Регистрация ​

Центр: internal/container/container.go → registerWebSearchProviders().

go
ws := websearch.NewManager()
ws.Register(google.New(cfg.WebSearch.Google))
ws.Register(bing.New(cfg.WebSearch.Bing))
ws.Register(duckduckgo.New(cfg.WebSearch.DuckDuckGo))
ws.Register(serpapi.New(cfg.WebSearch.SerpAPI))
ws.Register(tavily.New(cfg.WebSearch.Tavily))
ws.Register(brave.New(cfg.WebSearch.Brave))
ws.Register(searxng.New(cfg.WebSearch.SearXNG))
container.SetWebSearchManager(ws)

Существующие реализации ​

ПровайдерПакет
google (Programmable Search/Custom Search)internal/websearch/google/
binginternal/websearch/bing/
duckduckgointernal/websearch/duckduckgo/
serpapiinternal/websearch/serpapi/
tavilyinternal/websearch/tavily/
braveinternal/websearch/brave/
searxnginternal/websearch/searxng/

Шаги добавления ​

  1. Реализовать internal/websearch/myprovider/ с интерфейсом Provider.
  2. Зарегистрировать в registerWebSearchProviders().
  3. Добавить секцию конфигурации WebSearch.MyProvider в internal/config/.
  4. Обновить документацию Веб-поиск.
  5. Тесты с моками: go test ./internal/websearch/myprovider/....

Добавление источника данных (data source) ​

Источники данных (Confluence, Notion, Feishu/Lark, Git, S3, Seafile и др.) используются для синхронизации/импорта в БЗ.

Интерфейс ​

В internal/datasource/ базовый интерфейс Provider:

go
type Provider interface {
    ID() string
    Name() string
    ValidateConfig(ctx context.Context, cfg map[string]any) error
    ListResources(ctx context.Context, cfg map[string]any, opts *ListOptions) ([]*Resource, error)
    FetchContent(ctx context.Context, cfg map[string]any, res *Resource) (*Content, error)
    // опц.: Watch/Sync, Auth flow
}

Регистрация ​

Центр: internal/container/container.go → registerDataSourceProviders().

go
ds := datasource.NewRegistry()
ds.Register(confluence.New())
ds.Register(notion.New())
ds.Register(feishu.New())
ds.Register(seafile.New())
ds.Register(github.New())
ds.Register(s3.New())
// ...
container.SetDataSourceRegistry(ds)

Существующие реализации ​

ПровайдерФайл
confluenceinternal/datasource/confluence/
notioninternal/datasource/notion/
feishu / larkinternal/datasource/feishu/
seafileinternal/datasource/seafile/
githubinternal/datasource/github/
s3 / miniointernal/datasource/s3/
webhook / прочиесм. реестр

Шаги добавления ​

  1. Создать internal/datasource/myds/ с реализацией Provider.
  2. Зарегистрировать в registerDataSourceProviders().
  3. Добавить UI-форму/валидацию конфигурации (frontend src/pages/datasource/ при необходимости).
  4. Обновить Импорт источников данных и Seafile при релевантности.
  5. Тесты: go test ./internal/datasource/myds/....

Добавление IM-адаптера (IM integration) ​

Поддерживаются интеграции с корпоративными мессенджерами для канальной/ботовой работы.

Интерфейс ​

В internal/im/ интерфейс Adapter:

go
type Adapter interface {
    ID() string
    Name() string
    Init(ctx context.Context, cfg *Config) error
    Start(ctx context.Context) error
    Stop(ctx context.Context) error
    SendMessage(ctx context.Context, to string, msg *Message) error
    OnMessage(handler func(*InboundMessage)) // подписка
}

Регистрация ​

Центр: internal/container/container.go → registerIMAdapters().

go
imReg := im.NewRegistry()
imReg.Register(wechatwork.New())
imReg.Register(dingtalk.New())
imReg.Register(lark.New())
imReg.Register(feishu.New())
imReg.Register(slack.New())
imReg.Register(telegram.New())
imReg.Register(discord.New())
container.SetIMRegistry(imReg)

Существующие реализации ​

См. internal/im/<adapter>/: wechatwork, dingtalk, lark, feishu, slack, telegram, discord, custom и др.

Шаги добавления ​

  1. Реализовать internal/im/myim/adapter.go.
  2. Зарегистрировать в registerIMAdapters().
  3. Добавить конфигурацию в internal/config/im.go и хранение в БД (модель/миграция при необходимости).
  4. Обновить Интеграция IM.
  5. Интеграционные тесты с заглушкой: go test ./internal/im/myim/....

Добавление инструмента агента (agent tool) ​

Инструменты агента расширяют возможности агента (поиск, выполнение кода, чтение файлов, вызов MCP и др.).

Интерфейс ​

В internal/agent/tools/ используется интерфейс инструмента (типовой для движка агента):

go
type Tool interface {
    Name() string
    Description() string
    Parameters() map[string]any // JSON Schema
    Execute(ctx context.Context, args map[string]any) (*ToolResult, error)
}

Результат: ToolResult с Content, Error, Metadata.

Регистрация ​

Центр: internal/container/container.go → registerTools() (или internal/agent/tools/registry.go).

go
tools := []tools.Tool{
    newSearchTool(deps),
    newReadTool(deps),
    newWriteTool(deps),
    newThinkTool(),
    newWebSearchTool(deps.WebSearch),
    newMCPTool(deps.MCP),
    // ...
}
agent.SetTools(tools)

Также инструменты MCP динамически подгружаются из внешних MCP-сервисов (MCP-интеграция).

Существующие инструменты ​

См. internal/agent/tools/: search, read, write, think, web_search, shell, python, file, browser, mcp, knowledge, graph, wiki, skill, sandbox, memory и др.

Шаги добавления ​

  1. Создать internal/agent/tools/mytool.go с реализацией Tool.
  2. Зарегистрировать в registerTools() контейнера (с проверкой доступности/прав).
  3. При необходимости добавить в системный промпт/описание агента (internal/agent/prompts.go) — см. Сборка промптов диалога.
  4. Обновить документацию по агенту/инструментам (Агент-движок).
  5. Тесты: go test ./internal/agent/tools/....

Добавление бэкенда хранения (storage backend) ​

Файловое хранение (аватары, вложения, превью, экспорт) поддерживает несколько бэкендов.

Интерфейс ​

В internal/storage/ интерфейс Backend:

go
type Backend interface {
    Name() string
    Put(ctx context.Context, key string, r io.Reader, size int64, meta map[string]string) (string, error)
    Get(ctx context.Context, key string) (io.ReadCloser, error)
    Delete(ctx context.Context, key string) error
    URL(ctx context.Context, key string, opts *URLOptions) (string, error) // публичная/подписанная ссылка
    Exists(ctx context.Context, key string) (bool, error)
}

Регистрация ​

Центр: internal/container/container.go → initStorageRegistry().

go
reg := storage.NewRegistry()
reg.Register("local", local.New(cfg.Storage.Local))
reg.Register("s3", s3.New(cfg.Storage.S3))
reg.Register("oss", oss.New(cfg.Storage.OSS))
reg.Register("cos", cos.New(cfg.Storage.COS))
reg.Register("minio", minio.New(cfg.Storage.MinIO))
reg.Register("r2", r2.New(cfg.Storage.R2))
container.SetStorageRegistry(reg)

Активный бэкенд выбирается через config.Storage.Type.

Существующие реализации ​

БэкендПакет
local (файловая система)internal/storage/local/
s3 (AWS S3-совместимый)internal/storage/s3/
miniointernal/storage/minio/
r2 (Cloudflare R2)internal/storage/r2/
oss (Alibaba Cloud OSS)internal/storage/oss/
cos (COS)internal/storage/cos/

Шаги добавления ​

  1. Реализовать internal/storage/mybackend/ с интерфейсом Backend.
  2. Зарегистрировать в initStorageRegistry().
  3. Добавить конфигурацию Storage.MyBackend в internal/config/storage.go и валидацию.
  4. Обновить Бэкенды хранения.
  5. Тесты: go test ./internal/storage/mybackend/....

Прочие практические замечания ​

  • Зависимости через контейнер. По возможности получать зависимости из internal/container.Container, не создавать глобальные синглтоны вне контейнера.
  • Конфигурация. Все новые параметры добавлять в internal/config/ с валидацией и описанием ENV.
  • Миграции БД. Если расширение требует новых таблиц/полей — добавить миграцию в migrations/ (формат, принятый в проекте).
  • Логирование/трейсинг. Использовать internal/log и существующий контекстный логгер.
  • Безопасность. Для внешних вызовов учитывать таймауты, повторы с бэк-оффом, rate-limit, валидацию входных данных.
  • Документация. Обновить релевантный раздел в website-docs/ (features/development), добавить скриншоты при изменении UI.
  • Проверка связей. После изменений запустить npm run check:links и npm run check:mermaid в website-docs/, а также go build ./... и релевантные go test.

Версия v0.8.3 · MIT License