Оновлення інтерфейсу, сумісного з OpenAI: глибока підтримка Claude

31 лип. 2026 р. · AIHubMix · 8 min read · Новини

Оновлення інтерфейсу, сумісного з OpenAI: глибока підтримка Claude

Ми оновили інтерфейс, сумісний з OpenAI, з глибшими оптимізаціями, спеціально для моделей серії Claude. Тепер ви можете контролювати мислення та кешування більш точно та зручно. Чергування мислення в багатоповторних розмовах стало більш зручним для користувачів, що дозволяє безперешкодно інтегруватися без додаткових параметрів. Також підтримується активація бета-функцій, запропонованих Anthropic.

1. Мислення моделі (Розширене мислення)

1.1 Переваги чергування мислення

Коли чергування мислення не активовано, модель виконує мислення лише один раз на початку черги асистента; наступні відповіді генеруються безпосередньо після отримання результатів інструментів, без створення нових блоків мислення:

User → [Thinking] → Tool Call → Tool Result → Response

Коли чергування мислення активовано, модель вставляє новий блок мислення щоразу, коли отримує результат інструменту, формуючи ланцюг міркувань:

User → [Thinking] → Tool Call → Tool Result → [Thinking] → Response
                                                ↑ Чергування мислення

Це дозволяє моделі:

  • Виконувати вторинні міркування на основі результатів інструментів, а не просто конкатенувати виходи.
  • Ланцюгувати міркування між кількома викликами інструментів, де кожне рішення базується на аналізі попереднього кроку.
Джерело: Anthropic Interleaved Thinking

1.2 Активація мислення

Ви можете активувати мислення чотирма способами, вибравши будь-який з них:

Метод Приклад Опис
reasoning_effort "reasoning_effort": "low" Стандартний параметр OpenAI, розміщений на верхньому рівні тіла запиту
reasoning.effort "reasoning": {"effort": "low"} Еквівалент попереднього методу, розміщений у об'єкті reasoning
reasoning.max_tokens "reasoning": {"max_tokens": 1024} Точно контролює максимальну кількість токенів для мислення
Назва моделі з -think "model": "claude-sonnet-4-5-think" Найпростіший спосіб, не вимагає додаткових параметрів
Пріоритет (коли використовуються кілька методів): reasoning_effort > reasoning.max_tokens > reasoning.effort > -think суфікс

Можливі значення для зусиль: minimal / low / medium / high / xhigh

1.3 Повернення мислення

Повідомлення відповіді міститиме два нові поля:

  • reasoning_content: Зміст мислення (рядок), для зручного відображення.
  • reasoning_details: Повна структурована інформація про мислення, яка повинна повертатися так, як є, у багатоповторних розмовах; внутрішня структура може відрізнятися між постачальниками.

Приклад без потокового режиму (без непов'язаних полів):

{
  "choices": [{
    "message": {
      "role": "assistant",
      "content": "Привіт! Чим я можу вам допомогти сьогодні?",
      "reasoning_content": "Користувач просто вітається...",
      "reasoning_details": {
        "type": "thinking",
        "thinking": "Користувач просто вітається...",
        "signature": "Er8CCkYI..."
      }
    }
  }]
}

У потокових відповідях зміст мислення буде надсилатися частинами через delta.reasoning_content та delta.reasoning_details. Для повної логіки конкатенації потокового режиму зверніться до повного прикладу нижче.

1.4 Збереження мислення в багатоповторних розмовах (Чергування мислення вбудоване, додаткові параметри не потрібні)

Щоб дозволити моделі продовжувати свої можливості міркування в багатоповторних розмовах, просто вставте раніше повернуте reasoning_details так, як є у наступне повідомлення асистента:

messages = [
    {"role": "user", "content": "Яка погода в Бостоні?"},
    {
        "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": "дощ"}',
    }
]

AIHubMix автоматично активує чергування мислення, коли виявляє історичну інформацію про мислення в запиті, дозволяючи моделі продовжувати глибоке міркування після отримання результатів викликів інструментів без необхідності в додаткових параметрах.

1.5 Повний приклад

Наступні два приклади демонструють повний процес багатоповторного виклику інструменту + чергування мислення: запит користувача → модель думає та викликає інструмент → вставка результатів інструменту (збереження reasoning_details) → модель чергування мислення дає остаточну відповідь.

Без потокового режиму · Чергування мислення

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-***"),
)

# ── Визначення інструменту ───────────────────────────────────────────
tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Отримати поточну погоду для місця",
        "parameters": {
            "type": "object",
            "properties": {"location": {"type": "string", "description": "Назва міста"}},
            "required": ["location"]
        }
    }
}]

# ── Імітація виконання інструменту ─────────────────────────────────────
WEATHER_DB = {
    "boston": {"temperature": "45°F (7°C)", "condition": "дощ", "humidity": "85%", "wind": "15 mph NE"},
    "tokyo":  {"temperature": "72°F (22°C)", "condition": "сонячно", "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": "ясно"}))
    return "{}"

