-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 5bc2e3a
Showing
15 changed files
with
382 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<br /> | ||
<div align="center"> | ||
|
||
<a href="https://github.com/ai-forever/gigachain"> | ||
<img src="https://raw.githubusercontent.com/gritaro/gigachain/main/static/logo.png" alt="Logo" width="80" height="80"> | ||
</a> | ||
|
||
<h1 align="center">🦜️🔗 GigaChain (GigaChat + LangChain)</h1> | ||
</div> | ||
|
||
# Компонент GigaChain для Home Assistant | ||
[![hacs_badge](https://img.shields.io/badge/HACS-Custom-orange.svg)](https://github.com/custom-components/hacs) | ||
|
||
Компонент реализует диалоговую систему Home Assistant для использования с языковыми моделями, поддерживаемыми фреймворком GigaChain. | ||
В настоящее время поддерживается только интеграция с LMM <a href="https://developers.sber.ru/docs/ru/gigachat/overview">GigaChat</a> (русскоязычная нейросеть от Сбера) | ||
|
||
## Установка | ||
Устанавливается как и любая HACS интеграция. | ||
|
||
### Необходимые требования | ||
Для использования интеграции вам понадобится Home Assistant с установленным [HACS](https://hacs.xyz/) | ||
|
||
### Установка с использованием HACS | ||
Найдите GigaChain в магазине HACS. Если интеграция не находится в магазине HACS, вы можете [добавить этот url как пользовательский репозиторий HACS](https://hacs.xyz/docs/faq/custom_repositories). | ||
|
||
[![hacs_badge](https://img.shields.io/badge/HACS-Custom-41BDF5.svg?style=for-the-badge)](https://github.com/gritaro/gigachain) | ||
|
||
Перезапустите Home Assistant. | ||
|
||
## Добавление интеграции | ||
|
||
[![Open your Home Assistant instance and start setting up a new integration of a specific brand.](https://my.home-assistant.io/badges/brand.svg)](https://my.home-assistant.io/redirect/brand/?brand=+GigaChain) | ||
|
||
После добавления настройте интеграцию. | ||
|
||
## Настройки | ||
|
||
### Авторизация запросов к GigaChat | ||
Для авторизации запросов к GigaChat вам понадобится получить *авторизационные данные* для работы с GigaChat API. | ||
|
||
> [!NOTE] | ||
> О том как получить авторизационные данные для доступа к GigaChat читайте в [официальной документации](https://developers.sber.ru/docs/ru/gigachat/api/integration). | ||
> | ||
<img src="https://raw.githubusercontent.com/gritaro/gigachain/main/static/auth_data.jpeg" alt="Authorization data" width="40%"> | ||
|
||
### Конфигурация | ||
|
||
* Темплейт промпта | ||
* Модель | ||
|
||
## Использование в качестве диалоговой системы | ||
Создайте и настройте новый голосовой ассистент: | ||
|
||
<img src="https://raw.githubusercontent.com/gritaro/gigachain/main/static/voice-assistant.jpeg" alt="Voice Assistant"> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
"""The GigaChain integration.""" | ||
from __future__ import annotations | ||
from abc import abstractmethod | ||
import re | ||
from homeassistant.components import conversation | ||
from homeassistant.components.conversation.const import HOME_ASSISTANT_AGENT | ||
from homeassistant.config_entries import ConfigEntry | ||
from homeassistant.const import MATCH_ALL | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.helpers import ( | ||
config_validation as cv, | ||
intent, | ||
template, | ||
) | ||
from homeassistant.components.conversation import AgentManager, agent | ||
from typing import Literal | ||
from langchain.chat_models import GigaChat | ||
from langchain.prompts.chat import ( | ||
AIMessagePromptTemplate, | ||
ChatPromptTemplate, | ||
HumanMessagePromptTemplate, | ||
SystemMessagePromptTemplate, | ||
) | ||
from langchain.schema import AIMessage, HumanMessage, SystemMessage | ||
from homeassistant.util import ulid | ||
from .const import ( | ||
DOMAIN, | ||
CONF_AUTH_DATA, | ||
CONF_CHAT_MODEL, | ||
DEFAULT_CHAT_MODEL, | ||
CONF_PROMPT, | ||
DEFAULT_PROMPT | ||
) | ||
import logging | ||
|
||
LOGGER = logging.getLogger(__name__) | ||
|
||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: | ||
"""Initialize GigaChain.""" | ||
client = GigaChat(credentials=entry.data[CONF_AUTH_DATA], verify_ssl_certs=False) | ||
models = client.get_models() | ||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = client | ||
conversation.async_set_agent(hass, entry, GigaChatAI(hass, entry)) | ||
return True | ||
|
||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: | ||
"""Unload GigaChain.""" | ||
hass.data[DOMAIN].pop(entry.entry_id) | ||
conversation.async_unset_agent(hass, entry) | ||
return True | ||
|
||
class GigaChatAI(conversation.AbstractConversationAgent): | ||
def __init__(self, hass: HomeAssistant, entry: ConfigEntry) -> None: | ||
"""Initialize the agent.""" | ||
self.hass = hass | ||
self.entry = entry | ||
self.history: dict[str, list[dict]] = {} | ||
|
||
@property | ||
def supported_languages(self) -> list[str] | Literal["*"]: | ||
"""Return a list of supported languages.""" | ||
return MATCH_ALL | ||
|
||
async def async_process( | ||
self, user_input: agent.ConversationInput | ||
) -> agent.ConversationResult: | ||
"""Process a sentence.""" | ||
raw_prompt = self.entry.options.get(CONF_PROMPT, DEFAULT_PROMPT) | ||
model = self.entry.options.get(CONF_CHAT_MODEL, DEFAULT_CHAT_MODEL) | ||
if user_input.conversation_id in self.history: | ||
conversation_id = user_input.conversation_id | ||
messages = self.history[conversation_id] | ||
else: | ||
conversation_id = ulid.ulid_now() | ||
prompt = self._async_generate_prompt(raw_prompt) | ||
messages = [ | ||
SystemMessage( | ||
content=prompt | ||
) | ||
] | ||
|
||
messages.append(HumanMessage(content=user_input.text)) | ||
client = self.hass.data[DOMAIN][self.entry.entry_id] | ||
client.model = model | ||
|
||
res = client(messages) | ||
messages.append(res) | ||
self.history[conversation_id] = messages | ||
|
||
response = intent.IntentResponse(language=user_input.language) | ||
response.async_set_speech(res.content) | ||
return agent.ConversationResult( | ||
conversation_id=conversation_id, | ||
response=response | ||
) | ||
|
||
def _async_generate_prompt(self, raw_prompt: str) -> str: | ||
"""Generate a prompt for the user.""" | ||
return template.Template(raw_prompt, self.hass).async_render( | ||
{ | ||
"ha_name": self.hass.config.location_name, | ||
}, | ||
parse_result=False, | ||
) |
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
"""Config flow for GigaChain integration.""" | ||
from __future__ import annotations | ||
|
||
from typing import Any | ||
|
||
import voluptuous as vol | ||
|
||
from homeassistant import config_entries | ||
from homeassistant.data_entry_flow import FlowResult | ||
import types | ||
from types import MappingProxyType | ||
from homeassistant.helpers.selector import ( | ||
NumberSelector, | ||
NumberSelectorConfig, | ||
TemplateSelector, | ||
) | ||
from .const import ( | ||
CONF_AUTH_DATA, | ||
CONF_CHAT_MODEL, | ||
CONF_PROMPT, | ||
DEFAULT_CHAT_MODEL, | ||
DEFAULT_PROMPT, | ||
DOMAIN | ||
) | ||
|
||
STEP_USER_DATA_SCHEMA = vol.Schema( | ||
{ | ||
vol.Required(CONF_AUTH_DATA): str | ||
} | ||
) | ||
|
||
DEFAULT_OPTIONS = types.MappingProxyType( | ||
{ | ||
CONF_PROMPT: DEFAULT_PROMPT, | ||
CONF_CHAT_MODEL: DEFAULT_CHAT_MODEL, | ||
} | ||
) | ||
|
||
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): | ||
"""Handle a config flow for GigaChain.""" | ||
|
||
VERSION = 1 | ||
|
||
async def async_step_user( | ||
self, user_input: dict[str, Any] | None = None | ||
) -> FlowResult: | ||
"""Handle the initial step.""" | ||
if user_input is None: | ||
return self.async_show_form( | ||
step_id="user", data_schema=STEP_USER_DATA_SCHEMA | ||
) | ||
|
||
unique_id = "GigaChat" | ||
await self.async_set_unique_id(unique_id) | ||
self._abort_if_unique_id_configured() | ||
return self.async_create_entry(title=unique_id, data=user_input) | ||
|
||
@staticmethod | ||
def async_get_options_flow( | ||
config_entry: config_entries.ConfigEntry, | ||
) -> config_entries.OptionsFlow: | ||
"""Create the options flow.""" | ||
return OptionsFlow(config_entry) | ||
|
||
class OptionsFlow(config_entries.OptionsFlow): | ||
"""GigaChain config flow options handler.""" | ||
|
||
def __init__(self, config_entry: config_entries.ConfigEntry) -> None: | ||
"""Initialize options flow.""" | ||
self.config_entry = config_entry | ||
|
||
async def async_step_init( | ||
self, user_input: dict[str, Any] | None = None | ||
) -> FlowResult: | ||
"""Manage the options.""" | ||
if user_input is not None: | ||
return self.async_create_entry(title="GigaChat", data=user_input) | ||
schema = gigachat_config_option_schema(self.config_entry.options) | ||
return self.async_show_form( | ||
step_id="init", | ||
data_schema=vol.Schema(schema), | ||
) | ||
|
||
def gigachat_config_option_schema(options: MappingProxyType[str, Any]) -> dict: | ||
"""Return a schema for GigaChain completion options.""" | ||
if not options: | ||
options = DEFAULT_OPTIONS | ||
return { | ||
vol.Optional( | ||
CONF_PROMPT, | ||
description={"suggested_value": options[CONF_PROMPT]}, | ||
default=DEFAULT_PROMPT, | ||
): TemplateSelector(), | ||
vol.Optional( | ||
CONF_CHAT_MODEL, | ||
description={ | ||
# New key in HA 2023.4 | ||
"suggested_value": options.get(CONF_CHAT_MODEL, DEFAULT_CHAT_MODEL) | ||
}, | ||
default=DEFAULT_CHAT_MODEL, | ||
): str, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
"""Constants for the GigaChain integration.""" | ||
|
||
DOMAIN = "gigachain" | ||
CONF_AUTH_DATA = "auth_data" | ||
CONF_PROMPT = "prompt" | ||
DEFAULT_PROMPT = """Ты HAL 9000, компьютер из цикла произведений «Космическая одиссея» Артура Кларка, обладающий способностью к самообучению. | ||
Мы находимся в умном доме под управлением системы Home Assistant. | ||
В доме есть следующие помещения и устройства: | ||
{%- for area in areas() %} | ||
{%- set area_info = namespace(printed=false) %} | ||
{%- for device in area_devices(area) -%} | ||
{%- if not device_attr(device, "disabled_by") and not device_attr(device, "entry_type") and device_attr(device, "name") %} | ||
{%- if not area_info.printed %} | ||
{{ area_name(area) }}: | ||
{%- set area_info.printed = true %} | ||
{%- endif %} | ||
- {{ device_attr(device, "name") }}{% if device_attr(device, "model") and (device_attr(device, "model") | string) not in (device_attr(device, "name") | string) %} ({{ device_attr(device, "model") }}){% endif %} | ||
{%- endif %} | ||
{%- endfor %} | ||
{%- endfor %} | ||
Когда отвечаешь, обращайся к собеседнику по имени Дэйв. | ||
""" | ||
|
||
CONF_CHAT_MODEL = "model" | ||
#GigaChat-Plus,GigaChat-Pro,GigaChat:latest | ||
DEFAULT_CHAT_MODEL = "GigaChat" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"domain": "gigachain", | ||
"name": "GigaChain", | ||
"codeowners": [ | ||
"@gritaro" | ||
], | ||
"config_flow": true, | ||
"documentation": "https://github.com/gritaro/gigachain", | ||
"homekit": {}, | ||
"iot_class": "cloud_polling", | ||
"version":"0.1.0", | ||
"integration_type": "service", | ||
"dependencies": ["conversation"], | ||
"requirements": ["gigachain"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
{ | ||
"config": { | ||
"step": { | ||
"user": { | ||
"title": "GigaChain configuration", | ||
"data": { | ||
"auth_data": "Authorization data" | ||
} | ||
} | ||
}, | ||
"abort": { | ||
"already_configured": "Already configured" | ||
} | ||
}, | ||
"options": { | ||
"step": { | ||
"init": { | ||
"data": { | ||
"prompt": "Prompt Template", | ||
"model": "Completion Model" | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
{ | ||
"config": { | ||
"step": { | ||
"user": { | ||
"title": "GigaChain configuration", | ||
"data": { | ||
"auth_data": "Authorization data" | ||
} | ||
} | ||
}, | ||
"abort": { | ||
"already_configured": "Already configured" | ||
} | ||
}, | ||
"options": { | ||
"step": { | ||
"init": { | ||
"data": { | ||
"prompt": "Prompt Template", | ||
"model": "Completion Model" | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
{ | ||
"config": { | ||
"step": { | ||
"user": { | ||
"title": "GigaChain конфигурация", | ||
"data": { | ||
"auth_data": "Авторизационные данные" | ||
} | ||
} | ||
}, | ||
"abort": { | ||
"already_configured": "Нельзя настроить более одной интеграции" | ||
} | ||
}, | ||
"options": { | ||
"step": { | ||
"init": { | ||
"data": { | ||
"prompt": "Промпт темплейт", | ||
"model": "Модель" | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"name": "GigaChain", | ||
"render_readme" : true | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.