LlamaIndex学习2:会话状态管理与持久化
LlamaIndex会话状态管理与持久化
在上一篇文章中介绍了LlamaIndex与不同API的基本调用方式,这篇文章将探讨LlamaIndex的会话状态管理功能,这是构建具有记忆能力的AI应用的关键部分。
1. 状态管理的重要性
在与LLM交互过程中,保持对话上下文至关重要。如果没有状态管理:
- 用户每次提问都变成独立对话
- 模型无法记住之前的信息
- 无法构建连贯的交互体验
LlamaIndex提供了优雅的状态管理和持久化方案,使模型能够”记住”之前的对话内容。
2. 基本状态管理示例
下面是一个基本的状态管理示例,展示了如何使用LlamaIndex的Context
和AgentWorkflow
实现对话记忆:
from dotenv import load_dotenv
load_dotenv()
import os
from llama_index.llms.openrouter import OpenRouter
from llama_index.core.agent.workflow import AgentWorkflow
from llama_index.core.workflow import Context
from llama_index.core.workflow import JsonSerializer
# 初始化LLM
llm = OpenRouter(
model="google/gemma-3-27b-it:free",
api_key=os.getenv("OPEN_ROUTER_API_KEY"),
)
# 创建工作流
workflow = AgentWorkflow.from_tools_or_functions(
tools_or_functions=[],
llm=llm,
system_prompt="你是一个智能助手,请热情地回答用户的问题"
)
# 创建上下文对象
ctx = Context(workflow)
3. 状态持久化的实现
LlamaIndex的状态管理核心是Context
对象,它可以:
- 跟踪对话历史
- 保存用户信息
- 维护工具调用记录
以下示例展示如何实现状态的序列化和反序列化:
async def main():
# 第一轮对话
response = await workflow.run(user_msg="Hi, my name is 张三!", ctx=ctx)
print("*****************第一次对话**************************")
print('用户:Hi, my name is 张三!')
print('AI:',response)
# 第二轮对话 - 使用同一上下文
response2 = await workflow.run(user_msg="What's my name?", ctx=ctx)
print("*****************第二次对话**************************")
print('用户:What\'s my name?')
print('AI:',response2)
# 状态序列化 - 将上下文转换为字典
ctx_dict = ctx.to_dict(serializer=JsonSerializer())
# 状态反序列化 - 从字典恢复上下文
restored_ctx = Context.from_dict(
workflow, ctx_dict, serializer=JsonSerializer()
)
# 使用恢复的上下文继续对话
response3 = await workflow.run(user_msg="What's my name?", ctx=restored_ctx)
print("*****************第三次对话**************************")
print('用户:What\'s my name?')
print('AI:',response3)
运行结果:
*****************第一次对话**************************
用户:Hi, my name is 张三!
AI: 你好,张三!很高兴认识你!(Hello, Zhang San! Nice to meet you!)
*****************第二次对话**************************
用户:What's my name?
AI: 你的名字是张三。(Your name is Zhang San.)
*****************第三次对话**************************
用户:What's my name?
AI: 你的名字是张三。(Your name is Zhang San.)
代码解释:
# 状态序列化 - 将上下文转换为字典
ctx_dict = ctx.to_dict(serializer=JsonSerializer())
# 状态反序列化 - 从字典恢复上下文
restored_ctx = Context.from_dict(
workflow, ctx_dict, serializer=JsonSerializer()
)
这一步的作用是实现对话状态的序列化和反序列化,用于保存和恢复会话上下文。具体来说:
- 首先将Context对象(ctx)序列化成字典格式(ctx_dict),使用JsonSerializer()作为序列化器
- 然后再从这个字典重新创建一个新的Context对象(restored_ctx)
这种机制允许将对话的状态(包括历史会话、用户信息等)转换为可持久化的格式,以便可以:
- 将状态存储到数据库或文件系统
- 在服务重启后恢复上下文
- 在分布式系统中传递状态
- 跨会话维持用户对话连续性
在这个示例中,通过response3的调用可以验证状态是否成功保存和恢复,因为如果恢复成功,LLM应该能记住用户名是”张三”。
4. 状态持久化的实际应用
这种状态序列化机制可以应用于多种场景:
4.1 数据库存储
# 保存状态到数据库
def save_context_to_db(user_id, ctx):
ctx_dict = ctx.to_dict(serializer=JsonSerializer())
db.save_context(user_id, ctx_dict)
# 从数据库恢复状态
def load_context_from_db(user_id, workflow):
ctx_dict = db.load_context(user_id)
if ctx_dict:
return Context.from_dict(workflow, ctx_dict, serializer=JsonSerializer())
return Context(workflow)
4.2 文件系统存储
# 保存状态到文件
def save_context_to_file(file_path, ctx):
"""
将会话上下文保存到文件
Args:
file_path: 保存的文件路径
ctx: Context对象
"""
ctx_dict = ctx.to_dict(serializer=JsonSerializer())
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(ctx_dict, f, ensure_ascii=False, indent=2)
# 从文件恢复状态
def load_context_from_file(file_path, workflow):
"""
从文件加载会话上下文
Args:
file_path: 文件路径
workflow: 工作流对象
Returns:
恢复的Context对象,如果文件不存在则返回新的Context
"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
ctx_dict = json.load(f)
return Context.from_dict(workflow, ctx_dict, serializer=JsonSerializer())
except FileNotFoundError:
return Context(workflow)
这里进行本地文件保存上下文进行测试,修改上面main函数:
# 第一轮对话
response = await workflow.run(user_msg="Hi, my name is 张三!", ctx=ctx)
print("*****************第一次对话**************************")
print('用户:Hi, my name is 张三!')
print('AI:',response)
# 状态序列化 - 将上下文转换为字典
ctx_dict = ctx.to_dict(serializer=JsonSerializer())
# 保存会话状态到文件
save_context_to_file("conversation_state.json", ctx)
print("会话状态已保存到 conversation_state.json")
先运行第一遍,这时候会把序列化之后的ctx保存到conversation_state.json中,以下是执行log:
*****************第一次对话**************************
用户:Hi, my name is 张三!
AI:
Thought: The current language of the user is: Chinese. I need to acknowledge the user's greeting and introduction.
Action: None
Answer: 你好,张三!很高兴认识你!(Hello, Zhang San! Nice to meet you!)
会话状态已保存到 conversation_state.json
然后再将main函数改为:
# 先直接从缓存文件加载上下文
restored_ctx = load_context_from_file("conversation_state.json", workflow)
print("已从文件加载会话状态")
response = await workflow.run(user_msg="What's my name?",ctx=restored_ctx)
print("*****************第一次对话**************************")
print('用户:What\'s my name?')
print('AI:',response)
打印log
已从文件加载会话状态
*****************第一次对话**************************
用户:What's my name?
AI:
Thought: The current language of the user is: Chinese. The user is asking me what their name is. I should recall the information they provided earlier.
Action: None
Answer: 你的名字是张三。(Your name is Zhang San.)
5.总结
LlamaIndex的状态管理机制为构建具有记忆能力的AI应用提供了强大支持:
Context
对象管理对话历史和状态- 序列化/反序列化功能支持状态持久化
- 可以轻松集成到各种存储系统
通过这些功能,我们可以开发出能够记住用户偏好、历史交互和上下文信息的智能应用,大大提升用户体验和应用智能程度。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!