# ── Цикл багатоповторної розмови ─────────────────────────────
messages = [
    {"role": "user", "content": "Яка погода в Бостоні? Потім порекомендуйте, що вдягнути."}
]

turn = 0
while True:
    turn += 1
    print(f"\n── Черга {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

    # Друк процесу мислення
    if msg.reasoning_content:
        label = "Чергування мислення" if turn > 1 else "Мислення"
        print(f"[{label}] {msg.reasoning_content}")

    # Друк змісту відповіді
    if msg.content:
        print(f"[Відповідь] {msg.content}")

    # Друк викликів інструментів
    if msg.tool_calls:
        for tc in msg.tool_calls:
            print(f"[Виклик інструменту: {tc.function.name}] {tc.function.arguments}")

    # Побудова повідомлення асистента, зберігаючи reasoning_details (критично важливо!)
    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  # передати без змін
    messages.append(assistant_msg)

    # Відсутність tool_calls означає, що розмова завершена
    if not msg.tool_calls:
        break

    # Виконати інструменти та додати результати до повідомлень
    for tc in msg.tool_calls:
        args = json.loads(tc.function.arguments)
        result = execute_tool(tc.function.name, args)
        print(f"[Результат інструменту: {tc.function.name}] {result}")
        messages.append({"role": "tool", "tool_call_id": tc.id, "content": result})

Потокове · Чергування мислення

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-***"),
)

# ── Визначення інструменту та імітація виконання ─────────────────────────
tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Отримати поточну погоду для місця",
        "parameters": {
            "type": "object",
            "properties": {"location": {"type": "string", "description": "Назва міста"}},
            "required": ["location"]
        }
    }
}]

WEATHER_DB = {
    "boston": {"temperature": "45°F (7°C)", "condition": "дощ", "humidity": "85%", "wind": "15 mph NE"},
    "tokyo":  {"temperature": "72°F (22°C)", "condition": "сонячно", "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": "ясно"}))
    return "{}"

# ── Потоковий збирач відповідей ────────────────────────────────
def stream_and_collect(turn: int, **kwargs):
    """Потокове відповідь, друкуйте мислення/зміст в реальному часі, накопичуйте reasoning_details/tool_calls."""
    rd = {}            # накопичені reasoning_details
    content = ""       # накопичений текст відповіді
    tc_map = {}        # накопичені tool_calls (за індексом)
    cur = "none"       # поточний розділ виходу: 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

        # ── Обробка мислення ──
        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
            # Друк частин мислення в реальному часі
            thinking_chunk = rd_delta.get("thinking", "")
            if thinking_chunk:
                if cur != "thinking":
                    cur = "thinking"
                    label = "Чергування мислення" if turn > 1 else "Мислення"
                    sys.stdout.write(f"\n[{label}] ")
                sys.stdout.write(thinking_chunk)
                sys.stdout.flush()

        # ── Обробка змісту ──
        if delta.content:
            if cur != "content":
                if cur == "thinking":
                    sys.stdout.write("\n")
                cur = "content"
                sys.stdout.write("\n[Відповідь] ")
            sys.stdout.write(delta.content)
            sys.stdout.flush()
            content += delta.content

        # ── Обробка 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 ""

    # Завершити поточний розділ виходу
    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,
    }

# ── Цикл багатоповторної розмови ─────────────────────────────
messages = [
    {"role": "user", "content": "Яка погода в Бостоні? Потім порекомендуйте, що вдягнути."}
]

turn = 0
while True:
    turn += 1
    print(f"\n── Черга {turn} ──")

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

    # Друк викликів інструментів
    if result["tool_calls"]:
        for tc in result["tool_calls"]:
            print(f"[Виклик інструменту: {tc['function']['name']}] {tc['function']['arguments']}")

    # Побудова повідомлення асистента, зберігаючи reasoning_details (критично важливо!)
    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"]  # передати без змін
    messages.append(assistant_msg)

    # Відсутність tool_calls означає, що розмова завершена
    if not result["tool_calls"]:
        break

    # Виконати інструменти та додати результати до повідомлень
    for tc in result["tool_calls"]:
        args = json.loads(tc["function"]["arguments"])
        tool_result = execute_tool(tc["function"]["name"], args)
        print(f"[Результат інструменту: {tc['function']['name']}] {tool_result}")
        messages.append({"role": "tool", "tool_call_id": tc["id"], "content": tool_result})

1.6 Правила відображення інтенсивності мислення

Режим зусиль:

  • Opus 4.6 / Sonnet 4.6 і вище: відображається на рідному рівні зусиль Адаптивного мислення Anthropic.
  • Інші моделі: розраховуються за формулою для budget_tokens:
budget_tokens = max(min(max_tokens × effort_ratio, 128000), 1024)
зусилля effort_ratio
xhigh 0.95
high 0.80
medium 0.50
low 0.20
minimal 0.10

Відображення зусиль адаптивного мислення:

Вхідні зусилля Opus 4.6 Sonnet 4.6
xhigh max high
high high high
medium medium medium
low low low
minimal low low

max_tokens Режим: Безпосередньо призначається як budget_tokens Anthropic.

