1 """The Google Generative AI Conversation integration."""
3 from __future__
import annotations
6 from pathlib
import Path
8 from google.ai
import generativelanguage_v1beta
9 from google.api_core.client_options
import ClientOptions
10 from google.api_core.exceptions
import ClientError, DeadlineExceeded, GoogleAPIError
11 import google.generativeai
as genai
12 import google.generativeai.types
as genai_types
13 import voluptuous
as vol
24 ConfigEntryAuthFailed,
32 from .const
import CONF_CHAT_MODEL, CONF_PROMPT, DOMAIN, RECOMMENDED_CHAT_MODEL
34 SERVICE_GENERATE_CONTENT =
"generate_content"
35 CONF_IMAGE_FILENAME =
"image_filename"
37 CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
38 PLATFORMS = (Platform.CONVERSATION,)
41 async
def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
42 """Set up Google Generative AI Conversation."""
44 async
def generate_content(call: ServiceCall) -> ServiceResponse:
45 """Generate content from text and optionally images."""
46 prompt_parts = [call.data[CONF_PROMPT]]
47 image_filenames = call.data[CONF_IMAGE_FILENAME]
48 for image_filename
in image_filenames:
49 if not hass.config.is_allowed_path(image_filename):
51 f
"Cannot read `{image_filename}`, no access to path; "
52 "`allowlist_external_dirs` may need to be adjusted in "
53 "`configuration.yaml`"
55 if not Path(image_filename).exists():
57 mime_type, _ = mimetypes.guess_type(image_filename)
58 if mime_type
is None or not mime_type.startswith(
"image"):
62 "mime_type": mime_type,
63 "data": await hass.async_add_executor_job(
64 Path(image_filename).read_bytes
69 model = genai.GenerativeModel(model_name=RECOMMENDED_CHAT_MODEL)
72 response = await model.generate_content_async(prompt_parts)
76 genai_types.BlockedPromptException,
77 genai_types.StopCandidateException,
81 if not response.parts:
84 return {
"text": response.text}
86 hass.services.async_register(
88 SERVICE_GENERATE_CONTENT,
92 vol.Required(CONF_PROMPT): cv.string,
93 vol.Optional(CONF_IMAGE_FILENAME, default=[]): vol.All(
94 cv.ensure_list, [cv.string]
98 supports_response=SupportsResponse.ONLY,
104 """Set up Google Generative AI Conversation from a config entry."""
105 genai.configure(api_key=entry.data[CONF_API_KEY])
108 client = generativelanguage_v1beta.ModelServiceAsyncClient(
109 client_options=ClientOptions(api_key=entry.data[CONF_API_KEY])
111 await client.get_model(
112 name=entry.options.get(CONF_CHAT_MODEL, RECOMMENDED_CHAT_MODEL), timeout=5.0
114 except (GoogleAPIError, ValueError)
as err:
115 if isinstance(err, ClientError)
and err.reason ==
"API_KEY_INVALID":
117 if isinstance(err, DeadlineExceeded):
121 await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
127 """Unload GoogleGenerativeAI."""
128 if not await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
bool async_setup_entry(HomeAssistant hass, ConfigEntry entry)
bool async_setup(HomeAssistant hass, ConfigType config)
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)