Skip to content

旅游星推官|全城市通用AI行程规划项目方案

一、项目概述

产品名称:旅游星推官 产品能力:用户输入【出发城市+目的城市+游玩天数】,全国任意城市均可规划,AI自动结构化输出整套旅行方案 输出内容清单:

  1. 往返交通:飞机/高铁/大巴、参考票价、耗时、班次参考
  2. 逐日行程:上下午打卡景点、门票价格、开放时段
  3. 本地特色美食:店名、品类、人均消费
  4. 住宿推荐:经济型民宿、舒适型酒店(景点就近)
  5. 目的地天气、穿搭提醒、整体游玩总预算、避坑贴士 客户端:微信小程序 + H5(UniApp一套代码多端发布) 后端技术:Golang + Gin(首选方案,适配SSE流式逐token推送、高并发AI接口)

二、整体技术栈

1.后端 Golang

组件作用说明
Go1.23 + GinHTTP接口、SSE流式打字返回AI内容、路由管理
GORM (github.com/gorm.io/driver/postgres)PostgreSQL操作:用户数据、历史行程存储、城市基础配置
Redis热点目的地POI、天气、攻略缓存,减少第三方API调用,节省费用
langchaingoAI核心:大模型对接、Agent工具调用、RAG知识库检索
Chroma轻量级向量数据库(通过HTTP API交互),存放全国各城市旅游攻略,RAG补充真实数据
Docker项目容器打包,一键部署云服务器

2.前端 UniApp(Vue3 + uViewUI)

  1. 对话页面:输入出行需求,SSE长链接实时接收流式AI回复
  2. 行程卡片页:交通、景点、美食、住宿分模块排版展示
  3. 历史行程:云端存储历史规划记录,支持查看、重新编辑规划

3.存储分层

  1. PostgreSQL:业务结构化数据(用户、行程记录)
  2. Chroma向量库:全国旅游PDF/游记攻略向量化存储(RAG数据源)
  3. Redis:临时缓存热点数据,规避重复请求第三方接口

4.用户认证体系(微信小程序)

  1. 前端调用 wx.login() 获取临时 code,发送至后端
  2. 后端通过 code 换取微信 OpenID 和 SessionKey
  3. 签发 JWT Token 返回前端,后续请求 Bearer Token 鉴权
  4. 用户行程数据按 OpenID 隔离,确保数据安全与隐私

5.核心数据库表设计(PostgreSQL)

表名说明核心字段
users微信用户id (BIGSERIAL PK), openid (VARCHAR UNIQUE), nickname, avatar_url, created_at
trips行程记录id (BIGSERIAL PK), user_id (FK→users), from_city, to_city, days, raw_content (JSONB), created_at
city_config城市基础配置id (BIGSERIAL PK), city_name, province, hot_tags (JSONB), is_active

注:PostgreSQL 用 BIGSERIAL 代替 MySQL 的 AUTO_INCREMENT;JSONB 存储 AI 回复的完整结构化数据,方便后续解析展示。

6.API 限流与安全

  1. 单用户限流:同一用户每日最多发起 10 次行程规划,防刷防滥用
  2. 全局限流:Gin 中间件(ulule/limiterdidip/tollbooth),全站 QPS 上限控制
  3. 第三方 API 调用计数:Redis 原子计数器,实时监控高德/天气 API 调用量,接近免费额度自动告警
  4. 敏感词过滤:用户输入城市名做白名单校验,拒绝非中国城市或恶意输入

7.开发顺序建议:后端先行,前端跟进

核心原则:后端始终比前端快一个阶段,前端对接真实接口,不做 mock。

阶段后端前端说明
阶段1✅ AI + SSE 核心链路,curl 验证极简聊天框(能发请求、看流式文字即可)后端先跑通核心价值
阶段2✅ 高德 3 个 Tool + 自动化测试行程卡片 UI 开发(此时对接真实数据)后端稳定后前端再跟
阶段3✅ RAG + Chroma历史行程、登录等页面补全前端此时基本不动
阶段4-6完善部署联调 + 真机测试最后合拢

