拥有短期记忆的RAG Agent:记忆增强检索实战

在上一节内容中详细介绍了短期记忆管理的3种方式,删除、修剪和总结。在本节内容中,我们将基于第4.10节的内容实现一个类似 ChatGPT 的 RAG 问答工具,做到每次回答完用户问题后都判断是否需要对历史消息进行一次总结,并同步将会话消息实时保存到数据库,使得每次启动程序时都能恢复历史会话。

5.4 拥有短期记忆的 RAG Agent

在上一节内容中详细介绍了短期记忆管理的3种方式,删除、修剪和总结。在本节内容中,我们将基于第4.10节的内容实现一个类似 ChatGPT 的 RAG 问答工具,做到每次回答完用户问题后都判断是否需要对历史消息进行一次总结,并同步将会话消息实时保存到数据库,使得每次启动程序时都能恢复历史会话。

5.4.1 流程构建思路

为了实现上述目的,需要在图4-13的图结构之上再添加一个条件判断边和一个节点,来判断是否需要对历史记忆进行总结以及如何总结,整个流程如图5-6所示。

图 5-6 带记忆能力的 RAG Agent 图结构可视化

从图5-6可以看出,在每一轮回答结束以后两个分支都会统一汇集到 check_messages 节点,然后再通过条件分支判断是否需要进行历史消息总结。下面逐一对这部分内容进行介绍。

5.4.2 分支汇集与条件判断

由于 decide 这条边已经用 tools_condition 在做"是否调用工具"的分流,即 add_conditional_edges("decide",tools_condition, {"tools": "my_retrieve", END: END}),而 tools_condition 的映射是静态的,没法在左侧的 END 分支里再动态判断一次是否应该进行记忆总结,所以需要添加一个空节点来做汇集,即图5-6中的 check_messages,其对应的实现为:

复制代码
1 def passthrough(state: MyState) -> MyState:
2     return {}

在上述代码中,第2行 return {} 表示更新内容为空,即不对传入的 state 做任何修改。

进一步,实现是否需要进行总结的条件判断,示例代码如下:

复制代码
1 def count_messages(state: MyState) -> Literal[END, "to_summarize"]:
2     messages = state["messages"]
3     threshold = 5
4     if len(messages) > threshold:
5         return "to_summarize"
6     else:
7         return END

在上述代码中,我们简单地使用消息条数来进行判断,当然也可以是其它策略。第4~7行是根据条件判断流向 to_summarize 节点或直接结束。

5.4.3 历史记忆总结

接着,在第5.2.4节实现的 summarize_conversation 基础之上,再来对内部进行一些改造,使得能够更加灵活的总结和删除对应的历史记忆,示例代码如下:

复制代码
 1 def summarize_conversation(state: MyState) -> MyState:
 2  ......
 3     trimmed = trim_messages(state["messages"], max_tokens=5, strategy="last",
 4                 token_counter=len, start_on="human", end_on=("human", "ai"))
 5     trimmed_msg_ids = [msg.id for msg in trimmed] # 保留下来的消息
 6     delete_messages, summary_messages = [], []
 7     for msg in state["messages"]:
 8         if msg.id not in trimmed_msg_ids:
 9             delete_messages.append(RemoveMessage(id=msg.id))
10             if msg.type != 'tool': 
11                 summary_messages.append(msg)
12     summary_messages += [HumanMessage(content=summary_message)]
13     response = get_llm_model().invoke(summary_messages)
14     return {"summary": response.content, "messages": delete_messages}

在上述代码中,第3~4行中先使用 trim_messages 函数来对需要保留的消息记录做一次条件筛选,最多保留最后的5条消息,这样能够使得保留下来的消息更上下文更加完整。第5行是得到待保留消息的 ID,第7~11行是遍历原始状态中的每一条消息,然后标记待删除的消息,以及根据消息类型筛选待总结的消息,因为工具返回的内容篇幅通常很长,而且不一定都有用,所以去掉这部分内容。

5.4.4 搭建完整流程

在完成上述节点定义以后,最后来完成整个图的构建过程,示例代码如下:

复制代码
 1 def get_workflow(checkpointer: PostgresSaver):
 2     workflow = StateGraph(MyState)
 3     ...
 4     workflow.add_node("check_messages", passthrough)
 5     workflow.add_node("summarize", summarize_conversation)
 6     workflow.add_edge(START, "decide")
 7     workflow.add_conditional_edges("decide",tools_condition,
 8             {"tools": "my_retrieve", END: "check_messages"})
 9     workflow.add_conditional_edges("my_retrieve", grade_documents)
10     workflow.add_edge("generate_answer", "check_messages")
11     workflow.add_conditional_edges("check_messages", count_messages,
12         {"to_summarize": "summarize", END: END})
13     workflow.add_edge("summarize", END)
14     workflow.add_edge("rewrite_question", "decide")
15     graph = workflow.compile(checkpointer=checkpointer)
16     return graph

在上述代码中......

完整内容见:拥有短期记忆的RAG Agent:记忆增强检索实战

相关推荐
染指11101 小时前
152.Agent-LangGraph-Command的参数
人工智能·python·langchain·agents
虎鲸不是鱼1 小时前
【虎鲸进化论 41】AI 的盲区清单:责任、利害、定义、关系、最后一公里与主体性
人工智能·自动化·大模型·llm·自进化agent
跨境联盟1 小时前
实体大健康门店转型:精准营养服务如何跳出单纯卖产品的困局
大数据·人工智能·健康医疗·健康管理·精准营养
QN1幻化引擎1 小时前
信号场注意力(SFA):把 KV Cache 变成 O(1) 的双通道注意力——0.1B/0.3B 受控 A/B 精度反升 15.5% / 24.3%
pytorch·深度学习·大模型·transformer·注意力机制·推理优化
appsvip1 小时前
给社区系统加一套 AI 助手:从架构到落地的思考
大数据·人工智能·架构
田里的水稻1 小时前
FA_CNN卷积神经网络二---PyTorch
人工智能·pytorch·python·深度学习·cnn
镜象科技1 小时前
校园抑郁筛查实战:匿名、隐私与信任的平衡
人工智能
远航计算机1 小时前
AI 看不见图,它只读旁边的字
人工智能·chatgpt·aigc
tq10861 小时前
AI 时代 UX 的范式重构:从空间寻路到注意力分配
人工智能