Aktualizacja interfejsu zgodnego z OpenAI: Głębokie wsparcie dla Claude

31 lip 2026 · AIHubMix · 8 min read · Aktualności

Aktualizacja interfejsu zgodnego z OpenAI: Głębokie wsparcie dla Claude

Zaktualizowaliśmy interfejs zgodny z OpenAI o głębsze optymalizacje, szczególnie dla modeli serii Claude. Teraz możesz kontrolować myślenie i pamięć podręczną w sposób bardziej precyzyjny i wygodny. Przeplatane myślenie w rozmowach wieloturnowych jest teraz bardziej przyjazne dla użytkownika, umożliwiając płynne włączenie bez dodatkowych parametrów. Obsługuje również włączanie funkcji beta oferowanych przez Anthropic.

1. Myślenie modelu (Rozszerzone myślenie)

1.1 Zalety przeplatanego myślenia

Gdy przeplatane myślenie nie jest włączone, model wykonuje myślenie tylko raz na początku tury asystenta; kolejne odpowiedzi są generowane bezpośrednio po otrzymaniu wyników narzędzi, bez tworzenia nowych bloków myślenia:

Użytkownik → [Myślenie] → Wywołanie narzędzia → Wynik narzędzia → Odpowiedź

Gdy przeplatane myślenie jest włączone, model wstawia nowy blok myślenia za każdym razem, gdy otrzymuje wynik narzędzia, tworząc łańcuch rozumowania:

Użytkownik → [Myślenie] → Wywołanie narzędzia → Wynik narzędzia → [Myślenie] → Odpowiedź
                                                ↑ Przeplatane myślenie

To umożliwia modelowi:

  • Wykonywanie wtórnego rozumowania na podstawie wyników narzędzi, zamiast po prostu łączyć wyniki.
  • Łączenie rozumowania między wieloma wywołaniami narzędzi, gdzie każda decyzja opiera się na analizie poprzedniego kroku.
Źródło: Przeplatane myślenie Anthropic

1.2 Włączanie myślenia

Możesz włączyć myślenie na cztery sposoby, wybierając dowolny z nich:

Metoda Przykład Opis
reasoning_effort "reasoning_effort": "low" Standardowy parametr OpenAI, umieszczony na najwyższym poziomie ciała żądania
reasoning.effort "reasoning": {"effort": "low"} Równoważne poprzedniej metodzie, umieszczone w obiekcie reasoning
reasoning.max_tokens "reasoning": {"max_tokens": 1024} Precyzyjnie kontroluje maksymalną liczbę tokenów dla myślenia
Nazwa modelu z -think "model": "claude-sonnet-4-5-think" Najprostszy sposób, nie wymaga dodatkowych parametrów
Priorytet (gdy używane są wiele metod): reasoning_effort > reasoning.max_tokens > reasoning.effort > -think suffix

Możliwe wartości dla wysiłku: minimal / low / medium / high / xhigh

1.3 Zwracanie myślenia

W wiadomości odpowiedzi znajdą się dwa nowe pola:

  • reasoning_content: Treść myślenia (ciąg), do łatwego wyświetlania.
  • reasoning_details: Pełne zorganizowane informacje o myśleniu, które muszą być zwracane w takiej samej formie w rozmowach wieloturnowych; wewnętrzna struktura może różnić się między dostawcami.

Przykład bez strumieniowania (pomijając niepowiązane pola):

{
  "choices": [{
    "message": {
      "role": "assistant",
      "content": "Cześć! Jak mogę Ci dzisiaj pomóc?",
      "reasoning_content": "Użytkownik tylko mówi cześć...",
      "reasoning_details": {
        "type": "thinking",
        "thinking": "Użytkownik tylko mówi cześć...",
        "signature": "Er8CCkYI..."
      }
    }
  }]
}

W odpowiedziach strumieniowych treść myślenia będzie wysyłana w kawałkach za pomocą delta.reasoning_content i delta.reasoning_details. Aby uzyskać pełną logikę konkatenacji strumieniowej, zapoznaj się z pełnym przykładem poniżej.

1.4 Zachowanie myślenia w rozmowach wieloturnowych (Przeplatane myślenie jest wbudowane, nie są potrzebne dodatkowe parametry)

Aby umożliwić modelowi kontynuowanie swoich zdolności rozumowania w rozmowach wieloturnowych, wystarczy umieścić wcześniej zwrócone reasoning_details w takiej samej formie w wiadomości asystenta w następnej turze:

