Extrahování do JSON neznamená, že je extrakce správná: vytvořte pole smlouvy pro množství, jednotku a zdroj

To, že lze výsledek extrakce převést na JSON, neznamená, že je extrakce správná. Tento článek používá desetinné a polní kontrakty ke kontrole množství, jednotky, čísla stránky, původního textu a souřadnic a připojuje deterministické testy pro normální vstup a abnormální vstup, aby bylo možné chyby zastavit dříve, než se dostanou do downstreamu.

To, že výsledek extrakce může být analyzován pomocí JSON, neznamená, že může být přímo uložen v databázi. Tento článek je napsán pro vývojáře, kteří potřebují posílat data faktur a cenových nabídek do navazujících systémů. K demonstraci přísnějších hranic používáme syntetický fragment citace: kromě hodnoty má každé pole také jednotku, zdrojovou stránku, zdrojový text a souřadnice. Analyzátor nebo model je zodpovědný pouze za navrhování kandidátů a deterministický ověřovatel určuje, zda mohou být zahrnuti do databáze.

Po přečtení tohoto budete schopni pochopit myšlenku sady smluv o polích a budete vědět, jak explicitně zachovat chybějící a nejistá pole místo toho, abyste je ve výchozím nastavení vyplnili nulou.

Mohou být výsledky extrakce přímo uloženy v databázi? Závěr jednou větou

Zda jej lze vložit do databáze, závisí spíše na tom, zda projde terénní smlouva a ověření důkazů, než zda lze JSON analyzovat; pole, která se nepodaří ověřit, by měla být ponechána v nevyřízeném stavu a ve výchozím nastavení je nelze vyplnit nulou.

vaší situaciDoporučené postupydůvod
Analyzátor vrátil platný JSONPokračujte v ověřování smlouvy v terénu a neukládejte ji přímo do databáze.JSON znamená pouze to, že jej může program číst
Částka nemá žádnou měnu ani jednotkuNepřebírejte měnu, ponechte chybějící stavVyhněte se tajnému převzetí RMB
Částka se objevuje v regionálních formátech, jako je 1.200,50Definujte smlouvy samostatně pro každý povolený formátS regionálními pravidly nelze zacházet nenuceně a jednotně
Je třeba se vrátit do dokumentu a zkontrolovatUložte čísla stránek, zdrojový text a souřadnice a zkontrolujte rozsahy čísel stránekUsnadněte recenzentům základ pro umístění
Zapojení více měn nebo směnných kurzůPůvodní částka měny, typ měny a zdroj směnného kurzu jsou zachovány a neprovádí se žádná implicitní konverze.Částky nelze převést bez směnných kurzů

Předejte hodnotu spolu s důkazy

Odešlete fakturu nebo cenovou nabídku analyzátoru a JSON, který dostanete zpět, vám pouze řekne, že jej program dokáže přečíst. 1200 Je to jednotková cena nebo celková částka? Kde je měna? 1.200,50 je třeba chápat podle jakých regionálních pravidel? Opravdu existuje vrácené číslo stránky? Toto nejsou otázky, na které může syntaxe JSON odpovědět.

Poleomezeníproč potřeba
množstvíDesetinný řetězec, příklad omezený na nezáporné a dvě desetinná místaVyhněte se neúmyslnému zavedení binárních aproximací s pohyblivou řádovou čárkou
měnaTato scéna je omezena na USDNepřebírejte tajně RMB, když neexistuje žádná měna
source.pageZačíná na 1 a nesmí překročit počet stránekUsnadněte uživatelům návrat do původního umístění dokumentu
zdroj.citátMusí to být fragment na stránce poskytnutý volajícímPoskytněte recenzentům viditelné důkazy
source.bboxKonečná hodnota v rozsahu stránekZabraňte prázdným krabicím a neplatným souřadnicím před vydáváním se za důkazy

Souřadnicovou jednotkou je zde bod PDF a počátek je levý horní roh aktuální dohodnuté stránky. Upstream by měl nejprve sjednotit systémy rotace, ořezávání a souřadnic a nemůže přímo míchat souřadnice různých analyzátorů. Tento příklad pouze demonstruje konvenci a nedokazuje, že text je skutečně obsažen v rámečku.

Dokončete ověření a testování odmítnutí

