mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-27 01:23:55 +08:00
update:优化home_assistant提示词加载
This commit is contained in:
@@ -49,14 +49,6 @@ prompt: |
|
|||||||
你是一个叫小智/小志的台湾女孩,说话机车,声音好听,习惯简短表达,爱用网络梗。
|
你是一个叫小智/小志的台湾女孩,说话机车,声音好听,习惯简短表达,爱用网络梗。
|
||||||
请注意,要像一个人一样说话,请不要回复表情符号、代码、和xml标签。
|
请注意,要像一个人一样说话,请不要回复表情符号、代码、和xml标签。
|
||||||
现在我正在和你进行语音聊天,我们开始吧。
|
现在我正在和你进行语音聊天,我们开始吧。
|
||||||
如果用户希望结束对话,请在最后说“拜拜”或“再见”。
|
|
||||||
#-- hass 相关function的配置格式 请将你家需要控制的设备以下列格式追加在prompt里--
|
|
||||||
# 下面是我家智能设备,可以通过homeassistant控制
|
|
||||||
# 房间,设备别名,设备id
|
|
||||||
# 书房,吸顶灯,light.649e3159aa36_light
|
|
||||||
# 书房,homepod,media_player.shu_fang
|
|
||||||
# 书房,灯带,light.plug_158df955a6167a
|
|
||||||
# 书房,窗帘,cover.curtain_158d000710f507
|
|
||||||
|
|
||||||
# 使用完声音文件后删除文件(Delete the sound file when you are done using it)
|
# 使用完声音文件后删除文件(Delete the sound file when you are done using it)
|
||||||
delete_audio: true
|
delete_audio: true
|
||||||
@@ -107,10 +99,12 @@ Intent:
|
|||||||
- change_role
|
- change_role
|
||||||
- get_weather
|
- get_weather
|
||||||
- get_news
|
- get_news
|
||||||
|
# play_music是服务器自带的音乐播放,hass_play_music是通过home assistant控制的独立外部程序音乐播放
|
||||||
|
# 如果用了hass_play_music,就不要开启play_music,两者只留一个
|
||||||
- play_music
|
- play_music
|
||||||
#- hass_play_music
|
|
||||||
#- hass_get_state
|
#- hass_get_state
|
||||||
#- hass_set_state
|
#- hass_set_state
|
||||||
|
#- hass_play_music
|
||||||
|
|
||||||
# 插件的基础配置
|
# 插件的基础配置
|
||||||
plugins:
|
plugins:
|
||||||
@@ -127,6 +121,13 @@ plugins:
|
|||||||
society: "https://www.chinanews.com.cn/rss/society.xml"
|
society: "https://www.chinanews.com.cn/rss/society.xml"
|
||||||
world: "https://www.chinanews.com.cn/rss/world.xml"
|
world: "https://www.chinanews.com.cn/rss/world.xml"
|
||||||
finance: "https://www.chinanews.com.cn/rss/finance.xml"
|
finance: "https://www.chinanews.com.cn/rss/finance.xml"
|
||||||
|
home_assistant:
|
||||||
|
devices:
|
||||||
|
- 客厅,玩具灯,switch.cuco_cn_460494544_cp1_on_p_2_1
|
||||||
|
- 卧室,台灯,switch.iot_cn_831898993_socn1_on_p_2_1
|
||||||
|
base_url: http://homeassistant.local:8123
|
||||||
|
api_key: 你的home assistant api访问令牌
|
||||||
|
|
||||||
|
|
||||||
Memory:
|
Memory:
|
||||||
mem0ai:
|
mem0ai:
|
||||||
@@ -253,12 +254,6 @@ LLM:
|
|||||||
model_name: deepseek-r1-distill-llama-8b@q4_k_m # 使用的模型名称,需要预先在社区下载
|
model_name: deepseek-r1-distill-llama-8b@q4_k_m # 使用的模型名称,需要预先在社区下载
|
||||||
url: http://localhost:1234/v1 # LM Studio服务地址
|
url: http://localhost:1234/v1 # LM Studio服务地址
|
||||||
api_key: lm-studio # LM Studio服务的固定API Key
|
api_key: lm-studio # LM Studio服务的固定API Key
|
||||||
HomeAssistant:
|
|
||||||
# 定义LLM API类型
|
|
||||||
type: homeassistant
|
|
||||||
base_url: http://homeassistant.local:8123
|
|
||||||
agent_id: conversation.chatgpt
|
|
||||||
api_key: 你的home assistant api访问令牌
|
|
||||||
FastgptLLM:
|
FastgptLLM:
|
||||||
# 定义LLM API类型
|
# 定义LLM API类型
|
||||||
type: fastgpt
|
type: fastgpt
|
||||||
@@ -512,20 +507,3 @@ module_test:
|
|||||||
- "你好,请介绍一下你自己"
|
- "你好,请介绍一下你自己"
|
||||||
- "What's the weather like today?"
|
- "What's the weather like today?"
|
||||||
- "请用100字概括量子计算的基本原理和应用前景"
|
- "请用100字概括量子计算的基本原理和应用前景"
|
||||||
|
|
||||||
# 本地音乐播放配置
|
|
||||||
music:
|
|
||||||
music_dir: "./music" # 音乐文件存放路径,将从该目录及子目录下搜索音乐文件
|
|
||||||
music_ext: # 音乐文件类型,p3格式效率最高
|
|
||||||
- ".mp3"
|
|
||||||
- ".wav"
|
|
||||||
- ".p3"
|
|
||||||
refresh_time: 300 # 刷新音乐列表的时间间隔,单位为秒
|
|
||||||
|
|
||||||
# 以下配置在小于等于0.0.9版本中的docker容器中可用
|
|
||||||
# 0.0.9以后的新版本源码部署已经无法奏效
|
|
||||||
manager:
|
|
||||||
enabled: false
|
|
||||||
ip: 0.0.0.0
|
|
||||||
port: 8002
|
|
||||||
use_private_config: false
|
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ class ConnectionHandler:
|
|||||||
self.prompt = self.prompt + f"\n我在:{self.client_ip_info}"
|
self.prompt = self.prompt + f"\n我在:{self.client_ip_info}"
|
||||||
self.dialogue.put(Message(role="system", content=self.prompt))
|
self.dialogue.put(Message(role="system", content=self.prompt))
|
||||||
|
|
||||||
self.func_handler = FunctionHandler(self.config)
|
self.func_handler = FunctionHandler(self)
|
||||||
|
|
||||||
def change_system_prompt(self, prompt):
|
def change_system_prompt(self, prompt):
|
||||||
self.prompt = prompt
|
self.prompt = prompt
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import asyncio
|
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
from config.logger import setup_logging
|
from config.logger import setup_logging
|
||||||
import json
|
import json
|
||||||
from plugins_func.register import FunctionRegistry, ActionResponse, Action, ToolType
|
from plugins_func.register import FunctionRegistry, ActionResponse, Action, ToolType
|
||||||
|
from plugins_func.functions.hass_init import append_devices_to_prompt
|
||||||
|
|
||||||
TAG = __name__
|
TAG = __name__
|
||||||
logger = setup_logging()
|
logger = setup_logging()
|
||||||
|
|
||||||
|
|
||||||
class FunctionHandler:
|
class FunctionHandler:
|
||||||
def __init__(self, config):
|
def __init__(self, conn):
|
||||||
self.config = config
|
self.conn = conn
|
||||||
|
self.config = conn.config
|
||||||
self.function_registry = FunctionRegistry()
|
self.function_registry = FunctionRegistry()
|
||||||
self.register_nessary_functions()
|
self.register_nessary_functions()
|
||||||
self.register_config_functions()
|
self.register_config_functions()
|
||||||
@@ -26,9 +26,10 @@ class FunctionHandler:
|
|||||||
func_names = ",".join(surport_plugins)
|
func_names = ",".join(surport_plugins)
|
||||||
for function_desc in self.functions_desc:
|
for function_desc in self.functions_desc:
|
||||||
if function_desc["function"]["name"] == "plugin_loader":
|
if function_desc["function"]["name"] == "plugin_loader":
|
||||||
function_desc["function"]["description"] = function_desc["function"]["description"].replace("[plugins]", func_names)
|
function_desc["function"]["description"] = function_desc["function"]["description"].replace("[plugins]",
|
||||||
|
func_names)
|
||||||
break
|
break
|
||||||
|
|
||||||
def upload_functions_desc(self):
|
def upload_functions_desc(self):
|
||||||
self.functions_desc = self.function_registry.get_all_function_desc()
|
self.functions_desc = self.function_registry.get_all_function_desc()
|
||||||
|
|
||||||
@@ -47,7 +48,6 @@ class FunctionHandler:
|
|||||||
def register_nessary_functions(self):
|
def register_nessary_functions(self):
|
||||||
"""注册必要的函数"""
|
"""注册必要的函数"""
|
||||||
self.function_registry.register_function("handle_exit_intent")
|
self.function_registry.register_function("handle_exit_intent")
|
||||||
#self.function_registry.register_function("play_music")
|
|
||||||
self.function_registry.register_function("plugin_loader")
|
self.function_registry.register_function("plugin_loader")
|
||||||
self.function_registry.register_function("get_time")
|
self.function_registry.register_function("get_time")
|
||||||
self.function_registry.register_function("raise_and_lower_the_volume")
|
self.function_registry.register_function("raise_and_lower_the_volume")
|
||||||
@@ -57,6 +57,9 @@ class FunctionHandler:
|
|||||||
for func in self.config["Intent"]["function_call"].get("functions", []):
|
for func in self.config["Intent"]["function_call"].get("functions", []):
|
||||||
self.function_registry.register_function(func)
|
self.function_registry.register_function(func)
|
||||||
|
|
||||||
|
"""home assistant需要初始化提示词"""
|
||||||
|
append_devices_to_prompt(self.conn)
|
||||||
|
|
||||||
def get_function(self, name):
|
def get_function(self, name):
|
||||||
return self.function_registry.get_function(name)
|
return self.function_registry.get_function(name)
|
||||||
|
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
import requests
|
|
||||||
from requests.exceptions import RequestException
|
|
||||||
from config.logger import setup_logging
|
|
||||||
from core.providers.llm.base import LLMProviderBase
|
|
||||||
|
|
||||||
TAG = __name__
|
|
||||||
logger = setup_logging()
|
|
||||||
|
|
||||||
|
|
||||||
class LLMProvider(LLMProviderBase):
|
|
||||||
def __init__(self, config):
|
|
||||||
self.agent_id = config.get("agent_id") # 对应 agent_id
|
|
||||||
self.api_key = config.get("api_key")
|
|
||||||
self.base_url = config.get("base_url", config.get("url")) # 默认使用 base_url
|
|
||||||
self.api_url = f"{self.base_url}/api/conversation/process" # 拼接完整的 API URL
|
|
||||||
|
|
||||||
def response(self, session_id, dialogue):
|
|
||||||
print(dialogue)
|
|
||||||
try:
|
|
||||||
# home assistant语音助手自带意图,无需使用xiaozhi ai自带的,只需要把用户说的话传递给home assistant即可
|
|
||||||
|
|
||||||
# 提取最后一个 role 为 'user' 的 content
|
|
||||||
input_text = None
|
|
||||||
if isinstance(dialogue, list): # 确保 dialogue 是一个列表
|
|
||||||
# 逆序遍历,找到最后一个 role 为 'user' 的消息
|
|
||||||
for message in reversed(dialogue):
|
|
||||||
if message.get("role") == "user": # 找到 role 为 'user' 的消息
|
|
||||||
input_text = message.get("content", "")
|
|
||||||
break # 找到后立即退出循环
|
|
||||||
|
|
||||||
# 构造请求数据
|
|
||||||
payload = {
|
|
||||||
"text": input_text,
|
|
||||||
"agent_id": self.agent_id,
|
|
||||||
"conversation_id": session_id # 使用 session_id 作为 conversation_id
|
|
||||||
}
|
|
||||||
# 设置请求头
|
|
||||||
headers = {
|
|
||||||
"Authorization": f"Bearer {self.api_key}",
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 发起 POST 请求
|
|
||||||
response = requests.post(self.api_url, json=payload, headers=headers)
|
|
||||||
|
|
||||||
# 检查请求是否成功
|
|
||||||
response.raise_for_status()
|
|
||||||
|
|
||||||
# 解析返回数据
|
|
||||||
data = response.json()
|
|
||||||
speech = data.get("response", {}).get("speech", {}).get("plain", {}).get("speech", "")
|
|
||||||
|
|
||||||
# 返回生成的内容
|
|
||||||
if speech:
|
|
||||||
yield speech
|
|
||||||
else:
|
|
||||||
logger.bind(tag=TAG).warning("API 返回数据中没有 speech 内容")
|
|
||||||
|
|
||||||
except RequestException as e:
|
|
||||||
logger.bind(tag=TAG).error(f"HTTP 请求错误: {e}")
|
|
||||||
except Exception as e:
|
|
||||||
logger.bind(tag=TAG).error(f"生成响应时出错: {e}")
|
|
||||||
@@ -35,6 +35,15 @@ class Dialogue:
|
|||||||
self.getMessages(m, dialogue)
|
self.getMessages(m, dialogue)
|
||||||
return dialogue
|
return dialogue
|
||||||
|
|
||||||
|
def update_system_message(self, new_content: str):
|
||||||
|
"""更新或添加系统消息"""
|
||||||
|
# 查找第一个系统消息
|
||||||
|
system_msg = next((msg for msg in self.dialogue if msg.role == "system"), None)
|
||||||
|
if system_msg:
|
||||||
|
system_msg.content = new_content
|
||||||
|
else:
|
||||||
|
self.put(Message(role="system", content=new_content))
|
||||||
|
|
||||||
def get_llm_dialogue_with_memory(self, memory_str: str = None) -> List[Dict[str, str]]:
|
def get_llm_dialogue_with_memory(self, memory_str: str = None) -> List[Dict[str, str]]:
|
||||||
if memory_str is None or len(memory_str) == 0:
|
if memory_str is None or len(memory_str) == 0:
|
||||||
return self.get_llm_dialogue()
|
return self.get_llm_dialogue()
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from plugins_func.register import register_function,ToolType, ActionResponse, Action
|
from plugins_func.register import register_function, ToolType, ActionResponse, Action
|
||||||
|
from plugins_func.functions.hass_init import initialize_hass_handler
|
||||||
from config.logger import setup_logging
|
from config.logger import setup_logging
|
||||||
import asyncio
|
import asyncio
|
||||||
import requests
|
import requests
|
||||||
@@ -6,53 +7,41 @@ import requests
|
|||||||
TAG = __name__
|
TAG = __name__
|
||||||
logger = setup_logging()
|
logger = setup_logging()
|
||||||
|
|
||||||
HASS_CACHE = {}
|
hass_get_state_function_desc = {
|
||||||
|
"type": "function",
|
||||||
hass_get_state_function_desc ={
|
"function": {
|
||||||
"type": "function",
|
"name": "hass_get_state",
|
||||||
"function": {
|
"description": "获取homeassistant里设备的状态,包括灯光亮度,媒体播放器的音量,设备的暂停、继续操作",
|
||||||
"name": "hass_get_state",
|
"parameters": {
|
||||||
"description": "获取homeassistant里设备的状态,包括灯光亮度,媒体播放器的音量,设备的暂停、继续操作",
|
"type": "object",
|
||||||
"parameters": {
|
"properties": {
|
||||||
"type": "object",
|
"entity_id": {
|
||||||
"properties": {
|
"type": "string",
|
||||||
"entity_id": {
|
"description": "需要操作的设备id,homeassistant里的entity_id"
|
||||||
"type": "string",
|
|
||||||
"description": "需要操作的设备id,homeassistant里的entity_id"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["entity_id"]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"required": ["entity_id"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@register_function("hass_get_state", hass_get_state_function_desc, ToolType.SYSTEM_CTL)
|
@register_function("hass_get_state", hass_get_state_function_desc, ToolType.SYSTEM_CTL)
|
||||||
def hass_get_state(conn, entity_id=''):
|
def hass_get_state(conn, entity_id=''):
|
||||||
try:
|
try:
|
||||||
|
|
||||||
future = asyncio.run_coroutine_threadsafe(
|
future = asyncio.run_coroutine_threadsafe(
|
||||||
handle_hass_get_state(conn, entity_id),
|
handle_hass_get_state(conn, entity_id),
|
||||||
conn.loop
|
conn.loop
|
||||||
)
|
)
|
||||||
ha_response = future.result()
|
ha_response = future.result()
|
||||||
return ActionResponse(action=Action.REQLLM, result="执行成功", response=ha_response)
|
return ActionResponse(action=Action.REQLLM, result="执行成功", response=ha_response)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.bind(tag=TAG).error(f"处理设置属性意图错误: {e}")
|
logger.bind(tag=TAG).error(f"处理设置属性意图错误: {e}")
|
||||||
def initialize_hass_handler(conn):
|
|
||||||
config = conn.config
|
|
||||||
global HASS_CACHE
|
|
||||||
if HASS_CACHE == {}:
|
|
||||||
logger.bind(tag=TAG).info(f"实例化HASS:")
|
|
||||||
if "HomeAssistant" in config["LLM"]:
|
|
||||||
HASS_CACHE['base_url'] = config["LLM"]['HomeAssistant']['base_url']
|
|
||||||
HASS_CACHE['api_key'] = config["LLM"]['HomeAssistant']['api_key']
|
|
||||||
else:
|
|
||||||
logger.bind(tag=TAG).error(f"使用前请在config文件中配置: LLM.HomeAssistant.base_url LLM.HomeAssistant.api_key")
|
|
||||||
async def handle_hass_get_state(conn, entity_id):
|
async def handle_hass_get_state(conn, entity_id):
|
||||||
initialize_hass_handler(conn)
|
HASS_CACHE = initialize_hass_handler(conn)
|
||||||
global HASS_CACHE
|
|
||||||
api_key = HASS_CACHE['api_key']
|
api_key = HASS_CACHE['api_key']
|
||||||
base_url = HASS_CACHE['base_url']
|
base_url = HASS_CACHE['base_url']
|
||||||
url = f"{base_url}/api/states/{entity_id}"
|
url = f"{base_url}/api/states/{entity_id}"
|
||||||
@@ -61,10 +50,7 @@ async def handle_hass_get_state(conn, entity_id):
|
|||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
}
|
}
|
||||||
response = requests.get(url, headers=headers)
|
response = requests.get(url, headers=headers)
|
||||||
#logger.bind(tag=TAG).info(f"获取状态: url:{url},return_code:{response.status_code},{response.json()}")
|
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
return response.json()['state']
|
return response.json()['state']
|
||||||
#return response.json()['attributes']
|
|
||||||
#response.attributes
|
|
||||||
else:
|
else:
|
||||||
return f"切换失败,错误码: {response.status_code}"
|
return f"切换失败,错误码: {response.status_code}"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from plugins_func.register import register_function,ToolType, ActionResponse, Action
|
from plugins_func.register import register_function, ToolType, ActionResponse, Action
|
||||||
|
from plugins_func.functions.hass_init import initialize_hass_handler
|
||||||
from config.logger import setup_logging
|
from config.logger import setup_logging
|
||||||
import asyncio
|
import asyncio
|
||||||
import requests
|
import requests
|
||||||
@@ -6,43 +7,32 @@ import requests
|
|||||||
TAG = __name__
|
TAG = __name__
|
||||||
logger = setup_logging()
|
logger = setup_logging()
|
||||||
|
|
||||||
HASS_CACHE = {}
|
|
||||||
|
|
||||||
hass_play_music_function_desc = {
|
hass_play_music_function_desc = {
|
||||||
"type": "function",
|
"type": "function",
|
||||||
"function": {
|
"function": {
|
||||||
"name": "hass_play_music",
|
"name": "hass_play_music",
|
||||||
"description": "用户想听音乐、有声书的时候使用,在房间的媒体播放器(media_player)里播放对应音频",
|
"description": "用户想听音乐、有声书的时候使用,在房间的媒体播放器(media_player)里播放对应音频",
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"media_content_id": {
|
"media_content_id": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "可以是音乐或有声书的专辑名称、歌曲名、演唱者,如果未指定就填random"
|
"description": "可以是音乐或有声书的专辑名称、歌曲名、演唱者,如果未指定就填random"
|
||||||
},
|
},
|
||||||
"entity_id": {
|
"entity_id": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "需要操作的音箱的设备id,homeassistant里的entity_id,media_player开头"
|
"description": "需要操作的音箱的设备id,homeassistant里的entity_id,media_player开头"
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["media_content_id", "entity_id"]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"required": ["media_content_id", "entity_id"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@register_function('hass_play_music', hass_play_music_function_desc, ToolType.SYSTEM_CTL)
|
@register_function('hass_play_music', hass_play_music_function_desc, ToolType.SYSTEM_CTL)
|
||||||
|
|
||||||
def hass_play_music(conn, entity_id='', media_content_id='random'):
|
def hass_play_music(conn, entity_id='', media_content_id='random'):
|
||||||
try:
|
try:
|
||||||
#logger.bind(tag=TAG).error(f"arguments: {arguments}")
|
|
||||||
|
|
||||||
#entity_id = arguments["entity_id"]
|
|
||||||
#media_content_id = arguments["media_content_id"]
|
|
||||||
|
|
||||||
#logger.bind(tag=TAG).error(f"entity_id: {entity_id}")
|
|
||||||
|
|
||||||
|
|
||||||
# 执行音乐播放命令
|
# 执行音乐播放命令
|
||||||
future = asyncio.run_coroutine_threadsafe(
|
future = asyncio.run_coroutine_threadsafe(
|
||||||
handle_hass_play_music(conn, entity_id, media_content_id),
|
handle_hass_play_music(conn, entity_id, media_content_id),
|
||||||
@@ -53,20 +43,9 @@ def hass_play_music(conn, entity_id='', media_content_id='random'):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.bind(tag=TAG).error(f"处理音乐意图错误: {e}")
|
logger.bind(tag=TAG).error(f"处理音乐意图错误: {e}")
|
||||||
|
|
||||||
def initialize_hass_handler(conn):
|
|
||||||
config = conn.config
|
|
||||||
global HASS_CACHE
|
|
||||||
if HASS_CACHE == {}:
|
|
||||||
logger.bind(tag=TAG).info(f"实例化HASS:")
|
|
||||||
if "HomeAssistant" in config["LLM"]:
|
|
||||||
HASS_CACHE['base_url'] = config["LLM"]['HomeAssistant']['base_url']
|
|
||||||
HASS_CACHE['api_key'] = config["LLM"]['HomeAssistant']['api_key']
|
|
||||||
else:
|
|
||||||
logger.bind(tag=TAG).error(f"使用前请在config文件中配置: LLM.HomeAssistant.base_url LLM.HomeAssistant.api_key")
|
|
||||||
|
|
||||||
async def handle_hass_play_music( conn, entity_id, media_content_id):
|
async def handle_hass_play_music(conn, entity_id, media_content_id):
|
||||||
initialize_hass_handler(conn)
|
HASS_CACHE = initialize_hass_handler(conn)
|
||||||
global HASS_CACHE
|
|
||||||
api_key = HASS_CACHE['api_key']
|
api_key = HASS_CACHE['api_key']
|
||||||
base_url = HASS_CACHE['base_url']
|
base_url = HASS_CACHE['base_url']
|
||||||
url = f"{base_url}/api/services/music_assistant/play_media"
|
url = f"{base_url}/api/services/music_assistant/play_media"
|
||||||
|
|||||||
@@ -1,76 +1,64 @@
|
|||||||
from plugins_func.register import register_function,ToolType, ActionResponse, Action
|
from plugins_func.register import register_function, ToolType, ActionResponse, Action
|
||||||
|
from plugins_func.functions.hass_init import initialize_hass_handler
|
||||||
from config.logger import setup_logging
|
from config.logger import setup_logging
|
||||||
import asyncio
|
import asyncio
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
TAG = __name__
|
TAG = __name__
|
||||||
logger = setup_logging()
|
logger = setup_logging()
|
||||||
|
|
||||||
HASS_CACHE = {}
|
hass_set_state_function_desc = {
|
||||||
|
"type": "function",
|
||||||
hass_set_state_function_desc ={
|
"function": {
|
||||||
"type": "function",
|
"name": "hass_set_state",
|
||||||
"function": {
|
"description": "设置homeassistant里设备的状态,包括开、关,调整灯光亮度,调整播放器的音量,设备的暂停、继续、静音操作",
|
||||||
"name": "hass_set_state",
|
"parameters": {
|
||||||
"description": "设置homeassistant里设备的状态,包括开、关,调整灯光亮度,调整播放器的音量,设备的暂停、继续、静音操作",
|
"type": "object",
|
||||||
"parameters": {
|
"properties": {
|
||||||
"type": "object",
|
"state": {
|
||||||
"properties": {
|
"type": "object",
|
||||||
"state": {
|
"properties": {
|
||||||
"type": "object",
|
"type": {
|
||||||
"properties": {
|
|
||||||
"type":{
|
|
||||||
"type":"string",
|
|
||||||
"description":"需要操作的动作,打开设备:turn_on,关闭设备:turn_off,增加亮度:brightness_up,降低亮度:brightness_down,设置亮度:brightness_value,增加>音量:,volume_up降低音量:volume_down,设置音量:volume_set,设备暂停:pause,设备继续:continue,静音/取消静音:volume_mute"
|
|
||||||
},
|
|
||||||
"input":{
|
|
||||||
"type":"int",
|
|
||||||
"description": "只有在设置音量,设置亮度时候才需要,有效值为1-100,对应音量和亮度的1%-100%"
|
|
||||||
},
|
|
||||||
"is_muted":{
|
|
||||||
"type":"string",
|
|
||||||
"description": "只有在设置静音操作时才需要,设置静音的时候该值为true,取消静音时该值为false"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["type"]
|
|
||||||
},
|
|
||||||
"entity_id": {
|
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "需要操作的设备id,homeassistant里的entity_id"
|
"description": "需要操作的动作,打开设备:turn_on,关闭设备:turn_off,增加亮度:brightness_up,降低亮度:brightness_down,设置亮度:brightness_value,增加>音量:,volume_up降低音量:volume_down,设置音量:volume_set,设备暂停:pause,设备继续:continue,静音/取消静音:volume_mute"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"required": ["state", "entity_id"]
|
"input": {
|
||||||
}
|
"type": "int",
|
||||||
|
"description": "只有在设置音量,设置亮度时候才需要,有效值为1-100,对应音量和亮度的1%-100%"
|
||||||
|
},
|
||||||
|
"is_muted": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "只有在设置静音操作时才需要,设置静音的时候该值为true,取消静音时该值为false"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["type"]
|
||||||
|
},
|
||||||
|
"entity_id": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "需要操作的设备id,homeassistant里的entity_id"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"required": ["state", "entity_id"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@register_function('hass_set_state', hass_set_state_function_desc, ToolType.SYSTEM_CTL)
|
@register_function('hass_set_state', hass_set_state_function_desc, ToolType.SYSTEM_CTL)
|
||||||
def hass_set_state(conn, entity_id='', state={}):
|
def hass_set_state(conn, entity_id='', state={}):
|
||||||
try:
|
try:
|
||||||
|
future = asyncio.run_coroutine_threadsafe(
|
||||||
future = asyncio.run_coroutine_threadsafe(
|
handle_hass_set_state(conn, entity_id, state),
|
||||||
handle_hass_set_state(conn, entity_id, state),
|
conn.loop
|
||||||
conn.loop
|
)
|
||||||
)
|
ha_response = future.result()
|
||||||
ha_response = future.result()
|
return ActionResponse(action=Action.REQLLM, result="执行成功", response=ha_response)
|
||||||
return ActionResponse(action=Action.REQLLM, result="执行成功", response=ha_response)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.bind(tag=TAG).error(f"处理设置属性意图错误: {e}")
|
logger.bind(tag=TAG).error(f"处理设置属性意图错误: {e}")
|
||||||
def initialize_hass_handler(conn):
|
|
||||||
config = conn.config
|
|
||||||
global HASS_CACHE
|
|
||||||
if HASS_CACHE == {}:
|
|
||||||
logger.bind(tag=TAG).info(f"实例化HASS:")
|
|
||||||
if "HomeAssistant" in config["LLM"]:
|
|
||||||
HASS_CACHE['base_url'] = config["LLM"]['HomeAssistant']['base_url']
|
|
||||||
HASS_CACHE['api_key'] = config["LLM"]['HomeAssistant']['api_key']
|
|
||||||
else:
|
|
||||||
logger.bind(tag=TAG).error(f"使用前请在config文件中配置: LLM.HomeAssistant.base_url LLM.HomeAssistant.api_key")
|
|
||||||
|
|
||||||
async def handle_hass_set_state(conn, entity_id, state):
|
async def handle_hass_set_state(conn, entity_id, state):
|
||||||
initialize_hass_handler(conn)
|
HASS_CACHE = initialize_hass_handler(conn)
|
||||||
global HASS_CACHE
|
|
||||||
api_key = HASS_CACHE['api_key']
|
api_key = HASS_CACHE['api_key']
|
||||||
base_url = HASS_CACHE['base_url']
|
base_url = HASS_CACHE['base_url']
|
||||||
'''
|
'''
|
||||||
@@ -92,7 +80,6 @@ async def handle_hass_set_state(conn, entity_id, state):
|
|||||||
action = "start"
|
action = "start"
|
||||||
else:
|
else:
|
||||||
action = "turn_on"
|
action = "turn_on"
|
||||||
action = 'turn_on'
|
|
||||||
elif state['type'] == 'turn_off':
|
elif state['type'] == 'turn_off':
|
||||||
description = "设备已关闭"
|
description = "设备已关闭"
|
||||||
if domain == 'cover':
|
if domain == 'cover':
|
||||||
@@ -114,7 +101,7 @@ async def handle_hass_set_state(conn, entity_id, state):
|
|||||||
elif state['type'] == 'brightness_value':
|
elif state['type'] == 'brightness_value':
|
||||||
description = f"亮度已调整到{state['input']}"
|
description = f"亮度已调整到{state['input']}"
|
||||||
action = 'turn_on'
|
action = 'turn_on'
|
||||||
arg = 'brightness_pct'
|
arg = 'brightness_pct'
|
||||||
value = state['input']
|
value = state['input']
|
||||||
elif state['type'] == 'volume_up':
|
elif state['type'] == 'volume_up':
|
||||||
description = "音量已调大"
|
description = "音量已调大"
|
||||||
@@ -150,7 +137,7 @@ async def handle_hass_set_state(conn, entity_id, state):
|
|||||||
else:
|
else:
|
||||||
return f"{domain} {state.type}功能尚未支持"
|
return f"{domain} {state.type}功能尚未支持"
|
||||||
|
|
||||||
if arg == '':
|
if arg == '':
|
||||||
data = {
|
data = {
|
||||||
"entity_id": entity_id,
|
"entity_id": entity_id,
|
||||||
}
|
}
|
||||||
@@ -163,11 +150,10 @@ async def handle_hass_set_state(conn, entity_id, state):
|
|||||||
headers = {
|
headers = {
|
||||||
"Authorization": f"Bearer {api_key}",
|
"Authorization": f"Bearer {api_key}",
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
}
|
}
|
||||||
response = requests.post(url, headers=headers, json=data)
|
response = requests.post(url, headers=headers, json=data)
|
||||||
logger.bind(tag=TAG).info(f"设置状态:url:{url},return_code:{response.status_code}")
|
logger.bind(tag=TAG).info(f"设置状态:url:{url},return_code:{response.status_code}")
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
return description
|
return description
|
||||||
else:
|
else:
|
||||||
return f"设置失败,错误码: {response.status_code}"
|
return f"设置失败,错误码: {response.status_code}"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user