messages = [
    {"role": "user", "content": "Jaka jest pogoda w Bostonie?"},
    {
        "role": "assistant",
        "content": response.choices[0].message.content,
        "tool_calls": response.choices[0].message.tool_calls,
        "reasoning_details": response.choices[0].message.reasoning_details,
    },
    {
        "role": "tool",
        "tool_call_id": "toolu_xxx",
        "content": '{"temperature": 45, "condition": "rainy"}',
    }
]

AIHubMix automatycznie włączy przeplatane myślenie, gdy wykryje historyczne informacje o myśleniu w żądaniu, umożliwiając modelowi kontynuowanie głębokiego rozumowania po otrzymaniu wyników wywołania narzędzia bez konieczności dodatkowych parametrów.

1.5 Pełny przykład

Poniższe dwa przykłady ilustrują pełny proces wieloturnowego wywołania narzędzia + przeplatane myślenie: zapytanie użytkownika → model myśli i wywołuje narzędzie → wstrzykuje wyniki narzędzia (zachowując reasoning_details) → model przeplatane myślenie daje ostateczną odpowiedź.

Bez strumieniowania · Przeplatane myślenie

import os
import json
from openai import OpenAI

client = OpenAI(
    base_url="https://aihubmix.com/v1",
    api_key=os.environ.get("AIHUBMIX_API_KEY", "sk-***"),
)

# ── Definicja narzędzia ───────────────────────────────────────────
tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Pobierz aktualną pogodę dla lokalizacji",
        "parameters": {
            "type": "object",
            "properties": {"location": {"type": "string", "description": "Nazwa miasta"}},
            "required": ["location"]
        }
    }
}]

# ── Wykonanie narzędzia w trybie symulacji ───────────────────────
WEATHER_DB = {
    "boston": {"temperature": "45°F (7°C)", "condition": "rainy", "humidity": "85%", "wind": "15 mph NE"},
    "tokyo":  {"temperature": "72°F (22°C)", "condition": "sunny", "humidity": "45%", "wind": "5 mph S"},
}

def execute_tool(name: str, args: dict) -> str:
    if name == "get_weather":
        key = next((k for k in WEATHER_DB if k in args.get("location", "").lower()), None)
        return json.dumps(WEATHER_DB.get(key, {"temperature": "65°F", "condition": "clear"}))
    return "{}"

# ── Pętla rozmowy wieloturnowej ─────────────────────────────
messages = [
    {"role": "user", "content": "Jaka jest pogoda w Bostonie? A potem poleć, co ubrać."}
]

turn = 0
while True:
    turn += 1
    print(f"\n── Tura {turn} ──")

    response = client.chat.completions.create(
        model="claude-sonnet-4-5",
        messages=messages,
        tools=tools,
        extra_body={"reasoning": {"max_tokens": 2000}},
    )
    msg = response.choices[0].message

    # Wyświetl proces myślenia
    if msg.reasoning_content:
        label = "Przeplatane myślenie" if turn > 1 else "Myślenie"
        print(f"[{label}] {msg.reasoning_content}")

    # Wyświetl treść odpowiedzi
    if msg.content:
        print(f"[Odpowiedź] {msg.content}")

    # Wyświetl wywołania narzędzi
    if msg.tool_calls:
        for tc in msg.tool_calls:
            print(f"[Wywołanie narzędzia: {tc.function.name}] {tc.function.arguments}")

    # Zbuduj wiadomość asystenta, zachowując reasoning_details (krytyczne!)
    assistant_msg = {"role": "assistant", "content": msg.content}
    if msg.tool_calls:
        assistant_msg["tool_calls"] = msg.tool_calls
    if msg.reasoning_details:
        assistant_msg["reasoning_details"] = msg.reasoning_details  # przekaż w niezmienionej formie
    messages.append(assistant_msg)

    # Brak wywołań narzędzi oznacza, że rozmowa się zakończyła
    if not msg.tool_calls:
        break

    # Wykonaj narzędzia i dodaj wyniki do wiadomości
    for tc in msg.tool_calls:
        args = json.loads(tc.function.arguments)
        result = execute_tool(tc.function.name, args)
        print(f"[Wynik narzędzia: {tc.function.name}] {result}")
        messages.append({"role": "tool", "tool_call_id": tc.id, "content": result})

Strumieniowanie · Przeplatane myślenie

import os
import sys
import json
from openai import OpenAI

client = OpenAI(
    base_url="https://aihubmix.com/v1",
    api_key=os.environ.get("AIHUBMIX_API_KEY", "sk-***"),
)

