Kluczowe punkty
- Etykieta obejmuje ścieżki URL, formaty JSON żądań i odpowiedzi, uwierzytelnianie Bearer i strumieniowanie SSE.
- Nie mówi nic o tym, który model odpowiada, jak się zachowuje ani ile to kosztuje.
- Przełączanie zwykle oznacza zmianę dwóch wartości: base URL i klucz API.
- Przetestuj strumieniowanie, narzędzia, tryb JSON i kody błędów przed zaufaniem dostawcy.
Krótka odpowiedź
Gdy dostawca mówi, że jego API jest openai-compatible, oznacza to, że akceptuje te same żądania HTTP, które wysyłają biblioteki klienta OpenAI, i zwraca odpowiedzi w tej samej formie. Zachowujesz kod, zmieniasz adres bazowy i klucz, a wywołanie trafia na inny serwer.
To jest cała obietnica. To stwierdzenie o interfejsie, jak powiedzenie, że dwa ładowarki używają tego samego wtyku. Nie mówi Ci, co jest na drugim końcu kabla. Model, jego zasady bezpieczeństwa, jego cena i jego limity to wszystko decyzje dostawcy i bardzo się różnią.
Co dokładnie obejmuje ta etykieta
W praktyce kompatybilność z OpenAI to krótka lista konkretnych rzeczy. Jeśli dostawca obsługuje wszystkie, większość kodu klienta zadziała bez zmian.
- Ścieżki. Żądania czatu trafiają pod
POST /v1/chat/completions, a lista modeli pochodzi zGET /v1/models. - Autoryzacja. Klucz przesyłany jest w nagłówku
Authorization: Bearer. - Treść żądania. Ciąg
model, tablicamessagesobiektów zroleicontentoraz opcjonalne pola próbkowania takie jaktemperature,top_p,stopiseed. - Treść odpowiedzi. Tablica
choicesz wiadomością asystenta,finish_reasonoraz obiektusagez liczbą tokenów. - Strumieniowanie. Przy
stream: trueserwer wysyła zdarzenia Server-Sent Events, każde z małym delta JSON, kończąc się znacznikiem końcowym. - Opcjonalne funkcje. Wywoływanie narzędzi, tryb JSON i podobne pola, gdzie dostawca decyduje się je obsłużyć.
Ponieważ tak wiele narzędzi zostało napisanych pod ten format, stał się on wspólnym celem. Edytory, frameworki agentów, interfejsy do odgrywania ról i zwykłe skrypty pozwalają wprowadzić niestandardowy adres bazowy, i to wszystko, czego potrzebują.
Dlaczego jeden format stał się wspólnym celem
Format chat completions rozszerzył się, ponieważ był prosty i pojawił się wcześnie. Autor narzędzia, który go obsłuży raz, może dotrzeć do wielu backendów, a autor backendu, który go obsłuży raz, może dotrzeć do wielu narzędzi. To dobra oferta dla obu stron, więc format się utrzymał, nawet wśród usług niepowiązanych z firmą, która go zaprojektowała.
Dla Ciebie jako dewelopera ma to praktyczne znaczenie. Twój kod nie wymaga innej integracji dla każdego dostawcy. Możesz przenieść prototyp między punktami końcowymi w popołudnie, porównać dwa modele na tych samych promptach lub zachować drugiego dostawcę jako zapasowy, gdy pierwszy jest wolny. Koszt zmiany zdania jest niski, co ułatwia wypróbowanie nowej usługi bez zobowiązań.
Drugą stroną medalu jest to, że wspólny interfejs ukrywa rzeczywiste różnice. Ponieważ przełączanie jest tak łatwe, kuszące jest założenie, że wszystko za URL jest równoważne. Nie jest, a poniższe sekcje pokazują, gdzie pojawiają się zazwyczaj luki.
Co nie mówi Ci ta etykieta
Tutaj ludzie się zaskakują. Etykieta pomija wszystko, co decyduje o tym, czy API jest przydatne do Twojej pracy.
Model po drugiej stronie
Kompatybilny endpoint może obsługiwać dowolny model. Niektóre obsługują modele o otwartych wagach, niektóre kierują do kilku dostawców, niektóre owijają model własny. Kompatybilność nie oznacza, że usługa jest prowadzona przez OpenAI, ani że model zachowuje się jak ich. Nazwa modelu, którą przesyłasz w model, to tylko ciąg zdefiniowany przez dostawcę.
Zachowanie przy odmowie
Zasady treści należą do modelu i dostawcy, nie do protokołu. Dwa kompatybilne API mogą odpowiedzieć na ten sam prompt w przeciwny sposób. Jeśli Twoim przypadkiem użycia jest fikcja, roleplay lub inna legalna treść dla dorosłych, sprawdź, co dostawca mówi o odmowach, zanim połączysz cokolwiek.
Głębia funkcji
Niektórzy dostawcy implementują tylko czat. Inni dodają narzędzia, tryb JSON, prawdopodobieństwa logarytmiczne lub dodatkowe endpointy. Klient, który przesyła pole ignorowane przez serwer, nie zawsze zgłosi błąd głośno, więc cicha niezgodność jest możliwa.
Limity, ceny i błędy
Limity zapytań, długość okna kontekstu, maksymalny rozmiar treści i cena za token to wszystkie decyzje dostawcy. Treści błędów różnią się szczegółowo nawet przy tych samych kodach statusu HTTP, więc logika ponawiania powinna opierać się na kodach statusu i nagłówkach, a nie na tekście wiadomości.
Szybki test kompatybilności
Możesz zweryfikować dostawcę w kilka minut za pomocą trzech żądań. Zmień klucz na swój własny. Ten przykład używa adresu bazowego tej strony.
curl https://api.kimicode.top/v1/models \
-H "Authorization: Bearer YOUR_API_KEY"
curl https://api.kimicode.top/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "uncensored",
"messages": [{"role": "user", "content": "Reply with the word ready."}]
}'
Pierwsze wywołanie potwierdza klucz i wypisuje ID modeli. Drugie sprawdza format czatu. Następnie przetestuj części, od których zależy Twoja aplikacja: dodaj "stream": true i obserwuj przyrostowe fragmenty, przekaż tablicę tools, jeśli używasz wywoływania funkcji, i ustaw response_format na {"type":"json_object"}, jeśli potrzebujesz wyjścia do parsowania.
Wywołaj też celowo błąd, np. złym kluczem. Chcesz zobaczyć czysty status HTTP i treść błędu JSON, którą Twój klient może obsłużyć.
To samo wywołanie w Node
SDK dla JavaScriptu przyjmuje te same dwie wartości. Oto wywołanie strumieniowe, które jest formatem używanym przez większość interfejsów czatu.
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.kimicode.top/v1",
apiKey: process.env.API_KEY,
});
const stream = await client.chat.completions.create({
model: "uncensored",
stream: true,
messages: [{ role: "user", content: "Name three uses of SSE." }],
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
Jeśli wypisuje tekst słowo po słowie, ścieżka strumieniowania działa od początku do końca. Ta sama pętla działa z dowolnym kompatybilnym dostawcą, co jest głównym celem tego formatu.
Jak wygląda przełączanie w kodzie
W oficjalnym SDK Python zmiana to dwa argumenty konstruktora. Reszta Twojego programu pozostaje taka sama.
from openai import OpenAI
client = OpenAI(
base_url="https://api.kimicode.top/v1",
api_key="YOUR_API_KEY",
)
resp = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Summarize SSE in one sentence."}],
)
print(resp.choices[0].message.content)
SDK Node.js opiera się na tej samej idei z opcjami baseURL i apiKey. Wiele narzędzi odczytuje OPENAI_BASE_URL i OPENAI_API_KEY ze środowiska, więc czasem możesz przełączyć się bez dotykania kodu.
Pamiętaj, aby zmienić też ciąg modelu. Żądanie, które wymienia model, którego nowy serwer nie hostuje, zakończy się niepowodzeniem, i to najczęstszy pierwszy błąd.
Gdzie pasuje API tej strony
Usługa to hostowany, tekstowy endpoint API zgodny z formatem OpenAI. Uruchamia jeden model o otwartych wagach, obsługiwany przez niezależnego dostawcę i dostrojony tak, by odpowiadać bez odmawiania odpowiedzi dla prawnego użytku dorosłych. Nie jest to oficjalne API żadnego dostawcy modeli i nie przekieruje ruchu między dostawcami. ID modelu to uncensored.
Obsługuje strumieniowanie przez SSE z raportowaniem użycia na końcu, wywoływanie funkcji, tryb JSON i przekazuje temperaturę, top_p, stop, seed oraz kary. Okno kontekstu wynosi 100 000 tokenów dla promptu i uzupełnienia łącznie. Nie generuje obrazów ani audio i nie oferuje embeddingów ani dostrajania. Jedna zasada jest stała: brak treści seksualnych z udziałem nieletnich.
Rozliczenie jest oparte na przedpłacie i pomiarze zużycia: $0,15 za 1 mln tokenów wejściowych i $0,50 za 1 mln tokenów wyjściowych, bez subskrypcji. Liczby znajdziesz na stronie cenowej, a dokumentacja krok po kroku pokazuje pierwsze zapytanie. Jeśli chcesz przetestować produkt bez płacenia, nowe konta mogą odebrać darmowy kredyt próbny w wysokości $0,50 jednym kliknięciem na stronie klucza API.
Typowe pułapki kompatybilności
- Nieprawidłowy bazowy adres URL. Adres URL powinien kończyć się na
/v1. Klienci dołączają/chat/completionssami, więc dodanie go do adresu bazowego powoduje błąd 404. - Nieobsługiwane parametry. Jeśli biblioteka wysyła pole, którego serwer nie zna, sprawdź, czy jest odrzucane, czy ignorowane, a następnie usuń je.
- Strumieniowanie i współbieżność. Zapytanie strumieniowe zajmuje slot współbieżności do końca strumienia. Jeśli Twoja aplikacja otwiera wiele strumieni, możesz trafić na błąd 429 z kodem
concurrency, mimo że liczba zapytań na minutę jest niska. - Ponów próbę po kodzie 429. Traktuj kod 429 jako sygnał do oczekiwania. Gdy występuje nagłówek
Retry-After, respektuj go. - Liczenie tokenów. Nie zakładaj, że tokenizator innego dostawcy jest taki sam. Przeczytaj obiekt
usagew odpowiedzi, aby uzyskać liczby, za które jesteś rozliczany.
Żadna z tych pułapek nie jest trudna do naprawienia, gdy wiesz, gdzie ich szukać, a większość sprowadza się do dokładnego przeczytania pierwszego komunikatu błędu.
