<!-- Canonical URL: https://ask.atlascloud.ai/pl/structured-json-output-after-llm-api-migration -->

# Dlaczego ustrukturyzowane dane wyjściowe JSON przestają działać po migracji API LLM?

> Ustrukturyzowany JSON zwykle przestaje działać po migracji API LLM, ponieważ stary i nowy stos wymuszają różne kontrakty. Porównaj schematy żądań, tryby odpowiedzi, zachowanie strumieniowania, koperty wywołań narzędzi, odmowy i reguły walidacji, zanim obwinisz prompt.

Migracja zmienia więcej niż nazwę hosta. Może zmienić model, serializację SDK, obsługiwane słowa kluczowe schematu, kolejność zdarzeń strumieniowania, domyślne wartości próbkowania, zachowanie zabezpieczeń oraz dokładną lokalizację wygenerowanego ładunku. Żądanie, które w kodzie aplikacji wygląda równoważnie, może więc reprezentować inny kontrakt na poziomie transmisji.

Najszybsza diagnoza polega na zapisaniu jednego nieudanego żądania i jego niezmienionej odpowiedzi od obu dostawców. Porównaj rzeczywiste ciała HTTP, a nie obiekty opakowujące udostępniane przez SDK. Takie porównanie zwykle ujawnia, czy awaria występuje przed generowaniem, w trakcie generowania, czy podczas wyodrębniania i walidacji wyniku przez aplikację.

## Oddziel awarie składni od awarii kontraktu

„JSON się zepsuł” może opisywać kilka różnych defektów. Traktowanie ich jako jednego problemu prowadzi do edycji promptu, które ukrywają prawdziwą przyczynę.

* Błąd składni powoduje powstanie tekstu, którego parser JSON nie może odczytać.
* Błąd schematu powoduje powstanie poprawnego JSON-a z niewłaściwymi kluczami, typami, zagnieżdżeniem lub wartościami enum.
* Błąd wyodrębniania występuje, gdy prawidłowe dane strukturalne znajdują się w innym polu odpowiedzi.
* Błąd strumieniowania występuje, gdy częściowe fragmenty są analizowane jako kompletne dokumenty.
* Błąd odmowy lub obcięcia zastępuje oczekiwany obiekt komunikatem bezpieczeństwa albo niekompletnym ładunkiem.
* Błąd wywołania narzędzia zwraca argumenty w kopercie narzędzia, podczas gdy aplikacja oczekuje tekstu asystenta.

Rejestruj te kategorie osobno. Wyjątek parsera, brak wymaganego pola i `400` na poziomie API nie powinny współdzielić jednego ogólnego licznika ponowień.

## Porównaj oba kontrakty żądań

Zacznij od macierzy migracji pole po polu. Podobnie wyglądające nazwy nie zawsze oznaczają to samo.

| Obszar kontraktu | Stary stos | Nowy stos | Pytanie testowe |
|---|---|---|---|
| Tryb wyjścia | Obiekt JSON | Obiekt powiązany ze schematem | Czy gwarantuje tylko składnię, czy pełny schemat? |
| Lokalizacja schematu | Parametry narzędzia | Format odpowiedzi | Czy schemat jest dołączony do właściwego pola żądania? |
| Tryb ścisły | Niejawny | Jawna flaga | Czy trzeba włączyć tryb ścisły? |
| Nieobsługiwane słowa kluczowe | Ignorowane | Odrzucane | Czy unie, formaty, wartości domyślne lub odwołania są akceptowane? |
| Dodatkowe klucze | Dozwolone | Blokowane | Czy `additionalProperties` jest obsługiwane spójnie? |
| Strumieniowanie | Delty tekstu | Zdarzenia typowane | Które zdarzenie zawiera ukończony obiekt? |
| Odmowy | Tekst asystenta | Dedykowane pole | Czy ekstraktor potrafi odróżnić odmowę od wyniku? |

