ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

【fay-java】6-认知记忆系统,让数字人牢记

2026/9/29 20:09:06 拓冰建站 浏览量
【fay-java】6-认知记忆系统,让数字人牢记 fay-java 认知记忆系统genagents memory_stream 的纯 Java 复刻让数字人「记得住你」摘要本文拆解开源数字人框架 fay-java 的认知记忆系统——它让数字人从一个「无状态应答机」变成「有记忆、会反思、能画像」的长期陪伴型助手。全文讲清四件事①ConceptNode记忆节点的数据结构② 检索打分的三重公式相关性 × 时近性 × 重要性③ 异步写入「先计算、后持锁」的并发设计④ 定时反思与画像分析。含检索打分图、写入时序图与关键代码骨架。一、为什么数字人需要「记忆」一个能聊天的数字人如果没有记忆每次对话都是「第一次见你」——昨天你说过喜欢什么、上次聊到哪全都忘光。fay 的解决方案是一套叫genagents memory_stream的认知记忆流fay-java 把它用纯 Java 1:1 复刻了。它的核心思想是把「记忆」建模成一堆带权重的节点ConceptNode通过重要性评分 embedding 检索 定时反思来「记住该记的、忘掉该忘的」。二、数据结构ConceptNode一个记忆节点长这样{node_id:...,description:用户说他喜欢猫,created:2026-09-21T10:00:00,last_accessed:2026-09-21T12:00:00,importance:8,embedding:[0.12,-0.34,...],node_type:observation}对应的 Java POJO核心思路示意classConceptNode{StringnodeId;Stringdescription;// 用户说他喜欢猫LocalDateTimecreated;LocalDateTimelastAccessed;doubleimportance;// 0-10double[]embedding;StringnodeType;// observation / reflection}字段名与 Python 版 JSON 落盘完全一致Jackson POJO 对齐所以两版的记忆文件可以双向互换——Java 能读 Python 写出的nodes.jsonPython 也能读 Java 写出的。三、检索打分相关性 × 时近性 × 重要性检索一个记忆用的是三重打分score recency时近性× relevanceembedding 余弦相似度× importance重要性检索查询记忆流 nodesrelevanceembedding 余弦相似度recency时近性衰减importance重要性各自 min-max 归一化score recency × relevance × importanceTop-N 记忆注入提示词三个分量各自 min-max 归一化权重对齐 Python 的hp[recency_w, relevance_w, importance_w]。这样检索出来的是「最近、最相关、最重要」的记忆而不是简单地「文本里出现关键词」。四、记忆的写入先计算后持锁记忆写入不是同步阻塞在对话里而是异步线程池MemoryWriter进程单例。关键在次序nodes.jsonMemoryStreamEmbeddingClientImportanceScorer(LLM)MemoryWriter(异步线程池)对话收尾nodes.jsonMemoryStreamEmbeddingClientImportanceScorer(LLM)MemoryWriter(异步线程池)对话收尾先计算不持锁remember_conversation(question, answer)1importance 打分(1-10)2embedding 向量化3持锁 add save4刷盘 nodes.json / embeddings.json5// 核心思路示意先计算 importanceembedding再持锁写入voidremember(Stringuser,Stringtext){doubleimportanceimportanceScorer.score(text);// ① 网络调用不持锁double[]embembeddingClient.embed(text);// ② 网络调用不持锁lock.lock();// ③ 最后才持锁try{stream(user).add(text,importance,emb);stream(user).save();}finally{lock.unlock();}}这个次序对齐 Python 版「先计算后持锁」避免了「持锁期间还在等 LLM/embedding 网络调用」导致的锁长时间占用。ImportanceScorer做 0-100 整数评分fail-safe 25、解析失败默认 50——即使 LLM 打分失败记忆也不会丢只是给个保守值。五、反思与画像让记忆「长出新认知」记忆不只是被动堆积还会「反思」和「归纳」定时反思MemoryScheduler每日 23:00按星期轮换主题检索 → LLM 生成第一人称反思 → importance 打分 → 继承业务 tags → 落node_typereflection且pointer_id源节点 id 列表画像分析每日 11:30LLM 更新后写T_Member.user_portrait形成用户画像定时保存10 分钟Java 侧比 Python每日 00:00 退出保存更频繁降低异常退出丢记忆的风险。MemoryStream的核心接口核心思路示意classMemoryStream{ListConceptNodenodes;Pathdir;// memory/user/memory_stream/ConceptNodeadd(Stringdesc,doubleimportance,double[]embedding);ListConceptNoderetrieve(ListStringfocalPoints,intn);// 三重打分voidreflect();// 定时反思voidsave();voidload();// JSON 落盘与 Python 双向兼容}六、一个被「删除」的开关use_bionic_memory读代码时会看到一个use_bionic_memory配置但它在 Java 侧不再做任何分支。原因是仿生记忆bionic memory在 Python 上游 2026-03 就整体移除了只剩读写、没有消费方。Java 侧干脆删掉了这个门禁记忆恒走认知记忆流Cfg.useBionicMemory()保留为Deprecated兼容读取。这个细节值得记重写项目时遇到「上游遗留的无用配置」要追根溯源确认它是不是死代码而不是机械照搬。七、Embedding 的选择核心记忆不用 chromadbchroma 只在 Python 的 demo MCP 服务器里出现。真实记忆走 API embeddingEmbeddingClient单例启动预热探测维度请求前清洗 think 标签对齐api_embedding_service.py走 DashScope compatible-mode 的/v1/embeddingsOpenAI 兼容协议。本地 embeddingsentence_transformers没有迁移统一走云端 API——这也是 fay-java 少掉的一大坨 native 依赖。八、小结认知记忆系统的设计可以归纳为结构化节点 三重打分检索相关性 × 时近性 × 重要性异步写入 先计算后持锁避免锁内等网络定时反思 画像分析记忆主动「长出新认知」文件级双向兼容与 Python 版记忆文件互换清理上游死代码use_bionic_memory 门禁。这让数字人从一个「无状态应答机」变成一个「有记忆、会反思、能画像」的长期陪伴型助手。项目地址Giteehttps://gitee.com/liutao-lx/fay-javaGitHubhttps://github.com/liutao-lx/fay-java如果这篇文章对你有帮助欢迎点赞、收藏、关注对项目本身感兴趣的去 Gitee / GitHub 点个Star。下一篇《MCP 双端数字人如何调用工具、又把自己变成工具》。