-
+
@@ -48,14 +43,11 @@
新增
删除
+ @click="deleteSelectedParams">删除
@@ -91,9 +85,9 @@
import Api from "@/apis/api";
import HeaderBar from "@/components/HeaderBar.vue";
import ParamDialog from "@/components/ParamDialog.vue";
-
+import VersionFooter from "@/components/VersionFooter.vue";
export default {
- components: { HeaderBar, ParamDialog },
+ components: { HeaderBar, ParamDialog, VersionFooter },
data() {
return {
searchCode: "",
@@ -146,29 +140,29 @@ export default {
this.fetchParams();
},
fetchParams() {
- this.loading = true;
- Api.admin.getParamsList(
- {
- page: this.currentPage,
- limit: this.pageSize,
- paramCode: this.searchCode,
- },
- ({ data }) => {
- this.loading = false;
- if (data.code === 0) {
- this.paramsList = data.data.list.map(item => ({
- ...item,
- selected: false
- }));
- this.total = data.data.total;
- } else {
- this.$message.error({
- message: data.msg || '获取参数列表失败',
- showClose: true
- });
- }
- }
- );
+ this.loading = true;
+ Api.admin.getParamsList(
+ {
+ page: this.currentPage,
+ limit: this.pageSize,
+ paramCode: this.searchCode,
+ },
+ ({ data }) => {
+ this.loading = false;
+ if (data.code === 0) {
+ this.paramsList = data.data.list.map(item => ({
+ ...item,
+ selected: false
+ }));
+ this.total = data.data.total;
+ } else {
+ this.$message.error({
+ message: data.msg || '获取参数列表失败',
+ showClose: true
+ });
+ }
+ }
+ );
},
handleSearch() {
this.currentPage = 1;
@@ -197,33 +191,33 @@ export default {
},
handleSubmit({ form, done }) {
- if (form.id) {
- // 编辑
- Api.admin.updateParam(form, ({ data }) => {
- if (data.code === 0) {
- this.$message.success({
- message:"修改成功",
- showClose:true
+ if (form.id) {
+ // 编辑
+ Api.admin.updateParam(form, ({ data }) => {
+ if (data.code === 0) {
+ this.$message.success({
+ message: "修改成功",
+ showClose: true
+ });
+ this.dialogVisible = false;
+ this.fetchParams();
+ }
+ done && done();
});
- this.dialogVisible = false;
- this.fetchParams();
- }
- done && done();
- });
- } else {
- // 新增
- Api.admin.addParam(form, ({ data }) => {
- if (data.code === 0) {
- this.$message.success({
- message:"新增成功",
- showClose:true
+ } else {
+ // 新增
+ Api.admin.addParam(form, ({ data }) => {
+ if (data.code === 0) {
+ this.$message.success({
+ message: "新增成功",
+ showClose: true
+ });
+ this.dialogVisible = false;
+ this.fetchParams();
+ }
+ done && done();
});
- this.dialogVisible = false;
- this.fetchParams();
- }
- done && done();
- });
- }
+ }
},
deleteSelectedParams() {
@@ -243,8 +237,8 @@ export default {
if (Array.isArray(row) && row.length === 0) {
this.$message.warning({
- message:"请先选择需要删除的参数",
- showClose:true
+ message: "请先选择需要删除的参数",
+ showClose: true
});
return;
}
@@ -259,8 +253,8 @@ export default {
const ids = params.map(param => param.id);
if (ids.some(id => isNaN(id))) {
this.$message.error({
- message:'存在无效的参数ID',
- showClose: true
+ message: '存在无效的参数ID',
+ showClose: true
});
return;
}
@@ -341,16 +335,16 @@ export default {
}
.main-wrapper {
- margin: 5px 22px;
- border-radius: 15px;
- min-height: calc(100vh - 24vh);
- height: auto;
- max-height: 80vh;
- box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
- position: relative;
- background: rgba(237, 242, 255, 0.5);
- display: flex;
- flex-direction: column;
+ margin: 5px 22px;
+ border-radius: 15px;
+ min-height: calc(100vh - 24vh);
+ height: auto;
+ max-height: 80vh;
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
+ position: relative;
+ background: rgba(237, 242, 255, 0.5);
+ display: flex;
+ flex-direction: column;
}
.operation-bar {
@@ -402,21 +396,21 @@ export default {
}
.params-card {
- background: white;
- flex: 1;
- display: flex;
- flex-direction: column;
- border: none;
- box-shadow: none;
- overflow: hidden;
-
- ::v-deep .el-card__body {
- padding: 15px;
+ background: white;
+ flex: 1;
display: flex;
flex-direction: column;
- flex: 1;
+ border: none;
+ box-shadow: none;
overflow: hidden;
- }
+
+ ::v-deep .el-card__body {
+ padding: 15px;
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+ overflow: hidden;
+ }
}
.table_bottom {
@@ -467,7 +461,7 @@ export default {
gap: 10px;
.el-select {
- margin-right: 8px;
+ margin-right: 8px;
}
.pagination-btn:first-child,
@@ -535,15 +529,17 @@ export default {
width: 100%;
display: flex;
flex-direction: column;
+
.el-table__body-wrapper {
- flex: 1;
- overflow-y: auto;
- max-height: none !important;
+ flex: 1;
+ overflow-y: auto;
+ max-height: none !important;
}
.el-table__header-wrapper {
- flex-shrink: 0;
+ flex-shrink: 0;
}
+
.el-table__header th {
background: white !important;
color: black;
@@ -670,32 +666,31 @@ export default {
}
.el-table {
- --table-max-height: calc(100vh - 40vh);
- max-height: var(--table-max-height);
+ --table-max-height: calc(100vh - 40vh);
+ max-height: var(--table-max-height);
- .el-table__body-wrapper {
- max-height: calc(var(--table-max-height) - 40px);
- }
+ .el-table__body-wrapper {
+ max-height: calc(var(--table-max-height) - 40px);
+ }
}
:deep(.el-loading-mask) {
- background-color: rgba(255, 255, 255, 0.6) !important;
- backdrop-filter: blur(2px);
+ background-color: rgba(255, 255, 255, 0.6) !important;
+ backdrop-filter: blur(2px);
}
:deep(.el-loading-spinner .circular) {
- width: 28px;
- height: 28px;
+ width: 28px;
+ height: 28px;
}
:deep(.el-loading-spinner .path) {
- stroke: #6b8cff;
+ stroke: #6b8cff;
}
:deep(.el-loading-text) {
- color: #6b8cff !important;
- font-size: 14px;
- margin-top: 8px;
+ color: #6b8cff !important;
+ font-size: 14px;
+ margin-top: 8px;
}
-
diff --git a/main/manager-web/src/views/UserManagement.vue b/main/manager-web/src/views/UserManagement.vue
index 1ca70422..eb43a959 100644
--- a/main/manager-web/src/views/UserManagement.vue
+++ b/main/manager-web/src/views/UserManagement.vue
@@ -15,18 +15,13 @@
-
+
-
-
-
+
+
+
@@ -61,11 +56,7 @@
+
+
+
-
-
\ No newline at end of file
diff --git a/main/manager-web/vue.config.js b/main/manager-web/vue.config.js
index e61c0628..1c2e6b04 100644
--- a/main/manager-web/vue.config.js
+++ b/main/manager-web/vue.config.js
@@ -39,7 +39,7 @@ const cdnResources = {
const useCDN = process.env.VUE_APP_USE_CDN === 'true';
module.exports = defineConfig({
- productionSourceMap: process.env.NODE_ENV === 'production' ? false : true, // 生产环境不生成 source map
+ productionSourceMap: process.env.NODE_ENV !=='production', // 生产环境不生成 source map
devServer: {
port: 8001, // 指定端口为 8001
proxy: {
@@ -52,6 +52,7 @@ module.exports = defineConfig({
overlay: false, // 不显示 webpack 错误覆盖层
},
},
+ publicPath: process.env.VUE_APP_PUBLIC_PATH || "",
chainWebpack: config => {
// 修改 HTML 插件配置,动态插入 CDN 链接
diff --git a/main/xiaozhi-server/config/config_loader.py b/main/xiaozhi-server/config/config_loader.py
index 49a66558..849a2a8a 100644
--- a/main/xiaozhi-server/config/config_loader.py
+++ b/main/xiaozhi-server/config/config_loader.py
@@ -69,6 +69,11 @@ def get_config_from_api(config):
"url": config["manager-api"].get("url", ""),
"secret": config["manager-api"].get("secret", ""),
}
+ if config.get("server"):
+ config_data["server"] = {
+ "ip": config["server"].get("ip", ""),
+ "port": config["server"].get("port", ""),
+ }
return config_data
diff --git a/main/xiaozhi-server/config/logger.py b/main/xiaozhi-server/config/logger.py
index 5e933584..705b244c 100644
--- a/main/xiaozhi-server/config/logger.py
+++ b/main/xiaozhi-server/config/logger.py
@@ -3,7 +3,7 @@ import sys
from loguru import logger
from config.config_loader import load_config
-SERVER_VERSION = "0.3.9"
+SERVER_VERSION = "0.3.11"
def get_module_abbreviation(module_name, module_dict):
diff --git a/main/xiaozhi-server/config_from_api.yaml b/main/xiaozhi-server/config_from_api.yaml
index d5fd69bc..15962bb6 100644
--- a/main/xiaozhi-server/config_from_api.yaml
+++ b/main/xiaozhi-server/config_from_api.yaml
@@ -5,6 +5,9 @@
# 先启动manager-api和manager-web,注册一个账号,第一个注册的账号为管理员
# 使用管理员,进入【参数管理】页面,找到【server.secret】,复制它到参数值,注意每次从零部署,server.secret都会变化
# 打开本data目录下的.config.yaml文件,修改manager-api.secret为刚才复制出来的server.secret
+server:
+ ip: 0.0.0.0
+ port: 8000
manager-api:
# 你的manager-api的地址,最好使用局域网ip
url: http://127.0.0.1:8002/xiaozhi
diff --git a/main/xiaozhi-server/core/connection.py b/main/xiaozhi-server/core/connection.py
index 5bf7540b..8fa09318 100644
--- a/main/xiaozhi-server/core/connection.py
+++ b/main/xiaozhi-server/core/connection.py
@@ -226,12 +226,12 @@ class ConnectionHandler:
"""加载意图识别"""
self._initialize_intent()
"""加载位置信息"""
- self.client_ip_info = get_ip_info(self.client_ip, self.logger)
- if self.client_ip_info is not None and "city" in self.client_ip_info:
- self.logger.bind(tag=TAG).info(f"Client ip info: {self.client_ip_info}")
- self.prompt = self.prompt + f"\nuser location:{self.client_ip_info}"
-
- self.dialogue.update_system_message(self.prompt)
+ # self.client_ip_info = get_ip_info(self.client_ip, self.logger)
+ # if self.client_ip_info is not None and "city" in self.client_ip_info:
+ # self.logger.bind(tag=TAG).info(f"Client ip info: {self.client_ip_info}")
+ # self.prompt = self.prompt + f"\nuser location:{self.client_ip_info}"
+ #
+ # self.dialogue.update_system_message(self.prompt)
def _initialize_private_config(self):
read_config_from_api = self.config.get("read_config_from_api", False)
diff --git a/main/xiaozhi-server/core/providers/llm/AliBL/AliBL.py b/main/xiaozhi-server/core/providers/llm/AliBL/AliBL.py
index 51efdc06..769f3117 100644
--- a/main/xiaozhi-server/core/providers/llm/AliBL/AliBL.py
+++ b/main/xiaozhi-server/core/providers/llm/AliBL/AliBL.py
@@ -6,6 +6,7 @@ from core.providers.llm.base import LLMProviderBase
TAG = __name__
logger = setup_logging()
+
class LLMProvider(LLMProviderBase):
def __init__(self, config):
self.api_key = config["api_key"]
@@ -19,21 +20,25 @@ class LLMProvider(LLMProviderBase):
# 处理dialogue
if self.is_No_prompt:
dialogue.pop(0)
- logger.bind(tag=TAG).debug(f"【阿里百练API服务】处理后的dialogue: {dialogue}")
+ logger.bind(tag=TAG).debug(
+ f"【阿里百练API服务】处理后的dialogue: {dialogue}"
+ )
# 构造调用参数
call_params = {
"api_key": self.api_key,
"app_id": self.app_id,
"session_id": session_id,
- "messages": dialogue
+ "messages": dialogue,
}
if self.memory_id != False:
# 百练memory需要prompt参数
prompt = dialogue[-1].get("content")
call_params["memory_id"] = self.memory_id
call_params["prompt"] = prompt
- logger.bind(tag=TAG).debug(f"【阿里百练API服务】处理后的prompt: {prompt}")
+ logger.bind(tag=TAG).debug(
+ f"【阿里百练API服务】处理后的prompt: {prompt}"
+ )
responses = Application.call(**call_params)
if responses.status_code != HTTPStatus.OK:
@@ -44,9 +49,15 @@ class LLMProvider(LLMProviderBase):
)
yield "【阿里百练API服务响应异常】"
else:
- logger.bind(tag=TAG).debug(f"【阿里百练API服务】构造参数: {call_params}")
+ logger.bind(tag=TAG).debug(
+ f"【阿里百练API服务】构造参数: {call_params}"
+ )
yield responses.output.text
except Exception as e:
logger.bind(tag=TAG).error(f"【阿里百练API服务】响应异常: {e}")
yield "【LLM服务响应异常】"
+
+ def response_with_functions(self, session_id, dialogue, functions=None):
+ logger.bind(tag=TAG).info(f"阿里百练暂未实现完整的工具调用(function call)")
+ return self.response(session_id, dialogue)
diff --git a/main/xiaozhi-server/core/providers/llm/fastgpt/fastgpt.py b/main/xiaozhi-server/core/providers/llm/fastgpt/fastgpt.py
index 38f9a2c9..e0e6ccc7 100644
--- a/main/xiaozhi-server/core/providers/llm/fastgpt/fastgpt.py
+++ b/main/xiaozhi-server/core/providers/llm/fastgpt/fastgpt.py
@@ -21,37 +21,36 @@ class LLMProvider(LLMProviderBase):
# 发起流式请求
with requests.post(
- f"{self.base_url}/chat/completions",
- headers={"Authorization": f"Bearer {self.api_key}"},
- json={
- "stream": True,
- "chatId": session_id,
- "detail": self.detail,
- "variables": self.variables,
- "messages": [
- {
- "role": "user",
- "content": last_msg["content"]
- }
- ]
- },
- stream=True
+ f"{self.base_url}/chat/completions",
+ headers={"Authorization": f"Bearer {self.api_key}"},
+ json={
+ "stream": True,
+ "chatId": session_id,
+ "detail": self.detail,
+ "variables": self.variables,
+ "messages": [{"role": "user", "content": last_msg["content"]}],
+ },
+ stream=True,
) as r:
for line in r.iter_lines():
if line:
try:
- if line.startswith(b'data: '):
- if line[6:].decode('utf-8') == '[DONE]':
+ if line.startswith(b"data: "):
+ if line[6:].decode("utf-8") == "[DONE]":
break
data = json.loads(line[6:])
- if 'choices' in data and len(data['choices']) > 0:
- delta = data['choices'][0].get('delta', {})
- if delta and 'content' in delta and delta['content'] is not None:
- content = delta['content']
- if '
' in content:
+ if "choices" in data and len(data["choices"]) > 0:
+ delta = data["choices"][0].get("delta", {})
+ if (
+ delta
+ and "content" in delta
+ and delta["content"] is not None
+ ):
+ content = delta["content"]
+ if "" in content:
continue
- if '' in content:
+ if "" in content:
continue
yield content
@@ -62,4 +61,8 @@ class LLMProvider(LLMProviderBase):
except Exception as e:
logger.bind(tag=TAG).error(f"Error in response generation: {e}")
- yield "【服务响应异常】"
\ No newline at end of file
+ yield "【服务响应异常】"
+
+ def response_with_functions(self, session_id, dialogue, functions=None):
+ logger.bind(tag=TAG).info(f"fastgpt暂未实现完整的工具调用(function call)")
+ return self.response(session_id, dialogue)
diff --git a/main/xiaozhi-server/core/providers/llm/gemini/gemini.py b/main/xiaozhi-server/core/providers/llm/gemini/gemini.py
index ca78caa9..a91a6bf0 100644
--- a/main/xiaozhi-server/core/providers/llm/gemini/gemini.py
+++ b/main/xiaozhi-server/core/providers/llm/gemini/gemini.py
@@ -134,3 +134,7 @@ class LLMProvider(LLMProviderBase):
yield f"JSON解码错误:{e}"
except Exception as e:
yield f"发生错误:{e}"
+
+ def response_with_functions(self, session_id, dialogue, functions=None):
+ logger.bind(tag=TAG).info(f"gemini暂未实现完整的工具调用(function call)")
+ return self.response(session_id, dialogue)
diff --git a/main/xiaozhi-server/core/providers/tts/base.py b/main/xiaozhi-server/core/providers/tts/base.py
index e39ca65c..b83f6f06 100644
--- a/main/xiaozhi-server/core/providers/tts/base.py
+++ b/main/xiaozhi-server/core/providers/tts/base.py
@@ -26,13 +26,19 @@ class TTSProviderBase(ABC):
max_repeat_time = 5
text = MarkdownCleaner.clean_markdown(text)
while not os.path.exists(tmp_file) and max_repeat_time > 0:
- asyncio.run(self.text_to_speak(text, tmp_file))
+ try:
+ asyncio.run(self.text_to_speak(text, tmp_file))
+ except Exception as e:
+ logger.bind(tag=TAG).error(f"语音生成失败: {text},错误: {e}")
if not os.path.exists(tmp_file):
- max_repeat_time = max_repeat_time - 1
- logger.bind(tag=TAG).error(f"语音生成失败: {text}:{tmp_file},再试{max_repeat_time}次")
+ max_repeat_time -= 1
+ if max_repeat_time > 0:
+ logger.bind(tag=TAG).error(f"再试{max_repeat_time}次")
if max_repeat_time > 0:
- logger.bind(tag=TAG).info(f"语音生成成功: {text}:{tmp_file},重试{5 - max_repeat_time}次")
+ logger.bind(tag=TAG).info(
+ f"语音生成成功: {text}:{tmp_file},重试{5 - max_repeat_time}次"
+ )
return tmp_file
except Exception as e:
@@ -48,9 +54,11 @@ class TTSProviderBase(ABC):
# 获取文件后缀名
file_type = os.path.splitext(audio_file_path)[1]
if file_type:
- file_type = file_type.lstrip('.')
+ file_type = file_type.lstrip(".")
# 读取音频文件,-nostdin 参数:不要从标准输入读取数据,否则FFmpeg会阻塞
- audio = AudioSegment.from_file(audio_file_path, format=file_type, parameters=["-nostdin"])
+ audio = AudioSegment.from_file(
+ audio_file_path, format=file_type, parameters=["-nostdin"]
+ )
# 转换为单声道/16kHz采样率/16位小端编码(确保与编码器匹配)
audio = audio.set_channels(1).set_frame_rate(16000).set_sample_width(2)
@@ -72,11 +80,11 @@ class TTSProviderBase(ABC):
# 按帧处理所有音频数据(包括最后一帧可能补零)
for i in range(0, len(raw_data), frame_size * 2): # 16bit=2bytes/sample
# 获取当前帧的二进制数据
- chunk = raw_data[i:i + frame_size * 2]
+ chunk = raw_data[i : i + frame_size * 2]
# 如果最后一帧不足,补零
if len(chunk) < frame_size * 2:
- chunk += b'\x00' * (frame_size * 2 - len(chunk))
+ chunk += b"\x00" * (frame_size * 2 - len(chunk))
# 转换为numpy数组处理
np_frame = np.frombuffer(chunk, dtype=np.int16)
diff --git a/main/xiaozhi-server/core/websocket_server.py b/main/xiaozhi-server/core/websocket_server.py
index cb4dee08..d5fb69db 100644
--- a/main/xiaozhi-server/core/websocket_server.py
+++ b/main/xiaozhi-server/core/websocket_server.py
@@ -24,7 +24,7 @@ class WebSocketServer:
async def start(self):
server_config = self.config["server"]
- host = server_config["ip"]
+ host = server_config.get("ip", "0.0.0.0")
port = int(server_config.get("port", 8000))
self.logger.bind(tag=TAG).info(
diff --git a/main/xiaozhi-server/docker-compose_all.yml b/main/xiaozhi-server/docker-compose_all.yml
index 51bb4e68..91910120 100644
--- a/main/xiaozhi-server/docker-compose_all.yml
+++ b/main/xiaozhi-server/docker-compose_all.yml
@@ -47,6 +47,10 @@ services:
- SPRING_DATASOURCE_DRUID_PASSWORD=123456
- SPRING_DATA_REDIS_HOST=xiaozhi-esp32-server-redis
- SPRING_DATA_REDIS_PORT=6379
+ volumes:
+ # 配置文件目录
+ - ./uploadfile:/app/uploadfile
+
xiaozhi-esp32-server-db:
image: mysql:latest
container_name: xiaozhi-esp32-server-db
@@ -59,7 +63,7 @@ services:
networks:
- default
expose:
- - "3306"
+ - 3306
volumes:
- ./mysql/data:/var/lib/mysql
environment:
diff --git a/main/xiaozhi-server/plugins_func/functions/get_weather.py b/main/xiaozhi-server/plugins_func/functions/get_weather.py
index 060274d9..3764401e 100644
--- a/main/xiaozhi-server/plugins_func/functions/get_weather.py
+++ b/main/xiaozhi-server/plugins_func/functions/get_weather.py
@@ -2,6 +2,7 @@ import requests
from bs4 import BeautifulSoup
from config.logger import setup_logging
from plugins_func.register import register_function, ToolType, ActionResponse, Action
+from core.utils.util import get_ip_info
TAG = __name__
logger = setup_logging()
@@ -11,9 +12,12 @@ GET_WEATHER_FUNCTION_DESC = {
"function": {
"name": "get_weather",
"description": (
- "获取某个地点的天气,用户应提供一个位置,比如用户说杭州天气,参数为:杭州。"
+ "获取某个地点的天气信息。当用户询问与天气相关的问题(例如'今天的天气怎么样?'、'明天会下雨吗?'、'广州天气如何?'等),"
+ "或对话中包含'天气'字眼时,调用此功能。用户可以提供具体位置(如城市名),"
+ "如果未提供位置,则自动获取用户当前位置查询天气。"
"如果用户说的是省份,默认用省会城市。如果用户说的不是省份或城市而是一个地名,"
"默认用该地所在省份的省会城市。"
+ "当IP解析失败会使用默认地址"
),
"parameters": {
"type": "object",
@@ -57,6 +61,7 @@ WEATHER_CODE_MAP = {
"900": "热", "901": "冷", "999": "未知"
}
+
def fetch_city_info(location, api_key):
url = f"https://geoapi.qweather.com/v2/city/lookup?key={api_key}&location={location}&lang=zh"
response = requests.get(url, headers=HEADERS).json()
@@ -97,27 +102,47 @@ def parse_weather_info(soup):
def get_weather(conn, location: str = None, lang: str = "zh_CN"):
api_key = conn.config["plugins"]["get_weather"]["api_key"]
default_location = conn.config["plugins"]["get_weather"]["default_location"]
- location = location or conn.client_ip_info.get("city") or default_location
- logger.bind(tag=TAG).debug(f"获取天气: {location}")
+ print("用户设置的default_location为:", default_location)
+ client_ip = conn.client_ip
+ print("用户提供的location为:", location)
+ # 优先使用用户提供的location参数
+ if not location:
+ # 通过客户端IP解析城市
+ if client_ip:
+ # 动态解析IP对应的城市信息
+ ip_info = get_ip_info(client_ip, logger)
+ print("解析用户IP后的城市为:", ip_info)
+ location = ip_info.get("city") if ip_info and "city" in ip_info else None
+ else:
+ # 若IP解析失败或无IP,使用默认位置
+ location = default_location
+ print("解析失败,将使用默认地址", location)
city_info = fetch_city_info(location, api_key)
if not city_info:
return ActionResponse(Action.REQLLM, f"未找到相关的城市: {location},请确认地点是否正确", None)
-
soup = fetch_weather_page(city_info['fxLink'])
if not soup:
return ActionResponse(Action.REQLLM, None, "请求失败")
-
city_name, current_abstract, current_basic, temps_list = parse_weather_info(soup)
- weather_report = f"根据下列数据,用{lang}回应用户的查询天气请求:\n{city_name}未来7天天气:\n"
- for i, (date, weather, high, low) in enumerate(temps_list):
- if high and low:
- weather_report += f"{date}: {low}到{high}, {weather}\n"
- weather_report += (
- f"当前天气: {current_abstract}\n"
- f"当前天气参数: {current_basic}\n"
- f"(确保只报告指定单日的天气情况,除非未来会出现异常天气;或者用户明确要求想要了解多日天气,如果未指定,默认报告今天的天气。"
- "参数为0的值不需要报告给用户,每次都报告体感温度,根据语境选择合适的参数内容告知用户,并对参数给出相应评价)"
- )
- return ActionResponse(Action.REQLLM, weather_report, None)
\ No newline at end of file
+ print(f"当前查询的城市名称是: {city_name}")
+
+ weather_report = f"您查询的位置是:{city_name}\n\n当前天气: {current_abstract}\n"
+
+ # 添加有效的当前天气参数
+ if current_basic:
+ weather_report += "详细参数:\n"
+ for key, value in current_basic.items():
+ if value != "0": # 过滤无效值
+ weather_report += f" · {key}: {value}\n"
+
+ # 添加7天预报
+ weather_report += "\n未来7天预报:\n"
+ for date, weather, high, low in temps_list:
+ weather_report += f"{date}: {weather},气温 {low}~{high}\n"
+
+ # 提示语
+ weather_report += "\n(如需某一天的具体天气,请告诉我日期)"
+
+ return ActionResponse(Action.REQLLM, weather_report, None)
diff --git a/main/xiaozhi-server/plugins_func/functions/hass_init.py b/main/xiaozhi-server/plugins_func/functions/hass_init.py
index 4bd2f2ec..06d7c8bc 100644
--- a/main/xiaozhi-server/plugins_func/functions/hass_init.py
+++ b/main/xiaozhi-server/plugins_func/functions/hass_init.py
@@ -13,7 +13,7 @@ def append_devices_to_prompt(conn):
"functions", []
)
if "hass_get_state" in funcs or "hass_set_state" in funcs:
- prompt = "下面是我家智能设备,可以通过homeassistant控制\n"
+ prompt = "\n下面是我家智能设备列表(位置,设备名,entity_id),可以通过homeassistant控制\n"
devices = conn.config["plugins"]["home_assistant"].get("devices", [])
if len(devices) == 0:
return