|
| 1 | +"""Derive the ``api`` override block for a model. |
| 2 | +
|
| 3 | +The api block holds request-level parameters. :mod:`cecli.models` merges each |
| 4 | +of these keys into ``extra_params`` the same way the ``api`` section of a |
| 5 | +``model-overrides`` entry is applied. |
| 6 | +""" |
| 7 | + |
| 8 | +from __future__ import annotations |
| 9 | + |
| 10 | +from typing import Dict, Optional |
| 11 | + |
| 12 | +from .identifiers import is_anthropic, is_claude_5_plus, is_gemini_2_5 |
| 13 | +from .utils import supports_reasoning |
| 14 | + |
| 15 | +_THINKING_BUDGET_TOKENS = 2048 |
| 16 | +#: Default thinking budget for Gemini 2.5 models (Gemini 2.5 Pro's default). |
| 17 | +_GEMINI_THINKING_BUDGET_TOKENS = 8192 |
| 18 | + |
| 19 | + |
| 20 | +def derive_api_config(provider: Optional[str], route: str, record: Optional[Dict]) -> Dict: |
| 21 | + """Return the ``api`` config block for a model. |
| 22 | +
|
| 23 | + Args: |
| 24 | + provider: Provider portion of the model name (may be ``None``). |
| 25 | + route: Model route (name after the provider prefix). |
| 26 | + record: The matched model metadata record, or ``None`` for unknown models. |
| 27 | +
|
| 28 | + Returns: |
| 29 | + A dict of request-level params (reasoning format, thinking, tool calls). |
| 30 | + """ |
| 31 | + reasoning = supports_reasoning(record) |
| 32 | + record = record or {} |
| 33 | + gemini_2_5 = is_gemini_2_5(provider, route, record) |
| 34 | + api: Dict = {} |
| 35 | + |
| 36 | + if reasoning and not gemini_2_5: |
| 37 | + effort = _default_reasoning_effort(record) |
| 38 | + |
| 39 | + if effort: |
| 40 | + api["reasoning_effort"] = effort |
| 41 | + |
| 42 | + if is_anthropic(provider, route, record) and not is_claude_5_plus(provider, route, record): |
| 43 | + # Claude 5+ uses adaptive thinking via ``reasoning_effort`` instead of |
| 44 | + # the ``thinking.type.enabled`` budget block. |
| 45 | + api["thinking"] = {"type": "enabled", "budget_tokens": _THINKING_BUDGET_TOKENS} |
| 46 | + elif gemini_2_5: |
| 47 | + # Gemini 2.5 configures thinking via a token budget; litellm maps the |
| 48 | + # generic ``thinking`` param onto ``thinkingBudget`` + ``includeThoughts``. |
| 49 | + api["thinking"] = {"type": "enabled", "budget_tokens": _GEMINI_THINKING_BUDGET_TOKENS} |
| 50 | + |
| 51 | + if record.get("supports_parallel_function_calling", True): |
| 52 | + api["parallel_tool_calls"] = True |
| 53 | + |
| 54 | + return api |
| 55 | + |
| 56 | + |
| 57 | +def _default_reasoning_effort(record): |
| 58 | + """Default reasoning effort for a reasoning-capable model. |
| 59 | +
|
| 60 | + Always ``medium``; the metadata effort flags are intentionally not used. |
| 61 | + """ |
| 62 | + return "medium" |
0 commit comments