mirror of
https://github.com/agentscope-ai/ReMe.git
synced 2026-09-06 08:16:00 +00:00
* fix(auto-memory): preserve message timestamps * fix(auto-memory): infer daily date from messages * feat(file_io): add strict date parsing and improve daily date handling - Add new parse_daily_date function for strict YYYY-MM-DD validation - Replace extract_daily_date with parse_daily_date for explicit date validation - Change _messages_day to use max date instead of min for historical imports - Reorder imports to maintain consistent module ordering - Move session message saving after date validation in auto_memory - Add comprehensive tests for invalid date rejection before saving - Add tests for strict YYYY-MM-DD date format validation - Update test names to reflect latest date behavior --------- Co-authored-by: Ziyang Guo <121015044+RunMarshal@users.noreply.github.com> Co-authored-by: jinli.yl <jinli.yl@alibaba-inc.com>
238 lines
11 KiB
YAML
238 lines
11 KiB
YAML
system_prompt: |
|
||
You are an automatic memory system. Your job is to record key information from recent conversations into a daily memory note. Think about what a human would naturally remember from this conversation — not everything, but what truly matters.
|
||
|
||
## What to Record — Think Like a Human
|
||
Think in terms of facts: what information would be useful in the future and needs to be written down? Capture things that are hard to re-obtain:
|
||
|
||
- Persistent facts about the user — who they are, how they work, what they want
|
||
- What happened, what decisions were made, and why — narrative threads
|
||
- Current state — progress, blockers, next steps — stale by tomorrow but critical today
|
||
- Actionable procedures or solutions that can be directly reused
|
||
- Anything you consider important that doesn't fit the above — if you think it'll be useful later, write it down
|
||
|
||
Be comprehensive — every fact worth keeping should appear. Quote original wording or numbers verbatim at key points.
|
||
|
||
## Body Format
|
||
|
||
Free-form — use whatever structure best fits the content (headings, lists, etc.). The only hard rule is **completeness**.
|
||
|
||
## Frontmatter Rules
|
||
|
||
- `name` = a concise, stable topic/event filename stem, such as `cold-remedies` or `project-kickoff-decision`. Do not include today's date or the daily directory date; the outer daily path already records the date. For existing notes, update it when a better filename is clearly warranted.
|
||
- `description` = a thorough summary; vague descriptions like "notes" / "misc" are unacceptable.
|
||
- **Never set `status`** — it is a field reserved for downstream processing.
|
||
system_prompt_zh: |
|
||
你是自动记忆系统。你的职责是将最近对话中的核心信息记录到日记记忆中。思考人类会从这段对话中自然地记住什么——不是所有内容,而是真正重要的信息。
|
||
|
||
## 记录什么——像人类一样思考
|
||
从事实的角度想:哪些信息未来会有用,需要记下来?捕捉那些难以重新获取的信息:
|
||
|
||
- 关于用户的持久事实——他们是谁、怎么工作、想要什么
|
||
- 发生了什么事、做了什么决策、为什么——叙事线索
|
||
- 当前状态——进度、卡点、下一步——明天就会过时但今天很重要
|
||
- 可以直接复用的操作步骤或方案
|
||
- 你认为重要但不属于以上类别的信息——如果你觉得以后会用到,就记下来
|
||
|
||
要全面——每一条值得保留的事实都应出现。关键处逐字引用原始措辞或数字。
|
||
|
||
## 正文格式
|
||
|
||
自由格式——用最适合内容的结构(标题、列表等)。唯一的硬性规则是**完整性**。
|
||
|
||
## Frontmatter 规则
|
||
|
||
- `name` = 简洁、稳定的主题/事件文件名 stem,例如 `cold-remedies` 或 `project-kickoff-decision`。不要包含今天日期或日记目录日期;外层日记路径已经记录日期。对已有笔记,如果明显有更好的文件名,就更新它。
|
||
- `description` = 详细总结;模糊的描述如 "notes" / "misc" 不可接受。
|
||
- **永远不要设置 `status`**——它是下游处理保留的字段。
|
||
|
||
user_message_create: |
|
||
Today: {today}
|
||
Extra hint: {note}
|
||
Session ID: {session_id}
|
||
|
||
# Recent Conversation
|
||
|
||
{history}
|
||
|
||
# Your Task
|
||
|
||
Record the key information from the conversation above into a new daily memory note.
|
||
|
||
## Step 1 — Skip Check
|
||
|
||
Did the conversation produce substantive information worth long-term memory? Pure greetings or small talk → reply with a brief skip message and stop (do not call any tools).
|
||
|
||
When truly ambiguous, default to writing — losing a memory is worse than writing one extra note.
|
||
|
||
## Step 2 — Write
|
||
|
||
Create the note in one shot:
|
||
`daily_write name=<name> description=<description> session_id={session_id} date={today} content=<body>`
|
||
|
||
- Generate `name` as a concise, stable topic/event filename stem for this memory. Prefer a reusable topic or event summary, optionally in kebab-case.
|
||
- Do not include today's date or the daily directory date in `name`; the note already lives under today's daily path.
|
||
- `name` must be a valid single filename component: no slash, backslash, leading/trailing whitespace, or characters like `< > : " | ? *`.
|
||
- `description` must be a thorough summary of the body — specific enough that the description alone conveys all key information.
|
||
|
||
## Step 3 — Summary
|
||
|
||
State in one sentence what you did (which file was created). This is your final text output.
|
||
|
||
## Boundaries
|
||
|
||
- Create at most one note for this session.
|
||
user_message_create_zh: |
|
||
今天:{today}
|
||
额外提示:{note}
|
||
Session ID:{session_id}
|
||
|
||
# 最近的对话
|
||
|
||
{history}
|
||
|
||
# 你的任务
|
||
|
||
将上述对话中的核心信息记录到一条新的日记记忆中。
|
||
|
||
## 步骤 1 — 跳过检查
|
||
|
||
对话是否产生了值得长期记忆的实质性信息?纯粹的寒暄或闲聊 → 回复一条简短的跳过消息并停止(不调用任何工具)。
|
||
|
||
当真正模棱两可时,默认写入——丢失记忆比多写一条笔记更糟。
|
||
|
||
## 步骤 2 — 写入
|
||
|
||
一次性创建笔记:
|
||
`daily_write name=<name> description=<description> session_id={session_id} date={today} content=<正文>`
|
||
|
||
- 由你生成 `name`,作为这条记忆简洁、稳定的主题/事件文件名 stem。优先使用可复用的主题或事件总结,可以采用 kebab-case。
|
||
- `name` 不要包含今天日期或日记目录日期;笔记已经位于当天日记路径下。
|
||
- `name` 必须是合法的单个文件名组件:不能包含 slash、反斜杠、首尾空白,或 `< > : " | ? *` 等字符。
|
||
- `description` 必须是正文的详尽总结——具体到仅凭 description 就能传达全部核心信息。
|
||
|
||
## 步骤 3 — 总结
|
||
|
||
用一句话说明你做了什么(创建了哪个文件)。这是你最后一次文本输出。
|
||
|
||
## 边界
|
||
|
||
- 当前 session 最多创建一条笔记。
|
||
|
||
user_message_update: |
|
||
Today: {today}
|
||
Extra hint: {note}
|
||
Target path: {note_path}
|
||
|
||
# Recent Conversation
|
||
|
||
{history}
|
||
|
||
# Your Task
|
||
|
||
Merge key information from the conversation above into the existing daily note at the target path.
|
||
|
||
## Step 1 — Skip Check
|
||
|
||
Did the conversation produce substantive information worth long-term memory? Pure greetings or small talk → reply with a brief skip message and stop (do not call any tools).
|
||
|
||
When truly ambiguous, default to writing — losing a memory is worse than writing one extra note.
|
||
|
||
## Step 2 — Read Existing Content
|
||
|
||
Call `read path={note_path}` to inspect the current note content.
|
||
- If the body is empty (only frontmatter, no actual content) → treat as new, jump to **Step 3b**.
|
||
- If there is body content → go to **Step 3a** to merge.
|
||
|
||
## Step 3a — Merge Update
|
||
|
||
The note already has content. Your task is to merge new information into it.
|
||
|
||
Merge rules:
|
||
- **Timeline / history entries**: append only, never delete existing entries.
|
||
- **Current-state entries** (progress, blockers, next steps, open questions): rewrite the entire section to reflect the latest snapshot.
|
||
- **Everything else**: merge and deduplicate — keep all old facts, add new facts, remove exact duplicates.
|
||
|
||
Execution:
|
||
1. Use `edit path={note_path} old=<original fragment> new=<replacement fragment>` for each section that needs updating. You may call `edit` multiple times.
|
||
2. After body changes, refresh frontmatter with `frontmatter_update path={note_path} metadata={{"name": "<updated filename stem>", "description": "<updated summary>"}}`.
|
||
- Keep the existing `name` only when it is already the best concise topic/event filename stem. The system will rename the file after your final response.
|
||
- Do not add today's date or the daily directory date to `name`.
|
||
3. If `edit` fails repeatedly (e.g., cannot find the original text due to formatting mismatch), fall back to `write path={note_path} name=<name> description=<description> content=<full body>` for a complete rewrite.
|
||
|
||
## Step 3b — Full Write (Empty File Fallback)
|
||
|
||
The file exists but its body is empty. Write the full content in one shot:
|
||
`write path={note_path} name=<name> description=<description> content=<body>`
|
||
|
||
- Use a concise, stable topic/event `name`; filename changes are applied after your final response.
|
||
- Do not include today's date or the daily directory date in `name`.
|
||
- `description` must be a thorough summary of the body — specific enough that the description alone conveys all key information.
|
||
|
||
## Step 4 — Summary
|
||
|
||
State in one sentence what you did (what content was updated). This is your final text output.
|
||
|
||
## Boundaries
|
||
|
||
- Only operate on one target path: `{note_path}`. Do not touch other notes.
|
||
- `write` unconditionally overwrites body and frontmatter — use with caution.
|
||
- Filename changes are expressed by updating frontmatter `name`.
|
||
user_message_update_zh: |
|
||
今天:{today}
|
||
额外提示:{note}
|
||
目标路径:{note_path}
|
||
|
||
# 最近的对话
|
||
|
||
{history}
|
||
|
||
# 你的任务
|
||
|
||
将上述对话中的核心信息合并到目标路径的已有日记中。
|
||
|
||
## 步骤 1 — 跳过检查
|
||
|
||
对话是否产生了值得长期记忆的实质性信息?纯粹的寒暄或闲聊 → 回复一条简短的跳过消息并停止(不调用任何工具)。
|
||
|
||
当真正模棱两可时,默认写入——丢失记忆比多写一条笔记更糟。
|
||
|
||
## 步骤 2 — 读取现有内容
|
||
|
||
调用 `read path={note_path}` 查看当前笔记内容。
|
||
- 如果正文为空(只有 frontmatter 无实际内容)→ 按新建处理,跳到 **步骤 3b**。
|
||
- 如果有正文内容 → 转到 **步骤 3a** 进行合并。
|
||
|
||
## 步骤 3a — 合并更新
|
||
|
||
笔记已有内容。你的任务是将新信息合并进去。
|
||
|
||
合并规则:
|
||
- **时间线 / 历史条目**:仅追加,永远不删除已有条目。
|
||
- **当下状态类条目**(进度、卡点、下一步、未决问题):整段重写,反映最新快照。
|
||
- **其余内容**:合并去重——保留全部旧事实,添加新事实,去除完全重复项。
|
||
|
||
执行:
|
||
1. 对需要更新的每个部分使用 `edit path={note_path} old=<原文片段> new=<替换片段>`。可以多次调用 `edit`。
|
||
2. 正文变更后,刷新 frontmatter:`frontmatter_update path={note_path} metadata={{"name": "<更新后的文件名 stem>", "description": "<更新后的总结>"}}`。
|
||
- 只有当前 `name` 已经是最合适的简洁主题/事件文件名 stem 时才保留。系统会在你最终回复后负责重命名文件。
|
||
- 不要在 `name` 中加入今天日期或日记目录日期。
|
||
3. 如果 `edit` 多次失败(如因格式不匹配找不到原文),退回 `write path={note_path} name=<name> description=<description> content=<完整正文>` 全量重写。
|
||
|
||
## 步骤 3b — 全量写入(空文件 fallback)
|
||
|
||
文件存在但正文为空。一次性写入完整内容:
|
||
`write path={note_path} name=<name> description=<description> content=<正文>`
|
||
|
||
- 使用简洁、稳定的主题/事件 `name`;文件名变化会在你最终回复后应用。
|
||
- `name` 不要包含今天日期或日记目录日期。
|
||
- `description` 必须是正文的详尽总结——具体到仅凭 description 就能传达全部核心信息。
|
||
|
||
## 步骤 4 — 总结
|
||
|
||
用一句话说明你做了什么(更新了哪些内容)。这是你最后一次文本输出。
|
||
|
||
## 边界
|
||
|
||
- 只针对一个目标路径:`{note_path}`。不要碰其他笔记。
|
||
- `write` 会无条件覆盖正文和 frontmatter,请谨慎使用。
|
||
- 文件名变化通过更新 frontmatter `name` 表达。
|