simbiot-harness/venv/lib/python3.12/site-packages/strands/models/_defaults.py
Simbiot Harness b60439152b Simbiot Harness v0.1: тактовая лестница на Strands + CQRS/ES-спина
- harness/es.py: append-only event store + проекции (образец — кооп-портал)
- harness/levels.py: уровни 1с/1м/1ч/1д, контекст ∝ масштабу
- harness/scheduler.py: уровневые потоки, идемпотентные тики, absorbed-стабы
- harness/isolated_runner.py + _llm_worker.py: LLM-тик в сабпроцессе
  (глобальный asyncio-рантайм Strands не переживает 2+ create_harness)
- cli.py: init/task/tasks/status/events + requeue (написан самим минутным агентом)
- 9router: отдельный ключ sk-simbiot, модель auto (glm-5.3 первым)
2026-09-29 15:28:50 +00:00

199 lines
7.3 KiB
Python

"""Default model metadata lookup tables.
Provides context window limits for known model IDs across all providers.
Values sourced from provider documentation and
https://github.com/BerriAI/litellm/blob/litellm_internal_staging/model_prices_and_context_window.json
Applied to providers with well-known, fixed model IDs: Bedrock, Anthropic, OpenAI,
OpenAI Responses, Gemini, and Mistral. Providers that use local/custom model IDs
(Ollama, LlamaCpp, SageMaker) or proxy to other providers with their own prefixed
ID format (LiteLLM) are excluded — their context windows depend on deployment config,
not a static table.
"""
import logging
from collections.abc import Mapping
from typing import TypeVar
logger = logging.getLogger(__name__)
_C = TypeVar("_C", bound=Mapping[str, object])
# Default context window limit (in tokens) when the model does not report one.
DEFAULT_CONTEXT_WINDOW_LIMIT = 200_000
# Context window limits (in tokens) for known model IDs.
#
# Best-effort lookup table — unknown models return None and callers
# fall back gracefully (e.g. proactive compression is disabled).
# Users can always override with an explicit context_window_limit in their model config.
#
# For Bedrock models with cross-region prefixes (e.g. us., eu., global.),
# get_context_window_limit strips prefixes before lookup so only the base model ID is needed here.
_CONTEXT_WINDOW_LIMITS: dict[str, int] = {
# Anthropic (direct API)
"claude-sonnet-4-6": 1_000_000,
"claude-sonnet-4-20250514": 1_000_000,
"claude-sonnet-4-5": 200_000,
"claude-sonnet-4-5-20250929": 200_000,
"claude-opus-4-6": 1_000_000,
"claude-opus-4-6-20260205": 1_000_000,
"claude-opus-4-7": 1_000_000,
"claude-opus-4-7-20260416": 1_000_000,
"claude-opus-4-8": 1_000_000,
"claude-opus-5": 1_000_000,
"claude-fable-5": 1_000_000,
"claude-sonnet-5": 1_000_000,
"claude-opus-4-5": 200_000,
"claude-opus-4-5-20251101": 200_000,
"claude-opus-4-20250514": 200_000,
"claude-opus-4-1": 200_000,
"claude-opus-4-1-20250805": 200_000,
"claude-haiku-4-5": 200_000,
"claude-haiku-4-5-20251001": 200_000,
"claude-3-7-sonnet-20250219": 200_000,
"claude-3-5-sonnet-20241022": 200_000,
"claude-3-5-sonnet-20240620": 200_000,
"claude-3-5-haiku-20241022": 200_000,
"claude-3-opus-20240229": 200_000,
"claude-3-haiku-20240307": 200_000,
# Bedrock Anthropic (base model IDs — cross-region prefixes stripped by get_context_window_limit)
"anthropic.claude-sonnet-4-6": 1_000_000,
"anthropic.claude-sonnet-4-20250514-v1:0": 1_000_000,
"anthropic.claude-sonnet-4-5-20250929-v1:0": 200_000,
"anthropic.claude-opus-4-6-v1": 1_000_000,
"anthropic.claude-opus-4-7": 1_000_000,
"anthropic.claude-opus-4-8": 1_000_000,
"anthropic.claude-opus-5": 1_000_000,
"anthropic.claude-fable-5": 1_000_000,
"anthropic.claude-sonnet-5": 1_000_000,
"anthropic.claude-opus-4-5-20251101-v1:0": 200_000,
"anthropic.claude-opus-4-20250514-v1:0": 200_000,
"anthropic.claude-opus-4-1-20250805-v1:0": 200_000,
"anthropic.claude-haiku-4-5-20251001-v1:0": 200_000,
"anthropic.claude-haiku-4-5@20251001": 200_000,
"anthropic.claude-3-7-sonnet-20250219-v1:0": 200_000,
"anthropic.claude-3-7-sonnet-20240620-v1:0": 200_000,
"anthropic.claude-3-5-sonnet-20241022-v2:0": 200_000,
"anthropic.claude-3-5-sonnet-20240620-v1:0": 200_000,
"anthropic.claude-3-5-haiku-20241022-v1:0": 200_000,
"anthropic.claude-3-opus-20240229-v1:0": 200_000,
"anthropic.claude-3-haiku-20240307-v1:0": 200_000,
"anthropic.claude-3-sonnet-20240229-v1:0": 200_000,
"anthropic.claude-mythos-preview": 1_000_000,
# Bedrock Amazon Nova
"amazon.nova-pro-v1:0": 300_000,
"amazon.nova-lite-v1:0": 300_000,
"amazon.nova-micro-v1:0": 128_000,
"amazon.nova-premier-v1:0": 1_000_000,
"amazon.nova-2-lite-v1:0": 1_000_000,
"amazon.nova-2-pro-preview-20251202-v1:0": 1_000_000,
# Bedrock Z.AI
"zai.glm-4.7": 203_000,
# OpenAI
"gpt-6-astra": 1_050_000,
"gpt-5.6": 1_050_000,
"gpt-5.6-sol": 1_050_000,
"gpt-5.6-terra": 1_050_000,
"gpt-5.6-luna": 1_050_000,
"gpt-5.5": 1_050_000,
"gpt-5.5-pro": 1_050_000,
"gpt-5.4": 1_050_000,
"gpt-5.4-pro": 1_050_000,
"gpt-5.4-mini": 272_000,
"gpt-5.4-nano": 272_000,
"gpt-5.2": 272_000,
"gpt-5.2-pro": 272_000,
"gpt-5.1": 272_000,
"gpt-5": 272_000,
"gpt-5-mini": 272_000,
"gpt-5-nano": 272_000,
"gpt-5-pro": 128_000,
"gpt-4.1": 1_047_576,
"gpt-4.1-mini": 1_047_576,
"gpt-4.1-nano": 1_047_576,
"gpt-4o": 128_000,
"gpt-4o-mini": 128_000,
"gpt-4-turbo": 128_000,
"o3": 200_000,
"o3-mini": 200_000,
"o3-pro": 200_000,
"o4-mini": 200_000,
"o1": 200_000,
# Google Gemini
"gemini-2.5-flash": 1_048_576,
"gemini-2.5-flash-lite": 1_048_576,
"gemini-2.5-pro": 1_048_576,
"gemini-2.0-flash": 1_048_576,
"gemini-2.0-flash-lite": 1_048_576,
"gemini-3-pro-preview": 1_048_576,
"gemini-3-flash-preview": 1_048_576,
"gemini-3.6-flash": 1_048_576,
"gemini-3.5-flash": 1_048_576,
"gemini-3.5-flash-lite": 1_048_576,
"gemini-3.1-flash-lite": 1_048_576,
"gemini-3.1-pro-preview": 1_048_576,
"gemini-3.1-flash-lite-preview": 1_048_576,
# Mistral
"mistral-large-latest": 262_144,
"mistral-large-2512": 262_144,
"mistral-large-3": 262_144,
"mistral-medium-latest": 131_072,
"mistral-medium-2505": 131_072,
"mistral-small-latest": 131_072,
"mistral-small-3-2-2506": 131_072,
}
def get_context_window_limit(model_id: str) -> int | None:
"""Look up the context window limit for a model ID.
For Bedrock model IDs with prefixes (e.g. ``us.anthropic.claude-sonnet-4-6``),
prefixes are stripped as a fallback if the direct lookup fails.
Args:
model_id: The model ID to look up.
Returns:
The context window limit in tokens, or None if not found.
"""
direct = _CONTEXT_WINDOW_LIMITS.get(model_id)
if direct is not None:
return direct
# Fallback: strip prefixes before each dot and retry (handles nested cross-region prefixes and ARNs)
stripped = model_id
while (dot_index := stripped.find(".")) != -1:
stripped = stripped[dot_index + 1 :]
result = _CONTEXT_WINDOW_LIMITS.get(stripped)
if result is not None:
logger.debug(
"model_id=<%s>, stripped_id=<%s> | resolved context window limit via prefix strip", model_id, stripped
)
return result
return None
def resolve_config_metadata(config: _C, model_id: str) -> _C:
"""Resolve model metadata fields on a config dict from built-in lookup tables.
When ``context_window_limit`` is not explicitly set, looks it up from the built-in table.
Explicit values pass through unchanged. Returns a new dict only when resolution adds a field;
otherwise returns the original config to avoid unnecessary allocation.
Args:
config: The stored model config dict.
model_id: The model ID to look up.
Returns:
The config with resolved metadata, or the original config if nothing to resolve.
"""
if "context_window_limit" in config:
return config
limit = get_context_window_limit(model_id)
if limit is None:
return config
return {**config, "context_window_limit": limit} # type: ignore[return-value]