旅荐网

您现在的位置是:首页 > 国内旅游目的推荐 > 正文

国内旅游目的推荐

保姆级教程!5分钟部署能查天气、荐景点的智能旅行助(附完整可运行代码)

admin2026年02月10日 02:09:49国内旅游目的推荐1
保姆级教程!5分钟部署能查天气、荐景点的智能旅行助(附完整可运行代码)

不用复杂框架,不用高深算法,只需几行 Python 代码 + 3 个 API 密钥,就能搭建一个能自主拆解任务、调用工具的智能旅行助手!今天这篇「零踩坑教程」,从环境配置到代码运行全程拆解,新手也能跟着一步步部署成功,最后还能直接复用代码解决实际出行需求~

一、先明确:我们要做什么?

最终目标:让智能体独立完成用户指令 ——「查询今天北京的天气,再根据天气推荐合适的旅游景点」。

核心逻辑:遵循智能体经典的「Thought-Action-Observation」闭环

  1. 思考(Thought):用户需求分两步,必须先查天气再荐景点,缺一不可;

  2. 行动(Action):自动调用天气 API 获取数据,再调用搜索工具推荐景点;

  3. 观察(Observation):接收工具返回结果,判断是否需要继续行动,最终整合答案。

全程无需人工干预,让代码自己 “做决策”!

二、前置准备:3 个关键工具 + 1 个环境(必看!)

  1. 基础环境要求
  • 操作系统:Windows/macOS/Linux 均可

  • Python 版本:3.10+(低于 3.10 会出现依赖兼容问题)

  • 网络:需能访问外网(用于调用 API,国内用户可搭配常规工具)

  1. 必须安装的依赖库

打开终端 / 命令行,复制以下命令一键安装(建议先切换国内镜像源,速度更快):

切换清华镜像源(可选,加速安装)

pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

安装核心依赖(缺一不可)

pip install requests==2.31.0 tavily-python==0.3.0 openai==1.35.10 python-dotenv==1.0.1

  • requests:调用免费天气 API;

  • tavily-python:AI 专用搜索工具(景点推荐核心);

  • openai:兼容主流 LLM 平台(支持 AIHubmix/ModelScope 等);

  • python-dotenv:安全管理 API 密钥,避免泄露。

  1. 3 个 API 密钥获取(免费额度足够用)

这是部署成功的关键,每个都附详细获取步骤,按图操作即可:

(1)Tavily Search API(景点推荐用)

  1. 访问官网:https://tavily.com/(无需梯子,直接打开);

  2. 注册账号:支持邮箱 / Google 账号,注册流程 1 分钟完成;

  3. 获取密钥:登录后点击右上角「Console」,进入页面后直接复制「API Key」(默认生成 1 个,无需额外操作);

  4. 验证:免费额度每月 1000 次搜索,足够测试和日常使用。

(2)LLM API 密钥(智能决策核心,二选一)

推荐两个兼容 OpenAI 接口的平台,国内用户优先选 ModelScope,海外用户选 AIHubmix:

选项 A:ModelScope(国内友好,无网络限制)

  1. 访问官网:https://modelscope.cn/(阿里旗下,国内直接访问);

  2. 注册登录:支持手机号注册,需完成实名认证(常规流程,5 分钟内搞定);

  3. 绑定阿里云账号:登录后进入「个人中心」→「账号绑定」,绑定阿里云账号(必须绑定,否则 API 无法使用);

  4. 获取密钥:进入「模型服务」→「API-KEY 管理」,点击「生成新的 API-KEY」,复制保存;

  5. 选模型:进入「模型库」→ 筛选「API-Inference」,推荐选择「qwen-turbo」(免费,每天 2000 次调用)或「deepseek-r1-70b-instruct」(免费体验)。

选项 B:AIHubmix(海外稳定,支持多模型)

  1. 访问官网:https://aihubmix.com/?aff=Igcn/;

  2. 注册登录:支持邮箱 / 手机号,无需实名认证;

  3. 获取密钥:登录后进入「API 密钥管理」,直接复制默认生成的密钥;

  4. 选模型:进入「模型中心」→ 筛选「免费」,推荐「coding-glm-4.7-free」(兼容 OpenAI 格式)。

(3)天气 API(无需密钥,直接调用)

