
使用 LangGraph 构建 AI 🤖 代理:第 11 部分 - 构建餐厅和天气推荐...
- Rifx.Online
- Programming , Chatbots , Generative AI
- 28 Feb, 2025
Welcome back to the LangGraph系列! 🎉 在这一部分,我们将把迄今为止学到的所有内容提升到一个新水平,创建一个完全整合的现实世界用例:餐厅与天气推荐系统。想象一下你正在计划一个约会之夜——如果有一个AI可以根据活动和天气建议最佳餐厅,那该多好啊?这正是我们今天要构建的内容!
有什么新内容?🌟 在这篇文章中,你将了解:
- 多智能体协调: 多个AI智能体(如天气和餐厅搜索)如何协同工作以实现共同目标。
- 工具集成: 使用外部API(如DuckDuckGo和OpenWeatherMap)获取实时数据。
- 状态管理: 在子图和父图之间共享和转换数据。
- 现实世界应用: 创建一个基于事件的实用推荐系统。
目标 🎯 我们正在构建一个系统,其中:
- 用户请求特定地点和事件的餐厅推荐。
- 系统检查天气预报。
- 它获取该地点该事件的高评分餐厅。
- 最后,AI根据天气条件建议最佳去处——或者是否更适合待在家里。
让我们深入代码吧! 💻
1️⃣ 设置环境 🛠️
我们将首先加载必要的库并初始化Groq模型:
import datetime
from dotenv import load_dotenv
from typing_extensions import TypedDict, Annotated
from langgraph.prebuilt import ToolNode, tools_condition
from langchain_groq import ChatGroq
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langchain_community.tools import DuckDuckGoSearchRun
load_dotenv()
llm = ChatGroq(model="llama-3.3-70b-versatile")
2️⃣ 定义状态和工具 🧠
我们为天气和餐厅子图定义状态。
class WeatherState(TypedDict):
messages: Annotated[list, add_messages]
weather_report: str
class Restaurant(TypedDict):
name: Annotated[str, ..., "餐厅名称"]
address: Annotated[str, ..., "餐厅地址"]
details: Annotated[str, ..., "餐厅详情"]
class RestaurantState(TypedDict):
messages: Annotated[list, add_messages]
location: str
event: str
date: str
restaurants: list[Restaurant]
3️⃣ 构建天气子图 🌦️
天气子图获取实时天气数据并进行格式化。
def weather_assistant(state: WeatherState):
return {"messages": [llm.invoke(state["messages"])]}
def weather_formatter(state: WeatherState):
weather_report = ""
for message in state['messages']:
weather_report += message.content
return {"weather_report": weather_report}
weather_builder = StateGraph(WeatherState)
weather_builder.add_node("weather_assistant", weather_assistant)
weather_builder.add_node("weather_formatter", weather_formatter)
weather_builder.add_edge(START, "weather_assistant")
weather_builder.add_edge("weather_assistant", "weather_formatter")
weather_builder.add_edge("weather_formatter", END)
weather_graph = weather_builder.compile()
4️⃣ 构建餐厅子图 🍽️
我们使用DuckDuckGo的搜索工具获取餐厅建议。
def get_restaurants_duckduckGo_tool(query: str) -> str:
search = DuckDuckGoSearchRun()
return search.invoke(query)
tools = [get_restaurants_duckduckGo_tool]
llm_with_restaurant_tool = llm.bind_tools(tools)
def restaurant_assistant(state: RestaurantState):
result = llm_with_restaurant_tool.invoke(state["messages"])
return {"messages": [result]}
def restaurants_list_formatter(state: RestaurantState):
search_result = state["messages"][-1].content
structured_llm = llm.with_structured_output(Restaurant)
restaurants = structured_llm.invoke(search_result)
return {"restaurants": restaurants}
restaurant_builder = StateGraph(RestaurantState)
restaurant_builder.add_node("restaurant_assistant", restaurant_assistant)
restaurant_builder.add_node("restaurants_list", restaurants_list_formatter)
restaurant_builder.add_edge(START, "restaurant_assistant")
restaurant_builder.add_edge("restaurant_assistant", "restaurants_list")
restaurant_builder.add_edge("restaurants_list", END)
restaurant_graph = restaurant_builder.compile()
5️⃣ 将子图组合成父图 🌐
父图调用两个子图并提供最终推荐。
class ParentState(TypedDict):
messages: Annotated[list, add_messages]
location: str
date: str
event: str
restaurants: list[Restaurant]
weather_report: str
recommendation: str
def query_analyzer(state: ParentState):
return {
"location": "班加罗尔",
"date": "星期天",
"event": "约会夜",
"messages": state['messages']
}
def recommendation_analyzer(state: ParentState):
summary_prompt = (
f"天气报告: {state['weather_report']}\\n"
f"餐厅: {state['restaurants']}\\n"
"根据这些信息,建议外出是否是个好主意,或者待在家里更好。"
)
result = llm.invoke(summary_prompt)
return {"recommendation": result.content}
entry_builder = StateGraph(ParentState)
entry_builder.add_node("query_analyzer", query_analyzer)
entry_builder.add_node("weather_graph", weather_graph)
entry_builder.add_node("restaurant_graph", restaurant_graph)
entry_builder.add_node("recommendation_analyzer", recommendation_analyzer)
entry_builder.add_edge(START, "query_analyzer")
entry_builder.add_edge("query_analyzer", "weather_graph")
entry_builder.add_edge("query_analyzer", "restaurant_graph")
entry_builder.add_edge("weather_graph", "recommendation_analyzer")
entry_builder.add_edge("restaurant_graph", "recommendation_analyzer")
entry_builder.add_edge("recommendation_analyzer", END)
graph = entry_builder.compile()
result = graph.invoke({
"messages": ["告诉我下周日班加罗尔约会夜的最佳餐厅"]
})
print(result['recommendation'])
6️⃣ 输出 📝
星期天的天气看起来晴朗宜人——外出夜游的完美天气!🌙 以下是班加罗尔约会夜的一些高评分餐厅:
1️⃣ Grasshopper — 美丽的花园座位和美食菜单。
2️⃣ Olive Beach — 浪漫的氛围与地中海美食。
3️⃣ Byg Brewski Brewing Co. — 极好的氛围,手工啤酒和户外座位。
享受你的夜晚! 💕
7️⃣ 关键要点 🔑
- 子图的力量: 我们使用子图实现模块化和可重用的工作流。
- 工具集成: DuckDuckGo和天气API将现实世界数据引入我们的系统。
- 多智能体系统: 天气和餐厅子图独立工作并无缝结合其结果。
- 状态管理: 数据在子图和父图之间高效流动。
🎯 结论 在系列的这一部分中,我们探讨了子图如何在LangGraph中实现模块化,使我们能够通过将工作流分解为更小的可重用组件来构建复杂的多智能体系统。我们演示了如何管理父图和子图之间的通信,无论它们是否共享相同的状态架构或需要状态转换。
通过利用子图,我们可以构建执行复杂并行任务的AI代理,同时保持代码的清晰和可管理性。LangGraph使用子图组合复杂系统的能力使其成为开发可扩展、模块化AI代理的优秀工具。
💬 你怎么看? 在下面的评论中分享你的想法、问题或建议!
查看我的YouTube频道以获取更多精彩内容! [YouTube频道链接 — Harsha Selvi]
免责声明: 本文使用AI工具进行了重述,部分内容来源于多个来源,以提供全面的概述。