Hoppa till innehållet
Blogg

OpenAI-kompatibelt API: byt leverantör på tre rader

Vad OpenAI-kompatibelt egentligen betyder, de tre rader som flyttar din app till ett europeiskt API och en ärlig lista över det som inte följer med.

Union AI8 min läsning
UtvecklareOpen weights

Tre rader. Du pekar klientens base_url mot den nya leverantören, byter API-nyckel och ersätter modellnamnet med ett nivånamn. Allt annat i ett anrop till chat completions, messages-arrayen, streaming, verktyg, JSON-scheman, förblir precis som det är, eftersom OpenAI-kompatibelt betyder att samma HTTP-kontrakt är implementerat, inte bara att det liknar det.

Det intressanta med en migrering är inte koden. Det är det som inte följer med: endpoints som inte finns än, modellbeteende som skiftar under samma prompt och den enda felkod som du förmodligen aldrig har hanterat.

Infografik som delar upp en API-migrering i det som fungerar oförändrat, det som kräver en liten ändring och det som saknas.

Vad ”OpenAI-kompatibelt” faktiskt betyder

Det betyder kontraktet för en enda endpoint: POST /v1/chat/completions, med samma request body och samma form på svaret, inklusive formatet för server-sent events vid streaming. Kontraktet blev branschens standardgränssnitt på samma sätt som S3:s API blev standard för objektlagring, och av samma skäl: allt var redan skrivet mot det.

De officiella SDK:erna är tunna klienter ovanpå kontraktet. I OpenAI:s Python-bibliotek är bas-URL:en ett argument till konstruktorn, så att peka den någon annanstans är en funktion som stöds, inte ett hack. Din retry-logik, din hanterare för streaming och dina typdefinitioner fortsätter att fungera.

Vad det inte betyder är att hela plattformen har samma funktioner. Kompatibla tjänster implementerar chattendpointen väl och går isär efter det, och därför är den ärliga versionen av det här inlägget mest en lista över skillnader.

Hela migreringen
from openai import OpenAI
client = OpenAI(
api_key=os.environ["UNION_API_KEY"],
base_url="https://api.europeanailab.eu/v1",
)
response = client.chat.completions.create(
model="eu-standard",
messages=[{"role": "user", "content": prompt}],
stream=True,
)

3 rader skiljer sig: nyckeln, bas-URL:en och ett nivånamn i stället för ett modellnamn.

Allt annat i anropet är samma kontrakt: messages, streaming, verktyg, JSON-scheman. Det som ändras är inte formen på förfrågan utan vilken modell som skriver svaret, och därför handlar checklistan längre ner om utvärdering snarare än om kod.

De tre raderna i praktiken

Här är hela ändringen i Python. SDK:erna för Node, Go och .NET tar samma två argument under andra namn.

from openai import OpenAI

client = OpenAI(
    api_key=os.environ["UNION_API_KEY"],
    base_url="https://api.europeanailab.eu/v1",
)

response = client.chat.completions.create(
    model="eu-standard",
    messages=[{"role": "user", "content": prompt}],
    stream=True,
)

Om din kod redan läser bas-URL:en från en miljövariabel, vilket är värt att ordna före varje migrering, är det här en konfigurationsändring och inte en driftsättning av ny kod. Det ger dig också den billigaste tänkbara vägen tillbaka: peka den tillbaka.

Vad som följer med, vad som ändras, vad som saknas

Tabellen du faktiskt vill ha innan du planerar arbetet.

Funktion Status Vad du gör
Chat completions Fungerar oförändrat Ingenting
Streaming (SSE) Fungerar oförändrat Be om usage i strömmen så att mätningen blir exakt
Function calling och verktyg Samma form Testa om vilket verktyg modellen väljer, inte om den kan
Strukturerad output (JSON-schema) Samma form Fortsätt alltid validera på din sida
Systemprompter Fungerar Räkna med att justera formuleringen, inte strukturen
Modellnamn Ändras Använd en nivå: eu-lite, eu-standard, eu-long, eu-pro
Förbrukning och kostnad Ändras Läs svarets headers i stället för en dashboard
Embeddings, bild, tal Saknas Behåll din nuvarande leverantör för detta
Batch-API Saknas På färdplanen, inte släppt
Tillståndsbaserat API i stil med Assistants Saknas Inte planerat; håll tillståndet på din sida

Tre av raderna är sådant som saknas. Vi publicerar dem som en lista på startsidan i stället för att låta dig upptäcka dem mitt i migreringen, eftersom ”kompatibel” är ett ord som har töjts ut av tjänster som implementerar halva kontraktet och kallar det klart.

Varför modellnamn blir nivånamn

Du köper en nivå, inte en modell. eu-standard är arbetshästen, eu-long tar en miljon tokens kontext, eu-pro är den tunga resonerande modellen, och varje nivå motsvarar en namngiven open-weight-modell som publiceras med sin licens på sidan om AI-transparens.

