AWS Bedrock LiteLLM GenAI proxy

LiteLLM do Bedrock: błąd 'unsupported model id schema' / OAIBackend

Naprawa błędu LiteLLM 'unsupported model id schema' / OAIBackend przy połączeniu z AWS Bedrock: w nazwie modelu brakuje rozpoznawanego prefiksu providera lub użyto złej trasy dla ARN-ów profili inferencji.

Jerzy Kopaczewski ·
Wywołujesz AWS Bedrock przez proxy LiteLLM (lub SDK LiteLLM) i żądanie kończy się błędem, zanim w ogóle dotrze do AWS, z komunikatem o unsupported model id schema na trasie OAIBackend. Ten sam model działa, gdy wywołasz Bedrock bezpośrednio przez boto3, co sprawia, że wygląda to na problem AWS. Nim nie jest: to problem routingu modelu / konfiguracji w LiteLLM. Ten runbook pokazuje dlaczego i jak to naprawić.

Ten runbook opisuje błędy routingu modelu między LiteLLM a Bedrock. Architekturę uruchamiania modeli na AWS opisujemy w artykule LLM Inference na AWS - Bedrock vs SageMaker vs Self-Hosted na EKS, a zarządzaną warstwę agentów w Amazon Bedrock AgentCore - architektura, komponenty i cennik. Jeśli budujesz bramę modeli i chcesz zrobić to dobrze - umów konsultacje.

Objaw

Żądanie przez LiteLLM do modelu Bedrock kończy się błędem natychmiast. Komunikat odwołuje się do nazwy modelu i backendu/providera, którego nie udało się rozpoznać:

# Typowy błąd proxy / SDK LiteLLM (brzmienie zależy od wersji):
# litellm.BadRequestError: ... unsupported model id schema ...
# lub: LLM Provider NOT provided. Pass in the LLM provider you are trying to call.
# lub: Invalid model name passed in model=<twoj-model> ... OAIBackend
# lub: GetLLMProvider Exception - model=<twoj-model>, custom_llm_provider=...

# Sygnał: przekazana nazwa modelu NIE ma rozpoznawanego prefiksu providera,
# więc LiteLLM przeszedł do swojego backendu zgodnego z OpenAI (OAIBackend)
# i nie dopasował dla niego schematu Bedrock.

# Potwierdź, że TEN SAM model działa bezpośrednio przez boto3 (dowód, że AWS/dane
# uwierzytelniające są poprawne). Obecne modele Sonnet działają tylko przez
# profil inferencji, więc wywołaj je po ID profilu:
aws bedrock-runtime invoke-model \
  --model-id eu.anthropic.claude-sonnet-5-5 \
  --body '{"anthropic_version":"bedrock-2023-05-31","max_tokens":16,"messages":[{"role":"user","content":"hi"}]}' \
  --cli-binary-format raw-in-base64-out /dev/stdout
# Jeśli to działa, a LiteLLM nie, problem leży w nazwie modelu LiteLLM, nie w AWS.

Wskazanie właściwej warstwy to tu cała gra:

Gdzie zawodzi Znaczenie Ten runbook?
boto3 bezpośrednio działa, LiteLLM zawodzi Nazwie modelu LiteLLM brakuje prefiksu bedrock/ / zła trasa Tak
boto3 też zawodzi z AccessDenied IAM / dostęp do modelu, nie routing Nie (runbook o dostępie do modelu)
boto3 zawodzi z ValidationException Zła nazwa modelu lub region Nie (popraw nazwę modelu)

Przyczyna

LiteLLM decyduje, jak wywołać model, odczytując prefiks providera z początku nazwy modelu. Dla AWS Bedrock tym prefiksem jest bedrock/ (z podtrasami takimi jak bedrock/converse/ i bedrock/invoke/). Gdy prefiks jest nieobecny lub błędny, LiteLLM nie potrafi zaklasyfikować modelu jako wywołania Bedrock, przechodzi do backendu zgodnego z OpenAI (OAIBackend), a następnie zawodzi, bo surowa nazwa modelu Bedrock nie jest poprawnym schematem dla tego backendu. Błąd pojawia się przed jakimkolwiek wywołaniem sieciowym do AWS, dlatego dane uwierzytelniające i działające wywołanie boto3 nie mają z nim nic wspólnego.