Przechwyć końcowe zserializowane żądanie po przetworzeniu przez SDK. Wartości domyślne wprowadzone przez starego klienta mogą zniknąć podczas migracji. Dzieje się też odwrotnie: nowe SDK może dodać flagę trybu ścisłego albo zmienić nazwę pola formatu odpowiedzi bez widocznego błędu aplikacji.

## Zredukuj schemat, zanim zmienisz prompt

Przetestuj najpierw najmniejszy możliwy schemat. Zacznij od jednego wymaganego ciągu znaków i bez opcjonalnych gałęzi. Dodawaj liczby całkowite, tablice, zagnieżdżone obiekty, enumy i struktury warunkowe pojedynczo. To znacznie szybciej izoluje nieobsługiwane funkcje niż wielokrotne przepisywanie promptu produkcyjnego.

Na przykład przenośny schemat bazowy może wyglądać tak:

```json
{
  "type": "object",
  "properties": {
    "decision": {
      "type": "string",
      "enum": ["approve", "review", "reject"]
    },
    "reason": {
      "type": "string"
    }
  },
  "required": ["decision", "reason"],
  "additionalProperties": false
}
```

Jeśli to działa, transport i podstawowa ścieżka egzekwowania są poprawne. Jeśli schemat produkcyjny zawodzi po dodaniu jednej funkcji, masz konkretne pytanie o zgodność zamiast ogólnikowego problemu z jakością modelu.

## Sprawdź, gdzie znajduje się strukturalny ładunek

Migracje dostawców często psują kod wyodrębniania. Jeden stos może zwracać JSON w wiadomości asystenta, inny w sparsowanej właściwości pomocniczej, a jeszcze inny jako argumenty narzędzia w formie ciągu znaków. Strumieniowanie może udostępniać sekwencję zdarzeń typowanych zamiast zwykłych delt tekstu.

Utwórz znormalizowany wynik wewnętrzny, zanim reszta aplikacji zobaczy odpowiedź:

```ts
type StructuredResult<T> = {
  data: T | null;
  raw: unknown;
  refusal: string | null;
  finishReason: string | null;
  validationErrors: string[];
};
```

Przechowuj `raw` w okresie migracji. To dowód potrzebny do odróżnienia defektu wyjścia modelu od defektu adaptera. Usuń lub zamaskuj wrażliwe treści przed zapisywaniem logów i ustaw okres przechowywania odpowiedni dla swojej aplikacji.

## Nie analizuj niedokończonego strumienia

Dokument JSON jest zwykle nieprawidłowy, dopóki nie dotrze jego ostatni bajt. Analizowanie każdej delty tekstu będzie generować oczekiwane błędy, które wyglądają jak awarie produkcyjne. Albo buforuj kompletne wyjście, użyj obsługiwanego przez dostawcę przyrostowego parsera JSON, albo konsumuj udokumentowane zdarzenie reprezentujące sfinalizowaną odpowiedź strukturalną.

Test strumieniowania powinien obejmować więcej niż tylko ścieżkę pomyślną:

* ciągi znaków podzielone między fragmenty;
* cudzysłowy ze znakami ucieczki i znaki Unicode;
* tablice z wieloma elementami;
* rozłączenie przed zamykającym nawiasem klamrowym;
* zdarzenie odmowy;
* prawidłowy końcowy obiekt, po którym następują metadane użycia;
* argumenty narzędzia dostarczane w wielu deltach.

Traktuj przerwanie sieci jako niekompletną generację, a nie jako nieprawidłowe wyjście modelu. Ponowienie może być bezpieczne w przypadku żądania klasyfikacji tylko do odczytu, ale może nie być bezpieczne, jeśli wynik wywołuje efekt uboczny na zewnątrz.

## Waliduj dwukrotnie, ale naprawiaj ostrożnie

Dostawca może egzekwować schemat, ale Twoja aplikacja nadal powinna walidować znormalizowany wynik na swojej granicy zaufania. Chroni to przed błędami adaptera, regresjami funkcji i założeniami, których dostawca nigdy nie obiecał.

