Initial SQL-only 1C adapter baseline

This commit is contained in:
2026-07-22 03:03:47 +03:00
commit e2503b77e7
545 changed files with 184711 additions and 0 deletions
+286
View File
@@ -0,0 +1,286 @@
# 1C RAG
Цель: подготовить локальный корпус знаний по 1С для поиска и ответов без дообучения модели.
## Principles
- Сначала RAG и инструменты, потом fine-tuning.
- Не загружать в репозиторий базы, выгрузки, приватные документы, персональные данные и секреты.
- Не выдумывать метаданные конкретной базы 1С. Если нужны реквизиты или объекты, использовать tool boundary.
## Add Sources
Кладем материалы в:
```text
plugins/1c/rag/sources
```
Поддерживаемые форматы:
- `.md`
- `.txt`
- `.bsl`
- `.os`
## Prepare Corpus
```powershell
python scripts/validate_1c_rag_sources.py --print
python scripts/prepare_1c_rag_corpus.py
```
Результат:
```text
plugins/1c/datasets/prepared/rag_corpus.jsonl
plugins/1c/datasets/prepared/rag_manifest.json
```
Этот файл не коммитится.
## Test With Example
```powershell
python scripts/prepare_1c_rag_corpus.py --source-dir plugins/1c/rag/examples --output plugins/1c/datasets/prepared/rag_corpus.example.jsonl
```
## Build Search Index
```powershell
python scripts/build_1c_rag_index.py
```
Для синтетического примера:
```powershell
python scripts/build_1c_rag_index.py --corpus plugins/1c/datasets/prepared/rag_corpus.example.jsonl --output plugins/1c/datasets/prepared/rag_index.example.json
```
## Build Vector Index
```powershell
python scripts/build_1c_rag_vector_index.py
```
Результат:
```text
plugins/1c/datasets/prepared/rag_vector_index.sqlite
```
Индекс хранит `corpus_hash`, `embedding_model`, размерность, дату сборки и метаданные чанков.
Текущий provider `local-hashing-v1` - это локальный deterministic vector baseline, а не нейросемантическая embedding-модель. Он нужен, чтобы отладить формат, freshness и hybrid retrieval без скачивания модели. Нейросемантический provider подключается следующим слоем без смены SQLite-схемы.
OpenAI-compatible embedding endpoint:
```powershell
$env:EMBEDDING_API_KEY = "<token-if-needed>"
python scripts/build_1c_rag_vector_index.py `
--embedding-provider openai-compatible `
--embedding-model "<embedding-model-name>" `
--embedding-base-url "http://docker-gpu.cin.su:8000" `
--embedding-api-key-env EMBEDDING_API_KEY
```
Для поиска по такому индексу query embedding должен считаться тем же provider/model:
```powershell
python scripts/search_1c_rag_hybrid.py "реквизиты справочника номенклатура" `
--profile metadata `
--embedding-base-url "http://docker-gpu.cin.su:8000" `
--embedding-api-key-env EMBEDDING_API_KEY
```
Ключ не пишется в индекс и читается только из переменной окружения.
Полная сборка knowledge base теперь строит corpus, lexical index и vector index:
```powershell
python scripts/build_1c_knowledge_base.py --include-example-bsl
```
Если vector index временно не нужен:
```powershell
python scripts/build_1c_knowledge_base.py --skip-vector-index
```
## Search
```powershell
python scripts/search_1c_rag.py "метаданные справочника" --index plugins/1c/datasets/prepared/rag_index.example.json
```
Поиск использует локальный lexical BM25-подобный индекс с нормализацией 1С-терминов и алиасами вроде `1с/bsl`, `справочник/catalog`, `метаданные/metadata`.
Профили RAG лежат в:
```text
plugins/1c/rag/profiles.yaml
```
Основные профили:
- `auto`
- `general`
- `metadata`
- `bsl`
- `query`
- `safe-change`
`auto` выбирает профиль по тексту вопроса. Например, вопросы про реквизиты уходят в `metadata`, вопросы про процедуры и ошибки BSL - в `bsl`, вопросы с `ВЫБРАТЬ` - в `query`.
При подготовке корпуса источники получают смысловой `source_type`:
- `metadata`
- `bsl`
- `query`
- `safety`
- `docs`
Полезные параметры:
```powershell
python scripts/search_1c_rag.py "реквизиты справочника номенклатура" `
--index plugins/1c/datasets/prepared/rag_index.example.json `
--profile metadata `
--limit 5 `
--candidate-limit 30 `
--dedupe-by-document
```
Vector search:
```powershell
python scripts/search_1c_rag_vector.py "реквизиты справочника номенклатура" --profile metadata --limit 5
```
Hybrid search объединяет lexical и vector результаты через reciprocal-rank fusion:
```powershell
python scripts/search_1c_rag_hybrid.py "реквизиты справочника номенклатура" --profile metadata --limit 5
```
Если `vector_freshness.status = stale`, нужно пересобрать vector index после обновления corpus.
## Ask With Context
Без вызова модели, только сборка prompt:
```powershell
python scripts/ask_1c_rag.py "Какие реквизиты есть у справочника Номенклатура?" --index plugins/1c/datasets/prepared/rag_index.example.json --print-prompt
```
С явным профилем:
```powershell
python scripts/ask_1c_rag.py "Проверь BSL-код процедуры ПередЗаписью" --profile bsl --print-prompt
```
Проверка обязательных правил в prompt:
```powershell
python scripts/check_1c_rag_prompt.py
```
Проверка качества поиска по smoke-набору:
```powershell
python scripts/check_1c_rag_quality.py --print
```
Проверка auto-routing профилей:
```powershell
python scripts/check_1c_rag_profiles.py --print
```
С запущенной моделью:
```powershell
python scripts/ask_1c_rag.py "Какие реквизиты есть у справочника Номенклатура?" --index plugins/1c/datasets/prepared/rag_index.example.json --base-url http://docker-gpu.cin.su:8000 --model qwen3-4b-instruct
```
## Tool Contract
Контракт инструментов:
```text
plugins/1c/tools/tool-contract.yaml
```
Главное правило: модель не должна придумывать структуру базы 1С. Если ответ зависит от метаданных, сначала нужен вызов инструмента.
## Metadata Snapshot Flow
Для проверки RAG на структуре 1С можно сгенерировать source из metadata snapshot:
```powershell
python scripts/validate_1c_metadata_snapshot.py plugins/1c/metadata/examples/metadata.example.json
python scripts/convert_1c_metadata_to_rag.py --input plugins/1c/metadata/examples/metadata.example.json --output plugins/1c/rag/sources/metadata.example.generated.md
python scripts/build_1c_knowledge_base.py --include-example-bsl
python scripts/ask_1c_rag.py "Какие реквизиты есть у справочника Номенклатура?" --print-prompt
```
`build_1c_knowledge_base.py` выполняет валидацию snapshot, конвертацию источников, сборку corpus и индекса за один проход.
Перед сборкой corpus он также запускает `validate_1c_rag_sources.py`, чтобы заблокировать неподдерживаемые расширения, пустые файлы и вероятные секреты.
Manifest содержит source path, source type, file type, content hash и число чанков. Его удобно использовать для аудита и будущего инкрементального обновления индекса.
Проверить, не устарел ли manifest относительно `plugins/1c/rag/sources`:
```powershell
python scripts/check_1c_rag_freshness.py --print
```
Статус `stale` означает, что появились новые файлы, изменился hash, был удален источник или изменился `source_type`. После этого нужно пересобрать knowledge base.
Проверить, не устарел ли vector index относительно corpus:
```powershell
python scripts/check_1c_rag_vector_freshness.py --print
```
## Semantic Cache Embedding Worker
Для live 1C-адаптера semantic cache заполняется отдельно от RAG corpus. Адаптер отдает pending документы с `document_id` и `content_sha1`; worker считает embedding и вызывает `semantic.cache.embedding.upsert`. Если документ изменился, адаптер отвергнет embedding по `content_sha1`.
Dry-run:
```powershell
python scripts/embed_1c_semantic_cache.py --base-id upo_test --kind Template --limit 20 --dry-run --json
```
Запись baseline-векторов:
```powershell
python scripts/embed_1c_semantic_cache.py --base-id upo_test --kind Template --limit 20
```
Поиск по semantic cache с автоматически рассчитанным query embedding:
```powershell
python scripts/search_1c_semantic_cache.py "ОбластьШапка" --base-id upo_test --kind Template --limit 5 --validate-candidates
```
Если нужно перед поиском автоматически дозаполнить pending embeddings:
```powershell
python scripts/search_1c_semantic_cache.py "ОбластьШапка" --base-id upo_test --kind Template --embed-pending --validate-candidates
```
С OpenAI-compatible embedding endpoint:
```powershell
$env:EMBEDDING_API_KEY = "<token-if-needed>"
python scripts/embed_1c_semantic_cache.py `
--base-id upo_test `
--kind Template `
--embedding-provider openai-compatible `
--embedding-model "<embedding-model-name>" `
--embedding-base-url "http://docker-gpu.cin.su:8000" `
--embedding-api-key-env EMBEDDING_API_KEY
```
Semantic cache остается candidate-only: перед программными изменениями использовать `validate_candidates=true` или live read-selector из результата.