Konkretne przyczyny:

1. Brak prefiksu providera w nazwie modelu (najczęstsza).

Przekazano eu.anthropic.claude-sonnet-5-5 tam, gdzie LiteLLM oczekiwał formy z prefiksem, np. bedrock/converse/eu.anthropic.claude-sonnet-5-5. Bez bedrock/ LiteLLM nie ma skąd wiedzieć, że to model Bedrock, i traktuje go jak nazwę w stylu OpenAI.

2. Surowe ID profilu inferencji lub application-inference-profile bez właściwej trasy.

Międzyregionalne profile inferencji (ID z prefiksem eu., us. lub global., np. eu.anthropic.claude-sonnet-5-5) oraz ARN-y application-inference-profile nie niosą providera, który LiteLLM mógłby wywnioskować. Przekazane bez prefiksu wywołują ten sam efekt. Wymagają jawnej trasy bedrock/converse/, żeby LiteLLM wiedział, które API Bedrock wywołać. Dziś ma to większe znaczenie niż dawniej: obecne modele Sonnet działają wyłącznie przez profil inferencji (nie ma surowego ID bazowego do wywołania on-demand), więc model Bedrock przekazywany do LiteLLM jest w praktyce prawie zawsze ID profilu, który potrzebuje tej trasy.

3. Wpis model_list w proxy z ustawionym model_name, ale bez konkretnego litellm_params.model.

W YAML-u proxy model_name to tylko publiczny alias, którego używają klienci. Rzeczywisty model Bedrock musi być ustawiony w litellm_params.model, z prefiksem bedrock/. Jeśli tego brakuje lub jest bez prefiksu, każde wywołanie tego aliasu nie trafia na właściwą trasę.

4. Literówka lub własny alias, który nie jest prawdziwą nazwą modelu Bedrock.

Ręcznie napisany alias (my-claude, pseudonim provisioned throughput), który nigdy nie został odwzorowany na konkretną nazwę bedrock/..., nie ma schematu, do którego mógłby się rozwiązać.

Rozwiązanie

A) Dodaj prefiks providera bedrock/ (naprawia większość przypadków).

# SDK LiteLLM
import litellm

# ŹLE - brak prefiksu providera, przejście do OAIBackend:
# litellm.completion(model="eu.anthropic.claude-sonnet-5-5", messages=...)

# DOBRZE - trasa bedrock/converse/ + ID profilu inferencji:
response = litellm.completion(
    model="bedrock/converse/eu.anthropic.claude-sonnet-5-5",
    messages=[{"role": "user", "content": "hi"}],
    aws_region_name="eu-west-1",
)

B) Popraw model_list w proxy - prefiksuj prawdziwy model, zachowaj czysty alias.

# config.yaml dla proxy LiteLLM
model_list:
  # Klienci wywołują "claude-sonnet"; LiteLLM kieruje to na prefiksowany model Bedrock.
  - model_name: claude-sonnet
    litellm_params:
      model: bedrock/converse/eu.anthropic.claude-sonnet-5-5   # konkretny + trasa z prefiksem
      aws_region_name: eu-west-1

  # ŹLE - alias bez konkretnego prefiksowanego modelu:
  # - model_name: claude-sonnet
  #   litellm_params:
  #     model: eu.anthropic.claude-sonnet-5-5   # brak trasy bedrock/converse/
# Zrestartuj proxy i potwierdź, że model jest zarejestrowany pod swoim aliasem:
curl -s http://localhost:4000/v1/models -H "Authorization: Bearer $LITELLM_KEY" \
  | python -c "import sys,json; print([m['id'] for m in json.load(sys.stdin)['data']])"
# Oczekiwane: alias (np. "claude-sonnet") pojawia się na liście.

