当前位置: 首页 > news >正文

大模型:长期记忆的智能判断逻辑 MD5组件

补齐短板:长期记忆的智能判断逻辑

在面试中,你需要展示你不仅知道“长期记忆和短期记忆的区别”,还要知道“如何设计一个系统,让 Agent 自动决定该记住什么,该遗忘什么”。下面是一个完整的设计方案和代码实现,涵盖了三层过滤机制:语义分类 → 重要性评分 → 摘要压缩


🧠 设计目标

  • 长期记忆:存储对用户有长期价值的信息(如姓名、喜好、职业、重要计划)。
  • 短期记忆:存储当前会话的上下文,用于多轮对话。
  • 自动决策:每次收到用户消息后,系统自动判断该消息是否值得存入长期记忆。

🏗️ 架构与流程

用户输入 ↓ ① 语义分类(意图识别) ├── 个人信息(姓名、年龄、职业)→ 高优先级 ├── 偏好设置(喜欢什么、讨厌什么)→ 高优先级 ├── 重要事件(计划、承诺)→ 中优先级 └── 闲聊、问候、无关问题 → 低优先级 ↓ ② 重要性评分(规则 + 小模型) - 计算实体数量(人名、地名、日期) - 情感强度 - 是否包含“记住”、“以后”等关键词 - 综合得分 0~1 ↓ ③ 决定是否存储 - 如果得分 > 阈值(如 0.6)→ 存入长期记忆(向量库) - 否则 → 只保留在短期记忆中(会话窗口) ↓ ④ 定期摘要压缩(每周/每月) - 对长期记忆中的相似内容合并 - 对旧的短期记忆做摘要,提炼关键信息存入长期记忆

💻 代码实现(LangChain + 简单规则)

以下是一个完整的MemoryManager类,它实现了上述三层逻辑。

importrefromtypingimportList,Dict,Anyfromlangchain.embeddingsimportOpenAIEmbeddingsfromlangchain.vectorstoresimportChromafromlangchain.llmsimportOpenAIfromlangchain.chainsimportLLMChainfromlangchain.promptsimportPromptTemplatefromlangchain.schemaimportDocumentimportnumpyasnpclassMemoryManager:def__init__(self,llm,embeddings,vectorstore):self.llm=llm self.embeddings=embeddings self.vectorstore=vectorstore self.conversation_history=[]# 短期记忆(会话内)self.long_term_memory=[]# 长期记忆(文档列表)self.importance_threshold=0.6# 定义规则库(用于快速过滤)self.high_priority_keywords=["我叫","我的名字是","我是","喜欢","讨厌","爱好","生日","职业","工作"]self.medium_priority_keywords=["计划","打算","约定","答应","承诺","以后"]def_classify_intent(self,text:str)->str:"""① 语义分类:基于规则快速判断意图"""text_lower=text.lower()ifany(kwintext_lowerforkwin["我叫","我的名字是","我是"]):return"personal_info"ifany(kwintext_lowerforkwin["喜欢","讨厌","爱好","偏好"]):return"preference"ifany(kwintext_lowerforkwin["计划","打算","约定","承诺","以后"]):return"important_event"ifany(kwintext_lowerforkwin["今天天气","你好","谢谢"]):return"chitchat"return"unknown"def_compute_importance_score(self,text:str,intent:str)->float:"""② 计算重要性得分(0~1)"""score=0.0# 基于意图的基础分intent_score_map={"personal_info":0.9,"preference":0.8,"important_event":0.7,"chitchat":0.2,"unknown":0.3}score+=intent_score_map.get(intent,0.3)# 实体数量加分(人名、地名、日期)entity_count=len(re.findall(r'[\u4e00-\u9fa5]{2,4}',text))# 简单中文名字/地点ifentity_count>=2:score+=0.1# 包含“记住”、“以后”等词加分ifany(kwintextforkwin["记住","以后","一定","务必"]):score+=0.1# 长度加分(较长的消息可能包含更多信息)iflen(text)>20:score+=0.05# 情感强度(简单规则:包含“很”、“非常”、“特别”)ifany(kwintextforkwin["很","非常","特别","超级"]):score+=0.05returnmin(score,1.0)def_needs_long_term_storage(self,text:str)->bool:"""③ 综合判断:是否存入长期记忆"""intent=self._classify_intent(text)score=self._compute_importance_score(text,intent)print(f"[评估] 消息: '{text[:30]}...' 意图:{intent}, 得分:{score:.2f}")returnscore>=self.importance_thresholddefadd_message(self,role:str,content:str):"""处理一条新消息(来自用户或AI)"""# 先存入短期记忆(不管是否重要)self.conversation_history.append({"role":role,"content":content})# 只对用户消息做长期存储判断ifrole=="user":ifself._needs_long_term_storage(content):# 存入长期记忆(向量库)doc=Document(page_content=content,metadata={"source":"user","timestamp":"now"})self.vectorstore.add_documents([doc])self.long_term_memory.append(content)print(f"[长期记忆] 已存储:{content}")defget_conversation_context(self,max_turns=5):"""获取短期记忆(最近N轮)"""returnself.conversation_history[-max_turns*2:]defget_long_term_memories(self,query:str,k=3):"""从长期记忆中检索相关内容(RAG)"""docs=self.vectorstore.similarity_search(query,k=k)return[doc.page_contentfordocindocs]defsummarize_long_term_memories(self):"""④ 摘要压缩:定期对长期记忆做合并和压缩"""# 如果长期记忆条目超过50条,触发摘要iflen(self.long_term_memory)>50:prompt=PromptTemplate.from_template("以下是用户的所有长期记忆条目,请将它们合并成一份简洁的摘要(保留关键个人信息和事件):\n{memories}\n\n摘要:")chain=LLMChain(llm=self.llm,prompt=prompt)summary=chain.run(memories="\n".join(self.long_term_memory))# 清空旧记忆,存入摘要(实际生产可保留部分最新)self.vectorstore.delete_collection()new_doc=Document(page_content=summary,metadata={"type":"summary"})self.vectorstore.add_documents([new_doc])self.long_term_memory=[summary]print(f"[摘要] 长期记忆已压缩为:{summary[:100]}...")