Lze jej spustit pouze pomocí standardní knihovny Pythonu. Decimal musí být sestaven z řetězce, nepřevádějte jej nejprve na float a poté jej nepředávejte. Přesné desítkové zpracování částek naleznete v Desítková dokumentace Pythonu.

Níže uvedený kód je skutečným výstupem testu, nikoli zprávou o přesnosti rozpoznávání. Vzorové vstupy jsou ručně psané námi a na skutečných účtech nebylo provedeno žádné OCR nebo modelové vyhodnocení.

from copy import deepcopy
from decimal import Decimal
import math
import re

pages = [{"width": 595, "height": 842,
          "text": "Total: USD 1,200.50\nDelivery within 10 days"}]

def validate(candidate, pages):
    if set(candidate) != {"amount", "currency", "source"}:
        raise ValueError("unexpected or missing field")
    raw = candidate["amount"]
    if not isinstance(raw, str) or not re.fullmatch(r"(?:0|[1-9][0-9]*)\.[0-9]{2}", raw):
        raise ValueError("amount must be a two-decimal string")
    if candidate["currency"] != "USD":
        raise ValueError("unsupported currency for this contract")
    src = candidate["source"]
    if not isinstance(src, dict) or set(src) != {"page", "quote", "bbox"}:
        raise ValueError("source contract mismatch")
    number = src["page"]
    if type(number) is not int or not 1 <= number <= len(pages):
        raise ValueError("page outside document")
    page = pages[number - 1]
    quote = src["quote"]
    if not isinstance(quote, str) or not quote or quote not in page["text"]:
        raise ValueError("source quote not found")
    match = re.fullmatch(r"Total: USD ([0-9]{1,3}(?:,[0-9]{3})*\.[0-9]{2})", quote)
    if not match or Decimal(match[1].replace(",", "")) != Decimal(raw):
        raise ValueError("amount does not agree with source")
    box = src["bbox"]
    if (not isinstance(box, list) or len(box) != 4
            or any(type(v) not in (int, float) or not math.isfinite(v) for v in box)):
        raise ValueError("invalid box values")
    x0, y0, x1, y1 = box
    if not (0 <= x0 < x1 <= page["width"] and 0 <= y0 < y1 <= page["height"]):
        raise ValueError("box outside page or empty")
    return {"amount": str(Decimal(raw)), "currency": "USD", "source": deepcopy(src)}

good = {"amount": "1200.50", "currency": "USD", "source": {
    "page": 1, "quote": "Total: USD 1,200.50", "bbox": [40, 70, 260, 90]}}
assert validate(good, pages)["amount"] == "1200.50"
print("PASS valid source-linked amount: USD 1200.50")
bad_cases = []
wrong = deepcopy(good); wrong["amount"] = "12000.50"; bad_cases.append(wrong)
wrong = deepcopy(good); wrong["source"]["page"] = 2; bad_cases.append(wrong)
wrong = deepcopy(good); wrong["source"]["bbox"][2] = float("nan"); bad_cases.append(wrong)
wrong = deepcopy(good); wrong["source"]["bbox"][0] = 300; bad_cases.append(wrong)
for index, wrong in enumerate(bad_cases, 1):
    try:
        validate(wrong, pages)
        raise AssertionError("bad candidate accepted")
    except ValueError as error:
        print(f"PASS rejection {index}: {error}")

Pravidelnost je přísná, protože scéna je přísná

Tento regulární výraz přijímá pouze anglický formát částky v příkladu. Odmítá následující situace:

  • evropské desetinné číslo
  • záporné číslo
  • Vrácení peněz je uvedeno v závorkách
  • Ostatní měny
  • Čtyřmístná čísla bez tisícin

Skutečné systémy by si měly vybírat nezávislé smlouvy na základě typu dokumentu a regionu, a ne pouze mazat všechny čárky, tečky a mezery.

Před dalším rozšiřováním vstupního rozsahu si připravte příklady pozitivních a zamítnutých položek pro každý povolený formát. Pokud se jedná o bankovku ve více měnách, měla by být v polích zachována původní částka v měně, měna a zdroj směnného kurzu; bez směnného kurzu nelze částku tajně převést.

📊 Srovnání jádra