Skälet är omsättningen. Open-weight-modeller ersätts med några månaders mellanrum, och att hårdkoda dagens modellnamn i din applikation betyder en ny driftsättning varje gång fältet rör sig. En nivå är ett löfte om förmåga och pris som överlever att modellen under den byts ut, och när vi byter den säger vi det i stället för att i det tysta ändra vad din kod gör.

Licenserna spelar också roll, och de är korta nog att läsa. Det mesta vi kör är Apache 2.0 eller MIT, vilket är skälet till att samma vikter över huvud taget lagligt kan köras på europeisk hårdvara.

Två utvecklare vid ett ståbord som går igenom kod på en laptopskärm.

Vad som ändras i svaren, inte i API:et

Det här är delen som överraskar team, så budgetera för den. Ett leverantörsbyte är ett modellbyte, och modeller skiljer sig på sätt som inget kompatibilitetslager kan dölja.

Formateringen glider. En prompt som är finjusterad för att få en modell att skriva ren markdown kan ge en inledande harang hos en annan. Oftast en fix på en rad, men det är en fix.

Omdömet vid verktygsanrop skiljer sig. Formen på ett funktionsanrop är identisk; modellens vilja att göra anropet är det inte. Det finns både modeller som anropar för ivrigt och modeller som svarar ur minnet.

Vägranden skiljer sig. Vissa open-weight-modeller duckar för faktafrågor om politik eller historia. Vi behandlar det som en brist och skickar om frågan en gång till en modell utan den blinda fläcken, och talar om i headern X-EU-Routed när vi gjorde det. Det beskrivs i sin helhet på sidan om AI-transparens.

Det praktiska svaret är en testuppsättning. Spara tjugo riktiga förfrågningar med förväntade svar, kör dem mot båda leverantörerna och läs skillnaderna själv. Tjugo räcker för att fånga regressioner i formatering och verktygsval, och är tillräckligt få för att du faktiskt ska göra det.

Kostnad och mätning efter bytet

Prissättning per token är samma idé överallt, men var du läser siffrorna ändras. Varje svar bär med sig vad förfrågan kostade:

  • X-EU-Tokens-In och X-EU-Tokens-Out, de uppmätta tokens.
  • X-EU-Cost-EUR, vad som drogs från ditt saldo för förfrågan.
  • X-EU-Balance-EUR, vad som återstår.
  • X-EU-Model-Tier, vilken nivå som faktiskt körde den.

Det betyder att dina egna loggar kan besvara kostnadsfrågan per funktion, per kund och per endpoint, utan att vänta på att en månadsfaktura ska säga emot dig. Priserna bakom siffrorna finns på prissidan, och hur du ska tänka kring tokenkostnad i allmänhet, inklusive varför output är dyrare än input, går vi igenom i vad ett AI-API kostar per token.

En vana som är värd att ta med sig: sätt max_tokens på varje anrop. Det är den enskilt mest effektiva kostnadskontrollen i alla API:er som tar betalt per token, och det är en rad.

Fel, gränser och 402:an som du inte har hanterat

Din felhantering täcker förmodligen 429 och 500. Förbetald kredit lägger till en till.

  1. 402, otillräckligt saldo. Förfrågan avvisas med en länk för att fylla på, ingenting faktureras i efterhand och ditt saldo går aldrig under noll. Hantera det som ett autentiseringsfel: larma, försök inte igen i en loop.
  2. 429, rate limit eller tak. Respektera Retry-After. Taken sätter du själv, per nyckel, i euro per dag och per månad.
  3. 502 och 503, uppströms otillgänglig. Försök igen med backoff. Vad som händer vid ett avbrott, och begränsningen med en enda leverantör bakom det, beskrivs på statussidan.
  4. Misslyckade förfrågningar är gratis. Kom det inget användbart svar tillbaka dras ingenting från ditt saldo, och en förfrågan som skickats om till en svagare modell debiteras enligt det lägsta av de två priserna.

Taket för nya konton fångar folk en gång: 25 € per dag de första 48 timmarna, oavsett saldo. Det finns eftersom en läckt nyckel första dagen är det dyraste misstaget en ny integration kan göra.

Gör kompatibilitet dig faktiskt flyttbar?

Delvis, och det är värt att vara exakt med vilken del. Protokollkontraktet är flyttbart: varje tjänst som talar chat completions kan bytas in bakom samma klient. Bara det tar bort den grövsta formen av inlåsning, den där det att lämna betyder att skriva om hela integrationslagret.

Det som inte är flyttbart är allt du har byggt ovanpå en specifik modell. Prompter som finjusterats i månader, few-shot-exempel som valts för en modells egenheter, utvärderingsuppsättningar som poängsatts mot en modells stil och varje tröskelvärde du satt genom att se hur den modellen beter sig. Inget av det följer med rent, och inget av det syns i ett arkitekturdiagram.

