travel-agent-cli 0.2.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.
Files changed (36) hide show
  1. package/bin/cli.js +6 -6
  2. package/package.json +2 -2
  3. package/python/agents/__init__.py +19 -0
  4. package/python/agents/analysis_agent.py +234 -0
  5. package/python/agents/base.py +377 -0
  6. package/python/agents/collector_agent.py +304 -0
  7. package/python/agents/manager_agent.py +251 -0
  8. package/python/agents/planning_agent.py +161 -0
  9. package/python/agents/product_agent.py +672 -0
  10. package/python/agents/report_agent.py +172 -0
  11. package/python/analyzers/__init__.py +10 -0
  12. package/python/analyzers/hot_score.py +123 -0
  13. package/python/analyzers/ranker.py +225 -0
  14. package/python/analyzers/route_planner.py +86 -0
  15. package/python/cli/commands.py +254 -0
  16. package/python/collectors/__init__.py +14 -0
  17. package/python/collectors/ota/ctrip.py +120 -0
  18. package/python/collectors/ota/fliggy.py +152 -0
  19. package/python/collectors/weibo.py +235 -0
  20. package/python/collectors/wenlv.py +155 -0
  21. package/python/collectors/xiaohongshu.py +170 -0
  22. package/python/config/__init__.py +30 -0
  23. package/python/config/models.py +119 -0
  24. package/python/config/prompts.py +105 -0
  25. package/python/config/settings.py +172 -0
  26. package/python/export/__init__.py +6 -0
  27. package/python/export/report.py +192 -0
  28. package/python/main.py +632 -0
  29. package/python/pyproject.toml +51 -0
  30. package/python/scheduler/tasks.py +77 -0
  31. package/python/tools/fliggy_mcp.py +553 -0
  32. package/python/tools/flyai_tools.py +251 -0
  33. package/python/tools/mcp_tools.py +412 -0
  34. package/python/utils/__init__.py +9 -0
  35. package/python/utils/http.py +73 -0
  36. package/python/utils/storage.py +288 -0
