前言

在如今快速变化的 AI 世界里,能把各种信息整合成个性化、实用的旅行计划,简直是无价之宝!马上开启小孩们的暑假模式,旅行变热了。不管是随性的周末小逃亡,还是精心设计的长假期,旅行者们都越来越想要一个智能系统,能实时从网上抓取数据,转化成详细的行程安排、活动推荐和旅行小贴士。

图片

这篇博客要介绍一个用 LangGraph 和 LLaMA 3.x 模型驱动的 Multi-Agent Travel Itinerary Planner。这个系统集结了一支“智能团队”,每个智能体各司其职:

  • Generate Itinerary Agent —— 根据你的喜好,打造逐日的旅行计划
  • Recommend Activities Agent —— 推荐当地独特的体验活动
  • Fetch Useful Links Agent —— 通过 Google Serper API 抓取相关旅行指南
  • Weather Forecaster Agent —— 提供旅行期间的天气预报
  • Packing List Generator Agent —— 定制个性化的打包清单
  • Food & Culture Recommender Agent —— 分享当地美食和文化礼仪
  • Chat Agent —— 以对话方式解答你的后续问题

系统用 Streamlit 打造了一个超友好的界面,展示如何将现代 LLM(大型语言模型)和多智能体工作流结合,带来无缝的旅行规划体验。

跟着这篇博客,你可以一步步学会如何搭建这个项目——从环境配置到多智能体协作,还能了解如何根据自己的旅行需求定制这个系统。

项目运行前提条件

以下是为运行这个基于 Streamlit 的旅行规划工具(使用 LangGraph 和 LLaMA 3.2)准备的清晰且结构化的前提条件:

  1. Python 3.10+

确保你的系统已安装 Python 3.10 或更高版本。可以用以下命令检查版本:

python --version
  1. 安装所需的 Python 库

    项目依赖多个 Python 库,通过以下命令安装所有依赖:

    pip install -r requirements.txt
    

    一些关键库包括:

    • streamlit —— 用于交互式网页界面
    • langgraph —— 构建多智能体工作流
    • langchain-community —— 集成 Ollama 和外部工具
    • python-dotenv —— 安全管理环境变量
    • fpdf —— 生成可下载的 PDF 行程
    • serper-wrapper —— 通过 Google Serper API 抓取网页结果
  2. Ollama + LLaMA 3.x 模型

    这个规划工具的核心依赖 LLaMA 3.x,通过 Ollama 运行。请确保:

    这样你的智能体就能利用强大的本地 LLM 功能。

    • • 从 ollama.com 安装 Ollama

    • • 在本地启动 Ollama 服务器

    • • 下载并运行 LLaMA 3.x 模型:

      ollama run llama3
      
  3. API 密钥
    Fetch Useful Links Agent 使用 Serper.dev API 来获取实时的旅行贴士和指南。设置方法:

    • • 在 Serper.dev 注册

    • • 生成你的 API 密钥

    • • 在项目根目录创建

      .env
      

      文件,添加:

      SERPER_API_KEY=你的_api_密钥
      
  4. 项目结构(模块化代码)

智能体被拆分成独立模块,项目目录结构可能如下:

.
├── travel_agent.py
├── agents/
│   ├── generate_itinerary.py
│   ├── recommend_activities.py
│   ├── fetch_useful_links.py
│   ├── weather_forecaster.py
│   ├── packing_list_generator.py
│   ├── food_culture_recommender.py
│   └── chat_agent.py
├── utils_export.py
├── .env
├── requirements.txt
└── README.md

代码逐步解析

1. 导入依赖和环境设置

项目开始时会导入必要的 Python 库并加载环境变量,包括核心库如 jsondotenvtempfile,以及 LangChain 的组件,比如 ChatOllama 用于连接本地 LLaMA 3.2 模型。.env 文件存储敏感配置,比如 API 密钥。

import streamlit as st
import json
from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, END
from langchain_core.messages import HumanMessage
from langchain_community.chat_models import ChatOllama
from langchain_community.utilities import GoogleSerperAPIWrapper
from dotenv import load_dotenv
import os

# 加载环境变量
load_dotenv()

# 初始化 LLM
llm = ChatOllama(model="llama3.2", base_url="http://localhost:11434")

# 初始化 Google 搜索工具
search = GoogleSerperAPIWrapper()

