mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-27 01:23:55 +08:00
update:优化提示词
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<identity>
|
<identity>
|
||||||
{base_prompt}
|
{{base_prompt}}
|
||||||
</identity>
|
</identity>
|
||||||
|
|
||||||
<emotion>
|
<emotion>
|
||||||
@@ -21,18 +21,17 @@
|
|||||||
- **格式要求:**
|
- **格式要求:**
|
||||||
- **绝对禁止**使用 markdown、列表、标题等任何非自然对话格式。
|
- **绝对禁止**使用 markdown、列表、标题等任何非自然对话格式。
|
||||||
- **历史记忆:**
|
- **历史记忆:**
|
||||||
- 之前你和用户的聊天记录,在`<memory>`里。
|
- 之前你和用户的聊天记录,在`memory`里。
|
||||||
</communication_style>
|
</communication_style>
|
||||||
|
|
||||||
<speaker_recognition>
|
<speaker_recognition>
|
||||||
- **识别前缀:** 当用户消息开头为 `[说话人: 姓名]` 时,表示系统已识别说话人身份。
|
- **识别前缀:** 当用户格式为 `{"speaker":"某某某","content":"xxx"}` 时,表示系统已识别说话人身份,speaker是他的名字,content是说话的内容。
|
||||||
- **个性化回应:**
|
- **个性化回应:**
|
||||||
- **称呼姓名:** 在回应中自然地称呼对方名字(如果已知且合适)。
|
- **称呼姓名:** 在第一次识别说话人的时候必须称呼对方名字。
|
||||||
- **适配风格:** 参考该说话人**已知的特点或历史信息**(如有),调整回应风格和内容,使其更贴心。
|
- **适配风格:** 参考该说话人**已知的特点或历史信息**(如有),调整回应风格和内容,使其更贴心。
|
||||||
</speaker_recognition>
|
</speaker_recognition>
|
||||||
|
|
||||||
<tool_calling>
|
<tool_calling>
|
||||||
|
|
||||||
【核心原则】优先利用`<context>`信息,**仅在必要时调用工具**,调用后需用自然语言解释结果(绝口不提工具名)。
|
【核心原则】优先利用`<context>`信息,**仅在必要时调用工具**,调用后需用自然语言解释结果(绝口不提工具名)。
|
||||||
- **调用规则:**
|
- **调用规则:**
|
||||||
1. **严格模式:** 调用时**必须**严格遵循工具要求的模式,提供**所有必要参数**。
|
1. **严格模式:** 调用时**必须**严格遵循工具要求的模式,提供**所有必要参数**。
|
||||||
@@ -41,7 +40,7 @@
|
|||||||
4. **独立任务:** 除`<context>`已涵盖信息外,用户每个要求(即使相似)都视为**独立任务**,需调用工具获取最新数据,**不可偷懒复用历史结果**。
|
4. **独立任务:** 除`<context>`已涵盖信息外,用户每个要求(即使相似)都视为**独立任务**,需调用工具获取最新数据,**不可偷懒复用历史结果**。
|
||||||
5. **不确定时:** **切勿猜测或编造答案**。若不确定相关操作,可引导用户澄清或告知能力限制。
|
5. **不确定时:** **切勿猜测或编造答案**。若不确定相关操作,可引导用户澄清或告知能力限制。
|
||||||
- **重要例外(无需调用):**
|
- **重要例外(无需调用):**
|
||||||
- `查询"现在的时间"、"今天的日期/星期几"、"今天农历"、"{local_address}的天气/未来天气"` -> **直接使用`<context>`信息回复**。
|
- `查询"现在的时间"、"今天的日期/星期几"、"今天农历"、"{{local_address}}的天气/未来天气"` -> **直接使用`<context>`信息回复**。
|
||||||
- **需要调用的情况(示例):**
|
- **需要调用的情况(示例):**
|
||||||
- 查询**非今天**的农历(如明天、昨天、具体日期)。
|
- 查询**非今天**的农历(如明天、昨天、具体日期)。
|
||||||
- 查询**详细农历信息**(宜忌、八字、节气等)。
|
- 查询**详细农历信息**(宜忌、八字、节气等)。
|
||||||
@@ -51,11 +50,11 @@
|
|||||||
|
|
||||||
<context>
|
<context>
|
||||||
【重要!以下信息已实时提供,无需调用工具查询,请直接使用:】
|
【重要!以下信息已实时提供,无需调用工具查询,请直接使用:】
|
||||||
- **当前时间:** {current_time}
|
- **当前时间:** {{current_time}}
|
||||||
- **今天日期:** {today_date} ({today_weekday})
|
- **今天日期:** {{today_date}} ({{today_weekday}})
|
||||||
- **今天农历:** {lunar_date}
|
- **今天农历:** {{lunar_date}}
|
||||||
- **用户所在城市:** {local_address}
|
- **用户所在城市:** {{local_address}}
|
||||||
- **当地未来7天天气:** {weather_info}
|
- **当地未来7天天气:** {{weather_info}}
|
||||||
</context>
|
</context>
|
||||||
|
|
||||||
<memory>
|
<memory>
|
||||||
|
|||||||
@@ -645,37 +645,8 @@ class ConnectionHandler:
|
|||||||
self.logger.bind(tag=TAG).info(f"大模型收到用户消息: {query}")
|
self.logger.bind(tag=TAG).info(f"大模型收到用户消息: {query}")
|
||||||
self.llm_finish_task = False
|
self.llm_finish_task = False
|
||||||
|
|
||||||
# 检查是否是JSON格式的消息(包含说话人信息)
|
|
||||||
enhanced_query = query
|
|
||||||
try:
|
|
||||||
if query.strip().startswith("{") and query.strip().endswith("}"):
|
|
||||||
data = json.loads(query)
|
|
||||||
if "speaker" in data and "content" in data:
|
|
||||||
# 直接使用JSON格式,不重新格式化
|
|
||||||
enhanced_query = query
|
|
||||||
self.logger.bind(tag=TAG).info(f"识别到说话人: {data['speaker']}")
|
|
||||||
else:
|
|
||||||
# 如果有说话人信息但不是JSON格式,按原逻辑处理
|
|
||||||
if hasattr(self, "current_speaker") and self.current_speaker:
|
|
||||||
enhanced_query = f"[说话人: {self.current_speaker}] {query}"
|
|
||||||
self.logger.bind(tag=TAG).info(
|
|
||||||
f"识别到说话人: {self.current_speaker}"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
# 如果有说话人信息但不是JSON格式,按原逻辑处理
|
|
||||||
if hasattr(self, "current_speaker") and self.current_speaker:
|
|
||||||
enhanced_query = f"[说话人: {self.current_speaker}] {query}"
|
|
||||||
self.logger.bind(tag=TAG).info(
|
|
||||||
f"识别到说话人: {self.current_speaker}"
|
|
||||||
)
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
# JSON解析失败,按原逻辑处理
|
|
||||||
if hasattr(self, "current_speaker") and self.current_speaker:
|
|
||||||
enhanced_query = f"[说话人: {self.current_speaker}] {query}"
|
|
||||||
self.logger.bind(tag=TAG).info(f"识别到说话人: {self.current_speaker}")
|
|
||||||
|
|
||||||
if not tool_call:
|
if not tool_call:
|
||||||
self.dialogue.put(Message(role="user", content=enhanced_query))
|
self.dialogue.put(Message(role="user", content=query))
|
||||||
|
|
||||||
# Define intent functions
|
# Define intent functions
|
||||||
functions = None
|
functions = None
|
||||||
@@ -688,7 +659,7 @@ class ConnectionHandler:
|
|||||||
memory_str = None
|
memory_str = None
|
||||||
if self.memory is not None:
|
if self.memory is not None:
|
||||||
future = asyncio.run_coroutine_threadsafe(
|
future = asyncio.run_coroutine_threadsafe(
|
||||||
self.memory.query_memory(enhanced_query), self.loop
|
self.memory.query_memory(query), self.loop
|
||||||
)
|
)
|
||||||
memory_str = future.result()
|
memory_str = future.result()
|
||||||
|
|
||||||
@@ -698,13 +669,17 @@ class ConnectionHandler:
|
|||||||
# 使用支持functions的streaming接口
|
# 使用支持functions的streaming接口
|
||||||
llm_responses = self.llm.response_with_functions(
|
llm_responses = self.llm.response_with_functions(
|
||||||
self.session_id,
|
self.session_id,
|
||||||
self.dialogue.get_llm_dialogue_with_memory(memory_str),
|
self.dialogue.get_llm_dialogue_with_memory(
|
||||||
|
memory_str, self.config.get("voiceprint", {})
|
||||||
|
),
|
||||||
functions=functions,
|
functions=functions,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
llm_responses = self.llm.response(
|
llm_responses = self.llm.response(
|
||||||
self.session_id,
|
self.session_id,
|
||||||
self.dialogue.get_llm_dialogue_with_memory(memory_str),
|
self.dialogue.get_llm_dialogue_with_memory(
|
||||||
|
memory_str, self.config.get("voiceprint", {})
|
||||||
|
),
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.bind(tag=TAG).error(f"LLM 处理出错 {query}: {e}")
|
self.logger.bind(tag=TAG).error(f"LLM 处理出错 {query}: {e}")
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import uuid
|
|||||||
import re
|
import re
|
||||||
from typing import List, Dict
|
from typing import List, Dict
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from config.settings import load_config
|
|
||||||
|
|
||||||
|
|
||||||
class Message:
|
class Message:
|
||||||
@@ -49,7 +48,7 @@ class Dialogue:
|
|||||||
def get_llm_dialogue(self) -> List[Dict[str, str]]:
|
def get_llm_dialogue(self) -> List[Dict[str, str]]:
|
||||||
# 直接调用get_llm_dialogue_with_memory,传入None作为memory_str
|
# 直接调用get_llm_dialogue_with_memory,传入None作为memory_str
|
||||||
# 这样确保说话人功能在所有调用路径下都生效
|
# 这样确保说话人功能在所有调用路径下都生效
|
||||||
return self.get_llm_dialogue_with_memory(None)
|
return self.get_llm_dialogue_with_memory(None, None)
|
||||||
|
|
||||||
def update_system_message(self, new_content: str):
|
def update_system_message(self, new_content: str):
|
||||||
"""更新或添加系统消息"""
|
"""更新或添加系统消息"""
|
||||||
@@ -61,7 +60,7 @@ class Dialogue:
|
|||||||
self.put(Message(role="system", content=new_content))
|
self.put(Message(role="system", content=new_content))
|
||||||
|
|
||||||
def get_llm_dialogue_with_memory(
|
def get_llm_dialogue_with_memory(
|
||||||
self, memory_str: str = None
|
self, memory_str: str = None, voiceprint_config: dict = None
|
||||||
) -> List[Dict[str, str]]:
|
) -> List[Dict[str, str]]:
|
||||||
# 构建对话
|
# 构建对话
|
||||||
dialogue = []
|
dialogue = []
|
||||||
@@ -74,38 +73,37 @@ class Dialogue:
|
|||||||
if system_message:
|
if system_message:
|
||||||
# 基础系统提示
|
# 基础系统提示
|
||||||
enhanced_system_prompt = system_message.content
|
enhanced_system_prompt = system_message.content
|
||||||
|
|
||||||
# 添加说话人个性化描述
|
# 添加说话人个性化描述
|
||||||
try:
|
try:
|
||||||
config = load_config()
|
|
||||||
voiceprint_config = config.get("voiceprint", {})
|
|
||||||
speakers = voiceprint_config.get("speakers", [])
|
speakers = voiceprint_config.get("speakers", [])
|
||||||
|
|
||||||
if speakers:
|
if speakers:
|
||||||
enhanced_system_prompt += "\n\n<speaker>"
|
enhanced_system_prompt += "\n\n<speakers_info>"
|
||||||
for speaker_str in speakers:
|
for speaker_str in speakers:
|
||||||
try:
|
try:
|
||||||
parts = speaker_str.split(",", 2)
|
parts = speaker_str.split(",", 2)
|
||||||
if len(parts) >= 2:
|
if len(parts) >= 2:
|
||||||
speaker_id = parts[0].strip()
|
|
||||||
name = parts[1].strip()
|
name = parts[1].strip()
|
||||||
# 如果描述为空,则为""
|
# 如果描述为空,则为""
|
||||||
description = parts[2].strip() if len(parts) >= 3 else ""
|
description = (
|
||||||
|
parts[2].strip() if len(parts) >= 3 else ""
|
||||||
|
)
|
||||||
enhanced_system_prompt += f"\n- {name}:{description}"
|
enhanced_system_prompt += f"\n- {name}:{description}"
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
enhanced_system_prompt += "\n\n</speaker>"
|
enhanced_system_prompt += "\n\n</speakers_info>"
|
||||||
except:
|
except:
|
||||||
# 配置读取失败时忽略错误,不影响其他功能
|
# 配置读取失败时忽略错误,不影响其他功能
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# 使用正则表达式匹配 <memory> 标签,不管中间有什么内容
|
# 使用正则表达式匹配 <memory> 标签,不管中间有什么内容
|
||||||
enhanced_system_prompt = re.sub(
|
if memory_str is not None:
|
||||||
r"<memory>.*?</memory>",
|
enhanced_system_prompt = re.sub(
|
||||||
f"<memory>\n{memory_str}\n</memory>",
|
r"<memory>.*?</memory>",
|
||||||
system_message.content,
|
f"<memory>\n{memory_str}\n</memory>",
|
||||||
flags=re.DOTALL,
|
enhanced_system_prompt,
|
||||||
)
|
flags=re.DOTALL,
|
||||||
|
)
|
||||||
dialogue.append({"role": "system", "content": enhanced_system_prompt})
|
dialogue.append({"role": "system", "content": enhanced_system_prompt})
|
||||||
|
|
||||||
# 添加用户和助手的对话
|
# 添加用户和助手的对话
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import os
|
|||||||
import cnlunar
|
import cnlunar
|
||||||
from typing import Dict, Any
|
from typing import Dict, Any
|
||||||
from config.logger import setup_logging
|
from config.logger import setup_logging
|
||||||
|
from jinja2 import Template
|
||||||
|
|
||||||
TAG = __name__
|
TAG = __name__
|
||||||
|
|
||||||
@@ -196,7 +197,8 @@ class PromptManager:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# 替换模板变量
|
# 替换模板变量
|
||||||
enhanced_prompt = self.base_prompt_template.format(
|
template = Template(self.base_prompt_template)
|
||||||
|
enhanced_prompt = template.render(
|
||||||
base_prompt=user_prompt,
|
base_prompt=user_prompt,
|
||||||
current_time=current_time,
|
current_time=current_time,
|
||||||
today_date=today_date,
|
today_date=today_date,
|
||||||
|
|||||||
@@ -33,4 +33,5 @@ markitdown==0.1.1
|
|||||||
mcp-proxy==0.8.0
|
mcp-proxy==0.8.0
|
||||||
PyJWT==2.8.0
|
PyJWT==2.8.0
|
||||||
psutil==7.0.0
|
psutil==7.0.0
|
||||||
portalocker==2.10.1
|
portalocker==2.10.1
|
||||||
|
Jinja2==3.1.6
|
||||||
Reference in New Issue
Block a user