1 """Config flow for Ollama integration."""
3 from __future__
import annotations
8 from types
import MappingProxyType
13 import voluptuous
as vol
55 _LOGGER = logging.getLogger(__name__)
58 STEP_USER_DATA_SCHEMA = vol.Schema(
68 """Handle a config flow for Ollama."""
73 """Initialize config flow."""
74 self.
urlurl: str |
None =
None
75 self.
modelmodel: str |
None =
None
76 self.
clientclient: ollama.AsyncClient |
None =
None
80 self, user_input: dict[str, Any] |
None =
None
81 ) -> ConfigFlowResult:
82 """Handle the initial step."""
83 user_input = user_input
or {}
84 self.
urlurl = user_input.get(CONF_URL, self.
urlurl)
85 self.
modelmodel = user_input.get(CONF_MODEL, self.
modelmodel)
87 if self.
urlurl
is None:
89 step_id=
"user", data_schema=STEP_USER_DATA_SCHEMA, last_step=
False
95 self.
clientclient = ollama.AsyncClient(
98 async
with asyncio.timeout(DEFAULT_TIMEOUT):
101 downloaded_models: set[str] = {
102 model_info[
"model"]
for model_info
in response.get(
"models", [])
104 except (TimeoutError, httpx.ConnectError):
105 errors[
"base"] =
"cannot_connect"
107 _LOGGER.exception(
"Unexpected exception")
108 errors[
"base"] =
"unknown"
112 step_id=
"user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors
115 if self.
modelmodel
is None:
120 for m
in sorted(downloaded_models)
123 for m
in sorted(MODEL_NAMES)
124 if m
not in downloaded_models
126 model_step_schema = vol.Schema(
129 CONF_MODEL, description={
"suggested_value": DEFAULT_MODEL}
138 data_schema=model_step_schema,
141 if self.
modelmodel
not in downloaded_models:
147 data={CONF_URL: self.
urlurl, CONF_MODEL: self.
modelmodel},
151 self, user_input: dict[str, Any] |
None =
None
152 ) -> ConfigFlowResult:
153 """Step to wait for Ollama server to download a model."""
154 assert self.
modelmodel
is not None
155 assert self.
clientclient
is not None
163 f
"Downloading {self.model}",
168 _LOGGER.exception(
"Unexpected error while downloading model: %s", err)
175 progress_action=
"download",
180 self, user_input: dict[str, Any] |
None =
None
181 ) -> ConfigFlowResult:
182 """Step after model downloading has succeeded."""
183 assert self.
urlurl
is not None
184 assert self.
modelmodel
is not None
188 data={CONF_URL: self.
urlurl, CONF_MODEL: self.
modelmodel},
192 self, user_input: dict[str, Any] |
None =
None
193 ) -> ConfigFlowResult:
194 """Step after model downloading has failed."""
199 config_entry: ConfigEntry,
201 """Create the options flow."""
206 """Ollama options flow."""
208 def __init__(self, config_entry: ConfigEntry) ->
None:
209 """Initialize options flow."""
210 self.url: str = config_entry.data[CONF_URL]
211 self.model: str = config_entry.data[CONF_MODEL]
214 self, user_input: dict[str, Any] |
None =
None
215 ) -> ConfigFlowResult:
216 """Manage the options."""
217 if user_input
is not None:
218 if user_input[CONF_LLM_HASS_API] ==
"none":
219 user_input.pop(CONF_LLM_HASS_API)
228 data_schema=vol.Schema(schema),
233 hass: HomeAssistant, options: MappingProxyType[str, Any]
235 """Ollama options schema."""
236 hass_apis: list[SelectOptionDict] = [
247 for api
in llm.async_get_apis(hass)
254 "suggested_value": options.get(
255 CONF_PROMPT, llm.DEFAULT_INSTRUCTIONS_PROMPT
261 description={
"suggested_value": options.get(CONF_LLM_HASS_API)},
266 description={
"suggested_value": options.get(CONF_NUM_CTX, DEFAULT_NUM_CTX)},
269 min=MIN_NUM_CTX, max=MAX_NUM_CTX, step=1, mode=NumberSelectorMode.BOX
275 "suggested_value": options.get(CONF_MAX_HISTORY, DEFAULT_MAX_HISTORY)
279 min=0, max=sys.maxsize, step=1, mode=NumberSelectorMode.BOX
285 "suggested_value": options.get(CONF_KEEP_ALIVE, DEFAULT_KEEP_ALIVE)
289 min=-1, max=sys.maxsize, step=1, mode=NumberSelectorMode.BOX
296 """Get title for config entry."""
297 if model.endswith(
":latest"):
298 model = model.split(
":", maxsplit=1)[0]
ConfigFlowResult async_step_finish(self, dict[str, Any]|None user_input=None)
OptionsFlow async_get_options_flow(ConfigEntry config_entry)
ConfigFlowResult async_step_failed(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_download(self, dict[str, Any]|None user_input=None)
None __init__(self, ConfigEntry config_entry)
ConfigFlowResult async_step_init(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_create_entry(self, *str title, Mapping[str, Any] data, str|None description=None, Mapping[str, str]|None description_placeholders=None, Mapping[str, Any]|None options=None)
ConfigFlowResult async_abort(self, *str reason, Mapping[str, str]|None description_placeholders=None)
ConfigFlowResult async_show_form(self, *str|None step_id=None, vol.Schema|None data_schema=None, dict[str, str]|None errors=None, Mapping[str, str]|None description_placeholders=None, bool|None last_step=None, str|None preview=None)
ConfigEntry config_entry(self)
None config_entry(self, ConfigEntry value)
_FlowResultT async_show_form(self, *str|None step_id=None, vol.Schema|None data_schema=None, dict[str, str]|None errors=None, Mapping[str, str]|None description_placeholders=None, bool|None last_step=None, str|None preview=None)
_FlowResultT async_show_progress(self, *str|None step_id=None, str progress_action, Mapping[str, str]|None description_placeholders=None, asyncio.Task[Any]|None progress_task=None)
_FlowResultT async_show_progress_done(self, *str next_step_id)
_FlowResultT async_create_entry(self, *str|None title=None, Mapping[str, Any] data, str|None description=None, Mapping[str, str]|None description_placeholders=None)
_FlowResultT async_abort(self, *str reason, Mapping[str, str]|None description_placeholders=None)
str _get_title(str model)
dict ollama_config_option_schema(HomeAssistant hass, MappingProxyType[str, Any] options)
ssl.SSLContext get_default_context()