公司动态
基于大语言模型与API集成的智能旅行助手开发实践
这类工具最值得先看的不是功能列表而是能不能在普通环境里稳定跑起来以及它到底解决了什么具体问题。Gemini 接入 Viator 这个主题乍一看像是两个服务的集成但核心要解决的问题其实很明确如何通过一个统一的、智能化的对话界面来查询、筛选和预订全球的旅行活动而不是在多个网站和 App 之间来回切换、比价、看评论。它适合两类人看一类是经常需要规划行程、寻找特色体验的旅行者另一类是对 AI 应用集成、API 调用和自动化流程感兴趣的开发者。对于旅行者最关键的价值是省去了信息搜集和决策的繁琐过程对于开发者最值得关注的点是如何将大语言模型的自然语言理解能力与一个结构化的商业服务 API 进行可靠、安全的对接。下面我会按实际落地顺序拆一遍从理解集成原理、准备环境、模拟请求到处理真实预订流程中的边界情况。1. 先拆解“接入”到底意味着什么是界面整合还是 API 调用看到“Gemini 接入 Viator”很多人第一反应是有一个现成的、开箱即用的产品。但在实际动手前必须明确一个关键点目前并没有一个官方发布的、名为“Gemini for Viator”的独立应用。这里的“接入”更可能指的是一种技术实现模式或潜在的应用场景。1.1 两种主流的“接入”实现方式通常这类集成有两种实现路径前端界面整合开发一个 Web 或移动应用界面是类似 Gemini 的聊天对话框。用户用自然语言提问如“下周末在东京晚上有什么独特的文化体验预算每人1万日元左右”后端同时处理两项任务将用户问题发送给 Gemini 这类大语言模型的 API让其理解意图、提取关键筛选条件地点东京时间下周末晚上类型文化体验预算~1万日元。将这些结构化的条件转换为对 Viator API 的搜索请求获取活动列表。最后将 Viator API 返回的结构化数据活动名称、价格、评分、简介再用 Gemini API 组织成一段流畅、带总结和推荐的自然语言回复呈现给用户。自动化脚本/工作流对于开发者或高级用户可能是编写一个脚本Python 等。这个脚本同样接收自然语言指令通过代码调用 Gemini API 来解析指令再调用 Viator API 获取数据最终可能以格式化文本、邮件或日历事件的形式输出结果。现阶段对于大多数想体验的用户来说直接可用的成品较少更多需要基于双方提供的 API 自行搭建。因此本文后续将聚焦于第二种方式即从开发者的角度讲解如何利用 Gemini API 和 Viator API 构建一个简单的旅行活动查询工具。这是理解整个集成逻辑最直接的方法。1.2 你需要准备的核心资源在开始写代码之前你需要先申请好两个关键资源Gemini API 密钥这是调用 Google Gemini 模型能力的凭证。你需要前往 Google AI Studio (makersuite.google.com) 注册并创建 API Key。注意其可用区域和配额限制。Viator API 密钥这是访问 Viator 活动数据的凭证。你需要前往 Viator 的合作伙伴门户通常是partner.viator.com注册为开发者申请 API 访问权限。Viator API 通常是商业性质的可能需要联系其销售或合作伙伴团队并了解其费用结构、请求限制Rate Limits和使用条款。重要提示获取这两个密钥特别是 Viator 的可能需要一定时间并且可能涉及商业审核。对于初步学习和测试你可以先用 Gemini API 配合一个模拟的或本地的“活动数据”来验证核心逻辑。2. 环境搭建与最小可行性验证不要一上来就想做一个完整的预订系统。我建议先从最小可行性验证开始让程序能理解一句简单的旅行查询并返回一段固定的、模拟的 Viator 活动信息。2.1 基础 Python 环境配置假设我们使用 Python 作为开发语言。首先创建一个干净的虚拟环境并安装必要依赖。# 创建并激活虚拟环境以 venv 为例 python -m venv venv_gemini_viator # Windows: venv_gemini_viator\Scripts\activate # macOS/Linux: source venv_gemini_viator/bin/activate # 安装核心库 pip install google-generativeai requests python-dotenvgoogle-generativeai: Google 官方提供的 Gemini API Python SDK。requests: 用于后续发起 HTTP 请求调用 Viator API在模拟阶段也会用到。python-dotenv: 用于安全地管理环境变量和 API 密钥。2.2 安全存储你的 API 密钥永远不要将 API 密钥硬编码在代码中。创建一个.env文件来存储它们# .env 文件内容 GEMINI_API_KEY你的_Gemini_API_密钥 # VIATOR_API_KEY你的_Viator_API_密钥 暂时注释掉我们先模拟然后在代码中通过dotenv加载import os from dotenv import load_dotenv load_dotenv() # 加载 .env 文件中的环境变量 GEMINI_API_KEY os.getenv(GEMINI_API_KEY) # VIATOR_API_KEY os.getenv(VIATOR_API_KEY)2.3 第一步让 Gemini 理解用户意图我们先不连接 Viator只测试 Gemini 能否从用户的自然语言中准确提取出结构化的搜索参数。import google.generativeai as genai # 配置 Gemini API genai.configure(api_keyGEMINI_API_KEY) # 选择一个模型例如 gemini-1.5-pro model genai.GenerativeModel(gemini-1.5-pro) def parse_travel_query(user_query): 使用 Gemini 解析用户旅行查询提取结构化参数。 prompt f 你是一个旅行助手。请从用户的以下查询中提取出用于搜索旅行活动的关键参数。 请以 JSON 格式返回且只返回 JSON不要有其他解释。 需要的字段包括 - destination (城市或国家如 “Paris, France”) - start_date (YYYY-MM-DD 格式如果未指定则返回 null) - end_date (YYYY-MM-DD 格式如果未指定则返回 null) - category (活动类别如 “food”, “culture”, “adventure”, “sightseeing”) - budget_per_person (人均预算数字货币单位统一为 USD如果未指定则返回 null) - keywords (其他关键词列表如 [“night tour”, “small group”]) 用户查询{user_query} try: response model.generate_content(prompt) # 假设返回的是纯 JSON 文本 json_str response.text.strip() # 在实际应用中这里需要更健壮的 JSON 解析和错误处理 print(Gemini 解析出的参数, json_str) return json_str except Exception as e: print(f调用 Gemini API 出错{e}) return None # 测试一下 if __name__ __main__: test_query 我想下个月15号在罗马参加一个美食步行团最好是小团预算每人50欧左右。 result parse_travel_query(test_query)运行这段代码如果 Gemini API 配置正确你应该会看到它输出一段 JSON类似{destination: Rome, Italy, start_date: 2024-07-15, end_date: null, category: food, budget_per_person: 50, keywords: [walking tour, small group]}关键点这里我们通过精心设计的 Prompt提示词引导 Gemini 输出结构化的数据。Prompt 工程是这类应用的核心你需要不断调整它以适应更复杂、更模糊的用户输入。3. 模拟 Viator API 响应与集成测试拿到结构化的搜索参数后下一步本该是调用 Viator API。但在没有正式 API 密钥的测试阶段我们可以先模拟一个 Viator API 的响应。3.1 构建一个模拟的 Viator API 客户端我们创建一个函数接收上一步解析出的参数返回一个模拟的活动列表。import json from datetime import datetime def mock_viator_search(search_params): 模拟 Viator API 的搜索功能。 search_params: 从 parse_travel_query 返回的 JSON 字符串或字典。 if isinstance(search_params, str): params json.loads(search_params) else: params search_params destination params.get(destination, Unknown) category params.get(category, ) # 基于目的地和类别返回一些模拟活动 mock_activities [ { productCode: MOCK-001, title: fAuthentic {category.capitalize()} Experience in {destination.split(,)[0]}, description: fA wonderful small-group {category} tour exploring the hidden gems., price: {amount: 45.00, currency: USD}, rating: 4.8, reviewCount: 127, duration: 3 hours, bookingLink: fhttps://www.viator.com/mock-link-1 }, { productCode: MOCK-002, title: fPremium {category.capitalize()} Adventure in {destination.split(,)[0]}, description: fAn exclusive tour with an expert guide, limited to 10 people., price: {amount: 65.00, currency: USD}, rating: 4.9, reviewCount: 89, duration: 4.5 hours, bookingLink: fhttps://www.viator.com/mock-link-2 }, ] # 简单模拟一下预算过滤 budget params.get(budget_per_person) if budget: mock_activities [act for act in mock_activities if act[price][amount] budget] return mock_activities # 测试集成 if __name__ __main__: # 假设这是 Gemini 解析的结果 parsed_params {destination: Rome, Italy, start_date: 2024-07-15, category: food, budget_per_person: 50} activities mock_viator_search(parsed_params) print(模拟搜索到的活动, json.dumps(activities, indent2, ensure_asciiFalse))3.2 让 Gemini 生成人性化的回复现在我们有结构化的活动数据了但直接把这个 JSON 扔给用户很不友好。最后一步再次调用 Gemini让它根据活动数据生成一段推荐文字。def generate_recommendation(user_query, activities_list): 使用 Gemini 将活动列表转化为自然语言推荐。 activities_str json.dumps(activities_list, ensure_asciiFalse) prompt f 你是一个专业的旅行顾问。一位用户提出了以下需求 “{user_query}” 你已根据需求找到了以下活动选项 {activities_str} 请根据这些信息为用户生成一段友好、有帮助的回复。回复需要 1. 总结用户的查询条件。 2. 简要介绍你找到的每个活动突出亮点如高评分、符合预算、特色描述。 3. 给出一个初步的推荐建议。 4. 最后提醒用户可以通过提供的链接查看详情和预订。 请使用中文回复。 try: response model.generate_content(prompt) return response.text except Exception as e: print(f生成推荐时出错{e}) return 抱歉暂时无法生成推荐。 # 完整的流程测试 if __name__ __main__: user_input 我想下个月15号在罗马参加一个美食步行团最好是小团预算每人50欧左右。 print(f用户查询{user_input}) # 1. 解析查询 params parse_travel_query(user_input) if not params: print(无法解析查询。) exit() # 2. 搜索活动模拟 activities mock_viator_search(params) if not activities: final_response f根据您的条件{json.loads(params)}暂时没有找到合适的活动。建议您调整搜索条件例如放宽预算或选择其他日期。 else: # 3. 生成推荐 final_response generate_recommendation(user_input, activities) print(\n *50) print(旅行助手回复) print(*50) print(final_response)运行这个完整的流程你会看到一个端到端的演示用户输入自然语言 - Gemini 解析 -模拟搜索活动 - Gemini 生成推荐回复。这验证了集成的核心逻辑是可行的。4. 连接真实的 Viator API 与生产化考量模拟测试通过后下一步就是替换掉mock_viator_search函数接入真实的 Viator API。4.1 了解 Viator API 的基本使用Viator API 是 RESTful 风格的。你需要查阅其官方文档找到“产品搜索”相关的端点Endpoint。一个典型的搜索请求可能如下import requests def real_viator_search(search_params, viator_api_key, api_base_urlhttps://api.viator.com/partner): 调用真实的 Viator API 进行搜索。 注意此函数为示例实际参数和端点需以 Viator 官方文档为准。 headers { Accept: application/json, Accept-Language: en-US, Authorization: fBearer {viator_api_key} # 或可能是其他认证方式 } # 将我们解析的参数映射到 Viator API 所需的参数 query_params { destId: convert_destination_to_dest_id(search_params[destination]), # 需要目的地ID映射 startDate: search_params.get(start_date), endDate: search_params.get(end_date), categories: map_category_to_viator_code(search_params.get(category)), # 需要类别映射 sortOrder: REVIEW_AVG_RATING_D, topX: 10, currency: USD } # 移除空值参数 query_params {k: v for k, v in query_params.items() if v is not None} try: response requests.get(f{api_base_url}/products/search, headersheaders, paramsquery_params, timeout10) response.raise_for_status() # 检查 HTTP 错误 data response.json() # 从返回的 data 中提取活动列表并格式化成我们需要的结构 return format_viator_activities(data.get(products, [])) except requests.exceptions.RequestException as e: print(f调用 Viator API 失败{e}) return []这里有几个关键挑战参数映射Viator API 通常使用内部的目的地 ID (destId) 和分类代码而不是城市名称字符串。你需要维护一个映射表或者调用其“目的地自动补全”等辅助 API 来动态获取 ID。认证Viator API 的认证方式如 OAuth, API Key需严格按文档实现。错误处理网络超时、API 限流、无效参数等都需要妥善处理避免程序崩溃。数据格式化Viator API 返回的数据结构可能很复杂需要编写format_viator_activities函数来提取我们关心的字段标题、价格、评分、链接等。4.2 生产环境必须考虑的要点如果计划将这个工具用于实际服务以下问题不能忽略成本控制Gemini API 和 Viator API 都可能按调用次数收费。你需要实现缓存机制例如对相同的搜索条件在一定时间内缓存结果并设置用量监控和告警。用户体验与安全超时处理设置合理的 API 调用超时如 Gemini 5秒Viator 8秒并准备超时后的降级回复如“正在努力查询请稍后再试”或返回缓存结果。输入清洗与安全对用户的输入进行基本的清洗防止 Prompt 注入攻击。避免将未经处理的用户输入直接拼接进发送给 Gemini 的 Prompt。免责声明在回复中明确告知用户信息来源于 Viator并由 AI 进行整理建议用户预订前在 Viator 官网核实最新详情、价格和可用性。合规与条款仔细阅读 Gemini API 和 Viator API 的使用条款。确保你的使用场景特别是涉及商业用途、数据展示和转发符合其规定。绝对不要尝试绕过任何 API 的调用限制或进行未经授权的抓取。5. 常见问题排查与调试思路在实际开发中你肯定会遇到各种问题。下面是一个典型的排查顺序5.1 Gemini API 调用失败现象google.generativeai库抛出认证错误或权限错误。排查检查 API 密钥确认GEMINI_API_KEY环境变量已正确加载且密钥未过期、未禁用。可以在命令行用echo $GEMINI_API_KEY(Linux/macOS) 或echo %GEMINI_API_KEY%(Windows) 快速验证。检查网络连接确保你的运行环境可以访问generativelanguage.googleapis.com。临时关闭代理或防火墙试试。检查配额前往 Google AI Studio 控制台查看 API 调用次数配额是否已用尽。简化测试写一个最简单的脚本只调用model.generate_content(“Hello”)排除其他代码干扰。5.2 Gemini 解析结果不符合预期现象返回的不是纯 JSON或者提取的参数错误。排查优化 Prompt这是最常见的原因。在 Prompt 中更明确地指定输出格式如“输出必须是合法的 JSON且只包含以下字段……”。可以要求 Gemini 在思考时先输出一个“思考过程”但最终只返回 JSON。使用结构化输出如果 Gemini 版本支持如gemini-1.5-pro的response.candidates[0].content.parts[0]可能包含结构化数据优先使用该功能。后处理清洗对返回的文本进行后处理例如用json.loads()尝试解析如果失败则尝试用正则表达式提取{...}之间的内容。调整温度参数在调用generate_content时设置generation_configgenai.GenerationConfig(temperature0.1)降低随机性使输出更稳定。5.3 Viator API 返回空结果或错误现象real_viator_search返回空列表或 HTTP 错误码。排查验证认证先用一个最简单的请求如获取目的地列表测试 API 密钥和认证头是否正确。打印请求详情在开发阶段将构建好的最终请求 URL 和 Headers 打印出来用curl或 Postman 手动测试确认参数无误。检查参数映射重点检查destId和分类代码。确认你的映射函数convert_destination_to_dest_id能正确工作。Viator 可能提供“目的地搜索”API 来动态查询 ID。查看 API 响应即使返回 HTTP 200也要仔细查看响应体。可能包含“error”: “NO_PRODUCTS_AVAILABLE”之类的业务逻辑错误信息。遵守限流查看 Viator API 文档的 Rate Limiting 部分确保你的调用频率没有超标。5.4 整体流程响应慢现象从用户输入到最终回复耗时超过 10 秒。优化并行调用如果流程允许在解析出用户参数后可以并行发起对 Gemini用于生成推荐和 Viator API用于获取数据的调用而不是串行。实现缓存对“查询参数 - Viator 搜索结果”建立缓存如使用 Redis 或内存缓存缓存 5-10 分钟。对于热门目的地和常见查询能极大提升响应速度并降低成本。超时设置为两个 API 调用设置独立的、合理的超时时间。如果 Viator API 超时可以尝试使用缓存的结果或者直接返回一个友好的提示而不是让用户长时间等待。6. 扩展思路与边界探讨这个基础框架可以朝多个方向扩展但每个方向都有其边界和挑战。6.1 从“查询”到“预订”真正的“预订”涉及复杂的流程远非一个 API 调用那么简单可用性检查需要调用 Viator API 检查特定日期、人数的库存。价格明细获取含税、含费的总价。用户数据收集需要安全地收集参与者姓名、联系方式等敏感信息。绝对不要用 Gemini 等 AI 模型来传输或暂存用户的个人身份信息或支付信息。支付集成这需要接入支付网关并处理 PCI DSS 合规等复杂问题。订单确认与凭证处理订单确认、发送电子票等。因此一个完整的预订机器人或助手其技术复杂度和合规要求非常高。对于个人开发者或小团队更现实的路径是止步于“智能推荐与引流”即生成推荐并提供直达 Viator 官方预订页面的链接将后续复杂的预订流程交给 Viator 自身的平台完成。6.2 支持更复杂的查询用户的查询可能非常模糊例如“我暑假带小孩去伦敦有什么好玩的”。多轮对话需要维护对话上下文。你可以将历史对话记录也作为 Prompt 的一部分发送给 Gemini让它理解“暑假”可能指七八月“小孩”意味着需要筛选家庭友好型活动。意图消歧用户可能在同一句话里混合多个意图“找个地方吃饭然后看夜景”。需要更复杂的 Prompt 或甚至使用 Agent 架构让 AI 主动提问澄清“您是想找一个既能用餐又能观景的场所还是分别推荐餐厅和观景台”。6.3 与其他服务集成除了 Viator还可以考虑集成其他旅行服务 API如 Booking.com住宿、Skyscanner航班、Google Maps路线。这会让助手更强大但也带来新问题多 API 协调如何并行或按顺序调用多个 API并合并结果统一回复如何将来自不同源的数据航班时间、酒店价格、活动评分整合成一段连贯的推荐成本与复杂度激增每个 API 都有其学习成本、认证流程、调用限制和费用模型。我个人更建议先把单服务Viator的查询和推荐做稳定、做流畅。在核心流程解析 - 搜索 - 生成回复能稳定运行且响应迅速的基础上再考虑增加一个其他数据源。贪多求全往往会导致每个环节都不稳定。最后这类项目真正落地时最该盯住的不是功能列表有多长而是输入解析的准确性、API 调用的稳定性、异常情况的处理能力以及清晰的用户预期管理。告诉用户 AI 能做什么快速筛选和总结信息不能做什么直接完成支付和出具票据才能构建一个真正有用且可靠的数字助手。