mirror of
https://github.com/home-assistant/core.git
synced 2026-08-24 10:13:52 -05:00
Remove Temperature parameter from Anthropic integration (#168504)
This commit is contained in:
@@ -230,6 +230,19 @@ async def async_migrate_entry(hass: HomeAssistant, entry: AnthropicConfigEntry)
|
||||
)
|
||||
hass.config_entries.async_update_entry(entry, minor_version=3)
|
||||
|
||||
if entry.version == 2 and entry.minor_version == 3:
|
||||
# Remove Temperature parameter
|
||||
CONF_TEMPERATURE = "temperature"
|
||||
|
||||
for subentry in entry.subentries.values():
|
||||
data = subentry.data.copy()
|
||||
if CONF_TEMPERATURE not in data:
|
||||
continue
|
||||
data.pop(CONF_TEMPERATURE, None)
|
||||
hass.config_entries.async_update_subentry(entry, subentry, data=data)
|
||||
|
||||
hass.config_entries.async_update_entry(entry, minor_version=4)
|
||||
|
||||
LOGGER.debug(
|
||||
"Migration to version %s:%s successful", entry.version, entry.minor_version
|
||||
)
|
||||
|
||||
@@ -50,7 +50,6 @@ from .const import (
|
||||
CONF_PROMPT,
|
||||
CONF_PROMPT_CACHING,
|
||||
CONF_RECOMMENDED,
|
||||
CONF_TEMPERATURE,
|
||||
CONF_THINKING_BUDGET,
|
||||
CONF_THINKING_EFFORT,
|
||||
CONF_TOOL_SEARCH,
|
||||
@@ -109,7 +108,7 @@ class AnthropicConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
"""Handle a config flow for Anthropic."""
|
||||
|
||||
VERSION = 2
|
||||
MINOR_VERSION = 3
|
||||
MINOR_VERSION = 4
|
||||
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
@@ -324,10 +323,6 @@ class ConversationSubentryFlowHandler(ConfigSubentryFlow):
|
||||
): SelectSelector(
|
||||
SelectSelectorConfig(options=self._get_model_list(), custom_value=True)
|
||||
),
|
||||
vol.Optional(
|
||||
CONF_TEMPERATURE,
|
||||
default=DEFAULT[CONF_TEMPERATURE],
|
||||
): NumberSelector(NumberSelectorConfig(min=0, max=1, step=0.05)),
|
||||
vol.Optional(
|
||||
CONF_PROMPT_CACHING,
|
||||
default=DEFAULT[CONF_PROMPT_CACHING],
|
||||
|
||||
@@ -15,7 +15,6 @@ CONF_CHAT_MODEL = "chat_model"
|
||||
CONF_CODE_EXECUTION = "code_execution"
|
||||
CONF_MAX_TOKENS = "max_tokens"
|
||||
CONF_PROMPT_CACHING = "prompt_caching"
|
||||
CONF_TEMPERATURE = "temperature"
|
||||
CONF_THINKING_BUDGET = "thinking_budget"
|
||||
CONF_THINKING_EFFORT = "thinking_effort"
|
||||
CONF_TOOL_SEARCH = "tool_search"
|
||||
@@ -43,7 +42,6 @@ DEFAULT = {
|
||||
CONF_CODE_EXECUTION: False,
|
||||
CONF_MAX_TOKENS: 3000,
|
||||
CONF_PROMPT_CACHING: PromptCaching.PROMPT.value,
|
||||
CONF_TEMPERATURE: 1.0,
|
||||
CONF_THINKING_BUDGET: MIN_THINKING_BUDGET,
|
||||
CONF_THINKING_EFFORT: "low",
|
||||
CONF_TOOL_SEARCH: False,
|
||||
|
||||
@@ -98,7 +98,6 @@ from .const import (
|
||||
CONF_CODE_EXECUTION,
|
||||
CONF_MAX_TOKENS,
|
||||
CONF_PROMPT_CACHING,
|
||||
CONF_TEMPERATURE,
|
||||
CONF_THINKING_BUDGET,
|
||||
CONF_THINKING_EFFORT,
|
||||
CONF_TOOL_SEARCH,
|
||||
@@ -768,9 +767,6 @@ class AnthropicBaseLLMEntity(CoordinatorEntity[AnthropicCoordinator]):
|
||||
model_args["output_config"] = OutputConfigParam(effort=thinking_effort)
|
||||
else:
|
||||
model_args["thinking"] = ThinkingConfigDisabledParam(type="disabled")
|
||||
model_args["temperature"] = options.get(
|
||||
CONF_TEMPERATURE, DEFAULT[CONF_TEMPERATURE]
|
||||
)
|
||||
else:
|
||||
thinking_budget = options.get(
|
||||
CONF_THINKING_BUDGET, DEFAULT[CONF_THINKING_BUDGET]
|
||||
@@ -785,9 +781,6 @@ class AnthropicBaseLLMEntity(CoordinatorEntity[AnthropicCoordinator]):
|
||||
)
|
||||
else:
|
||||
model_args["thinking"] = ThinkingConfigDisabledParam(type="disabled")
|
||||
model_args["temperature"] = options.get(
|
||||
CONF_TEMPERATURE, DEFAULT[CONF_TEMPERATURE]
|
||||
)
|
||||
|
||||
if (
|
||||
self.model_info.capabilities
|
||||
|
||||
@@ -82,7 +82,6 @@
|
||||
'type': 'text',
|
||||
}),
|
||||
]),
|
||||
'temperature': 1.0,
|
||||
'thinking': dict({
|
||||
'type': 'disabled',
|
||||
}),
|
||||
@@ -288,7 +287,6 @@
|
||||
'type': 'text',
|
||||
}),
|
||||
]),
|
||||
'temperature': 1.0,
|
||||
'thinking': dict({
|
||||
'type': 'disabled',
|
||||
}),
|
||||
|
||||
@@ -254,7 +254,6 @@
|
||||
'type': 'text',
|
||||
}),
|
||||
]),
|
||||
'temperature': 1.0,
|
||||
'thinking': dict({
|
||||
'type': 'disabled',
|
||||
}),
|
||||
@@ -319,7 +318,6 @@
|
||||
'type': 'text',
|
||||
}),
|
||||
]),
|
||||
'temperature': 1.0,
|
||||
'thinking': dict({
|
||||
'type': 'disabled',
|
||||
}),
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
'translation_key': 'conversation',
|
||||
}),
|
||||
}),
|
||||
'entry_version': '2.3',
|
||||
'entry_version': '2.4',
|
||||
'options': dict({
|
||||
}),
|
||||
'state': 'loaded',
|
||||
|
||||
@@ -30,7 +30,6 @@ from homeassistant.components.anthropic.const import (
|
||||
CONF_PROMPT,
|
||||
CONF_PROMPT_CACHING,
|
||||
CONF_RECOMMENDED,
|
||||
CONF_TEMPERATURE,
|
||||
CONF_THINKING_BUDGET,
|
||||
CONF_THINKING_EFFORT,
|
||||
CONF_TOOL_SEARCH,
|
||||
@@ -276,10 +275,7 @@ async def test_subentry_options_thinking_budget_more_than_max(
|
||||
# Configure advanced step
|
||||
options = await hass.config_entries.subentries.async_configure(
|
||||
options["flow_id"],
|
||||
{
|
||||
"chat_model": "claude-sonnet-4-5",
|
||||
"temperature": 1,
|
||||
},
|
||||
{"chat_model": "claude-sonnet-4-5"},
|
||||
)
|
||||
assert options["type"] is FlowResultType.FORM
|
||||
assert options["step_id"] == "model"
|
||||
@@ -390,7 +386,6 @@ async def test_subentry_web_search_user_location(
|
||||
"prompt_caching": "prompt",
|
||||
"recommended": False,
|
||||
"region": "California",
|
||||
"temperature": 1.0,
|
||||
"thinking_budget": 1024,
|
||||
"timezone": "America/Los_Angeles",
|
||||
"tool_search": False,
|
||||
@@ -574,7 +569,6 @@ async def test_invalid_model(
|
||||
},
|
||||
{
|
||||
CONF_CHAT_MODEL: "claude-haiku-4-5",
|
||||
CONF_TEMPERATURE: 1.0,
|
||||
CONF_PROMPT_CACHING: "off",
|
||||
},
|
||||
{
|
||||
@@ -588,7 +582,6 @@ async def test_invalid_model(
|
||||
CONF_RECOMMENDED: False,
|
||||
CONF_PROMPT: "Speak like a pirate",
|
||||
CONF_PROMPT_CACHING: "off",
|
||||
CONF_TEMPERATURE: 1.0,
|
||||
CONF_CHAT_MODEL: "claude-haiku-4-5",
|
||||
CONF_MAX_TOKENS: DEFAULT[CONF_MAX_TOKENS],
|
||||
CONF_THINKING_BUDGET: DEFAULT[CONF_THINKING_BUDGET],
|
||||
@@ -619,7 +612,6 @@ async def test_invalid_model(
|
||||
},
|
||||
{
|
||||
CONF_CHAT_MODEL: "claude-sonnet-4-5",
|
||||
CONF_TEMPERATURE: 1.0,
|
||||
CONF_PROMPT_CACHING: "automatic",
|
||||
},
|
||||
{
|
||||
@@ -635,7 +627,6 @@ async def test_invalid_model(
|
||||
CONF_RECOMMENDED: False,
|
||||
CONF_PROMPT: "Speak like a pirate",
|
||||
CONF_PROMPT_CACHING: "automatic",
|
||||
CONF_TEMPERATURE: 1.0,
|
||||
CONF_CHAT_MODEL: "claude-sonnet-4-5",
|
||||
CONF_MAX_TOKENS: DEFAULT[CONF_MAX_TOKENS],
|
||||
CONF_THINKING_BUDGET: 2048,
|
||||
@@ -667,7 +658,6 @@ async def test_invalid_model(
|
||||
},
|
||||
{
|
||||
CONF_CHAT_MODEL: "claude-opus-4-7",
|
||||
CONF_TEMPERATURE: 1.0,
|
||||
CONF_PROMPT_CACHING: "prompt",
|
||||
},
|
||||
{
|
||||
@@ -683,7 +673,6 @@ async def test_invalid_model(
|
||||
CONF_RECOMMENDED: False,
|
||||
CONF_PROMPT: "Speak like a pirate",
|
||||
CONF_PROMPT_CACHING: "prompt",
|
||||
CONF_TEMPERATURE: 1.0,
|
||||
CONF_CHAT_MODEL: "claude-opus-4-7",
|
||||
CONF_MAX_TOKENS: DEFAULT[CONF_MAX_TOKENS],
|
||||
CONF_THINKING_EFFORT: "xhigh",
|
||||
@@ -707,7 +696,6 @@ async def test_invalid_model(
|
||||
},
|
||||
{
|
||||
CONF_CHAT_MODEL: "claude-3-haiku-20240307",
|
||||
CONF_TEMPERATURE: 0.3,
|
||||
CONF_PROMPT_CACHING: "automatic",
|
||||
},
|
||||
{},
|
||||
@@ -716,7 +704,6 @@ async def test_invalid_model(
|
||||
CONF_RECOMMENDED: False,
|
||||
CONF_PROMPT: "Speak like a pirate",
|
||||
CONF_PROMPT_CACHING: "automatic",
|
||||
CONF_TEMPERATURE: 0.3,
|
||||
CONF_CHAT_MODEL: "claude-3-haiku-20240307",
|
||||
CONF_MAX_TOKENS: DEFAULT[CONF_MAX_TOKENS],
|
||||
},
|
||||
@@ -726,7 +713,6 @@ async def test_invalid_model(
|
||||
CONF_RECOMMENDED: False,
|
||||
CONF_PROMPT: "Speak like a pirate",
|
||||
CONF_PROMPT_CACHING: "off",
|
||||
CONF_TEMPERATURE: 0.3,
|
||||
CONF_CHAT_MODEL: DEFAULT[CONF_CHAT_MODEL],
|
||||
CONF_MAX_TOKENS: DEFAULT[CONF_MAX_TOKENS],
|
||||
CONF_THINKING_BUDGET: DEFAULT[CONF_THINKING_BUDGET],
|
||||
@@ -888,7 +874,6 @@ async def test_creating_ai_task_subentry_advanced(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_CHAT_MODEL: "claude-sonnet-4-5",
|
||||
CONF_TEMPERATURE: 0.5,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -910,7 +895,6 @@ async def test_creating_ai_task_subentry_advanced(
|
||||
CONF_RECOMMENDED: False,
|
||||
CONF_CHAT_MODEL: "claude-sonnet-4-5",
|
||||
CONF_MAX_TOKENS: 1200,
|
||||
CONF_TEMPERATURE: 0.5,
|
||||
CONF_TOOL_SEARCH: False,
|
||||
CONF_WEB_SEARCH: False,
|
||||
CONF_WEB_SEARCH_MAX_USES: 5,
|
||||
|
||||
@@ -13,6 +13,7 @@ import httpx
|
||||
from httpx import URL, Request, Response
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.anthropic.config_flow import AnthropicConfigFlow
|
||||
from homeassistant.components.anthropic.const import DOMAIN
|
||||
from homeassistant.config_entries import (
|
||||
ConfigEntryDisabler,
|
||||
@@ -32,6 +33,8 @@ from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
MINOR_VERSION = AnthropicConfigFlow.MINOR_VERSION
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("side_effect", "error"),
|
||||
@@ -210,7 +213,7 @@ async def test_migration_from_v1_to_v2(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_config_entry.version == 2
|
||||
assert mock_config_entry.minor_version == 3
|
||||
assert mock_config_entry.minor_version == MINOR_VERSION
|
||||
assert mock_config_entry.data == {"api_key": "1234"}
|
||||
assert mock_config_entry.options == {}
|
||||
|
||||
@@ -409,7 +412,11 @@ async def test_migration_from_v1_disabled(
|
||||
entry = entries[0]
|
||||
assert entry.disabled_by is merged_config_entry_disabled_by
|
||||
assert entry.version == 2
|
||||
assert entry.minor_version == 3
|
||||
assert (
|
||||
entry.minor_version == 3
|
||||
if merged_config_entry_disabled_by is not None
|
||||
else MINOR_VERSION
|
||||
)
|
||||
assert not entry.options
|
||||
assert entry.title == "Claude conversation"
|
||||
assert len(entry.subentries) == 2
|
||||
@@ -529,7 +536,7 @@ async def test_migration_from_v1_to_v2_with_multiple_keys(
|
||||
|
||||
for idx, entry in enumerate(entries):
|
||||
assert entry.version == 2
|
||||
assert entry.minor_version == 3
|
||||
assert entry.minor_version == MINOR_VERSION
|
||||
assert not entry.options
|
||||
assert len(entry.subentries) == 1
|
||||
subentry = list(entry.subentries.values())[0]
|
||||
@@ -620,7 +627,7 @@ async def test_migration_from_v1_to_v2_with_same_keys(
|
||||
|
||||
entry = entries[0]
|
||||
assert entry.version == 2
|
||||
assert entry.minor_version == 3
|
||||
assert entry.minor_version == MINOR_VERSION
|
||||
assert not entry.options
|
||||
assert len(entry.subentries) == 2 # Two subentries from the two original entries
|
||||
|
||||
@@ -740,7 +747,7 @@ async def test_migration_from_v2_1_to_v2_2(
|
||||
assert len(entries) == 1
|
||||
entry = entries[0]
|
||||
assert entry.version == 2
|
||||
assert entry.minor_version == 3
|
||||
assert entry.minor_version == MINOR_VERSION
|
||||
assert not entry.options
|
||||
assert entry.title == "Claude"
|
||||
assert len(entry.subentries) == 2
|
||||
@@ -817,7 +824,7 @@ async def test_migration_from_v2_1_to_v2_2(
|
||||
DeviceEntryDisabler.CONFIG_ENTRY,
|
||||
RegistryEntryDisabler.CONFIG_ENTRY,
|
||||
True,
|
||||
3,
|
||||
MINOR_VERSION,
|
||||
None,
|
||||
DeviceEntryDisabler.USER,
|
||||
RegistryEntryDisabler.DEVICE,
|
||||
@@ -827,7 +834,7 @@ async def test_migration_from_v2_1_to_v2_2(
|
||||
DeviceEntryDisabler.USER,
|
||||
RegistryEntryDisabler.DEVICE,
|
||||
True,
|
||||
3,
|
||||
MINOR_VERSION,
|
||||
None,
|
||||
DeviceEntryDisabler.USER,
|
||||
RegistryEntryDisabler.DEVICE,
|
||||
@@ -837,7 +844,7 @@ async def test_migration_from_v2_1_to_v2_2(
|
||||
DeviceEntryDisabler.USER,
|
||||
RegistryEntryDisabler.USER,
|
||||
True,
|
||||
3,
|
||||
MINOR_VERSION,
|
||||
None,
|
||||
DeviceEntryDisabler.USER,
|
||||
RegistryEntryDisabler.USER,
|
||||
@@ -847,7 +854,7 @@ async def test_migration_from_v2_1_to_v2_2(
|
||||
None,
|
||||
None,
|
||||
True,
|
||||
3,
|
||||
MINOR_VERSION,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
@@ -984,3 +991,69 @@ async def test_migrate_entry_to_v2_3(
|
||||
assert mock_config_entry.disabled_by == config_entry_disabled_by_after_migration
|
||||
assert conversation_device.disabled_by == device_disabled_by_after_migration
|
||||
assert conversation_entity.disabled_by == entity_disabled_by_after_migration
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_setup_entry")
|
||||
async def test_migrate_entry_to_v2_4(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""Test migration to version 2.4."""
|
||||
# Create a v2.3 config entry
|
||||
mock_config_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data={CONF_API_KEY: "test-api-key"},
|
||||
version=2,
|
||||
minor_version=3,
|
||||
subentries_data=[
|
||||
{
|
||||
"data": {
|
||||
"recommended": True,
|
||||
"llm_hass_api": ["assist"],
|
||||
"prompt": "You are a helpful assistant",
|
||||
"chat_model": "claude-haiku-4-5",
|
||||
},
|
||||
"subentry_id": "mock_id_1",
|
||||
"subentry_type": "conversation",
|
||||
"title": "Claude haiku default",
|
||||
"unique_id": None,
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"recommended": False,
|
||||
"llm_hass_api": ["assist"],
|
||||
"prompt": "You are a helpful assistant",
|
||||
"chat_model": "claude-haiku-4-5",
|
||||
"temperature": 0.5,
|
||||
},
|
||||
"subentry_id": "mock_id_2",
|
||||
"subentry_type": "conversation",
|
||||
"title": "Claude haiku non-default",
|
||||
"unique_id": None,
|
||||
},
|
||||
],
|
||||
)
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
# Run migration
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Check that minor version was updated
|
||||
assert mock_config_entry.version == 2
|
||||
assert mock_config_entry.minor_version == MINOR_VERSION
|
||||
|
||||
# Verify data was not changed for the first subentry
|
||||
assert mock_config_entry.subentries["mock_id_1"].data == {
|
||||
"recommended": True,
|
||||
"llm_hass_api": ["assist"],
|
||||
"prompt": "You are a helpful assistant",
|
||||
"chat_model": "claude-haiku-4-5",
|
||||
}
|
||||
|
||||
# Verify that temperature was removed from the second subentry
|
||||
assert mock_config_entry.subentries["mock_id_2"].data == {
|
||||
"recommended": False,
|
||||
"llm_hass_api": ["assist"],
|
||||
"prompt": "You are a helpful assistant",
|
||||
"chat_model": "claude-haiku-4-5",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user