🧪 测试示例

fromlangchain_openaiimportChatOpenAI,OpenAIEmbeddingsfromlangchain.vectorstoresimportChroma# 初始化组件llm=ChatOpenAI(model="gpt-3.5-turbo",temperature=0)embeddings=OpenAIEmbeddings()vectorstore=Chroma(collection_name="long_term_memory",embedding_function=embeddings)# 创建记忆管理器mem_manager=MemoryManager(llm,embeddings,vectorstore)# 模拟对话user_inputs=["你好,我叫张三,是一名软件工程师。","我今天心情不错。","我喜欢打篮球和看电影。","北京今天天气怎么样?","我计划下个月去日本旅游。","谢谢你的帮助。",]formsginuser_inputs:mem_manager.add_message("user",msg)print("---")# 查询长期记忆query="我的职业是什么?"results=mem_manager.get_long_term_memories(query,k=2)print(f"查询结果:{results}")# 获取短期上下文context=mem_manager.get_conversation_context(max_turns=3)print(f"最近对话:{context}")

输出示例(可能因模型和阈值不同而略有差异):

[评估] 消息: '你好,我叫张三,是一名软件工程师。...' 意图: personal_info, 得分: 0.95 [长期记忆] 已存储: 你好,我叫张三,是一名软件工程师。 --- [评估] 消息: '我今天心情不错。...' 意图: chitchat, 得分: 0.25 --- [评估] 消息: '我喜欢打篮球和看电影。...' 意图: preference, 得分: 0.85 [长期记忆] 已存储: 我喜欢打篮球和看电影。 --- ... 查询结果: ['你好,我叫张三,是一名软件工程师。', '我喜欢打篮球和看电影。']

🗣️ 面试回答话术