为什么后端先行?

  1. 核心价值在后端:AI 行程生成 + SSE 流式是项目灵魂,前端本质是「聊天框 + 卡片」,复杂度远低于后端。后端不通,前端再好看也没意义。
  2. SSE 必须后端先跑通:EventSource 的 Last-Event-IDretry、分块传输编码等行为 mock 不出来,前端用假数据开发后期必然返工。
  3. 第三方 API 是不确定性最大的部分:高德 POI 字段结构、DeepSeek function calling 与 langchaingo 适配程度,这些必须最先消除风险。
  4. AI 输出结构会迭代多版:契约守不住,约定 JSON 格式然后前后端并行的模式在 AI 项目里行不通。

反模式提醒:

做法为什么不好
前端先写完所有页面再调后端SSE 行为不对齐,后期大量返工
前后端完全并行、约定 JSON 格式AI 输出结构会迭代多版,契约守不住
前端 mock 大量假数据开发真数据到了之后布局必崩(文本长度、卡片数量不可预测)

三、第三方API明细&资费(交通/美食/民宿/天气)

3.1 高德地图(交通+景点+美食+民宿POI,主力数据源)

  1. 开户:个人实名认证免费开通,无开户费、无年费、不开通自动扣费
  2. 免费配额(个人开发者永久)
    • 城际路线规划:每日免费2000次
    • POI关键词检索(美食/酒店/景区):每日免费5000次
    • 地理编码:每日免费5000次
  3. 计费规则:免费额度用尽直接接口报错,不自动扣费;商用大批量使用按需充值:约0.015元/次

开发、内测、小流量运营完全够用,零成本。

3.2 美食、民宿酒店三种数据源方案

方案1【推荐·零成本】仅使用高德POI

通过关键词城市+民宿/特色美食/景区酒店查询,获取门店名称、地址、商圈、评分,满足行程推荐展示,不走其他付费接口。

方案2【小规模上线可选】美团开放平台

  • POI基础查询:每月免费100万次,超出0.15元/百次
  • 实时房价、预订接口:前期不接入预订功能,无需开通

方案3【后期商业化】携程开放平台

  • 仅展示酒店信息免费,产生订单成交后收取商家佣金,开发者无查询扣费;前期不做预订不用接入。

3.3 和风天气API

个人开发者每日免费3000次,查询目的地近3日天气,依据天气智能调整行程(雨天替换室内景点)。

3.4 大模型接口(DeepSeek/通义千问)

新用户赠送大量免费token,开发内测全免费;正式商用按量计费,成本极低。

四、省钱优化方案(降API开销)

  1. Redis缓存:同一目的地7天内重复请求优先读取缓存,不再调用高德API
  2. RAG本地知识库:全国攻略提前入库向量库,小众景点、本地美食优先读取本地数据,减少接口请求
  3. 分层使用数据源:内测全免费POI+RAG;日活500以内靠缓存维持免费;高流量后按需小额充值高德

五、六阶段落地开发计划

阶段1:基础对话交互(3天)

  1. UniApp聊天框对接Gin后端,接收用户出行参数
  2. 固定通用Prompt(全城市通用) 你是专业旅游星推官,根据用户给出的出发地、目的地、游玩天数生成规范旅行方案:
  3. 往返交通:高铁 / 飞机参考票价、行程时长;
  4. 每日行程:分上午下午推荐景点、标注门票、开放时间;
  5. 当日周边特色美食,附带人均消费;
  6. 就近推荐 2 家经济型民宿、2 家中端酒店;
  7. 汇总整体预估预算、出行注意事项; 无准确数据时标注【暂无精准信息】,禁止编造虚假景点与店铺。 plaintext
  8. 对接大模型,SSE流式输出内容,纯文本行程测试。