用免费公开的 wttr.in API,无需注册,代码中已内置接口,直接使用即可。

  1. 环境变量配置(避免密钥硬编码)

  2. 在项目文件夹(比如命名为「travel-agent」)中,新建一个名为「.env」的文件(注意:文件名前有个点,无后缀);

  3. 用记事本 / VS Code 打开「.env」,按以下格式粘贴密钥(替换成你自己的):

Tavily API(必须填)

TAVILY_API_KEY=你的Tavily密钥(比如:tvly-xxxxxxxxx)

LLM配置(二选一,填对应平台的信息)

选项A:ModelScope(国内用户优先)

OPENAI_API_KEY=你的ModelScope API-KEY(比如:sk-xxxxxxxxx) OPENAI_BASE_URL=https://api-inference.modelscope.cn/v1/ MODEL_ID=qwen-turbo(或你选的其他模型名称)

选项B:AIHubmix(海外用户)

OPENAI_API_KEY=你的AIHubmix密钥(比如:sk-xxxxxxxxx)

OPENAI_BASE_URL=https://aihubmix.com/v1

MODEL_ID=coding-glm-4.7-free

  1. 保存文件:确保「.env」和后续的代码文件在同一个文件夹下。

三、完整可运行代码(直接复制粘贴,无需修改)

新建一个 Python 文件(命名为「travel_agent.py」),复制以下代码,保存到项目文件夹(与「.env」同目录):

import requests import os import re from tavily import TavilyClient from dotenv import load_dotenv from openai import OpenAI from typing import Dict, Optional, Tuple

 第一步:加载环境变量(关键!)

load_dotenv()  # 自动读取.env文件中的配置 print("正在加载环境变量...")

验证核心配置是否存在

required_env = ["TAVILY_API_KEY", "OPENAI_API_KEY", "OPENAI_BASE_URL", "MODEL_ID"] missing_env = [env for env in required_env if not os.getenv(env)] if missing_env: raise ValueError(f"缺少必要环境变量,请检查.env文件:{', '.join(missing_env)}") print("环境变量加载成功!")

第二步:定义工具函数(天气+景点)

def get_weather(city: str) -> str: """ 工具1:查询指定城市实时天气(基于wttr.in免费API) :param city: 城市名称(如"北京"、"上海") :return: 格式化的天气信息或错误提示 """ if not city: return "错误:城市名称不能为空" url = f"https://wttr.in/{city}?format=j1" try: # 设置超时时间,避免网络卡顿时无限等待 response = requests.get(url, timeout=10) response.raise_for_status()  # 自动抛出HTTP错误(如404、500) data = response.json()

    # 提取关键天气数据(兼容API返回格式变化)
    current_condition = data.get("current_condition", [{}])[0]
    weather_desc = current_condition.get("weatherDesc", [{}])[0].get("value", "未知")
    temp_c = current_condition.get("temp_C", "未知")
    humidity = current_condition.get("humidity", "未知")

    return f"{city}当前天气:{weather_desc},气温{temp_c}摄氏度,湿度{humidity}%"
except requests.exceptions.Timeout:
    return f"错误:查询{city}天气超时,请检查网络连接"
except requests.exceptions.RequestException as e:
    return f"错误:查询{city}天气失败(网络问题):{str(e)[:50]}"
except (KeyError, IndexError) as e:
    return f"错误:解析天气数据失败,可能是城市名称无效({str(e)})"

def get_attraction(city: str, weather: str) -> str: """ 工具2:根据城市和天气推荐景点(基于Tavily Search API) :param city: 城市名称 :param weather: 天气信息(如"晴朗,气温26摄氏度") :return: 格式化的景点推荐或错误提示 """ if not city or not weather: return "错误:城市名称和天气信息不能为空"

api_key = os.getenv("TAVILY_API_KEY")
tavily = TavilyClient(api_key=api_key)
# 构造精准查询词,提升搜索结果质量
query = f"{city},{weather},推荐3个最适合的旅游景点,每个景点附带1句推荐理由(简洁明了)"

try:
    # 调用Tavily API,设置基础搜索深度(平衡速度和精度)
    response = tavily.search(
        query=query,
        search_depth="basic",
        include_answer=True,
        timeout=15
    )

    # 优先使用API总结后的答案
    if response.get("answer"):
        return response["answer"]

    # 若没有总结答案,格式化原始搜索结果
    results = response.get("results", [])[:3]  # 最多取3个结果
    if not results:
        return f"未找到{city}在{weather}天气下的景点推荐,可尝试更换城市或天气描述"

    formatted = [f"{i+1}. {res.get('title', '未知景点')}:{res.get('content', '无推荐理由')[:80]}..." for i, res in enumerate(results)]
    return "根据实时搜索,为你推荐以下景点:\n" + "\n".join(formatted)