2. 导入智能体

环境设置好后,我们会导入各个模块化的智能体,每个智能体负责旅行规划的一个特定部分。这种设计让每个智能体专注于单一职责(比如生成行程、推荐活动或预报天气),系统更易扩展和调试。

from agents import generate_itinerary, recommend_activities, fetch_useful_links, weather_forecaster, packing_list_generator, food_culture_recommender, chat_agent
2.1 🗺️ 行程生成智能体

这个智能体根据用户偏好(目的地、预算、旅行月份、时长、旅行类型)生成逐日的旅行行程。

from langchain_core.messages import HumanMessage
from langchain_community.chat_models import ChatOllama
import json 

def generate_itinerary(state):
    llm = ChatOllama(model="llama3.2", base_url="http://localhost:11434")
    prompt = f"""
    根据以下偏好,创建详细的行程:
    {json.dumps(state['preferences'], indent=2)}

    包含每天的安排、餐饮选择和休息时间。
    """
    try:
        result = llm.invoke([HumanMessage(content=prompt)]).content
        return {"itinerary": result.strip()}
    except Exception as e:
        return {"itinerary": "", "warning": str(e)}

它将结构化的偏好转化为可读、可执行的多日计划,借助本地运行的 LLaMA 3.x 模型。

2.2 🎯 活动推荐智能体

这个智能体根据用户偏好和已生成的行程,推荐当地独特的、具有文化特色的活动。

from langchain_core.messages import HumanMessage
from langchain_community.chat_models import ChatOllama
import json 

def recommend_activities(state):
    llm = ChatOllama(model="llama3.2", base_url="http://localhost:11434")
    prompt = f"""
    根据以下偏好和行程,推荐独特的本地活动:
    偏好:{json.dumps(state['preferences'], indent=2)}
    行程:{state['itinerary']}

    尽可能为每天提供项目符号列表形式的建议。
    """
    try:
        result = llm.invoke([HumanMessage(content=prompt)]).content
        return {"activity_suggestions": result.strip()}
    except Exception as e:
        return {"activity_suggestions": "", "warning": str(e)}

2.3 🔗 有用链接智能体

这个智能体通过 Serper API 获取最新的博客、旅行建议和指南,提升用户对内容的信任度。

from langchain_community.utilities import GoogleSerperAPIWrapper

deffetch_useful_links(state):
    search = GoogleSerperAPIWrapper()
    destination = state['preferences'].get('destination', '')
    month = state['preferences'].get('month', '')
    query = f"{destination} {month} 的旅行贴士和指南"
    try:
        search_results = search.results(query)
        organic_results = search_results.get("organic", [])
        links = [
            {"title": result.get("title", "无标题"), "link": result.get("link", "")}
            for result in organic_results[:5]
        ]
        return {"useful_links": links}
    except Exception as e:
        return {"useful_links": [], "warning": f"获取链接失败:{str(e)}"}

它会抓取前 5 个相关结果,以可点击的标题形式返回,方便用户进一步阅读。

2.4 🌦️ 天气预报智能体

这个智能体为选定的目的地和旅行月份提供天气预报,并给出自然语言总结和实用建议,比如带伞或防晒霜。

from langchain_core.messages import HumanMessage
from langchain_community.chat_models import ChatOllama

def weather_forecaster(state):
    llm = ChatOllama(model="llama3.2", base_url="http://localhost:11434")
    prompt = f"""
    根据目的地和月份,提供详细的天气预报,包括温度、降水情况和旅行者的建议:
    目的地:{state['preferences'].get('destination', '')}
    月份:{state['preferences'].get('month', '')}
    """
    try:
        result = llm.invoke([HumanMessage(content=prompt)]).content
        return {"weather_forecast": result.strip()}
    except Exception as e:
        return {"weather_forecast": "", "warning": str(e)}

它确保旅行者为实际天气做好准备。

2.5 🧳 打包清单智能体

根据目的地、旅行时长、天气和旅行类型,这个智能体生成一份全面的打包清单,考虑季节和具体场景。

from langchain_core.messages import HumanMessage
from langchain_community.chat_models import ChatOllama