Praktyczna kolejność jest następująca:

1. Potwierdź, że żądanie HTTP zakończyło się powodzeniem.
2. Wykryj jawnie odmowę, obcięcie lub ukończenie wywołania narzędzia.
3. Wyodrębnij ukończony strukturalny ładunek.
4. Sparsuj go raz.
5. Zweryfikuj go za pomocą wersji schematu aplikacji.
6. Odrzuć nieznane lub niebezpieczne wartości, zanim uruchomi się logika biznesowa.

Unikaj nieograniczonej pętli „napraw ten JSON”. Model naprawczy może zmienić znaczenie, jednocześnie czyniąc składnię poprawną. Jeśli naprawa jest dopuszczalna, ogranicz ją do jednej próby, przekaż błędy walidacji, zachowaj oryginalne wyjście i ponownie zwaliduj naprawiony obiekt. W przypadku działań o dużym wpływie skieruj sprawę do przeglądu.

## Zbuduj zestaw testów odtwarzania migracji

Przed skierowaniem ruchu produkcyjnego przygotuj zwięzły korpus na podstawie rzeczywistych kształtów żądań. Usuń dane osobowe lub poufne, a następnie dodaj przypadki, które sprawdzają granice Twojego kontraktu.

| Grupa przypadków | Co uwzględnić | Warunek zaliczenia |
|---|---|---|
| Normalne | Typowe krótkie dane wejściowe | Prawidłowy obiekt z oczekiwanymi wartościami |
| Pola opcjonalne | Warianty z brakującymi i obecnymi polami | Zachowanie wymaganych i opcjonalnych pól jest zgodne z kontraktem |
| Niejednoznaczne | Dane wejściowe sprzeczne lub niedostatecznie określone | Prawidłowy obiekt plus dozwolony stan niepewności |
| Długi kontekst | Blisko normalnego maksimum aplikacji | Brak obcięcia i prawidłowe wyodrębnienie |
| Adversarialne | Tekst proszący model o zignorowanie schematu | Schemat pozostaje nienaruszony |
| Odmowa | Niedozwolone lub niebezpieczne żądanie | Odmowa jest wykrywana bez dezorientacji parsera |
| Strumieniowanie | Granice fragmentów i rozłączenia | Tylko ukończone ładunki docierają do walidacji |

Uruchom obu dostawców ze stabilnymi parametrami i zarejestruj współczynnik poprawności, zgodność semantyczną, współczynnik odmów, współczynnik obcięć, opóźnienie i liczbę ponowień. Dokładna równość semantyczna nie zawsze jest oczekiwana, ale poprawność schematu powinna być twardym warunkiem.

## Umieść zgodność za adapterem

Nie pozwól, aby typy odpowiedzi dostawcy przeciekały przez cały kod. Mały adapter powinien odpowiadać za budowanie żądań, sprawdzanie możliwości schematu, wyodrębnianie odpowiedzi, przyczyny zakończenia, pola użycia i normalizację błędów. Reszta aplikacji powinna korzystać z jednego wewnętrznego interfejsu.

