基于谷歌ADK的 智能产品推荐系统(1): 功能简介
Google的智能体开发工具包(Agent Development Kit,简称ADK)是一个开源的、以代码为中心的Python工具包,旨在帮助开发者更轻松、更灵活地构建、评估和部署复杂的人工智能智能体(AI Agent)。ADK 是一个灵活的模块化框架,用于开发和部署 AI 智能体。尽管 ADK 针对 Gemini 和谷歌生态系统进行了优化,但它是模型无关、部署无关的,并且旨在与其他框架兼容。ADK 的设计旨在使智能体开发更像软件开发,从而使开发人员更容易创建、部署和编排从简单任务到复杂工作流的智能体架构。今天我们来分析基于谷歌ADK框架开发的 个性化购物智能体项目
深入剖析个性化购物 Agent:技术栈与实现原理
个性化购物 Agent 项目展示了一个强大的框架,旨在模拟和实现在线购物环境中的智能导购。它不仅仅是一个简单的聊天机器人,更是一个集成了环境模拟、自然语言理解、搜索引擎、以及复杂交互逻辑的综合系统。本文将深入剖析其核心技术组件和实现原理。
大家可以在github上访问该项目: adk-samples/python/agents/personalized-shopping at main · google/adk-samples · GitHub
1. 引言:智能购物的未来
随着电子商务的飞速发展,用户期望获得更智能、更个性化的购物体验。传统的关键词搜索和筛选已难以满足复杂需求。个性化购物 Agent 项目应运而生,它通过模拟真实购物网站的交互,利用大型语言模型 (LLM) 的理解和推理能力,为用户提供从需求分析到产品推荐,再到辅助购买的全流程智能服务。
2. 核心架构概览
该项目的架构可以概括为:
-
表示层/环境层 (WebShop Simulation): 一个模拟的 Web 购物环境,用户(或 Agent)可以在其中执行搜索、浏览商品、查看详情等操作。
-
感知与行动层 (Tools): Agent 通过 search 工具从环境中获取信息,通过 click 工具在环境中执行操作。
-
决策层 (LLM Agent): 基于 LLM 的 Agent,它接收用户指令和环境观察,决策下一步的行动。
-
数据层 (Product Data & Search Index): 包含大量产品信息,并通过搜索引擎建立索引以支持快速检索。
参考项目 README.md 中的架构图,我们可以更直观地理解各组件的协同工作。
该项目的目录结构:
3. 深入组件
模拟 Web 环境 (WebShop):核心交互的基石
WebShop 环境是整个系统的核心,它为 Agent 提供了一个可交互的“沙盒”。
-
WebAgentTextEnv (web_agent_text_env.py):
-
这是一个基于 OpenAI Gym 规范实现的环境。它封装了与模拟 Web 服务器和浏览器的交互逻辑。
-
观测模式 (Observation Mode): 支持多种观测模式,如 html (原始 HTML)、text (提取的纯文本)、text_rich (带结构标记的文本) 和 url。这使得 Agent 可以根据需要获取不同粒度的信息。convert_html_to_text 方法负责将 HTML 转换为文本表示。
-
状态 (State): 包含当前页面的 url、html 源码和当前的 instruction_text。
-
动作 (Action): Agent 可以执行 search[keywords] 或 click[button_name] 这样的动作。parse_action 函数用于解析这些动作字符串。
-
交互历史: 环境会记录之前的观测 (prev_obs) 和动作 (prev_actions),这对于需要上下文信息的 Agent 至关重要。
-
-
SimServer (web_agent_text_env.py):
-
这是一个轻量级的服务器模拟器,虽然代码中使用了 Flask 的 @app.route 装饰器,但它并不实际运行一个独立的 Flask Web 服务器进程。相反,它通过内部方法调用来模拟 HTTP 请求和响应的流程。
-
路由处理: 定义了如 / (首页/搜索页)、/search_results/...、/item_page/...、/item_sub_page/... 和 /done 等页面的逻辑。
-
会话管理 (user_sessions): 为每个会话维护状态,包括当前搜索的关键词、浏览的商品 (asin)、选择的选项、已执行的动作次数以及当前的目标 (goal)。
-
核心方法 receive: 这是服务器的入口点,根据传入的参数(如 keywords 或 clickable_name)分发到不同的页面处理函数,并返回生成的 HTML、新的 URL 和状态信息(奖励、是否结束)。
-
HTML 渲染 (map_action_to_html in engine.py): 根据当前的动作和会话状态,使用 render_template_string 动态渲染相应的 HTML 模板(如 search_page.html, results_page.html, item_page.html 等)。
-
-
SimBrowser (web_agent_text_env.py):
-
模拟浏览器的基本行为,如 get (加载页面) 和 click (点击元素)。
-
它不进行实际的网络请求,而是直接调用 SimServer.receive 方法来获取页面内容和更新状态。
-
维护 current_url 和 page_source (当前页面的 HTML)。
-
-
HTML 模板与动态渲染 (templates/ 目录, engine.py):
-
项目包含了一系列 HTML 模板文件(如 item_page.html, results_page.html),使用 Jinja2 模板引擎(通过 Flask 的 render_template_string)。
-
engine.py 中的 map_action_to_html 函数是渲染的核心,它根据不同的动作类型(如 "search", "click[Description]", "click[Buy Now]")选择合适的模板,并传入必要的上下文数据(如产品信息、搜索结果、会话 ID 等)进行渲染。
-
Agent 大脑:LLM 与提示工程
Agent 的智能来源于大型语言模型 (LLM) 以及精心设计的提示 (Prompt)。
-
Agent 类与 LLM 集成 (agent.py):
-
使用了 google.adk.agents.Agent 类来构建 Agent。
-
可以通过 LiteLlm 类集成了外部 LLM 服务,例如 deepseek/deepseek-chat。这表明系统可以灵活地替换不同的 LLM 后端。
-
Agent 被赋予了 name ("personalized_shopping_agent") 和核心指令。
-
-
prompt.py (personalized_shopping_agent_instruction):
-
这是至关重要的部分。该文件中的长字符串 personalized_shopping_agent_instruction 为 LLM 提供了详细的角色定义、任务目标、交互流程和关键指南。
-
交互流程定义: 清晰地描述了从初始问询、搜索、产品探索、购买确认到最终完成的每一步。
-
按钮处理注意事项: 特别强调了只能点击当前页面可见按钮,以及如何使用 "< Prev" 和 "Back to Search" 按钮进行导航。
-
这个 Prompt 的质量直接决定了 Agent 的行为是否符合预期,是否能够有效地使用工具并与用户进行流畅交互。
-
核心工具:Search 与 Click
Agent 通过工具与模拟环境进行交互。
-
search.py:
-
定义了一个名为 search 的异步函数,它被包装成 FunctionTool 供 Agent 调用。
-
功能: 接收用户提供的 keywords,构造动作字符串 f"search[{keywords}]"。
-
环境交互: 调用 webshop_env.step(action_string) 将搜索动作传递给模拟环境。
-
指令更新: 在执行搜索前,会更新 webshop_env.server.assigned_instruction_text,这可能会影响页面上显示的指令文本。
-
结果返回: 返回环境的观测结果 (通常是搜索结果页面的文本表示)。
-
工件保存: 使用 tool_context.save_artifact 将生成的 HTML 页面作为工件保存,便于调试和追溯。
-
-
click.py:
-
定义了一个名为 click 的异步函数,同样被包装成 FunctionTool。
-
功能: 接收要点击的 button_name,构造动作字符串 f"click[{button_name}]"。
-
环境交互: 调用 webshop_env.step(action_string) 将点击动作传递给模拟环境。
-
特殊处理: 如果点击的是 "Back to Search",会特殊设置 webshop_env.server.assigned_instruction_text。
-
结果返回: 返回点击后新页面的观测结果。
-
工件保存: 同样保存 HTML 工件。
-
数据处理与搜索引擎集成
高效的商品检索是购物 Agent 的核心能力之一。
-
产品数据 (items_*.json in shared_libraries/data/):
-
这些 JSON 文件包含了大量的商品信息,如 ASIN、标题、描述、特性、选项(颜色、尺寸)、价格、图片链接等。
-
engine.py 中的 load_products 函数负责加载和初步清洗这些数据,例如处理价格格式、提取选项、关联评论(尽管评论数据在示例中似乎未完全集成)。
-
-
数据预处理 (convert_product_file_format.py in shared_libraries/search_engine/):
-
此脚本将原始的 items_shuffle.json 转换为 Pyserini 搜索引擎所需的特定 JSONL 格式。
-
对于每个产品,它会提取关键字段(标题、描述、要点、选项文本)并合并成一个 contents 字段,供搜索引擎索引。
-
-
Pyserini (Lucene) 搜索引擎与索引构建 (run_indexing.sh, engine.py):
-
run_indexing.sh 脚本使用 Pyserini(一个基于 Lucene 的 Python 搜索工具包)来为预处理后的产品文档构建索引。针对不同数量级的产品(100, 1k, 10k, 50k)分别创建索引。
-
engine.py 中的 init_search_engine 函数根据配置的产品数量加载相应的 Pyserini LuceneSearcher 实例。
-
get_top_n_product_from_keywords 函数使用加载的 search_engine 执行关键词搜索,并返回匹配度最高的 N 个商品。
-
目标定义与奖励机制
为了评估 Agent 的性能并可能用于强化学习,项目定义了目标和奖励。
-
goal.py (shared_libraries/web_agent_site/engine/):
-
目标生成 (get_goals, get_human_goals, get_synthetic_goals):
-
可以生成两种类型的购物目标:基于人类标注的指令 (items_human_ins.json) 或基于产品属性和选项合成的指令。
-
每个目标包含目标商品的 ASIN、期望属性、选项、价格上限以及一段自然语言指令文本。
-
-
奖励计算 (get_reward):
-
这是评估 Agent 购买行为的核心函数。它比较 Agent 最终“购买”的商品与预设目标。
-
多维度奖励:
-
r_type: 评估购买商品与目标商品在类别、查询词、标题上的匹配度。使用了 Spacy进行名词提取和比较。
-
r_price: 评估购买价格是否在目标价格上限内。
-
r_att: 评估购买商品的属性与目标属性的匹配度。使用了 thefuzz库进行模糊字符串匹配。
-
r_option: 评估购买商品的选项(如颜色、尺寸)与目标选项的匹配度。同样使用 thefuzz。
-
-
最终的总奖励是这些分项奖励的加权组合,并乘以类型匹配度 r_type。
-
-
4. 交互流程解析
-
初始化: init_env.py 初始化 WebAgentTextEnv 环境,加载指定数量的产品数据并构建搜索引擎。Agent 被实例化,并加载了 personalized_shopping_agent_instruction。
-
用户输入: 用户向 Agent 发出购物请求(例如,“帮我找一件夏季碎花连衣裙”)。
-
Agent 决策 (LLM):
-
LLM 根据其指令和用户输入,决定调用 search 工具。
-
它可能会从用户输入中提取关键词 "夏季 碎花 连衣裙"。
-
-
执行 Search 工具:
-
search 工具调用 webshop_env.step("search[夏季 碎花 连衣裙]")。
-
SimServer 接收到搜索请求,调用 Pyserini 搜索引擎,获取商品列表。
-
SimServer 使用 results_page.html 模板渲染搜索结果页面。
-
WebAgentTextEnv 将渲染后的页面(或其文本表示)作为观测结果返回给 Agent。
-
-
Agent 决策 (LLM):
-
LLM 接收到搜索结果页面的观测。根据其指令,它可能会向用户展示部分结果,并询问用户对哪个商品感兴趣。
-
-
用户选择/Agent 决策 (LLM):
-
假设用户选择了某个商品 (例如,通过其 ASIN 或名称)。
-
LLM 决定调用 click 工具,参数可能是该商品的 ASIN (这会是一个链接按钮)。
-
-
执行 Click 工具 (商品详情):
-
click 工具调用 webshop_env.step("click[B09P5CRVQ6]") (假设 ASIN 是 B09P5CRVQ6)。
-
SimServer 接收到点击请求,识别出这是一个商品链接,加载该商品的详细信息。
-
SimServer 使用 item_page.html 模板渲染商品详情页面。
-
环境将商品详情页作为新的观测返回给 Agent。
-
-
产品探索 (LLM & Click 工具):
-
根据指令,Agent 会主动点击 "Description", "Features", "Reviews" 按钮,收集信息。
-
每次点击都会触发 click 工具,环境会切换到对应的子页面(如 description_page.html),然后 Agent 会点击 "< Prev" 返回。
-
LLM 整合从这些部分收集到的信息,形成对产品的总结。
-
-
选项选择与购买确认 (LLM & Click 工具):
-
如果商品有颜色、尺寸等选项,Agent (在 LLM 指导下) 会根据用户偏好(如果之前提供过)或询问用户后,点击相应的选项按钮。
-
每次点击选项都会刷新页面,更新已选选项。
-
LLM 向用户确认是否购买。
-
-
执行购买 (LLM & Click 工具):
-
用户确认后,LLM 指导 Agent 点击 "Buy Now" 按钮。
-
click 工具调用 webshop_env.step("click[Buy Now]")。
-
SimServer 接收请求,进入 done 逻辑:
-
计算基于 goal.py 的奖励。
-
渲染 done_page.html。
-
-
环境返回结束页面和最终奖励。
-
-
结束: Agent告知用户购买完成。
5. 部署与评估
-
部署 (README.md): 项目支持通过 Poetry 构建 wheel 文件,并提供了部署到 Vertex AI Agent Engine 的脚本 (deployment/deploy.py)。这使得 Agent 可以作为云服务对外提供。
-
评估 (README.md, eval/):
-
项目使用 pytest 进行评估。评估集可能包含一系列查询、预期的工具调用轨迹和参考答案。
-
test_config.json 可能定义了评估的判断标准。
-
tool_trajectory_avg_score 和 response_match_score 是衡量用户满意度的指标。
-
6. 定制化与未来展望
-
数据定制: 用户可以替换自己的产品数据 (items_*.json),并相应地更新人类标注指令 (items_human_ins.json),然后重新运行索引脚本,即可让 Agent 在新的商品集上工作。
-
产品数量: init_env.py 中的 num_product_items 参数可以调整加载的产品数量,以平衡性能和内存消耗。
-
LLM 更换: LiteLlm 的设计使得更换后端 LLM 相对容易。
-
功能扩展:
-
更复杂的对话管理和上下文理解。
-
集成图像搜索能力(README 中提到,但代码细节未完全展示)。
-
与真实用户账户和支付系统集成(当前为模拟)。
-
更精细化的推荐算法。
-
7. 总结
个性化购物 Agent 项目是一个精心设计的系统,它巧妙地结合了:
-
模拟环境技术: 通过 Gym 接口、轻量级服务器和浏览器模拟,构建了一个可复现、可控制的交互环境。
-
大型语言模型: 利用 LLM 的自然语言理解、推理和决策能力作为 Agent 的核心大脑。
-
提示工程: 精心设计的 Prompt 是引导 LLM 正确行为的关键。
-
工具使用: 通过定义清晰的 search 和 click 工具,赋予 Agent 在环境中感知和行动的能力。
-
信息检索: 集成 Pyserini/Lucene 搜索引擎,实现高效的产品信息检索。
-
模块化设计: 各个组件(环境、Agent、工具、数据)相对独立,易于理解、维护和扩展。
该项目不仅是电子商务领域 AI 应用的一个优秀范例,也为研究和开发更复杂的交互式 Agent 提供了宝贵的参考和实践基础。
参考资料
Quickstart - Agent Development Kit
https://github.com/google/adk-samples/tree/main/python/agents/personalized-shopping