fix cn prompt problem

This commit is contained in:
jinli.yl 2024-07-18 15:46:34 +08:00
parent 9944e711de
commit 9b0f222c22
13 changed files with 153 additions and 33 deletions

View file

@ -115,12 +115,18 @@ worker:
get_observation:
class: memory.worker.write.get_observation_worker
generation_model: dashscope_generation
generation_model_kwargs:
top_k: 1
get_observation_with_time:
class: memory.worker.write.get_observation_with_time_worker
generation_model: dashscope_generation
generation_model_kwargs:
top_k: 1
contra_repeat:
class: memory.worker.write.contra_repeat_worker
generation_model: dashscope_generation
generation_model_kwargs:
top_k: 1
store_memory:
class: memory.worker.write.update_memory_worker
method: from_memory_key
@ -142,6 +148,7 @@ models:
class: models.llama_index_generation_model
module_name: dashscope_generation
model_name: qwen-max
max_tokens: 2000
dashscope_embedding:
class: models.llama_index_embedding_model
module_name: dashscope_embedding

View file

@ -1,7 +1,7 @@
get_reflection_subject_system:
cn: |
任务:从下面的信息中提取出最重要的最多{num_questions}条{user_name}属性,要求不与已有的{user_name}属性语义重复。
要求1:{user_name}属性可以是一般的{user_name}偏好,也可以是运动偏好,旅游偏好,饮食偏好等等,也可以是重要事件性质,比如最近重要的事情,也可以是一些高度概括的人生理想,价值观,人生观,性格, 也可以是和朋友的人际关系等等。
要求1:{user_name}属性可以是基本信息,基础画像,也可以是运动偏好,旅游偏好,饮食偏好等等兴趣偏好,也可以是重要事件性质,比如最近重要的事情,也可以是一些高度概括的人生理想,价值观,人生观,性格,也可以是和朋友的人际关系等等。
要求2:根据{user_name}属性,我们可以生成“{user_name}的<{user_name}属性>是什么?”的问题,以此可以从下面的信息中提取{user_name}属性对应的值。
输出格式:每一行输出一个{user_name}属性,每个{user_name}属性推荐4个字,如果没有信息请回答无,最多输出{num_questions}条。
@ -81,9 +81,9 @@ get_reflection_subject_few_shot:
{user_name}年龄为28岁。
{user_name}体重为70kg。
{user_name}是男性。
已有{user_name}属性:性别,年龄,体重,当前学习进展
已有{user_name}属性:性别,体重,当前学习进展
新增{user_name}属性:
无
年龄
get_reflection_subject_user_query:
cn: |

View file

@ -24,7 +24,7 @@ class ContraRepeatWorker(MemoryBaseWorker):
FILE_PATH: str = __file__
def _parse_params(self, **kwargs):
self.generation_model_top_k: int = kwargs.get("generation_model_top_k", 1)
self.generation_model_kwargs: dict = kwargs.get("generation_model_kwargs", {})
self.retrieve_top_k: int = kwargs.get("retrieve_top_k", 30)
self.contra_repeat_max_count: int = kwargs.get("contra_repeat_max_count", 50)
@ -69,7 +69,7 @@ class ContraRepeatWorker(MemoryBaseWorker):
self.logger.info(f"contra_repeat_message={contra_repeat_message}")
# call LLM
response = self.generation_model.call(messages=contra_repeat_message, top_k=self.generation_model_top_k)
response = self.generation_model.call(messages=contra_repeat_message, **self.generation_model_kwargs)
# return if empty
if not response.status or not response.message.content:

View file

@ -1,6 +1,8 @@
contra_repeat_system:
cn: |
对下面的{num_obs}句句子,逐一判断是否与“前面序号”的任意句子存在信息的矛盾,或者句子的主要信息被“前面序号”的任意句子中的信息包含。只判断与“前面序号”的句子的关系。
任务:对下面的{num_obs}句句子,逐一判断是否与“前面序号”的任意句子存在信息的矛盾,或者句子的主要信息被“前面序号”的任意句子中的信息包含。
注意:只判断与“前面序号”的句子的关系,不要判断“后面序号”。
其中矛盾的形式可以有很多种,可以是逻辑上的矛盾,可以是属性上的变化导致的矛盾,比如不能同时在两个地方工作,同一个时刻不能在两个地点,同一个时刻不能干两件事情等等。
对每个句子都做一个判断,最后一共输出{num_obs}条判断。
请一步步思考,并按如下格式输出:
思考:思考的依据和过程,30字以内。
@ -107,4 +109,4 @@ contra_repeat_user_query:
en: |
Sentences:
{user_query}
{user_query}