except Exception as e:
    return f"错误:景点搜索失败:{str(e)[:50]}"

工具注册表:统一管理所有工具,方便后续扩展

TOOL_REGISTRY: Dict[str, callable] = { "get_weather": get_weather, "get_attraction": get_attraction }

第三步:LLM客户端(兼容OpenAI接口)

class LLMClient: def init(self, model: str, api_key: str, base_url: str): self.client = OpenAI( api_key=api_key, base_url=base_url, timeout=20  # 设置LLM调用超时时间 ) self.model = model

def generate_response(self, user_prompt: str, system_prompt: str) -> Optional[str]:
    """
    调用LLM生成思考和行动
    :param user_prompt: 用户请求(含历史记录)
    :param system_prompt: 系统提示词(智能体规则)
    :return: LLM返回结果或None(失败时)
    """
    try:
        messages = [
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": user_prompt}
        ]
        response = self.client.chat.completions.create(
            model=self.model,
            messages=messages,
            temperature=0.3,  # 降低随机性,确保工具调用格式稳定
            max_tokens=200
        )
        return response.choices[0].message.content.strip()
    except Exception as e:
        print(f"LLM调用失败:{str(e)}")
        return None

初始化LLM客户端

llm_client = LLMClient( model=os.getenv("MODEL_ID"), api_key=os.getenv("OPENAI_API_KEY"), base_url=os.getenv("OPENAI_BASE_URL") )

 第四步:智能体核心配置(提示词模板)

SYSTEM_PROMPT = """ 你是一个严格遵守规则的智能旅行助手,只能使用提供的工具解决用户问题,按以下要求工作:

核心任务

分析用户请求,通过调用工具获取必要信息,最终给出完整答案。

可用工具(仅能使用这两个)

  1. get_weather(city="城市名称"):查询指定城市的实时天气,必须传入city参数(字符串类型);
  2. get_attraction(city="城市名称", weather="天气信息"):根据城市和天气推荐景点,两个参数都必须传入。

输出格式(强制要求!不按格式输出会失败)

每次回复只能包含一对Thought和Action,格式如下: Thought: [你的思考过程,比如"用户需要先查天气,再荐景点,现在调用天气工具"] Action: [行动指令,二选一]

  • 调用工具:function_name(arg_name="arg_value", arg2_name="arg2_value")
  • 结束任务:Finish[最终给用户的答案,简洁友好,包含关键信息]

重要规则

  1. 必须先获取天气信息,才能调用景点推荐工具,不能跳过步骤;
  2. 工具参数必须用双引号包裹(如city="北京"),不能遗漏或用单引号;
  3. 每次只能执行一个行动(要么调用一个工具,要么结束任务),不能同时调用多个工具;
  4. 拿到景点推荐结果后,必须立即用Finish格式返回最终答案,不能再调用其他工具;
  5. 若工具返回错误(如"查询失败"),请直接用Finish格式告知用户,不再重试。 """

 第五步:主循环(实现Thought-Action-Observation闭环)

def run_travel_agent(user_query: str, max_rounds: int = 5) -> None: """ 运行智能旅行助手主循环 :param user_query: 用户请求 :param max_rounds: 最大循环次数(避免无限迭代) """ print(f"\n===== 智能旅行助手 ======") print(f"用户请求:{user_query}") print("=" * 50)

# 存储对话历史(上下文)
conversation_history: list[str] = [f"用户请求:{user_query}"]

for round_num in range(1, max_rounds + 1):
    print(f"\n【循环{round_num}/{max_rounds}】")

    # 1. 构建完整提示词(包含历史上下文)
    full_prompt = "\n".join(conversation_history)

    # 2. 调用LLM生成思考和行动
    print("正在调用大语言模型...")
    llm_output = llm_client.generate_response(full_prompt, SYSTEM_PROMPT)
    if not llm_output:
        print("错误:LLM未返回有效结果,终止任务")
        return

    print(f"模型输出:\n{llm_output}")
    conversation_history.append(llm_output)

    # 3. 解析LLM输出中的Action(关键步骤,兼容格式误差)
    action, final_answer = parse_action(llm_output)

    # 4. 处理行动:结束任务或调用工具
    if final_answer:
        print(f"\n✅ 任务完成!最终答案:\n{final_answer}")
        return

    if not action:
        error_msg = "错误:未解析到有效Action,格式不符合要求"
        print(error_msg)
        conversation_history.append(f"Observation: {error_msg}")
        continue

    # 5. 执行工具调用
    tool_name, tool_kwargs = action
    if tool_name not in TOOL_REGISTRY:
        error_msg = f"错误:未定义工具'{tool_name}',仅支持{list(TOOL_REGISTRY.keys())}"
        print(error_msg)
        conversation_history.append(f"Observation: {error_msg}")
        continue

    print(f"正在调用工具:{tool_name},参数:{tool_kwargs}")
    tool_result = TOOL_REGISTRY[tool_name](**tool_kwargs)
    print(f"工具返回结果:\n{tool_result}")
    conversation_history.append(f"Observation: {tool_result}")

# 循环次数用尽仍未完成任务
print(f"\n❌ 任务超时:已达到最大循环次数{max_rounds},终止任务")

def parse_action(llm_output: str) -> Tuple[Optional[Tuple[str, Dict[str, str]]], Optional[str]]: """ 解析LLM输出,提取Action(兼容格式误差) :return: ((工具名,工具参数), 最终答案),若未匹配则返回(None, None) """ # 先检查是否是结束任务 finish_match = re.search(r"Finish[([^]]+)]", llm_output, re.IGNORECASE | re.DOTALL) if finish_match: return None, finish_match.group(1).strip()

# 检查是否是工具调用
action_match = re.search(r"Action:\s*(\w+)\((.*?)\)", llm_output, re.DOTALL)
if not action_match:
    return None, None

tool_name = action_match.group(1).strip()
args_str = action_match.group(2).strip()

# 解析工具参数(兼容空格、引号格式误差)
kwargs = {}
args_pattern = re.findall(r'(\w+)\s*=\s*"([^"]*)"', args_str)
for arg_name, arg_value in args_pattern:
    kwargs[arg_name.strip()] = arg_value.strip()

return (tool_name, kwargs), None

启动智能助手(直接运行即可)

if name == "main": # 可修改用户请求,比如查询上海、广州等其他城市 user_input = "你好,请帮我查询一下今天北京的天气,然后根据天气推荐一个合适的旅游景点。" run_travel_agent(user_input)

四、运行验证+常见问题排查(零踩坑关键)

  1. 一键运行步骤

  2. 确保「travel_agent.py」和「.env」在同一个文件夹下;

  3. 打开终端,进入该文件夹(命令:cd 文件夹路径,比如 cd Desktop/travel-agent);

  4. 输入命令:python travel_agent.py,按下回车,等待运行即可。

  5. 预期运行效果(示例)

正在加载环境变量... 环境变量加载成功!

===== 智能旅行助手 ====== 

用户请求:你好,请帮我查询一下今天北京的天气,然后根据天气推荐一个合适的旅游景点。

【循环1/5】 正在调用大语言模型... 模型输出: Thought: 用户需要先查询北京的天气,再根据天气推荐景点,现在调用get_weather工具获取天气信息。 Action: get_weather(city="北京") 正在调用工具:get_weather,参数:{'city': '北京'} 工具返回结果: 北京当前天气:晴朗,气温26摄氏度,湿度45%

【循环2/5】 正在调用大语言模型... 模型输出: Thought: 已经获取到北京的天气信息,现在调用get_attraction工具,根据天气推荐合适的景点。 Action: get_attraction(city="北京", weather="晴朗,气温26摄氏度,湿度45%") 正在调用工具:get_attraction,参数:{'city': '北京', 'weather': '晴朗,气温26摄氏度,湿度45%'} 工具返回结果:

  1. 颐和园:晴朗天气下可欣赏昆明湖的碧波荡漾与古建倒影,气候舒适适合漫步。
  2. 八达岭长城:晴天视野开阔,能清晰观赏长城的蜿蜒起伏,拍照出片率高。
  3. 奥林匹克森林公园:植被繁茂,晴朗天气适合骑行、野餐,感受自然气息。

【循环3/5】 正在调用大语言模型... 模型输出: Thought: 已经获取到天气和景点推荐信息,无需继续调用工具,整理成最终答案反馈给用户。 Action: Finish[今天北京天气晴朗,气温26摄氏度,湿度45%,非常适合户外出行~ 推荐3个合适的景点:1. 颐和园,可赏湖景与古建;2. 八达岭长城,视野开阔适合观光拍照;3. 奥林匹克森林公园,适合休闲漫步。祝你旅途愉快!]

✅ 任务完成!最终答案: 今天北京天气晴朗,气温26摄氏度,湿度45%,非常适合户外出行~ 推荐3个合适的景点:1. 颐和园,可赏湖景与古建;2. 八达岭长城,视野开阔适合观光拍照;3. 奥林匹克森林公园,适合休闲漫步。祝你旅途愉快!

  1. 常见问题速查(新手必看)
  • 问题1:运行报错“缺少必要环境变量” → 解决方案:检查.env文件是否和代码文件同目录,密钥是否填写正确,没有遗漏空格;

  • 问题2:LLM调用失败/超时 → 解决方案:国内用户确认ModelScope API已绑定阿里云账号,海外用户检查网络,更换模型重试;

  • 问题3:天气查询失败/城市无效 → 解决方案:确保城市名称正确(如“北京”而非“北京市”),检查网络能否访问wttr.in;

  • 问题4:pip安装依赖报错 → 解决方案:确认Python版本≥3.10,用清华镜像源重新安装(复制前文的镜像源命令);

  • 问题5:模型输出格式错误,无法解析Action → 解决方案:无需修改代码,重新运行即可(LLM偶尔会输出偏差,降低随机性后概率极低)。

五、不止于查天气荐景点:新手也能玩转智能体

看到这里,相信你已经成功部署了自己的第一个智能旅行助手!可能有朋友会说:“这看起来只是个简单的工具调用,和我理解的‘智能体’不一样?”

其实不然——我们今天搭建的,正是当前主流智能体(比如ChatGPT插件、LangChain应用)的核心雏形。它没有复杂的框架封装,却完整实现了“思考-行动-观察”的闭环,这也是智能体能“自主工作”的关键。

从技术层面来说,这段代码里藏着3个核心知识点,新手吃透就能入门智能体开发:

  1. 工具化思维:把“查天气”“荐景点”拆成独立工具,后续想加“查火车票”“订酒店”,只需新增工具函数,不用改动核心逻辑;

  2. 提示词工程:通过严格的格式约束,让LLM“听话”,精准调用工具——这也是为什么代码能稳定运行,不出现乱输出的关键;

  3. 上下文管理:用对话历史保存每一步的思考、行动和结果,让智能体能“记住”前一步做了什么,从而推进任务,而不是孤立决策。

而从实用角度来说,这个智能助手也能直接“上手即用”:

比如周末想出去玩,不用先打开天气APP查天气,再打开旅游软件找景点,只需修改代码里的“user_input”,把“北京”改成你所在的城市,运行代码就能直接拿到定制化推荐;甚至可以发给朋友,帮他们规划短途出行,成就感拉满~

如果想进一步进阶,也可以试试这些简单的拓展玩法,零难度就能升级智能助手:

  • 新增工具:添加“查火车票”“查酒店价格”的函数,让助手能规划完整出行流程;

  • 优化交互:把文字输入改成GUI界面(用tkinter简单封装),不用打开终端就能使用;

  • 支持多城市:修改提示词和代码,让助手能同时处理“查询上海和苏州的天气,分别推荐景点”;

  • 离线运行:用Ollama部署本地模型(比如Llama 3),不用依赖外网API,断网也能使用。

很多人觉得智能体开发“高深莫测”,需要掌握复杂的框架和算法,但其实从最简单的案例入手,一步步实践,就能快速入门。今天这篇教程,就是希望能帮你打破“技术壁垒”——不用死记硬背理论,不用纠结复杂概念,跟着步骤复制代码、配置环境,就能亲手搭建一个能解决实际问题的智能体。

最后想说:AI时代,动手实践才是最快的学习方式。可能你第一次运行会遇到报错,第一次配置API会出错,但没关系,跟着排查指南一步步解决,当看到智能助手自动查天气、荐景点的那一刻,你会发现:原来智能体开发,并没有想象中那么难。

赶紧拿起电脑,跟着教程操作起来吧~ 部署成功后,不妨在评论区晒出你的运行效果,看看谁的智能助手更实用!如果遇到解决不了的问题,也可以在评论区留言,我会一一回复帮你排查~

补充说明:文中所有API均提供免费额度,完全满足日常测试和使用需求,无需付费;代码已做容错优化,新手直接复制粘贴即可运行,无需修改任何参数(除了替换自己的API密钥)。

发表评论

评论列表

  • 这篇文章还没有收到评论,赶紧来抢沙发吧~