haru-cli 0.1.1__tar.gz → 0.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {haru_cli-0.1.1 → haru_cli-0.1.2}/CHANGELOG.md +15 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/PKG-INFO +35 -4
- {haru_cli-0.1.1 → haru_cli-0.1.2}/README.md +34 -3
- {haru_cli-0.1.1 → haru_cli-0.1.2}/config/agents.yaml +7 -0
- haru_cli-0.1.2/config/models.yaml +31 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/docs/configuration.md +12 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/pyproject.toml +1 -1
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/agents/factory.py +20 -8
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/commands/chat.py +119 -11
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/commands/config.py +15 -2
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/commands/run.py +32 -5
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/config/schema.py +20 -1
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/config/templates/agents.yaml +7 -0
- haru_cli-0.1.2/src/haru/config/templates/models.yaml +31 -0
- haru_cli-0.1.2/src/haru/models/bedrock.py +146 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/tests/unit/test_agent_factory.py +19 -1
- {haru_cli-0.1.1 → haru_cli-0.1.2}/tests/unit/test_bedrock.py +74 -3
- {haru_cli-0.1.1 → haru_cli-0.1.2}/tests/unit/test_cli.py +68 -1
- {haru_cli-0.1.1 → haru_cli-0.1.2}/uv.lock +1 -1
- haru_cli-0.1.1/config/models.yaml +0 -20
- haru_cli-0.1.1/src/haru/config/templates/models.yaml +0 -20
- haru_cli-0.1.1/src/haru/models/bedrock.py +0 -77
- {haru_cli-0.1.1 → haru_cli-0.1.2}/.github/workflows/ci.yml +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/.github/workflows/release.yml +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/.gitignore +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/.kiro/steering/coding-standards.md +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/.kiro/steering/git-workflow.md +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/.kiro/steering/product.md +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/.kiro/steering/security.md +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/.kiro/steering/structure.md +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/.kiro/steering/tech.md +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/.kiro/steering/testing.md +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/.pre-commit-config.yaml +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/.python-version +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/CLAUDE.md +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/LICENSE +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/config/guardrails.yaml +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/config/haru.yaml +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/config/logging.yaml +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/config/mcp.yaml +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/config/prompts/researcher.md +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/config/prompts/supervisor.md +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/config/prompts/writer.md +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/renovate.json +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/__init__.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/__main__.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/agents/__init__.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/agents/orchestration.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/auth/__init__.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/auth/cache.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/auth/pkce.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/auth/session.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/auth/sso.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/cli.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/commands/__init__.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/commands/agents.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/commands/login.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/commands/session.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/commands/streaming.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/config/__init__.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/config/loader.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/config/templates/__init__.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/config/templates/haru.yaml +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/config/templates/logging.yaml +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/config/templates/mcp.yaml +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/config/templates/prompts/researcher.md +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/config/templates/prompts/supervisor.md +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/config/templates/prompts/writer.md +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/errors.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/models/__init__.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/observability/__init__.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/observability/guardrails.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/observability/telemetry.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/sessions/__init__.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/sessions/manager.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/steering/__init__.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/steering/prompts.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/tools/__init__.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/tools/mcp.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/src/haru/tools/registry.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/tests/conftest.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/tests/integration/test_packaging.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/tests/unit/test_cache.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/tests/unit/test_config_command.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/tests/unit/test_config_loader.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/tests/unit/test_guardrails.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/tests/unit/test_main.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/tests/unit/test_mcp.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/tests/unit/test_orchestration.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/tests/unit/test_pkce.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/tests/unit/test_prompts.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/tests/unit/test_session.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/tests/unit/test_sessions.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/tests/unit/test_sso.py +0 -0
- {haru_cli-0.1.1 → haru_cli-0.1.2}/tests/unit/test_telemetry.py +0 -0
|
@@ -9,6 +9,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
### Added
|
|
11
11
|
|
|
12
|
+
- Sampling controls (`temperature`, `top_p`, `top_k`, `seed`) across three
|
|
13
|
+
surfaces: model entries, per-agent `sampling:` blocks, and CLI/REPL
|
|
14
|
+
overrides (`--temperature/--top-p/--top-k/--seed`, `/sampling`).
|
|
15
|
+
Precedence CLI/REPL → agent → model, merged per-field; unset fields are
|
|
16
|
+
omitted from requests. `top_k`/`seed` travel via Converse
|
|
17
|
+
`additionalModelRequestFields`.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- `temperature` is no longer required (or sent by default) on model entries —
|
|
22
|
+
Claude 5-series and Opus 4.7+ reject non-default sampling values with an
|
|
23
|
+
HTTP 400, which the previous always-sent temperature would have triggered.
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
12
27
|
- `haru config init`: interactive starter configuration under
|
|
13
28
|
`~/.config/haru` (SSO settings prompted; guardrails explicitly disabled
|
|
14
29
|
when no id is provided). `haru config show` prints a secret-free summary.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: haru-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Secure, scriptable CLI for Amazon Bedrock Claude models via the AWS Strands Agents SDK.
|
|
5
5
|
Author: haru-cli maintainers
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -96,12 +96,43 @@ caching tokens in the botocore-compatible schema under `~/.aws/sso/cache`
|
|
|
96
96
|
tokens are refreshed automatically; when a fresh login is needed, commands say
|
|
97
97
|
so plainly.
|
|
98
98
|
|
|
99
|
+
## Sampling controls
|
|
100
|
+
|
|
101
|
+
haru-cli exposes `temperature`, `top_p`, `top_k`, and `seed` on **three
|
|
102
|
+
configuration surfaces** — a capability Kiro CLI does not offer on any of its
|
|
103
|
+
configuration surfaces (its v2/v3 agent formats and `cli.json` define no
|
|
104
|
+
sampling fields):
|
|
105
|
+
|
|
106
|
+
| Surface | Where | Example |
|
|
107
|
+
| ------------------------ | ---------------------------------------------- | ----------------------------------------- |
|
|
108
|
+
| Model catalogue | `models.yaml`, per model entry | `temperature: 0.2`, `top_k: 50` |
|
|
109
|
+
| Agent profile | `agents.yaml`, per agent `sampling:` block | `sampling: {temperature: 0.1}` |
|
|
110
|
+
| CLI / REPL | `--temperature/--top-p/--top-k/--seed` flags on `run` and `chat`; `/sampling` in the REPL | `haru run "..." --top-k 20` |
|
|
111
|
+
|
|
112
|
+
Precedence: **CLI/REPL override → agent `sampling:` block → model entry**,
|
|
113
|
+
merged per-field. Unset fields are omitted from requests entirely, keeping
|
|
114
|
+
the provider's defaults. In the chat REPL, `/sampling` shows the model
|
|
115
|
+
default, session override, and effective value for each field;
|
|
116
|
+
`/sampling temperature=0.2 top_k=50` applies overrides and `/sampling reset`
|
|
117
|
+
clears them.
|
|
118
|
+
|
|
119
|
+
Model compatibility (AWS-side behaviour, not a haru limitation):
|
|
120
|
+
|
|
121
|
+
- **Claude 5-series and Opus 4.7+** (Sonnet 5, Opus 5, Opus 4.8) reject
|
|
122
|
+
non-default `temperature`/`top_p`/`top_k` with an HTTP 400 — leave them
|
|
123
|
+
unset on those entries (the shipped config does).
|
|
124
|
+
- **Claude Haiku 4.5, Sonnet 4.5, and older Claude models**, plus
|
|
125
|
+
non-Anthropic Bedrock models, accept them.
|
|
126
|
+
- `seed` is forwarded via Converse `additionalModelRequestFields` for Bedrock
|
|
127
|
+
models that support it; **no Claude model accepts a seed today**, so do not
|
|
128
|
+
expect determinism from Claude — the field exists for models that honour it.
|
|
129
|
+
|
|
99
130
|
## Configuration
|
|
100
131
|
|
|
101
132
|
Declarative YAML under `config/` — models, agents, orchestration
|
|
102
|
-
(supervisor/swarm/graph), MCP servers, guardrails, sessions,
|
|
103
|
-
OpenTelemetry. No secrets in YAML: values reference environment
|
|
104
|
-
`${env:VAR}`. See [docs/configuration.md](docs/configuration.md).
|
|
133
|
+
(supervisor/swarm/graph), MCP servers, guardrails, sessions, sampling,
|
|
134
|
+
logging, and OpenTelemetry. No secrets in YAML: values reference environment
|
|
135
|
+
variables with `${env:VAR}`. See [docs/configuration.md](docs/configuration.md).
|
|
105
136
|
|
|
106
137
|
## Development
|
|
107
138
|
|
|
@@ -68,12 +68,43 @@ caching tokens in the botocore-compatible schema under `~/.aws/sso/cache`
|
|
|
68
68
|
tokens are refreshed automatically; when a fresh login is needed, commands say
|
|
69
69
|
so plainly.
|
|
70
70
|
|
|
71
|
+
## Sampling controls
|
|
72
|
+
|
|
73
|
+
haru-cli exposes `temperature`, `top_p`, `top_k`, and `seed` on **three
|
|
74
|
+
configuration surfaces** — a capability Kiro CLI does not offer on any of its
|
|
75
|
+
configuration surfaces (its v2/v3 agent formats and `cli.json` define no
|
|
76
|
+
sampling fields):
|
|
77
|
+
|
|
78
|
+
| Surface | Where | Example |
|
|
79
|
+
| ------------------------ | ---------------------------------------------- | ----------------------------------------- |
|
|
80
|
+
| Model catalogue | `models.yaml`, per model entry | `temperature: 0.2`, `top_k: 50` |
|
|
81
|
+
| Agent profile | `agents.yaml`, per agent `sampling:` block | `sampling: {temperature: 0.1}` |
|
|
82
|
+
| CLI / REPL | `--temperature/--top-p/--top-k/--seed` flags on `run` and `chat`; `/sampling` in the REPL | `haru run "..." --top-k 20` |
|
|
83
|
+
|
|
84
|
+
Precedence: **CLI/REPL override → agent `sampling:` block → model entry**,
|
|
85
|
+
merged per-field. Unset fields are omitted from requests entirely, keeping
|
|
86
|
+
the provider's defaults. In the chat REPL, `/sampling` shows the model
|
|
87
|
+
default, session override, and effective value for each field;
|
|
88
|
+
`/sampling temperature=0.2 top_k=50` applies overrides and `/sampling reset`
|
|
89
|
+
clears them.
|
|
90
|
+
|
|
91
|
+
Model compatibility (AWS-side behaviour, not a haru limitation):
|
|
92
|
+
|
|
93
|
+
- **Claude 5-series and Opus 4.7+** (Sonnet 5, Opus 5, Opus 4.8) reject
|
|
94
|
+
non-default `temperature`/`top_p`/`top_k` with an HTTP 400 — leave them
|
|
95
|
+
unset on those entries (the shipped config does).
|
|
96
|
+
- **Claude Haiku 4.5, Sonnet 4.5, and older Claude models**, plus
|
|
97
|
+
non-Anthropic Bedrock models, accept them.
|
|
98
|
+
- `seed` is forwarded via Converse `additionalModelRequestFields` for Bedrock
|
|
99
|
+
models that support it; **no Claude model accepts a seed today**, so do not
|
|
100
|
+
expect determinism from Claude — the field exists for models that honour it.
|
|
101
|
+
|
|
71
102
|
## Configuration
|
|
72
103
|
|
|
73
104
|
Declarative YAML under `config/` — models, agents, orchestration
|
|
74
|
-
(supervisor/swarm/graph), MCP servers, guardrails, sessions,
|
|
75
|
-
OpenTelemetry. No secrets in YAML: values reference environment
|
|
76
|
-
`${env:VAR}`. See [docs/configuration.md](docs/configuration.md).
|
|
105
|
+
(supervisor/swarm/graph), MCP servers, guardrails, sessions, sampling,
|
|
106
|
+
logging, and OpenTelemetry. No secrets in YAML: values reference environment
|
|
107
|
+
variables with `${env:VAR}`. See [docs/configuration.md](docs/configuration.md).
|
|
77
108
|
|
|
78
109
|
## Development
|
|
79
110
|
|
|
@@ -28,3 +28,10 @@ orchestration:
|
|
|
28
28
|
edges:
|
|
29
29
|
- from: research
|
|
30
30
|
to: write
|
|
31
|
+
# Per-agent sampling overrides beat the model entry's values and are in turn
|
|
32
|
+
# beaten by CLI/REPL overrides. Example:
|
|
33
|
+
# researcher:
|
|
34
|
+
# model: haiku-4-5
|
|
35
|
+
# sampling:
|
|
36
|
+
# temperature: 0.1
|
|
37
|
+
# top_k: 20
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Sampling fields (temperature, top_p, top_k, seed) are optional; unset
|
|
2
|
+
# fields are omitted from requests, keeping the provider's defaults.
|
|
3
|
+
# Claude 5-series and Opus 4.7+ models reject non-default temperature/top_p/
|
|
4
|
+
# top_k with an HTTP 400, so leave them unset on those entries. seed is
|
|
5
|
+
# passed through to models that support it (no Claude model does today).
|
|
6
|
+
default_model: sonnet-5
|
|
7
|
+
models:
|
|
8
|
+
opus-5:
|
|
9
|
+
model_id: us.anthropic.claude-opus-5
|
|
10
|
+
region: us-east-1
|
|
11
|
+
max_tokens: 8192
|
|
12
|
+
streaming: true
|
|
13
|
+
sonnet-5:
|
|
14
|
+
model_id: us.anthropic.claude-sonnet-5
|
|
15
|
+
region: us-east-1
|
|
16
|
+
max_tokens: 8192
|
|
17
|
+
streaming: true
|
|
18
|
+
opus-4-8:
|
|
19
|
+
model_id: us.anthropic.claude-opus-4-8
|
|
20
|
+
region: us-east-1
|
|
21
|
+
max_tokens: 8192
|
|
22
|
+
streaming: true
|
|
23
|
+
# Haiku 4.5 accepts sampling parameters:
|
|
24
|
+
haiku-4-5:
|
|
25
|
+
model_id: us.anthropic.claude-haiku-4-5
|
|
26
|
+
region: us-east-1
|
|
27
|
+
max_tokens: 4096
|
|
28
|
+
temperature: 0.2
|
|
29
|
+
top_p: 0.9
|
|
30
|
+
top_k: 50
|
|
31
|
+
streaming: true
|
|
@@ -38,6 +38,18 @@ Bare Bedrock model ids receive the `us.` geographic inference-profile prefix
|
|
|
38
38
|
by default. Explicit prefixes (`eu.`, `au.`, `global.`, ...) and full ARNs
|
|
39
39
|
pass through as configured — writing one into YAML is the approval surface.
|
|
40
40
|
|
|
41
|
+
## Sampling
|
|
42
|
+
|
|
43
|
+
`temperature`, `top_p`, `top_k`, and `seed` are optional on every model entry
|
|
44
|
+
and may also be set per agent (a `sampling:` block) or per invocation
|
|
45
|
+
(`--temperature/--top-p/--top-k/--seed`, or `/sampling` inside `haru chat`).
|
|
46
|
+
Precedence is CLI/REPL → agent → model, merged per-field; unset fields are
|
|
47
|
+
omitted from requests. `temperature`/`top_p` map to the Converse inference
|
|
48
|
+
configuration; `top_k` and `seed` travel via
|
|
49
|
+
`additionalModelRequestFields`. Claude 5-series and Opus 4.7+ models reject
|
|
50
|
+
non-default sampling values (HTTP 400), and no Claude model honours `seed` —
|
|
51
|
+
use these fields with models that accept them (for example Haiku 4.5).
|
|
52
|
+
|
|
41
53
|
## Sessions
|
|
42
54
|
|
|
43
55
|
Conversation persistence is configured in the base file:
|
|
@@ -15,9 +15,9 @@ from strands.models import BedrockModel
|
|
|
15
15
|
from strands.session.session_manager import SessionManager
|
|
16
16
|
from strands.tools.mcp import MCPClient
|
|
17
17
|
|
|
18
|
-
from haru.config.schema import HaruConfig
|
|
18
|
+
from haru.config.schema import HaruConfig, SamplingConfig
|
|
19
19
|
from haru.errors import ConfigError
|
|
20
|
-
from haru.models.bedrock import build_model, get_model_config
|
|
20
|
+
from haru.models.bedrock import build_model, get_model_config, merge_sampling
|
|
21
21
|
from haru.steering.prompts import DEFAULT_PROMPTS_ROOT, load_prompts, resolve_prompt
|
|
22
22
|
from haru.tools.mcp import collect_tools
|
|
23
23
|
|
|
@@ -31,16 +31,19 @@ def build_agent( # noqa: PLR0913 - keyword-only wiring points, all optional
|
|
|
31
31
|
mcp_clients: Mapping[str, MCPClient] | None = None,
|
|
32
32
|
session_manager: SessionManager | None = None,
|
|
33
33
|
model_name: str | None = None,
|
|
34
|
+
sampling: SamplingConfig | None = None,
|
|
34
35
|
) -> Agent:
|
|
35
36
|
"""Build the named agent from configuration (default model when unnamed).
|
|
36
37
|
|
|
37
38
|
``model_name`` overrides the model for the default (unnamed) agent only;
|
|
38
|
-
named agents pin their own model.
|
|
39
|
-
|
|
39
|
+
named agents pin their own model. ``sampling`` overrides sampling fields
|
|
40
|
+
(precedence: this override, then the agent's ``sampling`` block, then the
|
|
41
|
+
model entry). Raises ConfigError for unknown agents, prompt references,
|
|
42
|
+
tools, or an invalid override.
|
|
40
43
|
"""
|
|
41
44
|
if agent_name is None:
|
|
42
45
|
model_cfg = get_model_config(config, model_name)
|
|
43
|
-
model = build_model(model_cfg, session, guardrails=config.guardrails)
|
|
46
|
+
model = build_model(model_cfg, session, guardrails=config.guardrails, sampling=sampling)
|
|
44
47
|
return Agent(model=model, session_manager=session_manager)
|
|
45
48
|
if model_name is not None:
|
|
46
49
|
raise ConfigError(
|
|
@@ -48,7 +51,12 @@ def build_agent( # noqa: PLR0913 - keyword-only wiring points, all optional
|
|
|
48
51
|
" to the default agent only"
|
|
49
52
|
)
|
|
50
53
|
model, system_prompt, tools = resolve_agent_parts(
|
|
51
|
-
config,
|
|
54
|
+
config,
|
|
55
|
+
agent_name,
|
|
56
|
+
session,
|
|
57
|
+
prompts_root=prompts_root,
|
|
58
|
+
mcp_clients=mcp_clients,
|
|
59
|
+
sampling=sampling,
|
|
52
60
|
)
|
|
53
61
|
return Agent(
|
|
54
62
|
model=model,
|
|
@@ -59,13 +67,14 @@ def build_agent( # noqa: PLR0913 - keyword-only wiring points, all optional
|
|
|
59
67
|
)
|
|
60
68
|
|
|
61
69
|
|
|
62
|
-
def resolve_agent_parts(
|
|
70
|
+
def resolve_agent_parts( # noqa: PLR0913 - keyword-only wiring points, all optional
|
|
63
71
|
config: HaruConfig,
|
|
64
72
|
agent_name: str,
|
|
65
73
|
session: boto3.Session,
|
|
66
74
|
*,
|
|
67
75
|
prompts_root: Path | None = None,
|
|
68
76
|
mcp_clients: Mapping[str, MCPClient] | None = None,
|
|
77
|
+
sampling: SamplingConfig | None = None,
|
|
69
78
|
) -> tuple[BedrockModel, str | None, list[Any]]:
|
|
70
79
|
"""Resolve an agent's model, steering prompt, and tool list from config."""
|
|
71
80
|
if config.agents is None or agent_name not in config.agents.agents:
|
|
@@ -73,7 +82,10 @@ def resolve_agent_parts(
|
|
|
73
82
|
raise ConfigError(f"Unknown agent {agent_name!r}; configured agents: {available}")
|
|
74
83
|
agent_cfg = config.agents.agents[agent_name]
|
|
75
84
|
model = build_model(
|
|
76
|
-
get_model_config(config, agent_cfg.model),
|
|
85
|
+
get_model_config(config, agent_cfg.model),
|
|
86
|
+
session,
|
|
87
|
+
guardrails=config.guardrails,
|
|
88
|
+
sampling=merge_sampling(agent_cfg.sampling, sampling),
|
|
77
89
|
)
|
|
78
90
|
|
|
79
91
|
system_prompt: str | None = None
|
|
@@ -7,31 +7,37 @@ models and agents mid-session.
|
|
|
7
7
|
|
|
8
8
|
from collections.abc import Callable
|
|
9
9
|
from pathlib import Path
|
|
10
|
-
from typing import Any
|
|
10
|
+
from typing import Any, cast
|
|
11
11
|
|
|
12
12
|
import click
|
|
13
|
+
from pydantic import ValidationError
|
|
13
14
|
from rich.console import Console
|
|
14
15
|
|
|
15
16
|
from haru.agents.factory import build_agent
|
|
16
17
|
from haru.auth.session import build_boto3_session
|
|
17
18
|
from haru.commands.streaming import collect_response, surface_guardrail
|
|
18
19
|
from haru.config import load_config, resolve_config_path
|
|
19
|
-
from haru.config.schema import HaruConfig
|
|
20
|
-
from haru.errors import HaruError
|
|
20
|
+
from haru.config.schema import HaruConfig, SamplingConfig
|
|
21
|
+
from haru.errors import ConfigError, HaruError
|
|
22
|
+
from haru.models.bedrock import effective_sampling, get_model_config, sampling_overrides
|
|
21
23
|
from haru.observability.telemetry import configure_telemetry
|
|
22
24
|
from haru.sessions.manager import build_session_manager
|
|
23
25
|
from haru.tools.mcp import started_mcp_clients
|
|
24
26
|
|
|
25
27
|
_EXIT_WORDS = frozenset({"exit", "quit"})
|
|
28
|
+
_SAMPLING_FIELDS = ("temperature", "top_p", "top_k", "seed")
|
|
26
29
|
|
|
27
30
|
_HELP_TEXT = """\
|
|
28
31
|
Commands:
|
|
29
|
-
/help
|
|
30
|
-
/model
|
|
31
|
-
/model <name>
|
|
32
|
-
/agent
|
|
33
|
-
/agent <name>
|
|
34
|
-
|
|
32
|
+
/help Show this help
|
|
33
|
+
/model List configured models
|
|
34
|
+
/model <name> Switch the default agent to <name> (resets the conversation)
|
|
35
|
+
/agent List configured agents
|
|
36
|
+
/agent <name> Switch to agent <name> (resets the conversation)
|
|
37
|
+
/sampling Show effective sampling for the active target
|
|
38
|
+
/sampling k=v [k=v ...] Override temperature/top_p/top_k/seed (resets the conversation)
|
|
39
|
+
/sampling reset Clear sampling overrides (resets the conversation)
|
|
40
|
+
exit | quit Leave the chat (also /exit, /quit, Ctrl-D)"""
|
|
35
41
|
|
|
36
42
|
|
|
37
43
|
def run_chat( # noqa: PLR0913 - keyword-only wiring points, all optional
|
|
@@ -42,6 +48,7 @@ def run_chat( # noqa: PLR0913 - keyword-only wiring points, all optional
|
|
|
42
48
|
read_input: Callable[[str], str] = input,
|
|
43
49
|
prompts_root: Path | None = None,
|
|
44
50
|
session_id: str | None = None,
|
|
51
|
+
sampling: SamplingConfig | None = None,
|
|
45
52
|
) -> None:
|
|
46
53
|
"""Run the interactive chat loop until the user exits."""
|
|
47
54
|
session = build_boto3_session(config.auth)
|
|
@@ -51,7 +58,11 @@ def run_chat( # noqa: PLR0913 - keyword-only wiring points, all optional
|
|
|
51
58
|
else None
|
|
52
59
|
)
|
|
53
60
|
with started_mcp_clients(config.mcp) as mcp_clients:
|
|
54
|
-
state: dict[str, Any] = {
|
|
61
|
+
state: dict[str, Any] = {
|
|
62
|
+
"agent_name": agent_name,
|
|
63
|
+
"model_name": None,
|
|
64
|
+
"sampling": sampling,
|
|
65
|
+
}
|
|
55
66
|
|
|
56
67
|
def make_agent(name: str | None, model: str | None) -> Any:
|
|
57
68
|
return build_agent(
|
|
@@ -62,6 +73,7 @@ def run_chat( # noqa: PLR0913 - keyword-only wiring points, all optional
|
|
|
62
73
|
mcp_clients=mcp_clients,
|
|
63
74
|
session_manager=session_manager,
|
|
64
75
|
model_name=model,
|
|
76
|
+
sampling=state["sampling"],
|
|
65
77
|
)
|
|
66
78
|
|
|
67
79
|
state["agent"] = make_agent(agent_name, None)
|
|
@@ -121,11 +133,92 @@ def _handle_slash(
|
|
|
121
133
|
_print_agents(config, console, state)
|
|
122
134
|
else:
|
|
123
135
|
_switch(state, console, make_agent, agent_name=argument, model_name=None)
|
|
136
|
+
elif name == "sampling":
|
|
137
|
+
if argument is None:
|
|
138
|
+
_print_sampling(config, console, state)
|
|
139
|
+
else:
|
|
140
|
+
_apply_sampling(argument, config, console, state, make_agent)
|
|
124
141
|
else:
|
|
125
142
|
console.print(f"Unknown command /{command}; type /help for commands.")
|
|
126
143
|
return True
|
|
127
144
|
|
|
128
145
|
|
|
146
|
+
def _parse_sampling(argument: str) -> SamplingConfig:
|
|
147
|
+
"""Parse ``key=value`` sampling tokens into a SamplingConfig."""
|
|
148
|
+
values: dict[str, str] = {}
|
|
149
|
+
for token in argument.split():
|
|
150
|
+
key, separator, raw_value = token.partition("=")
|
|
151
|
+
if not separator or key not in _SAMPLING_FIELDS or not raw_value:
|
|
152
|
+
fields = ", ".join(_SAMPLING_FIELDS)
|
|
153
|
+
raise ConfigError(f"Bad sampling token {token!r}; use key=value with keys: {fields}")
|
|
154
|
+
values[key] = raw_value
|
|
155
|
+
try:
|
|
156
|
+
return SamplingConfig.model_validate(values)
|
|
157
|
+
except ValidationError as exc:
|
|
158
|
+
raise ConfigError(f"Invalid sampling values: {exc}") from exc
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _apply_sampling(
|
|
162
|
+
argument: str,
|
|
163
|
+
config: HaruConfig,
|
|
164
|
+
console: Console,
|
|
165
|
+
state: dict[str, Any],
|
|
166
|
+
make_agent: Callable[[str | None, str | None], Any],
|
|
167
|
+
) -> None:
|
|
168
|
+
"""Apply or clear sampling overrides, keeping the old state on failure."""
|
|
169
|
+
if argument.lower() == "reset":
|
|
170
|
+
override: SamplingConfig | None = None
|
|
171
|
+
else:
|
|
172
|
+
try:
|
|
173
|
+
override = _parse_sampling(argument)
|
|
174
|
+
except ConfigError as exc:
|
|
175
|
+
console.print(f"[red]{exc}[/]")
|
|
176
|
+
return
|
|
177
|
+
previous = state["sampling"]
|
|
178
|
+
state["sampling"] = override
|
|
179
|
+
try:
|
|
180
|
+
agent = make_agent(state["agent_name"], state["model_name"])
|
|
181
|
+
except HaruError as exc:
|
|
182
|
+
state["sampling"] = previous
|
|
183
|
+
console.print(f"[red]{exc}[/]")
|
|
184
|
+
return
|
|
185
|
+
state["agent"] = agent
|
|
186
|
+
if override is None:
|
|
187
|
+
console.print("Sampling overrides cleared (conversation reset).")
|
|
188
|
+
else:
|
|
189
|
+
console.print("Sampling overrides applied (conversation reset).")
|
|
190
|
+
_print_sampling(config, console, state)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def _print_sampling(config: HaruConfig, console: Console, state: dict[str, Any]) -> None:
|
|
194
|
+
"""Show model defaults, session overrides, and effective sampling values."""
|
|
195
|
+
agent_name = state["agent_name"]
|
|
196
|
+
model_key = state["model_name"]
|
|
197
|
+
if agent_name is not None and config.agents is not None:
|
|
198
|
+
agent_cfg = config.agents.agents.get(agent_name)
|
|
199
|
+
model_key = agent_cfg.model if agent_cfg is not None else model_key
|
|
200
|
+
try:
|
|
201
|
+
model_cfg = get_model_config(config, model_key)
|
|
202
|
+
except HaruError as exc:
|
|
203
|
+
console.print(f"[red]{exc}[/]")
|
|
204
|
+
return
|
|
205
|
+
override = cast(SamplingConfig | None, state["sampling"])
|
|
206
|
+
effective = effective_sampling(model_cfg, override)
|
|
207
|
+
console.print(f"Sampling for model {model_cfg.model_id!r} (unset = provider default):")
|
|
208
|
+
for field in _SAMPLING_FIELDS:
|
|
209
|
+
model_value = getattr(model_cfg, field)
|
|
210
|
+
override_value = getattr(override, field) if override is not None else None
|
|
211
|
+
effective_value = getattr(effective, field)
|
|
212
|
+
console.print(
|
|
213
|
+
f" {field:<12} model={_fmt(model_value):<8}"
|
|
214
|
+
f" override={_fmt(override_value):<8} effective={_fmt(effective_value)}"
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _fmt(value: Any) -> str:
|
|
219
|
+
return "-" if value is None else str(value)
|
|
220
|
+
|
|
221
|
+
|
|
129
222
|
def _switch(
|
|
130
223
|
state: dict[str, Any],
|
|
131
224
|
console: Console,
|
|
@@ -190,7 +283,19 @@ def _print_agents(config: HaruConfig, console: Console, state: dict[str, Any]) -
|
|
|
190
283
|
default=None,
|
|
191
284
|
help="Persist and restore this conversation under the given session id.",
|
|
192
285
|
)
|
|
193
|
-
|
|
286
|
+
@click.option("--temperature", type=float, default=None, help="Sampling temperature (0-1).")
|
|
287
|
+
@click.option("--top-p", "top_p", type=float, default=None, help="Nucleus sampling (0-1).")
|
|
288
|
+
@click.option("--top-k", "top_k", type=int, default=None, help="Top-k sampling (>=1).")
|
|
289
|
+
@click.option("--seed", type=int, default=None, help="Seed (models that support it only).")
|
|
290
|
+
def chat( # noqa: PLR0913, PLR0917 - one option per flag; Click passes positionally
|
|
291
|
+
config_path: Path | None,
|
|
292
|
+
agent_name: str | None,
|
|
293
|
+
session_id: str | None,
|
|
294
|
+
temperature: float | None,
|
|
295
|
+
top_p: float | None,
|
|
296
|
+
top_k: int | None,
|
|
297
|
+
seed: int | None,
|
|
298
|
+
) -> None:
|
|
194
299
|
"""Chat interactively with a Bedrock agent (streaming)."""
|
|
195
300
|
console = Console()
|
|
196
301
|
try:
|
|
@@ -203,6 +308,9 @@ def chat(config_path: Path | None, agent_name: str | None, session_id: str | Non
|
|
|
203
308
|
console=console,
|
|
204
309
|
prompts_root=resolved.parent / "prompts",
|
|
205
310
|
session_id=session_id,
|
|
311
|
+
sampling=sampling_overrides(
|
|
312
|
+
temperature=temperature, top_p=top_p, top_k=top_k, seed=seed
|
|
313
|
+
),
|
|
206
314
|
)
|
|
207
315
|
except HaruError as exc:
|
|
208
316
|
raise click.ClickException(str(exc)) from exc
|
|
@@ -6,8 +6,21 @@ from pathlib import Path
|
|
|
6
6
|
import click
|
|
7
7
|
|
|
8
8
|
from haru.config import load_config, resolve_config_path, user_config_path
|
|
9
|
+
from haru.config.schema import ModelConfig
|
|
9
10
|
from haru.errors import HaruError
|
|
10
11
|
|
|
12
|
+
|
|
13
|
+
def _sampling_summary(entry: ModelConfig) -> str:
|
|
14
|
+
"""Compact ``[temp=.. top_k=..]`` summary of a model's set sampling fields."""
|
|
15
|
+
labels = {"temperature": "temp", "top_p": "top_p", "top_k": "top_k", "seed": "seed"}
|
|
16
|
+
parts = [
|
|
17
|
+
f"{label}={value}"
|
|
18
|
+
for field, label in labels.items()
|
|
19
|
+
if (value := getattr(entry, field)) is not None
|
|
20
|
+
]
|
|
21
|
+
return f" [{' '.join(parts)}]" if parts else ""
|
|
22
|
+
|
|
23
|
+
|
|
11
24
|
_TEMPLATE_FILES = ("haru.yaml", "models.yaml", "agents.yaml", "mcp.yaml", "logging.yaml")
|
|
12
25
|
_PROMPT_FILES = ("supervisor.md", "researcher.md", "writer.md")
|
|
13
26
|
|
|
@@ -128,8 +141,8 @@ def show(config_path: Path | None) -> None:
|
|
|
128
141
|
if loaded.models is not None:
|
|
129
142
|
default = loaded.models.default_model
|
|
130
143
|
names = ", ".join(
|
|
131
|
-
f"{name}{' (default)' if name == default else ''}"
|
|
132
|
-
for name in sorted(loaded.models.models)
|
|
144
|
+
f"{name}{' (default)' if name == default else ''}{_sampling_summary(entry)}"
|
|
145
|
+
for name, entry in sorted(loaded.models.models.items())
|
|
133
146
|
)
|
|
134
147
|
click.echo(f"Models: {names}")
|
|
135
148
|
if loaded.agents is not None:
|
|
@@ -9,19 +9,21 @@ from haru.agents.factory import build_agent
|
|
|
9
9
|
from haru.auth.session import build_boto3_session
|
|
10
10
|
from haru.commands.streaming import collect_response, surface_guardrail
|
|
11
11
|
from haru.config import load_config, resolve_config_path
|
|
12
|
-
from haru.config.schema import HaruConfig
|
|
12
|
+
from haru.config.schema import HaruConfig, SamplingConfig
|
|
13
13
|
from haru.errors import HaruError
|
|
14
|
+
from haru.models.bedrock import sampling_overrides
|
|
14
15
|
from haru.observability.telemetry import configure_telemetry
|
|
15
16
|
from haru.tools.mcp import started_mcp_clients
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
def run_prompt(
|
|
19
|
+
def run_prompt( # noqa: PLR0913 - keyword-only wiring points, all optional
|
|
19
20
|
config: HaruConfig,
|
|
20
21
|
prompt: str,
|
|
21
22
|
agent_name: str | None = None,
|
|
22
23
|
*,
|
|
23
24
|
console: Console | None = None,
|
|
24
25
|
prompts_root: Path | None = None,
|
|
26
|
+
sampling: SamplingConfig | None = None,
|
|
25
27
|
) -> str:
|
|
26
28
|
"""Execute ``prompt`` once and return the full response text.
|
|
27
29
|
|
|
@@ -30,7 +32,12 @@ def run_prompt(
|
|
|
30
32
|
session = build_boto3_session(config.auth)
|
|
31
33
|
with started_mcp_clients(config.mcp) as mcp_clients:
|
|
32
34
|
agent = build_agent(
|
|
33
|
-
config,
|
|
35
|
+
config,
|
|
36
|
+
agent_name,
|
|
37
|
+
session,
|
|
38
|
+
prompts_root=prompts_root,
|
|
39
|
+
mcp_clients=mcp_clients,
|
|
40
|
+
sampling=sampling,
|
|
34
41
|
)
|
|
35
42
|
chunks: list[str] = []
|
|
36
43
|
result = collect_response(agent, prompt, chunks.append)
|
|
@@ -48,13 +55,33 @@ def run_prompt(
|
|
|
48
55
|
help="Path to haru.yaml (default: config/haru.yaml).",
|
|
49
56
|
)
|
|
50
57
|
@click.option("--agent", "agent_name", default=None, help="Agent name from configuration.")
|
|
51
|
-
|
|
58
|
+
@click.option("--temperature", type=float, default=None, help="Sampling temperature (0-1).")
|
|
59
|
+
@click.option("--top-p", "top_p", type=float, default=None, help="Nucleus sampling (0-1).")
|
|
60
|
+
@click.option("--top-k", "top_k", type=int, default=None, help="Top-k sampling (>=1).")
|
|
61
|
+
@click.option("--seed", type=int, default=None, help="Seed (models that support it only).")
|
|
62
|
+
def run( # noqa: PLR0913, PLR0917 - one option per flag; Click passes positionally
|
|
63
|
+
prompt: str,
|
|
64
|
+
config_path: Path | None,
|
|
65
|
+
agent_name: str | None,
|
|
66
|
+
temperature: float | None,
|
|
67
|
+
top_p: float | None,
|
|
68
|
+
top_k: int | None,
|
|
69
|
+
seed: int | None,
|
|
70
|
+
) -> None:
|
|
52
71
|
"""Run a single prompt and print the answer."""
|
|
53
72
|
try:
|
|
54
73
|
resolved = resolve_config_path(config_path)
|
|
55
74
|
config = load_config(resolved)
|
|
56
75
|
configure_telemetry(config.observability)
|
|
57
|
-
answer = run_prompt(
|
|
76
|
+
answer = run_prompt(
|
|
77
|
+
config,
|
|
78
|
+
prompt,
|
|
79
|
+
agent_name,
|
|
80
|
+
prompts_root=resolved.parent / "prompts",
|
|
81
|
+
sampling=sampling_overrides(
|
|
82
|
+
temperature=temperature, top_p=top_p, top_k=top_k, seed=seed
|
|
83
|
+
),
|
|
84
|
+
)
|
|
58
85
|
except HaruError as exc:
|
|
59
86
|
raise click.ClickException(str(exc)) from exc
|
|
60
87
|
click.echo(answer)
|
|
@@ -53,13 +53,31 @@ class IncludesConfig(_FrozenModel):
|
|
|
53
53
|
logging: str | None = None
|
|
54
54
|
|
|
55
55
|
|
|
56
|
+
class SamplingConfig(_FrozenModel):
|
|
57
|
+
"""Optional sampling parameters.
|
|
58
|
+
|
|
59
|
+
Unset fields are omitted from requests entirely, keeping the provider's
|
|
60
|
+
defaults — required by Claude 5-series models, which reject non-default
|
|
61
|
+
sampling values. ``seed`` is passed through for Bedrock models that
|
|
62
|
+
support it (no Claude model does today).
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
temperature: float | None = Field(default=None, ge=0.0, le=1.0)
|
|
66
|
+
top_p: float | None = Field(default=None, ge=0.0, le=1.0)
|
|
67
|
+
top_k: int | None = Field(default=None, ge=1)
|
|
68
|
+
seed: int | None = None
|
|
69
|
+
|
|
70
|
+
|
|
56
71
|
class ModelConfig(_FrozenModel):
|
|
57
72
|
"""A single Bedrock model entry."""
|
|
58
73
|
|
|
59
74
|
model_id: str
|
|
60
75
|
region: str
|
|
61
76
|
max_tokens: int = Field(ge=1)
|
|
62
|
-
temperature: float = Field(ge=0.0, le=1.0)
|
|
77
|
+
temperature: float | None = Field(default=None, ge=0.0, le=1.0)
|
|
78
|
+
top_p: float | None = Field(default=None, ge=0.0, le=1.0)
|
|
79
|
+
top_k: int | None = Field(default=None, ge=1)
|
|
80
|
+
seed: int | None = None
|
|
63
81
|
streaming: bool = True
|
|
64
82
|
|
|
65
83
|
|
|
@@ -83,6 +101,7 @@ class AgentConfig(_FrozenModel):
|
|
|
83
101
|
system_prompt_ref: str | None = None
|
|
84
102
|
tools: tuple[str, ...] = ()
|
|
85
103
|
mcp_servers: tuple[str, ...] = ()
|
|
104
|
+
sampling: SamplingConfig | None = None
|
|
86
105
|
|
|
87
106
|
|
|
88
107
|
class SwarmConfig(_FrozenModel):
|
|
@@ -28,3 +28,10 @@ orchestration:
|
|
|
28
28
|
edges:
|
|
29
29
|
- from: research
|
|
30
30
|
to: write
|
|
31
|
+
# Per-agent sampling overrides beat the model entry's values and are in turn
|
|
32
|
+
# beaten by CLI/REPL overrides. Example:
|
|
33
|
+
# researcher:
|
|
34
|
+
# model: haiku-4-5
|
|
35
|
+
# sampling:
|
|
36
|
+
# temperature: 0.1
|
|
37
|
+
# top_k: 20
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Sampling fields (temperature, top_p, top_k, seed) are optional; unset
|
|
2
|
+
# fields are omitted from requests, keeping the provider's defaults.
|
|
3
|
+
# Claude 5-series and Opus 4.7+ models reject non-default temperature/top_p/
|
|
4
|
+
# top_k with an HTTP 400, so leave them unset on those entries. seed is
|
|
5
|
+
# passed through to models that support it (no Claude model does today).
|
|
6
|
+
default_model: sonnet-5
|
|
7
|
+
models:
|
|
8
|
+
opus-5:
|
|
9
|
+
model_id: us.anthropic.claude-opus-5
|
|
10
|
+
region: us-east-1
|
|
11
|
+
max_tokens: 8192
|
|
12
|
+
streaming: true
|
|
13
|
+
sonnet-5:
|
|
14
|
+
model_id: us.anthropic.claude-sonnet-5
|
|
15
|
+
region: us-east-1
|
|
16
|
+
max_tokens: 8192
|
|
17
|
+
streaming: true
|
|
18
|
+
opus-4-8:
|
|
19
|
+
model_id: us.anthropic.claude-opus-4-8
|
|
20
|
+
region: us-east-1
|
|
21
|
+
max_tokens: 8192
|
|
22
|
+
streaming: true
|
|
23
|
+
# Haiku 4.5 accepts sampling parameters:
|
|
24
|
+
haiku-4-5:
|
|
25
|
+
model_id: us.anthropic.claude-haiku-4-5
|
|
26
|
+
region: us-east-1
|
|
27
|
+
max_tokens: 4096
|
|
28
|
+
temperature: 0.2
|
|
29
|
+
top_p: 0.9
|
|
30
|
+
top_k: 50
|
|
31
|
+
streaming: true
|