@@ -0,0 +1,672 @@
1
+ """Product Analysis Agent - 旅行产品可行性分析专家
2
+
3
+ 负责分析特定话题作为旅行产品的潜力,生成详细可行性分析报告
4
+ """
5
+ from typing import Dict, Any, List, Optional
6
+ import json
7
+ from datetime import datetime
8
+
9
+ from agents.base import BaseAgent
10
+ from agents.collector_agent import CollectionAgent
11
+ from agents.analysis_agent import AnalysisAgent
12
+
13
+
14
+ class ProductAnalysisAgent(BaseAgent):
15
+ """旅行产品可行性分析 Agent
16
+
17
+ 职责:
18
+ - 接收用户给定的话题(如"北欧极光"、"东南亚潜水"等)
19
+ - 在社交媒体和新闻中搜索相关资料
20
+ - 分析该话题作为旅行产品的市场潜力
21
+ - 生成详细的可行性分析报告
22
+
23
+ 分析维度:
24
+ 1. 市场需求分析(社交媒体热度、搜索趋势)
25
+ 2. 资源供给分析(航线、酒店、景点)
26
+ 3. 竞争格局分析(现有产品、价格区间)
27
+ 4. 风险评估(政策、安全、季节性)
28
+ 5. 商业价值评估(利润空间、目标客群)
29
+ """
30
+
31
+ name = "product_analysis_agent"
32
+ role = "旅行产品可行性分析专家"
33
+ goal = "深度分析特定旅行话题的商业潜力,输出专业的可行性分析报告"
34
+
35
+ def __init__(
36
+ self,
37
+ provider: Optional[str] = None,
38
+ model: Optional[str] = None,
39
+ use_tools: bool = False,
40
+ ):
41
+ super().__init__(provider, model, use_tools)
42
+
43
+ # 子 Agent 用于数据采集和初步分析
44
+ self.collector = CollectionAgent(provider, model, use_tools)
45
+ self.analyst = AnalysisAgent(provider, model, use_tools)
46
+
47
+ async def execute_local(self, task: str, context: Dict[str, Any]) -> str:
48
+ """本地执行(降级模式)"""
49
+ topic = context.get("topic", "未知话题")
50
+ return f"Product Analysis Agent 本地执行:分析话题'{topic}'的可行性(模拟报告)"
51
+
52
+ async def analyze_topic(
53
+ self,
54
+ topic: str,
55
+ include_news: bool = True,
56
+ include_ota: bool = True,
57
+ verbose: bool = True
58
+ ) -> Dict[str, Any]:
59
+ """分析指定话题的旅行产品可行性
60
+
61
+ Args:
62
+ topic: 分析话题,如"北欧极光"、"东南亚潜水"、"日本赏樱"等
63
+ include_news: 是否包含新闻资讯分析
64
+ include_ota: 是否包含 OTA 数据分析
65
+ verbose: 是否输出详细日志
66
+
67
+ Returns:
68
+ 完整分析结果字典
69
+ """
70
+ result = {
71
+ "topic": topic,
72
+ "status": "analyzing",
73
+ "started_at": datetime.now().isoformat(),
74
+ "stages": {}
75
+ }
76
+
77
+ if verbose:
78
+ print(f"\n[{self.name}] 🚀 开始分析话题:[bold]{topic}[/bold]")
79
+
80
+ # ========== Stage 1: 数据采集 ==========
81
+ if verbose:
82
+ print(f"\n[{self.name}] 📥 Stage 1: 数据采集")
83
+
84
+ # 构建搜索关键词
85
+ keywords = self._expand_keywords(topic)
86
+
87
+ collection_result = await self.collector.collect_all(
88
+ keyword=keywords["primary"],
89
+ include_ota=include_ota
90
+ )
91
+
92
+ result["stages"]["collection"] = {
93
+ "keywords_used": keywords,
94
+ "social_media_count": len(collection_result.get("social_media", {}).get("posts", [])),
95
+ "wenlv_count": len(collection_result.get("wenlv", {}).get("infos", [])),
96
+ "flight_count": len(collection_result.get("ota", {}).get("flights", [])),
97
+ "hotel_count": len(collection_result.get("ota", {}).get("hotels", [])),
98
+ }
99
+
100
+ if verbose:
101
+ print(f" ✓ 搜索关键词:{keywords['primary']}")
102
+ print(f" ✓ 社交媒体:{result['stages']['collection']['social_media_count']} 条")
103
+ print(f" ✓ 文旅信息:{result['stages']['collection']['wenlv_count']} 条")
104
+ if include_ota:
105
+ print(f" ✓ 航班:{result['stages']['collection']['flight_count']} 条")
106
+ print(f" ✓ 酒店:{result['stages']['collection']['hotel_count']} 条")
107
+
108
+ # ========== Stage 2: 市场需求分析 ==========
109
+ if verbose:
110
+ print(f"\n[{self.name}] 📊 Stage 2: 市场需求分析")
111
+
112
+ posts = collection_result.get("social_media", {}).get("posts", [])
113
+ wenlv_infos = collection_result.get("wenlv", {}).get("infos", [])
114
+
115
+ # 分析社交媒体热度
116
+ social_hotspot_analysis = await self._analyze_social_hotspot(posts, topic)
117
+ result["stages"]["market_demand"] = social_hotspot_analysis
118
+
119
+ if verbose:
120
+ print(f" ✓ 社交媒体热度:{social_hotspot_analysis.get('heat_level', 'unknown')}")
121
+ print(f" ✓ 互动总量:{social_hotspot_analysis.get('total_engagements', 0):,}")
122
+ print(f" ✓ 相关内容:{social_hotspot_analysis.get('content_count', 0)} 条")
123
+
124
+ # ========== Stage 3: 资源供给分析 ==========
125
+ if verbose:
126
+ print(f"\n[{self.name}] 🏨 Stage 3: 资源供给分析")
127
+
128
+ resource_analysis = await self._analyze_resources(
129
+ topic=topic,
130
+ flights=collection_result.get("ota", {}).get("flights", []),
131
+ hotels=collection_result.get("ota", {}).get("hotels", []),
132
+ wenlv_infos=wenlv_infos
133
+ )
134
+ result["stages"]["resources"] = resource_analysis
135
+
136
+ if verbose:
137
+ print(f" ✓ 航线丰富度:{resource_analysis.get('flight_availability', 'unknown')}")
138
+ print(f" ✓ 酒店选择:{resource_analysis.get('hotel_options', 'unknown')}")
139
+ print(f" ✓ 预估费用:{resource_analysis.get('estimated_cost_range', '未知')}")
140
+
141
+ # ========== Stage 4: 综合评估 ==========
142
+ if verbose:
143
+ print(f"\n[{self.name}] 📈 Stage 4: 综合评估")
144
+
145
+ assessment = await self._comprehensive_assessment(
146
+ topic=topic,
147
+ market_demand=social_hotspot_analysis,
148
+ resources=resource_analysis,
149
+ posts=posts,
150
+ wenlv_infos=wenlv_infos
151
+ )
152
+ result["stages"]["assessment"] = assessment
153
+
154
+ if verbose:
155
+ print(f" ✓ 市场潜力:{assessment.get('market_potential', 'unknown')}")
156
+ print(f" ✓ 推荐指数:{assessment.get('recommendation_score', 0)}/10")
157
+ print(f" ✓ 风险等级:{assessment.get('risk_level', 'unknown')}")
158
+
159
+ # ========== Stage 5: 生成报告 ==========
160
+ if verbose:
161
+ print(f"\n[{self.name}] 📝 Stage 5: 生成分析报告")
162
+
163
+ report = await self._generate_report(
164
+ topic=topic,
165
+ collection=result["stages"]["collection"],
166
+ market_demand=result["stages"]["market_demand"],
167
+ resources=result["stages"]["resources"],
168
+ assessment=result["stages"]["assessment"]
169
+ )
170
+ result["stages"]["report"] = {
171
+ "content": report,
172
+ "generated_at": datetime.now().isoformat()
173
+ }
174
+
175
+ if verbose:
176
+ print(f" ✓ 报告长度:{len(report)} 字符")
177
+
178
+ # ========== 完成 ==========
179
+ result["status"] = "completed"
180
+ result["completed_at"] = datetime.now().isoformat()
181
+
182
+ if verbose:
183
+ print(f"\n[{self.name}] ✅ 分析完成!")
184
+
185
+ return result
186
+
187
+ def _expand_keywords(self, topic: str) -> Dict[str, str]:
188
+ """扩展搜索关键词
189
+
190
+ Args:
191
+ topic: 原始话题
192
+
193
+ Returns:
194
+ 关键词字典
195
+ """
196
+ # 简单扩展逻辑,实际可接入 NLP 模型
197
+ keyword_map = {
198
+ "极光": {"primary": "极光旅行", "related": "北极光 南极光 极光摄影"},
199
+ "潜水": {"primary": "潜水度假", "related": "水肺潜水 浮潜 潜水考证"},
200
+ "滑雪": {"primary": "滑雪旅行", "related": "滑雪场 滑雪度假 粉雪"},
201
+ "樱花": {"primary": "赏樱旅行", "related": "樱花季 樱花前线 日本樱花"},
202
+ "海岛": {"primary": "海岛度假", "related": "海滩 浮潜 海岛游"},
203
+ }
204
+
205
+ for key, value in keyword_map.items():
206
+ if key in topic:
207
+ return {
208
+ "primary": value["primary"],
209
+ "related": value["related"],
210
+ "original": topic
211
+ }
212
+
213
+ return {
214
+ "primary": topic,
215
+ "related": f"{topic}攻略 {topic}推荐",
216
+ "original": topic
217
+ }
218
+
219
+ async def _analyze_social_hotspot(
220
+ self,
221
+ posts: List[Dict],
222
+ topic: str
223
+ ) -> Dict[str, Any]:
224
+ """分析社交媒体热度
225
+
226
+ Args:
227
+ posts: 帖子列表
228
+ topic: 话题
229
+
230
+ Returns:
231
+ 热度分析结果
232
+ """
233
+ if not posts:
234
+ return {
235
+ "heat_level": "低",
236
+ "total_engagements": 0,
237
+ "content_count": 0,
238
+ "trend": "平稳",
239
+ "key_topics": []
240
+ }
241
+
242
+ # 计算总互动量
243
+ total_likes = sum(p.get("likes", 0) for p in posts)
244
+ total_comments = sum(p.get("comments", 0) for p in posts)
245
+ total_shares = sum(p.get("shares", 0) for p in posts)
246
+ total_engagements = total_likes + total_comments + total_shares
247
+
248
+ # 判断热度等级
249
+ if total_engagements > 100000:
250
+ heat_level = "非常高"
251
+ elif total_engagements > 10000:
252
+ heat_level = "高"
253
+ elif total_engagements > 1000:
254
+ heat_level = "中等"
255
+ else:
256
+ heat_level = "低"
257
+
258
+ # 提取关键话题/标签
259
+ tags = []
260
+ for post in posts:
261
+ if post.get("tags"):
262
+ tags.extend(post["tags"][:3])
263
+
264
+ # 统计高频标签
265
+ from collections import Counter
266
+ tag_counts = Counter(tags)
267
+ key_topics = [tag for tag, _ in tag_counts.most_common(5)]
268
+
269
+ return {
270
+ "heat_level": heat_level,
271
+ "total_engagements": total_engagements,
272
+ "total_likes": total_likes,
273
+ "total_comments": total_comments,
274
+ "total_shares": total_shares,
275
+ "content_count": len(posts),
276
+ "trend": "上升" if total_engagements > 5000 else "平稳",
277
+ "key_topics": key_topics,
278
+ "avg_engagement_per_post": total_engagements / len(posts) if posts else 0
279
+ }
280
+
281
+ async def _analyze_resources(
282
+ self,
283
+ topic: str,
284
+ flights: List[Dict],
285
+ hotels: List[Dict],
286
+ wenlv_infos: List[Dict]
287
+ ) -> Dict[str, Any]:
288
+ """分析资源供给情况
289
+
290
+ Args:
291
+ topic: 话题
292
+ flights: 航班数据
293
+ hotels: 酒店数据
294
+ wenlv_infos: 文旅信息
295
+
296
+ Returns:
297
+ 资源分析结果
298
+ """
299
+ # 航班分析
300
+ if flights:
301
+ flight_prices = [f.get("price", 0) for f in flights if f.get("price")]
302
+ avg_flight_price = sum(flight_prices) / len(flight_prices) if flight_prices else 0
303
+ flight_availability = "丰富" if len(flights) > 20 else "一般" if len(flights) > 5 else "较少"
304
+ else:
305
+ avg_flight_price = 0
306
+ flight_availability = "未知"
307
+
308
+ # 酒店分析
309
+ if hotels:
310
+ hotel_prices = [h.get("price", 0) for h in hotels if h.get("price")]
311
+ avg_hotel_price = sum(hotel_prices) / len(hotel_prices) if hotel_prices else 0
312
+ hotel_options = "丰富" if len(hotels) > 50 else "一般" if len(hotels) > 10 else "较少"
313
+ else:
314
+ avg_hotel_price = 0
315
+ hotel_options = "未知"
316
+
317
+ # 文旅政策分析
318
+ policy_support = "有" if wenlv_infos and len(wenlv_infos) > 3 else "暂无"
319
+
320
+ # 预估费用范围
321
+ if avg_flight_price > 0 and avg_hotel_price > 0:
322
+ min_cost = avg_flight_price + avg_hotel_price * 3
323
+ max_cost = avg_flight_price * 2 + avg_hotel_price * 7
324
+ estimated_cost_range = f"¥{int(min_cost)}-{int(max_cost)}"
325
+ else:
326
+ estimated_cost_range = "需进一步调研"
327
+
328
+ return {
329
+ "flight_availability": flight_availability,
330
+ "flight_count": len(flights),
331
+ "avg_flight_price": avg_flight_price,
332
+ "hotel_options": hotel_options,
333
+ "hotel_count": len(hotels),
334
+ "avg_hotel_price": avg_hotel_price,
335
+ "policy_support": policy_support,
336
+ "wenlv_count": len(wenlv_infos),
337
+ "estimated_cost_range": estimated_cost_range
338
+ }
339
+
340
+ async def _comprehensive_assessment(
341
+ self,
342
+ topic: str,
343
+ market_demand: Dict[str, Any],
344
+ resources: Dict[str, Any],
345
+ posts: List[Dict],
346
+ wenlv_infos: List[Dict]
347
+ ) -> Dict[str, Any]:
348
+ """综合评估
349
+
350
+ Args:
351
+ topic: 话题
352
+ market_demand: 市场需求分析
353
+ resources: 资源分析
354
+ posts: 帖子列表
355
+ wenlv_infos: 文旅信息
356
+
357
+ Returns:
358
+ 综合评估结果
359
+ """
360
+ # 市场潜力评分(1-10)
361
+ heat_scores = {
362
+ "非常高": 9,
363
+ "高": 7,
364
+ "中等": 5,
365
+ "低": 3
366
+ }
367
+ market_score = heat_scores.get(market_demand.get("heat_level", "低"), 5)
368
+
369
+ # 资源成熟度评分
370
+ resource_score = 5
371
+ if resources.get("flight_availability") == "丰富":
372
+ resource_score += 2
373
+ elif resources.get("flight_availability") == "一般":
374
+ resource_score += 1
375
+
376
+ if resources.get("hotel_options") == "丰富":
377
+ resource_score += 2
378
+ elif resources.get("hotel_options") == "一般":
379
+ resource_score += 1
380
+
381
+ if resources.get("policy_support") == "有":
382
+ resource_score += 1
383
+
384
+ # 综合推荐指数
385
+ recommendation_score = round((market_score + resource_score) / 2, 1)
386
+
387
+ # 风险等级评估
388
+ if recommendation_score >= 8:
389
+ risk_level = "低"
390
+ market_potential = "非常高"
391
+ elif recommendation_score >= 6:
392
+ risk_level = "中"
393
+ market_potential = "高"
394
+ else:
395
+ risk_level = "高"
396
+ market_potential = "一般"
397
+
398
+ # 目标客群分析
399
+ target_audience = self._analyze_target_audience(posts)
400
+
401
+ # SWOT 分析要点
402
+ swot = await self._generate_swot(topic, market_demand, resources)
403
+
404
+ return {
405
+ "market_score": market_score,
406
+ "resource_score": resource_score,
407
+ "recommendation_score": recommendation_score,
408
+ "market_potential": market_potential,
409
+ "risk_level": risk_level,
410
+ "target_audience": target_audience,
411
+ "swot": swot
412
+ }
413
+
414
+ def _analyze_target_audience(self, posts: List[Dict]) -> Dict[str, Any]:
415
+ """分析目标客群画像"""
416
+ # 简化实现,实际可接入用户画像分析
417
+ if not posts:
418
+ return {
419
+ "age_group": "未知",
420
+ "interests": [],
421
+ "consumption_level": "未知"
422
+ }
423
+
424
+ # 基于互动数据推测
425
+ avg_engagement = sum(p.get("likes", 0) + p.get("comments", 0) for p in posts) / len(posts)
426
+
427
+ if avg_engagement > 1000:
428
+ consumption_level = "高"
429
+ elif avg_engagement > 100:
430
+ consumption_level = "中等"
431
+ else:
432
+ consumption_level = "大众"
433
+
434
+ return {
435
+ "age_group": "25-40 岁",
436
+ "interests": ["旅行", "摄影", "美食", "文化体验"],
437
+ "consumption_level": consumption_level
438
+ }
439
+
440
+ async def _generate_swot(
441
+ self,
442
+ topic: str,
443
+ market_demand: Dict[str, Any],
444
+ resources: Dict[str, Any]
445
+ ) -> Dict[str, List[str]]:
446
+ """生成 SWOT 分析"""
447
+ swot = {
448
+ "strengths": [],
449
+ "weaknesses": [],
450
+ "opportunities": [],
451
+ "threats": []
452
+ }
453
+
454
+ # Strengths
455
+ if market_demand.get("heat_level") in ["高", "非常高"]:
456
+ swot["strengths"].append("社交媒体关注度高,市场需求旺盛")
457
+ if resources.get("flight_availability") == "丰富":
458
+ swot["strengths"].append("航线资源丰富,交通便利")
459
+ if resources.get("hotel_options") == "丰富":
460
+ swot["strengths"].append("住宿选择多样,接待能力强")
461
+
462
+ # Weaknesses
463
+ if resources.get("flight_availability") in ["较少", "未知"]:
464
+ swot["weaknesses"].append("航线资源有限,交通可达性待提升")
465
+ if market_demand.get("total_engagements", 0) < 1000:
466
+ swot["weaknesses"].append("市场认知度较低,需要加强推广")
467
+
468
+ # Opportunities
469
+ if resources.get("policy_support") == "有":
470
+ swot["opportunities"].append("文旅政策支持,有官方背书")
471
+ swot["opportunities"].append("后疫情时代旅行需求反弹")
472
+ swot["opportunities"].append("社交媒体传播效应显著")
473
+
474
+ # Threats
475
+ swot["threats"].append("同类旅行产品竞争")
476
+ swot["threats"].append("季节性因素影响")
477
+ swot["threats"].append("政策变化风险")
478
+
479
+ return swot
480
+
481
+ async def _generate_report(
482
+ self,
483
+ topic: str,
484
+ collection: Dict[str, Any],
485
+ market_demand: Dict[str, Any],
486
+ resources: Dict[str, Any],
487
+ assessment: Dict[str, Any]
488
+ ) -> str:
489
+ """生成完整分析报告"""
490
+ report = f"""# 旅行产品可行性分析报告
491
+
492
+ ## 分析话题:{topic}
493
+
494
+ **报告生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
495
+
496
+ ---
497
+
498
+ ## 📊 一、执行摘要
499
+
500
+ ### 核心结论
501
+
502
+ | 评估维度 | 评分 | 等级 |
503
+ |---------|------|------|
504
+ | 市场潜力 | {assessment.get('market_score', 0)}/10 | {assessment.get('market_potential', '未知')} |
505
+ | 资源成熟度 | {assessment.get('resource_score', 0)}/10 | - |
506
+ | **推荐指数** | **{assessment.get('recommendation_score', 0)}/10** | {assessment.get('market_potential', '未知')} |
507
+ | 风险等级 | - | {assessment.get('risk_level', '未知')} |
508
+
509
+ ### 采集数据概览
510
+
511
+ - 社交媒体内容:{collection.get('social_media_count', 0)} 条
512
+ - 文旅政策信息:{collection.get('wenlv_count', 0)} 条
513
+ - 航班信息:{collection.get('flight_count', 0)} 条
514
+ - 酒店信息:{collection.get('hotel_count', 0)} 条
515
+
516
+ ---
517
+
518
+ ## 🔥 二、市场需求分析
519
+
520
+ ### 社交媒体热度
521
+
522
+ | 指标 | 数值 |
523
+ |------|------|
524
+ | 热度等级 | {market_demand.get('heat_level', '未知')} |
525
+ | 总互动量 | {market_demand.get('total_engagements', 0):,} |
526
+ | 总点赞数 | {market_demand.get('total_likes', 0):,} |
527
+ | 总评论数 | {market_demand.get('total_comments', 0):,} |
528
+ | 总分享数 | {market_demand.get('total_shares', 0):,} |
529
+ | 篇均互动 | {market_demand.get('avg_engagement_per_post', 0):.1f} |
530
+ | 趋势判断 | {market_demand.get('trend', '平稳')} |
531
+
532
+ ### 热门话题标签
533
+
534
+ {', '.join(assessment.get('key_topics', []) or market_demand.get('key_topics', ['暂无数据']))}
535
+
536
+ ---
537
+
538
+ ## 🏨 三、资源供给分析
539
+
540
+ ### 交通资源
541
+
542
+ | 指标 | 数值 |
543
+ |------|------|
544
+ | 航线丰富度 | {resources.get('flight_availability', '未知')} |
545
+ | 航班数量 | {resources.get('flight_count', 0)} 条 |
546
+ | 平均机票价格 | ¥{resources.get('avg_flight_price', 0):.0f} |
547
+
548
+ ### 住宿资源
549
+
550
+ | 指标 | 数值 |
551
+ |------|------|
552
+ | 酒店选择 | {resources.get('hotel_options', '未知')} |
553
+ | 酒店数量 | {resources.get('hotel_count', 0)} 家 |
554
+ | 平均酒店价格 | ¥{resources.get('avg_hotel_price', 0):.0f}/晚 |
555
+
556
+ ### 政策支持
557
+
558
+ - 文旅政策信息:{resources.get('wenlv_count', 0)} 条
559
+ - 政策支持:{resources.get('policy_support', '暂无')}
560
+
561
+ ### 预估费用范围
562
+
563
+ **{resources.get('estimated_cost_range', '需进一步调研')}**(按 3-7 天行程估算)
564
+
565
+ ---
566
+
567
+ ## 👥 四、目标客群画像
568
+
569
+ | 维度 | 特征 |
570
+ |------|------|
571
+ | 年龄段 | {assessment.get('target_audience', {}).get('age_group', '未知')} |
572
+ | 消费水平 | {assessment.get('target_audience', {}).get('consumption_level', '未知')} |
573
+ | 兴趣标签 | {', '.join(assessment.get('target_audience', {}).get('interests', []))} |
574
+
575
+ ---
576
+
577
+ ## 📈 五、SWOT 分析
578
+
579
+ ### 优势 (Strengths)
580
+ {chr(10).join('✓ ' + s for s in assessment.get('swot', {}).get('strengths', ['暂无']))}
581
+
582
+ ### 劣势 (Weaknesses)
583
+ {chr(10).join('✗ ' + w for w in assessment.get('swot', {}).get('weaknesses', ['暂无']))}
584
+
585
+ ### 机会 (Opportunities)
586
+ {chr(10).join('✓ ' + o for o in assessment.get('swot', {}).get('opportunities', ['暂无']))}
587
+
588
+ ### 威胁 (Threats)
589
+ {chr(10).join('⚠ ' + t for t in assessment.get('swot', {}).get('threats', ['暂无']))}
590
+
591
+ ---
592
+
593
+ ## 💡 六、产品开发建议
594
+
595
+ ### 推荐产品类型
596
+
597
+ 基于分析结果,建议开发以下类型的旅行产品:
598
+
599
+ 1. **核心产品**: 围绕"{topic}"主题的深度体验产品
600
+ 2. **差异化亮点**: 结合社交媒体热门元素,打造网红打卡点
601
+ 3. **价格策略**: {resources.get('estimated_cost_range', '待调研')}的中高端定位
602
+
603
+ ### 开发优先级
604
+
605
+ | 优先级 | 事项 | 说明 |
606
+ |--------|------|------|
607
+ | P0 | 供应链确认 | 落实航线、酒店、地接资源 |
608
+ | P1 | 产品设计 | 规划行程路线和体验项目 |
609
+ | P2 | 定价策略 | 基于成本和竞品定价 |
610
+ | P3 | 营销素材 | 制作社交媒体推广内容 |
611
+
612
+ ### 风险缓释措施
613
+
614
+ 1. **季节性风险**: 设计多季节产品线,降低单一季节依赖
615
+ 2. **政策风险**: 密切关注文旅政策变化,保持灵活调整
616
+ 3. **竞争风险**: 打造差异化体验,建立品牌壁垒
617
+
618
+ ---
619
+
620
+ ## 🎯 七、结论与建议
621
+
622
+ ### 最终结论
623
+
624
+ **推荐指数:{assessment.get('recommendation_score', 0)}/10**
625
+
626
+ 话题"{topic}"作为旅行产品的开发可行性评估为:**{assessment.get('market_potential', '未知')}**
627
+
628
+ - 市场热度:{market_demand.get('heat_level', '未知')}
629
+ - 资源成熟度:{resources.get('flight_availability', '未知')} / {resources.get('hotel_options', '未知')}
630
+ - 风险等级:{assessment.get('risk_level', '未知')}
631
+
632
+ ### 行动建议
633
+
634
+ {
635
+ "建议立即启动产品开发" if assessment.get('recommendation_score', 0) >= 7 else
636
+ "建议进一步市场调研后决策" if assessment.get('recommendation_score', 0) >= 5 else
637
+ "建议谨慎评估,暂不优先开发"
638
+ }
639
+
640
+ ---
641
+
642
+ *本报告由 AI 旅行产品分析 Agent 生成,仅供参考。实际决策请结合专业市场调研和商业判断。*
643
+ """
644
+ return report
645
+
646
+ async def quick_analysis(self, topic: str) -> str:
647
+ """快速分析(简化版)
648
+
649
+ Args:
650
+ topic: 分析话题
651
+
652
+ Returns:
653
+ 简化版分析报告
654
+ """
655
+ result = await self.analyze_topic(
656
+ topic=topic,
657
+ include_ota=False,
658
+ verbose=False
659
+ )
660
+
661
+ assessment = result.get("stages", {}).get("assessment", {})
662
+ return f"""【快速分析】话题:{topic}
663
+
664
+ 推荐指数:{assessment.get('recommendation_score', 0)}/10
665
+ 市场潜力:{assessment.get('market_potential', '未知')}
666
+ 风险等级:{assessment.get('risk_level', '未知')}
667
+
668
+ 核心结论:{
669
+ "建议重点开发" if assessment.get('recommendation_score', 0) >= 7 else
670
+ "建议进一步调研" if assessment.get('recommendation_score', 0) >= 5 else
671
+ "建议谨慎评估"
672
+ }"""