๐Ÿ“ฆ EqualifyEverything / equalify-reflow

๐Ÿ“„ model-tiers.md ยท 65 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65# Model tiers reference

Model selection across the pipeline happens through two tiers defined in `src/agents/model_tiers.py`. Each agent picks a tier; a backend-specific map resolves that tier to a concrete model ID at call time.

**Source of truth:** `src/agents/model_tiers.py`.

## Tiers

| Tier | Model family | Used for | Pricing (per 1M tokens, approx) |
|---|---|---|---|
| `ModelTier.EFFICIENT` | Claude Haiku 4.5 | Every current agent call site. Fast, cheap, validated against integration fixtures. | ~$1 input / ~$5 output |
| `ModelTier.REASONING` | Claude Sonnet 4.5 | Reserved for heavier analysis. Not wired into pipeline call sites today; available for new agents that measurably benefit. | ~$3 input / ~$15 output |

Default to `EFFICIENT`. Promote to `REASONING` only when integration fixtures show measurable quality improvement that the 3ร— cost justifies.

## Backend maps

Two dicts, one per supported backend. Both are pinned to the same model generation (`...-v1:0` for Bedrock, bare `claude-<tier>-4-5-<date>` for Anthropic direct) so output parity holds when switching backends.

### Bedrock inference profiles

```python
BEDROCK_TIER_MAP = {
    ModelTier.REASONING: "us.anthropic.claude-sonnet-4-5-20250929-v1:0",
    ModelTier.EFFICIENT: "us.anthropic.claude-haiku-4-5-20251001-v1:0",
}
```

The `us.` prefix is **required** for Claude 4.5 models on Bedrock โ€” these are inference profile IDs, not on-demand model IDs. On-demand will 404.

### Anthropic direct

```python
ANTHROPIC_TIER_MAP = {
    ModelTier.REASONING: "claude-sonnet-4-5-20250929",
    ModelTier.EFFICIENT: "claude-haiku-4-5-20251001",
}
```

## Resolving a model at call time

Agents should **not** reach into these dicts directly. Use `get_model_for_tier` from `src/agents/model_factory.py`:

```python
from src.agents.model_factory import get_model_for_tier
from src.agents.model_tiers import ModelTier

model = get_model_for_tier(ModelTier.EFFICIENT)
agent = Agent(model=model, output_type=MyOutputModel, ...)
```

The factory picks the backend based on `AI_PROVIDER` and available credentials (see [AI backend selection](../explanation/ai-backend-selection.md) when that doc lands; for now the logic is: `AI_PROVIDER=anthropic` forces direct, `AI_PROVIDER=bedrock` forces Bedrock, unset auto-detects by checking `ANTHROPIC_API_KEY`).

## Backwards-compatibility aliases

`model_tiers.py` still exports `MODEL_TIER_MAP` (alias for `BEDROCK_TIER_MAP`) and `get_model_id(tier)` (returns Bedrock ID). New code should not use these โ€” they're retained only for the handful of call sites that haven't been migrated to the factory.

## Updating the tiers

When a new Claude model generation ships and fixtures validate the upgrade:

1. Update both `BEDROCK_TIER_MAP` and `ANTHROPIC_TIER_MAP` together โ€” never one without the other, or output will drift between backends.
2. Run `make test-e2e` against the full fixture suite to catch regressions.
3. Note the generation change in the PR body so reviewers can sanity-check.