Zkontrolujte hladinuOtázky, na které lze odpovědětStále nezodpovězené otázky
Analýza JSONZda může program číst obsahJe částka jednotkovou cenou nebo celkovou částkou a jaká je měna?
terénní smlouvaJsou formát částky, měna, rozsah čísel stránek a souřadnice legální?Zda souřadnicový rámeček přesně zalamuje text
Kontrola zdrojeZda v textu aktuální stránky existuje citace a zda se částka rovná omezenému formátuJe čára skutečným konečným součtem pro firmu?

"Osvědčený" neznamená "osvědčený"

Program ověří, že v textu aktuální stránky existuje citace a že se částka rovná tomuto omezenému formátu. Neověřuje, že souřadnicový rámec přesně zalamuje původní text, ani neurčuje, zda je řádek skutečným součtem podniku. Upstream textové vrstvy mohou pocházet z chybného OCR a na stejné stránce se může objevit více součtů.

Proto jsou smlouvy v terénu pouze prvními dveřmi. Dále jsou vyžadovány následné kontroly konzistence umístění, jednoznačné rozlišení kandidátů na stejné stránce, ověření vztahu mezisoučtu a celkové daně a ruční vzorkování. Než důležitá obchodní data projdou těmito dveřmi, měla by být uložena ve stavu „k ověření"namísto „potvrzeno".

Jak to implementovat do workflow dokumentů

Uchovávejte shrnutí původního souboru, zaznamenejte zpracovanou verzi pro každou extrakci a uložte důvod zamítnutí. Proces překladu by měl být také kontrolován pomocí stejných polí: text lze změnit do jiných jazyků, ale nelze ztratit shodu mezi důležitými částkami a jednotkami. O souvisejících dokumentových službách se můžete dozvědět prostřednictvím Produktový portál OmniDoc; smlouva a kód v tomto článku jsou nezávislé na rozhraní API produktu a nespoléhají na žádná nezveřejněná rozhraní.

🎯 Která metoda je pro vás vhodná?

Pokud chcete zpracovávat účty ve více měnách

Zachovejte původní částku a typ měny a zaznamenejte zdroj směnného kurzu. Pokud neexistuje směnný kurz, nebude proveden žádný převod.

Pokud chcete rozšířit rozsah vstupních formátů

Nejprve napište pozitivní příklady a příklady odmítnutí pro každý formát a poté pravidla uvolněte. Neuvolňujte přímo pravidelná pravidla.

Pokud budou data použita pro finanční nebo obchodní rozhodnutí

Označte pole jako čekající na ověření a poté jej potvrďte po konzistenci umístění, jednoznačné jednoznačnosti a ručním vzorkování.

Pokud chcete udělat překlad dokumentů

Jazyk textu lze změnit, ale odpovídající vztah mezi částkou a jednotkou musí být zachován pomocí stejného auditu v terénu.

❓ Často kladené otázky (FAQ)

1. Pokud lze JSON analyzovat, lze jej přímo uložit do databáze?

žádný. Analýza pouze ukazuje, že program může číst obsah, a také vyžaduje terénní smlouvu a ověření důkazů.

2. Program ověřil cenovou nabídku, znamená to, že částka musí být správná?

žádný. Pouze ověřuje, že v textu aktuální stránky existuje citace a že se částka rovná omezenému formátu, a neověřuje souřadnicový rámec ani celkový význam podniku.

3. Proč nelze chybějící částku považovat za 0?

Chybějící množství, neúspěšné ověření a skutečně nula jsou tři různé stavy a jejich smícháním bude pro následné uživatele obtížné rozlišit.

4. Jak by se mělo zacházet s víceměnovými účty?

Původní částka v měně a typ měny jsou zachovány. Nepřevádějte částky, když neexistuje žádný směnný kurz, a ponechte zdroj směnného kurzu.

📝 Shrnutí

Výsledky extrakce jsou použitelné na základě smlouvy, důkazů a akceptace, nikoli pro samotný formát JSON. Každé pole by mělo být dohledatelné zpět na určitou stránku v dokumentu a data, která se nepodaří ověřit, zůstanou čekající na ověření.

Vyzkoušejte to hned: Nahrajte dokument a začněte překládat při zachování původního rozvržení

Aktualizováno 2026-11-14