def packing_list_generator(state):
    llm = ChatOllama(model="llama3.2", base_url="http://localhost:11434")
    prompt = f"""
    为 {state['preferences'].get('destination', '')}{state['preferences'].get('holiday_type', '常规')} 假期生成一份全面的打包清单,旅行时间为 {state['preferences'].get('month', '')},时长 {state['preferences'].get('duration', 0)} 天。
    根据预计天气和旅行类型包含必需品。
    """
    try:
        result = llm.invoke([HumanMessage(content=prompt)]).content
        return {"packing_list": result.strip()}
    except Exception as e:
        return {"packing_list": "", "warning": str(e)}

2.6 🍲 美食与文化推荐智能体

这个智能体融合美食探索和文化沉浸,推荐必尝的当地菜肴、餐厅,并提供礼仪建议,帮助旅行者避免失礼并享受当地热情。

from langchain_core.messages import HumanMessage
from langchain_community.chat_models import ChatOllama

def food_culture_recommender(state):
    llm = ChatOllama(model="llama3.2", base_url="http://localhost:11434")
    prompt = f"""
    对于前往 {state['preferences'].get('destination', '')} 的旅行,预算为 {state['preferences'].get('budget_type', '中档')}:
    1. 推荐当地特色菜肴和餐厅。
    2. 提供重要的文化规范、礼仪建议和旅行者需注意的事项。
    回复格式分为“美食与餐饮”和“文化与礼仪”两部分。
    """
    try:
        result = llm.invoke([HumanMessage(content=prompt)]).content
        return {"food_culture_info": result.strip()}
    except Exception as e:
        return {"food_culture_info": "", "warning": str(e)}

2.7 💬 对话智能体

这个智能体为界面提供交互式问答功能,用户可以提出后续问题、请求澄清或调整计划,获得类人化的即时回答。

from langchain_core.messages import HumanMessage
from langchain_community.chat_models import ChatOllama
import json

defchat_node(state):
    llm = ChatOllama(model="llama3.2", base_url="http://localhost:11434")
    prompt = f"""
    上下文:
    偏好:{json.dumps(state['preferences'], indent=2)}
    行程:{state['itinerary']}

    用户问题:
    {state['user_question']}

    以对话方式提供见解或建议:保持回复简洁
    {{ "chat_response": "此处为你的回答" }}
    """
    try:
        result = llm.invoke([HumanMessage(content=prompt)]).content
        try:
            parsed = json.loads(result.strip())
            response = parsed.get("chat_response", result.strip())
        except json.JSONDecodeError:
            response = result.strip()
        chat_entry = {"question": state['user_question'], "response": response}
        chat_history = state.get('chat_history', []) + [chat_entry]
        return {"chat_response": response, "chat_history": chat_history}
    except Exception as e:
        return {"chat_response": "", "warning": str(e)}

它会存储对话历史,根据完整的上下文(用户偏好 + 行程)进行回答,让对话更连贯、智能。

3. 用 LangGraph 连接智能体

我们用 LangGraph 协调模块化智能体之间的流程,定义一个节点图,明确每个节点的入口和出口。LangGraph 在后台处理状态转换,确保每个函数都能干净地更新并传递状态。

3.1 定义全局状态

在连接智能体之前,我们定义一个共享的 GraphState,用于跟踪每个智能体的中间输出——从行程到天气预报再到对话历史。

from typing import TypedDict, Annotated
class GraphState(TypedDict):
    preferences_text: str
    preferences: dict
    itinerary: str
    activity_suggestions: str
    useful_links: list[dict]
    weather_forecast: str
    packing_list: str
    food_culture_info: str
    chat_history: Annotated[list[dict], "问答列表"]
    user_question: str
    chat_response: str

这让所有智能体都能读写一个动态更新的状态字典。

3.2 将智能体注册为节点

将每个导入的智能体函数添加到 LangGraph 工作流中作为节点:

from langgraph.graph import StateGraph, END
workflow = StateGraph(GraphState)
# 注册智能体为节点
workflow.add_node("generate_itinerary", generate_itinerary)
workflow.add_node("recommend_activities", recommend_activities)
workflow.add_node("fetch_useful_links", fetch_useful_links)
workflow.add_node("weather_forecaster", weather_forecaster)
workflow.add_node("packing_list_generator", packing_list_generator)
workflow.add_node("food_culture_recommender", food_culture_recommender)
workflow.add_node("chat", chat_agent)

