Базы знаний и управление знаниями
База знаний используется для организации соответствующих материалов и единой конфигурации разбиения на блоки, векторных моделей, поисковых индексов, Wiki и графов знаний. Файлы, веб-страницы, рукописный Markdown и FAQ управляются как элементы знаний, которые после добавления анализируются и индексируются согласно конфигурации.
Разные базы знаний могут иметь независимые настройки обработки. При выполнении запросов можно ограничить область поиска, а доступ участников и совместное использование в организации также авторизуются на уровне базы знаний.
Точки входа для операций управления
| Операция | Интерфейс |
|---|---|
| Создание базы, изменение размера блоков и переключение индексов | Вкладки «Разбиение на блоки» и «Стратегия индексации» в окне редактирования базы знаний |
| Загрузка файлов, импорт веб-страниц или написание Markdown | Область загрузки в списке документов или выпадающее меню «Создать»; прогресс загрузки отображается в панели задач в правом нижнем углу |
| Настройка порядка списка документов | «Сортировка» на панели инструментов списка: по времени обновления, времени загрузки/создания (по умолчанию новые сверху) или имени файла |
| Проверка прогресса анализа или поиск зависших документов | Статус на карточке документа или открытие временной шкалы анализа (см. Просмотр прогресса анализа) |
| Организация документов с помощью папок | Дерево папок слева от списка документов; при загрузке каталога структура папок сохраняется (см. Дерево папок) |
| Присвоение тегов документам (несколько на один документ) | Для одного — в деталях; для нескольких — через «Теги» в панели массовых операций (см. Теги (KnowledgeTag)) |
| Проверка результатов анализа, исправление опечаток | Открыть документ → Список блоков → Прямое редактирование блока (см. Редактирование блоков и история версий) |
| Добавление настраиваемых полей, таких как отдел или уровень секретности | Настраиваемые метаданные в деталях документа (см. Ключевые моменты модели) |
| Просмотр записей операций | Настройки базы знаний → Активность (см. Поток активности базы знаний (KB Activity)) |
| Копирование базы знаний или перемещение документов между базами | Копирование в списке баз знаний или перемещение в массовых операциях с документами (см. Копирование базы знаний и перемещение знаний) |
| Массовая загрузка исходных файлов | Выбрать документы → «Массовая загрузка» в панели массовых операций (см. Массовая загрузка) |
Создание базы знаний и импорт материалов
При создании базы знаний выберите тип контента, модели и методы индексации, затем загрузите файлы, импортируйте веб-страницы или напишите Markdown. Для обычных материалов используйте базу документов, для стандартных вопросов и ответов — базу FAQ. Векторное хранилище нельзя изменить после создания, поэтому его следует определить до создания базы.
На странице подтверждения загрузки можно установить теги и параметры анализа для текущей партии файлов, включая создание аннотации документа (включено по умолчанию; при отключении анализ, индексация и другие процессы выполняются в обычном режиме). Параметры разовой обработки имеют приоритет над конфигурацией базы знаний, которая, в свою очередь, имеет приоритет над значениями пространства по умолчанию. Для уже существующих документов требуется повторный анализ, чтобы применить измененные параметры разбиения.
При массовой загрузке панель задач в правом нижнем углу суммирует все файлы: одновременно передаются до 3 файлов, отображаются переданные байты, оставшееся время, а также количество доступных для поиска, обрабатываемых, неудачных и уже существующих файлов. Отдельные файлы можно отменить или отправить повторно; после завершения всех загрузок можно покинуть страницу, анализ продолжится в фоновом режиме. Тайм-аут загрузки больших файлов автоматически продлевается в зависимости от их размера.
Просмотр прогресса анализа
Список и карточки документов отображают статус анализа каждого документа. Если в течение 20 минут нет прогресса, статус меняется на «В очереди» или «Подозрение на зависание»: первый означает, что задачи все еще ждут в очереди (обычно действий не требуется); второй — что задачи по этому документу больше не продвигаются. В этом случае можно проверить временную шкалу анализа, чтобы увидеть, на каком этапе произошла остановка, или перезапустить процесс после его остановки. Документы, по которым долгое время нет прогресса, автоматически помечаются системой как неудачные с кодом ошибки TASK_STALLED.
Временная шкала анализа показывает затраченное время и результат по этапам. При сбое карточка ошибки в верхней части поясняет этап и причину сбоя, а также предоставляет кнопку повтора.
Просмотр галереи
Во вкладке «Галерея» базы знаний собраны изображения, извлечённые из документов, — бесконечная прокрутка с постепенной подгрузкой. Можно искать по описанию изображения и распознанному тексту (OCR), фильтровать по свойствам изображения, исходному документу и другим атрибутам, предоставляемым системой; по клику открывается крупное изображение с описанием, OCR и сведениями об источнике. Фильтр по исходным документам поддерживает множественный выбор — удобно для сверки результатов разбора целой пачки файлов.
Галерея показывает уже имеющиеся изображения и не требует включённого поиска по векторам изображений.
Мультимодальный Embedding и поиск изображений
Embedding-модели, умеющие принимать изображения на вход, кодируют текст и исходное изображение в одно и то же векторное пространство, благодаря чему текстовый вопрос может находить релевантные изображения. Уже поддерживаемые модели включают WeMM-Embedding от и Qwen3-VL-Embedding; при подключении нужно учитывать поддержку картинок на вход и протокол запроса; о развёртывании и подключении WeMM см. настройка моделей.
В настройках базы знаний включите мультимодальную обработку и «Поиск по векторам изображений» и выберите векторную модель с поддержкой изображений. Векторы изображений по умолчанию выключены: уже проиндексированные документы нужно разобрать заново, чтобы они были дополнены векторами изображений; страницы сканированных PDF векторов изображений не получают. Подробные параметры и ограничения — в разделе «Векторы изображений» ниже.
Организация папок и тегов
Папки используются для архивации по каталогам, один документ может принадлежать только одной папке. Загрузка всего каталога позволяет сохранить иерархическую структуру; при переименовании или перемещении в дереве папок пути подкаталогов обновляются одновременно, а при совпадении целевого каталога содержимое объединяется. Перемещение документов между папками в одной базе знаний только меняет их классификацию и не требует повторного анализа.
Теги используются для перекрестной классификации, документ может быть связан с несколькими тегами. Теги можно предустановить при загрузке или изменить массово после выбора документов; в диалоговом окне массовой операции предварительно выбираются теги, общие для выбранных документов. При фильтрации по нескольким тегам возвращаются документы, соответствующие любому из них.
При включении автоматического тегирования система после завершения анализа выбирает подходящие варианты из существующих тегов-кандидатов. По умолчанию на один документ назначается не более 3 тегов, если теги уже есть, шаг пропускается. Конфигурация влияет только на последующий анализ, не дополняет исторические документы автоматически, а ошибки модели не блокируют завершение обработки документа.
Редактирование блоков и дополнение метаданных
Редактирование текстовых блоков в деталях документа позволяет исправлять ошибки анализа и перестраивать индекс. Каждое редактирование или откат создает новую версию; если другой пользователь уже обновил тот же блок, система предложит обновить страницу и попробовать снова. Если обновление индекса не удалось, отредактированное содержимое сохраняется, отображается статус ошибки, и можно попробовать отправить повторно.
Настраиваемые метаданные используются для добавления информации, такой как отдел, уровень секретности или номер версии (до 20 элементов). Изменение метаданных инициирует обновление аннотации; подробности о длине полей и поддерживаемых типах см. в справочном разделе.
Копирование и перемещение контента
Копирование базы знаний позволяет повторно использовать существующую конфигурацию и контент. При перемещении между базами можно выбрать повторное использование векторов или повторный анализ: повторное использование требует, чтобы обе базы были привязаны к одному векторному хранилищу, повторный анализ позволяет использовать конфигурацию хранилища и обработки целевой базы. Перемещение является асинхронной задачей, прогресс которой можно отслеживать.
Массовая загрузка исходных файлов
После выбора документов нажмите «Массовая загрузка», чтобы упаковать исходные файлы выбранных документов в ZIP-архив с сохранением структуры папок базы знаний. После распаковки их можно загрузить снова по папкам. В одной партии может быть до 200 документов, общий объем исходных файлов — до 512 МиБ; элементы без исходных файлов (например, импортированные веб-страницы) будут пропущены. Опция «Выбрать все загруженные» включает только те документы, которые загружены в данный момент. Права на массовую загрузку такие же, как на загрузку одного файла: требуется роль Contributor или выше с правами на редактирование базы знаний.
Просмотр активности и использования
Раздел «Активность» в настройках базы знаний фиксирует изменения конфигурации, документов, блоков, общего доступа и Wiki. Этот вход предназначен для вошедших в систему пользователей с правами управления ресурсами, API-ключи не имеют доступа. Для операций, инициированных через API-ключ, под именем исполнителя будет дополнительно отображаться имя ключа.
В базах знаний, доступных через общий доступ организации с правами только для чтения (Viewer), интерфейс не отображает кнопки загрузки, редактирования, удаления и настроек.
Квота хранилища рассчитывается по рабочему пространству и включает файлы, текст, векторы и индексы. Проверка квоты выполняется перед созданием базы знаний и загрузкой, после удаления контента соответствующий объем высвобождается.
Конфигурация и справочник интерфейсов
Модель и параметры базы знаний
Тип базы знаний
internal/types/knowledgebase.go:
const (
KnowledgeBaseTypeDocument = "document" // Тип документа
KnowledgeBaseTypeFAQ = "faq" // Тип FAQ
KnowledgeBaseTypeWiki = "wiki" // Тип Wiki
)При обновлении базы знаний настройки, не соответствующие ее типу, будут очищены (например, FAQConfig для не-FAQ базы). VectorStoreID использует тег GORM <-:create, не подлежит изменению после создания (для предотвращения несоответствия индекса и хранилища).
Обзор структуры конфигурации
ChunkingConfig (Конфигурация разбиения на блоки)
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
chunk_size | int | Обязательно | Размер блока (в символах) |
chunk_overlap | int | - | Перекрытие соседних блоков |
separators | []string | - | Список разделителей |
parser_engine_rules | []ParserEngineRule | - | Движок анализа по типу файла: {file_types, engine, xlsx_first_row_as_header?} |
enable_parent_child | bool | false | Включить стратегию родительских и дочерних блоков |
parent_chunk_size | int | 4096 | Размер родительского блока (для возврата контекста) |
child_chunk_size | int | 384 | Размер дочернего блока (для эмбеддинга и поиска) |
strategy | string | Пусто (= legacy) | Стратегия разбиения: legacy (историческое рекурсивное разбиение) / auto (автоматический выбор слоя профайлером) / heading / heuristic / recursive (фиксированный слой), подробнее в Механизм разбиения |
token_limit | int | 0 | Лимит токенов (0 = без ограничений) |
languages | []string | Автоопределение | Подсказка языка |
table_metadata_instructions | string | - | Инструкции для генерации метаданных таблиц |
IndexingStrategy (Переключатели конвейера индексации)
| Поле | По умолчанию | Описание |
|---|---|---|
vector_enabled | true | Семантический векторный поиск |
keyword_enabled | true | Поиск по ключевым словам (BM25) |
wiki_enabled | false | Генерация страниц Wiki |
graph_enabled | false | Извлечение графа знаний |
Мультимодальные и обогащающие конфигурации
VLMConfig (Визуально-языковая модель):
| Поле | Описание |
|---|---|
enabled / model_id | Новая версия: переключатель включения + ID модели |
description_language | Язык описания изображений (пусто = соответствует языку документа) |
custom_instructions | Инструкции по интерпретации изображений на уровне базы знаний |
model_name / base_url / api_key / interface_type | Поля совместимости со старыми версиями (ollama / openai) |
Определение включения: Enabled && ModelID != "" или для старых версий ModelName != "" && BaseURL != "".
ASRConfig: enabled / model_id / language (подсказка языка, опционально).
ImageProcessingConfig (Наблюдение атрибутов изображений, условный OCR и векторы изображений):
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
model_id | string | - | ID VLM-модели, используемой для понимания изображений (участвует в отслеживании использования моделей) |
image_attrs_enabled | bool | false | Переключатель конвейера наблюдения атрибутов изображений. Отключено (по умолчанию) = историческое поведение: для каждого изображения отправляется отдельный запрос на описание и OCR, наблюдение атрибутов не производится; включено — первый раунд «наблюдение атрибутов + описание», затем чистая функция кода решает, стоит ли запускать второй раунд OCR на основе результатов наблюдения |
image_actions | object | см. ниже | Условия срабатывания OCR: { ocr: { on: ImageAttrCondition[], on_unobserved: bool } }. on — список условий «атрибут=значение»; on_unobserved — консервативная страховка при отсутствии наблюдения атрибутов моделью (по умолчанию true = OCR выполняется) |
image_vector_enabled | bool | false | Переключатель векторов изображений. При включении и способной обрабатывать изображения векторной модели (возможность «вход изображение» у модели) после генерации описания изображения векторная модель напрямую кодирует картинку и сохраняет одну векторную запись изображения, которая затем участвует в поиске; см. раздел «Векторы изображений» ниже |
После включения image_attrs_enabled модель больше не классифицирует изображения, а только «наблюдает» атрибуты по пунктам и выдает описание. На текущем этапе активированы два пункта наблюдения (полный реестр см. в GET /api/v1/image-attrs/schema, только для чтения, требуется роль Viewer; реестр глобальный и не меняется от базы знаний):
| Атрибут | Значение | Значение |
|---|---|---|
contain.text | none / sparse / block | Плотность текстовых блоков на изображении. block = основной текст, заслуживающий OCR |
contain.data_visual | true / false | Наличие диаграмм / визуализации данных (метки осей и т.д. также могут содержать текст) |
Решение об OCR принимается чистой функцией кода DecideOCR (internal/application/service/image_attr_decision.go), не сохраняется в базе:
- Выполняется
contain.text == blockилиcontain.data_visual == true→ запускается OCR; - Если атрибуты в считанной стратегии отсутствуют (модель пропустила ответ или дала недопустимое значение) → используется страховка
on_unobserved(по умолчанию OCR выполняется); - Если все атрибуты наблюдаемы и ни один не сработал → OCR пропускается.
Если модель отвечает не по теме или атрибуты отсутствуют, применяется стратегия on_unobserved (по умолчанию OCR продолжается); при значении false изображения без наблюдавшихся атрибутов тоже будут пропускать OCR. Полный результат наблюдения с негативными значениями может привести к пропуску OCR, поэтому результаты 판단а модели и распознавания текста по-прежнему нуждаются в выборочной проверке. Обратите внимание, что отсутствие ключа атрибута является нормальным результатом: при неудаче наблюдения консервативные значения по умолчанию не записываются (версия схемы attrs/2), поэтому image_attrs может быть пустым объектом, и читающая сторона должна различать «не наблюдалось» и «наблюдалось отрицательное значение».
Конвейер и результаты наблюдения записываются в дочерний span траектории обработки каждого изображения для облегчения сверки и устранения неполадок: input pipeline = observation_driven (этот переключатель включен) или caption_ocr (отключен, историческое поведение); output attr_policy (решение об OCR в этом раунде), image_attrs (наблюдаемые атрибуты), ocr_skipped (attr_policy = пропущено стратегией / disabled = главный выключатель OCR выключен), observation_failed (эффективное наблюдение не сформировано), chunks_created.
Перед добавлением в базу OCR отклоняет пустые ответы, содержимое, состоящее только из разделителей, и длинные повторяющиеся строки, занимающие основную часть вывода; обычные короткие метки, числа и таблицы при этом сохраняются. Если OpenAI-совместимая VLM возвращает finish_reason=length, непустой усечённый вывод тоже считается сбоем. Обычный промпт для изображения требует транскрибации видимого текста, кнопки и подписи на скриншоте выводятся построчно, и только настоящие таблицы оформляются в Markdown; для сканированных PDF используется отдельный промпт с макетом документа.
Каждый запуск OCR создаёт отдельный дочерний span обработки multimodal.image[i].ocr; в Langfuse он отображается как image.ocr и содержит вызов модели и проверку вывода. При сбое фиксируются ocr_status=failed, ocr_error_code (OCR_INVALID_OUTPUT / OCR_TRUNCATED / OCR_REQUEST_FAILED) и причина ошибки, а чанк этого OCR не создаётся и не индексируется. Корректное описание изображения при этом сохраняется, а output всей картинки помечается outcome=partial_failure как частичный сбой — задача по изображению целиком из-за недействительного OCR не перезапускается. Явный ответ «текста нет» записывается как ocr_status=no_text и отличается от аномалии; успешное распознавание — succeeded. Уже созданные аномальные чанки автоматически не удаляются — соответствующий документ нужно разобрать заново.
Через WEKNORA_OCR_TEST_FIXTURE можно указать локальный JSON-файл ({"model": <конфигурация модели>, "image_paths": [<локальный путь к изображению>]}) и запустить go test ./internal/application/service -run '^TestLiveImageOCRValidation$' -v -count=1, чтобы проверить работу на реальной модели. Для частных endpoint'ов требуется SSRF_WHITELIST. Тест использует in-memory репозиторий чанков и не пишет в рабочую БД; конфигурации с учётными данными и оригиналы изображений следует хранить вне системы контроля версий.
При разовой загрузке или повторном анализе можно переопределить image_attrs_enabled и image_actions для документа в process_config (KnowledgeProcessOverrides) тела запроса; не переданные элементы наследуются из настроек базы знаний. image_actions объединяются по ключу действия (on заменяется целиком). Поля интерфейса см. в API базы знаний, детали конвейера см. в Анализ документов.
Векторы изображений (image_vector_enabled): по умолчанию выключены, и после обновления существующие базы знаний остаются с выключенным значением (в сохранённой конфигурации базы этого ключа нет, поэтому при чтении получается false); включить их нужно явно в настройках базы знаний «Конфигурация обработки изображений → Поиск по векторам изображений» (раздел появляется после включения мультимодальности) или через API. Функция действует только когда переключатель включён и векторная модель умеет обрабатывать изображения — при выполнении лишь одного условия векторы изображений не создаются при загрузке и не возвращаются при поиске. Автоматического включения по возможностям модели намеренно нет: модель с поддержкой изображений нередко используется только для кодирования текста, и автоматическое включение добавило бы таким базам лишний векторный вызов на каждую картинку и изменило поведение поиска — после включения пула кандидатов документного векторного поиска увеличивается в 1.5 раза, а попадания изображений фильтруются отдельным порогом min(VectorThreshold, 0.1).
- векторы изображений создаются в рамках мультимодальной задачи, поэтому мультимодальность (VLM) тоже должна быть включена:
Contentвектора изображения переиспользует описание изображения (а при его отсутствии — текст OCR); страницы сканированных PDF не получают векторов изображений; - переключатель влияет только на документы, загружаемые или разбираемые заново после его включения; чтобы дополнить векторами изображений уже существующие документы, их нужно разобрать повторно;
- при выключении уже созданные векторы изображений (созданные до выключения или привнесённые документом, переехавшим из базы с включёнными векторами изображений) вместе со своими чанками сохраняются, но при поиске всегда отбрасываются и больше не возвращаются; удаляются вместе с документом при удалении / повторном разборе документа и при удалении базы знаний; после повторного включения сохранённые векторы изображений снова участвуют в поиске. Копирование документа в базу без включённых векторов изображений векторы изображений не переносит;
- при совместном поиске по нескольким базам решение принимается по переключателю каждой базы: в базах с выключенными векторами изображений они не возвращаются;
- поисковый движок не умеет фильтровать по типу источника, поэтому невозвращаемые строки изображений (попадания векторов изображений из баз без включения и любые строки изображений из поиска по ключевым словам) можно отбросить только после возврата результатов. Чтобы они не заняли весь пул кандидатов и не вытеснили текст, при заполнении документного векторного или ключеслового пула такими строками TopK удваивается и поиск повторяется, пока не наберётся достаточно не требующих отсечения кандидатов (текстовые попадания и попадания изображений из баз с включёнными векторами изображений), не исчерпается индекс или не будет достигнут предел в 500 кандидатов (для пула в 50 строк — не более 4 дополнительных запросов на пул). Поэтому в группах store со строками изображений может добавиться несколько поисковых запросов; если строк изображений впереди текста больше примерно 500, текстовые попадания всё равно могут быть пропущены. При сбое или частичном ответе повторной выборки сохраняются полные результаты предыдущего раунда.
QuestionGenerationConfig (Генерация вопросов): enabled; question_count количество генерируемых вопросов на блок (по умолчанию 3, максимум 10); custom_instructions описание целевой аудитории / стиля.
ExtractConfig (Граф знаний): enabled, text, tags, nodes []*GraphNode{name, chunks, attributes}, relations []*GraphRelation{node1, node2, type}, custom_instructions (руководство по извлечению в доменной области).
FAQConfig (Только для базы FAQ): index_mode (question_only / question_answer, по умолчанию последний), question_index_mode (combined / separate, по умолчанию combined), подробнее в главе FAQ.
WikiConfig (База знаний с включенным indexing_strategy.wiki_enabled) — обратите внимание, это не только для type = "wiki": после включения индекса Wiki в обычной базе документов UpdateKnowledgeBase автоматически создаст для нее пустой WikiConfig с этими настраиваемыми параметрами:
| Поле | По умолчанию | Описание |
|---|---|---|
synthesis_model_id | - | LLM для генерации Wiki |
max_pages_per_ingest | 0 (без ограничений) | Макс. количество создаваемых/обновляемых страниц за один прием |
extraction_granularity | standard | focused (только основные темы) / standard / exhaustive (все сущности и концепции) |
content_instructions / extraction_instructions | - | Руководство по стилю генерации и извлечения |
ingest_batch_size / ingest_map_parallel / ingest_reduce_parallel / ingest_max_inflight | 5 / 10 / 10 / 4 | Параметры параллелизма приема |
Все поля типа custom_instructions при обновлении проверяются на длину и валидность через validateKnowledgeBasePromptInstructions (internal/handler/knowledgebase.go).
Конфигурация хранилища
- StorageProviderConfig (новое):
provider ∈ {local, minio, cos, tos, s3, oss, ks3, obs}; - StorageBackendID: привязка к конкретному экземпляру бэкенда хранилища;
- StorageConfig (устаревший столбец
cos_config):secret_id / secret_key / region / bucket_name / app_id / path_prefix / provider / endpoint / use_ssl / force_path_style.
Вычисляемые поля KB
В ответе списка / деталей прилагаются: knowledge_count (без учета удаляемых документов, соответствует списку документов), chunk_count, is_processing (база FAQ), processing_count (количество обрабатываемых элементов знаний в базе документов), share_count (количество организаций, с которыми предоставлен доступ), creator_name, is_pinned / pinned_at (статус закрепления текущим пользователем).
Также имеется поле хранилища is_temporary: помечает временные (ephemeral) базы знаний, которые не отображаются в обычном списке. Оно используется системой внутренне, типичный сценарий — кэширование веб-страниц, захваченных при поиске в сети, как контента, доступного для поиска. Ручное создание не порождает временные базы.
Автоматические теги
Включите автоматические теги в настройках тегов базы документов, подготовьте теги-кандидаты и выберите модель чата. После завершения анализа система асинхронно выбирает подходящие варианты из существующих тегов, новые теги не создаются. auto_tag_config применимо только к типу document:
| Поле | По умолчанию | Описание |
|---|---|---|
| enabled | false | Включить автоматические теги |
| model_id | Пусто | Если пусто, используется summary_model_id базы знаний |
| max_tags | 3 | Максимальное количество автоматических ассоциаций на документ, лимит 10 |
| skip_if_tagged | true | Пропускать, если теги уже есть (включая добавленные вручную или из источника данных); false — добавлять инкрементно |
Конфигурация вступает в силу только для вновь проанализированных или повторно анализируемых документов и не заполняет исторические документы автоматически. Ошибки модели не блокируют завершение обработки документа, асинхронные задачи повторяются согласно стратегии очереди. Теги-кандидаты берутся из первых 500 тегов базы знаний; автоматическая ассоциация не удаляет теги, добавленные вручную. Добавление тегов источником данных по имени источника — это другой механизм.
AI-генерация описания базы знаний
У базы знаний есть два описания: description — написанное пользователем «для чего эта база», и generated_profile — выведенное системой из профиля документов «что на самом деле в этой базе». Они не перекрывают друг друга, агент при работе читает оба одновременно, чтобы решить, в какой из привязанных баз знаний выполнять поиск по вопросу.
Генерация делится на три уровня, только последний вызывает модель:
- Профиль документа: задача аннотации документа при генерации краткой аннотации выводит структурированный профиль (
knowledges.profile): суть в одном предложении (gist), 3–5 ключевых слов, тип документа, типичный вопрос. Он существует вместе с документом и исчезает при его удалении. - Агрегация базы знаний: чистая статистика базы данных — количество документов, типы файлов, счетчики тегов, счетчики ключевых слов (нормализация регистра и пунктуации), счетчики типов документов, типичные вопросы из выборки по темам, заголовки из равномерной выборки, а также вычисление хеша входных данных. Удаление, перемещение, повторный анализ не требуют специальной обработки, пересчет дает точный результат.
- Текст описания: агрегация (одна-две тысячи токенов, не зависит от количества документов) передается модели для получения сути (gist), объединенного списка тем и 3–5 типичных вопросов. Если хеш агрегации не изменился, вызов модели пропускается.
profile_config применимо только к типу document:
| Поле | По умолчанию | Описание |
|---|---|---|
| enabled | false | Автоматическое обновление при добавлении/удалении документов или обновлении аннотации (защита от дребезга 30 сек, запускается один раз для одного окна) |
| model_id | Пусто | Если пусто, используется summary_model_id базы знаний |
| custom_instructions | Пусто | Дополнительные требования, добавляемые к системному промпту (например, ориентация на читателя, необходимость сохранения терминов) |
Независимо от включения автообновления, на странице настроек базы знаний можно нажать «Сгенерировать AI-описание» для разовой генерации и одним кликом принять gist в качестве описания, написанного вручную. generated_profile.status может быть ready/empty (нет проанализированных документов, модель не вызывается)/failed (сохраняется предыдущий текст и записывается ошибка). Загрузки с отключенной аннотацией документа учитывают только заголовок, тип и теги, не учитывая ключевые слова.
Управление знаниями (Knowledge)
Ключевые моменты модели
internal/types/knowledge.go. Ключевые поля: type (manual ручной Markdown / faq / тип файла), source / channel (канал приема), parse_status, summary_status, enable_status, file_name/type/size/hash/path, storage_size, metadata (JSON, для ручных знаний хранится ManualKnowledgeMetadata{content, format, status(draft/publish), version}), custom_metadata (JSON, настраиваемые метаданные пользователя), last_faq_import_result.
custom_metadata хранит поддерживаемые пользователем описательные поля, такие как отдел, уровень секретности, номер версии; metadata хранит внутренние состояния и ID процесса обработки. Настраиваемых метаданных может быть до 20, ключи длиной 1–64 символа, значения поддерживают строку, число, булево значение или null, длина не более 1000 символов. Изменение инициирует автоматическое обновление аннотации.
В реализации Knowledge.CustomMetadataText() генерирует текст ключ: значение, отсортированный по ключам, для использования при генерации аннотации и в контексте модели уровня документа. Поля введены миграцией 000078.
Константы каналов приема: web, api, browser_extension, wechat, wecom, feishu, feishu_drive, lark_drive, dingtalk, slack, im, notion, confluence, yuque, rss, ima.
Конечный автомат статусов анализа:
Сбой отдельной дочерней задачи обогащения (аннотация, генерация вопросов, граф, Wiki) не переводит документ в failed, документ переходит в completed после завершения всех дочерних задач. Документы, зависшие в pending, processing, finalizing или deleting, очищаются фоновой проверкой, см. Система асинхронных задач.
Независимый статус аннотации: summary_status ∈ {none, pending, processing, completed, failed}.
Маршрутизация знаний
| Метод | Путь | Описание | Контроль доступа |
|---|---|---|---|
| POST | /knowledge-bases/:id/knowledge/file | Загрузка файла | OwnedKBOrAdmin + KBAccessWrite |
| POST | /knowledge-bases/:id/knowledge/url | Импорт URL | То же самое |
| POST | /knowledge-bases/:id/knowledge/manual | Знание в ручном Markdown | То же самое |
| GET | /knowledge-bases/:id/knowledge | Список (пагинация + фильтрация + сортировка) | Viewer+ + KBAccessRead |
| POST | /knowledge-bases/:id/knowledge/batch-download | Массовая загрузка исходных файлов (ZIP) | Contributor+ + KBAccessWrite |
| GET / PUT | /knowledge-bases/:id/knowledge/folders | Дерево папок / Переименование или перемещение папки | Viewer+ + KBAccessRead / OwnedKBOrAdmin + KBAccessWrite |
| DELETE | /knowledge-bases/:id/knowledge | Очистка содержимого KB | Admin + KBAccessWrite |
| GET | /knowledge/:id, /knowledge/batch | Детали / Массовое получение | Viewer+ |
| GET | /knowledge/:id/stages, /knowledge/:id/spans | Этапы обработки / Отрезки (spans) | Viewer+ |
| PUT / DELETE | /knowledge/:id, /knowledge/manual/:id | Обновление (включая custom_metadata) / Удаление | OwnedKnowledgeKBOrAdmin + KBAccessWrite |
| POST | /knowledge/:id/reparse, /knowledge/:id/cancel-parse | Повторный анализ / Отмена анализа | То же самое |
| POST | /knowledge/:id/regenerate-summary | Повторная генерация аннотации документа | То же самое |
| GET | /knowledge/:id/download | Загрузка исходного файла | Contributor+ + KBAccessWrite |
| GET | /knowledge/:id/preview | Предварительный просмотр файла | Viewer+ + KBAccessRead |
| PUT | /knowledge/tags | Массовое обновление тегов | Contributor+ / ingest |
| POST | /knowledge/batch-reparse, /knowledge/batch-delete | Массовый повторный анализ / Удаление | Contributor+ / ingest |
| POST | /knowledge/folder | Помещение документа в папку | Contributor+ / ingest |
| POST | /knowledge/move | Перемещение знания | Contributor+ / ingest |
| GET | /knowledge/move/progress/:task_id | Прогресс перемещения | Viewer+ |
Параметры фильтрации списка
KnowledgeListFilter в internal/types/knowledge.go + internal/handler/knowledge.go:
| Параметр | Описание |
|---|---|
page / page_size | Пагинация (по умолчанию 1 / 20) |
sort_by / sort_order | Сортировка: updated_at / created_at / file_name, asc / desc; по умолчанию created_at desc |
keyword | Поиск по имени файла / заголовку |
file_type | Фильтр по типу файла (pdf / manual / url …) |
parse_status | Фильтр по статусу анализа |
source | Фильтр по каналу приема (api / web / feishu …) |
tag_ids | Фильтр по тегам, несколько через запятую (семантика OR) |
start_time / end_time | Диапазон времени обновления (RFC3339) |
folder_path | Фильтр по папке. Наличие этого параметра определяет режим списка: отсутствие — плоский вид всей базы, пустая строка — корневой каталог базы знаний (без подкаталогов) |
folder_recursive | Используется вместе с folder_path, при true возвращаются также документы из подкаталогов |
Дерево папок
Папки используются для организации документов по проектам, источникам или уровням каталогов, поддерживают сохранение структуры при загрузке, а также переименование и перемещение после добавления.
Операции с папками:
- Загрузка всего каталога: структура каталогов сохраняется как есть, не требуется создавать папки вручную после загрузки;
- Создание / Переименование / Перемещение папки: операции в дереве папок слева от списка документов. Переименование меняет путь вместе с подкаталогами; при совпадении целевого пути папки объединяются; не допускается перемещение папки в собственный подкаталог;
- Переклассификация документов: перемещение выбранных документов в указанную папку (можно вернуть в корень). Это меняет только классификацию, не требует повторного анализа и не влияет на индекс;
- Просмотр по каталогам:
folder_pathв интерфейсе списка определяет режим отображения — отсутствие параметра дает плоский список всей базы, пустая строка — корневой каталог (без подкаталогов), в сочетании сfolder_recursive=trueвыводит список вместе с подкаталогами.
Папки и теги решают разные задачи и могут использоваться совместно: папка — это уникальная принадлежность (документ находится только в одном каталоге, подходит для архивации по проектам/источникам), теги — это связь «многие ко многим» (документ может иметь несколько тегов, подходит для перекрестной фильтрации по темам, секретности, статусу). При поиске оба могут выступать условиями ограничения области.
Путь каталога хранится в knowledges.folder_path, в file_name хранится только имя файла. Миграция 000079 восстановила пути каталогов из исторических имен файлов.
Интерфейсы папок: GET/PUT /knowledge-bases/:id/knowledge/folders и POST /knowledge/folder, подробнее см. в API базы знаний.
Теги (KnowledgeTag)
internal/types/tag.go + internal/handler/tag.go:
type KnowledgeTag struct {
ID string // UUID
SeqID int64 // Автоинкрементный целочисленный ID (для API)
TenantID uint64
KnowledgeBaseID string
Name string // Уникально внутри KB
Color string
SortOrder int
}
type KnowledgeTagRelation struct { KnowledgeID, TagID string } // Многие ко многимОдин документ может иметь несколько тегов. Ранее использовался один тег (knowledges.tag_id), миграция 000063 заменила его на таблицу связей knowledge_tag_relations: при создании таблицы старые данные о тегах были перенесены, а столбец knowledges.tag_id был удален. Таким образом, сейчас:
- Чтение:
Knowledge.Tagsполучается через массовый JOIN поknowledge_idпри запросе (gorm:"-", не находится в таблице knowledges); - Запись: семантика полной замены —
PUT /knowledge/tagsпередает{knowledge_id: [tag_ids]}, реализация сначала удаляет все связи документа, затем записывает новый набор; - Фильтрация:
tag_idsимеет семантику OR (возвращается при попадании в любой тег), SQL выполняетknowledges.id IN (SELECT knowledge_id FROM knowledge_tag_relations WHERE tag_id IN (...)); - Для элементов FAQ все иначе: они сами являются блоками (chunks), тег хранится в
chunks.tag_id(один тег), это другой путь, отличный от таблицы связей документов.
Маршруты управления самими тегами: GET /knowledge-bases/:id/tags (Viewer+), POST (OwnedKBOrAdmin), PUT/DELETE /knowledge-bases/:id/tags/:tag_id (OwnedKBOrAdmin); параметр пути tag_id принимает как UUID, так и целочисленный seq_id.
Две точки входа на фронтенде:
- Массовое присвоение тегов: после выбора нескольких документов в списке кнопка «Теги» в панели массовых операций открывает
BatchTagDialog.vue. Диалоговое окно предварительно выбирает теги, общие для выбранных документов, поддерживает поиск и прямой переход к управлению тегами, обновляет список после отправки; - Установка тегов при загрузке: диалоговое окно подтверждения загрузки (
UploadConfirmDialog.vue) позволяет указать теги и параметры анализа непосредственно перед добавлением файлов, избавляя от необходимости изменять их после загрузки.
Редактирование блоков и история версий
В деталях документа можно редактировать текст блоков, исправляя ошибки анализа OCR, таблиц или формул. После сохранения индекс будет перестроен, а история версий сохранена для просмотра и отката.
Реализация (internal/application/service/chunk.go, миграция 000078):
Модель данных:
| Поле / Таблица | Роль |
|---|---|
chunks.source_content | Исходный вывод анализатора, неизменяемо. Не записывается при создании блока, лениво заполняется из content при первом ручном редактировании |
chunks.content | Текущий активный контент (используется для поиска и отображения цитат) |
chunks.content_revision | Увеличивается на 1 при каждом редактировании или откате, используется как оптимистичная блокировка |
chunks.index_status | ready / processing / failed, указывает, отражен ли текущий контент в поисковом хранилище |
chunks.last_editor_id | Исполнитель, создавший текущую версию |
Таблица chunk_revisions | Снимки перезаписанных исторических версий (контент, статус включения, редактор, источник, время) |
Ключевые моменты поведения:
- Редактируемы только блоки типа
text; контент после удаления пробелов не может быть пустым, лимит 200 000 байт; - Оптимистичный параллелизм: запрос может содержать
expected_revision, при несоответствии текущей версии возвращается 409, фронтенд предлагает обновить страницу; - Нельзя добавлять новые изображения: вставка URL изображений, отсутствующих в исходном контенте, будет отклонена; при удалении ссылки Markdown на изображение соответствующий дочерний блок OCR / caption деактивируется, а не удаляется физически, что позволяет повторно активировать их при откате версии;
- Согласованность родительских и дочерних блоков: после редактирования дочернего блока изменения накладываются на родительский блок по смещению (поле
source_contentродительского блока остается неизменным, замены применяются в обратном порядке, изменение длины не нарушает систему координат); - Обработка сбоев индексации: при сбое перестроения индекса строка сохраняется как обычно, но
index_status = failed, на интерфейсе отображается подсказка; повторная отправка того же контента инициирует повторную попытку; - Сохранение сгенерированных вопросов: после редактирования контента исходные поисковые вопросы сохраняются, но помечаются как «не соответствующие текущей версии текста», их можно переписать по одному (
PUT /chunks/by-id/:id/questions) или перегенерировать целиком (POST /chunks/by-id/:id/questions/regenerate); - Связь с аннотацией: изменение контента или статуса включения ставит задачу обновления аннотации документа в очередь,
summary_statusпереходит вpending; также можно запустить вручную черезPOST /knowledge/:id/regenerate-summary.
Откат (POST /chunks/:knowledge_id/:id/revert) сам по себе является новым редактированием: контент целевой исторической версии записывается как текущий, номер версии продолжает расти, а старый контент попадает в список истории, поэтому «откат отката» также возможен.
Список интерфейсов см. в Справочник API: Блоки и теги.
Ручное редактирование аннотации и просмотр блоков
В режиме предварительного просмотра документа можно отредактировать аннотацию и сохранить ее для исправления автоматической аннотации. Если в PUT /knowledge/:id пропущено description, аннотация сохраняется, явная пустая строка — очищает; обновление аннотации не эквивалентно изменению исходного содержимого документа. При необходимости повторной генерации используйте «Перегенерировать аннотацию», изменение контента/метаданных также может спровоцировать обновление.
Блоки документа загружаются постранично, переключение документов и переходы из поиска обновляют состояние пагинации. Полный список полей см. в API знаний и API блоков.
Безопасность загрузки и предварительного просмотра
Механизм безопасности GET /knowledge/:id/preview подтверждается тестом internal/handler/knowledge_preview_security_test.go:
| Контроль | Реализация | Цель |
|---|---|---|
Установка Content-Type по расширению | PDF, изображения, текст и т.д. открываются для просмотра встроенными средствами; типы, которые могут быть исполнены браузером (HTML, SVG, XML, JS, CSS), принудительно получают application/octet-stream | Предотвращение исполнения загруженного контента браузером как страницы (защита от хранимого XSS) |
X-Content-Type-Options: nosniff | Заголовок ответа | Запрет обхода через MIME-сниффинг |
Content-Disposition | attachment для исполняемых типов, inline для остальных | Опасные типы можно только скачать, нельзя рендерить в браузере |
| Проверка пути | ValidateKBScopedStoragePath() | Путь к файлу должен находиться в пределах разрешенного хранилища этого KB (защита от path traversal / несанкционированного чтения) |
| Ограничение размера | Ограничение в теле ответа GetFile | Предотвращение сбоев предварительного просмотра из-за слишком больших файлов |
Тестовые сценарии явно подтверждают: даже если файл HTML содержит <script>alert(1)</script>, он будет передан только как двоичное вложение. Эндпоинты загрузки (/knowledge/:id/download и массовая загрузка /knowledge-bases/:id/knowledge/batch-download) требуют уровня Contributor+ и проходят через контроль доступа KBAccessWrite.
Предварительный просмотр возвращает сам исходный файл, он также доступен при доступе через общий доступ только для чтения (viewer в организации, видимость через общего агента). Ограничение «Загрузка только для Editor и выше» является продуктовым ограничением удобства, а не границей контроля доступа: любой, кто может читать KB, может получить исходные файлы из него.
Копирование базы знаний и перемещение знаний
Копирование (Copy / Duplicate) и Preflight
internal/application/service/knowledge_clone_move.go, правила preflight зафиксированы в internal/handler/knowledgebase_copy_preflight_test.go:
POST /knowledge-bases/copy: копирование всей базы (конфигурация + контент), в теле передаетсяsource_id; асинхронная задача, прогресс проверяется черезGET /knowledge-bases/copy/progress/:task_id(в потоке активности фиксируетсяkb.clone_started/kb.clone_completed/kb.clone_failed).POST /knowledge-bases/:id/duplicate: копирование только конфигурации (без копирования контента / индекса / записей о доступе), в потоке активности фиксируетсяkb.duplicated.
Preflight (проверка перед копированием, немедленный синхронный отказ):
- Изоляция тенантов для исходной / целевой KB (отказ при разных тенантах);
- Существование исходной KB;
- Совместимость VectorStore: режим
reuse_vectorsне поддерживает KB в разных векторных базах (векторы нельзя переместить напрямую); - Совместимость StorageBackend: копирование между разными бэкендами хранилища не поддерживается;
- При вызове через API-ключ обе KB (исходная и целевая) должны быть в allow-list.
Контроль перемещения знаний (move gate)
POST /knowledge/move поддерживает два режима, ограничения проверяются на уровне обработчика и сервиса (подтверждено тестами internal/handler/knowledge_move_gate_test.go и internal/application/service/knowledge_move_gate_test.go):
- Режим
reuse_vectors: прямое повторное использование существующих векторов, требует, чтобы исходная и целевая KB были привязаны к одному VectorStore; - Режим
reparse: целевая база заново анализируется для генерации векторов, допускает перемещение между разными векторными базами.
Семантика определения принадлежности к одной базе SharesStoreWith() (нормализация пустой строки в nil, nil означает хранилище по умолчанию в окружении):
nil & nil → true (оба env-store)
"" & nil → true (пустая строка нормализуется в nil)
"store-a" & "store-a" → true
"store-a" & "store-b" → false
"store-a" & nil → false (явная привязка vs env-store не считаются одной базой)GET /knowledge-bases/:id/move-targets возвращает подходящие целевые базы; перемещение является асинхронной задачей, прогресс проверяется через GET /knowledge/move/progress/:task_id.
Квоты хранилища и использование
Квоты привязаны к тенанту (internal/types/tenant.go):
| Поле | По умолчанию | Описание |
|---|---|---|
storage_quota | 10737418240 (10GB) | Общая квота тенанта |
storage_used | 0 | Использованный объем (включает исходные файлы, текст, векторы и индексы) |
Перед созданием KB и загрузкой знаний выполняется проверка квоты (цепочка проверок в internal/handler/knowledgebase.go), при превышении в записи отказывается; каждый элемент знания записывает свои file_size и storage_size, при удалении объем высвобождается.
Маршруты и права KB
(Семантика контроля доступа см. в главе «Тенанты, пользователи и аутентификация/авторизация»; KBAccessRead/Write разрешает пути общего доступа организации.)
| Метод | Путь | Обработчик | Контроль доступа |
|---|---|---|---|
| POST | /knowledge-bases | CreateKnowledgeBase | Contributor+ / API-ключ manage_kbs |
| GET | /knowledge-bases | ListKnowledgeBases | Viewer+ / retrieve |
| GET | /knowledge-bases/:id | GetKnowledgeBase | Viewer+ + KBAccessRead |
| PUT | /knowledge-bases/:id | UpdateKnowledgeBase | OwnedKBOrAdmin + KBAccessWrite |
| DELETE | /knowledge-bases/:id | DeleteKnowledgeBase | OwnedKBOrAdmin + KBAccessWrite |
| PUT | /knowledge-bases/:id/pin | TogglePinKnowledgeBase | Viewer+ + KBAccessRead |
| POST/GET | /knowledge-bases/:id/hybrid-search | HybridSearch | Viewer+ + KBAccessRead |
| POST | /knowledge-bases/copy | CopyKnowledgeBase | Contributor+ / manage_kbs |
| POST | /knowledge-bases/:id/duplicate | DuplicateKnowledgeBase | Contributor+ / manage_kbs + KBAccessRead |
| POST | /knowledge-bases/:id/profile/generate | GenerateKnowledgeBaseProfile | OwnedKBOrAdmin + KBAccessWrite / manage_kbs |
| GET | /knowledge-bases/copy/progress/:task_id | GetKBCloneProgress | Viewer+ / retrieve или manage_kbs |
| GET | /knowledge-bases/:id/move-targets | ListMoveTargets | Viewer+ + KBAccessRead |
| GET | /knowledge-bases/:id/activity | ListKnowledgeBaseActivity | OwnedKBOrAdmin + KBAccessRead (только JWT) |
Процесс создания (internal/handler/knowledgebase.go): Проверка Contributor → Проверка квоты хранилища тенанта → Проверка EmbeddingModelID → Проверка привязки VectorStoreID → Создание → Возврат KB + vector_store_display.
Каскадное удаление: Удаление всех Knowledge в KB → Chunk → Векторный индекс → Индекс ключевых слов → Страницы Wiki → Теги → Файлы в хранилище → Мягкое удаление самой KB. Редактор (editor) со стороны общего доступа не может удалить исходную KB (для удаления требуются права владельца тенанта + права администратора).
Гибридный поиск (Hybrid Search)
POST /knowledge-bases/:id/hybrid-search (internal/handler/knowledgebase.go + internal/application/service/knowledgebase_search*.go) комбинирует выдачу согласно IndexingStrategy базы знаний: векторы (vector_enabled) + ключевые слова BM25 (keyword_enabled), проходит через объединение (rank fusion) и переранжирование (rerank), может дополняться графом знаний (graph_enabled); для нескольких KB используется параллельный запуск в knowledgebase_search_fanout.go и слияние в knowledgebase_search_fusion.go; путь поиска в общих KB см. в knowledgebase_search_shared.go. Поиск в базе FAQ имеет специальную стратегию попадания (фильтрация негативных примеров / итеративный поиск), см. главу FAQ.
Конвейер обработки знаний
internal/application/service/knowledge_create.go / knowledge_process.go / knowledge_process_config.go:
Загрузка (file/url/manual)
→ Создание Knowledge (parse_status=pending) → Постановка в очередь Asynq
→ Worker: DocReader анализ → Разбиение на блоки (ChunkingConfig)
→ Векторный эмбеддинг (indexing_strategy.vector_enabled)
→ Индекс ключевых слов (keyword_enabled)
→ Извлечение графа (graph_enabled + ExtractConfig)
→ Генерация Wiki (wiki_enabled + WikiConfig)
→ Генерация вопросов (QuestionGenerationConfig.enabled)
→ Аннотация документа (process_config.summary_enabled, включено по умолчанию)
→ parse_status=finalizing, pending_subtasks_count=N
→ Атомарное уменьшение счетчика после каждой дочерней задачи; при 0 → parse_status=completedПриоритет объединения конфигураций (EffectiveProcessConfig): Knowledge.ProcessOverrides (переопределение при разовой загрузке, хранится в KnowledgeProcessOverrides метаданных знания, может перекрывать правила анализатора / разбиение / VLM / ASR / генерацию вопросов / граф / аннотацию и т.д.) > Конфигурация KB > Значения тенанта по умолчанию.
Типы блоков Chunk (internal/types/chunk.go): text, parent_text, image_ocr, image_caption, summary, entity, relationship, faq, web_search, table_summary, table_column, wiki_page; блок поддерживает переключатель is_enabled и битовые флаги flags (bit0 = может быть рекомендован).
Поток активности базы знаний (KB Activity)
Вкладка «Активность» в настройках базы знаний фиксирует изменения конфигурации, загрузку и удаление документов, редактирование блоков, изменение прав доступа и обновления Wiki, включая исполнителя, время и результат.
internal/application/service/kb_activity.go использует систему аудита (AuditLog, область knowledge_base), записи через recordKBActivity(ctx, audit, tenantID, kbID, action, targetType, targetID, outcome, details):
- Действия активности (
internal/types/audit_log.go):kb.created/kb.updated/kb.deleted/kb.duplicated/kb.clone_started/kb.clone_completed/kb.clone_failed,kb.share_added/kb.share_permission_changed/kb.share_removed, а также действия на уровне знаний / блоков; - Источник триггера:
kbActivityTaskMetadata{TaskID, Trigger}из контекста (userдействие пользователя /systemфоновая задача) автоматически включается в детали; на основе outcome автоматически добавляетсяprocessing_status(accepted→pending, success→completed, partial→partial, failed/denied→failed, canceled→canceled); - Идентификация через API-ключ: вызов
X-API-Keyзаписываетdetails.api_key_id/details.api_key_name(снимок имени). На странице активности после основного инициатора дополнительно отображается имя ключа; операции JWT на веб-странице не содержат эти два поля. Асинхронные задачи сохраняют идентификатор ключа вTaskInitiator, но не восстанавливают область прав ключа в worker; - Заголовки образцов для массовых операций:
kbActivityAppendSampleTitlesдобавляет до 5 уникальных заголовков для массовых операций (первый какtitle, остальные в массивtitles), обеспечивая читаемость и ограниченность потока активности; - Механизм подавления:
withKBActivitySuppressed(ctx)позволяет внутренним каскадным операциям не создавать дублирующие записи активности.
Эндпоинт запроса: GET /knowledge-bases/:id/activity (OwnedKBOrAdmin, только для пользователей JWT, доступ по API-ключу запрещен).
Реализация
Все пути указаны относительно корня репозитория:
| Уровень | Файл |
|---|---|
| Модель KB и структура конфигурации | internal/types/knowledgebase.go, indexing_strategy.go |
| Модели Знание / Блок / Тег | internal/types/knowledge.go, chunk.go, tag.go |
| Переопределение конфигурации обработки | internal/types/knowledge_process.go |
| Обработчик KB | internal/handler/knowledgebase.go |
| Обработчик знаний | internal/handler/knowledge.go |
| Обработчик тегов | internal/handler/tag.go |
| Сервис KB | internal/application/service/knowledgebase.go |
| Создание знаний / конвейер обработки | internal/application/service/knowledge_create.go, knowledge_process.go, knowledge_process_config.go |
| Копирование и перемещение | internal/application/service/knowledge_clone_move.go |
| Поток активности | internal/application/service/kb_activity.go |
| Маршрутизация и контроль доступа | internal/router/routes_knowledge.go, internal/router/rbac.go |
| Ключевые тесты-подтверждения | internal/handler/knowledge_preview_security_test.go, knowledge_move_gate_test.go, knowledgebase_copy_preflight_test.go |
