Identyfikatorom modeli nie miejsce w TypeScript

· 5 min czytania

Id modelu to najszybciej zmieniający się fakt w całym tym systemie. Dostawcy zmieniają nazwy modeli, wycofują je, wypuszczają warianty z datą, po cichu zmieniają, na co wskazuje alias bez daty, a połowę udostępniają w zależności od tego, które konto pyta. Wkompiluj to w pakiet, a masz gwarancję, że pakiet w ciągu kilku tygodni będzie błędny — nie zepsuty w oczywisty sposób, co byłoby przynajmniej zgłoszeniem błędu, lecz błędny w ten konkretny sposób, w którym lista wyboru proponuje komuś model, którego jego klucz nie może wywołać.

Dlatego katalog jest plikiem JSON, a ciekawe nie jest to, że to JSON. Ciekawe jest to, co warstwy pod spodem przyznają na temat pewności.

Pięć warstw, późniejsze wygrywają z wcześniejszymi

0. pi-ai's built-in models      whatever it knows about the catalogued vendors
1. the bundled catalog.json     27 providers, 6 verified models
2. ~/.oharness/catalog.json     your edits, and what discovery found
3. a catalog path in config
4. providers / models in config
5. /models refresh              asks the vendor directly

Czytaj tę kolumnę liczb jako ranking pewności, a nie kolejność ładowania. Warstwa 0 to czyjaś migawka świata. Warstwa 1 to to, co byliśmy gotowi stwierdzić wprost. Warstwa 5 to dostawca odpowiadający na temat twojego konta, w tej chwili — i ona wygrywa, bo nic, co wydaliśmy trzy miesiące temu, nie wie więcej o twoich uprawnieniach niż endpoint, który zaraz wywołasz.

Warstwa dołączona zawiera dwudziestu siedmiu dostawców i sześć zweryfikowanych modeli, a ta proporcja to cały projekt. Fakty o dostawcach — endpoint, zmienna środowiskowa, protokół przesyłowy — są na tyle stabilne, że można je dostarczyć. Id modeli nie są, więc wprost podane są tylko te, które dało się faktycznie zweryfikować, a cała reszta przychodzi z wykrywania, które pyta własny /models każdego dostawcy.

Sześć to niewygodna liczba do opublikowania. Ale też uczciwa.

Nadpisania działają na poziomie pól

Powód, dla którego ma to znaczenie w codziennym użyciu, jest mniejszy i nudniejszy: skierowanie Kimi na jego endpoint dla Chin kontynentalnych nie powinno oznaczać ponownego podawania wszystkiego innego o Kimi.

{ "providers": { "moonshot": { "baseUrl": "https://api.moonshot.cn/v1" } } }

To cała edycja. Nadpisania całych wpisów to sposób, w jaki psują się formaty konfiguracji — ktoś kopiuje dostarczony blok, żeby zmienić URL, a dwa wydania później jego kopia jest jedyną rzeczą, która stoi między nim a poprawką, którą wszyscy inni już dostali.

Gdzie kończy się zasiew

Warstwa 0 zasługuje na uwagę, bo to ona zaskakuje ludzi: dostawca, którego nigdy nie podłączyłeś, i tak ma modele do pokazania. Pochodzą one z pi-ai, warstwy przesyłowej, która dostarcza wygenerowany katalog tego, co wie. Zawierają okna kontekstu, cenniki i poziomy rozumowania, a nie wiedzą absolutnie nic o tym, co twoje konto może wywołać — dlatego zarówno wpis podany wprost, jak i wszystko, co zwróci wykrywanie, wygrywa z nimi, a OHARNESS_NO_BUILTIN_MODELS=1 całkowicie wyłącza zasiew.

Dwa ograniczenia chronią przed szkodami z jego strony.

Model jest zasiewany tylko do wpisu, którego protokół odpowiada API, pod którym pi-ai go skatalogował. Modele Mistral są w pi-ai przypisane do jego własnego API conversations, więc zostawia się je wykrywaniu, zamiast wysyłać je do endpointu zgodnego z OpenAI w kształcie, którego ten nie obsługuje. Wysłanie złego kształtu to błąd 400, który musisz debugować, a nie gorsza odpowiedź, z którą da się żyć.

A tam, gdzie oba katalogi nie zgadzają się co do id dostawcy, uzgadnia się je przez wskazanie tego drugiego, a nie przez zgadywanie:

{ "providers": { "moonshot": { "piProvider": "moonshotai" } } }

Dostawca bez zasiewu i jeszcze bez wykrywania — lokalny serwer, brama, dla której nikt nie dostarcza nazw — i tak pojawia się na liście wyboru jako pojedynczy wiersz, który otwiera panel jego podłączenia. Pusty stan, który sam się tłumaczy, jest lepszy niż dostawca, którego po prostu nie ma, dopóki nie zostanie spełniony jakiś niewidoczny warunek.

Protokół to jedyna rzecz warta nazwania

Pole protocol we wpisie katalogu nazywa format, którym posługuje się jego endpoint:

anthropic-messages   openai-chat      openai-responses
gemini               bedrock          vertex
openai-codex

openai-codex to ten, który uzasadnia trzymanie tej listy jawnie, zamiast wywnioskowania jej z nazwy dostawcy. To backend, z którym rozmawia Codex CLI, i jest to naprawdę inny format przesyłowy niż openai-responses, a nie ten sam na innym hoście: store jest odrzucane, max_output_tokens nie jest wysyłane, a id konta podróżuje we własnym nagłówku. System, który zgadywałby „to OpenAI, użyj kształtu OpenAI”, myliłby się w jego przypadku na trzy różne sposoby.

SDK stojące za tymi protokołami są importowane leniwie, więc sesja, która rozmawia wyłącznie z Anthropic, nigdy nie ładuje klientów AWS ani Google.

Co się nie przesunęło

Uwierzytelnianie. Dane uwierzytelniające są rozwiązywane przy każdym żądaniu przez własny AuthManager harnessu, bo token subskrypcji ważny przy uruchomieniu godzinę później ważny już nie jest. Dlatego implementacje API z pi-ai są wywoływane bezpośrednio i otrzymują już rozwiązany klucz i nagłówki, zamiast przechodzić przez jego uwierzytelnianie dostawców i magazyn danych uwierzytelniających.

Dlatego niektóre wpisy w ogóle nie są dostarczane. Bedrock i Vertex działają jako protokoły, ale tylko z danymi uwierzytelniającymi, które już są w środowisku — pełne podpisywanie SigV4 i gcloud ADC żyją dokładnie w tej warstwie dostawców, z której ten harness rezygnuje przy uwierzytelnianiu. Azure OpenAI nie ma stałego bazowego URL do skatalogowania, bo endpoint jest inny dla każdego wdrożenia. Oba może zadeklarować każdy, kto ma już skonfigurowane środowisko; żaden nie zostanie dostarczony jako działająca konfiguracja domyślna, która po cichu nią nie jest.

Wzorzec pod tym wszystkim: podawaj fakty, które stoją w miejscu, pytaj o te, które się zmieniają, i trzymaj tę różnicę na widoku w pliku, a nie zakopaną w informacjach o wydaniu.


OHarness to harness agenta open source na licencji MIT. Dokumentacja dostawców opisuje każdą warstwę, nadpisanie i protokół wymienione powyżej, a centrum dostawców pokazuje, co jest dziś w dołączonym katalogu.