# ── Definicja narzędzia i symulacja wykonania ─────────────────────────
tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Pobierz aktualną pogodę dla lokalizacji",
        "parameters": {
            "type": "object",
            "properties": {"location": {"type": "string", "description": "Nazwa miasta"}},
            "required": ["location"]
        }
    }
}]

WEATHER_DB = {
    "boston": {"temperature": "45°F (7°C)", "condition": "rainy", "humidity": "85%", "wind": "15 mph NE"},
    "tokyo":  {"temperature": "72°F (22°C)", "condition": "sunny", "humidity": "45%", "wind": "5 mph S"},
}

def execute_tool(name: str, args: dict) -> str:
    if name == "get_weather":
        key = next((k for k in WEATHER_DB if k in args.get("location", "").lower()), None)
        return json.dumps(WEATHER_DB.get(key, {"temperature": "65°F", "condition": "clear"}))
    return "{}"

# ── Zbieracz odpowiedzi strumieniowej ────────────────────────────────
def stream_and_collect(turn: int, **kwargs):
    """Strumieniuj odpowiedź, wyświetlaj myślenie/treść w czasie rzeczywistym, gromadź reasoning_details/tool_calls."""
    rd = {}            # zgromadzone reasoning_details
    content = ""       # zgromadzony tekst odpowiedzi
    tc_map = {}        # zgromadzone tool_calls (według indeksu)
    cur = "none"       # bieżąca sekcja wyjściowa: none / thinking / content

    stream = client.chat.completions.create(stream=True, **kwargs)
    for chunk in stream:
        if not chunk.choices:
            continue
        delta = chunk.choices[0].delta

        # ── Obsługuje myślenie ──
        rd_delta = getattr(delta, "reasoning_details", None)
        if rd_delta and isinstance(rd_delta, dict):
            for k, v in rd_delta.items():
                if k == "type":
                    rd[k] = v
                elif isinstance(v, str):
                    rd[k] = rd.get(k, "") + v
                elif v is not None:
                    rd[k] = v
            # Wyświetlaj kawałki myślenia w czasie rzeczywistym
            thinking_chunk = rd_delta.get("thinking", "")
            if thinking_chunk:
                if cur != "thinking":
                    cur = "thinking"
                    label = "Przeplatane myślenie" if turn > 1 else "Myślenie"
                    sys.stdout.write(f"\n[{label}] ")
                sys.stdout.write(thinking_chunk)
                sys.stdout.flush()

        # ── Obsługuje treść ──
        if delta.content:
            if cur != "content":
                if cur == "thinking":
                    sys.stdout.write("\n")
                cur = "content"
                sys.stdout.write("\n[Odpowiedź] ")
            sys.stdout.write(delta.content)
            sys.stdout.flush()
            content += delta.content

        # ── Obsługuje tool_calls ──
        for tc in delta.tool_calls or []:
            i = tc.index
            if i not in tc_map:
                tc_map[i] = {"id": "", "type": "function",
                             "function": {"name": "", "arguments": ""}}
            if tc.id:
                tc_map[i]["id"] = tc.id
            if tc.function:
                tc_map[i]["function"]["name"] += tc.function.name or ""
                tc_map[i]["function"]["arguments"] += tc.function.arguments or ""

    # Zakończ bieżącą sekcję wyjściową
    if cur in ("thinking", "content"):
        sys.stdout.write("\n")

    tool_calls = [tc_map[i] for i in sorted(tc_map)] if tc_map else None
    return {
        "content": content or None,
        "reasoning_details": rd or None,
        "tool_calls": tool_calls,
    }

# ── Pętla rozmowy wieloturnowej ─────────────────────────────
messages = [
    {"role": "user", "content": "Jaka jest pogoda w Bostonie? A potem poleć, co ubrać."}
]

turn = 0
while True:
    turn += 1
    print(f"\n── Tura {turn} ──")

    result = stream_and_collect(
        turn,
        model="claude-sonnet-4-5",
        messages=messages,
        tools=tools,
        extra_body={"reasoning": {"max_tokens": 2000}},
    )

    # Wyświetl wywołania narzędzi
    if result["tool_calls"]:
        for tc in result["tool_calls"]:
            print(f"[Wywołanie narzędzia: {tc['function']['name']}] {tc['function']['arguments']}")

    # Zbuduj wiadomość asystenta, zachowując reasoning_details (krytyczne!)
    assistant_msg = {"role": "assistant", "content": result["content"]}
    if result["tool_calls"]:
        assistant_msg["tool_calls"] = result["tool_calls"]
    if result["reasoning_details"]:
        assistant_msg["reasoning_details"] = result["reasoning_details"]  # przekaż w niezmienionej formie
    messages.append(assistant_msg)

    # Brak wywołań narzędzi oznacza, że rozmowa się zakończyła
    if not result["tool_calls"]:
        break

    # Wykonaj narzędzia i dodaj wyniki do wiadomości
    for tc in result["tool_calls"]:
        args = json.loads(tc["function"]["arguments"])
        tool_result = execute_tool(tc["function"]["name"], args)
        print(f"[Wynik narzędzia: {tc['function']['name']}] {tool_result}")
        messages.append({"role": "tool", "tool_call_id": tc["id"], "content": tool_result})