“在设计长期记忆系统时,我采用了三层判断逻辑:

  1. 语义分类:我预先定义了一组规则(或小模型),将用户输入分为个人信息、偏好、重要事件、闲聊等类别。个人信息(如姓名、职业)和偏好会被标记为高优先级。
  2. 重要性评分:对于每一条用户消息,我会计算一个综合得分,考量因素包括:是否包含姓名/地点等实体、是否包含承诺性词汇(如‘以后’、‘一定’)、消息长度、情感强度等。得分超过阈值(如0.6)才会被存入长期记忆。
  3. 摘要压缩:为了防止长期记忆无限膨胀,我会定期对存储的内容进行摘要合并。当条目过多时,使用LLM将多条记忆压缩成一段概述,既保留关键信息,又节省存储空间。

这套方案结合了规则引擎的快速性和LLM的语义理解能力,在实际项目中取得了不错的效果。当然,如果资源允许,我会用一个小型的分类器模型(如BERT)替换规则,进一步提升判断精度。”

MD5 组件:哈希世界的“老牌主力”

1. MD5 是什么?

MD5(Message Digest Algorithm 5,消息摘要算法第五版)是一种广泛使用的密码学哈希函数,由 Ronald Rivest 于 1991 年设计。它接收任意长度的输入,输出一个128 位(16 字节)的固定长度哈希值,通常表示为 32 位的十六进制字符串(例如d41d8cd98f00b204e9800998ecf8427e)。

在 Python 中,MD5 通过内置的hashlib模块提供:

importhashlib md5=hashlib.md5()md5.update(b"hello world")print(md5.hexdigest())# 输出: 5eb63bbbe01eeed093cb22bb8f5acdc3

2. MD5 的核心特性

特性说明
固定长度无论输入多大,输出始终是 128 位(16 字节)。
单向性无法从哈希值反推出原始输入(理论上)。
雪崩效应输入微小变化会导致输出巨大变化。
快速计算计算速度快,适合大量数据。
碰撞风险已被证明存在理论碰撞(两个不同输入产生相同哈希),不适用于安全场景。

3. MD5 在 LLM/RAG 项目中的典型应用(结合你的经历)

在你之前的 Excel 比较智能体代码中,hashlib.md5被用来生成文件的版本指纹,以判断两次上传的内容是否发生变化:

content_hash=hashlib.md5(json.dumps(all_sheets).encode()).hexdigest()

为什么要这样做?

  • 避免重复处理相同内容的文件(去重)。
  • 快速判断文件是否被修改,无需逐行比较整个文件。
  • 作为缓存键(例如,如果哈希没变,直接从缓存返回结果)。

除此之外,MD5 在 RAG 系统中还有这些常见用途:

场景说明
文本块去重对切分后的 Chunk 生成哈希,在入库前检查是否已存在,避免重复向量化。
缓存键生成将用户 Query 的 MD5 作为缓存键,相同问题直接返回缓存答案,降低 LLM 调用成本。
数据完整性校验确保传输的文档(如上传的 PDF)未被篡改。
版本跟踪对知识库的增量更新时,只更新发生变化的片段(通过比对哈希)。

4. MD5 的安全隐患(面试重点!)

重要结论:MD5 已不再安全,不应在安全敏感场景中使用(如密码存储、数字证书)。

  • 碰撞攻击:2004 年研究人员已发现 MD5 的碰撞方法,两个不同文件可生成相同哈希。2010 年进一步改进,普通 PC 也能快速制造碰撞。
  • 破解速度:如今 GPU 可在数秒内破解短密码的 MD5 哈希。

替代方案

场景推荐算法
密码存储使用bcryptPBKDF2Argon2(加盐、迭代)
文件完整性校验使用SHA-256SHA-3
去重/缓存键仍可用 MD5(非安全场景,追求速度)

5. 面试高频追问与回答

Q1:MD5 和 SHA-256 有什么区别?

对比维度MD5SHA-256
输出长度128 位256 位
安全性低(已被攻破)高(至今无有效碰撞)
速度极快较慢(但现代硬件可接受)
适用场景非安全去重、缓存安全场景(数字签名、文件校验)

Q2:既然 MD5 不安全,为什么还在用?
A:因为它的速度优势在非安全场景中依然显著,例如去重、缓存、版本检测,这些场景不需要防御恶意碰撞。但如果是涉及用户隐私或防篡改的场景,必须弃用。