每个节点名称是一个字符串标识符,用于在图中引用该函数。

3.3 定义流程

我们指定入口点并将每个节点连接到终点(END)。为简单起见,每个用户操作运行一个节点,但你也可以根据需要定义复杂路径。

workflow.set_entry_point("generate_itinerary")
# 定义单次流程的终点
workflow.add_edge("generate_itinerary", END)
workflow.add_edge("recommend_activities", END)
workflow.add_edge("fetch_useful_links", END)
workflow.add_edge("weather_forecaster", END)
workflow.add_edge("packing_list_generator", END)
workflow.add_edge("food_culture_recommender", END)
workflow.add_edge("chat", END)

最后,编译图:

graph = workflow.compile()

这会生成一个可调用的对象,接受 GraphState 并在选定节点运行后返回更新版本。

3.4 使用示例

调用图中的任意智能体:

result = graph.invoke(st.session_state.state)

也可以直接调用特定节点(如果需要):

workflow.get_node("recommend_activities")(st.session_state.state)

这对于 Streamlit 前端的按钮驱动交互尤其有用,接下来会介绍。

4. 构建 Streamlit 界面

Streamlit 界面将所有功能整合在一起,让用户可以输入旅行偏好、调用各个智能体并查看结果,界面简洁且交互性强。

4.1 初始化会话状态

我们初始化一个全面的会话状态字典,持久保存所有智能体的输入和输出:

if "state"notin st.session_state:
    st.session_state.state = {
        "preferences_text": "",
        "preferences": {},
        "itinerary": "",
        "activity_suggestions": "",
        "useful_links": [],
        "weather_forecast": "",
        "packing_list": "",
        "food_culture_info": "",
        "chat_history": [],
        "user_question": "",
        "chat_response": ""
    }

这确保系统各部分(从行程到对话历史)保持同步。

4.2 用户输入表单

我们提供一个表单,让用户输入旅行详情,如目的地、月份、时长、旅行类型和预算:

with st.form("travel_form"):
    col1, col2 = st.columns(2)
    with col1:
        destination = st.text_input("目的地")
        month = st.selectbox("旅行月份", [...])
        duration = st.slider("旅行天数", 1, 30, 7)
        num_people = st.selectbox("人数", [...])
    with col2:
        holiday_type = st.selectbox("旅行类型", [...])
        budget_type = st.selectbox("预算类型", [...])
        comments = st.text_area("额外备注")
    submit_btn = st.form_submit_button("生成行程")

提交后,我们会更新会话状态并触发行程生成智能体。

4.3 智能体操作按钮

生成行程后,我们显示一排按钮,让用户获取活动建议、有用链接、天气预报、打包清单和美食文化信息。每个按钮触发对应的智能体,并动态更新界面:

col_btn1, col_btn2, col_btn3, col_btn4, col_btn5 = st.columns(5)
with col_btn1:
    if st.button("获取活动建议"):
        result = recommend_activities(st.session_state.state)
        st.session_state.state.update(result)
with col_btn2:
    if st.button("获取有用链接"):
        result = fetch_useful_links(st.session_state.state)
        st.session_state.state.update(result)
# ... 类似地处理天气、打包清单、美食与文化

这种模块化方式让用户可以交互式探索旅行的不同方面。

4.4 显示智能体输出

我们将每个智能体的输出显示在可展开的面板中,保持界面整洁有序:

if st.session_state.state.get("activity_suggestions"):
    with st.expander("🎯 活动建议"):
        st.markdown(st.session_state.state["activity_suggestions"])
if st.session_state.state.get("useful_links"):
    with st.expander("🔗 有用链接"):
        for link in st.session_state.state["useful_links"]:
            st.markdown(f"- [{link['title']}]({link['link']})")
# ... 类似地处理天气、打包清单、美食与文化信息

这让用户可以按需深入查看具体信息。

4.5 交互式聊天

为了完善体验,我们加入了一个由 chat_agent 驱动的聊天界面,用户可以询问行程相关问题,获得基于上下文的对话式回答:

st.markdown("### 聊聊你的行程")
for chat in st.session_state.state["chat_history"]:
    with st.chat_message("user"):
        st.markdown(chat["question"])
    with st.chat_message("assistant"):
        st.markdown(chat["response"])
