RAG для 1С: поиск по документации и коду конфигурации с помощью ИИ

Собираем ассистента, который отвечает на вопросы по вашей конфигурации и регламентам со ссылкой на источник. Код на Python и расчёт цены запроса.

5 мин · · бизнес · автоматизация

Типичная ситуация в компании на 1С: правила учёта лежат в документах, логика в десятках тысяч строк модулей, а ответ на вопрос «где у нас считается скидка» знает один человек. RAG для 1С решает это так: сначала находит нужные фрагменты кода и документов, потом отдаёт их модели вместе с вопросом, и она отвечает со ссылкой на источник. Ниже схема, код на Python и расчёт стоимости, а в конце разговор о том, когда RAG не нужен вовсе.

Что такое RAG простыми словами

Модель не знает вашу конфигурацию, а вставить в запрос всё нельзя или дорого. Поэтому делают в два шага:

  1. Поиск. По вопросу из вашей базы знаний выбираются несколько самых подходящих фрагментов.
  2. Ответ. Фрагменты и вопрос уходят в модель с инструкцией «отвечай только по этим материалам и указывай источник».

Так нейросеть для работы с 1С получает нужный контекст, а вы платите только за те несколько тысяч токенов, которые реально ушли в запрос.

Что индексировать

Сразу решите, что в индексе, а чего там быть не должно.

Подходит:

  • модули конфигурации (.bsl) из выгрузки в файлы;
  • описания объектов метаданных: справочники, документы, регистры, их реквизиты;
  • внутренние регламенты и инструкции пользователей;
  • документацию, на использование которой у вас есть право: проверьте условия лицензии на справочные материалы, прежде чем загружать их в сторонний сервис.

Не подходит:

  • содержимое самой информационной базы: персональные данные клиентов и сотрудников, цены контрагентов, зарплаты;
  • пароли, строки подключения, ключи доступа из модулей и настроек.

Если в коде есть секреты, вычистите их до индексации. Вопросы и найденные фрагменты уходят провайдеру модели, и это нужно учесть в политике безопасности.

Как резать код: по процедурам

Режьте код не на куски фиксированной длины, а по границам процедур и функций. Тогда фрагмент содержит законченную логику, а не половину условия. К каждому куску добавьте заголовок с путём к файлу: по нему потом вы будете ссылаться на источник.

bash
import re
from pathlib import Path

SPLIT = re.compile(r"(?mi)^(?=(?:Процедура|Функция)\s)")


def chunk_bsl(root: str) -> list[dict]:
    chunks = []
    for path in Path(root).rglob("*.bsl"):
        text = path.read_text(encoding="utf-8-sig", errors="ignore")
        for part in SPLIT.split(text):
            part = part.strip()
            if len(part) < 40:
                continue
            chunks.append({"source": str(path.relative_to(root)), "text": part[:3000]})
    return chunks

Обрезка до 3000 символов страхует от гигантских процедур. Регламенты в текстовых файлах режут по абзацам или разделам тем же способом. Если в модулях встречаются английские ключевые слова Procedure и Function, добавьте их в шаблон.

Поиск: начните с BM25

Для кода 1С полезен обычный текстовый поиск: идентификаторы, имена объектов и ключевые слова совпадают буквально. Для начала хватит алгоритма BM25 из библиотеки rank_bm25. Русскую морфологию грубо компенсирует усечение слов до пяти букв:

bash
from rank_bm25 import BM25Okapi


def tokens(s: str) -> list[str]:
    return [w[:5] for w in re.findall(r"\w+", s.lower())]


chunks = chunk_bsl("./config_dump")
index = BM25Okapi([tokens(c["source"] + " " + c["text"]) for c in chunks])


def search(question: str, k: int = 6) -> list[dict]:
    scores = index.get_scores(tokens(question))
    top = sorted(range(len(chunks)), key=lambda i: scores[i], reverse=True)[:k]
    return [chunks[i] for i in top]

Про эмбеддинги. Векторный поиск по смыслу полезен для регламентов на естественном языке. В списке эндпоинтов шлюза (chat completions, responses, messages, models) отдельного метода эмбеддингов нет, поэтому для векторного поиска используйте локальную модель эмбеддингов, а для генерации ответа шлюз. Самый разумный путь: BM25 для кода, при необходимости векторный поиск для текстов и объединение результатов.

Генерация ответа с источниками

bash
from openai import OpenAI

client = OpenAI(base_url="https://api.zukko.pro/v1", api_key="fetch_ваш_ключ")