1.6 Zasady mapowania intensywności myślenia

Tryb wysiłku:

  • Opus 4.6 / Sonnet 4.6 i wyżej: mapuje do natywnego poziomu wysiłku Adaptive Thinking Anthropic.
  • Inne modele: obliczane za pomocą wzoru na budget_tokens:
budget_tokens = max(min(max_tokens × effort_ratio, 128000), 1024)
wysiłek effort_ratio
xhigh 0.95
high 0.80
medium 0.50
low 0.20
minimal 0.10

Mapowanie wysiłku Adaptive Thinking:

Przychodzący wysiłek Opus 4.6 Sonnet 4.6
xhigh max high
high high high
medium medium medium
low low low
minimal low low

Tryb max_tokens: Bezpośrednio przypisany jako budget_tokens Anthropic.

-think suffix: Opus/Sonnet 4.6+ używa myślenia adaptacyjnego (wysiłek=medium); inne modele ustawiają budget_tokens = min(10240, max_tokens - 1), z domyślnym max_tokens równym 4096.


2. Pamięć podręczna zapytań

Możesz używać pamięci podręcznej zapytań podczas składania żądań do modelu Claude za pośrednictwem interfejsu czatu. Ustawiając punkty przerwania cache_control w wiadomościach, duże bloki tekstu (takie jak karty ról, dane RAG, rozdziały książek itp.) mogą być przechowywane w pamięci podręcznej do ponownego użycia, co pozwala na bezpośrednie trafienie do pamięci podręcznej w kolejnych żądaniach i znaczne obniżenie kosztów.

Oficjalna dokumentacja Claude: Pamięć podręczna zapytań

2.1 Koszty pamięci podręcznej

Operacja Mnożnik ceny (względem oryginalnej ceny wejściowej)
Zapis pamięci podręcznej (TTL 5 minut) 1.25x
Zapis pamięci podręcznej (TTL 1 godzina) 2x
Odczyt pamięci podręcznej 0.1x

2.2 Obsługiwane modele i minimalna długość pamięci podręcznej

Model Minimalna liczba tokenów w pamięci podręcznej
Claude Opus 4.8 1024
Claude Opus 4.7 2048
Claude Opus 4.6 / Opus 4.5 4096
Claude Sonnet 4.6 / Sonnet 4.5 / Opus 4.1 / Opus 4 / Sonnet 4 / Sonnet 3.7 (przestarzałe) 1024
Claude Haiku 4.5 4096
Claude Haiku 3.5 (przestarzałe) / Haiku 3 2048
Limit ilości punktów przerwania: Maksymalnie 4 cache_control punkty przerwania na żądanie.

2.3 TTL pamięci podręcznej

TTL Składnia Scenariusze zastosowania
5 minut (domyślnie) "cache_control": {"type": "ephemeral"} Krótkie sesje, rutynowe żądania
1 godzina "cache_control": {"type": "ephemeral", "ttl": "1h"} Długie sesje, aby uniknąć powtarzających się zapisów pamięci podręcznej

Koszty zapisu dla TTL 1-godzinnego są wyższe, ale mogą zaoszczędzić całkowite wydatki, redukując powtarzające się zapisy w długich sesjach. Wszystkie modele od Claude 4.5 i później od wszystkich dostawców (w tym Anthropic, Amazon Bedrock, Google Vertex AI) obsługują TTL 1-godzinny.

2.4 Użycie

Możesz ustawić punkty przerwania pamięci podręcznej, używając pola cache_control w system, user (w tym obrazy) oraz tools. Poniższe przykłady pokazują tylko kluczową strukturę, pomijając duże bloki tekstu.

Pamięć podręczna wiadomości systemowej (domyślnie TTL 5 minut):

