# 第06章:会话与状态管理 ## 📌 本章目标 - 理解 Session、State、Memory 三层上下文架构 - 掌握 SessionService 的使用方法 - 学习 State 的读写和管理 - 了解 MemoryService 和跨会话记忆 - 掌握 Runner 的使用方法 --- ## 6.1 上下文管理架构 ### 6.1.1 三层上下文模型 ``` ┌──────────────────────────────────────────────────────┐ │ 上下文管理架构 │ │ │ │ ┌────────────────────────────────────────────┐ │ │ │ Memory(记忆层) │ │ │ │ - 跨会话持久化知识 │ │ │ │ - 可搜索的知识库 │ │ │ │ - 管理者:MemoryService │ │ │ │ - 实现:InMemory / Vector DB / Cloud │ │ │ └────────────────────────────────────────────┘ │ │ │ │ ┌────────────────────────────────────────────┐ │ │ │ Session(会话层) │ │ │ │ - 单次对话线程 │ │ │ │ - 消息历史(Events) │ │ │ │ - 管理者:SessionService │ │ │ │ - 实现:InMemory / Firestore / DB │ │ │ └────────────────────────────────────────────┘ │ │ │ │ ┌────────────────────────────────────────────┐ │ │ │ State(状态层) │ │ │ │ - 会话内的临时数据 │ │ │ │ - temp: 临时状态(当前调用有效) │ │ │ │ - 持久状态(会话期间有效) │ │ │ └────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────┘ ``` ### 6.1.2 各层对比 | 层级 | 生命周期 | 用途 | 管理服务 | |------|----------|------|----------| | **Memory** | 跨会话持久化 | 长期知识、用户偏好 | MemoryService | | **Session** | 单次对话 | 消息历史、对话上下文 | SessionService | | **State** | 会话期间 | 临时数据、中间结果 | session.state | | **temp: State** | 单次调用 | 工具间数据传递 | session.state | --- ## 6.2 Session(会话) ### 6.2.1 Session 是什么? Session 代表用户与 Agent 系统之间的一次对话交互。它包含: - **消息历史**:按时间顺序记录的所有消息和事件 - **状态数据**:对话过程中产生的临时数据 - **元信息**:应用名称、用户 ID、会话 ID 等 ### 6.2.2 SessionService(会话服务) ```python """ SessionService — 会话管理服务 负责创建、读取、更新和删除会话 """ from google.adk.sessions import InMemorySessionService # 导入内存会话服务 import asyncio # 导入异步库 async def session_demo(): """演示 SessionService 的使用""" # ======================================== # 创建会话服务 # ======================================== # InMemorySessionService:将数据存储在内存中 # 适用于开发和测试,数据在程序重启后丢失 session_service = InMemorySessionService() # ======================================== # 创建会话 # ======================================== session = await session_service.create_session( app_name="my_app", # 应用名称(用于标识应用) user_id="user_001", # 用户唯一标识 session_id="session_001", # 会话唯一标识 # state={"key": "value"}, # 可选:初始化状态 ) print(f"会话创建成功: {session.id}") # 打印会话 ID print(f"应用名称: {session.app_name}") # 打印应用名称 print(f"用户 ID: {session.user_id}") # 打印用户 ID # ======================================== # 获取会话 # ======================================== existing_session = await session_service.get_session( app_name="my_app", # 应用名称 user_id="user_001", # 用户 ID session_id="session_001", # 会话 ID ) print(f"获取会话: {existing_session.id}") # 打印会话信息 # ======================================== # 删除会话 # ======================================== await session_service.delete_session( app_name="my_app", # 应用名称 user_id="user_001", # 用户 ID session_id="session_001", # 会话 ID ) print("会话已删除") # 确认删除 # 运行演示 asyncio.run(session_demo()) # 执行异步函数 ``` ### 6.2.3 SessionService 实现对比 | 实现 | 存储方式 | 持久化 | 适用场景 | |------|----------|--------|----------| | **InMemorySessionService** | 内存 | ❌ | 开发、测试 | | **FirestoreSessionService** | Google Firestore | ✅ | 生产环境 | | **SqliteSessionService** | SQLite 文件 | ✅ | 本地生产 | | **自定义** | 自定义后端 | ✅ | 特殊需求 | --- ## 6.3 State(状态管理) ### 6.3.1 State 基础操作 ```python """ State 状态管理 在会话中读写和管理数据 """ from google.adk.agents import Agent # 导入 Agent 类 from google.adk.runners import Runner # 导入运行器 from google.adk.sessions import InMemorySessionService # 导入会话服务 from google.genai import types # 导入类型定义 import asyncio # 导入异步库 # ======================================== # 定义使用 State 的工具 # ======================================== def add_to_cart(item: str, price: float, ctx) -> dict: """ 将商品添加到购物车 Args: item (str): 商品名称 price (float): 商品价格 ctx: 工具上下文(自动注入),用于访问会话状态 Returns: dict: 操作结果 """ # 获取当前购物车(如果不存在则初始化为空列表) cart = ctx.state.get("cart", []) # 从 state 中读取购物车 # 添加新商品到购物车 cart.append({ # 追加商品信息 "item": item, # 商品名称 "price": price, # 商品价格 }) # 更新 state 中的购物车 ctx.state["cart"] = cart # 写回 state # 计算购物车总价 total = sum(item["price"] for item in cart) # 求和 return { # 返回结果 "status": "success", # 状态 "message": f"已将 {item} 添加到购物车", # 消息 "cart_items": len(cart), # 购物车商品数量 "total": total, # 总价 } def get_cart(ctx) -> dict: """ 获取购物车内容 Args: ctx: 工具上下文 Returns: dict: 购物车内容 """ cart = ctx.state.get("cart", []) # 读取购物车 if not cart: # 如果购物车为空 return { # 返回空购物车信息 "status": "success", "message": "购物车是空的", "items": [], "total": 0, } total = sum(item["price"] for item in cart) # 计算总价 return { # 返回购物车内容 "status": "success", "items": cart, # 商品列表 "total": total, # 总价 } def clear_cart(ctx) -> dict: """ 清空购物车 Args: ctx: 工具上下文 Returns: dict: 操作结果 """ ctx.state["cart"] = [] # 清空购物车 return { # 返回结果 "status": "success", "message": "购物车已清空", } # ======================================== # 创建 Agent # ======================================== shopping_agent = Agent( name="shopping_assistant", # Agent 名称 model="gemini-2.0-flash", # 模型 instruction=( # 指令 "你是一个购物助手。\n" "帮助用户管理购物车:添加商品、查看购物车、清空购物车。" ), tools=[ # 注册工具 add_to_cart, # 添加商品 get_cart, # 查看购物车 clear_cart, # 清空购物车 ], ) ``` ### 6.3.2 temp: 临时状态 ```python """ temp: 临时状态 只在当前调用(invocation)中有效,调用结束后自动清除 适用于工具间传递中间数据 """ def step1_process(query: str, ctx) -> dict: """ 处理步骤一:预处理数据 Args: query (str): 用户查询 ctx: 工具上下文 Returns: dict: 预处理结果 """ # 对查询进行预处理 processed = query.strip().lower() # 去除空格并转小写 # 保存到临时状态(temp: 前缀) # 这个数据只在当前调用中有效 ctx.state["temp:processed_query"] = processed # 临时存储 return { # 返回结果 "status": "success", "processed_query": processed, } def step2_enhance(ctx) -> dict: """ 处理步骤二:增强数据 Args: ctx: 工具上下文 Returns: dict: 增强结果 """ # 从临时状态读取步骤一的数据 processed = ctx.state.get("temp:processed_query") # 读取临时状态 if not processed: # 如果没有数据 return { # 返回错误 "status": "error", "error_message": "请先执行预处理步骤。" } # 增强处理 enhanced = f"[增强] {processed}" # 模拟增强处理 return { # 返回结果 "status": "success", "enhanced_query": enhanced, } # temp: 状态 vs 普通状态: # - temp:xxx:当前调用结束后自动清除 # - xxx:会话期间持久保存 ``` --- ## 6.4 Runner(运行器) ### 6.4.1 Runner 基础用法 ```python """ Runner — ADK 的核心执行引擎 负责协调 Agent、会话服务和工具调用 """ from google.adk.agents import Agent # 导入 Agent 类 from google.adk.runners import Runner # 导入运行器 from google.adk.sessions import InMemorySessionService # 导入会话服务 from google.genai import types # 导入类型定义 import asyncio # 导入异步库 # ======================================== # 定义一个简单的 Agent # ======================================== def get_greeting(name: str) -> dict: """生成问候语""" return { # 返回问候语 "status": "success", "greeting": f"你好,{name}!欢迎来到 ADK 教程。", } agent = Agent( name="greeting_agent", # Agent 名称 model="gemini-2.0-flash", # 模型 instruction="你是一个问候助手。", # 指令 tools=[get_greeting], # 注册工具 ) # ======================================== # 使用 Runner 运行 Agent # ======================================== APP_NAME = "demo_app" # 应用名称 USER_ID = "user_001" # 用户 ID SESSION_ID = "session_001" # 会话 ID async def run_agent(): """运行 Agent 的完整流程""" # 第一步:创建会话服务 session_service = InMemorySessionService() # 内存会话服务 # 第二步:创建会话 session = await session_service.create_session( app_name=APP_NAME, # 应用名称 user_id=USER_ID, # 用户 ID session_id=SESSION_ID, # 会话 ID ) # 第三步:创建 Runner runner = Runner( agent=agent, # 要运行的 Agent app_name=APP_NAME, # 应用名称 session_service=session_service, # 会话服务 # max_turns=10, # 可选:最大对话轮数 ) # 第四步:构造用户消息 user_message = types.Content( role='user', # 角色:用户 parts=[types.Part(text='你好,请向我打招呼')], # 消息内容 ) # 第五步:运行 Agent 并处理事件流 events = runner.run_async( user_id=USER_ID, # 用户 ID session_id=SESSION_ID, # 会话 ID new_message=user_message, # 用户消息 ) # 第六步:遍历事件流,提取响应 async for event in events: # 遍历所有事件 print(f"事件类型: {type(event).__name__}") # 打印事件类型 # 检查是否为最终响应 if event.is_final_response(): # 如果是最终响应 response_text = event.content.parts[0].text # 提取文本 print(f"Agent 回复: {response_text}") # 打印回复 # 检查是否为工具调用事件 if hasattr(event, 'function_call'): # 如果有函数调用 print(f"工具调用: {event.function_call}") # 打印调用信息 # 运行 asyncio.run(run_agent()) # 执行异步函数 ``` ### 6.4.2 多轮对话 ```python """ 多轮对话示例 在同一个会话中进行多轮交互 """ from google.adk.agents import Agent # 导入 Agent 类 from google.adk.runners import Runner # 导入运行器 from google.adk.sessions import InMemorySessionService # 导入会话服务 from google.genai import types # 导入类型定义 import asyncio # 导入异步库 agent = Agent( name="chat_agent", # Agent 名称 model="gemini-2.0-flash", # 模型 instruction="你是一个友好的聊天助手,记住用户告诉你的信息。", # 指令 ) async def multi_turn_chat(): """多轮对话演示""" # 初始化服务 session_service = InMemorySessionService() # 会话服务 await session_service.create_session( # 创建会话 app_name="chat_app", # 应用名称 user_id="user_001", # 用户 ID session_id="chat_001", # 会话 ID ) # 创建 Runner runner = Runner( agent=agent, # Agent app_name="chat_app", # 应用名称 session_service=session_service, # 会话服务 ) # 模拟多轮对话 questions = [ # 对话列表 "我叫小明,今年25岁。", # 第一轮:自我介绍 "我叫什么名字?", # 第二轮:测试记忆 "我今年多大?", # 第三轮:测试记忆 ] for question in questions: # 遍历每轮对话 print(f"\n[用户]: {question}") # 打印用户消息 # 构造消息 content = types.Content( role='user', # 角色 parts=[types.Part(text=question)], # 内容 ) # 运行 Agent events = runner.run_async( user_id="user_001", # 用户 ID session_id="chat_001", # 会话 ID(同一个会话) new_message=content, # 新消息 ) # 获取响应 async for event in events: # 遍历事件 if event.is_final_response(): # 最终响应 print(f"[Agent]: {event.content.parts[0].text}") # 打印回复 asyncio.run(multi_turn_chat()) # 执行多轮对话 ``` --- ## 6.5 Memory(记忆服务) ### 6.5.1 Memory 概述 Memory 是跨会话的持久化知识存储,Agent 可以搜索和检索历史信息。 ```python """ MemoryService — 记忆管理服务 管理跨会话的持久化知识 """ from google.adk.memory import InMemoryMemoryService # 导入内存记忆服务 async def memory_demo(): """演示 MemoryService 的使用""" # ======================================== # 创建记忆服务 # ======================================== # InMemoryMemoryService:将记忆存储在内存中 # 适用于开发测试,数据在重启后丢失 memory_service = InMemoryMemoryService() # ======================================== # 添加记忆 # ======================================== await memory_service.add_session_events_to_memory( app_name="my_app", # 应用名称 user_id="user_001", # 用户 ID session_id="session_001", # 会话 ID ) # ======================================== # 搜索记忆 # ======================================== results = await memory_service.search( query="用户偏好", # 搜索查询 app_name="my_app", # 应用名称 user_id="user_001", # 用户 ID ) # 处理搜索结果 for result in results: # 遍历结果 print(f"记忆内容: {result}") # 打印记忆 # 运行演示 import asyncio asyncio.run(memory_demo()) ``` ### 6.5.2 Memory 与 Session 的区别 ``` ┌────────────────────────────────────────────────────┐ │ Session(会话) │ │ ┌──────────────────────────────────────────────┐ │ │ │ 消息1 → 消息2 → 消息3 → ... → 消息N │ │ │ │ state: {cart: [...], preferences: {...}} │ │ │ └──────────────────────────────────────────────┘ │ │ 生命周期:会话开始 → 会话结束 │ └────────────────────────────────────────────────────┘ ┌────────────────────────────────────────────────────┐ │ Memory(记忆) │ │ ┌──────────────────────────────────────────────┐ │ │ │ 会话1摘要 → 会话2摘要 → 会话3摘要 → ... │ │ │ │ 用户偏好 → 历史交互 → 长期知识 │ │ │ └──────────────────────────────────────────────┘ │ │ 生命周期:跨会话持久化 │ └────────────────────────────────────────────────────┘ ``` --- ## 📌 本章小结 - ADK 采用三层上下文架构:Memory > Session > State - **Session**:单次对话线程,由 SessionService 管理 - **State**:会话内数据,通过 `ctx.state` 读写 - **temp: State**:临时状态,当前调用有效 - **Memory**:跨会话持久化知识,由 MemoryService 管理 - **Runner** 是核心执行引擎,协调 Agent 和会话 **下一章**:[第07章 - 回调机制与事件系统](./07-callbacks-and-events.md) → 学习如何使用回调函数控制 Agent 行为。