快速结论:该问题出现在 RAGFlow 记忆提取(Memory extraction)流程中,当模型返回的 valid_at 为空或不是合法 ISO 8601 字符串时,会被原样写入数据库;semantic 类目约有 6.5% 的条目出现空 valid_at,并伴随日志中的 [Bug]: Memory extraction stores an empty valid_at for semantic items, and an unparseable timestamp is written through unchanged 相关报错。
适用环境:RAGFlow v0.26.4,问题发生在 memory 提取/写入服务链路(memory/utils/prompt_util.py、common/time_utils.py、api/db/joint_services/memory_message_service.py)。Issue 未提供操作系统、Python、CUDA 或显卡信息。
最快修复方案:暂无确认的一步修复方案。Issue 中确认了缺陷位置与两处修改建议(改 semantic 模板必填 timestamp、format_iso_8601_to_ymd_hms 记录被拒绝的值并返回默认值或空串),但未给出已合并的补丁版本。
注意事项:建议中的修改属于 Issue 作者与评论者确认的“正确方向”,并非官方已验证的发布修复,落地前需自行测试;同时需考虑历史数据中已写入的异常 valid_at 是否需要回补,否则排序逻辑(order_by.desc("valid_at"))仍会受影响。
问题场景
用户在 RAGFlow v0.26.4 上开启记忆(memory)功能,调用 memory 提取流程对对话内容做 semantic / episodic / procedural 多类型抽取时触发。具体触发点是 PromptAssembler.assemble_system_prompt({"memory_type": ["semantic", "episodic"]}) 生成的系统提示词,以及后续把抽取结果写入消息表的 memory_message_service.py 调用链。表现为 semantic 条目 valid_at 为空、或模型给出的时间字符串无法被解析却仍被写库;在一个约 4,132 条记录的记忆库中,144 条(占 semantic 条目的 6.5%,episodic 与 raw 为 0%)出现空 valid_at,每天可见约 20 次相关错误日志。
报错原文
[Bug]: Memory extraction stores an empty valid_at for semantic items, and an unparseable timestamp is written through unchanged
ERROR ISO string too short
日志仅包含异常消息(例如 ISO string too short),不包含字段名、被拒绝的值、所属 memory 或 message 信息。
原因分析
两个缺陷叠加导致该现象:
原因一:输出模板不对称。在 memory/utils/prompt_util.py 的 OUTPUT_TEMPLATES 中,不同类型对 valid_at 的声明不一致:semantic 写作 "timestamp or empty"(模型读作可选),而 episodic 为 "event start timestamp"、procedural 为 "procedure effective timestamp"(明确必填)。这与 SYSTEM_BASE_TEMPLATE 中的 Each extracted item MUST have: content, valid_at, invalid_at 以及 semantic 的 Default: valid_at = conversation time 相矛盾。模型倾向于遵循格式块,于是 semantic 条目出现空 valid_at,分布与模板不对称完全吻合。
原因二:解析失败后静默写穿。common/time_utils.py 的 format_iso_8601_to_ymd_hms 在解析异常时只记录 str(e),然后把原始字符串原样返回。调用点 api/db/joint_services/memory_message_service.py 中,valid_at 直接透传、没有像 invalid_at 那样做空值保护(if extracted_content.get("invalid_at")),因此空值或脏时间戳被直接持久化进时间列。
可能影响:valid_at 参与 MessageService.list_message 的 order_by.desc("valid_at") 排序,也是事实的时间有效性字段;无时间戳的条目会排在最后,无法参与任何时效性/最近性逻辑。
环境排查
- 确认 RAGFlow 版本是否为 v0.26.4(Issue 观察版本)。
- 确认 memory 提取是否同时启用了 semantic 与其他类型,便于对比 6.5% 与 0% 的分布。
- 检查
memory/utils/prompt_util.py中OUTPUT_TEMPLATES的 semantic / episodic / procedural 三处valid_at声明是否一致。 - 检查
common/time_utils.py的format_iso_8601_to_ymd_hms异常分支是否仍返回time_str。 - 检查
api/db/joint_services/memory_message_service.py调用点对valid_at是否有空值守卫。 - Issue 未提供 Python、CUDA、PyTorch、显卡或依赖版本,相关项无需核对。
解决步骤
- 统计当前记忆库中
valid_at为空的记录数与类型分布,确认是否集中在 semantic,并核对是否接近 6.5% 量级。 - 检索日志中的
ERROR ISO string too short类异常条目,评估每天出现频率(Issue 中约 20 次/天),确认存在静默写穿。 - 按 Issue 建议修改 semantic 的输出模板,使其要求时间戳,例如改成
"valid_at": "timestamp — use the conversation time when the fact has no date of its own",与上下文的 MUST have 及 Default 规则对齐。 - 按 Issue 建议修改
format_iso_8601_to_ymd_hms:在异常分支中连同被拒绝的值一起记录,并改为抛出异常或替换为显式默认值(含空字符串),而不再把未解析字符串写入时间列。 - 为
memory_message_service.py调用点的valid_at增加与invalid_at一致的空值/格式防护。 - 对已落库的异常
valid_at数据做清理或回补,避免影响order_by.desc("valid_at")排序与时效逻辑。
验证方法
改动后重新跑一轮 memory 提取,检查 semantic 条目是否仍出现空 valid_at;确认日志中不再出现只含 ISO string too short 这类无上下文的错误,且解析失败时能看到被拒绝的值或得到预期的默认值/异常;同时复核 list_message 按 valid_at 降序返回的顺序是否符合预期。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。

![[Bug]: rag/res/term.freq is loaded by term_weight but not shipped — every lowercase Latin token gets the same IDF](https://www.chat-gpts.plus/wp-content/uploads/2026/09/18414-d3efad56-768x403.jpg)
