Initial SQL-only 1C adapter baseline
This commit is contained in:
@@ -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 из результата.
|
||||
Reference in New Issue
Block a user