# 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 = "" python scripts/build_1c_rag_vector_index.py ` --embedding-provider openai-compatible ` --embedding-model "" ` --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 = "" python scripts/embed_1c_semantic_cache.py ` --base-id upo_test ` --kind Template ` --embedding-provider openai-compatible ` --embedding-model "" ` --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 из результата.