-think суфікс: Opus/Sonnet 4.6+ використовує адаптивне мислення (зусилля=середнє); інші моделі встановлюють budget_tokens = min(10240, max_tokens - 1), з типовим max_tokens 4096.


2. Кешування запитів

Ви можете використовувати кешування запитів, роблячи запити до моделі Claude через інтерфейс чату. Встановивши контроль кешу cache_control у повідомленнях, великі блоки тексту (як картки ролей, дані RAG, глави книг тощо) можуть бути кешовані для повторного використання, що дозволяє наступним запитам безпосередньо звертатися до кешу та значно знижувати витрати.

Офіційна документація Claude: Кешування запитів

2.1 Витрати на кешування

Операція Множник ціни (відносно початкової ціни запиту)
Запис кешу (TTL 5 хвилин) 1.25x
Запис кешу (TTL 1 година) 2x
Читання кешу 0.1x

2.2 Підтримувані моделі та мінімальна довжина кешу

Модель Мінімальна кількість токенів кешу
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 (застаріле) 1024
Claude Haiku 4.5 4096
Claude Haiku 3.5 (застаріле) / Haiku 3 2048
Обмеження кількості контрольних точок: Максимум 4 контрольні точки cache_control на запит.

2.3 TTL кешу

TTL Синтаксис Сценарії застосування
5 хвилин (за замовчуванням) "cache_control": {"type": "ephemeral"} Короткі сесії, рутинні запити
1 година "cache_control": {"type": "ephemeral", "ttl": "1h"} Довгі сесії, щоб уникнути повторних записів кешу

Витрати на запис для TTL 1 година вищі, але вони можуть заощадити загальні витрати, зменшуючи повторні записи в тривалих сесіях. Усі моделі з Claude 4.5 і пізніше від усіх постачальників (включаючи Anthropic, Amazon Bedrock, Google Vertex AI) підтримують TTL 1 година.

2.4 Використання

Ви можете встановити контрольні точки кешу, використовуючи поле cache_control в system, user (включаючи зображення) та tools. Наступні приклади показують лише ключову структуру, пропускаючи великі блоки тексту.

Кешування системного повідомлення (за замовчуванням TTL 5 хвилин):

{
  "model": "claude-opus-4-5",
  "messages": [
    {
      "role": "system",
      "content": [
        {"type": "text", "text": "Ви є AI асистентом"},
        {
          "type": "text",
          "text": "(довгий контекст)",
          "cache_control": {"type": "ephemeral"}
        }
      ]
    },
    {
      "role": "user",
      "content": [{"type": "text", "text": "Привіт"}]
    }
  ]
}

Кешування повідомлення користувача (TTL 1 година):

{
  "model": "claude-opus-4-5",
  "messages": [
    {
      "role": "system",
      "content": [{"type": "text", "text": "Ви є AI асистентом"}]
    },
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "(довгий контекст)",
          "cache_control": {"type": "ephemeral", "ttl": "1h"}
        },
        {"type": "text", "text": "Привіт"}
      ]
    }
  ]
}

Кешування повідомлення зображення:

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

Кешування визначення інструменту:

cache_control розміщується на верхньому рівні об'єкта інструменту (поряд з type та function):

{
  "tools": [{
    "type": "function",
    "function": {
      "name": "get_weather",
      "description": "Отримати поточну погоду для місця",
      "parameters": {
        "type": "object",
        "properties": {"city": {"type": "string"}},
        "required": ["city"]
      }
    },
    "cache_control": {"type": "ephemeral", "ttl": "1h"}
  }]
}

2.5 Перегляд статусу кешу

Поле usage відповіді поверне claude_cache_tokens_details, записуючи детальну інформацію про кеш:

Перше запит (створення кешу):

{
  "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
    }
  }
}

Наступні запити (використання кешу):

{
  "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
    }
  }
}
Поле Значення
cache_creation_input_tokens Кількість токенів, записаних у кеш у цьому запиті
cache_read_input_tokens Кількість токенів, прочитаних з кешу в цьому запиті
cache_write_5_minutes_input_tokens Кількість токенів, записаних у кеш з TTL 5 хвилин
cache_write_1_hour_input_tokens Кількість токенів, записаних у кеш з TTL 1 година
prompt_tokens_details.cached_tokens Кількість кешованих токенів, коли кеш використовується, сумісна з форматом OpenAI

3. Заголовок запиту для anthropic-beta

Ви можете активувати бета-функції моделі Claude через HTTP заголовок anthropic-beta, який AIHubMix передасть до API Anthropic.

Використання

Додайте anthropic-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": "Ви є AI асистентом"},
        {
          "type": "text",
          "text": "(довгий контекст)",
          "cache_control": {"type": "ephemeral"}
        }
      ]
    },
    {"role": "user", "content": [{"type": "text", "text": "привіт"}]}
  ]
}'
Для конкретних доступних ідентифікаторів бета-функцій, будь ласка, зверніться до Документації API Anthropic.

Останнє оновлення: 2026-06-01

More from the blog