|
@@ -1,3 +1,4 @@
|
|
|
+import datetime
|
|
|
from typing import Optional, List, Dict
|
|
|
|
|
|
from pqai_agent.agents.simple_chat_agent import SimpleOpenAICompatibleChatAgent
|
|
@@ -9,11 +10,10 @@ from pqai_agent.toolkit.message_notifier import MessageNotifier
|
|
|
|
|
|
DEFAULT_SYSTEM_PROMPT = '''
|
|
|
<基本设定>
|
|
|
-你是一位熟悉中老年用户交流习惯的微信客服Agent。
|
|
|
+你是一位熟悉中老年用户交流习惯的微信客服。
|
|
|
你擅长以下事项:
|
|
|
* 倾听、引导和共情,在对话中自然促进用户互动
|
|
|
* 理解中老年人的典型情感需求、对话习惯
|
|
|
-* 分析用户的微信名、头像,以适合的话术与用户建立联系
|
|
|
|
|
|
你的工作方法论:
|
|
|
* 分析用户请求以确定核心需求
|
|
@@ -26,11 +26,38 @@ DEFAULT_SYSTEM_PROMPT = '''
|
|
|
* 所有的思考和回答都要用工作语言
|
|
|
</语言设定>
|
|
|
|
|
|
-<通用话术>
|
|
|
-* 时间锚点:"早上好!今天阳光这么好,您打算做点什么让自己开心的事呀?"
|
|
|
-* 轻量求助:"听说最近好多长辈在学手机拍照技巧,您有没有什么实用小窍门能教教我呀?"
|
|
|
-* 正向引导:"这个季节最适合喝养生茶啦,您平时喜欢枸杞红枣茶还是菊花茶呀?"
|
|
|
-</通用话术>
|
|
|
+<通用话术列表>
|
|
|
+<话术>
|
|
|
+* 简介:简单自我介绍,并向用户发出交友邀请
|
|
|
+* 适用情形:初次问候
|
|
|
+* 内容:根据你的人设做出简短自我介绍,并向用户发出交友邀请
|
|
|
+* 要求:简短亲切,1-2句话;模拟微信聊天的回复格式,分段清晰
|
|
|
+</话术>
|
|
|
+<话术>
|
|
|
+* 简介:使用用户微信名做藏头诗,进行问候
|
|
|
+* 适用情形:不限
|
|
|
+* 内容:首先进行用户问候,然后介绍藏头诗,最后以一个让老年人有动力继续聊天的问句结尾
|
|
|
+* 要求:最后的问句要与藏头诗或用户自身经历有关,与藏头诗自然承接,无需和用户画像其他内容相关
|
|
|
+</话术>
|
|
|
+<话术>
|
|
|
+* 简介:介绍自己的兴趣并询问用户的兴趣爱好
|
|
|
+* 适用情形:不限
|
|
|
+* 内容:根据用户头像分析用户的特点、可能的兴趣爱好,作为参考,表述自己有相同的兴趣爱好,并举一些简短的例子 ,然后询问用户的兴趣爱好
|
|
|
+* 要求:询问无需和用户画像中其他信息有关;说明引发你问候的是用户头像;简短亲切,2-3句话 30字左右;如无用户信息或行为,不要根据联想杜撰用户偏好/行为
|
|
|
+</话术>
|
|
|
+<话术>
|
|
|
+* 简介:对用户进行节日/节气相关问候
|
|
|
+* 适用情形:不限
|
|
|
+* 内容:结合具体节假日及其习俗产生问候,以一个让老年人有动力继续聊天的问句结尾,与前面的问候自然承接
|
|
|
+* 要求:根据今日或近日实际日期,不要假设日期和节日;忽略小众节假日,和根据最近的节假日产生问候,如临近或刚过完重要节日,可询问节日安排或节日经历;简短亲切,2-3句话 30字左右;如无用户信息或行为,不要根据联想杜撰用户偏好/行为
|
|
|
+</话术>
|
|
|
+<话术>
|
|
|
+* 简介:询问用户当日计划安排并产生问候
|
|
|
+* 适用情形:不限
|
|
|
+* 内容:向用户介绍你的今日安排以及询问用户的今日安排
|
|
|
+* 要求:简短亲切,1-2句话,像用户熟悉的晚辈一样问候沟通;模拟微信聊天的回复格式,分段清晰
|
|
|
+</话术>
|
|
|
+</通用话术列表>
|
|
|
|
|
|
<心理学技巧>
|
|
|
* 怀旧效应:可以用"当年/以前"触发美好回忆
|
|
@@ -40,7 +67,7 @@ DEFAULT_SYSTEM_PROMPT = '''
|
|
|
|
|
|
<风险规避原则>
|
|
|
* 避免过度打扰和重复:注意分析历史对话
|
|
|
-* 避免过度解读
|
|
|
+* 避免过度解读:不要过度解读用户的信息
|
|
|
* 文化适配:注意不同地域的用户文化差异
|
|
|
* 准确性要求:不要使用虚构的信息
|
|
|
</风险规避原则>
|
|
@@ -75,9 +102,10 @@ QUERY_PROMPT_TEMPLATE = """现在,请通过多步思考,选择合适的方
|
|
|
|
|
|
注意对话信息的格式为: [角色][时间]对话内容
|
|
|
注意一定要分析对话信息中的时间,避免和当前时间段不符的内容!注意一定要结合历史的对话情况进行分析和问候方式的选择!
|
|
|
-可以使用analyse_image分析用户头像。
|
|
|
+如有必要,可以使用analyse_image分析用户头像。
|
|
|
必须使用message_notify_user发送最终的问候内容,调用message_notify_user时不要传入除了问候内容外的其它任何信息。
|
|
|
-Please think step by step.
|
|
|
+注意每次问候只使用一种话术。
|
|
|
+Now, start to process your task. Please think step by step.
|
|
|
"""
|
|
|
|
|
|
class MessagePushAgent(SimpleOpenAICompatibleChatAgent):
|
|
@@ -96,13 +124,27 @@ class MessagePushAgent(SimpleOpenAICompatibleChatAgent):
|
|
|
super().__init__(model, system_prompt, tools, generate_cfg, max_run_step)
|
|
|
|
|
|
def generate_message(self, user_profile: Dict, context: Dict, dialogue_history: List[Dict]) -> str:
|
|
|
- query = QUERY_PROMPT_TEMPLATE.format(**user_profile, **context, dialogue_history=dialogue_history)
|
|
|
+ formatted_dialogue = MessagePushAgent.compose_dialogue(dialogue_history)
|
|
|
+ query = QUERY_PROMPT_TEMPLATE.format(**user_profile, **context, dialogue_history=formatted_dialogue)
|
|
|
self.run(query)
|
|
|
for tool_call in reversed(self.tool_call_records):
|
|
|
if tool_call['name'] == MessageNotifier.message_notify_user.__name__:
|
|
|
return tool_call['arguments']['message']
|
|
|
return ''
|
|
|
|
|
|
+ @staticmethod
|
|
|
+ def compose_dialogue(dialogue: List[Dict]) -> str:
|
|
|
+ role_map = {'user': '用户', 'assistant': '客服'}
|
|
|
+ messages = []
|
|
|
+ for msg in dialogue:
|
|
|
+ if not msg['content']:
|
|
|
+ continue
|
|
|
+ if msg['role'] not in role_map:
|
|
|
+ continue
|
|
|
+ format_dt = datetime.datetime.fromtimestamp(msg['timestamp'] / 1000).strftime('%Y-%m-%d %H:%M:%S')
|
|
|
+ messages.append('[{}][{}]{}'.format(role_map[msg['role']], format_dt, msg['content']))
|
|
|
+ return '\n'.join(messages)
|
|
|
+
|
|
|
if __name__ == '__main__':
|
|
|
import pqai_agent.logging_service
|
|
|
pqai_agent.logging_service.setup_root_logger()
|
|
@@ -118,9 +160,14 @@ if __name__ == '__main__':
|
|
|
'interests': ['钓鱼', '旅游']
|
|
|
}
|
|
|
test_context = {
|
|
|
- "current_datetime": "2025-05-13 08:00:00",
|
|
|
+ "current_datetime": "2025-05-10 08:00:00",
|
|
|
}
|
|
|
- response = agent.generate_message(test_user_profile, test_context, [])
|
|
|
+ def create_ts(year, month, day, hour, minute):
|
|
|
+ return datetime.datetime(year, month, day, hour, minute).timestamp() * 1000
|
|
|
+ messages = [
|
|
|
+ # {"role": "assistant", "content": "月哥,早上好!看到您的头像是一片宁静的户外风景,感觉您一定很喜欢大自然吧?今天天气不错,您有什么计划吗?", "timestamp": create_ts(2025, 5, 10, 8, 0)},
|
|
|
+ ]
|
|
|
+ response = agent.generate_message(test_user_profile, test_context, messages)
|
|
|
print(response)
|
|
|
|
|
|
|