C) Użyj jawnej trasy dla ARN-ów profili inferencji i application-inference-profile.

model_list:
  # Międzyregionalny profil inferencji - potrzebuje trasy converse, żeby LiteLLM
  # wiedział, które API Bedrock wywołać.
  - model_name: claude-sonnet-xr
    litellm_params:
      model: bedrock/converse/us.anthropic.claude-sonnet-5-5
      aws_region_name: us-east-1

  # Application inference profile po ARN - ta sama zasada, jawna trasa.
  - model_name: claude-app-profile
    litellm_params:
      model: bedrock/converse/arn:aws:bedrock:us-east-1:111122223333:application-inference-profile/abc123
      aws_region_name: us-east-1

D) Odwzoruj własne aliasy na konkretną nazwę modelu Bedrock.

model_list:
  # Pseudonim provisioned throughput lub własna nazwa musi rozwiązać się
  # do prawdziwego, prefiksowanego modelu.
  - model_name: my-claude          # przyjazna nazwa używana przez aplikację
    litellm_params:
      model: bedrock/converse/eu.anthropic.claude-sonnet-5-5  # właściwy model
      aws_region_name: eu-west-1
# Nigdy nie przekazuj samego pseudonimu - LiteLLM nie ma schematu dla "my-claude".

E) Wskaż providera jawnie, jeśli nie możesz zmienić nazwy modelu.

# Jeśli nazwa modelu jest narzucona wyżej i nie możesz dodać prefiksu,
# wskaż providera bezpośrednio:
response = litellm.completion(
    model="eu.anthropic.claude-sonnet-5-5",
    custom_llm_provider="bedrock",     # wymusza trasę Bedrock
    messages=[{"role": "user", "content": "hi"}],
    aws_region_name="eu-west-1",
)

Weryfikacja

# 1. Prefiksowane wywołanie przez LiteLLM zwraca teraz odpowiedź, nie błąd routingu.
python -c "
import litellm
r = litellm.completion(
    model='bedrock/converse/eu.anthropic.claude-sonnet-5-5',
    messages=[{'role':'user','content':'reply with OK'}],
    aws_region_name='eu-west-1',
)
print(r.choices[0].message.content)
"
# Oczekiwane: normalna odpowiedź. Brak błędu 'unsupported model id schema' / OAIBackend.

# 2. Przez proxy wywołaj po aliasie i potwierdź kod 200.
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:4000/v1/chat/completions \
  -H "Authorization: Bearer $LITELLM_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"claude-sonnet","messages":[{"role":"user","content":"hi"}]}'
# Oczekiwane: 200.

# 3. Potwierdź, że LiteLLM rozwiązał providera jako bedrock (debug raz, potem wyłącz).
python -c "
import litellm
litellm.set_verbose = True
litellm.completion(model='bedrock/converse/eu.anthropic.claude-sonnet-5-5',
    messages=[{'role':'user','content':'hi'}], aws_region_name='eu-west-1')
" 2>&1 | grep -i "provider" | head -3
# Oczekiwane: linie logu pokazujące custom_llm_provider = bedrock (nie openai / OAIBackend).
Ten błąd to prawie zawsze brak prefiksu bedrock/ w nazwie modelu, a nie problem AWS - dlatego ten sam model działa przez boto3. Zasada: w LiteLLM każda nazwa modelu Bedrock ma prefiks (bedrock/<model-id>), ARN-y profili inferencji i application-inference-profile biorą jawną trasę (bedrock/converse/<id-lub-arn>), a w YAML-u proxy prawdziwy prefiksowany model zawsze trafia do litellm_params.model, nigdy tylko do model_name.

 

Jerzy Kopaczewski

Budujesz bramę modeli na Bedrock?

Umów bezpłatną rozmowę 30 min. Pomagamy zespołom postawić LiteLLM lub bramę Bedrock z czystym routingiem modeli, fallbackiem i kontrolą kosztów, tak aby błędy routingu jak ten nigdy nie trafiły na produkcję.

Umów rozmowę