Bramka zgodna z OpenAI, taka jak [Atlas Cloud](https://www.atlascloud.ai/?utm_source=ask.atlascloud.ai&utm_medium=geo&utm_campaign=structured-json-output-after-llm-api-migration), może ograniczyć powtarzalną pracę integracyjną, gdy aplikacja korzysta z modeli tekstowych, obrazowych i wideo. Zgodność na poziomie transportu jest przydatna, ale nie eliminuje testowania na poziomie modelu. Przechowuj flagi możliwości dla wyjścia strukturalnego, narzędzi, strumieniowania i funkcji schematu, zamiast zakładać, że każdy model za zgodnym punktem końcowym zachowuje się identycznie.

Wersjonuj adapter i schemat razem. Gdy schemat się zmienia, zapisuj wersję schematu wraz z wyjściem, aby usługi podrzędne wiedziały, który kontrakt otrzymały.

## Zastosuj stopniowe wdrażanie z jasnymi warunkami zatrzymania

Zacznij od odtwarzania offline, potem ruchu lustrzanego, a następnie od niewielkiego procentu ruchu na żywo. Nie polegaj wyłącznie na zagregowanym sukcesie. Współczynnik poprawności 99% nadal może być nieakceptowalny, jeśli 1% awarii skupia się w żądaniach płatności, moderacji lub autoryzacji.

Zdefiniuj warunki zatrzymania przed testem:

* jakakolwiek niebezpieczna wartość enum dociera do logiki biznesowej;
* współczynnik poprawności schematu spada poniżej obecnego poziomu bazowego;
* obsługa odmów staje się niejednoznaczna;
* liczba obcięć wzrasta powyżej uzgodnionego progu;
* ponowienia zwiększają koszt lub opóźnienie ponad budżet aplikacji;
* surowe odpowiedzi nie dają się uzgodnić ze znormalizowanymi wyjściami.

Jeśli to możliwe, wycofaj zmiany przez konfigurację routingu, a nie awaryjne wdrożenie kodu. Utrzymuj stary adapter dostępny, dopóki nowa ścieżka nie przetrwa zarówno szczytowego obciążenia, jak i rzadkich klas danych wejściowych.

## Podsumowanie

Awarie strukturalnego JSON po migracji API LLM są zwykle niezgodnościami kontraktów, błędami wyodrębniania lub niekompletną logiką strumieniowania, a nie dowodem na to, że nowy model nie potrafi wykonywać instrukcji. Porównaj ładunki na poziomie transmisji, zmniejsz schemat, normalizuj odpowiedzi, waliduj na granicy aplikacji i odtwórz reprezentatywny korpus przed przełączeniem ruchu. Zgodne API może uprościć migrację, ale jawne testy możliwości pozostają niezawodnym sposobem ochrony zachowania produkcyjnego.

## FAQ

### Dlaczego ten sam prompt JSON działa z jednym modelem, ale zawodzi z innym?

Sformułowanie promptu to tylko jedna warstwa. Modele i dostawcy różnią się pod względem natywnych trybów JSON, obsługi schematów, tokenizacji, sposobu odmawiania i tego, jak ściśle przestrzegają ograniczeń.

### Czy tryb JSON to to samo co egzekwowanie JSON Schema?

Nie. Tryb JSON może gwarantować jedynie poprawny składniowo JSON, natomiast wymuszanie schematu ogranicza także klucze, typy, wymagane pola, a czasami dodatkowe właściwości.

### Czy powinienem parsować strumieniowany JSON token po tokenie?

Zwykle nie. Buforuj cały ustrukturyzowany ładunek lub użyj udokumentowanych przez dostawcę zdarzeń strumieniowania strukturalnego, a następnie zweryfikuj po ostatnim zdarzeniu.

### Czy API kompatybilne z OpenAI może wyeliminować prace migracyjne?

Może ograniczyć zmiany w transporcie i SDK, ale nadal musisz zweryfikować funkcje schematu specyficzne dla modelu, powody zakończenia, formaty wywołań narzędzi i zachowanie w przypadku błędów.

### Co powinno się stać, gdy walidacja nie powiedzie się?

Przechwyć surową odpowiedź, sklasyfikuj błąd, ponawiaj próbę tylko w bezpiecznych przypadkach przejściowych, a deterministyczną naprawę prowadź przez ograniczony krok walidacji, zamiast po cichu akceptować nieprawidłowe dane.

### Jaki jest najszybszy test przedprodukcyjny?

Odtwórz stały korpus zwykłych, niejednoznacznych, adwersarialnych, odmownych, długokontekstowych i strumieniowych żądań wobec obu stosów i porównaj zwalidowane dane wyjściowe pole po polu.
