Фисирую состояние
This commit is contained in:
@@ -42,7 +42,8 @@
|
||||
### Sections
|
||||
- `sections/summary.md`
|
||||
- `sections/details.md`
|
||||
- `sections/api-scenario.md`
|
||||
- `sections/tech-use-case.md`
|
||||
- `sections/fr.md`
|
||||
- `sections/api-contract.md`
|
||||
- `sections/requirements-format.md`
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
## Особые правила
|
||||
|
||||
- Во frontmatter обязательно указывать `endpoint` (например: `POST /api/v1/clients/contacts-dgr`).
|
||||
- Сценарий оформляется как технический use case.
|
||||
- Функциональные требования маркируются `FR-*`.
|
||||
- Нефункциональные требования маркируются `NFR-*`.
|
||||
|
||||
@@ -47,6 +47,7 @@ system_analytics_refs: []
|
||||
- `module` — модуль или подсистема.
|
||||
- `layer` — слой системы.
|
||||
- `updated_at` хранится в формате `YYYY-MM-DD`.
|
||||
- Для документов с `doc_type: api_method` поле `endpoint` является обязательным.
|
||||
|
||||
## Связи и навигация
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
# API Scenario Rules
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл описывает, как оформлять подраздел `### Сценарий` в API-документах.
|
||||
|
||||
## Обязательные части
|
||||
|
||||
- название
|
||||
- предусловия
|
||||
- триггер
|
||||
- основной сценарий
|
||||
- альтернативный сценарий
|
||||
- обработка ошибок
|
||||
- постусловие
|
||||
|
||||
## Правила
|
||||
|
||||
- Сценарий должен быть лаконичным.
|
||||
- Сценарий должен отражать суть шага.
|
||||
- Сложные технические детали надо выносить в `FR-*`.
|
||||
@@ -0,0 +1,37 @@
|
||||
# Functional requrements rules
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл описывает, как оформлять функциональные требования в подраздел `### Функциональные требования` в документах.
|
||||
|
||||
## Правила
|
||||
- Функциональное требование (FR) расширяет и дополняет шаги, описанные в сценарии.
|
||||
- Функциональное требование (FR) не должно копировать шаг сценария не неся дополнительной информации.
|
||||
- Название функционального требования формируется следующим образом - "FR.<номер>. <Название>", где
|
||||
- <номер> идет инкрементально внутри конкретного документа, начинается с 1.
|
||||
- <Название> - кратко описывает что делает требование, суть действий (от 3 до 7 слов)
|
||||
|
||||
|
||||
|
||||
## Пример целевого описания сценария
|
||||
|
||||
### Примеры названия FR
|
||||
- Получение данных клиента из АС ЕПК
|
||||
- Проверка уровня доступа
|
||||
- Сценарий построения списка связанных предложений
|
||||
|
||||
|
||||
### Примеры описания FR
|
||||
FR.1. Получение данных клиента из АС ЕПК
|
||||
1. Сформировать запрос к эндпоинту POST /api/v1/path/to/resourse в АС ЕПК
|
||||
- Заголовки
|
||||
- <тут идет описание заголовков и того как они формируются>
|
||||
- Параметры запроса
|
||||
- <тут идет описание параметров и того как они формируются>
|
||||
- Тело запроса
|
||||
- <тут идет описание структуры объекта JSON или payload в другмо формате так как это задано требованиями>
|
||||
|
||||
2. Обработать ответ от АС ЕПК
|
||||
Успешный ответ - <взять из описания вызываеого api критерии успешного ответа >
|
||||
Ничего не найдено - <взять из описания вызываеого api критерии успешного овтета, опционально (если применимо)>
|
||||
Ошибка - <взять из описания вызываеого api критерии успешного ответа >
|
||||
@@ -0,0 +1,66 @@
|
||||
# Scenario Rules
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл описывает, как оформлять технический USE CASE в подраздел `### Сценарий` в документах.
|
||||
|
||||
## Обязательные части
|
||||
|
||||
- название
|
||||
- предусловия
|
||||
- триггер
|
||||
- основной сценарий
|
||||
- альтернативный сценарий
|
||||
- обработка ошибок
|
||||
- постусловие
|
||||
|
||||
## Правила
|
||||
- Основной и альтернативные сценарии состоят из шагов.
|
||||
|
||||
- Каждый шаг описывается одним предложением не более 15-20 слов, и состоит из двух частей. Первая часть описывает что мы делаем по смыслу, чтобы это было понятно человеку без низкоуровневых технических деталей. Например: авторизует запрос, получает данные клиента, запрашивает справочники. Вторая часть описывает как это реализовано технически - вызывает эндпоинт /path/to/resource в системе <название системы>.
|
||||
|
||||
- В описании шага не должно быть длинных технических деталей. Если техничсекую реализацию нельхзя описатьодним предложенеим (в лимите длины описания шага), то необхлодимо это вынести в отдельное функциональное требование FR.<номер>. <Название> и описать в нем технические детали. А в шаге сослаться на это требование через "Описание приведено в FR.<номер>. <Название>"
|
||||
|
||||
- Для шагов авторизации обязателен доп шаг с описанием обработки ошибки.
|
||||
- Для шагов с интеграцией обязателен доп шаг с описанием обработки ошибки.
|
||||
- Для шагов с проверкой условий обязательны доп шаги с описанием переходов по сценарию.
|
||||
|
||||
- Название "FR.<номер>. <Название>" формируется следующим образом:
|
||||
- <номер> идет инкрементально внутри конкретного документа, начинается с 1.
|
||||
- <Название> - кратко описывает что делает требование, суть действий.
|
||||
|
||||
- Для каждого шага при необходимости нужно прописать логику действий в случае ошибки или если логика шага определяет несколько сценариев разивития при выполнении заданных условий.
|
||||
|
||||
- Для шагов, которые описывают интеграцию с другой системой необходимо указать название точки интеграции (название эндпоинта, название топика и так далее) и сделать ссылку на FR.<номер>. <Название> с описанием шагов интеграции - как сформировать запрос/сообщение, как обработать ответ, политику ретраев.
|
||||
|
||||
- Сценарий собирается из тезисов, приведенных системной аналимтике в свободной формулировке
|
||||
|
||||
- Функциональные требования "FR.<номер>. <Название>" не должны дублировать шагов сценария в use case. Они содержат детали, которые вынесены из юзкейса чтобы не делать его тяжелым. Если шаг юзкейса описывается одним предложением в лимите длины, то FR делать не нужно.
|
||||
|
||||
- FR обязательно описывается для шага с интеграцией
|
||||
- FR Не описывается для шага авторизации.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Пример целевого описания сценария
|
||||
|
||||
### Примеры шагов сценария
|
||||
|
||||
Пример 1
|
||||
- Авторизует запрос пользователя по наличию у него экшена ролевой модели CI02792632.ContactsDGR.Detail
|
||||
- В случае ошибки - завершить сценарий с кодом UNAUTHORIZED
|
||||
|
||||
Пример 2
|
||||
- Запрашивает данные клиента - вызывает /api/v1/clients/{client-id}/info
|
||||
- В случае ошибки - завершить сценарий с кодом CLIENT_INFO_REQUEST_FAIL
|
||||
|
||||
Пример 3
|
||||
- Возвращает ответ в формате <название DTO>
|
||||
|
||||
### Примеры названия FR
|
||||
- Получение данных клиента из АС ЕПК
|
||||
- Проверка уровня доступа
|
||||
- Сценарий построения списка связанных предложений
|
||||
@@ -8,6 +8,7 @@ module: example_module
|
||||
layer: application
|
||||
domain: example_domain
|
||||
sub_domain: example_subdomain
|
||||
endpoint: POST /api/v1/example
|
||||
related_docs: []
|
||||
status: draft
|
||||
updated_at: 2026-03-20
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# Documentation Rules V2
|
||||
|
||||
Этот каталог — новая структура правил для DOC_UPDATE/FROM_FEATURE.
|
||||
|
||||
## Цель
|
||||
|
||||
Разделить инструкции на 2 независимых блока:
|
||||
|
||||
1. `types/` — инструкции по структуре конкретных типов документов (`ui_page`, `api_method`, и т.д.).
|
||||
2. `common-elements/` — инструкции по структуре общих элементов страницы (`tech-use-case`, `fr`, и др.).
|
||||
|
||||
## Структура каталога
|
||||
|
||||
- `documentation-rules.md` — верхнеуровневые правила.
|
||||
- `global/` — общие правила оформления и frontmatter.
|
||||
- `types/` — правила по типам документов (вместо `artifact-types/`).
|
||||
- `common-elements/` — правила по общим секциям (вместо `sections/`).
|
||||
- `templates/` — шаблоны документов.
|
||||
|
||||
## Переключение профиля
|
||||
|
||||
Загрузчик поддерживает переключение через env:
|
||||
|
||||
- `DOC_RULES_PROFILE=v2` (по умолчанию) — использовать `doc_rules_v2`.
|
||||
- `DOC_RULES_PROFILE=legacy` — использовать старый каталог `doc_rules`.
|
||||
|
||||
Если `v2` не содержит валидных пар `type + template`, загрузчик автоматически fallback на `doc_rules`.
|
||||
@@ -0,0 +1,24 @@
|
||||
# API Contract Rules
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл описывает, как оформлять подраздел `## Контракт` в API-документах.
|
||||
|
||||
## Что должно быть описано
|
||||
|
||||
- входные параметры
|
||||
- выходные параметры
|
||||
- JSON-структуры запросов и ответов
|
||||
- обязательность полей
|
||||
- типы полей
|
||||
- ограничения
|
||||
- описание назначения полей
|
||||
- примеры данных
|
||||
- auth
|
||||
- idempotency
|
||||
- timeout
|
||||
- ошибки и их HTTP-коды
|
||||
|
||||
## Правило качества
|
||||
|
||||
Контракт должен быть достаточно формальным, чтобы по нему можно было собрать OpenAPI-спецификацию.
|
||||
@@ -0,0 +1,13 @@
|
||||
# Details Section Rules
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл задает общие правила для секции `## Details`.
|
||||
|
||||
## Правила
|
||||
|
||||
- `Details` оформляется как `## Details`.
|
||||
- Внутри `Details` используются заголовки уровня `###` и ниже.
|
||||
- Структура Details зависит от типа документа.
|
||||
- В Details не нужно повторно дублировать навигацию и связи, если они уже есть во frontmatter.
|
||||
- Интеграции, ошибки и кодовые привязки должны быть выделены в отдельные подразделы, если они существенны для понимания документа.
|
||||
@@ -0,0 +1,37 @@
|
||||
# Functional requrements rules
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл описывает, как оформлять функциональные требования в подраздел `### Функциональные требования` в документах.
|
||||
|
||||
## Правила
|
||||
- Функциональное требование (FR) расширяет и дополняет шаги, описанные в сценарии.
|
||||
- Функциональное требование (FR) не должно копировать шаг сценария не неся дополнительной информации.
|
||||
- Название функционального требования формируется следующим образом - "FR.<номер>. <Название>", где
|
||||
- <номер> идет инкрементально внутри конкретного документа, начинается с 1.
|
||||
- <Название> - кратко описывает что делает требование, суть действий (от 3 до 7 слов)
|
||||
|
||||
|
||||
|
||||
## Пример целевого описания сценария
|
||||
|
||||
### Примеры названия FR
|
||||
- Получение данных клиента из АС ЕПК
|
||||
- Проверка уровня доступа
|
||||
- Сценарий построения списка связанных предложений
|
||||
|
||||
|
||||
### Примеры описания FR
|
||||
FR.1. Получение данных клиента из АС ЕПК
|
||||
1. Сформировать запрос к эндпоинту POST /api/v1/path/to/resourse в АС ЕПК
|
||||
- Заголовки
|
||||
- <тут идет описание заголовков и того как они формируются>
|
||||
- Параметры запроса
|
||||
- <тут идет описание параметров и того как они формируются>
|
||||
- Тело запроса
|
||||
- <тут идет описание структуры объекта JSON или payload в другмо формате так как это задано требованиями>
|
||||
|
||||
2. Обработать ответ от АС ЕПК
|
||||
Успешный ответ - <взять из описания вызываеого api критерии успешного ответа >
|
||||
Ничего не найдено - <взять из описания вызываеого api критерии успешного овтета, опционально (если применимо)>
|
||||
Ошибка - <взять из описания вызываеого api критерии успешного ответа >
|
||||
@@ -0,0 +1,16 @@
|
||||
# Requirements Format Rules
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл задает формат для функциональных и нефункциональных требований.
|
||||
|
||||
## Функциональные требования
|
||||
|
||||
- Использовать коды `FR-1`, `FR-2`, `FR-3` и так далее.
|
||||
- Каждое требование должно описывать отдельный обязательный аспект поведения.
|
||||
- Идентификаторы локальны в пределах одного документа.
|
||||
|
||||
## Нефункциональные требования
|
||||
|
||||
- Использовать коды `NFR-1`, `NFR-2`, `NFR-3` и так далее.
|
||||
- Требования должны описывать характеристики качества, ограничения и эксплуатационные свойства.
|
||||
@@ -0,0 +1,13 @@
|
||||
# Summary Section Rules
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл задает правила для секции `## Summary`.
|
||||
|
||||
## Правила
|
||||
|
||||
- Summary должен быть коротким explain-слоем быстрого контекста.
|
||||
- Summary должен объяснять суть документа без лишних деталей.
|
||||
- Summary должен быть пригоден для explain и быстрого чтения.
|
||||
- Предпочтительный формат: список ключевых фактов `Purpose`, `Actor`, `Trigger`, `Errors`, `Related ...` и т.д.
|
||||
- Для крупных документов допустим более длинный summary, если он остается структурированным.
|
||||
@@ -0,0 +1,66 @@
|
||||
# Scenario Rules
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл описывает, как оформлять технический USE CASE в подраздел `### Сценарий` в документах.
|
||||
|
||||
## Обязательные части
|
||||
|
||||
- название
|
||||
- предусловия
|
||||
- триггер
|
||||
- основной сценарий
|
||||
- альтернативный сценарий
|
||||
- обработка ошибок
|
||||
- постусловие
|
||||
|
||||
## Правила
|
||||
- Основной и альтернативные сценарии состоят из шагов.
|
||||
|
||||
- Каждый шаг описывается одним предложением не более 15-20 слов, и состоит из двух частей. Первая часть описывает что мы делаем по смыслу, чтобы это было понятно человеку без низкоуровневых технических деталей. Например: авторизует запрос, получает данные клиента, запрашивает справочники. Вторая часть описывает как это реализовано технически - вызывает эндпоинт /path/to/resource в системе <название системы>.
|
||||
|
||||
- В описании шага не должно быть длинных технических деталей. Если техничсекую реализацию нельхзя описатьодним предложенеим (в лимите длины описания шага), то необхлодимо это вынести в отдельное функциональное требование FR.<номер>. <Название> и описать в нем технические детали. А в шаге сослаться на это требование через "Описание приведено в FR.<номер>. <Название>"
|
||||
|
||||
- Для шагов авторизации обязателен доп шаг с описанием обработки ошибки.
|
||||
- Для шагов с интеграцией обязателен доп шаг с описанием обработки ошибки.
|
||||
- Для шагов с проверкой условий обязательны доп шаги с описанием переходов по сценарию.
|
||||
|
||||
- Название "FR.<номер>. <Название>" формируется следующим образом:
|
||||
- <номер> идет инкрементально внутри конкретного документа, начинается с 1.
|
||||
- <Название> - кратко описывает что делает требование, суть действий.
|
||||
|
||||
- Для каждого шага при необходимости нужно прописать логику действий в случае ошибки или если логика шага определяет несколько сценариев разивития при выполнении заданных условий.
|
||||
|
||||
- Для шагов, которые описывают интеграцию с другой системой необходимо указать название точки интеграции (название эндпоинта, название топика и так далее) и сделать ссылку на FR.<номер>. <Название> с описанием шагов интеграции - как сформировать запрос/сообщение, как обработать ответ, политику ретраев.
|
||||
|
||||
- Сценарий собирается из тезисов, приведенных системной аналимтике в свободной формулировке
|
||||
|
||||
- Функциональные требования "FR.<номер>. <Название>" не должны дублировать шагов сценария в use case. Они содержат детали, которые вынесены из юзкейса чтобы не делать его тяжелым. Если шаг юзкейса описывается одним предложением в лимите длины, то FR делать не нужно.
|
||||
|
||||
- FR обязательно описывается для шага с интеграцией
|
||||
- FR Не описывается для шага авторизации.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Пример целевого описания сценария
|
||||
|
||||
### Примеры шагов сценария
|
||||
|
||||
Пример 1
|
||||
- Авторизует запрос пользователя по наличию у него экшена ролевой модели CI02792632.ContactsDGR.Detail
|
||||
- В случае ошибки - завершить сценарий с кодом UNAUTHORIZED
|
||||
|
||||
Пример 2
|
||||
- Запрашивает данные клиента - вызывает /api/v1/clients/{client-id}/info
|
||||
- В случае ошибки - завершить сценарий с кодом CLIENT_INFO_REQUEST_FAIL
|
||||
|
||||
Пример 3
|
||||
- Возвращает ответ в формате <название DTO>
|
||||
|
||||
### Примеры названия FR
|
||||
- Получение данных клиента из АС ЕПК
|
||||
- Проверка уровня доступа
|
||||
- Сценарий построения списка связанных предложений
|
||||
@@ -0,0 +1,71 @@
|
||||
# Documentation Rules
|
||||
|
||||
Этот каталог оформляет MVP документации проекта в атомарном формате.
|
||||
|
||||
## Базовая структура
|
||||
|
||||
- Каждый документ содержит YAML frontmatter.
|
||||
- В документе должен быть один `H1`, совпадающий с `title`.
|
||||
- Основные разделы оформляются как `## Summary` и `## Details`.
|
||||
- Внутри `Details` используются заголовки уровня `###` и ниже.
|
||||
- Связи, сущности и навигация описываются во frontmatter через `related_docs`, `links`, `entities`, `parent`, `children`.
|
||||
|
||||
## Summary
|
||||
|
||||
- Краткий explain-слой быстрого контекста.
|
||||
- Должен позволять быстро понять назначение документа без чтения `Details`.
|
||||
- Предпочтительный формат: компактный список ключевых фактов без длинных абзацев.
|
||||
|
||||
## Details
|
||||
|
||||
- Раскрывает полное описание объекта.
|
||||
- Структура `Details` зависит от типа документа.
|
||||
- Сценарии, ограничения, интеграции, ошибки и кодовые привязки должны быть разнесены по отдельным подразделам.
|
||||
|
||||
## API documents
|
||||
|
||||
Для `api_method` внутри `## Details` обязательны разделы:
|
||||
- `### Описание`
|
||||
- `### Сценарий`
|
||||
- `### Функциональные требования`
|
||||
- `### Нефункциональные требования`
|
||||
- `### Контракт`
|
||||
|
||||
Если у метода есть интеграции и ошибки, также обязательны:
|
||||
- `### Интеграции`
|
||||
- `### Ошибки`
|
||||
- `### Связанный код`
|
||||
- `### История изменений`
|
||||
|
||||
### Сценарий
|
||||
|
||||
Сценарий оформляется как технический use case и содержит:
|
||||
- название
|
||||
- предусловия
|
||||
- триггер
|
||||
- основной сценарий
|
||||
- альтернативный сценарий
|
||||
- обработку ошибок
|
||||
- постусловие
|
||||
|
||||
### Требования
|
||||
|
||||
- Функциональные требования маркируются как `FR-1`, `FR-2`, ...
|
||||
- Нефункциональные требования маркируются как `NFR-1`, `NFR-2`, ...
|
||||
- Идентификаторы требований локальны в рамках одного документа.
|
||||
|
||||
### Контракт
|
||||
|
||||
Контракт должен быть пригоден для последующей сборки OpenAPI-спецификации и включать:
|
||||
- входные параметры
|
||||
- выходные параметры
|
||||
- структуру JSON-сообщений
|
||||
- обязательность полей
|
||||
- типы и ограничения
|
||||
- описание полей
|
||||
- правила заполнения
|
||||
- примеры данных
|
||||
- auth
|
||||
- idempotency
|
||||
- timeout
|
||||
- ошибки и их HTTP-коды
|
||||
@@ -0,0 +1,38 @@
|
||||
# Documentation System
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл задает общую модель документации проекта.
|
||||
|
||||
## Базовая модель
|
||||
|
||||
Каждый документ должен состоять из двух слоев:
|
||||
- YAML frontmatter
|
||||
- контент
|
||||
|
||||
Контент всегда состоит из двух обязательных разделов:
|
||||
- `## Summary`
|
||||
- `## Details`
|
||||
|
||||
Над ними должен быть один заголовок `# <title>`, совпадающий со значением `title` во frontmatter.
|
||||
|
||||
## Принципы
|
||||
|
||||
- Документы должны быть атомарными.
|
||||
- Один документ описывает одну тему.
|
||||
- Вместо дублирования между документами используются явные ссылки.
|
||||
- Связи и навигация должны быть формализованы.
|
||||
- Документы должны быть пригодны для чтения человеком и для RAG.
|
||||
- Документы должны быть пригодны для частичного обновления без деградации структуры.
|
||||
|
||||
## Типы документов
|
||||
|
||||
На уровне проекта поддерживаются типы:
|
||||
- `api_method`
|
||||
- `logic_block`
|
||||
- `architecture_overview`
|
||||
- `domain_entity`
|
||||
- `ui_page`
|
||||
- `integration_doc`
|
||||
- `index_page`
|
||||
- `glossary_item`
|
||||
@@ -0,0 +1,67 @@
|
||||
# Frontmatter Rules
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл описывает единый контракт YAML frontmatter для всех документов.
|
||||
|
||||
## Обязательные поля
|
||||
|
||||
```yaml
|
||||
id: string
|
||||
title: string
|
||||
doc_type: string
|
||||
domain: string
|
||||
sub_domain: string
|
||||
related_docs: []
|
||||
status: string
|
||||
```
|
||||
|
||||
## Поля совместимости и рекомендуемые поля
|
||||
|
||||
```yaml
|
||||
type: string
|
||||
name: string
|
||||
module: string
|
||||
layer: string
|
||||
updated_at: YYYY-MM-DD
|
||||
tags: []
|
||||
entities: []
|
||||
parent: string | null
|
||||
children: []
|
||||
links: {}
|
||||
source_of_truth: string
|
||||
related_code: []
|
||||
system_analytics_refs: []
|
||||
```
|
||||
|
||||
## Правила
|
||||
|
||||
- `id` должен быть стабильным и уникальным в пределах документации проекта.
|
||||
- `title` — человекочитаемый заголовок.
|
||||
- `doc_type` — канонический тип документа.
|
||||
- `domain` и `sub_domain` определяют бизнес-контекст документа.
|
||||
- `related_docs` хранит явные связи с другими markdown-документами.
|
||||
- `status` хранит жизненный цикл документа: например `draft`, `approved`, `active`.
|
||||
- `type` допустимо дублировать как alias для tooling-совместимости с индексаторами.
|
||||
- `name` — короткое системное имя документа.
|
||||
- `module` — модуль или подсистема.
|
||||
- `layer` — слой системы.
|
||||
- `updated_at` хранится в формате `YYYY-MM-DD`.
|
||||
|
||||
## Связи и навигация
|
||||
|
||||
- `entities` описывает сущности, связанные с документом.
|
||||
- `parent` и `children` описывают иерархию.
|
||||
- `links` описывает typed graph связей между документами, кодом и интеграциями.
|
||||
|
||||
## Формат links
|
||||
|
||||
```yaml
|
||||
links:
|
||||
called_by:
|
||||
- ext.health_probe
|
||||
uses_logic:
|
||||
- logic.some_flow
|
||||
integrates_with:
|
||||
- ext.some_system
|
||||
```
|
||||
@@ -0,0 +1,33 @@
|
||||
# Linking Rules
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл описывает, как связывать документы между собой.
|
||||
|
||||
## Иерархия
|
||||
|
||||
- `parent` используется для родительского документа.
|
||||
- `children` используется для прямых дочерних документов.
|
||||
- Иерархия должна быть осмысленной и стабильной.
|
||||
- Для общей точки входа допустим `index_page`.
|
||||
|
||||
## Графовые связи
|
||||
|
||||
Для `related_docs` используются ссылки на соседние документы.
|
||||
|
||||
Для `links` рекомендуется использовать typed-ключи:
|
||||
- `called_by`
|
||||
- `uses_logic`
|
||||
- `reads_db`
|
||||
- `writes_db`
|
||||
- `integrates_with`
|
||||
- `used_by`
|
||||
- `exposes_api`
|
||||
- `uses_entities`
|
||||
|
||||
## Правила использования
|
||||
|
||||
- Если документ логически входит в другой, использовать `parent`/`children`.
|
||||
- Если связь нужна для навигации между равноправными документами, дублировать ее в `related_docs`.
|
||||
- Если связь отражает поведение, интеграции или переиспользование, фиксировать ее в `links`.
|
||||
- Детальное описание интеграций хранить в body документа, а не только во frontmatter.
|
||||
@@ -0,0 +1,24 @@
|
||||
# Naming Rules
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл описывает правила именования документов, файлов и идентификаторов.
|
||||
|
||||
## Правила для файлов
|
||||
|
||||
- Имена файлов должны быть в kebab-case.
|
||||
- Имя файла должно отражать одну тему.
|
||||
- Для шаблонов использовать суффикс `.template.md`.
|
||||
|
||||
## Правила для id
|
||||
|
||||
- `id` строится в формате `<type-group>.<name>`.
|
||||
- Примеры:
|
||||
- `api.send_message_endpoint`
|
||||
- `logic.telegram_notification_loop`
|
||||
- `architecture.telegram_notify_app`
|
||||
|
||||
## Правила для title
|
||||
|
||||
- `title` должен быть кратким и человекочитаемым.
|
||||
- В `title` допускаются пробелы и естественный язык.
|
||||
@@ -0,0 +1,19 @@
|
||||
# Writing Style
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл задает правила стиля для текстового наполнения документации.
|
||||
|
||||
## Правила стиля
|
||||
|
||||
- Текст должен быть лаконичным.
|
||||
- Формулировки должны быть точными и техническими.
|
||||
- Summary должен быть кратким explain-слоем.
|
||||
- Details должен раскрывать суть без лишней воды.
|
||||
- Нежелательно смешивать несколько тем в одном документе.
|
||||
- Если детали относятся к другому артефакту, их нужно выносить в отдельный документ.
|
||||
|
||||
## Язык
|
||||
|
||||
- Основной язык документации — русский.
|
||||
- Технические термины, названия классов, API, RAG, OpenAPI, runtime и другие устоявшиеся identifiers можно оставлять на английском.
|
||||
@@ -0,0 +1,84 @@
|
||||
---
|
||||
id: api.example_method
|
||||
type: api_method
|
||||
doc_type: api_method
|
||||
name: example_method
|
||||
title: HTTP API /example
|
||||
module: example_module
|
||||
layer: application
|
||||
domain: example_domain
|
||||
sub_domain: example_subdomain
|
||||
related_docs: []
|
||||
status: draft
|
||||
updated_at: 2026-03-20
|
||||
source_of_truth: code
|
||||
parent: null
|
||||
children: []
|
||||
tags: []
|
||||
entities: []
|
||||
links: {}
|
||||
---
|
||||
|
||||
# HTTP API /example
|
||||
|
||||
## Summary
|
||||
|
||||
Краткое описание метода.
|
||||
|
||||
## Details
|
||||
|
||||
## Описание
|
||||
|
||||
Короткое описание сути метода.
|
||||
|
||||
## Сценарий
|
||||
|
||||
**Название:**
|
||||
|
||||
**Предусловия:**
|
||||
-
|
||||
|
||||
**Триггер:**
|
||||
-
|
||||
|
||||
**Основной сценарий:**
|
||||
1.
|
||||
|
||||
**Альтернативный сценарий:**
|
||||
1.
|
||||
|
||||
**Обработка ошибок:**
|
||||
1.
|
||||
|
||||
**Постусловие:**
|
||||
-
|
||||
|
||||
## Функциональные требования
|
||||
|
||||
**FR-1.**
|
||||
|
||||
## Нефункциональные требования
|
||||
|
||||
**NFR-1.**
|
||||
|
||||
## Контракт
|
||||
|
||||
### Входные параметры
|
||||
|
||||
| Параметр | Где передается | Тип | Обязательность | Ограничения | Описание | Пример |
|
||||
|---|---|---|---|---|---|---|
|
||||
| | | | | | | |
|
||||
|
||||
### Выходные параметры
|
||||
|
||||
| Поле | Тип | Обязательность | Ограничения | Описание | Заполнение | Пример |
|
||||
|---|---|---|---|---|---|---|
|
||||
| | | | | | | |
|
||||
|
||||
### Интеграции
|
||||
|
||||
### Ошибки
|
||||
|
||||
### Связанный код
|
||||
|
||||
### История изменений
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
---
|
||||
id: architecture.example_system
|
||||
type: architecture_overview
|
||||
doc_type: architecture_overview
|
||||
name: example_system
|
||||
title: Обзор архитектуры Example System
|
||||
module: example_module
|
||||
layer: system
|
||||
domain: example_domain
|
||||
sub_domain: example_subdomain
|
||||
related_docs: []
|
||||
status: draft
|
||||
updated_at: 2026-03-20
|
||||
source_of_truth: mixed
|
||||
parent: null
|
||||
children: []
|
||||
tags: []
|
||||
entities: []
|
||||
links: {}
|
||||
---
|
||||
|
||||
# Обзор архитектуры Example System
|
||||
|
||||
## Summary
|
||||
|
||||
Краткое описание архитектуры.
|
||||
|
||||
## Details
|
||||
|
||||
### Описание
|
||||
|
||||
### Контекст
|
||||
|
||||
### Границы системы
|
||||
|
||||
### Компоненты
|
||||
|
||||
### Интеграционные сценарии
|
||||
|
||||
### Интеграции
|
||||
|
||||
### Ограничения
|
||||
|
||||
### Связанный код
|
||||
|
||||
### Связанные документы
|
||||
|
||||
### История изменений
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
id: domain.example_entity
|
||||
type: domain_entity
|
||||
doc_type: domain_entity
|
||||
name: example_entity
|
||||
title: Пример доменной сущности
|
||||
module: example_module
|
||||
layer: domain
|
||||
domain: example_domain
|
||||
sub_domain: example_subdomain
|
||||
related_docs: []
|
||||
status: draft
|
||||
updated_at: 2026-03-20
|
||||
source_of_truth: code
|
||||
parent: null
|
||||
children: []
|
||||
tags: []
|
||||
entities: []
|
||||
links: {}
|
||||
---
|
||||
|
||||
# Пример доменной сущности
|
||||
|
||||
## Summary
|
||||
|
||||
Краткое описание сущности.
|
||||
|
||||
## Details
|
||||
|
||||
### Описание
|
||||
|
||||
### Модель данных
|
||||
|
||||
### Состояния и инварианты
|
||||
|
||||
### Технический use case
|
||||
|
||||
### Функциональные требования
|
||||
|
||||
### Нефункциональные требования
|
||||
|
||||
### Интеграции
|
||||
|
||||
### Связанный код
|
||||
|
||||
### Связанные документы
|
||||
|
||||
### История изменений
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
id: logic.example_block
|
||||
type: logic_block
|
||||
doc_type: logic_block
|
||||
name: example_block
|
||||
title: Пример блока логики
|
||||
module: example_module
|
||||
layer: application
|
||||
domain: example_domain
|
||||
sub_domain: example_subdomain
|
||||
related_docs: []
|
||||
status: draft
|
||||
updated_at: 2026-03-20
|
||||
source_of_truth: code
|
||||
parent: null
|
||||
children: []
|
||||
tags: []
|
||||
entities: []
|
||||
links: {}
|
||||
---
|
||||
|
||||
# Пример блока логики
|
||||
|
||||
## Summary
|
||||
|
||||
Краткое описание блока логики.
|
||||
|
||||
## Details
|
||||
|
||||
### Описание
|
||||
|
||||
### Контекст
|
||||
|
||||
### Технический use case
|
||||
|
||||
### Функциональные требования
|
||||
|
||||
### Нефункциональные требования
|
||||
|
||||
### Интеграции
|
||||
|
||||
### Ограничения и условия вызова
|
||||
|
||||
### Ошибки и деградации
|
||||
|
||||
### Связанные API
|
||||
|
||||
### Связанный код
|
||||
|
||||
### История изменений
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
id: ui.example_page
|
||||
type: ui_page
|
||||
doc_type: ui_page
|
||||
name: example_page
|
||||
title: Пример UI-страницы
|
||||
module: example_module
|
||||
layer: presentation
|
||||
domain: example_domain
|
||||
sub_domain: example_subdomain
|
||||
related_docs: []
|
||||
status: draft
|
||||
updated_at: 2026-03-20
|
||||
source_of_truth: mixed
|
||||
parent: null
|
||||
children: []
|
||||
tags: []
|
||||
entities: []
|
||||
links: {}
|
||||
---
|
||||
|
||||
# Пример UI-страницы
|
||||
|
||||
## Summary
|
||||
|
||||
Краткое описание страницы и её назначения.
|
||||
|
||||
## Details
|
||||
|
||||
### Назначение страницы
|
||||
|
||||
### Пользовательский сценарий
|
||||
|
||||
### Основные блоки интерфейса
|
||||
|
||||
### Связанные API и сущности
|
||||
|
||||
### Функциональные требования
|
||||
|
||||
### Нефункциональные требования
|
||||
|
||||
### Ограничения и граничные случаи
|
||||
|
||||
### Ошибки и валидации
|
||||
|
||||
### Связанный код
|
||||
|
||||
### Связанные документы
|
||||
|
||||
### История изменений
|
||||
@@ -0,0 +1,39 @@
|
||||
# API Method Rules
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл задает правила для документов типа `api_method`.
|
||||
|
||||
## Когда использовать
|
||||
|
||||
Использовать для описания одного HTTP endpoint или одного отдельного API метода.
|
||||
|
||||
## Обязательная структура
|
||||
|
||||
Документ должен содержать:
|
||||
- YAML frontmatter
|
||||
- `# <title>`
|
||||
- `## Summary`
|
||||
- `## Details`
|
||||
|
||||
Внутри `## Details` обязательны:
|
||||
- `### Описание`
|
||||
- `### Сценарий`
|
||||
- `### Функциональные требования`
|
||||
- `### Нефункциональные требования`
|
||||
- `### Контракт`
|
||||
|
||||
## Особые правила
|
||||
|
||||
- Сценарий оформляется как технический use case.
|
||||
- Функциональные требования маркируются `FR-*`.
|
||||
- Нефункциональные требования маркируются `NFR-*`.
|
||||
- Контракт должен быть пригоден для последующей сборки OpenAPI.
|
||||
- Если у метода есть интеграции, они выносятся в `### Интеграции`.
|
||||
- Ошибки и HTTP-коды либо описываются в `### Ошибки`, либо ссылаются на централизованный каталог ошибок.
|
||||
|
||||
## Ошибки оформления
|
||||
|
||||
- Нельзя заменять контракт общим текстовым описанием.
|
||||
- Нельзя смешивать несколько endpoint в одном документе.
|
||||
- Нельзя хранить связи и навигацию вне frontmatter.
|
||||
@@ -0,0 +1,31 @@
|
||||
# Architecture Overview Rules
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл задает правила для документов типа `architecture_overview`.
|
||||
|
||||
## Когда использовать
|
||||
|
||||
Использовать как входной документ для понимания системы, модуля или сервиса.
|
||||
|
||||
## Обязательная структура
|
||||
|
||||
Документ должен содержать:
|
||||
- YAML frontmatter
|
||||
- `# <title>`
|
||||
- `## Summary`
|
||||
- `## Details`
|
||||
|
||||
## Что описывать в Details
|
||||
|
||||
- границы системы
|
||||
- основные компоненты
|
||||
- ключевые взаимодействия
|
||||
- интеграционные сценарии
|
||||
- главные ограничения
|
||||
- ссылки на дочерние документы по API, logic, domain и другим артефактам
|
||||
|
||||
## Ошибки оформления
|
||||
|
||||
- Нельзя дублировать в архитектурном обзоре полные API-контракты.
|
||||
- Нельзя делать архитектурный обзор единственным документом на всю систему без декомпозиции.
|
||||
@@ -0,0 +1,30 @@
|
||||
# Domain Entity Rules
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл задает правила для документов типа `domain_entity`.
|
||||
|
||||
## Когда использовать
|
||||
|
||||
Использовать для описания одной доменной сущности, ее смысла, состояния и роли в системе.
|
||||
|
||||
## Обязательная структура
|
||||
|
||||
Документ должен содержать:
|
||||
- YAML frontmatter
|
||||
- `# <title>`
|
||||
- `## Summary`
|
||||
- `## Details`
|
||||
|
||||
## Что описывать в Details
|
||||
|
||||
- смысл сущности
|
||||
- ключевые атрибуты
|
||||
- состояния или инварианты
|
||||
- использование сущности в системе
|
||||
- интеграции с API, workflow или внешними потребителями, если они важны для понимания модели
|
||||
|
||||
## Ошибки оформления
|
||||
|
||||
- Нельзя смешивать несколько независимых сущностей в одном документе.
|
||||
- Нельзя подменять доменную сущность описанием endpoint или workflow.
|
||||
@@ -0,0 +1,25 @@
|
||||
# Integration Doc Rules
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл задает правила для документов типа `integration_doc`.
|
||||
|
||||
## Когда использовать
|
||||
|
||||
Использовать для описания интеграции между системами, сервисами или внешними провайдерами.
|
||||
|
||||
## Обязательная структура
|
||||
|
||||
Документ должен содержать:
|
||||
- YAML frontmatter
|
||||
- `# <title>`
|
||||
- `## Summary`
|
||||
- `## Details`
|
||||
|
||||
## Что описывать в Details
|
||||
|
||||
- цель интеграции
|
||||
- участвующие стороны
|
||||
- направление обмена
|
||||
- ключевой сценарий взаимодействия
|
||||
- ограничения и риски
|
||||
@@ -0,0 +1,31 @@
|
||||
# Logic Block Rules
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл задает правила для документов типа `logic_block`.
|
||||
|
||||
## Когда использовать
|
||||
|
||||
Использовать для описания одного законченного блока логики, workflow или процесса.
|
||||
|
||||
## Обязательная структура
|
||||
|
||||
Документ должен содержать:
|
||||
- YAML frontmatter
|
||||
- `# <title>`
|
||||
- `## Summary`
|
||||
- `## Details`
|
||||
|
||||
## Что описывать в Details
|
||||
|
||||
- назначение логического блока
|
||||
- входы и выходы
|
||||
- последовательность выполнения
|
||||
- интеграции
|
||||
- ключевые ограничения
|
||||
- состояние и ошибки, если они важны для понимания блока
|
||||
|
||||
## Ошибки оформления
|
||||
|
||||
- Нельзя описывать весь модуль целиком, если логика распадается на несколько независимых блоков.
|
||||
- Нельзя превращать документ в пересказ исходного кода построчно.
|
||||
@@ -0,0 +1,24 @@
|
||||
# UI Page Rules
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот файл задает правила для документов типа `ui_page`.
|
||||
|
||||
## Когда использовать
|
||||
|
||||
Использовать для описания одной пользовательской страницы, экрана или отдельного UI-сценария.
|
||||
|
||||
## Обязательная структура
|
||||
|
||||
Документ должен содержать:
|
||||
- YAML frontmatter
|
||||
- `# <title>`
|
||||
- `## Summary`
|
||||
- `## Details`
|
||||
|
||||
## Что описывать в Details
|
||||
|
||||
- назначение страницы
|
||||
- пользовательский сценарий
|
||||
- основные блоки интерфейса
|
||||
- связанные API и сущности
|
||||
+33
-7
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from app.core.agent.processes.v2.workflows.doc_update_from_feature.doc_rules_pipeline.models import DocRulesBundle
|
||||
@@ -7,20 +8,45 @@ from app.core.agent.processes.v2.workflows.doc_update_from_feature.doc_rules_pip
|
||||
|
||||
class DocRulesLoader:
|
||||
def __init__(self, root: Path | None = None) -> None:
|
||||
base = root or (Path(__file__).resolve().parents[3] / "doc_rules")
|
||||
self._root = base
|
||||
base_dir = Path(__file__).resolve().parents[3]
|
||||
if root is not None:
|
||||
self._root = root
|
||||
return
|
||||
profile = os.getenv("DOC_RULES_PROFILE", "legacy").strip().lower()
|
||||
if profile == "legacy":
|
||||
self._root = base_dir / "doc_rules"
|
||||
return
|
||||
self._root = base_dir / "doc_rules_v2"
|
||||
|
||||
@property
|
||||
def root(self) -> Path:
|
||||
return self._root
|
||||
|
||||
def load(self) -> DocRulesBundle:
|
||||
bundle = self._load_from_root(self._root)
|
||||
if bundle.supported_doc_types:
|
||||
return bundle
|
||||
# Safe fallback for quick rollback or incomplete v2 setup.
|
||||
fallback = self._root.parent / "doc_rules"
|
||||
if fallback != self._root:
|
||||
fallback_bundle = self._load_from_root(fallback)
|
||||
if fallback_bundle.supported_doc_types:
|
||||
return fallback_bundle
|
||||
return bundle
|
||||
|
||||
def _load_from_root(self, root: Path) -> DocRulesBundle:
|
||||
artifact_rules = self._read_folder(root / "artifact-types", suffix=".md")
|
||||
if not artifact_rules:
|
||||
artifact_rules = self._read_folder(root / "types", suffix=".md")
|
||||
sections = self._read_folder(root / "sections", suffix=".md")
|
||||
if not sections:
|
||||
sections = self._read_folder(root / "common-elements", suffix=".md")
|
||||
return DocRulesBundle(
|
||||
documentation_rules=self._read_file(self._root / "documentation-rules.md"),
|
||||
global_rules=self._read_folder(self._root / "global", suffix=".md"),
|
||||
artifact_rules=self._read_folder(self._root / "artifact-types", suffix=".md"),
|
||||
templates=self._read_templates(self._root / "templates"),
|
||||
sections=self._read_folder(self._root / "sections", suffix=".md"),
|
||||
documentation_rules=self._read_file(root / "documentation-rules.md"),
|
||||
global_rules=self._read_folder(root / "global", suffix=".md"),
|
||||
artifact_rules=artifact_rules,
|
||||
templates=self._read_templates(root / "templates"),
|
||||
sections=sections,
|
||||
)
|
||||
|
||||
def _read_templates(self, folder: Path) -> dict[str, str]:
|
||||
|
||||
+7
-7
@@ -5,14 +5,14 @@ from app.core.agent.processes.v2.workflows.doc_update_from_feature.doc_rules_pip
|
||||
|
||||
|
||||
class DocRulesSelector:
|
||||
_DEFAULT_SECTIONS: tuple[str, ...] = ("summary", "details", "requirements-format")
|
||||
_DEFAULT_SECTIONS: tuple[str, ...] = ("summary", "details", "tech-use-case", "fr", "requirements-format")
|
||||
_SECTIONS_BY_TYPE: dict[str, tuple[str, ...]] = {
|
||||
"api_method": ("summary", "details", "api-scenario", "api-contract", "requirements-format"),
|
||||
"integration_doc": ("summary", "details", "api-contract", "requirements-format"),
|
||||
"ui_page": ("summary", "details", "requirements-format"),
|
||||
"logic_block": ("summary", "details", "requirements-format"),
|
||||
"architecture_overview": ("summary", "details", "requirements-format"),
|
||||
"domain_entity": ("summary", "details", "requirements-format"),
|
||||
"api_method": ("summary", "details", "tech-use-case", "fr", "api-contract", "requirements-format"),
|
||||
"integration_doc": ("summary", "details", "tech-use-case", "fr", "api-contract", "requirements-format"),
|
||||
"ui_page": ("summary", "details", "tech-use-case", "fr", "requirements-format"),
|
||||
"logic_block": ("summary", "details", "tech-use-case", "fr", "requirements-format"),
|
||||
"architecture_overview": ("summary", "details", "tech-use-case", "fr", "requirements-format"),
|
||||
"domain_entity": ("summary", "details", "tech-use-case", "fr", "requirements-format"),
|
||||
}
|
||||
|
||||
def select(self, bundle: DocRulesBundle, doc_type: str) -> SelectedDocRules | None:
|
||||
|
||||
@@ -61,8 +61,8 @@ class IndexJobStore:
|
||||
cache_miss_files=row.cache_miss_files,
|
||||
error=payload,
|
||||
)
|
||||
stale_timeout_sec = max(1, int(os.getenv("RAG_RUNNING_STALE_TIMEOUT_SEC", "8")))
|
||||
if job.status == IndexJobStatus.RUNNING and self._is_stale(row.updated_at, stale_timeout_sec):
|
||||
stale_timeout_sec = int(os.getenv("RAG_RUNNING_STALE_TIMEOUT_SEC", "0"))
|
||||
if stale_timeout_sec > 0 and job.status == IndexJobStatus.RUNNING and self._is_stale(row.updated_at, stale_timeout_sec):
|
||||
payload = ErrorPayload(
|
||||
code="index_stalled",
|
||||
desc="Indexing stalled in running state; likely blocked network call during embedding/auth.",
|
||||
|
||||
@@ -117,7 +117,7 @@ class IndexingOrchestrator:
|
||||
},
|
||||
)
|
||||
|
||||
timeout_sec = max(1, int(os.getenv("RAG_INDEX_JOB_TIMEOUT_SEC", "15")))
|
||||
timeout_sec = max(1, int(os.getenv("RAG_INDEX_JOB_TIMEOUT_SEC", "180")))
|
||||
indexed, failed, cache_hits, cache_misses = await asyncio.wait_for(
|
||||
operation(progress_cb),
|
||||
timeout=timeout_sec,
|
||||
|
||||
@@ -217,11 +217,23 @@ class RagService:
|
||||
batch_size = max(1, int(os.getenv("RAG_EMBED_BATCH_SIZE", "16")))
|
||||
request_timeout_sec = max(1, int(os.getenv("RAG_EMBED_REQUEST_TIMEOUT_SEC", "5")))
|
||||
request_retries = max(1, int(os.getenv("RAG_EMBED_REQUEST_MAX_RETRIES", "1")))
|
||||
max_chars = max(200, int(os.getenv("RAG_EMBED_MAX_CHARS", "1200")))
|
||||
overlap_chars = max(0, int(os.getenv("RAG_EMBED_OVERLAP_CHARS", "120")))
|
||||
prepared = self._prepare_docs_for_embedding(docs, max_chars=max_chars, overlap_chars=overlap_chars)
|
||||
if len(prepared) != len(docs):
|
||||
LOGGER.warning(
|
||||
"rag embed doc split: path=%s original_docs=%s prepared_docs=%s max_chars=%s overlap_chars=%s",
|
||||
file.get("path", ""),
|
||||
len(docs),
|
||||
len(prepared),
|
||||
max_chars,
|
||||
overlap_chars,
|
||||
)
|
||||
metadata = self._document_metadata(file, repo_id, blob_sha)
|
||||
for doc in docs:
|
||||
for doc in prepared:
|
||||
doc.metadata.update(metadata)
|
||||
for start in range(0, len(docs), batch_size):
|
||||
batch = docs[start : start + batch_size]
|
||||
for start in range(0, len(prepared), batch_size):
|
||||
batch = prepared[start : start + batch_size]
|
||||
LOGGER.warning(
|
||||
"rag embed batch start: path=%s batch_start=%s batch_size=%s timeout_sec=%s retries=%s",
|
||||
file.get("path", ""),
|
||||
@@ -243,7 +255,67 @@ class RagService:
|
||||
)
|
||||
for doc, vector in zip(batch, vectors):
|
||||
doc.embedding = vector
|
||||
return docs
|
||||
return prepared
|
||||
|
||||
def _prepare_docs_for_embedding(
|
||||
self,
|
||||
docs: list[RagDocument],
|
||||
*,
|
||||
max_chars: int,
|
||||
overlap_chars: int,
|
||||
) -> list[RagDocument]:
|
||||
prepared: list[RagDocument] = []
|
||||
for doc in docs:
|
||||
text = str(doc.text or "")
|
||||
if len(text) <= max_chars:
|
||||
prepared.append(doc)
|
||||
continue
|
||||
parts = self._split_text_for_embedding(text, max_chars=max_chars, overlap_chars=overlap_chars)
|
||||
if len(parts) <= 1:
|
||||
prepared.append(doc)
|
||||
continue
|
||||
for idx, part in enumerate(parts, start=1):
|
||||
metadata = dict(doc.metadata)
|
||||
metadata["embed_part_index"] = idx
|
||||
metadata["embed_part_total"] = len(parts)
|
||||
if doc.doc_id:
|
||||
metadata["embed_original_doc_id"] = doc.doc_id
|
||||
prepared.append(
|
||||
RagDocument(
|
||||
layer=doc.layer,
|
||||
source=doc.source,
|
||||
title=f"{doc.title} [part {idx}/{len(parts)}]",
|
||||
text=part,
|
||||
metadata=metadata,
|
||||
links=list(doc.links),
|
||||
span=doc.span,
|
||||
doc_id=f"{doc.doc_id}:part:{idx}" if doc.doc_id else None,
|
||||
lang=doc.lang,
|
||||
)
|
||||
)
|
||||
return prepared
|
||||
|
||||
def _split_text_for_embedding(self, text: str, *, max_chars: int, overlap_chars: int) -> list[str]:
|
||||
normalized = text.replace("\r\n", "\n").replace("\r", "\n")
|
||||
parts: list[str] = []
|
||||
start = 0
|
||||
length = len(normalized)
|
||||
while start < length:
|
||||
hard_end = min(length, start + max_chars)
|
||||
end = hard_end
|
||||
if hard_end < length:
|
||||
soft_start = min(length, start + max_chars // 2)
|
||||
pivot = normalized.rfind("\n", soft_start, hard_end)
|
||||
if pivot > start:
|
||||
end = pivot + 1
|
||||
chunk = normalized[start:end].strip()
|
||||
if chunk:
|
||||
parts.append(chunk)
|
||||
if end >= length:
|
||||
break
|
||||
next_start = max(start + 1, end - overlap_chars)
|
||||
start = next_start
|
||||
return parts or [normalized]
|
||||
|
||||
def _with_file_metadata(self, docs: list[RagDocument], file: dict, repo_id: str, blob_sha: str) -> list[RagDocument]:
|
||||
metadata = self._document_metadata(file, repo_id, blob_sha)
|
||||
|
||||
@@ -35,7 +35,7 @@ class GigaChatTokenProvider:
|
||||
def _fetch_token(self) -> tuple[str, float]:
|
||||
if not self._settings.credentials:
|
||||
raise GigaChatError("GIGACHAT_TOKEN is not set")
|
||||
timeout_sec = max(1, int(os.getenv("GIGACHAT_AUTH_TIMEOUT_SEC", "5")))
|
||||
timeout_sec = max(1, int(os.getenv("GIGACHAT_AUTH_TIMEOUT_SEC", "20")))
|
||||
headers = {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
"Accept": "application/json",
|
||||
|
||||
Reference in New Issue
Block a user