mirror of
https://github.com/home-assistant/core.git
synced 2026-03-01 14:25:31 +00:00
Update Anthropic models (#163897)
This commit is contained in:
@@ -112,19 +112,12 @@ async def get_model_list(client: anthropic.AsyncAnthropic) -> list[SelectOptionD
|
||||
# Resolve alias from versioned model name:
|
||||
model_alias = (
|
||||
model_info.id[:-9]
|
||||
if model_info.id
|
||||
not in (
|
||||
"claude-3-haiku-20240307",
|
||||
"claude-3-5-haiku-20241022",
|
||||
"claude-3-opus-20240229",
|
||||
)
|
||||
if model_info.id != "claude-3-haiku-20240307"
|
||||
and model_info.id[-2:-1] != "-"
|
||||
else model_info.id
|
||||
)
|
||||
if short_form.search(model_alias):
|
||||
model_alias += "-0"
|
||||
if model_alias.endswith(("haiku", "opus", "sonnet")):
|
||||
model_alias += "-latest"
|
||||
model_options.append(
|
||||
SelectOptionDict(
|
||||
label=model_info.display_name,
|
||||
|
||||
@@ -37,8 +37,6 @@ DEFAULT = {
|
||||
MIN_THINKING_BUDGET = 1024
|
||||
|
||||
NON_THINKING_MODELS = [
|
||||
"claude-3-5", # Both sonnet and haiku
|
||||
"claude-3-opus",
|
||||
"claude-3-haiku",
|
||||
]
|
||||
|
||||
@@ -51,7 +49,7 @@ NON_ADAPTIVE_THINKING_MODELS = [
|
||||
"claude-opus-4-20250514",
|
||||
"claude-sonnet-4-0",
|
||||
"claude-sonnet-4-20250514",
|
||||
"claude-3",
|
||||
"claude-3-haiku",
|
||||
]
|
||||
|
||||
UNSUPPORTED_STRUCTURED_OUTPUT_MODELS = [
|
||||
@@ -60,19 +58,13 @@ UNSUPPORTED_STRUCTURED_OUTPUT_MODELS = [
|
||||
"claude-opus-4-20250514",
|
||||
"claude-sonnet-4-0",
|
||||
"claude-sonnet-4-20250514",
|
||||
"claude-3",
|
||||
"claude-3-haiku",
|
||||
]
|
||||
|
||||
WEB_SEARCH_UNSUPPORTED_MODELS = [
|
||||
"claude-3-haiku",
|
||||
"claude-3-opus",
|
||||
"claude-3-5-sonnet-20240620",
|
||||
"claude-3-5-sonnet-20241022",
|
||||
]
|
||||
|
||||
DEPRECATED_MODELS = [
|
||||
"claude-3-5-haiku",
|
||||
"claude-3-7-sonnet",
|
||||
"claude-3-5-sonnet",
|
||||
"claude-3-opus",
|
||||
"claude-3",
|
||||
]
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Iterator
|
||||
from typing import TYPE_CHECKING, cast
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@@ -19,7 +19,7 @@ from homeassistant.helpers.selector import (
|
||||
)
|
||||
|
||||
from .config_flow import get_model_list
|
||||
from .const import CONF_CHAT_MODEL, DEFAULT, DEPRECATED_MODELS, DOMAIN
|
||||
from .const import CONF_CHAT_MODEL, DEPRECATED_MODELS, DOMAIN
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from . import AnthropicConfigEntry
|
||||
@@ -67,13 +67,23 @@ class ModelDeprecatedRepairFlow(RepairsFlow):
|
||||
self._model_list_cache[entry.entry_id] = model_list
|
||||
|
||||
if "opus" in model:
|
||||
suggested_model = "claude-opus-4-5"
|
||||
elif "haiku" in model:
|
||||
suggested_model = "claude-haiku-4-5"
|
||||
family = "claude-opus"
|
||||
elif "sonnet" in model:
|
||||
suggested_model = "claude-sonnet-4-5"
|
||||
family = "claude-sonnet"
|
||||
else:
|
||||
suggested_model = cast(str, DEFAULT[CONF_CHAT_MODEL])
|
||||
family = "claude-haiku"
|
||||
|
||||
suggested_model = next(
|
||||
(
|
||||
model_option["value"]
|
||||
for model_option in sorted(
|
||||
(m for m in model_list if family in m["value"]),
|
||||
key=lambda x: x["value"],
|
||||
reverse=True,
|
||||
)
|
||||
),
|
||||
vol.UNDEFINED,
|
||||
)
|
||||
|
||||
schema = vol.Schema(
|
||||
{
|
||||
|
||||
@@ -81,6 +81,12 @@ async def mock_init_component(
|
||||
"""Initialize integration."""
|
||||
model_list = AsyncPage(
|
||||
data=[
|
||||
ModelInfo(
|
||||
id="claude-sonnet-4-6",
|
||||
created_at=datetime.datetime(2026, 2, 17, 0, 0, tzinfo=datetime.UTC),
|
||||
display_name="Claude Sonnet 4.6",
|
||||
type="model",
|
||||
),
|
||||
ModelInfo(
|
||||
id="claude-opus-4-6",
|
||||
created_at=datetime.datetime(2026, 2, 4, 0, 0, tzinfo=datetime.UTC),
|
||||
@@ -123,30 +129,12 @@ async def mock_init_component(
|
||||
display_name="Claude Sonnet 4",
|
||||
type="model",
|
||||
),
|
||||
ModelInfo(
|
||||
id="claude-3-7-sonnet-20250219",
|
||||
created_at=datetime.datetime(2025, 2, 24, 0, 0, tzinfo=datetime.UTC),
|
||||
display_name="Claude Sonnet 3.7",
|
||||
type="model",
|
||||
),
|
||||
ModelInfo(
|
||||
id="claude-3-5-haiku-20241022",
|
||||
created_at=datetime.datetime(2024, 10, 22, 0, 0, tzinfo=datetime.UTC),
|
||||
display_name="Claude Haiku 3.5",
|
||||
type="model",
|
||||
),
|
||||
ModelInfo(
|
||||
id="claude-3-haiku-20240307",
|
||||
created_at=datetime.datetime(2024, 3, 7, 0, 0, tzinfo=datetime.UTC),
|
||||
display_name="Claude Haiku 3",
|
||||
type="model",
|
||||
),
|
||||
ModelInfo(
|
||||
id="claude-3-opus-20240229",
|
||||
created_at=datetime.datetime(2024, 2, 29, 0, 0, tzinfo=datetime.UTC),
|
||||
display_name="Claude Opus 3",
|
||||
type="model",
|
||||
),
|
||||
]
|
||||
)
|
||||
with patch(
|
||||
@@ -204,7 +192,7 @@ def mock_create_stream() -> Generator[AsyncMock]:
|
||||
id="msg_1234567890ABCDEFGHIJKLMN",
|
||||
content=[],
|
||||
role="assistant",
|
||||
model="claude-3-5-sonnet-20240620",
|
||||
model=kwargs["model"],
|
||||
usage=Usage(input_tokens=0, output_tokens=0),
|
||||
),
|
||||
type="message_start",
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
# serializer version: 1
|
||||
# name: test_model_list
|
||||
list([
|
||||
dict({
|
||||
'label': 'Claude Sonnet 4.6',
|
||||
'value': 'claude-sonnet-4-6',
|
||||
}),
|
||||
dict({
|
||||
'label': 'Claude Opus 4.6',
|
||||
'value': 'claude-opus-4-6',
|
||||
@@ -29,21 +33,9 @@
|
||||
'label': 'Claude Sonnet 4',
|
||||
'value': 'claude-sonnet-4-0',
|
||||
}),
|
||||
dict({
|
||||
'label': 'Claude Sonnet 3.7',
|
||||
'value': 'claude-3-7-sonnet-latest',
|
||||
}),
|
||||
dict({
|
||||
'label': 'Claude Haiku 3.5',
|
||||
'value': 'claude-3-5-haiku-20241022',
|
||||
}),
|
||||
dict({
|
||||
'label': 'Claude Haiku 3',
|
||||
'value': 'claude-3-haiku-20240307',
|
||||
}),
|
||||
dict({
|
||||
'label': 'Claude Opus 3',
|
||||
'value': 'claude-3-opus-20240229',
|
||||
}),
|
||||
])
|
||||
# ---
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
'role': 'assistant',
|
||||
}),
|
||||
]),
|
||||
'model': 'claude-3-7-sonnet-latest',
|
||||
'model': 'claude-sonnet-4-5',
|
||||
'stream': True,
|
||||
'system': list([
|
||||
dict({
|
||||
|
||||
@@ -427,7 +427,7 @@ async def test_model_list_error(
|
||||
CONF_PROMPT: "Speak like a pirate",
|
||||
},
|
||||
{
|
||||
CONF_CHAT_MODEL: "claude-3-opus",
|
||||
CONF_CHAT_MODEL: "claude-3-haiku-20240307",
|
||||
CONF_TEMPERATURE: 1.0,
|
||||
},
|
||||
),
|
||||
@@ -435,7 +435,7 @@ async def test_model_list_error(
|
||||
CONF_RECOMMENDED: False,
|
||||
CONF_PROMPT: "Speak like a pirate",
|
||||
CONF_TEMPERATURE: 1.0,
|
||||
CONF_CHAT_MODEL: "claude-3-opus",
|
||||
CONF_CHAT_MODEL: "claude-3-haiku-20240307",
|
||||
CONF_MAX_TOKENS: DEFAULT[CONF_MAX_TOKENS],
|
||||
},
|
||||
),
|
||||
@@ -459,7 +459,7 @@ async def test_model_list_error(
|
||||
CONF_LLM_HASS_API: [],
|
||||
},
|
||||
{
|
||||
CONF_CHAT_MODEL: "claude-3-5-haiku-20241022",
|
||||
CONF_CHAT_MODEL: "claude-haiku-4-5",
|
||||
CONF_TEMPERATURE: 1.0,
|
||||
},
|
||||
{
|
||||
@@ -472,8 +472,9 @@ async def test_model_list_error(
|
||||
CONF_RECOMMENDED: False,
|
||||
CONF_PROMPT: "Speak like a pirate",
|
||||
CONF_TEMPERATURE: 1.0,
|
||||
CONF_CHAT_MODEL: "claude-3-5-haiku-20241022",
|
||||
CONF_CHAT_MODEL: "claude-haiku-4-5",
|
||||
CONF_MAX_TOKENS: DEFAULT[CONF_MAX_TOKENS],
|
||||
CONF_THINKING_BUDGET: 0,
|
||||
CONF_WEB_SEARCH: False,
|
||||
CONF_WEB_SEARCH_MAX_USES: 10,
|
||||
CONF_WEB_SEARCH_USER_LOCATION: False,
|
||||
|
||||
@@ -539,7 +539,7 @@ async def test_extended_thinking(
|
||||
next(iter(mock_config_entry.subentries.values())),
|
||||
data={
|
||||
CONF_LLM_HASS_API: llm.LLM_API_ASSIST,
|
||||
CONF_CHAT_MODEL: "claude-3-7-sonnet-latest",
|
||||
CONF_CHAT_MODEL: "claude-sonnet-4-5",
|
||||
CONF_THINKING_BUDGET: 1500,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -103,7 +103,7 @@ async def test_downgrade_from_v3_to_v2(
|
||||
"recommended": True,
|
||||
"llm_hass_api": ["assist"],
|
||||
"prompt": "You are a helpful assistant",
|
||||
"chat_model": "claude-3-haiku-20240307",
|
||||
"chat_model": "claude-haiku-4-5",
|
||||
},
|
||||
"subentry_id": "mock_id",
|
||||
"subentry_type": "conversation",
|
||||
@@ -154,7 +154,7 @@ async def test_migration_from_v1_to_v2(
|
||||
"recommended": True,
|
||||
"llm_hass_api": ["assist"],
|
||||
"prompt": "You are a helpful assistant",
|
||||
"chat_model": "claude-3-haiku-20240307",
|
||||
"chat_model": "claude-haiku-4-5",
|
||||
}
|
||||
mock_config_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
@@ -315,7 +315,7 @@ async def test_migration_from_v1_disabled(
|
||||
"recommended": True,
|
||||
"llm_hass_api": ["assist"],
|
||||
"prompt": "You are a helpful assistant",
|
||||
"chat_model": "claude-3-haiku-20240307",
|
||||
"chat_model": "claude-haiku-4-5",
|
||||
}
|
||||
mock_config_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
@@ -444,7 +444,7 @@ async def test_migration_from_v1_to_v2_with_multiple_keys(
|
||||
"recommended": True,
|
||||
"llm_hass_api": ["assist"],
|
||||
"prompt": "You are a helpful assistant",
|
||||
"chat_model": "claude-3-haiku-20240307",
|
||||
"chat_model": "claude-haiku-4-5",
|
||||
}
|
||||
mock_config_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
@@ -534,7 +534,7 @@ async def test_migration_from_v1_to_v2_with_same_keys(
|
||||
"recommended": True,
|
||||
"llm_hass_api": ["assist"],
|
||||
"prompt": "You are a helpful assistant",
|
||||
"chat_model": "claude-3-haiku-20240307",
|
||||
"chat_model": "claude-haiku-4-5",
|
||||
}
|
||||
mock_config_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
@@ -639,7 +639,7 @@ async def test_migration_from_v2_1_to_v2_2(
|
||||
"recommended": True,
|
||||
"llm_hass_api": ["assist"],
|
||||
"prompt": "You are a helpful assistant",
|
||||
"chat_model": "claude-3-haiku-20240307",
|
||||
"chat_model": "claude-haiku-4-5",
|
||||
}
|
||||
mock_config_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
@@ -901,7 +901,7 @@ async def test_migrate_entry_to_v2_3(
|
||||
"recommended": True,
|
||||
"llm_hass_api": ["assist"],
|
||||
"prompt": "You are a helpful assistant",
|
||||
"chat_model": "claude-3-haiku-20240307",
|
||||
"chat_model": "claude-haiku-4-5",
|
||||
},
|
||||
"subentry_id": conversation_subentry_id,
|
||||
"subentry_type": "conversation",
|
||||
|
||||
@@ -114,8 +114,8 @@ async def test_repair_flow_iterates_subentries(
|
||||
|
||||
model_options: list[dict[str, str]] = [
|
||||
{"label": "Claude Haiku 4.5", "value": "claude-haiku-4-5"},
|
||||
{"label": "Claude Sonnet 4.5", "value": "claude-sonnet-4-5"},
|
||||
{"label": "Claude Opus 4.5", "value": "claude-opus-4-5"},
|
||||
{"label": "Claude Sonnet 4.6", "value": "claude-sonnet-4-6"},
|
||||
{"label": "Claude Opus 4.6", "value": "claude-opus-4-6"},
|
||||
]
|
||||
|
||||
with patch(
|
||||
@@ -152,12 +152,12 @@ async def test_repair_flow_iterates_subentries(
|
||||
result = await process_repair_fix_flow(
|
||||
client,
|
||||
flow_id,
|
||||
json={CONF_CHAT_MODEL: "claude-sonnet-4-5"},
|
||||
json={CONF_CHAT_MODEL: "claude-sonnet-4-6"},
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert (
|
||||
_get_subentry(entry_one, "ai_task_data").data[CONF_CHAT_MODEL]
|
||||
== "claude-sonnet-4-5"
|
||||
== "claude-sonnet-4-6"
|
||||
)
|
||||
assert (
|
||||
_get_subentry(entry_one, "conversation").data[CONF_CHAT_MODEL]
|
||||
@@ -172,12 +172,12 @@ async def test_repair_flow_iterates_subentries(
|
||||
result = await process_repair_fix_flow(
|
||||
client,
|
||||
flow_id,
|
||||
json={CONF_CHAT_MODEL: "claude-opus-4-5"},
|
||||
json={CONF_CHAT_MODEL: "claude-opus-4-6"},
|
||||
)
|
||||
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert (
|
||||
_get_subentry(entry_two, "conversation").data[CONF_CHAT_MODEL]
|
||||
== "claude-opus-4-5"
|
||||
== "claude-opus-4-6"
|
||||
)
|
||||
|
||||
assert issue_registry.async_get_issue(DOMAIN, "model_deprecated") is None
|
||||
|
||||
Reference in New Issue
Block a user