Q3:在 LangChain/RAG 系统中,你如何用 MD5 优化性能?
A:我会对文档块(Chunk)生成 MD5 哈希作为文档 ID,存入向量库时检查 ID 是否存在,实现增量更新。另外,对高频 Query 做 MD5 缓存键,减少 LLM 调用成本(但需配合时效性设计,如 TTL)。

Q4:如何应对 MD5 的碰撞问题?
A:在安全场景,我使用 SHA-256 或 SHA-3。在非安全场景(如去重),碰撞概率极低(2^128),且即使发生也无大碍,因此可以接受。


6. 实战代码示例(结合 LangChain)

importhashlibfromlangchain.schemaimportDocumentdefget_document_id(doc:Document)->str:"""使用 MD5 生成文档唯一 ID(基于内容+元数据)"""content=doc.page_content meta_str=str(sorted(doc.metadata.items()))combined=content+meta_strreturnhashlib.md5(combined.encode('utf-8')).hexdigest()# 使用示例doc=Document(page_content="hello world",metadata={"source":"test.txt"})doc_id=get_document_id(doc)print(f"文档 ID:{doc_id}")

7. 总结话术(面试收尾)

“MD5 是一个经典的哈希算法,虽然因为碰撞问题不再适合安全场景,但它在去重、缓存和版本控制等性能敏感场景中依然有巨大价值。在实际项目中,我会区分用途:用 MD5 做快速指纹生成,用 SHA-256 做数据完整性校验,用 bcrypt 做密码存储。理解每个算法的强弱,是工程选型的基本功。”

http://www.jsqmd.com/news/1139457/

相关文章:

  • Redis集群创建时出现“Node xxx.xxx is not empty”问题处理
  • PyTorch 2.0 参数初始化实战:3种方法对比,MNIST 训练提速 15%
  • YimMenu技术架构深度解析:从游戏逆向工程到现代C++菜单设计
  • 位运算知识点
  • 布:AI 驱动的 Redis 客户端,更快、更直观
  • PyTorch 1.13 CIFAR-10 图像分类实战:5层CNN网络实现85%+准确率
  • 机器学习经典任务
  • 软考中高级备考避坑指南|十四年机构真实通过率与高效上岸方案
  • XSS靶场通关全解析:从基础注入到高级绕过实战
  • 微信二次开发实战:别再用笨办法同步消息了,教你用回调打通内部业务后台
  • Linux Shell全面学习实操总结
  • Mac本地AI修图工具极影AI:安装配置与创成式填充功能实测指南
  • 如何免费高效下载全网音乐:开源工具MusicDownload完整指南
  • Java毕业设计-基于 SpringBoot+Vue 的病人病历管理系统的设计与实现 基于 Web 的病历信息管理系统(源码+LW+部署文档+全bao+远程调试+代码讲解等)
  • 8G显存本地部署AI漫剧生成:从Stable Diffusion到视频合成全流程
  • RAG解决复杂问题—多跳推理
  • Vidu S1:全球领先的实时交互模型
  • OpenCV cv2.cvtColor 与 NumPy 切片转换:3 种方法性能与内存实测对比
  • 后量子密码学:基于Gabidulin码的McEliece加密与量子深度优化
  • 零基础 GPT5.5 提问技巧:告别模糊提问,获取精准答案
  • 3分钟掌握League Akari:英雄联盟自动化工具箱完整指南
  • 激光驱动电路PCB布局实战:4项关键措施将谐振拖尾电流降低80%
  • PKHeX.Mobile:跨平台手机版宝可梦存档编辑器完整指南
  • 写入与查询全链路:vminsert → vmstorage → vmselect
  • 【Java毕业设计】基于 SpringBoot 的律师爱心援助法律援助平台的设计与实现 基于 SpringBoot+Vue 的公益法律援助服务平台(源码+文档+远程调试,全bao定制等)
  • 于LangChain与DeepSeek实现Plan-and-Execute Agent,让AI学会“先规划后行动”
  • 、keyd:Linux 系统级改键工具。
  • Gin 架构在区块链应用中的最佳实践
  • 【时间之外】这些AI应用的误区,你踩中几个?
  • 从集成到原生:魔点钉钉一个入口统管智慧园区