Знакът на КАГАМИ КАГАМИ
kagami.bg/academy · lesson · machine-readable viewUPDATED 2026-10-01 · VERIFIED 2026-10-01 (code run in a sandbox, no model)
IDENTITY
module
KW I24 · Numbers are read by code, not by a model
series
KAGAMI Way · Track I — Infrastructure
level
Intermediate
duration
~20 min
trust_label
UPDATED 2026-10-01 (code examples use fictional data, EUR; VAT 20%, rate 1.95583 and rounding verified against official sources) · VERIFIED 2026-10-01 (code executed in a sandbox with Python 3 and Decimal; no language model was run) · not TESTED with a model in this edition
language
human view: bg · english edition: /en/academy/moduli/KW_I24_Numbers_By_Code.html
next
KW_I25_Same_Model_Other_Machine.html · Same model, another machine
PURPOSE

A language model may copy a number as a string and must not convert one. This module separates the two operations, shows the failure shapes seen on Bulgarian-formatted figures, and gives the code-side checks that must sit behind every extracted record: re-add rows, recompute VAT and currency, order-of-magnitude check, keep the raw string.

KEY CONCEPTS
COMMANDS / PATHS
CHECKLIST
NEXT MODULE

KW_I25_Same_Model_Other_Machine.html · Same model, another machine · offer: Quick experiment (kagami.bg/stalbata/)

SOURCES
TAGS
numbersvalidationparsinglocaledecimalaudithuman-in-the-loop
ОБНОВЕНО · 01.10.2026 ПРОВЕРЕНО · 01.10.2026

Числата се разчитат с код, не с модел

Един и същ модел преписва „1 849,97“ съвършено вярно и превръща „3,6 kW“ в 3600. Разликата не е в трудността, а в операцията: преписването е копиране, превръщането е тълкуване. Само едното е безопасно — затова моделът копира числата, а кодът ги смята.

⏱ ~20 мин Средно Локален AI числа · валидиране · човек в контура
Python (Decimal)🔒 локално Езиков модел (локален или облачен)🌐 глобален модел

01Какво ще научиш

02Преди да започнеш

ℹ️
Какво е и какво не е проверено
Кодът в урока е изпълнен в пясъчник (Python 3, без езиков модел) и резултатите по-долу са от това изпълнение. Урокът не е изпитван наново с модел. Ставката на ДДС, курсът и правилото за закръгляване са сверени с официални източници на 01.10.2026 (виж „Източници“).

