RAG for 1C: searching documentation and configuration code with AI

Build an assistant that answers questions about your configuration and internal rules with a source reference. Python code and a per-query cost estimate.

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

A typical situation in a company running 1C: accounting rules sit in documents, the logic in tens of thousands of lines of modules, and only one person knows the answer to "where do we calculate the discount". RAG for 1C solves this by first finding the relevant pieces of code and documents, then passing them to the model together with the question, and the model answers with a source reference. Below are the scheme, Python code and a cost estimate, and at the end a word on when RAG is not needed at all.

What RAG is in plain words

A model does not know your configuration, and pasting everything into a request is impossible or expensive. So it is done in two steps:

  1. Search. For the question, the several best-matching fragments are picked from your knowledge base.
  2. Answer. The fragments and the question go to the model with the instruction "answer only from these materials and name the source".

This way the neural network for working with 1C gets the context it needs, and you pay only for the few thousand tokens that actually went into the request.

What to index

Decide right away what goes into the index and what must stay out.

Suitable:

  • configuration modules (.bsl) from a dump to files;
  • descriptions of metadata objects: catalogs, documents, registers and their attributes;
  • internal rules and user instructions;
  • documentation you have the right to use: check the license terms of reference materials before loading them into a third-party service.

Not suitable:

  • the contents of the information base itself: personal data of customers and employees, counterparty prices, salaries;
  • passwords, connection strings and access keys from modules and settings.

If the code contains secrets, clean them out before indexing. Questions and the found fragments go to the model provider, and this must be reflected in your security policy.

How to split code: by procedure

Split code not into fixed-length pieces but at the boundaries of procedures and functions. Then a fragment holds complete logic rather than half a condition. Add a header with the file path to each piece: you will use it later to cite the source.

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

The cut at 3000 characters guards against gigantic procedures. Rules in text files are split by paragraph or section the same way. (The pattern matches the Russian keywords Процедура and Функция; if your code uses the English keywords Procedure and Function, add them to the pattern.)

Search: start with BM25

Plain text search is useful for 1C code: identifiers, object names and keywords match literally. The BM25 algorithm from the rank_bm25 library is enough to begin with. Russian morphology is roughly compensated by truncating words to five letters:

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]

About embeddings. Semantic vector search is useful for rules written in natural language. The gateway's endpoint list (chat completions, responses, messages, models) has no separate embeddings method, so for vector search use a local embeddings model and use the gateway for generating the answer. The most reasonable path: BM25 for code, vector search for texts if needed, and merge the results.

Generating the answer with sources

bash
from openai import OpenAI

client = OpenAI(base_url="https://api.zukko.pro/v1", api_key="fetch_your_key")

SYSTEM = """You are an assistant for a 1C configuration. Answer only from the given fragments.
For every claim, name the source in the format [file path].
If the answer is not in the fragments, say: "The found materials do not contain the answer"
and suggest which search query to try. Do not invent anything."""


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)
    # no temperature: newer Claude models reject values other than 1.0

If you want to control answer variation with temperature, check whether the chosen model accepts it: newer Claude models reject values other than 1.0, so the example does not set it.

How to ask questions

  • Name objects as in the metadata: "Document РеализацияТоваровУслуг", not "sales".
  • One question, one topic. Split compound questions.
  • If the answer is "not in the materials", ask the model to suggest another search query and repeat.
  • Check the source reference: open the file and make sure the code really says what the model said.

What a query costs

An assumption: 6 fragments of 400 tokens, plus the question and instruction of 400 tokens, so 2800 input tokens and 500 output tokens. Prices as of 18 October 2026, dollars per 1M tokens.

claude-sonnet-5-5 (0.4 / 2): 2800 × 0.4 / 1,000,000 = $0.00112 500 × 2 / 1,000,000 = $0.001 Total $0.00212, a thousand queries about $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 Total $0.001416, a thousand queries about $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 Total $0.0000554, a thousand queries about $0.055.

We do not claim which model answers more accurately on your code: take 20 real questions with known answers and test two or three models. Current prices: GET https://api.zukko.pro/v1/models.

When RAG is not needed

If your corpus is small, it can be put into the request whole: models have contexts up to 1M tokens. For 200,000 tokens of code and documents, the price of one request on claude-sonnet-5-5:

200,000 × 0.4 / 1,000,000 = $0.08 at the input price.

In the Anthropic format, on repeated requests with the same prefix, a cache read costs 0.05: 200,000 × 0.05 / 1,000,000 = $0.01. The first request pays for these tokens as a cache write at 0.5: 200,000 × 0.5 / 1,000,000 = $0.10 instead of $0.08 at the input price. More on the cache in the post on prompt caching. But a long context is harder to control (it is harder to see what the answer relied on), and as the knowledge base grows you will have to return to search. Approaches are compared in the posts on RAG by hand and on long context.

You can connect a key in the dashboard. If you are interested not in search but in direct integration of 1C with a neural network, see the post on 1C integration.

FAQ

Do I need a vector database for RAG?

Not necessarily. For 1C code, BM25 over text often works well enough, and for natural-language rules you can add vector search with a local embeddings model.

Can I index data from the base?

You should not. Index code, metadata and rules, but not records with personal and commercial data: questions and the found fragments go to the model provider.

How do I update the index?

Rebuild it after each configuration dump. For small projects a full rebuild takes seconds because BM25 is built in memory.

How do I reduce invented answers?

The instruction "answer only from the fragments", mandatory source references and a human check of the source.

zukko

Pay 25×
less

for Claude Code & ChatGPT

One fetch_* key and base URL api.zukko.pro — for Cursor, Claude Code, Codex, and any SDK.

Get API keyDocumentation

api.zukko.pro · fetch_*

RAG for 1C: search over code and documentation · Zukko