Persist non-conversation memory across sessions

This commit is contained in:
Your Name 2025-12-20 13:53:18 -06:00
parent 1d97288174
commit ed8d913a50

View file

@ -30,6 +30,7 @@ from homeassistant.const import CONF_LLM_HASS_API, MATCH_ALL
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError, TemplateError from homeassistant.exceptions import HomeAssistantError, TemplateError
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.storage import Store
from homeassistant.helpers import device_registry as dr, intent, llm, template from homeassistant.helpers import device_registry as dr, intent, llm, template
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util import ulid from homeassistant.util import ulid
@ -186,6 +187,8 @@ class GroqdConversationEntity(
self.entry = entry self.entry = entry
self.history: dict[str, list[ChatCompletionMessageParam]] = {} self.history: dict[str, list[ChatCompletionMessageParam]] = {}
self._memory_index: dict[str, str] = {} self._memory_index: dict[str, str] = {}
self._persisted_history: dict[str, list[ChatCompletionMessageParam]] = {}
self._store: Store | None = None
self._attr_unique_id = entry.entry_id self._attr_unique_id = entry.entry_id
self._attr_device_info = dr.DeviceInfo( self._attr_device_info = dr.DeviceInfo(
identifiers={(DOMAIN, entry.entry_id)}, identifiers={(DOMAIN, entry.entry_id)},
@ -206,6 +209,10 @@ class GroqdConversationEntity(
async def async_added_to_hass(self) -> None: async def async_added_to_hass(self) -> None:
await super().async_added_to_hass() await super().async_added_to_hass()
conversation.async_set_agent(self.hass, self.entry, self) conversation.async_set_agent(self.hass, self.entry, self)
self._store = Store(self.hass, 1, f"groqd_history_{self.entry.entry_id}")
data = await self._store.async_load() or {}
self._persisted_history = data.get("history", {})
self._memory_index = data.get("memory_index", {})
self.entry.async_on_unload( self.entry.async_on_unload(
self.entry.add_update_listener(self._async_entry_update_listener) self.entry.add_update_listener(self._async_entry_update_listener)
) )
@ -277,16 +284,13 @@ class GroqdConversationEntity(
if user_input.conversation_id is not None: if user_input.conversation_id is not None:
conversation_id = user_input.conversation_id conversation_id = user_input.conversation_id
history = self.history.get(conversation_id, []) history = self.history.get(conversation_id, [])
elif memory_key and memory_key in self._memory_index:
conversation_id = self._memory_index[memory_key]
history = self.history.get(conversation_id, [])
else: else:
conversation_id = ulid.ulid_now() conversation_id = ulid.ulid_now()
history = [] history = []
else: else:
if memory_key and memory_key in self._memory_index: if memory_key and memory_key in self._memory_index:
conversation_id = self._memory_index[memory_key] conversation_id = self._memory_index[memory_key]
history = self.history.get(conversation_id, []) history = self._persisted_history.get(memory_key, [])
else: else:
conversation_id = ulid.ulid_now() conversation_id = ulid.ulid_now()
history = [] history = []
@ -465,9 +469,16 @@ class GroqdConversationEntity(
elif limit > 0: elif limit > 0:
history = history[-limit:] history = history[-limit:]
self.history[conversation_id] = history if memory_scope == "conversation":
if memory_key: self.history[conversation_id] = history
self._memory_index[memory_key] = conversation_id else:
if memory_key:
self._persisted_history[memory_key] = history
self._memory_index[memory_key] = conversation_id
if self._store:
await self._store.async_save(
{"history": self._persisted_history, "memory_index": self._memory_index}
)
intent_response.async_set_speech(response.content or "") intent_response.async_set_speech(response.content or "")
return conversation.ConversationResult( return conversation.ConversationResult(