Ustrukturyzowane dane wyjściowe w wielomodelowej bramie API: schemat JSON, wywołania narzędzi i zabezpieczenia semantyczne
Praktyczny wzorzec adaptera zapewniający niezawodne ustrukturyzowane wyniki u wielu dostawców LLM: normalizuj schematy, sprawdzaj odpowiedzi, obsługuj wywołania narzędzi, rejestruj awarie i blokuj niebezpieczne działania, zanim dotrą do produkcyjnych przepływów pracy.
Namawianie modelu do „zwrotu JSON” nie jest umową produkcyjną. Może wygenerować prawidłowy JSON z nieprawidłowym wyliczeniem, pominąć wymaganą regułę biznesową lub w sposób pewny zażądać akcji, której użytkownik nigdy nie autoryzował. W przepływie pracy obejmującym wielu dostawców problem staje się trudniejszy: każdy dostawca udostępnia różne mechanizmy ustrukturyzowanego wyniku i użycia narzędzi, a każdy obsługuje tylko część JSON uniwersum schematu.
Praktyczne rozwiązanie to nie jedna magiczna wskazówka. Jest to wzorzec bramy warstwowej: znormalizuj schemat pożądany przez programistę, przetłumacz go na natywne dla dostawcy formaty ustrukturyzowanych danych wyjściowych lub formaty wywołań narzędzi, jeśli to możliwe, zweryfikuj zwrócony obiekt i zastosuj bariery semantyczne przed jakimkolwiek skutkiem ubocznym.
W tym przewodniku wyodrębniono trzy różne cele, które często są ze sobą mieszane:
- Ważność składni: odpowiedź można przeanalizować JSON.
- Ważność schematu: JSON pasuje do wymaganych pól, typów, wyliczeń i reguł strukturalnych.
- Poprawność biznesowa: obiekt jest bezpieczny, wierny intencjom użytkownika i ważny dla dalszych działań.
Awaria produkcji: poprawna JSON, nieprawidłowe działanie
Rozważ automatyzację obsługi, która kieruje przychodzące zgłoszenia:
{
"ticket_id": "t_481",
"category": "billing",
"priority": "urgent",
"action": "refund_customer",
"amount_usd": 499
}
Ten obiekt jest poprawny składniowo. Może nawet przekazać prosty schemat, jeśli action jest ciągiem znaków, a amount_usd jest liczbą. Ale nadal może się mylić. Być może klient poprosił jedynie o kopię faktury. Być może zwroty powyżej 100 USD wymagają zgody menedżera. Być może użytkownik nie jest w ogóle upoważniony do wywoływania zwrotów pieniędzy.
Ustrukturyzowane dane wyjściowe redukują błędy analizy. Nie zastępują autoryzacji, kontroli zasad, kontroli zapasów, kontroli cen, idempotencji ani potwierdzenia przez człowieka w przypadku ryzykownych operacji.
Fakty: jakie tryby ustrukturyzowanego wyjścia dostawcy zapewniają, a jakich nie obiecują
Krajobraz dostawców zmienia się szybko, ale dla architektury ma znaczenie kilka stabilnych faktów:
-
Tryb
- JSON może pomóc w uzyskaniu prawidłowego JSON, ale prawidłowy JSON to nie to samo, co zgodność z określonym schematem.
- Tryby strukturalnego wyjścia natywne dla dostawcy zostały zaprojektowane w celu poprawy zgodności ze schematem, ale zwykle obsługują tylko podzbiór JSON schematu.
- Wywoływanie narzędzi zwykle lepiej pasuje do działań niż swobodne JSON, ponieważ model wybiera zadeklarowane narzędzie i zwraca argumenty strukturalne, podczas gdy aplikacja pozostaje odpowiedzialna za wykonanie.
- Różni dostawcy udostępniają różne umowy. Jeden może użyć ścisłego JSON formatu odpowiedzi według schematu, inny może używać schematów wprowadzania danych za pomocą narzędzia, a jeszcze inny może wymagać awaryjnego sprawdzania poprawności i ponownej próby.
- Nawet dane wyjściowe zgodne ze schematem mogą być semantycznie błędne, zanim dotrą do bazy danych, przepływu pracy lub płatnej akcji.
Konsekwencje architektoniczne są proste: OpenAIkompatybilny API może ujednolicić interfejs klienta, ale warstwa niezawodności musi nadal rozumieć możliwości dostawcy i weryfikować wyniki po wygenerowaniu.
Zalecana architektura: adapter wyjścia strukturalnego
Użyj adaptera po stronie bramy pomiędzy kodem aplikacji a interfejsami API dostawcy. Aplikacja wysyła jedną intencję schematu. Brama mapuje tę intencję na najsilniejszy obsługiwany mechanizm dostawcy.
1. Zaakceptuj jedno znormalizowane żądanie z aplikacji
Klient nie powinien potrzebować oddzielnych ścieżek kodu dla każdego dostawcy. Praktyczna koperta żądania obejmuje preferencje modelu, dane wejściowe zadania, schemat, metadane schematu i poziom ryzyka:
{
"model": "auto:accurate",
"messages": [
{"role": "system", "content": "Extract invoice fields. Do not infer missing values."},
{"role": "user", "content": "Invoice text..."}
],
"structured_output": {
"schema_id": "invoice_extraction",
"schema_version": "2026-08-01",
"mode": "json_schema",
"strict": true,
"schema": {
"type": "object",
"additionalProperties": false,
"required": ["invoice_number", "vendor_name", "total", "currency", "due_date"],
"properties": {
"invoice_number": {"type": "string"},
"vendor_name": {"type": "string"},
"total": {"type": "number", "minimum": 0},
"currency": {"type": "string", "enum": ["USD", "EUR", "GBP"]},
"due_date": {"type": "string", "format": "date"},
"confidence": {"type": "number", "minimum": 0, "maximum": 1}
}
}
},
"metadata": {
"workflow": "accounts_payable",
"risk_level": "medium"
}
}
Ta umowa zapewnia bramie wystarczającą ilość informacji, aby wybrać implementację natywną dostawcy, przeprowadzić weryfikację i zarejestrować istotne dane o błędach.
2. Utrzymuj matrycę możliwości dostawcy
Brama powinna utrzymywać matrycę możliwości odczytywalną maszynowo, a nie opierać się na założeniach typu „wszystkie OpenAI kompatybilne modele obsługują to samo zachowanie schematu”. Przydatna macierz obejmuje:
- Nazwa dostawcy i modelu.
- Obsługuje tryb JSON.
- Obsługuje JSON format odpowiedzi schematu.
- Obsługuje wywołania narzędzi.
- Obsługuje tryb ścisłego schematu.
- Znane JSON Ograniczenia podzbioru schematu.
- Czy równoległe wywołania narzędzi są zgodne z trybem ścisłego schematu.
- Zachowanie awaryjne, gdy żądany tryb nie jest obsługiwany.
Przykładowy rekord możliwości:
{
"provider": "provider_a",
"model": "model_x",
"json_mode": true,
"json_schema_response": true,
"tool_calls": true,
"strict_schema": true,
"schema_limitations": ["no oneOf", "limited format validation"],
"fallback": "reject_or_route_to_compatible_model"
}
Ta macierz powinna zostać wersjonowana i przetestowana. Gdy dostawca zmienia zachowanie lub zostaje dodany nowy model, przed skierowaniem produkcji należy sprawdzić zgodność ustrukturyzowanych wyników.
3. Przetłumacz na najsilniejszą umowę natywną dla dostawcy
Adapter powinien przestrzegać jasnej kolejności preferencji:
- Użyj ścisłych, strukturalnych wyników natywnych dostawcy, jeśli jest to obsługiwane przez wybrany model i schemat.
- Używaj narzędzi natywnych dostawcy do wykonywania akcji i zadań podobnych do funkcji.
- Użyj nieścisłych wyników strukturalnych lub trybu JSON z walidacją i ponownymi próbami, gdy tryb ścisły jest niedostępny.
- Odrzuć żądanie, kieruj do zgodnego modelu awaryjnego lub zwróć odpowiedź nie zawierającą żadnych działań w przypadku przepływów pracy obarczonych wysokim ryzykiem.
Nie zmieniaj po cichu operacji wysokiego ryzyka z trybu ścisłego schematu do „najlepszego wysiłku JSON”. Jeśli aplikacja zażądała rygorystycznego zachowania, a wybrany dostawca nie może tego obsłużyć, brama powinna to uwidocznić poprzez błąd, decyzję o routingu lub wyraźną flagę zmiany wersji na niższą.
Trzy warstwy sprawdzania poprawności przed wykonaniem
Warstwa 1: weryfikacja analizy
Najpierw sprawdź, czy odpowiedź można rozłożyć na oczekiwaną kopertę. Szybka porażka w przypadku zniekształconych JSON, brakujących bloków wywołań narzędzi, obciętych odpowiedzi lub mieszanego języka naturalnego i JSON, gdy zabrania tego umowa.
function parseStructuredResponse(raw) {
try {
return { ok: true, value: JSON.parse(raw) };
} catch (error) {
return { ok: false, failure_type: "parse_failure", error: String(error) };
}
}
Wywołania narzędzi natywne dla dostawcy mogą nie wymagać analizowania obiektu typu blob z surowym tekstem, ale nadal wymagają sprawdzania poprawności koperty: czy model wybrał znane narzędzie, czy podał argumenty i czy zatrzymał się w celu wykonania narzędzia zgodnie z oczekiwaniami?
Warstwa 2: JSON Walidacja schematu
Następnie sprawdź poprawność obiektu względem zadeklarowanego schematu, używając walidatora po stronie serwera. Zrób to nawet wtedy, gdy dostawca twierdzi, że obsługuje ścisłe schematy. Walidacja po stronie bramy zapewnia spójne rejestrowanie błędów, chroni przed błędami integracji i wychwytuje niezgodności na dalszym etapie.
const validate = schemaValidator.compile(schema);
const valid = validate(object);
if (!valid) {
return {
ok: false,
failure_type: "schema_failure",
errors: validate.errors
};
}W celu zapewnienia przenośności zaprojektuj schematy z uwzględnieniem wspólnego podzbioru:
- Preferuj wyraźne
type,required,properties,enumiadditionalProperties: false. - Unikaj skomplikowanych kombinacji, takich jak głęboko zagnieżdżone
oneOf,anyOfi schematy warunkowe, chyba że wiesz, że docelowy dostawca je obsługuje. - Argumenty dotyczące działań powinny być małe i konkretne.
- Użyj ciągów znaków dla identyfikatorów, dat i kodów, chyba że dalsze systemy wymagają innego typu.
- Wyraźnie przedstaw niepewność za pomocą pól takich jak
confidence,missing_fieldslubrequires_human_review.
Warstwa 3: weryfikacja semantyczna i biznesowa
Na koniec sprawdź, czy ustrukturyzowany wynik jest prawidłowy dla zadania. Ta warstwa jest specyficzna dla domeny i nie można jej zlecić JSON samemu schematowi.
W przypadku wyodrębniania faktur kontrole semantyczne mogą obejmować:
- Suma nie jest ujemna i odpowiada elementom zamówienia w granicach tolerancji.
- Waluta pojawia się w dokumencie źródłowym.
- Termin porodu nie jest niemożliwie odległy w przeszłości lub przyszłości.
- Dostawca znajduje się na liście zatwierdzonych dostawców.
- Wiarygodność jest wystarczająco wysoka, aby można było wprowadzić wpis automatycznie.
W przypadku kwalifikacji potencjalnego klienta kontrole mogą obejmować:
- Wybrany segment jest jednym z aktywnych segmentów zespołu sprzedaży.
- Żądany budżet nie jest ustalany, jeśli użytkownik go nie podał.
- Akcja „demo książki” nie jest wykonywana, chyba że użytkownik wyraźnie o to poprosił.
W przypadku automatyzacji partnera API kontrole mogą obejmować:
- Konto sprzedawcy jest upoważnione do utworzenia żądanego klienta lub klucza.
- Żądany limit wydatków jest zgodny z zasadami partnera.
- Operacja ma klucz idempotencji.
- Działanie jest rejestrowane w dzienniku audytu przed wykonaniem.
Wywołania narzędzi: traktuj dane wyjściowe modelu jako żądanie, a nie wykonanie
Wywoływanie narzędzi jest właściwym wzorcem, gdy model musi poprosić aplikację o wykonanie jakiejś czynności: utworzenie zgłoszenia, wysłanie Telegram polecenia botowi, sprawdzenie cen, zaktualizowanie rekordu klienta lub rozpoczęcie przepływu pracy.
Bezpieczna pętla narzędzi wygląda następująco:
- Aplikacja deklaruje dostępne narzędzia i ich schematy wejściowe.
- Model zwraca wywołanie narzędzia z argumentami strukturalnymi.
- Brama sprawdza nazwę narzędzia i argumenty.
- Aplikacja sprawdza autoryzację, zasady, idempotencję i wymagania dotyczące potwierdzenia użytkownika.
- Dopiero wtedy aplikacja uruchamia narzędzie.
- Wynik narzędzia jest wysyłany z powrotem do modelu, jeśli rozmowa ma być kontynuowana.
Nigdy nie traktuj wywołania narzędzia jako dowodu, że akcja powinna zostać wykonana. Potraktuj to jako ustrukturyzowaną propozycję. Aplikacja pozostaje autorytetem w zakresie skutków ubocznych.
Bezpieczna drabina awaryjna dla przepływów pracy obejmujących wiele modeli
Brama powinna definiować zachowanie awaryjne przed wystąpieniem incydentów. Praktyczna drabina to:
- Podstawowy: ściśle ustrukturyzowane dane wyjściowe dotyczące preferowanego modelu.
- Zgodne rozwiązanie awaryjne: inny model obsługujący te same rygorystyczne wymagania dotyczące schematu.
- Weryfikacja i ponowna próba: dostawca bez ścisłego wsparcia, używany tylko wtedy, gdy pozwala na to ryzyko.
- Weryfikacja manualna: umieść w kolejce ustrukturyzowany wynik i treść źródłową do zatwierdzenia.
- Reakcja braku działania: wyjaśnij, że system nie może bezpiecznie ukończyć operacji.
Ponowne próby są przydatne w przypadku formatowania lub drobnych błędów schematu, ale nie stanowią strategii bezpieczeństwa. Jeśli obiekt jest semantycznie niebezpieczny, wielokrotne monitowanie może zamienić prawidłowe odrzucenie w niebezpieczny obiekt wykonywalny. W przypadku działań obarczonych wysokim ryzykiem preferuj sprawdzenie lub odmowę zamiast powtarzających się prób wymuszenia sukcesu.
Obserwowalność: rejestruj każdą decyzję dotyczącą ustrukturyzowanych wyników
Awarie wyjść strukturalnych to sygnały operacyjne. Rejestruj je z wystarczającą ilością szczegółów, aby ulepszyć routing, schematy i podpowiedzi bez ujawniania niepotrzebnych poufnych treści.
Zalecane pola:
schema_idischema_version.- Dostawca i model.
- Żądany tryb i aktualnie używany tryb.
- Stan błędu analizy.
- Stan błędu schematu i błędy sprawdzania poprawności.
- Przyczyna niepowodzenia weryfikacji semantycznej.
- Liczba ponownych prób.
- Opóźnienie.
- Wykorzystanie i koszt tokena.
- Stan działania końcowego: wykonane, umieszczone w kolejce, odrzucone lub zwrócone użytkownikowi.
- Zespół, projekt, klucz API lub identyfikator konta partnera, jeśli to konieczne.
Te dzienniki obsługują debugowanie, analizę kosztów, porównywanie dostawców i zarządzanie zespołem API. Pomagają także odpowiedzieć na pytania takie jak: „Która wersja schematu powoduje najwięcej ponownych prób?” oraz „Który model awaryjny spełnia składnię, ale nie przechodzi weryfikacji biznesowej?”
Zasady wersjonowania schematu
Schematy to interfejsy produkcyjne. Traktuj ich jak API kontrakty.
- Uwzględnij
schema_idischema_versionw metadanych i dziennikach żądań. - Nie zmieniaj po cichu wymaganych pól dla istniejących automatyzacji.
- Zachowaj dostępność starych schematów podczas migracji klientów.
- Dodaj nowe pola opcjonalne, zanim staną się wymagane.
- Testuj schematy względem każdego dostawcy i modelu awaryjnego w puli routingu.
- Zapisz, która wersja schematu została użyta w przypadku każdego działania wywołującego skutki uboczne.
Wersjonowanie staje się szczególnie ważne dla agencji, sprzedawców i automatyzacji Partnera API, gdzie wielu dalszych klientów może polegać na stabilnej umowie strukturalnej.
Kiedy nie należy wykonywać ustrukturyzowanego wyniku
Zatrzymaj się, gdy wystąpi którykolwiek z poniższych warunków:
- Odpowiedzi nie można przeanalizować.
- Obiekt nie przeszedł JSON walidacji schematu.
- Wartość wyliczeniowa jest nieobsługiwana lub wymyślona.
- Nie można podać ilości, ceny, daty ani waluty.
- Wynik jest sprzeczny z deklarowaną intencją użytkownika.
- Model wykazuje niski stopień pewności lub brakuje dowodów.
- Instrukcja użytkownika jest niejednoznaczna.
- Działanie ma skutki uboczne i brakuje potwierdzenia.
- Konto, zespół lub API klucz nie są autoryzowane.
- Odpowiedź dostawcy zawiera odmowę lub brak odpowiedzi ze względów bezpieczeństwa.
Zalecenia a prognozy
Zalecenia: tam, gdzie to możliwe, używaj ustrukturyzowanych wyników natywnych dostawcy, sprawdzaj poprawność każdej bramy odpowiedzi, preferuj wywołania narzędzi dla działań, utrzymuj macierz możliwości, schematy wersji i blokuj skutki uboczne do czasu zakończenia kontroli semantycznych.
Przewidywania: obsługa przez dostawców ustrukturyzowanych wyników prawdopodobnie stanie się silniejsza i bardziej spójna, ale przenośność pozostanie problemem, ponieważ rodziny modeli, podzbiory schematów i pętle wywołań narzędzi nie staną się identyczne z dnia na dzień. Zespoły, które teraz tworzą weryfikację, obserwowalność i wersjonowanie schematu, będą lepiej przygotowane do przyjęcia nowych funkcji dostawców bez konieczności przepisywania każdego przepływu pracy.
Lista kontrolna implementacji
- Zdefiniuj znormalizowany format żądania ustrukturyzowanego wyjścia dla swoich aplikacji.
- Utwórz macierz możliwości dostawcy dla każdego modelu w puli routingu.
- Projektuj schematy przy użyciu JSON przenośnego podzbioru schematu.
- Tłumacz żądania na ścisłe mechanizmy natywne dostawcy, jeśli są obsługiwane.
- Sprawdź analizowalność, zgodność schematu i poprawność biznesową po wygenerowaniu.
- Używaj wywołań narzędzi do operacji ubocznych.
- Wymagaj autoryzacji, idempotencji i potwierdzenia poza modelem.
- Rejestruj wersję schematu, dostawcę, błędy sprawdzania poprawności, ponowne próby, opóźnienia, koszt i stan działania.
- Zdefiniuj zachowanie awaryjne według poziomu ryzyka przepływu pracy.
- Zachowaj dostępność starych schematów do czasu migracji zależnych automatyzacji.
Praktycznym celem nie jest sprawienie, aby każdy model zachowywał się identycznie. Ma dać twórcom aplikacji jedną stabilną umowę, podczas gdy brama uczciwie radzi sobie z różnicami dostawców. Ustrukturyzowane dane wyjściowe są niezbędną infrastrukturą do niezawodnej automatyzacji sztucznej inteligencji, ale granicą produkcji jest walidator i warstwa zasad, która decyduje, czy obiekt jest bezpieczny w użyciu.