{
  "model": "claude-opus-4-5",
  "messages": [
    {
      "role": "system",
      "content": [
        {"type": "text", "text": "Jesteś asystentem AI"},
        {
          "type": "text",
          "text": "(długi kontekst)",
          "cache_control": {"type": "ephemeral"}
        }
      ]
    },
    {
      "role": "user",
      "content": [{"type": "text", "text": "Cześć"}]
    }
  ]
}

Pamięć podręczna wiadomości użytkownika (TTL 1 godzina):

{
  "model": "claude-opus-4-5",
  "messages": [
    {
      "role": "system",
      "content": [{"type": "text", "text": "Jesteś asystentem AI"}]
    },
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "(długi kontekst)",
          "cache_control": {"type": "ephemeral", "ttl": "1h"}
        },
        {"type": "text", "text": "Cześć"}
      ]
    }
  ]
}

Pamięć podręczna wiadomości obrazkowej:

{
  "role": "user",
  "content": [
    {
      "type": "image_url",
      "image_url": {"detail": "auto", "url": "data:image/jpeg;base64,/9j/4AAQ..."},
      "cache_control": {"type": "ephemeral"}
    },
    {"type": "text", "text": "Co to jest?"}
  ]
}

Pamięć podręczna definicji narzędzia:

cache_control jest umieszczane na najwyższym poziomie obiektu narzędzia (obok type i function):

{
  "tools": [{
    "type": "function",
    "function": {
      "name": "get_weather",
      "description": "Pobierz aktualną pogodę dla lokalizacji",
      "parameters": {
        "type": "object",
        "properties": {"city": {"type": "string"}},
        "required": ["city"]
      }
    },
    "cache_control": {"type": "ephemeral", "ttl": "1h"}
  }]
}

2.5 Wyświetlanie statusu pamięci podręcznej

Pole usage odpowiedzi zwróci claude_cache_tokens_details, rejestrując szczegółowe informacje o pamięci podręcznej:

Pierwsze żądanie (tworzenie pamięci podręcznej):

{
  "usage": {
    "prompt_tokens": 22,
    "completion_tokens": 890,
    "total_tokens": 912,
    "claude_cache_tokens_details": {
      "cache_creation_input_tokens": 6266,
      "cache_read_input_tokens": 0,
      "cache_write_5_minutes_input_tokens": 6266,
      "cache_write_1_hour_input_tokens": 0
    }
  }
}

Kolejne żądania (trafienie w pamięć podręczną):

{
  "usage": {
    "prompt_tokens": 22,
    "completion_tokens": 810,
    "total_tokens": 832,
    "prompt_tokens_details": {
      "cached_tokens": 6266
    },
    "claude_cache_tokens_details": {
      "cache_creation_input_tokens": 0,
      "cache_read_input_tokens": 6266,
      "cache_write_5_minutes_input_tokens": 0,
      "cache_write_1_hour_input_tokens": 0
    }
  }
}
Pole Znaczenie
cache_creation_input_tokens Liczba tokenów zapisanych w pamięci podręcznej w tym żądaniu
cache_read_input_tokens Liczba tokenów odczytanych z pamięci podręcznej w tym żądaniu
cache_write_5_minutes_input_tokens Liczba tokenów zapisanych w pamięci podręcznej TTL 5 minut
cache_write_1_hour_input_tokens Liczba tokenów zapisanych w pamięci podręcznej TTL 1 godzina
prompt_tokens_details.cached_tokens Liczba tokenów w pamięci podręcznej, gdy pamięć podręczna jest trafiona, zgodna z formatem OpenAI

3. Nagłówek żądania dla anthropic-beta

Możesz włączyć funkcje beta modelu Claude za pomocą nagłówka HTTP anthropic-beta, który AIHubMix przekaże do API Anthropic.

Użycie

Dodaj anthropic-beta do nagłówka żądania, a wartość powinna być odpowiednim identyfikatorem funkcji beta:

curl "https://aihubmix.com/v1/chat/completions" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
  -H "anthropic-beta: context-1m-2025-08-07" \
  -d '{
  "model": "claude-opus-4-5",
  "messages": [
    {
      "role": "system",
      "content": [
        {"type": "text", "text": "Jesteś asystentem AI"},
        {
          "type": "text",
          "text": "(długi kontekst)",
          "cache_control": {"type": "ephemeral"}
        }
      ]
    },
    {"role": "user", "content": [{"type": "text", "text": "cześć"}]}
  ]
}'
Aby uzyskać szczegółowe identyfikatory beta, zapoznaj się z Dokumentacją API Anthropic.

Ostatnia aktualizacja: 2026-06-01

More from the blog