阶段2:接入高德+AI工具函数(5天)

基于langchaingo自定义3个AI工具,AI缺真实数据时自动调用高德接口:

  1. GetTraffic(startCity, targetCity):城际飞机/高铁查询
  2. GetScenicSpot(cityName):城市景点POI检索
  3. GetFoodAndHotel(city,area):周边美食、民宿POI查询
  4. 编写接口自动化测试,验证3个Tool函数返回数据结构正确
  5. AI输出质量人工抽检(30条测试用例,覆盖不同城市+天数组合)

阶段3:搭建全国RAG知识库(5天)

  1. 搜集全国各省市旅游攻略、游记、PDF文档
  2. Go脚本批量解析文档、文本向量化存入Chroma
  3. 用户发起行程规划,优先检索本地知识库,结合高德数据生成方案,降低大模型杜撰概率

阶段4:天气接入+前端优化(2天)

  1. 接入和风天气API,根据目的地天气动态调整行程安排
  2. 前端拆分行程卡片样式,历史规划落地存入PostgreSQL
  3. 登录鉴权联调:wx.login → JWT签发 → 接口鉴权中间件

阶段5:测试与质量保障(2天)

  1. 微信小程序真机测试(iOS/Android 各2款机型)
  2. 接口压力测试:wrk/vegeta 模拟 100 并发 SSE 连接,验证系统稳定性
  3. AI 输出质量复查:确认 RAG 检索相关度、幻觉率控制在可接受范围
  4. 边界场景测试:网络断开重连、Token 过期、空城市名、超长天数等异常输入