SYSTEM = """Ты помощник по конфигурации 1С. Отвечай только по приведённым фрагментам.
Для каждого утверждения указывай источник в формате [путь к файлу].
Если ответа во фрагментах нет, скажи: «В найденных материалах ответа нет»
и предложи, какой запрос поиска попробовать. Ничего не придумывай."""


def ask(question: str, model: str = "claude-sonnet-5-5") -> str:
    found = search(question)
    context = "\n\n".join(f"### [{c['source']}]\n{c['text']}" for c in found)
    # temperature не задаём: новые модели Claude отклоняют значения, отличные от 1.0

Если хотите управлять разбросом ответов параметром temperature, проверьте, принимает ли его выбранная модель: новые модели Claude отклоняют значения, отличные от 1.0, поэтому в примере он не задан.

Как задавать вопросы

  • Называйте объекты как в метаданных: «Документ РеализацияТоваровУслуг», а не «продажи».
  • Один вопрос, одна тема. Составные вопросы разбивайте.
  • Если ответ «в материалах нет», попросите модель предложить другой запрос поиска и повторите.
  • Проверяйте ссылку на источник: откройте файл и убедитесь, что код действительно говорит то, что сказала модель.

Сколько стоит запрос

Допущение: 6 фрагментов по 400 токенов, плюс вопрос и инструкция 400 токенов, итого 2800 токенов входа и 500 токенов ответа. Цены на 18 октября 2026, долларов за 1M токенов.

claude-sonnet-5-5 (0.4 / 2): 2800 × 0.4 / 1 000 000 = $0.00112 500 × 2 / 1 000 000 = $0.001 Итого $0.00212, тысяча запросов около $2.12.

gpt-6.1-sol (0.27 / 1.32): 2800 × 0.27 / 1 000 000 = $0.000756 500 × 1.32 / 1 000 000 = $0.00066 Итого $0.001416, тысяча запросов около $1.42.

deepseek-v4.1-flash (0.013 / 0.038): 2800 × 0.013 / 1 000 000 = $0.0000364 500 × 0.038 / 1 000 000 = $0.000019 Итого $0.0000554, тысяча запросов около $0.055.

Какая модель точнее отвечает по вашему коду, мы не утверждаем: возьмите 20 реальных вопросов с известными ответами и проверьте две-три модели. Актуальные цены: GET https://api.zukko.pro/v1/models.

Когда RAG не нужен

Если ваш корпус небольшой, его можно положить в запрос целиком: у моделей контекст до 1M токенов. Для 200 000 токенов кода и документов цена одного запроса на claude-sonnet-5-5:

200 000 × 0.4 / 1 000 000 = $0.08 по цене входа.

В Anthropic-формате при повторных запросах с одним и тем же префиксом чтение кэша стоит 0.05: 200 000 × 0.05 / 1 000 000 = $0.01. Первый запрос оплачивает эти токены как запись в кэш по 0.5: 200 000 × 0.5 / 1 000 000 = $0.10 вместо $0.08 по цене входа. Подробнее про кэш см. статью про кэширование промптов. Но длинный контекст хуже контролировать (сложнее понять, на что опирался ответ), а при росте базы знаний придётся вернуться к поиску. Сравнение подходов есть в статьях про RAG своими руками и про длинный контекст.

Подключить ключ можно в кабинете. Если вас интересует не поиск, а прямая интеграция 1С с нейросетью, смотрите статью про интеграцию 1С.

Частые вопросы

Нужна ли для RAG векторная база?

Не обязательно. Для кода 1С BM25 по тексту часто работает достаточно хорошо, а для регламентов на естественном языке можно добавить векторный поиск с локальной моделью эмбеддингов.

Можно ли индексировать данные из базы?

Не стоит. Индексируйте код, метаданные и регламенты, но не записи с персональными данными и коммерческой информацией: вопросы и найденные фрагменты уходят провайдеру модели.

Как обновлять индекс?

Пересобирайте его после каждой выгрузки конфигурации. Для небольших проектов полная пересборка занимает секунды, потому что BM25 строится в памяти.

Как снизить выдуманные ответы?

Инструкция «отвечай только по фрагментам», обязательные ссылки на источник и проверка источника человеком.

zukko

Платите в 25×
меньше

за Claude Code & ChatGPT

Один ключ fetch_* и base URL api.zukko.pro — в Cursor, Claude Code, Codex и любом SDK.