03Стъпки

  1. Преписване срещу превръщане

    Когато моделът върне числото като низ, точно както стои в документа, той просто го е пренесъл. Тази операция е надеждна — същият модел я прави вярно дори върху разкривен текст от OCR. Когато обаче трябва да върне число, някой трябва да реши къде е десетичният знак, кое е разделител на хиляди и кое е мерна единица. Това е тълкуване и тук моделът греши.

    ВходътКакво излизаКакво е станало
    3,6 kW3600запетаята е взета за разделител на хиляди
    742,31857423185запетаята е премахната изцяло
    250 kWh250000интервалът преди единицата е взет за хиляди
    „хиляда двеста тридесет и четири евро и 56 цента“1204,56изписаното с думи е сглобено с една сгрешена цифра

    Примерите са измислени, но формите на грешка са тези, които се срещат при български формат: десетична запетая, интервал за хиляди, единица след числото и сума с думи.

    ⚠️
    Размерът не е гаранция
    В наши вътрешни проби модел от 3,3 GB даде 10 от 10 на същия списък, а модел от 5,2 GB сгреши 5 от 10 — устойчиво, при всяко пускане. Не е повторено за това издание. Изводът за работата е същият: не се решава с по-голям модел, а с друго разпределение на труда.
  2. Тихата грешка

    Грешките от превръщане имат общо свойство: нищо не се оплаква. Няма изключение, няма предупреждение. Излиза число, което изглежда точно като число. Разликата между 1 234,56 и 1 204,56 е една цифра и нищо в отговора не подсказва коя е вярната.

    Клас А — шумен провал. Моделът връща каша, невалиден JSON или отказва. Следващата стъпка не може да прочете входа и спира.
    Клас Б — тих провал. Моделът връща правдоподобен запис със сгрешено число. Минава всяка проверка за форма, влиза в регистъра и се открива месеци по-късно — ако изобщо се прави сверка.

    ⛔
    Правилото
    Моделите се оценяват по класа на провала, не по обща оценка. Модел от клас Б е по-опасен от модел от клас А със същия резултат в таблицата.
    ✅
    Разделението на труда
    Моделът чете, разпределя и намира. Кодът смята, превръща и сверява. Числото пътува през веригата като низ колкото може по-дълго и става число на едно-единствено място — в код, с тест.
  3. Сверката с код

    Всеки извлечен запис с числа минава през няколко реда проверки. Те не поправят нищо — вдигат флаг. Поправката е работа на човек, защото поправка без поглед е същата грешка с друг автор.

    Парите се смятат с Decimal, не с float: двоичното дробно число не може да представи точно 2,675 и round(2.675, 2) връща 2,67, докато десетичното закръгляване „половината нагоре“ дава 2,68. При пускане в пясъчника видяхме точно това.

    python · четири проверки върху измислен запис
    from decimal import Decimal, ROUND_HALF_UP
    RATE = Decimal("1.95583")   # фиксиран курс: лева за 1 евро
    CENT = Decimal("0.01")
    
    def to_dec(raw):
        # единственото място, където низ става число
        s = raw.replace(" ", "").replace(" ", "").replace(",", ".")
        return Decimal(s)
    
    def eur_to_bgn(eur):
        return (eur * RATE).quantize(CENT, rounding=ROUND_HALF_UP)
    
    def check(r):
        flags = []
        rows = [to_dec(x["amount_raw"]) for x in r["rows"]]
        net, vat, total = to_dec(r["net_raw"]), to_dec(r["vat_raw"]), to_dec(r["total_raw"])
        if sum(rows) != net:
            flags.append("сборът на редовете не съвпада с нетото")
        if (net * Decimal("0.20")).quantize(CENT, ROUND_HALF_UP) != vat:
            flags.append("ДДС не е 20% от нетото")
        if net + vat != total:
            flags.append("нето + ДДС не е равно на общото")
        if eur_to_bgn(total) != to_dec(r["total_bgn_raw"]):
            flags.append("сумата в лева не отговаря на фиксирания курс")
        return flags
    
    record = {   # ООД „Пример“, ЕИК 000000000 — измислен запис
        "rows": [{"amount_raw": "1 000,00"}, {"amount_raw": "541,64"}],
        "net_raw": "1 541,64", "vat_raw": "308,33",
        "total_raw": "1 849,97", "total_bgn_raw": "3 618,23",
    }
    print(check(record))   # []  — няма флагове

    Изпълнение в пясъчник: измисленият запис излиза без флагове. Ако вторият ред е сгрешен на „514,64“ (разменени цифри), проверките вдигат флаг „сборът на редовете не съвпада с нетото“ и документът остава непипнат.

    Четирите задължителни проверки

    1. Пресмятане наново. Съберѝ редовете и сравни с обявеното. 2. Превръщане от кода. Всяко производно число (ДДС, сума в друга валута) се пресмята пак, никога не се приема наготово. 3. Проверка за порядък. Стойност, която се различава от съседите си с хиляда пъти, е заподозряна по презумпция. 4. Суровият низ остава. До всяко превърнато число стои текстът, от който е дошло — иначе сверката после е невъзможна.

    ℹ️
    Защо флаг, а не поправка
    Автоматичната поправка изглежда като услуга и се държи като загуба на следа. Флагът струва на човека десет секунди и оставя документа такъв, какъвто е.
    ✅
    Сверено на 01.10.2026: ставка, курс, закръгляване
    Стандартната ставка по чл. 66, ал. 1 от ЗДДС е 20 на сто. Фиксираният курс е 1 EUR = 1,95583 BGN (решение на Съвета на ЕС от 8 юли 2025 г., съобщено от ЕЦБ). Официалният калкулатор на evroto.bg (Министерство на финансите) прилага този курс и математическото правило за закръгляване — до цент, „половината нагоре“, както в кода по-горе. Намалените ставки по ЗДДС (например 9 %) тук не се разглеждат: проверката е за документи със стандартна ставка.
  4. И електронната таблица лъже

    Правилото не е само за езикови модели — то е за числата изобщо. Същата тиха грешка живее и в таблиците, които хората попълват от години, само че там никой не я търси.

    При преглед на месечни протоколи, водени в електронна таблица, излязоха три сгрешени формули. Едната умножаваше количеството по празна клетка — формулата е валидна, резултатът е нула. Друга носеше твърдо вписана стара тарифа от предишна година. Никоя не даде грешка. Един ред показваше 3,03 за 50 кубика три месеца подред — и минаваше, защото никой не сравняваше количеството със сумата.

    Проверката е същата като при модела: сборът на редовете срещу обявеното общо и количество срещу сума по тарифа. Две сравнения, които се пишат веднъж и се пускат върху целия архив, а не само върху последния месец.

    ⚠️
    Уроците
    Проверявай формулите, не само стойностите: отвори файла на ниво формула, иначе виждаш точно това, което таблицата иска да ти покаже. И общото правило: колона, която се смята, не се въвежда и не се извлича — смята се при четене, от код, върху суровите стойности. Ако хранилището не умее изчислима колона (а повечето прости хранилища не умеят), сметката живее в изгледа, не в таблицата.

04Проверка

1. Коя операция е безопасна за езиков модел?

2. Кой клас грешка е по-опасен?

3. Какво прави сверката, когато сборът на редовете не съвпада с общото?

4. Защо суровият низ се пази до превърнатото число?

05Какво следва

06Източници

  1. Python: модулът decimal — десетична аритметика и закръгляване (ROUND_HALF_UP).
  2. Python: дробните числа и техните ограничения — защо round(2.675, 2) дава 2,67.
  3. Закон за данъка върху добавената стойност — чл. 66, ал. 1: стандартна ставка 20 на сто (сверено на 01.10.2026).
  4. ЕЦБ, 8 юли 2025 г. — България влиза в еврозоната на 1 януари 2026 г.; курсът е фиксиран на 1,95583 лв. за 1 евро.
  5. evroto.bg (Министерство на финансите) — калкулатор по фиксирания курс и математическото правило за закръгляване.
  6. Собствени наблюдения на КАГАМИ при извличане на суми от български документи и при преглед на таблици (не са повторени за това издание). Кодовите примери в урока са с измислени данни.