阶段6:容器打包上线(1.5天)

  1. Docker Compose 编排:Gin 后端 + PostgreSQL + Redis + Chroma,一键启动
  2. 配置 Nginx 反向代理 + SSL 证书(Let's Encrypt 免费)
  3. PostgreSQL 初始化脚本:自动建表 + 种子数据(热门城市列表)
  4. 部署阿里云 2核4G 轻量服务器(建议比1核2G高一级,PG/Chroma 较吃内存)
  5. 配置日志收集:Gin 访问日志 + 错误日志落盘,按天切割
  6. UniApp 打包提交微信小程序审核上线

六、测试策略(四层质量保障体系)

核心思路:AI 项目的输出不固定,不能简单断言"返回值等于某个字符串"。测试要分层——确定性逻辑用自动化,不确定性输出用结构校验 + 人工抽检。

第一层:单元测试(确定性部分)

传统单测方法,针对输入输出明确的函数。

1.1 Tool Function 返回结构校验

go
func TestGetScenicSpot(t *testing.T) {
    spots, err := GetScenicSpot("成都")  // 高德 POI 真实调用
    if err != nil {
        t.Fatalf("高德API调用失败: %v", err)
    }
    if len(spots) == 0 {
        t.Fatal("成都应该有景点返回,实际为0条")
    }
    for _, s := range spots {
        if s.Name == "" {
            t.Error("景点名称为空")
        }
        if s.Rating < 0 || s.Rating > 5 {
            t.Errorf("%s 评分异常: %.1f", s.Name, s.Rating)
        }
    }
}

测什么: 字段非空、数值在合理范围、热门城市返回条数 > 0。

1.2 JSON Schema 结构校验

AI 输出需符合预定义的 JSON Schema,用 gojsonschema 验证:

json
{
  "type": "object",
  "required": ["traffic", "daily_plan", "food", "hotel", "budget"],
  "properties": {
    "daily_plan": {
      "type": "array",
      "minItems": 1,
      "items": { "required": ["day", "morning", "afternoon"] }
    }
  }
}

AI 返回了合法 JSON 但缺了 trafficdaily_plan → 测试直接挂。

1.3 幻觉关键词检测

go
func TestNoHallucination(t *testing.T) {
    forbidden := []string{"虚构景区", "不存在的", "据我所知"}
    output := callAI("北京出发,三亚3天")
    for _, word := range forbidden {
        if strings.Contains(output, word) {
            t.Errorf("输出包含可疑内容: %s", word)
        }
    }
}

第二层:集成测试(AI + 工具协作链路)

这是项目最关键的一层测试。 模拟用户真实请求,验证整条链路。

2.1 SSE 流式连通性

检查点方法断言
Content-Typeresp.Header.Get("Content-Type")必须包含 text/event-stream
data 帧持续到达bufio.Scanner 逐行读取60s 内至少收到 1 个 data 帧
超时保护context.WithTimeout流断开后优雅结束,不 hang

2.2 AI 格式化输出检查点

不走 SSE,直接调 /api/plan 拿完整结果,分层检查:

检查项方法断言示例
交通覆盖关键字匹配必须出现「高铁」「飞机」「大巴」≥1 个
逐日行程正则第\d+天.*上午.*下午 天数匹配
数据诚实性字符串包含缺失真实数据时必须有【暂无精准信息】
美食推荐关键字匹配「美食」「餐厅」「人均」「小吃」≥1 个
住宿推荐关键字匹配「民宿」「酒店」「入住」≥1 个
预算汇总正则\d+元 或「预算」关键字
工具调用追踪埋点计数器GetTraffic / GetScenicSpot 调用次数 > 0

工具调用追踪是最重要的防线——工具没被调用 = AI 在自由发挥 = 大概率幻觉:

go
func TestToolCallTrace(t *testing.T) {
    trafficCalled := atomic.LoadInt32(&trafficCallCount)
    scenicCalled  := atomic.LoadInt32(&scenicCallCount)
    callAIWithTools("深圳出发,成都3天")
    if trafficCalled == 0 {
        t.Error("GetTraffic 没有被调用,AI可能在编造交通数据")
    }
    if scenicCalled == 0 {
        t.Error("GetScenicSpot 没有被调用")
    }
}

第三层:人工评测(体感质量)

自动化能测"有没有",测不了"好不好"。

3.1 评测样本集(30 条)

场景示例预期行为
常规热门深圳→成都 3天完整规划,数据丰富
小众目的地北京→婺源 2天数据偏少但不编造
同城游上海→上海 1天不走城际交通,纯市内
不合理输入地球→火星 10天拒绝或标注无数据
极长行程广州→新疆 15天每日都有内容
跨省多城杭州→西安+兰州 7天路线合理不绕路

3.2 打分卡(1-5 分)

维度权重标准
信息准确性40%景点/店名真实存在,票价合理
结构完整性30%交通/每日行程/美食/住宿/预算全部覆盖
实用性20%路线合理,不会上午城东下午城西
可读性10%排版清晰,无大段重复废话

通过标准:30 条平均分 ≥ 3.5,单项 ≤ 2 分标记为 badcase 回溯。


第四层:回归测试(持续保障)

4.1 Golden File 基线对比

把 30 条用例的第一版输出保存为 testdata/golden/,后续每次改 Prompt 或 Tool 逻辑,跑一遍对比:

变化类型处理方式
结构变了人工确认是否预期变更
数据源变了自动标记 diff
格式崩了直接报警,禁止合并

4.2 CI 流水线

git push → go test ./... → AI 集成测试 → Golden File 对比 → 通过/拒绝

集成测试或 Golden File 对比失败 = 不允许合并。


测试分工速查表

阶段测试动作工具/方法责任人
阶段1SSE 连通性 + JSON Schema 校验go test + curl后端
阶段2Tool 调用追踪 + 输出检查点 + 30 条人工评测go test + 打分表后端 + 全员抽检
阶段3RAG 召回率 + Golden File 基线建立Chroma 查询日志后端
阶段5全链路压测 + 真机回归wrk/vegeta + 真人走查全员

七、运维监控与告警

  1. 高德 API 调用量监控:Redis 计数器 + 每日定时写入 PostgreSQL,Grafana 面板可视化;接近免费额度(80%)自动告警
  2. 大模型 API 耗时监控:Gin 中间件记录每次 AI 请求耗时,P99 > 10s 触发告警
  3. 服务健康检查/health 端点检查 PG、Redis、Chroma 连通性,Docker healthcheck 自动重启异常容器
  4. 告警通道:企业微信机器人/邮件通知,告警内容包括:接口名、错误率、发生时间
  5. 日志方案:Gin 访问日志 + 业务错误日志落盘,按天切割保留 30 天;关键错误额外写入 Redis List 便于实时查询

八、后期迭代拓展功能

  1. 出行标签筛选:特种兵穷游/亲子游/轻奢度假,AI自动调整住宿、景点搭配
  2. 行程微调:用户指定修改某天景点,AI局部重新生成方案
  3. 扩充县域、古镇小众目的地库,覆盖全国小地点规划

九、配套学习&开源资源

  1. langchaingo开源地址:https://github.com/tmc/langchaingo
  2. 高德开放平台文档:https://lbs.amap.com/
  3. 和风天气开发文档:https://dev.qweather.com/
  4. 参考开源:Travel-Agent-Go(Go语言AI旅行规划项目)

十、项目全周期成本总结

  1. 开发&内测:API 侧 0 元(各平台免费额度);服务器可选本地 Docker 全模拟(¥0),或阿里云 2核4G 轻量约 ¥80/月
  2. 日活<500 小规模运营:API 依旧免费(Redis 缓存命中率高);服务器 + 域名 + SSL 约 ¥100/月
  3. 大批量商用:按需充值高德接口(约 ¥0.015/次),月度 API 成本可控在 ¥500 以内;服务器按需升配
  4. 总预估:从开发到上线运营前3个月,总现金支出可控制在 ¥300 以内

十一、关键风险与应对策略

风险项影响概率应对措施
大模型幻觉/杜撰虚假信息用户体验差、信任度下降Prompt 强制标注【暂无精准信息】;RAG 本地知识库优先检索真实数据;人工抽检 + 用户反馈机制
高德 POI 数据不准确(店铺已关闭、票价过时)行程推荐质量下降页面增加"信息有误?"反馈按钮;优先展示评分≥4.0 的 POI;定期更新热点城市缓存
微信小程序审核不通过无法上线AI 生成内容不属于 UGC,无需办证;但需添加内容审核 + 用户协议 + 免责声明;建议提前用体验版提交预审
SSE 长连接在实际网络环境下不稳定用户看到断流/卡顿前端实现断线重连(EventSource reconnect + Last-Event-ID);后端设置合理的超时时间(5min)
Chroma 单机性能瓶颈(攻略数据增长)RAG 检索变慢前期攻略数据量可控(<1万条);后期可平滑迁移到 Milvus / Qdrant
高德/和风 API 超额或被限流功能不可用Redis 计数器 + 80% 阈值告警;核心城市数据提前缓存在本地
云服务器被攻击或爬虫恶意调用费用暴增、服务中断API 限流中间件;Nginx IP 黑名单;微信小程序天然隔离部分爬虫

附:Go最简Demo(测试调用大模型生成行程)

go
package main

import (
	"context"
	"fmt"
	"github.com/tmc/langchaingo/llms/openai"
)

func main() {
	llm, err := openai.New(
		openai.WithBaseURL("你的大模型中转地址"),
		openai.WithToken("你的key"),
		openai.WithModel("deepseek-chat"),
	)
	if err != nil {
		panic(err)
	}

	prompt := `你是旅游星推官,深圳出发,云南游玩3天,输出完整行程:交通、每日景点、美食、住宿、预算`
	resp, err := llm.Call(context.Background(), prompt)
	if err != nil {
		panic(err)
	}
	fmt.Println(resp)
}

Released under the MIT License.