View file

@ -50,7 +50,7 @@ class GetObservationWithTimeWorker(GetObservationWorker):
dt_handler = DatetimeHandler(dt=msg.time_created)
dt = dt_handler.string_format(self.prompt_handler.time_string_format)
# Append formatted timestamp-query pairs to the user_query_list
user_query_list.append(f"{i} {dt} {self.target_name}{self.get_language_value(COLON_WORD)}{msg.content}")
user_query_list.append(f"{i + 1} {dt} {self.target_name}{self.get_language_value(COLON_WORD)}{msg.content}")
# Construct the system prompt with the count of observations
system_prompt = self.prompt_handler.get_observation_with_time_system.format(num_obs=len(user_query_list),

View file

@ -6,14 +6,15 @@ time_string_format:
get_observation_with_time_system:
cn: |
任务:从下面的{num_obs}句{user_name}句子中依次提取出关于{user_name}的重要信息,相应的关键词与时间信息。
任务:从下面的{num_obs}句{user_name}句子中依次提取出关于{user_name}的重要信息,相应的关键词与时间信息。如果没有重要信息则回答“无”,最多提取{num_obs}条信息。
每一句{user_name}句子的格式是:<序号> <对话时间> {user_name}:<句子>
对每一句句子,只提取非常明确的信息和进行非常确定的推断,不要进行任何猜测。不要提取重复的信息,如果句子中的所有信息与已经提取出的信息重复了则回答“重复“,如果没有重要信息则回答“无”。
如果{user_name}信息涉及时间,则结合对话时间推断{user_name}信息的时间信息,没有则不输出。注意区分,对于句子中包含{user_name}假设的信息或者{user_name}虚构的内容比如{user_name}创作的小说或剧本,不要提取信息。
{user_name}的重要信息可以包含用户基本信息,用户画像信息,用户兴趣偏好信息,用户性格,用户价值观,用户人际关系,用户重大事件转折点等等重要信息。
如果句子中只包含{user_name}假设的信息或者{user_name}虚构的内容比如{user_name}创作的小说或剧本,回答“无”。
如果{user_name}信息涉及时间,则结合对话时间推断{user_name}信息的时间信息,没有则不输出。
对每个句子都做一次信息提取,最后一共输出{num_obs}条信息。
请一步步思考,并一定要按如下格式依次输出,最后的结果一定要加<>:
思考:思考的依据和过程,50字以内。
信息:<句子序号> <时间信息或“无”> <明确的重要信息或“重复”或”无“> <关键词>
信息:<句子序号> <时间信息或不输出> <明确的重要信息或“无”> <关键词>
en: |
Instruction: Extract important information about {user_name}, corresponding keywords, and time information from the following {num_obs} sentences by {user_name}, one by one.
@ -49,7 +50,7 @@ get_observation_with_time_few_shot:
{user_name}句子:
1 2020年1月4日周日10点 {user_name}:我花5000元买了100股海天味业。
2 2023年4月27日周五8点 {user_name}:明天是我和妻子的结婚纪念日,帮我推荐一家餐厅。
3 2020年1月4日周日10点 {user_name}:我花5000元买了100股海天味业。
3 2020年1月4日周日10点 {user_name}:我花50000元买了100股茅台。
4 2021年6月2日周四23点 {user_name}:谢啦。我中午在公司附近吃,帮我推荐一家阿里巴巴徐汇滨江园区附近的餐厅吧。
5 2021年7月9日周六11点 {user_name}:两个坏消息,我打羽毛球把拍子打断线了。。。然后我去我朋友家撸猫,结果我猫毛过敏,今天疯狂打喷嚏。。。
@ -58,8 +59,8 @@ get_observation_with_time_few_shot:
思考:从第2句可以得知{user_name}与妻子的结婚纪念日是明天,这是关于{user_name}重要纪念日的信息。其余信息重要性不足。{user_name}信息涉及时间,结合对话时间为2023年4月27日,
以及结婚纪念日为周期性日期,推断{user_name}与妻子的结婚纪念日是每年4月28日。
信息:<2> <每年4月28日> <{user_name}与妻子的结婚纪念日是每年4月28日。> <妻子, 结婚纪念日>
思考:第3句含有的信息与第1句重复了。
信息:<3> <> <重复> <>
思考:第3句含有的信息与第1句相似,但是不重复,可以得知{user_name}购买了茅台股票。
信息:<3> <> <{user_name}购买了茅台股票,购买数量为100股,购买金额为50000元。> <茅台, 股票>
思考:从第4句以得知{user_name}在阿里巴巴徐汇滨江园区工作,这是关于{user_name}的工作的重要信息。其余信息重要性不足。{user_name}信息不涉及时间。
信息:<4> <> <{user_name}在阿里巴巴徐汇滨江园区工作。> <阿里巴巴, 徐汇滨江园区, 工作>
思考:从第5句可以得知{user_name}前天打羽毛球时把球拍打断了线,但这不是重要的信息。还可以得知{user_name}对猫毛过敏,这是关于{user_name}的健康的重要信息。{user_name}信息不涉及时间。

View file

@ -17,7 +17,7 @@ class GetObservationWorker(MemoryBaseWorker):
OBS_STORE_KEY: str = NEW_OBS_NODES
def _parse_params(self, **kwargs):
self.generation_model_top_k: int = kwargs.get("generation_model_top_k", 1)
self.generation_model_kwargs: dict = kwargs.get("generation_model_kwargs", {})
def add_observation(self, message: Message, time_infer: str, obs_content: str, keywords: str):
dt_handler = DatetimeHandler(dt=message.time_created)
@ -65,7 +65,7 @@ class GetObservationWorker(MemoryBaseWorker):
user_query_list = []
for i, msg in enumerate(filter_messages):
# Construct each user query item with index, target name, and message content
user_query_list.append(f"{i} {self.target_name}{self.get_language_value(COLON_WORD)}{msg.content}")
user_query_list.append(f"{i + 1} {self.target_name}{self.get_language_value(COLON_WORD)}{msg.content}")
# Format the system prompt with the number of observations and target name
system_prompt = self.prompt_handler.get_observation_system.format(num_obs=len(user_query_list),
@ -109,7 +109,7 @@ class GetObservationWorker(MemoryBaseWorker):
obtain_obs_message = self.build_message(filter_messages)
# Generates observations using the language model
response = self.generation_model.call(messages=obtain_obs_message, top_k=self.generation_model_top_k)
response = self.generation_model.call(messages=obtain_obs_message, **self.generation_model_kwargs)
if not response.status or not response.message.content:
return

View file

@ -1,13 +1,12 @@
get_observation_system:
cn: |
任务:从下面的{num_obs}句{user_name}句子中依次提取出关于{user_name}的重要信息和兴趣偏好,与相应的关键词。最多提取{num_obs}条信息。
如果句子中的所有信息与已经提取出的信息完全一样则回答“重复“,如果没有重要信息则回答“无”。
用户信息可以包含用户基本信息,用户画像信息,用户兴趣偏好信息,用户性格,用户价值观,用户重大事件转折点等等重要信息。
注意区分,对于句子中包含{user_name}假设的信息或者{user_name}虚构的内容比如{user_name}创作的小说或剧本,不要提取信息。
任务:从下面的{num_obs}句{user_name}句子中依次提取出关于{user_name}的重要信息,与相应的关键词。如果没有重要信息则回答“无”,最多提取{num_obs}条信息。
{user_name}的重要信息可以包含用户基本信息,用户画像信息,用户兴趣偏好信息,用户性格,用户价值观,用户人际关系,用户重大事件转折点等等重要信息。
如果句子中只包含{user_name}假设的信息或者{user_name}虚构的内容比如{user_name}创作的小说或剧本,回答“无”。
对每个句子都做一次信息提取,最后一共输出{num_obs}条信息。
请一定要按如下格式依次输出,最后的结果一定要加<>:
请一步步思考,并一定要按如下格式依次输出,最后的结果一定要加<>:
思考:思考的依据和过程,50字以内。
信息:<句子序号> <> <明确的重要信息或“重复”或”无“> <关键词>
信息:<句子序号> <> <明确的重要信息或“无”> <关键词>
en: |
Task: Extract important information, interests and corresponding keywords from the following {num_obs} sentences about {user_name} in sequence. Extract up to {num_obs} pieces of information.
@ -25,16 +24,22 @@ get_observation_few_shot:
{user_name}句子:
1 {user_name}:我现在处境很糟,没有工作,负债几万,怎么办
2 {user_name}:有人说兴趣是最好的老师,也建议兴趣和职业联系起来,但我发现喜欢打篮球的人很多,但靠打篮球成职业的稀少,赚钱的更少,此外,怎么分辨兴趣和喜欢
3 {user_name}:我现在处境很糟,没有工作,负债几万,怎么办
3 {user_name}:我现在心情很糟糕
4 {user_name}:我是一个刚毕业的学生,对社会,行业不了解,给我介绍一下社会系统和行业格局
5 {user_name}:我花5000元买了100股海天味业。
6 {user_name}:我花50000元买了100股茅台。
思考:从第1句可以得知{user_name}现在没有工作,负债几万,这是关于{user_name}工作与经济状况的重要信息。
信息:<1> <> <{user_name}当前无工作且负债几万> <无工作, 负债几万>
思考:第2句是{user_name}对他人观点的讨论和疑问,没有明确提及{user_name}个人信息。
信息:<2> <> <无> <>
思考:第3句含有的信息与第1句重复了。
信息:<3> <> <重复> <>
思考:从第3句可以得知{user_name}当前心情不好。
信息:<3> <> <{user_name}当前心情不好> <心情>
思考:从第4句可以得知{user_name}是一个刚毕业的学生,这是关于{user_name}身份背景状况的重要信息。其余信息重要性不足。
信息:<4> <> <{user_name}是一名刚毕业的学生。> <刚毕业, 学生>
思考:从第5句可以得知{user_name}购买了海天味业股票,购买数量为100股,购买金额为5000元,这是关于{user_name}的投资决策的重要信息。
信息:<5> <> <{user_name}购买了海天味业股票,购买数量为100股,购买金额为5000元。> <海天味业, 股票>
思考:第6句含有的信息与第1句相似,可以得知{user_name}购买了茅台股票。
信息:<6> <> <{user_name}购买了茅台股票,购买数量为100股,购买金额为50000元。> <茅台, 股票>
示例2:
{user_name}句子:
@ -64,7 +69,7 @@ get_observation_few_shot:
6 {user_name}:李增杰:这个是星座蛙设,但是我是处女座的,我妈感觉因为我的不正常,我妈不让我看了\n雌猴摸了摸李增杰的头,这样啊\n雌猴打开了哔哩哔哩看了看\n雌猴:要不换个设吧,我听你未来的你说,有一个叫难忘的朱古力232这个人,他弄的设是Windows设\n这是剧本1,剧本2未完待续
思考:从第1句可以得知{user_name}寻求购买新能源汽车的建议或推荐,这是这是关于{user_name}的大宗消费的重要的信息。
信息:<1> <> <{user_name}寻求购买新能源汽车的建议或推荐。> <购买, 新能源汽车>
思考:从第2句可以得知{user_name}当前所在城市为上海,这是关于{user_name}的生活地区的重要信息。其余信息与第1句重复了。
思考:从第2句可以得知{user_name}当前所在城市为上海,这是关于{user_name}的生活地区的重要信息。
信息:<2> <> <{user_name}所在的城市是上海。> <上海>
思考:第3句是{user_name}对某个观点的讨论和疑问,没有明确提及{user_name}个人信息。
信息:<3> <> <无> <>
@ -74,6 +79,16 @@ get_observation_few_shot:
信息:<5> <> <{user_name}购买了海天味业股票,购买数量为100股,购买金额为5000元。> <海天味业, 股票>
思考:第6句是{user_name}创作的剧本内容,无法提取{user_name}个人信息。
信息:<6> <> <无> <>
示例4:
{user_name}句子:
1 {user_name}:李子好酸啊,我不太喜欢吃。
2 {user_name}:桃子上的毛太多了,我不爱吃他。
思考:从第1句可以得知{user_name}不太喜欢吃李子。
信息:<1> <> <{user_name}不喜欢吃李子。> <李子>
思考:从第2句可以得知{user_name}不喜欢吃桃子,和上一句相似都是对某一种水果不喜欢,但是表达了不同的信息。
信息:<2> <> <{user_name}不喜欢吃桃子。> <西瓜>
en: |
Example 1:

View file

@ -20,7 +20,7 @@ class InfoFilterWorker(MemoryBaseWorker):
def _parse_params(self, **kwargs):
self.preserved_scores: str = kwargs.get("preserved_scores", "2,3")
self.info_filter_msg_max_size: int = kwargs.get("info_filter_msg_max_size", 200)
self.generation_model_top_k: int = kwargs.get("generation_model_top_k", 1)
self.generation_model_kwargs: dict = kwargs.get("generation_model_kwargs", {})
def _run(self):
"""
@ -69,7 +69,7 @@ class InfoFilterWorker(MemoryBaseWorker):
self.logger.info(f"info_filter_message={info_filter_message}")
# call llm
response = self.generation_model.call(messages=info_filter_message, top_k=self.generation_model_top_k)
response = self.generation_model.call(messages=info_filter_message, **self.generation_model_kwargs)
# return if empty
if not response.status or not response.message.content:

View file

@ -1,8 +1,8 @@
info_filter_system:
cn: |
任务:对所给{batch_size}个句子中所含有的关于{user_name}的信息打分,分数为0,1,2或3。
注意:其中0表示不包含用户信息,1表示句子中包含用户假设的信息或者用户虚构的内容比如用户创作的小说或剧本,2表示包含用户的一般信息,时效性信息或者需要猜测才能得到的用户信息,3表示明确含有或者可以确定推断出关于用户的重要信息,或者用户要求记录。
用户信息可以包含用户基本信息,用户画像信息,用户兴趣偏好信息,用户性格,用户价值观,用户重大事件转折点等等重要信息。
注意:其中0表示不包含用户信息,1表示句子中只包含用户假设的信息或者用户虚构的内容比如用户创作的小说或剧本,2表示包含用户的一般信息,时效性信息或者需要猜测才能得到的用户信息,3表示明确含有或者可以确定推断出关于用户的重要信息,或者用户要求记录。
{user_name}的重要信息可以包含用户基本信息,用户画像信息,用户兴趣偏好信息,用户性格,用户价值观,用户人际关系,用户重大事件转折点等等重要信息。
对每个句子都做一次信息打分,一共输出{batch_size}个分数。
请一定要按如下格式依次输出,最后的结果一定要加<>:
思考:思考的依据和过程,30字以内。

View file

@ -52,6 +52,7 @@ class BaseModel(metaclass=ABCMeta):
else:
kwargs = self.kwargs
self._model = obj_cls(**kwargs)
return self._model
@abstractmethod

View file

@ -49,6 +49,7 @@ class LlamaIndexGenerationModel(BaseModel):
self.data = {"messages": [ChatMessage(role=msg.role, content=msg.content) for msg in messages]}
else:
raise RuntimeError("prompt and messages are both empty!")
self.data.update(**kwargs)
def after_call(self,
model_response: ModelResponse,

View file

@ -1,9 +1,11 @@
import unittest
from memory_scope.cli import MemoryScope
from memory_scope.constants.common_constants import CHAT_MESSAGES, NEW_OBS_NODES
from memory_scope.constants.common_constants import CHAT_MESSAGES, NEW_OBS_NODES, NEW_OBS_WITH_TIME_NODES, \
MERGE_OBS_NODES
from memory_scope.enumeration.message_role_enum import MessageRoleEnum
from memory_scope.memory.worker.memory_base_worker import MemoryBaseWorker
from memory_scope.scheme.memory_node import MemoryNode
from memory_scope.scheme.message import Message
from memory_scope.utils.global_context import G_CONTEXT
from memory_scope.utils.tool_functions import init_instance_by_config
@ -42,6 +44,7 @@ class TestWorkersCn(unittest.TestCase):
result = "\n".join(result)
worker.logger.info(f"result={result}")
@unittest.skip
def test_get_observation_cn(self):
name = "get_observation"
@ -59,6 +62,7 @@ class TestWorkersCn(unittest.TestCase):
Message(role=MessageRoleEnum.USER.value, content="我不喜欢吃苹果"),
Message(role=MessageRoleEnum.USER.value, content="我准备去高考"),
Message(role=MessageRoleEnum.USER.value, content="我不喜欢吃西瓜"),
Message(role=MessageRoleEnum.USER.value, content="我不爱吃西瓜"),
Message(role=MessageRoleEnum.USER.value, content="我在一家叫京东的公司干活"),
]
@ -73,3 +77,92 @@ class TestWorkersCn(unittest.TestCase):
result = [node.content for node in worker.memory_handler.get_memories(NEW_OBS_NODES)]
result = "\n".join(result)
worker.logger.info(f"result={result}")
@unittest.skip
def test_get_observation_with_time_cn(self):
name = "get_observation_with_time"
worker: MemoryBaseWorker = init_instance_by_config(
config=G_CONTEXT.worker_config[name],
suffix_name="worker",
name=name,
is_multi_thread=False,
context={},
context_lock=None,
thread_pool=G_CONTEXT.thread_pool)
chat_messages = [
Message(role=MessageRoleEnum.USER.value, content="去年我们一起合作了因果推断技术"),
Message(role=MessageRoleEnum.USER.value, content="上个月我去了杭州旅游"),
Message(role=MessageRoleEnum.USER.value, content="下周我要去高考"),
Message(role=MessageRoleEnum.USER.value, content="明天我去北京出差"),
Message(role=MessageRoleEnum.USER.value, content="前天我把苹果扔掉了"),
Message(role=MessageRoleEnum.USER.value, content="前天我把苹果扔掉了,我不喜欢吃"),
Message(role=MessageRoleEnum.USER.value, content="明天是我生日"),
]
worker.set_context(CHAT_MESSAGES, chat_messages)
worker.run()
result = [node.content for node in worker.memory_handler.get_memories(NEW_OBS_WITH_TIME_NODES)]
result = "\n".join(result)
worker.logger.info(f"result={result}")
# @unittest.skip
def test_contra_repeat_cn(self):
name = "contra_repeat"
worker: MemoryBaseWorker = init_instance_by_config(
config=G_CONTEXT.worker_config[name],
suffix_name="worker",
name=name,
is_multi_thread=False,
context={},
context_lock=None,
thread_pool=G_CONTEXT.thread_pool)
nodes = [
MemoryNode(user_name="AI", target_name="用户", content="用户在美团干活"),
MemoryNode(user_name="AI", target_name="用户", content="用户在阿里巴巴工作"),
]
worker.memory_handler.set_memories(NEW_OBS_NODES, nodes)
worker.run()
result1 = "\n".join([" ".join([node.content, node.store_status, node.action_status])
for node in worker.memory_handler.get_memories(MERGE_OBS_NODES)])
nodes = [
MemoryNode(user_name="AI", target_name="用户", content="用户在京东工作"),
MemoryNode(user_name="AI", target_name="用户", content="用户在美团干活"),
]
worker.memory_handler.set_memories(NEW_OBS_NODES, nodes)
worker.run()
result2 = "\n".join([" ".join([node.content, node.store_status, node.action_status])
for node in worker.memory_handler.get_memories(MERGE_OBS_NODES)])
nodes = [
MemoryNode(user_name="AI", target_name="用户", content="用户在京东工作"),
MemoryNode(user_name="AI", target_name="用户", content="用户在美团干活"),
]
worker.memory_handler.set_memories(NEW_OBS_NODES, nodes)
worker.run()
result3 = "\n".join([" ".join([node.content, node.store_status, node.action_status])
for node in worker.memory_handler.get_memories(MERGE_OBS_NODES)])
nodes = [
MemoryNode(user_name="AI", target_name="用户", content="我喜欢吃西瓜"),
MemoryNode(user_name="AI", target_name="用户", content="用户在阿里巴巴干活"),
MemoryNode(user_name="AI", target_name="用户", content="我不爱吃西瓜"),
]
worker.memory_handler.set_memories(NEW_OBS_NODES, nodes)
worker.run()
result4 = "\n".join([" ".join([node.content, node.store_status, node.action_status])
for node in worker.memory_handler.get_memories(MERGE_OBS_NODES)])
worker.logger.info(f"result1={result1}")
worker.logger.info(f"result2={result2}")
worker.logger.info(f"result3={result3}")
worker.logger.info(f"result4={result4}")