Behandla alltså modellen som ett beroende med en version, inte som en konstant. Håll prompterna i filer i stället för utspridda i koden, lägg testuppsättningen i repot och skriv ner varför ett tröskelvärde är vad det är. Team som gör så byter leverantör på en eftermiddag. Team som inte gör det lägger ett kvartal på att upptäcka vad deras prompter kompenserade för.

En checklista för migreringen

En halv dag för en liten tjänst, en sprint för något med verklig trafik.

  1. Flytta bas-URL:en till konfigurationen om den inte redan ligger där. Allt nedan blir lättare när det är gjort.
  2. Välj nivå efter arbetslast, inte efter namn. Klassificering och extraktion hör hemma på den billiga nivån; bara resonemangstungt arbete behöver den dyra.
  3. Bygg testuppsättningen. Tjugo riktiga förfrågningar och förväntade svar, incheckade i repot.
  4. Kör båda leverantörerna sida vid sida på en liten andel av trafiken och jämför resultaten.
  5. Koppla in kostnadsheaders i det du redan loggar.
  6. Lägg till hanteringen av 402, och ett tak per nyckel när du ändå håller på.
  7. Behåll den gamla leverantören konfigurerad i två veckor. En migrering du kan ångra med en konfigurationsändring är en migrering du kan göra en vanlig tisdag.

Vilken leverantör du ska köra utvärderingen mot är en egen fråga, och de fyra realistiska alternativen jämförs i europeiska AI-leverantörer jämförda. De första tio förfrågningarna är gratis och minsta påfyllning är 10 €, så utvärderingen kostar mindre än mötet om huruvida den ska göras. Hela kontraktet, med curl och Python att kopiera, finns i API-dokumentationen, och var förfrågningarna behandlas, steg för steg, står i vart dina prompter tar vägen.

Vanliga frågor

Vad betyder OpenAI-kompatibelt?

Det betyder att tjänsten implementerar samma HTTP-kontrakt som OpenAI:s endpoint för chat completions: samma request body, samma form på svaret, samma format för streaming. Eftersom de officiella SDK:erna är tunna skal runt det kontraktet räcker det oftast att peka en av dem mot en annan bas-URL.

Hur byter jag från OpenAI:s API till en annan leverantör?

Byt API-nyckel, sätt klientens base_url till den nya leverantören och byt ut modellnamnet. I OpenAI:s SDK:er för Python och Node är bas-URL:en ett argument till konstruktorn, så ändringen är tre rader: nyckeln, bas-URL:en och modellnamnet.

Fungerar streaming och function calling fortfarande efter bytet?

Hos Union AI, ja. Streaming använder samma format för server-sent events och kan returnera tokenförbrukningen i slutet av strömmen, och function calling och strukturerad output med JSON-schema behåller samma form på förfrågan och svar. Det som skiljer är modellens omdöme om när den ska anropa ett verktyg, och det är värt att testa.

Vilka OpenAI-funktioner saknas i kompatibla API:er?

Det varierar mellan leverantörer, och de ärliga publicerar listan. Hos Union AI är version 1 bara kontraktet för chat completions: det finns inga endpoints för embeddings, bild eller tal, inget batch-API och inget tillståndsbaserat API i stil med Assistants. De står på färdplanen i stället för att antydas finnas, så kontrollera samma fyra luckor hos varje kompatibel leverantör.

Ger mina prompter samma svar på en open-weight-modell?

Nej, och det gör aldrig två modeller. Formateringsinstruktioner, beteendet vid verktygsanrop och sättet att vägra skiftar, så behandla ett leverantörsbyte som ett modellbyte: spara tjugo riktiga förfrågningar som testuppsättning och jämför svaren innan du går över.

Hur jämför jag kostnaden innan jag byter?

Ta en veckas verklig trafik, räkna input- och output-tokens var för sig och prissätt båda sidor per miljon tokens enligt deras listpriser. Output dominerar de flesta fakturor, så en leverantör som ser billig ut på input kan ändå bli dyrare för en pratsam arbetslast.

Kan jag fortsätta använda OpenAI:s SDK?

Ja. OpenAI:s officiella SDK:er fungerar oförändrade mot varje tjänst som implementerar samma kontrakt, och det är hela poängen med kompatibiliteten. Du behåller din retry-logik, din hantering av streaming och dina typer, och ändrar bara vart förfrågningarna går.

Kom igång med AI för européer.

Använd AI utan att skicka din data utomlands: allt på europeiska servrar, till ett europeiskt pris.

13 € i månaden för chatten, avsluta när du vill. Eller per token med kredit från 10 €.

Osäker? Gör quizet på 60 sekunder →