travel-agent-cli 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -21
- package/bin/cli.js +14 -11
- package/package.json +8 -4
- package/python/agents/__init__.py +19 -0
- package/python/agents/analysis_agent.py +234 -0
- package/python/agents/base.py +377 -0
- package/python/agents/collector_agent.py +304 -0
- package/python/agents/manager_agent.py +251 -0
- package/python/agents/planning_agent.py +161 -0
- package/python/agents/product_agent.py +672 -0
- package/python/agents/report_agent.py +172 -0
- package/python/analyzers/__init__.py +10 -0
- package/python/analyzers/hot_score.py +123 -0
- package/python/analyzers/ranker.py +225 -0
- package/python/analyzers/route_planner.py +86 -0
- package/python/cli/commands.py +254 -0
- package/python/collectors/__init__.py +14 -0
- package/python/collectors/ota/ctrip.py +120 -0
- package/python/collectors/ota/fliggy.py +152 -0
- package/python/collectors/weibo.py +235 -0
- package/python/collectors/wenlv.py +155 -0
- package/python/collectors/xiaohongshu.py +170 -0
- package/python/config/__init__.py +30 -0
- package/python/config/models.py +119 -0
- package/python/config/prompts.py +105 -0
- package/python/config/settings.py +172 -0
- package/python/export/__init__.py +6 -0
- package/python/export/report.py +192 -0
- package/python/main.py +632 -0
- package/python/pyproject.toml +51 -0
- package/python/scheduler/tasks.py +77 -0
- package/python/tools/fliggy_mcp.py +553 -0
- package/python/tools/flyai_tools.py +251 -0
- package/python/tools/mcp_tools.py +412 -0
- package/python/utils/__init__.py +9 -0
- package/python/utils/http.py +73 -0
- package/python/utils/storage.py +288 -0
package/README.md
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
# travel-agent-cli
|
|
2
2
|
|
|
3
|
-
AI 驱动的旅行目的地推荐 Agent -
|
|
3
|
+
AI 驱动的旅行目的地推荐 Agent - 命令行工具(集成 FlyAI 旅行搜索)
|
|
4
|
+
|
|
5
|
+
## 新功能 v0.2.0
|
|
6
|
+
|
|
7
|
+
- 🆕 **FlyAI 旅行搜索**:集成 Fliggy MCP,支持航班、酒店、景点实时查询
|
|
8
|
+
- 🔧 修复多 Agent 初始化问题
|
|
9
|
+
- 📝 优化 CLI 输出格式
|
|
4
10
|
|
|
5
11
|
## 安装
|
|
6
12
|
|
|
@@ -9,7 +15,7 @@ AI 驱动的旅行目的地推荐 Agent - 命令行工具
|
|
|
9
15
|
npm install -g travel-agent-cli
|
|
10
16
|
|
|
11
17
|
# 或者使用 npx 直接运行(无需安装)
|
|
12
|
-
npx travel-agent-cli
|
|
18
|
+
npx travel-agent-cli flyai "5 天日本行程"
|
|
13
19
|
```
|
|
14
20
|
|
|
15
21
|
### 安装要求
|
|
@@ -67,6 +73,23 @@ travel-agent analyze "北欧极光"
|
|
|
67
73
|
|
|
68
74
|
## 命令说明
|
|
69
75
|
|
|
76
|
+
### flyai - FlyAI 旅行搜索(新)
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
travel-agent flyai <查询> [选项]
|
|
80
|
+
|
|
81
|
+
选项:
|
|
82
|
+
--destination 目的地城市
|
|
83
|
+
--duration 行程天数/日期
|
|
84
|
+
--budget 预算范围
|
|
85
|
+
|
|
86
|
+
示例:
|
|
87
|
+
travel-agent flyai "5 天日本行程规划"
|
|
88
|
+
travel-agent flyai "北京到上海航班" --destination 上海
|
|
89
|
+
travel-agent flyai "三亚海景酒店" --destination 三亚
|
|
90
|
+
travel-agent flyai "东京景点推荐" --destination 东京
|
|
91
|
+
```
|
|
92
|
+
|
|
70
93
|
### run - 运行完整工作流
|
|
71
94
|
|
|
72
95
|
```bash
|
|
@@ -77,8 +100,6 @@ travel-agent run [选项]
|
|
|
77
100
|
-n, --top 推荐目的地数量 (默认:10)
|
|
78
101
|
-p, --plan-top 规划路线的目的地数量 (默认:3)
|
|
79
102
|
--no-ota 不采集 OTA 数据
|
|
80
|
-
-S, --schedule 启用定时任务
|
|
81
|
-
-c, --cron Cron 表达式
|
|
82
103
|
```
|
|
83
104
|
|
|
84
105
|
### analyze - 旅行产品可行性分析
|
|
@@ -102,18 +123,21 @@ travel-agent model <子命令> [选项]
|
|
|
102
123
|
use 切换模型
|
|
103
124
|
|
|
104
125
|
选项:
|
|
105
|
-
-p, --provider LLM 提供商 (anthropic/openai/deepseek/azure/ollama)
|
|
126
|
+
-p, --provider LLM 提供商 (anthropic/openai/deepseek/azure/ollama/qwen)
|
|
106
127
|
-m, --model 模型名称
|
|
107
128
|
```
|
|
108
129
|
|
|
109
|
-
###
|
|
130
|
+
### agents - 查看 Agent 团队信息
|
|
110
131
|
|
|
111
132
|
```bash
|
|
112
|
-
travel-agent
|
|
133
|
+
travel-agent agents
|
|
113
134
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
135
|
+
输出:
|
|
136
|
+
- Manager (协调者)
|
|
137
|
+
- Collector (采集 Agent)
|
|
138
|
+
- Analyst (分析 Agent)
|
|
139
|
+
- Planner (规划 Agent)
|
|
140
|
+
- Reporter (报告 Agent)
|
|
117
141
|
```
|
|
118
142
|
|
|
119
143
|
### config - 配置管理
|
|
@@ -126,37 +150,68 @@ travel-agent config [选项]
|
|
|
126
150
|
--init 初始化配置文件
|
|
127
151
|
```
|
|
128
152
|
|
|
153
|
+
### status - 系统状态
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
travel-agent status
|
|
157
|
+
|
|
158
|
+
输出:
|
|
159
|
+
- 版本号
|
|
160
|
+
- 当前 LLM 提供商和模型
|
|
161
|
+
- API 配置状态
|
|
162
|
+
```
|
|
163
|
+
|
|
129
164
|
## 支持的 LLM 提供商
|
|
130
165
|
|
|
131
166
|
| 提供商 | 默认模型 | 配置项 |
|
|
132
167
|
|--------|---------|--------|
|
|
133
|
-
| Anthropic | claude-sonnet-4-
|
|
168
|
+
| Anthropic | claude-sonnet-4-5-20250929 | ANTHROPIC_API_KEY |
|
|
134
169
|
| OpenAI | gpt-4o | OPENAI_API_KEY |
|
|
135
170
|
| DeepSeek | deepseek-chat | DEEPSEEK_API_KEY |
|
|
136
171
|
| Azure OpenAI | gpt-4 | AZURE_OPENAI_API_KEY, AZURE_OPENAI_ENDPOINT |
|
|
137
172
|
| Ollama | llama3 | OLLAMA_BASE_URL (本地部署) |
|
|
173
|
+
| Qwen (通义千问) | qwen-max | DASHSCOPE_API_KEY |
|
|
138
174
|
|
|
139
|
-
##
|
|
175
|
+
## FlyAI 旅行搜索(Fliggy MCP 集成)
|
|
140
176
|
|
|
141
|
-
|
|
177
|
+
FlyAI 旅行搜索已集成 **Fliggy MCP**(飞猪开放平台)服务:
|
|
142
178
|
|
|
143
|
-
|
|
144
|
-
|
|
179
|
+
- **沙箱模式**:默认使用,返回模拟数据,无需配置
|
|
180
|
+
- **生产模式**:需配置飞猪开放平台 App Key 和 App Secret
|
|
181
|
+
|
|
182
|
+
配置方式(可选):
|
|
183
|
+
```ini
|
|
184
|
+
# 在 .env 文件中添加
|
|
185
|
+
FLIGGY_APP_KEY=your_app_key
|
|
186
|
+
FLIGGY_APP_SECRET=your_app_secret
|
|
145
187
|
```
|
|
146
188
|
|
|
147
|
-
|
|
189
|
+
## 示例
|
|
148
190
|
|
|
191
|
+
### FlyAI 旅行搜索
|
|
149
192
|
```bash
|
|
150
|
-
|
|
151
|
-
|
|
193
|
+
# 综合旅行规划
|
|
194
|
+
travel-agent flyai "5 天日本行程规划"
|
|
195
|
+
|
|
196
|
+
# 航班搜索
|
|
197
|
+
travel-agent flyai "北京到上海航班" --destination 上海
|
|
152
198
|
|
|
153
|
-
|
|
199
|
+
# 酒店搜索
|
|
200
|
+
travel-agent flyai "三亚海景酒店" --destination 三亚
|
|
154
201
|
|
|
202
|
+
# 景点搜索
|
|
203
|
+
travel-agent flyai "东京景点推荐" --destination 东京
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### 搜索海岛游推荐
|
|
155
207
|
```bash
|
|
156
|
-
travel-agent run -
|
|
208
|
+
travel-agent run -k "海岛游" -n 10
|
|
157
209
|
```
|
|
158
210
|
|
|
159
|
-
###
|
|
211
|
+
### 分析极光旅行产品
|
|
212
|
+
```bash
|
|
213
|
+
travel-agent analyze "北欧极光"
|
|
214
|
+
```
|
|
160
215
|
|
|
161
216
|
```bash
|
|
162
217
|
travel-agent analyze "日本赏樱" -o ./analysis_report.md
|
package/bin/cli.js
CHANGED
|
@@ -11,8 +11,8 @@ const fs = require('fs');
|
|
|
11
11
|
|
|
12
12
|
// 获取包的安装路径
|
|
13
13
|
const packagePath = path.join(__dirname, '..');
|
|
14
|
-
const
|
|
15
|
-
const mainPy = path.join(
|
|
14
|
+
const pythonDir = path.join(packagePath, 'python');
|
|
15
|
+
const mainPy = path.join(pythonDir, 'main.py');
|
|
16
16
|
|
|
17
17
|
// 检查 Python 是否可用
|
|
18
18
|
function findPython() {
|
|
@@ -34,9 +34,9 @@ function findPython() {
|
|
|
34
34
|
// 检查虚拟环境是否存在
|
|
35
35
|
function getVenvPython() {
|
|
36
36
|
const venvPaths = [
|
|
37
|
-
path.join(
|
|
38
|
-
path.join(
|
|
39
|
-
path.join(
|
|
37
|
+
path.join(pythonDir, 'venv', 'bin', 'python'),
|
|
38
|
+
path.join(pythonDir, '.venv', 'bin', 'python'),
|
|
39
|
+
path.join(pythonDir, 'venv', 'Scripts', 'python.exe'),
|
|
40
40
|
];
|
|
41
41
|
|
|
42
42
|
for (const venvPath of venvPaths) {
|
|
@@ -64,15 +64,18 @@ function run() {
|
|
|
64
64
|
travel-agent <command> [options]
|
|
65
65
|
|
|
66
66
|
可用命令:
|
|
67
|
-
run
|
|
68
|
-
analyze
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
model 管理 LLM
|
|
67
|
+
run 运行完整工作流(数据采集 → 分析评分 → 路线规划 → 报告生成)
|
|
68
|
+
analyze 分析旅行产品可行性(市场调研 → 资源评估 → 生成报告)
|
|
69
|
+
agents 查看 Agent 团队信息
|
|
70
|
+
status 显示系统状态(版本、模型、API 配置)
|
|
71
|
+
model 管理 LLM 模型配置(list/status/use)
|
|
72
|
+
config 管理配置(--show/--init)
|
|
73
|
+
help 显示帮助信息
|
|
72
74
|
|
|
73
75
|
示例:
|
|
74
76
|
travel-agent run -k "海岛游" # 搜索海岛游推荐
|
|
75
77
|
travel-agent analyze "北欧极光" # 分析极光旅行产品
|
|
78
|
+
travel-agent agents # 查看 Agent 团队
|
|
76
79
|
travel-agent model list # 查看支持的模型
|
|
77
80
|
travel-agent --help # 显示帮助
|
|
78
81
|
|
|
@@ -115,7 +118,7 @@ function run() {
|
|
|
115
118
|
const pyArgs = [mainPy, ...args];
|
|
116
119
|
const child = spawn(pythonCmd, pyArgs, {
|
|
117
120
|
stdio: 'inherit',
|
|
118
|
-
cwd:
|
|
121
|
+
cwd: pythonDir
|
|
119
122
|
});
|
|
120
123
|
|
|
121
124
|
child.on('error', (err) => {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "travel-agent-cli",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "AI 驱动的旅行目的地推荐 Agent -
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "AI 驱动的旅行目的地推荐 Agent - 命令行工具(集成 FlyAI 旅行搜索)",
|
|
5
5
|
"bin": {
|
|
6
6
|
"travel-agent": "bin/cli.js",
|
|
7
7
|
"travel-agent-cli": "bin/cli.js"
|
|
@@ -18,13 +18,17 @@
|
|
|
18
18
|
"llm",
|
|
19
19
|
"cli",
|
|
20
20
|
"旅行",
|
|
21
|
-
"推荐"
|
|
21
|
+
"推荐",
|
|
22
|
+
"flyai",
|
|
23
|
+
"fliggy",
|
|
24
|
+
"机票",
|
|
25
|
+
"酒店"
|
|
22
26
|
],
|
|
23
27
|
"author": "Your Name <your.email@example.com>",
|
|
24
28
|
"license": "MIT",
|
|
25
29
|
"repository": {
|
|
26
30
|
"type": "git",
|
|
27
|
-
"url": "https://github.com/your-username/travel-agent.git",
|
|
31
|
+
"url": "git+https://github.com/your-username/travel-agent.git",
|
|
28
32
|
"directory": "npm-package"
|
|
29
33
|
},
|
|
30
34
|
"engines": {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Agents 模块 - 多 Agent 系统
|
|
2
|
+
|
|
3
|
+
导出所有 Agent 类
|
|
4
|
+
"""
|
|
5
|
+
from agents.base import BaseAgent
|
|
6
|
+
from agents.collector_agent import CollectionAgent
|
|
7
|
+
from agents.analysis_agent import AnalysisAgent
|
|
8
|
+
from agents.planning_agent import PlanningAgent
|
|
9
|
+
from agents.report_agent import ReportAgent
|
|
10
|
+
from agents.manager_agent import ManagerAgent
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"BaseAgent",
|
|
14
|
+
"CollectionAgent",
|
|
15
|
+
"AnalysisAgent",
|
|
16
|
+
"PlanningAgent",
|
|
17
|
+
"ReportAgent",
|
|
18
|
+
"ManagerAgent",
|
|
19
|
+
]
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"""分析 Agent - 负责数据分析和目的地排序"""
|
|
2
|
+
from typing import Dict, Any, List, Optional
|
|
3
|
+
import json
|
|
4
|
+
from agents.base import BaseAgent
|
|
5
|
+
from analyzers.hot_score import HotScoreCalculator
|
|
6
|
+
from config.models import SocialPost, WenlvInfo
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AnalysisAgent(BaseAgent):
|
|
10
|
+
"""分析 Agent
|
|
11
|
+
|
|
12
|
+
职责:
|
|
13
|
+
- 计算目的地热度评分
|
|
14
|
+
- 综合分析并排序
|
|
15
|
+
- 生成推荐理由
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
name = "analysis_agent"
|
|
19
|
+
role = "旅行数据分析师"
|
|
20
|
+
goal = "分析采集的数据,识别热门目的地,给出专业评分和推荐理由"
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
provider: Optional[str] = None,
|
|
25
|
+
model: Optional[str] = None,
|
|
26
|
+
use_tools: bool = False,
|
|
27
|
+
):
|
|
28
|
+
super().__init__(provider, model, use_tools)
|
|
29
|
+
self.score_calculator = HotScoreCalculator()
|
|
30
|
+
|
|
31
|
+
async def execute_local(self, task: str, context: Dict[str, Any]) -> str:
|
|
32
|
+
"""本地执行分析"""
|
|
33
|
+
posts = context.get("posts", [])
|
|
34
|
+
wenlv_infos = context.get("wenlv_infos", [])
|
|
35
|
+
analysis = context.get("analysis", {})
|
|
36
|
+
|
|
37
|
+
# 如果有分析数据,生成本地推荐
|
|
38
|
+
if analysis:
|
|
39
|
+
destinations = analysis.get("destinations", [])
|
|
40
|
+
top_n = 10
|
|
41
|
+
|
|
42
|
+
recommendations = []
|
|
43
|
+
for i, dest in enumerate(destinations[:top_n], 1):
|
|
44
|
+
recommendations.append({
|
|
45
|
+
"name": dest.get("name", "未知目的地"),
|
|
46
|
+
"rank": i,
|
|
47
|
+
"score": dest.get("scores", {}).get("total_score", 5.0),
|
|
48
|
+
"reason": f"基于 {dest.get('post_count', 0)} 条社交媒体内容和 {dest.get('wenlv_count', 0)} 条文旅信息推荐",
|
|
49
|
+
"estimated_cost": "¥3000-5000",
|
|
50
|
+
"suggested_days": 5,
|
|
51
|
+
"best_time": "春秋季节",
|
|
52
|
+
"highlights": ["特色美食", "文化体验", "自然风光"]
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
result = {
|
|
56
|
+
"destinations": recommendations,
|
|
57
|
+
"summary": "本地分析推荐结果"
|
|
58
|
+
}
|
|
59
|
+
return json.dumps(result, ensure_ascii=False)
|
|
60
|
+
|
|
61
|
+
# 简化的本地分析
|
|
62
|
+
destinations = self._extract_destinations(posts, wenlv_infos)
|
|
63
|
+
|
|
64
|
+
recommendations = []
|
|
65
|
+
for i, dest in enumerate(destinations[:10], 1):
|
|
66
|
+
recommendations.append({
|
|
67
|
+
"name": dest,
|
|
68
|
+
"rank": i,
|
|
69
|
+
"score": 5.0,
|
|
70
|
+
"reason": "本地分析结果",
|
|
71
|
+
"estimated_cost": "¥3000-5000",
|
|
72
|
+
"suggested_days": 5,
|
|
73
|
+
"best_time": "春秋季节",
|
|
74
|
+
"highlights": ["特色美食", "文化体验"]
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
result = {
|
|
78
|
+
"destinations": recommendations,
|
|
79
|
+
"summary": "本地分析推荐结果"
|
|
80
|
+
}
|
|
81
|
+
return json.dumps(result, ensure_ascii=False)
|
|
82
|
+
|
|
83
|
+
def _extract_destinations(
|
|
84
|
+
self,
|
|
85
|
+
posts: List[Dict],
|
|
86
|
+
wenlv_infos: List[Dict]
|
|
87
|
+
) -> List[str]:
|
|
88
|
+
"""从数据中提取目的地"""
|
|
89
|
+
common_destinations = [
|
|
90
|
+
"三亚", "云南", "大理", "丽江", "西双版纳",
|
|
91
|
+
"四川", "成都", "九寨沟", "川西",
|
|
92
|
+
"北京", "上海", "广州", "深圳",
|
|
93
|
+
"浙江", "杭州", "乌镇", "苏州", "南京",
|
|
94
|
+
"江苏", "陕西", "西安",
|
|
95
|
+
"广西", "桂林", "阳朔",
|
|
96
|
+
"海南", "西藏", "拉萨", "新疆", "喀纳斯",
|
|
97
|
+
"甘肃", "敦煌", "青海", "青海湖",
|
|
98
|
+
"黑龙江", "哈尔滨", "吉林", "长白山"
|
|
99
|
+
]
|
|
100
|
+
|
|
101
|
+
destinations = {}
|
|
102
|
+
|
|
103
|
+
for post in posts:
|
|
104
|
+
text = f"{post.get('title', '')} {post.get('content', '')}"
|
|
105
|
+
for dest in common_destinations:
|
|
106
|
+
if dest in text:
|
|
107
|
+
if dest not in destinations:
|
|
108
|
+
destinations[dest] = {"posts": 0, "wenlv": 0}
|
|
109
|
+
destinations[dest]["posts"] += 1
|
|
110
|
+
|
|
111
|
+
for info in wenlv_infos:
|
|
112
|
+
region = info.get("region", "")
|
|
113
|
+
if region and region != "全国":
|
|
114
|
+
if region not in destinations:
|
|
115
|
+
destinations[region] = {"posts": 0, "wenlv": 0}
|
|
116
|
+
destinations[region]["wenlv"] += 1
|
|
117
|
+
|
|
118
|
+
# 按热度排序
|
|
119
|
+
sorted_dests = sorted(
|
|
120
|
+
destinations.items(),
|
|
121
|
+
key=lambda x: x[1]["posts"] * 2 + x[1]["wenlv"] * 3,
|
|
122
|
+
reverse=True
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
return [d[0] for d in sorted_dests]
|
|
126
|
+
|
|
127
|
+
async def analyze_destinations(
|
|
128
|
+
self,
|
|
129
|
+
posts: List[Dict],
|
|
130
|
+
wenlv_infos: List[Dict],
|
|
131
|
+
flights: List[Dict] = None,
|
|
132
|
+
hotels: List[Dict] = None
|
|
133
|
+
) -> Dict[str, Any]:
|
|
134
|
+
"""分析目的地数据
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
posts: 社交媒体帖子列表
|
|
138
|
+
wenlv_infos: 文旅信息列表
|
|
139
|
+
flights: 航班数据(可选)
|
|
140
|
+
hotels: 酒店数据(可选)
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
分析结果字典
|
|
144
|
+
"""
|
|
145
|
+
# 提取目的地
|
|
146
|
+
destinations = self._extract_destinations(posts, wenlv_infos)
|
|
147
|
+
|
|
148
|
+
# 为每个目的地计算评分
|
|
149
|
+
scored_destinations = []
|
|
150
|
+
for dest in destinations:
|
|
151
|
+
# 筛选相关数据
|
|
152
|
+
related_posts = [
|
|
153
|
+
p for p in posts
|
|
154
|
+
if dest in p.get("title", "") or dest in p.get("content", "")
|
|
155
|
+
]
|
|
156
|
+
related_wenlv = [
|
|
157
|
+
w for w in wenlv_infos
|
|
158
|
+
if dest in w.get("title", "") or dest in w.get("content", "") or dest == w.get("region")
|
|
159
|
+
]
|
|
160
|
+
|
|
161
|
+
# 计算评分
|
|
162
|
+
score_info = self.score_calculator.calculate_destination_score(
|
|
163
|
+
destination=dest,
|
|
164
|
+
posts=[SocialPost(**p) if isinstance(p, dict) else p for p in related_posts],
|
|
165
|
+
wenlv_infos=[WenlvInfo(**w) if isinstance(w, dict) else w for w in related_wenlv],
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
scored_destinations.append({
|
|
169
|
+
"name": dest,
|
|
170
|
+
"scores": score_info,
|
|
171
|
+
"post_count": len(related_posts),
|
|
172
|
+
"wenlv_count": len(related_wenlv),
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
# 按总分排序
|
|
176
|
+
scored_destinations.sort(
|
|
177
|
+
key=lambda x: x["scores"]["total_score"],
|
|
178
|
+
reverse=True
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
return {
|
|
182
|
+
"destinations": scored_destinations,
|
|
183
|
+
"total_analyzed": len(scored_destinations),
|
|
184
|
+
"top_destinations": [d["name"] for d in scored_destinations[:5]]
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async def generate_recommendations(
|
|
188
|
+
self,
|
|
189
|
+
analysis_result: Dict[str, Any],
|
|
190
|
+
top_n: int = 10
|
|
191
|
+
) -> str:
|
|
192
|
+
"""生成推荐结果
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
analysis_result: 分析结果
|
|
196
|
+
top_n: 推荐数量
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
推荐的 JSON 字符串
|
|
200
|
+
"""
|
|
201
|
+
task = f"""基于以下分析结果,生成 TOP{top_n}旅行目的地推荐。
|
|
202
|
+
|
|
203
|
+
对于每个目的地,请提供:
|
|
204
|
+
1. 排名
|
|
205
|
+
2. 目的地名称
|
|
206
|
+
3. 综合得分(基于提供的分数)
|
|
207
|
+
4. 推荐理由(100-200 字)
|
|
208
|
+
5. 预估费用范围
|
|
209
|
+
6. 建议游玩天数
|
|
210
|
+
7. 最佳旅行时间
|
|
211
|
+
8. 亮点特色(2-3 个)
|
|
212
|
+
|
|
213
|
+
分析数据:
|
|
214
|
+
{json.dumps(analysis_result, ensure_ascii=False, indent=2)}
|
|
215
|
+
|
|
216
|
+
请输出 JSON 格式:
|
|
217
|
+
{{
|
|
218
|
+
"destinations": [
|
|
219
|
+
{{
|
|
220
|
+
"name": "目的地",
|
|
221
|
+
"rank": 1,
|
|
222
|
+
"score": 8.5,
|
|
223
|
+
"reason": "推荐理由...",
|
|
224
|
+
"estimated_cost": "¥3000-5000",
|
|
225
|
+
"suggested_days": 5,
|
|
226
|
+
"best_time": "3-5 月",
|
|
227
|
+
"highlights": ["亮点 1", "亮点 2"]
|
|
228
|
+
}}
|
|
229
|
+
],
|
|
230
|
+
"summary": "整体总结"
|
|
231
|
+
}}
|
|
232
|
+
"""
|
|
233
|
+
|
|
234
|
+
return await self.execute(task, {"analysis": analysis_result})
|