使用说明
TripWeaver
现场演示
- 前端(React):https://tripweaver-ai.vercel.app/
- 后端(FastAPI):https://tripweaver.onrender.com
- Swagger用户界面:
https://tripweaver.onrender.com/docs - 健康:
https://tripweaver.onrender.com/health
- Swagger用户界面:
MCP编排的多上下文 出行计划:
自然语言→ 启发式解析器→ LLM解析器优化 → POI检索(离线/谷歌)→ 贪婪得分→ 维基百科丰富→ LLM解释层 → React前端。
后端(FastAPI)目前支持:
- 自然语言查询解析
- 基于规则的启发式解析器
- LLM精炼结构化解析(OpenAI)
- 两个POI数据源
- 离线CSV数据集 (
data/global_poi_dataset.csv) - Live Google Places API网站
- 离线CSV数据集 (
- 评分+贪婪POI选择
- 维基百科描述丰富
- 日常起搏控制 (宽松/标准/包装+定制
max_places_per_day) - LLM行程说明 (日复一日的推理、替代方案、旅行提示)
- JSON行程输出与React前端兼容
1.安装
1.1克隆存储库
git clone https://github.com/Hans-Yin/TripWeaver.git
cd TripWeaver
1.2放置离线POI数据集
您的离线数据集必须放置在:
TripWeaver/data/global_poi_dataset.csv
必填(或可自动规范化)列:
city_name,place_name,country,place_categoryprice,open_time,close_time,popularity_scorelat,lon
列别名,如 price_usd, poi_category, latitude, longitude 自动映射。
1.3安装依赖项
推荐一个虚拟环境:
pip install -r requirements.txt
1.4环境变量
Google Places API密钥(可选)
对于实时POI检索:
export GOOGLE_PLACES_API_KEY="YOUR_GOOGLE_PLACES_API_KEY"
OpenAI API密钥(LLM解析器+LLM解释层需要)
export OPENAI_API_KEY="YOUR_OPENAI_API_KEY"
没有这些键,离线模式仍然可以工作(没有LLM功能/实时谷歌位置)。
2.运行后端服务器
从项目根:
uvicorn backend.app.main:app --reload
本地API终结点:
CORS被启用以支持React前端(本地开发和Vercel)。
已部署后端:
- 基本URL:
https://tripweaver.onrender.com - Swagger用户界面:
https://tripweaver.onrender.com/docs - 健康:
https://tripweaver.onrender.com/health
3.请求架构(POST /plan)
请求示例:
{
"query": "3 days in New York, love museums and parks, low budget, avoid crowds",
"days": 3,
"city": null,
"data_source": "offline",
"max_places_per_day": 4,
"pace": "standard"
}
字段摘要
| 字段 | 类型 | 描述 |
|---|---|---|
query |
string | 免费自然语言旅行查询(城市、天数、偏好、预算、人群) |
days |
int(可选) | 显式天数;覆盖解析器/LLM(如果提供) |
city |
string | null |
data_source |
"offline" |
"google" |
max_places_per_day |
int(可选) | 每天戴硬帽(例如,放松时戴3个,打包时戴6个) |
pace |
string(可选) | "relaxed", "standard",或 "packed" (用于UX+LLM解释) |
后端工作流程
-
启发式解析器 提取物
city,days,categories从query -
LLM解析器优化 将查询转换为结构化JSON (
city,total_days,categories,budget,crowd_preference) -
合并显式
days从请求(如果存在)解析total_days -
检索POI
- 自 离线CSV,或
- 自 Google Places API
-
贪婪得分 (人气+品类匹配)
-
应用
max_places_per_day在跨天分发POI时 -
维基百科丰富 POI描述
-
LLM解释层 生成:
- 行程概述
- 日复一日的叙述和节奏
- 备选建议
- 旅行提示(预算、人群、时间)
-
返回JSON用于前端渲染
4.示例响应
4.1离线数据集模式
{
"city": "New York",
"days": [
{
"day": 1,
"places": [
{
"name": "Central Park",
"category": "park",
"description": "Central Park is an urban park..."
},
{
"name": "The Metropolitan Museum of Art",
"category": "museum",
"description": "The Metropolitan Museum of Art..."
}
]
},
{
"day": 2,
"places": [
{
"name": "Brooklyn Bridge",
"category": "landmark",
"description": "The Brooklyn Bridge is..."
}
]
}
],
"explanation": "This itinerary balances museums and parks while keeping each day at a manageable pace..."
}
4.2实时谷歌位置模式
{
"city": "New York",
"days": [
{
"day": 1,
"places": [
{
"name": "Central Park",
"category": "park",
"description": "..."
},
{
"name": "The Metropolitan Museum of Art",
"category": "museum",
"description": "..."
}
]
},
{
"day": 2,
"places": [
{
"name": "Brooklyn Museum",
"category": "museum",
"description": "..."
},
{
"name": "American Museum of Natural History",
"category": "museum",
"description": "..."
}
]
}
],
"explanation": "This two-day New York itinerary highlights major museums while keeping walking distances reasonable..."
}
确切的POI可能因Google Places API的响应而有所不同。
5.反应前端
React前端(Vite)提供了一个简单的UI:
-
输入自然语言旅行查询
-
选择 数据源:离线/谷歌
-
选择 每日速度:
- 🧘 放松的 (约3个景点/天)
- 🚶 标准 (约4个景点/天)
- ⚡ 拥挤的 (约6个景点/天)
-
可选覆盖 最大斑点/天 通过数字输入
-
切换 显示LLM解释
-
将生成的行程可视化为每日时间表
已部署前端:
前端发送 POST /plan 请求到FastAPI后端(本地或部署的渲染端点)。
如果你想 在本地FastAPI后端上运行前端,您需要更新API端点。
编辑 src/api.ts
// src/api.ts
import axios from "axios";
// Use this for deployed backend (default)
const API_BASE = "https://tripweaver.onrender.com";
// Use this for local backend (uncomment when running FastAPI locally)
// const API_BASE = "http://127.0.0.1:8000";
何时更改此设置
| 场景 | API_BASE |
|---|---|
| 使用已部署的后端(渲染) | https://tripweaver.onrender.com |
| 在本地运行FastAPI | http://127.0.0.1:8000 |
更改端点后,重新启动前端开发服务器:
npm run dev
这允许相同的前端代码库与 本地后端或部署的后端.
6.贡献者
- 尹伯涵
- 陈文政
- 徐逸飞