Compare commits

...
23 Commits
Author SHA1 Message Date
SMKRV 8cd876195a Bump to version 2.1.6 2025-05-20 01:50:06 +03:00
SMKRV 376753e001 fix: correct field naming in Gemini API requests from camelCase to snake_case and improve message handling 2025-05-20 01:42:38 +03:00
SMKRV b6e73e847d fix(api_client): correct Google Gemini API integration
- Change JSON field names from camelCase to snake_case as required by Gemini API
  (generation_config, max_output_tokens, system_instruction)
- Improve message handling to ensure proper role alternation (user/model)
- Add safety checks for empty contents and ensure first message is always from user
- Implement robust error handling and response parsing
- Handle edge cases where candidatesTokenCount might be returned as a list

Fixes #6
2025-05-20 01:16:41 +03:00
SMKRV 440c734214 Bump release version to v2.1.4 2025-05-19 23:20:27 +03:00
SMKRV 73788373cd Release v2.1.3 2025-05-19 23:12:55 +03:00
SMKRV 4bfc96019b fix: DEFAULT_GEMINI_ENDPOINT 2025-05-19 15:53:43 +03:00
SMKRV 2138fc7654 fix: DEFAULT_GEMINI_ENDPOINT 2025-05-19 15:36:58 +03:00
SMKRV 95bd2ebb41 Add support for Google Gemini (thanks to @Azzedde) #5 2025-05-19 15:10:19 +03:00
smkrvandGitHub cad0fd7031 Merge pull request #5 from Azzedde/main
Add Gemini API provider support to HA Text AI integration by @Azzedde
2025-05-19 14:44:06 +03:00
Azzedde c003b258f6 Add Gemini API provider support to HA Text AI integration 2025-05-18 13:23:55 +02:00
SMKRV 65a10c77f4 ~ 2025-01-30 01:15:13 +03:00
SMKRV e1463828c9 ~ 2025-01-30 01:14:24 +03:00
SMKRV 5ebb9c9c66 fix: max_tokens value 2025-01-29 18:04:13 +03:00
SMKRV f17c631a79 fix: max_tokens value 2025-01-29 18:02:42 +03:00
SMKRV 0e06794384 refactor(docs): shields & community links updated 2025-01-29 03:05:47 +03:00
SMKRV d8a924909b refactor(docs): shields & community links updated 2025-01-29 03:05:11 +03:00
SMKRV 29f1659a02 refactor(docs): shields & community links updated 2025-01-29 03:04:39 +03:00
SMKRV 5b7905de80 refactor(docs): shields & community links updated 2025-01-29 03:03:48 +03:00
SMKRV cf9ac6dcea refactor(docs): shields & community links updated 2025-01-29 01:08:45 +03:00
SMKRV 568eb3e16c refactor(docs): shields updated 2025-01-29 00:58:27 +03:00
SMKRV 53fb150389 refactor(docs): shields updated 2025-01-29 00:58:09 +03:00
SMKRV acbb53d2af refactor(docs): shields updated 2025-01-29 00:57:27 +03:00
SMKRV e19db29441 refactor(docs): DeepSeek Integration 2025-01-28 16:25:59 +03:00
17 changed files with 178 additions and 79 deletions
-41
View File
@@ -1,41 +0,0 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# Home Assistant
.storage
.cloud
.google.token
# IDE
.idea/
.vscode/
*.swp
*.swo
*~
# OS
.DS_Store
Thumbs.db
*.psd
*.zip
*.txt
*.pdf
+15 -11
View File
@@ -2,8 +2,8 @@
<div align="center"> <div align="center">
![GitHub release](https://img.shields.io/github/release/smkrv/ha-text-ai.svg?style=flat-square) ![GitHub last commit](https://img.shields.io/github/last-commit/smkrv/ha-text-ai.svg?style=flat-square) [![License: CC BY-NC-SA 4.0](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg?style=flat-square)](https://creativecommons.org/licenses/by-nc-sa/4.0/) [![hacs_badge](https://img.shields.io/badge/HACS-Custom-41BDF5.svg?style=flat-square)](https://github.com/hacs/integration) ![GitHub release](https://img.shields.io/github/v/release/smkrv/ha-text-ai?style=flat-square) ![GitHub last commit](https://img.shields.io/github/last-commit/smkrv/ha-text-ai?style=flat-square) [![License: CC BY-NC-SA 4.0](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg?style=flat-square)](https://creativecommons.org/licenses/by-nc-sa/4.0/) [![hacs_badge](https://img.shields.io/badge/HACS-Custom-41BDF5.svg?style=flat-square)](https://github.com/hacs/integration)
![Deutsch](https://img.shields.io/badge/de-Deutsch-blue?style=flat-square) ![English](https://img.shields.io/badge/en-English-blue?style=flat-square) ![Español](https://img.shields.io/badge/es-Español-blue?style=flat-square) ![हिन्दी](https://img.shields.io/badge/hi-हिन्दी-blue?style=flat-square) ![Italiano](https://img.shields.io/badge/it-Italiano-blue?style=flat-square) ![Русский](https://img.shields.io/badge/ru-Русский-blue?style=flat-square) ![Српски](https://img.shields.io/badge/sr-Српски-blue?style=flat-square) ![中文](https://img.shields.io/badge/zh-中文-blue?style=flat-square) ![Deutsch](https://img.shields.io/badge/lang-DE-blue?style=flat-square) ![English](https://img.shields.io/badge/lang-EN-blue?style=flat-square) ![Español](https://img.shields.io/badge/lang-ES-blue?style=flat-square) ![हिन्दी](https://img.shields.io/badge/lang-HI-blue?style=flat-square) ![Italiano](https://img.shields.io/badge/lang-IT-blue?style=flat-square) ![Русский](https://img.shields.io/badge/lang-RU-blue?style=flat-square) ![Српски](https://img.shields.io/badge/lang-SR-blue?style=flat-square) ![中文](https://img.shields.io/badge/lang-ZH-blue?style=flat-square)
<img src="https://github.com/smkrv/ha-text-ai/blob/15c717fcb0204bf4a0d4b4b4c6f0bb93e9f6c9a9/custom_components/ha_text_ai/icons/logo%402x.png" alt="HA Text AI" style="width: 50%; max-width: 256px; max-height: 128px; aspect-ratio: 2/1; object-fit: contain;"/> <img src="https://github.com/smkrv/ha-text-ai/blob/15c717fcb0204bf4a0d4b4b4c6f0bb93e9f6c9a9/custom_components/ha_text_ai/icons/logo%402x.png" alt="HA Text AI" style="width: 50%; max-width: 256px; max-height: 128px; aspect-ratio: 2/1; object-fit: contain;"/>
@@ -12,22 +12,23 @@
</div> </div>
<p align="center"> <p align="center">
Transform your smart home experience with powerful AI assistance powered by multiple AI providers including OpenAI GPT and Anthropic Claude models. Get intelligent responses, automate complex scenarios, and enhance your home automation with advanced natural language processing. Transform your smart home experience with powerful AI assistance powered by multiple AI providers including OpenAI GPT, DeepSeek and Anthropic Claude models. Get intelligent responses, automate complex scenarios, and enhance your home automation with advanced natural language processing.
</p> </p>
--- ---
> [!IMPORTANT] > [!IMPORTANT]
> 🤝 Community Driven > 🤝 Community Driven: for more details on the integration,
> check out the discussion on the **[Home Assistant Community forum](https://community.home-assistant.io/t/ha-text-ai-transforming-home-automation-through-multi-llm-integration/799741)**
> >
> <a href="https://community.home-assistant.io/t/ha-text-ai-transforming-home-automation-with-multi-provider-language-models/799741"><img src="https://img.shields.io/badge/Community-blue?style=for-the-badge&logo=homeassistant&logoColor=white&color=03a9f4"/></a> > <a href="https://my.home-assistant.io/redirect/hacs_repository/?owner=smkrv&repository=ha-text-ai&category=Integration"><img src="https://my.home-assistant.io/badges/hacs_repository.svg" width="210" height="auto"></a>
> >
> [Screenshots](assets/images/screenshots/screenshot.jpg) > [Screenshots](assets/images/screenshots/screenshot.jpg)
## 🌟 Features ## 🌟 Features
- 🧠 **Multi-Provider AI Integration**: Support for OpenAI GPT and Anthropic Claude models - 🧠 **Multi-Provider AI Integration**: Support for OpenAI GPT, DeepSeek and Anthropic Claude models
- 💬 **Advanced Language Processing**: Context-aware, multi-turn conversations - 💬 **Advanced Language Processing**: Context-aware, multi-turn conversations
- 📝 **Enhanced Memory Management**: Secure file-based history storage - 📝 **Enhanced Memory Management**: Secure file-based history storage
-**Performance Optimization**: Efficient token usage and smart rate limiting -**Performance Optimization**: Efficient token usage and smart rate limiting
@@ -42,6 +43,7 @@ Transform your smart home experience with powerful AI assistance powered by mult
### 🧠 **Multi-Provider AI Integration** ### 🧠 **Multi-Provider AI Integration**
- Support for OpenAI GPT models - Support for OpenAI GPT models
- Anthropic Claude integration - Anthropic Claude integration
- DeepSeek integration
- Custom API endpoints - Custom API endpoints
- Flexible model selection - Flexible model selection
@@ -104,12 +106,13 @@ Transform your smart home experience with powerful AI assistance powered by mult
## 📋 Prerequisites ## 📋 Prerequisites
- Home Assistant 2024.11 or later - Home Assistant 2024.2.2 or later
- Active API key from: - Active API key from:
- OpenAI ([Get key](https://platform.openai.com/account/api-keys)) - OpenAI ([Get key](https://platform.openai.com/account/api-keys))
- Anthropic ([Get key](https://console.anthropic.com/)) - Anthropic ([Get key](https://console.anthropic.com/))
- DeepSeek 🆕 ([Get key](https://platform.deepseek.com/api_keys)) - DeepSeek ([Get key](https://platform.deepseek.com/api_keys))
- OpenRouter ([Get key](https://openrouter.ai/keys)) - OpenRouter ([Get key](https://openrouter.ai/keys))
- Google Gemini 🆕 ([Get key](https://ai.google.dev/gemini-api/docs/api-key)) thanks to ([@Azzedde](https://github.com/Azzedde))
- Any OpenAI-compatible API provider - Any OpenAI-compatible API provider
- Python 3.9 or newer - Python 3.9 or newer
- Stable internet connection - Stable internet connection
@@ -117,7 +120,7 @@ Transform your smart home experience with powerful AI assistance powered by mult
## Configuration Options ## Configuration Options
### 🔧 **Core Configuration Settings** ### 🔧 **Core Configuration Settings**
- 🌐 **API Provider**: OpenAI/Anthropic - 🌐 **API Provider**: OpenAI/Anthropic/DeepSeek
- 🔑 **API Key**: Provider-specific authentication - 🔑 **API Key**: Provider-specific authentication
- 🤖 **Model Selection**: Flexible, provider-specific models - 🤖 **Model Selection**: Flexible, provider-specific models
- 🌡️ **Temperature**: Creativity control (0.0-2.0) - 🌡️ **Temperature**: Creativity control (0.0-2.0)
@@ -157,6 +160,9 @@ To be compatible, a provider should support:
## ⚡ Installation ## ⚡ Installation
### HACS Installation (Recommended) ### HACS Installation (Recommended)
>[!TIP]
>HA Text AI is available in the default HACS repository. You can install it directly through HACS or click the button below to open it there.
<a href="https://my.home-assistant.io/redirect/hacs_repository/?owner=smkrv&repository=ha-text-ai&category=Integration"><img src="https://my.home-assistant.io/badges/hacs_repository.svg" width="170" height="auto"></a> <a href="https://my.home-assistant.io/redirect/hacs_repository/?owner=smkrv&repository=ha-text-ai&category=Integration"><img src="https://my.home-assistant.io/badges/hacs_repository.svg" width="170" height="auto"></a>
1. Open HACS in Home Assistant 1. Open HACS in Home Assistant
2. Click on "Integrations" 2. Click on "Integrations"
@@ -167,8 +173,6 @@ To be compatible, a provider should support:
7. Click "Download" 7. Click "Download"
8. Restart Home Assistant 8. Restart Home Assistant
Note: Also Integration has been submitted to HACS store and is currently pending review in [pull request #2896](https://github.com/hacs/default/pull/2896).
### Manual Installation ### Manual Installation
1. Download the latest release 1. Download the latest release
2. Extract and copy `custom_components/ha_text_ai` to your `custom_components` directory 2. Extract and copy `custom_components/ha_text_ai` to your `custom_components` directory
+3
View File
@@ -40,13 +40,16 @@ from .const import (
API_PROVIDER_OPENAI, API_PROVIDER_OPENAI,
API_PROVIDER_ANTHROPIC, API_PROVIDER_ANTHROPIC,
API_PROVIDER_DEEPSEEK, API_PROVIDER_DEEPSEEK,
API_PROVIDER_GEMINI,
DEFAULT_MODEL, DEFAULT_MODEL,
DEFAULT_DEEPSEEK_MODEL, DEFAULT_DEEPSEEK_MODEL,
DEFAULT_GEMINI_MODEL,
DEFAULT_TEMPERATURE, DEFAULT_TEMPERATURE,
DEFAULT_MAX_TOKENS, DEFAULT_MAX_TOKENS,
DEFAULT_OPENAI_ENDPOINT, DEFAULT_OPENAI_ENDPOINT,
DEFAULT_ANTHROPIC_ENDPOINT, DEFAULT_ANTHROPIC_ENDPOINT,
DEFAULT_DEEPSEEK_ENDPOINT, DEFAULT_DEEPSEEK_ENDPOINT,
DEFAULT_GEMINI_ENDPOINT,
DEFAULT_REQUEST_INTERVAL, DEFAULT_REQUEST_INTERVAL,
DEFAULT_CONTEXT_MESSAGES, DEFAULT_CONTEXT_MESSAGES,
API_TIMEOUT, API_TIMEOUT,
@@ -20,6 +20,7 @@ from .const import (
API_PROVIDER_ANTHROPIC, API_PROVIDER_ANTHROPIC,
API_PROVIDER_DEEPSEEK, API_PROVIDER_DEEPSEEK,
API_PROVIDER_OPENAI, API_PROVIDER_OPENAI,
API_PROVIDER_GEMINI,
MIN_TEMPERATURE, MIN_TEMPERATURE,
MAX_TEMPERATURE, MAX_TEMPERATURE,
MIN_MAX_TOKENS, MIN_MAX_TOKENS,
@@ -115,6 +116,10 @@ class APIClient:
return await self._create_deepseek_completion( return await self._create_deepseek_completion(
model, messages, temperature, max_tokens model, messages, temperature, max_tokens
) )
elif self.api_provider == API_PROVIDER_GEMINI:
return await self._create_gemini_completion(
model, messages, temperature, max_tokens
)
else: else:
return await self._create_openai_completion( return await self._create_openai_completion(
model, messages, temperature, max_tokens model, messages, temperature, max_tokens
@@ -238,6 +243,100 @@ class APIClient:
_LOGGER.error(f"Connection check failed: {str(e)}") _LOGGER.error(f"Connection check failed: {str(e)}")
return False return False
async def _create_gemini_completion(
self,
model: str,
messages: List[Dict[str, str]],
temperature: float,
max_tokens: int,
) -> Dict[str, Any]:
"""Create completion using Gemini API."""
# Extract API key from headers (Bearer token)
api_key = self.headers.get("Authorization", "").replace("Bearer ", "")
url = f"{self.endpoint}/models/{model}:generateContent?key={api_key}"
# Convert messages to Gemini format
contents = []
system_instruction = ""
# Process messages
for msg in messages:
if msg['role'] == 'system':
system_instruction += msg['content'] + "\n"
else:
# Convert role: 'user' stays 'user', anything else becomes 'model'
role = "user" if msg['role'] == 'user' else "model"
contents.append({
"role": role,
"parts": [{"text": msg['content']}]
})
# Ensure contents starts with a user message if not empty
if contents and contents[0]["role"] != "user":
# Add a placeholder user message
contents.insert(0, {
"role": "user",
"parts": [{"text": "I need your assistance."}]
})
# Ensure contents is not empty
if not contents:
contents.append({
"role": "user",
"parts": [{"text": "I need your assistance."}]
})
# Create payload with snake_case keys as required by Gemini API
payload = {
"contents": contents,
"generation_config": { # Changed from camelCase to snake_case
"temperature": temperature,
"max_output_tokens": max_tokens # Changed from camelCase to snake_case
}
}
if system_instruction:
payload["system_instruction"] = { # Changed from camelCase to snake_case
"parts": [{"text": system_instruction.strip()}]
}
try:
data = await self._make_request(url, payload)
# Safely extract response data
candidates = data.get("candidates", [])
if not candidates:
raise HomeAssistantError("Gemini API returned no candidates")
content = candidates[0].get("content", {})
parts = content.get("parts", [])
if not parts:
raise HomeAssistantError("Gemini API response contains no content parts")
answer_text = parts[0].get("text", "")
# Safely extract usage data
usage = data.get("usageMetadata", {})
prompt_tokens = usage.get("promptTokenCount", 0)
completion_tokens = usage.get("candidatesTokenCount", 0)
total_tokens = usage.get("totalTokenCount", prompt_tokens + completion_tokens)
return {
"choices": [{
"message": {
"content": answer_text
}
}],
"usage": {
"prompt_tokens": prompt_tokens,
"completion_tokens": completion_tokens,
"total_tokens": total_tokens
}
}
except Exception as e:
_LOGGER.error(f"Gemini API error: {str(e)}")
raise HomeAssistantError(f"Gemini API error: {str(e)}")
async def shutdown(self) -> None: async def shutdown(self) -> None:
"""Shutdown API client.""" """Shutdown API client."""
_LOGGER.debug("Shutting down API client") _LOGGER.debug("Shutting down API client")
+23 -4
View File
@@ -29,15 +29,18 @@ from .const import (
API_PROVIDER_OPENAI, API_PROVIDER_OPENAI,
API_PROVIDER_ANTHROPIC, API_PROVIDER_ANTHROPIC,
API_PROVIDER_DEEPSEEK, API_PROVIDER_DEEPSEEK,
API_PROVIDER_GEMINI,
API_PROVIDERS, API_PROVIDERS,
DEFAULT_MODEL, DEFAULT_MODEL,
DEFAULT_DEEPSEEK_MODEL, DEFAULT_DEEPSEEK_MODEL,
DEFAULT_GEMINI_MODEL,
DEFAULT_TEMPERATURE, DEFAULT_TEMPERATURE,
DEFAULT_MAX_TOKENS, DEFAULT_MAX_TOKENS,
DEFAULT_REQUEST_INTERVAL, DEFAULT_REQUEST_INTERVAL,
DEFAULT_OPENAI_ENDPOINT, DEFAULT_OPENAI_ENDPOINT,
DEFAULT_ANTHROPIC_ENDPOINT, DEFAULT_ANTHROPIC_ENDPOINT,
DEFAULT_DEEPSEEK_ENDPOINT, DEFAULT_DEEPSEEK_ENDPOINT,
DEFAULT_GEMINI_ENDPOINT,
DEFAULT_CONTEXT_MESSAGES, DEFAULT_CONTEXT_MESSAGES,
MIN_TEMPERATURE, MIN_TEMPERATURE,
MAX_TEMPERATURE, MAX_TEMPERATURE,
@@ -93,15 +96,20 @@ class HATextAIConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
self._errors = {} self._errors = {}
if user_input is None: if user_input is None:
# Выбор endpoint по провайдеру # Selecting an endpoint by provider
default_endpoint = { default_endpoint = {
API_PROVIDER_OPENAI: DEFAULT_OPENAI_ENDPOINT, API_PROVIDER_OPENAI: DEFAULT_OPENAI_ENDPOINT,
API_PROVIDER_ANTHROPIC: DEFAULT_ANTHROPIC_ENDPOINT, API_PROVIDER_ANTHROPIC: DEFAULT_ANTHROPIC_ENDPOINT,
API_PROVIDER_DEEPSEEK: DEFAULT_DEEPSEEK_ENDPOINT, API_PROVIDER_DEEPSEEK: DEFAULT_DEEPSEEK_ENDPOINT,
API_PROVIDER_GEMINI: DEFAULT_GEMINI_ENDPOINT,
}.get(self._provider, DEFAULT_OPENAI_ENDPOINT) }.get(self._provider, DEFAULT_OPENAI_ENDPOINT)
# Выбор модели по умолчанию по провайдеру # Selecting the default model by provider
default_model = DEFAULT_DEEPSEEK_MODEL if self._provider == API_PROVIDER_DEEPSEEK else DEFAULT_MODEL default_model = (
DEFAULT_DEEPSEEK_MODEL if self._provider == API_PROVIDER_DEEPSEEK else
DEFAULT_GEMINI_MODEL if self._provider == API_PROVIDER_GEMINI else
DEFAULT_MODEL
)
return self.async_show_form( return self.async_show_form(
step_id="provider", step_id="provider",
@@ -256,7 +264,11 @@ class HATextAIConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
unique_id = f"{DOMAIN}_{normalized_name}_{self._provider}".lower() unique_id = f"{DOMAIN}_{normalized_name}_{self._provider}".lower()
default_model = DEFAULT_DEEPSEEK_MODEL if self._provider == API_PROVIDER_DEEPSEEK else DEFAULT_MODEL default_model = (
DEFAULT_DEEPSEEK_MODEL if self._provider == API_PROVIDER_DEEPSEEK else
DEFAULT_GEMINI_MODEL if self._provider == API_PROVIDER_GEMINI else
DEFAULT_MODEL
)
entry_data = { entry_data = {
CONF_API_PROVIDER: self._provider, CONF_API_PROVIDER: self._provider,
@@ -304,6 +316,13 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
return self.async_create_entry(title="", data=user_input) return self.async_create_entry(title="", data=user_input)
current_data = {**self.config_entry.data, **self.config_entry.options} current_data = {**self.config_entry.data, **self.config_entry.options}
provider = current_data.get(CONF_API_PROVIDER)
default_model = (
DEFAULT_DEEPSEEK_MODEL if provider == API_PROVIDER_DEEPSEEK else
DEFAULT_GEMINI_MODEL if provider == API_PROVIDER_GEMINI else
DEFAULT_MODEL
)
return self.async_show_form( return self.async_show_form(
step_id="init", step_id="init",
+7 -1
View File
@@ -12,6 +12,8 @@ from typing import Final
import voluptuous as vol import voluptuous as vol
from homeassistant.const import Platform, CONF_API_KEY, CONF_NAME from homeassistant.const import Platform, CONF_API_KEY, CONF_NAME
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv
import logging
_LOGGER = logging.getLogger(__name__)
# Domain and platforms # Domain and platforms
DOMAIN: Final = "ha_text_ai" DOMAIN: Final = "ha_text_ai"
@@ -22,11 +24,13 @@ CONF_API_PROVIDER: Final = "api_provider"
API_PROVIDER_OPENAI: Final = "openai" API_PROVIDER_OPENAI: Final = "openai"
API_PROVIDER_ANTHROPIC: Final = "anthropic" API_PROVIDER_ANTHROPIC: Final = "anthropic"
API_PROVIDER_DEEPSEEK: Final = "deepseek" API_PROVIDER_DEEPSEEK: Final = "deepseek"
API_PROVIDER_GEMINI: Final = "gemini"
API_PROVIDERS: Final = [ API_PROVIDERS: Final = [
API_PROVIDER_OPENAI, API_PROVIDER_OPENAI,
API_PROVIDER_ANTHROPIC, API_PROVIDER_ANTHROPIC,
API_PROVIDER_DEEPSEEK API_PROVIDER_DEEPSEEK,
API_PROVIDER_GEMINI
] ]
# Read version from manifest.json # Read version from manifest.json
@@ -49,6 +53,7 @@ except Exception as err:
DEFAULT_OPENAI_ENDPOINT: Final = "https://api.openai.com/v1" DEFAULT_OPENAI_ENDPOINT: Final = "https://api.openai.com/v1"
DEFAULT_ANTHROPIC_ENDPOINT: Final = "https://api.anthropic.com" DEFAULT_ANTHROPIC_ENDPOINT: Final = "https://api.anthropic.com"
DEFAULT_DEEPSEEK_ENDPOINT: Final = "https://api.deepseek.com" DEFAULT_DEEPSEEK_ENDPOINT: Final = "https://api.deepseek.com"
DEFAULT_GEMINI_ENDPOINT: Final = "https://generativelanguage.googleapis.com/v1beta"
# Configuration constants # Configuration constants
CONF_MODEL: Final = "model" CONF_MODEL: Final = "model"
@@ -69,6 +74,7 @@ ICONS_SUBDOMAIN = "icons"
# Default values # Default values
DEFAULT_MODEL: Final = "gpt-4o-mini" DEFAULT_MODEL: Final = "gpt-4o-mini"
DEFAULT_DEEPSEEK_MODEL: Final = "deepseek-chat" DEFAULT_DEEPSEEK_MODEL: Final = "deepseek-chat"
DEFAULT_GEMINI_MODEL: Final = "gemini-pro"
DEFAULT_TEMPERATURE: Final = 0.1 DEFAULT_TEMPERATURE: Final = 0.1
DEFAULT_MAX_TOKENS: Final = 1000 DEFAULT_MAX_TOKENS: Final = 1000
DEFAULT_REQUEST_INTERVAL: Final = 1.0 DEFAULT_REQUEST_INTERVAL: Final = 1.0
+2 -1
View File
@@ -16,6 +16,7 @@
"requirements": [ "requirements": [
"openai>=1.12.0", "openai>=1.12.0",
"anthropic>=0.8.0", "anthropic>=0.8.0",
"google-generativeai>=0.3.0",
"aiohttp>=3.8.0", "aiohttp>=3.8.0",
"async-timeout>=4.0.0", "async-timeout>=4.0.0",
"certifi>=2024.2.2" "certifi>=2024.2.2"
@@ -23,6 +24,6 @@
"single_config_entry": false, "single_config_entry": false,
"ssdp": [], "ssdp": [],
"usb": [], "usb": [],
"version": "2.1.1", "version": "2.1.6",
"zeroconf": [] "zeroconf": []
} }
+2 -2
View File
@@ -63,13 +63,13 @@ ask_question:
max_tokens: max_tokens:
name: Max Tokens name: Max Tokens
description: Maximum length of the response (1-4096 tokens) description: Maximum length of the response (tokens)
required: false required: false
default: 1000 default: 1000
selector: selector:
number: number:
min: 1 min: 1
max: 4096 max: 100000
step: 1 step: 1
mode: box mode: box
@@ -88,12 +88,13 @@
"selector": { "selector": {
"api_provider": { "api_provider": {
"options": { "options": {
"openai": "OpenAI (kompatibel)", "openai": "OpenAI (compatible)",
"anthropic": "Anthropic (kompatibel)", "anthropic": "Anthropic (compatible)",
"deepseek": "DeepSeek" "deepseek": "DeepSeek",
} "gemini": "Google Gemini"
} }
}, }
},
"services": { "services": {
"ask_question": { "ask_question": {
"name": "Frage stellen (HA Text AI)", "name": "Frage stellen (HA Text AI)",
@@ -86,11 +86,12 @@
} }
}, },
"selector": { "selector": {
"api_provider": { "api_provider": {
"options": { "options": {
"openai": "OpenAI (compatible)", "openai": "OpenAI (compatible)",
"anthropic": "Anthropic (compatible)", "anthropic": "Anthropic (compatible)",
"deepseek": "DeepSeek" "deepseek": "DeepSeek",
"gemini": "Google Gemini"
} }
} }
}, },
@@ -90,10 +90,11 @@
"options": { "options": {
"openai": "OpenAI (compatible)", "openai": "OpenAI (compatible)",
"anthropic": "Anthropic (compatible)", "anthropic": "Anthropic (compatible)",
"deepseek": "DeepSeek" "deepseek": "DeepSeek",
} "gemini": "Google Gemini"
} }
}, }
},
"services": { "services": {
"ask_question": { "ask_question": {
"name": "Hacer Pregunta (HA Text AI)", "name": "Hacer Pregunta (HA Text AI)",
@@ -90,7 +90,8 @@
"options": { "options": {
"openai": "OpenAI (अनुकूलित)", "openai": "OpenAI (अनुकूलित)",
"anthropic": "Anthropic (अनुकूलित)", "anthropic": "Anthropic (अनुकूलित)",
"deepseek": "DeepSeek" "deepseek": "DeepSeek",
"gemini": "Google Gemini"
} }
} }
}, },
@@ -90,7 +90,8 @@
"options": { "options": {
"openai": "OpenAI (compatibile)", "openai": "OpenAI (compatibile)",
"anthropic": "Anthropic (compatibile)", "anthropic": "Anthropic (compatibile)",
"deepseek": "DeepSeek" "deepseek": "DeepSeek",
"gemini": "Google Gemini"
} }
} }
}, },
@@ -90,7 +90,8 @@
"options": { "options": {
"openai": "OpenAI (совместимый)", "openai": "OpenAI (совместимый)",
"anthropic": "Anthropic (совместимый)", "anthropic": "Anthropic (совместимый)",
"deepseek": "DeepSeek" "deepseek": "DeepSeek",
"gemini": "Google Gemini"
} }
} }
}, },
@@ -90,7 +90,8 @@
"options": { "options": {
"openai": "OpenAI (компатибилан)", "openai": "OpenAI (компатибилан)",
"anthropic": "Anthropic (компатибилан)", "anthropic": "Anthropic (компатибилан)",
"deepseek": "DeepSeek" "deepseek": "DeepSeek",
"gemini": "Google Gemini"
} }
} }
}, },
@@ -90,7 +90,8 @@
"options": { "options": {
"openai": "OpenAI(兼容)", "openai": "OpenAI(兼容)",
"anthropic": "Anthropic(兼容)", "anthropic": "Anthropic(兼容)",
"deepseek": "DeepSeek " "deepseek": "DeepSeek",
"gemini": "Google Gemini"
} }
} }
}, },
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
"name": "HA text AI", "name": "HA Text AI",
"render_readme": true, "render_readme": true,
"homeassistant": "2024.11.0" "homeassistant": "2024.11.0"
} }