if user_input := st.chat_input("询问行程相关问题"):
    st.session_state.state["user_question"] = user_input
    result = chat_agent(st.session_state.state)
    st.session_state.state.update(result)
    st.experimental_rerun()

这种无缝的聊天体验让旅行规划更具互动性和个性化。

4.6 PDF 导出

最后,我们提供一个导出按钮,让用户将行程下载为 PDF 文档:

if st.button("导出为 PDF"):
    pdf_path = export_to_pdf(st.session_state.state["itinerary"])
    if pdf_path:
        with open(pdf_path, "rb") as f:
            st.download_button("下载行程 PDF", f, file_name="itinerary.pdf")

这个界面设计让用户旅程流畅直观,同时高效整合了由 LangGraph 和 LLaMA 3.x 模型驱动的多智能体后端。

总结

这个项目的亮点在于,它将复杂的旅行规划问题拆分成多个专注的小智能体,每个智能体处理特定任务,比如生成行程、推荐活动、抓取实时网页数据或提供文化贴士。这种模块化设计不仅让代码更清晰、易于维护,还能让你轻松替换或改进单个智能体,而无需重构整个系统。加上 LangGraph 的流程管理,智能体之间的协作和数据流转变得超级顺畅。

更强的是,Streamlit 界面让整个系统易于使用且交互性强,用户只需几次点击就能获得实时反馈,探索旅行的方方面面。这种模块化 AI 智能体、灵活的流程编排和用户友好的界面结合,造就了一个实用、可扩展、随时能投入实际使用的工具。如果你对开发 AI 驱动的应用感兴趣,这种多智能体模式是一个很棒的学习和适配模板。

最后

为什么要学AI大模型

当下,⼈⼯智能市场迎来了爆发期,并逐渐进⼊以⼈⼯通⽤智能(AGI)为主导的新时代。企业纷纷官宣“ AI+ ”战略,为新兴技术⼈才创造丰富的就业机会,⼈才缺⼝将达 400 万!

DeepSeek问世以来,生成式AI和大模型技术爆发式增长,让很多岗位重新成了炙手可热的新星,岗位薪资远超很多后端岗位,在程序员中稳居前列。

在这里插入图片描述

与此同时AI与各行各业深度融合,飞速发展,成为炙手可热的新风口,企业非常需要了解AI、懂AI、会用AI的员工,纷纷开出高薪招聘AI大模型相关岗位。
在这里插入图片描述
最近很多程序员朋友都已经学习或者准备学习 AI 大模型,后台也经常会有小伙伴咨询学习路线和学习资料,我特别拜托北京清华大学学士和美国加州理工学院博士学位的鲁为民老师给大家这里给大家准备了一份涵盖了AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频 全系列的学习资料,这些学习资料不仅深入浅出,而且非常实用,让大家系统而高效地掌握AI大模型的各个知识点。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

AI大模型系统学习路线

在面对AI大模型开发领域的复杂与深入,精准学习显得尤为重要。一份系统的技术路线图,不仅能够帮助开发者清晰地了解从入门到精通所需掌握的知识点,还能提供一条高效、有序的学习路径。

img

但知道是一回事,做又是另一回事,初学者最常遇到的问题主要是理论知识缺乏、资源和工具的限制、模型理解和调试的复杂性,在这基础上,找到高质量的学习资源,不浪费时间、不走弯路,又是重中之重。

AI大模型入门到实战的视频教程+项目包

看视频学习是一种高效、直观、灵活且富有吸引力的学习方式,可以更直观地展示过程,能有效提升学习兴趣和理解力,是现在获取知识的重要途径

在这里插入图片描述
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
在这里插入图片描述

海量AI大模型必读的经典书籍(PDF)

阅读AI大模型经典书籍可以帮助读者提高技术水平,开拓视野,掌握核心技术,提高解决问题的能力,同时也可以借鉴他人的经验。对于想要深入学习AI大模型开发的读者来说,阅读经典书籍是非常有必要的。
在这里插入图片描述

600+AI大模型报告(实时更新)

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。
在这里插入图片描述

AI大模型面试真题+答案解析

我们学习AI大模型必然是想找到高薪的工作,下面这些面试题都是总结当前最新、最热、最高频的面试题,并且每道题都有详细的答案,面试前刷完这套面试题资料,小小offer,不在话下
在这里插入图片描述

在这里插入图片描述

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