Iluzja „gotowego AI” w środowisku enterprise#
Wdrożenie generatywnej sztucznej inteligencji w firmach B2B przebiega często według tego samego, rozczarowującego scenariusza:
- Zespół buduje szybki prototyp w oparciu o popularny framework (np. naiwny LangChain) i publiczne API LLM.
- Na prostych prezentacjach demo wszystko wygląda spektakularnie – asystent odpowiada na pytania o firmowe regulaminy.
- System trafia na środowisko produkcyjne i... zaczyna generować krytyczne błędy:
- Przypisuje klientowi rabat 90% na podstawie wyrwanego z kontekstu fragmentu umowy,
- Myli numer przesyłki kurierskiej o jedną cyfrę, uniemożliwiając rozliczenie reklamacji w ERP,
- Halucynuje nieistniejące stany magazynowe lub zasady zwrotu towarów.
W środowisku B2C halucynacja chatbota może być anegdotą. W procesach B2B, gdzie w grę wchodzi odpowiedzialność finansowa, umowy SLA i operacje na bazach danych, nawet 1% halucynacji dyskwalifikuje system z wdrożenia produkcyjnego.
Dlaczego naiwny RAG (Vector-Only) zawodzi w biznesie?#
Większość tutoriali proponuje prosty mechanizm: weź dokumenty -> podziel na chunki -> wygeneruj wektory (embeddings) -> wyszukaj Cosine Similarity -> wyślij do promptu LLM.
To podejście dramatycznie zawodzi w trzech kluczowych obszarach:
1. Utrata precyzji leksykalnej#
Wyszukiwanie wektorowe operuje na znaczeniu semantycznym, a nie na dokładnych ciągach znaków. Jeśli zapytasz o numer faktury FV/2026/11/0491 lub kod części SKU-883-X9, silnik wektorowy może uznać za „bardzo podobny” rekord o numerze FV/2026/11/0492, ponieważ ich kontekst językowy jest niemal identyczny.
2. Brak strukturalnej kontroli typów (Free-text Trap)#
Zwrócenie przez model odpowiedzi w formie naturalnego tekstu (nawet z prośbą „odpowiedz w formacie JSON”) prędzej czy później zakończy się błędem parsowania: model doda komentarz przed nawiasem klamrowym, użyje pojedynczych cudzysłowów lub zmieni nazwę klucza z refund_amount na amount_to_refund.
3. Brak idempotencji operacji zapisu#
Jeśli agent AI ma uprawnienie do zmiany stanu w systemie ERP (np. anulowanie zamówienia, zatwierdzenie korekty), ponowienie zapytania sieciowego bez klucza idempotencji może doprowadzić do podwójnego wykonania operacji finansowej.
Architektura Deterministycznego RAG (Zero-Hallucination Framework)#
Aby zbudować odporny na błędy, audytowalny silnik AI klasy enterprise, stosujemy architekturę trójwarstwową:
[Zapytanie użytkownika / API Webhook]
│
▼
[Warstwa 1: Hybrydowy Retrieval]
├── [BM25 Full-Text Search (Elastic / PostgreSQL Fulltext)]
│ (Precyzja leksykalna: kody SKU, NIP-y, numery przesyłek)
└── [Dense Vector Search (pgvector / Qdrant)]
(Precyzja semantyczna: intencja, polityki, regulacje)
│
▼ (Reranking: BGE-Reranker / Cross-Encoder)
│
[Warstwa 2: Deterministyczne Guardrails]
├── [Pydantic / Instructor Strict JSON Schema]
├── [Walidacja reguł biznesowych: kwoty, limity, uprawnienia]
└── [Confidence Score Threshold (np. ≥ 0.92)]
│
├── (Jeśli confidence < 0.92 ──► Human-in-the-Loop)
▼
[Warstwa 3: Idempotentna Egzekucja w ERP]
├── [Sprawdzenie unikalnego Idempotency-Key]
├── [Zapis transakcyjny do bazy danych SQL]
└── [Niezmienny audyt w logach (Prompt + Reasoning + Output)]
Implementacja techniczna: Pydantic & Instructor#
Zamiast przekazywać surowy tekst do bazy danych, zmuszamy model LLM do zwrócenia deterministycznego typu Pydantic za pośrednictwem biblioteki Instructor:
from pydantic import BaseModel, Field, field_validator
from decimal import Decimal
from typing import Literal
class DisputeResolutionDecision(BaseModel):
"""Ściśle walidowana decyzja agenta AI dotycząca sporu handlowego."""
case_id: str = Field(description="Identyfikator sprawy w ERP")
decision: Literal["APPROVE_REFUND", "REJECT", "ESCALATE_TO_HUMAN"]
refund_amount_net: Decimal = Field(ge=0, le=5000, description="Kwota refundacji netto")
justification_rule_code: str = Field(description="Kod regulaminowy uzasadniający decyzję")
confidence_score: float = Field(ge=0.0, le=1.0)
@field_validator("refund_amount_net")
@classmethod
def validate_positive_for_approval(cls, v: Decimal, info) -> Decimal:
if info.data.get("decision") == "APPROVE_REFUND" and v <= 0:
raise ValueError("Decyzja o refundacji wymaga kwoty większej od 0")
return v
Jeśli model spróbuje wygenerować nieprawidłową kwotę lub pominie wymagany kod regulaminowy, biblioteka Instructor automatycznie wyśle błąd walidacji z powrotem do modelu z prośbą o samokorektę (Self-Correction Loop), nie dopuszczając wadliwych danych do systemu ERP.
3 Złote Zasady dla CTO wdrażających AI#
- Hybrydowy search to konieczność: Nigdy nie polegaj wyłącznie na wektorach w danych biznesowych. Połączenie BM25 z pgvector daje najlepsze rezultaty z obu światów.
- LLM jako parser, nie jako sędzia: Model językowy powinien wyciągać fakty i strukturę z dokumentów, ale to deterministyczny kod w Pythonie/Go powinien decydować o zatwierdzeniu operacji finansowej.
- Loguj wszystko (Audit Trail): Każde wywołanie modelu musi być powiązane z unikalnym identyfikatorem zapytania, użytym promptem systemowym i wersją wag modelu, aby sprostać wymogom compliance (RODO, EU AI Act).

