如果你正在准备大数据方向或 AI 方向的毕业设计,又不想只做一个“调包展示型 Demo”,那这次的系统应该很适合参考:基于 Hadoop 与 AI Agent 的西藏旅游数据分析及智能规划系统。它不是单纯写一个爬虫,也不是只调一个大模型接口,而是把大数据采集、存储、清洗、分析、可视化,再加上一层 AI Agent 对话式行程规划串成完整链路。
从材料看,这类系统在课设、毕设里非常典型:数据源明确、技术栈偏工程、有可视化界面、有交互能力,还能作为“大数据 + AI Agent”复合型项目写进简历。硬件门槛也不算高,伪分布式 Hadoop 集群在 8GB 内存的笔记本上就能跑,后期可以平滑迁移到云服务器或 Docker 环境。整篇文章我会按“核心能力、场景边界、环境准备、部署启动、数据链路、Agent 规划、接口批量任务、资源观察、常见问题、最佳实践”来展开,尽量把部署思路和验证方法写具体。
1. 核心能力速览
这个系统的核心定位是:面向旅游领域的数据分析与智能规划平台。底层用 Hadoop 体系做数据存储与离线分析,上层用 AI Agent 编排对话、检索、推荐和行程规划能力。下面用一张表快速概括。
| 能力项 | 说明 |
|---|---|
| 系统类型 | 大数据分析 + AI 智能规划综合系统 |
| 核心组件 | Hadoop HDFS、Hive、Spark(可选)、Python、FastAPI/Flask、大模型 API |
| 数据链路 | 数据采集 -> 数据清洗 -> HDFS 存储 -> Hive/Spark 分析 -> 可视化 -> Agent 推荐规划 |
| 主要功能 | 西藏旅游数据分析、景点热度分析、游客偏好分析、智能行程规划、多轮对话推荐 |
| 部署方式 | Hadoop 伪分布式、Docker(可选)、本地 Python 服务和 Web 前端 |
| 是否支持 API | 支持,后端提供 REST API 供前端和第三方调用 |
| 是否支持批量任务 | 支持,可批量导入数据和批量生成规划方案 |
| 硬件门槛 | 伪分布式建议 8GB 内存以上,单机可跑通完整链路 |
| 显存要求 | 无硬性要求,Agent 推理走云端或本地大模型 API,不强制 GPU |
| 适合场景 | 毕业设计、课程设计、大数据综合实训、旅游数据分析项目 |
从功能结构看,这个系统最大的价值不是“某一段代码有多难”,而是把 Hadoop 生态、数据分析、可视化、AI 智能体这四个模块完整打通。读者拿到这套思路后,可以快速替换数据源和技术组件,迁移到其他行业场景。
2. 适用场景与使用边界
2.1 适合谁、能解决什么问题
这类系统最适合以下三类读者:
- 大数据方向毕业生。项目覆盖 Hadoop、Hive、Spark、可视化等核心关键词,适合写进简历。
- AI Agent 方向初学者。不需要从头训练大模型,只需要把大模型 API、工具调用、业务规则编排起来。
- 旅游行业数据从业者。如果手里有公开景区数据,可以借鉴数据分析和行程规划模块。
它能解决的问题也很明确:
- 把零散旅游数据统一存储到 HDFS,解决“数据放在多个 Excel 和数据库里”的问题。
- 用 Hive SQL 或 Spark 做离线分析,得到景点热度、淡旺季分布、用户偏好等结论。
- 用 AI Agent 把“用户提问 -> 数据检索 -> 景点推荐 -> 行程编排”串起来,比静态查询更接近真实需求。
2.2 不适合做什么
这个项目的定位是“毕业设计级工程”,不是“生产级高并发平台”。如果目标是支撑千万级日活的旅游 App,那需要换成实时计算框架、分布式数据库、微服务治理,架构复杂度会高很多。另外,如果只想做模型训练,不想碰 Hadoop 部署,那这套系统明显偏重工程集成,不一定合适。
2.3 数据合规与版权边界
旅游数据可能涉及景区客流、用户评论、酒店价格等。做毕设时要注意三点:
- 尽量使用公开统计数据和模拟数据,不要爬取包含个人隐私的评论和订单数据。
- 如果数据集来自第三方平台,需要确认授权范围,不能直接用于商用。
- AI Agent 生成行程建议时,只做信息聚合和推荐,不要替代专业旅游机构做出风险承诺。
3. 环境准备与前置条件
3.1 操作系统与资源要求
Hadoop 本身是跨平台的,但伪分布式部署在 Linux 上最省心。如果你只有 Windows 笔记本,优先用 WSL2 或 Docker 搭 Hadoop,避免环境变量和权限问题。内存建议至少 8GB,因为 NameNode、DataNode、ResourceManager 加在一起会占用不少内存。
我建议的最小环境清单如下:
| 项目 | 最低要求 |
|---|---|
| 操作系统 | Ubuntu 20.04/22.04、CentOS 7+、WSL2 均可 |
| 内存 | 8GB(伪分布式最低建议) |
| 磁盘 | 至少 30GB 可用空间 |
| JDK | JDK 8 或 JDK 11(视 Hadoop 版本而定) |
| Hadoop | Hadoop 3.x |
| Hive | Hive 3.x |
| Python | Python 3.8+ |
| 数据库 | MySQL 5.7 或 8.0(存分析结果和用户信息) |
| 大模型 API | 需要一个可调用的 LLM API 或本地模型服务 |
3.2 端口规划
Hadoop 和 Hive 默认占用的端口较多,部署前先检查冲突:
| 组件 | 默认端口 |
|---|---|
| NameNode WebUI | 9870(Hadoop 3.x) |
| DataNode | 9864 |
| YARN ResourceManager | 8088 |
| Hive Metastore(如需) | 9083 |
| HiveServer2 | 10000 |
| Flask/FastAPI 后端 | 8000 或 5000 |
如果端口被占用,可以手动改配置文件,也可以用ss -lntp或netstat -lntp检查。
3.3 SSH 免密登录
伪分布式模式下,建议配置本机 SSH 免密登录,避免每次启动服务都卡在密码输入上。通用命令如下:
ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys4. 安装部署与启动方式
4.1 Hadoop 伪分布式部署
这里给出一套常见配置模板。实际路径和主机名需要按你的环境调整。
先设置环境变量:
# ~/.bashrc 追加 export HADOOP_HOME=/opt/hadoop export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin修改core-site.xml:
<configuration> <property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> </property> <property> <name>hadoop.tmp.dir</name> <value>/data/hadoop/tmp</value> </property> </configuration>修改hdfs-site.xml:
<configuration> <property> <name>dfs.replication</name> <value>1</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>/data/hadoop/namenode</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>/data/hadoop/datanode</value> </property> </configuration>修改yarn-site.xml:
<configuration> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> </configuration>配置完成后格式化文件系统。注意:每次重新格式化前,如果之间启动过集群,最好先删除namenode和datanode对应目录,再格式化。
hdfs namenode -format start-dfs.sh start-yarn.sh启动后访问:
- HDFS WebUI:http://localhost:9870
- YARN WebUI:http://localhost:8088
看到两个页面正常打开,说明 Hadoop 核心服务没问题。
4.2 Hive 安装与初始化
Hive 负责把 SQL 转换成 MapReduce 或 Spark 任务,是离线分析的常用入口。下载二进制包后,将 Hive 解压到/opt/hive。接着设置hive-site.xml中的 MySQL 连接信息:
<configuration> <property> <name>javax.jdo.option.ConnectionURL</name> <value>jdbc:mysql://localhost:3306/hive_metastore?createDatabaseIfNotExist=true</value> </property> <property> <name>javax.jdo.option.ConnectionDriverName</name> <value>com.mysql.cj.jdbc.Driver</value> </property> <property> <name>javax.jdo.option.ConnectionUserName</name> <value>hive</value> </property> <property> <name>javax.jdo.option.ConnectionPassword</name> <value>your_password</value> </property> </configuration>初始化 metastore schema:
schematool -dbType mysql -initSchema然后启动 HiveServer2 和 metastore:
hive --service metastore & hiveserver2 &测试连接:
beeline -u jdbc:hive2://localhost:10000 -n hive4.3 系统中台服务启动
后端服务建议用 FastAPI 或 Flask 实现,主要聚合三类能力:
- 读取 Hive/MySQL 的分析结果。
- 提供景点和线路查询接口。
- 调用大模型 API 完成 Agent 对话和行程规划。
先安装依赖:
pip install fastapi uvicorn requests pandas pymysql最小启动示例:
from fastapi import FastAPI app = FastAPI() @app.get("/api/health") def health(): return {"status": "ok"}启动:
uvicorn main:app --host 0.0.0.0 --port 8000访问http://localhost:8000/api/health,返回{"status":"ok"}就说明系统台服务跑起来了。
5. 数据链路:从采集到可视化
5.1 数据采集模块
西藏旅游数据分析系统的数据源,可以分成三类:
- 景区基础信息,包含名称、地区、门票、开放时间、简介。
- 客流与热度数据,包含月度游客量、消费水平、停留时长。
- 用户评论或问卷调查数据,包含满意度、偏好标签、出行类型。
如果做毕设,最稳妥的方式是先用模拟数据生成一份 CSV,再写爬虫爬取公开景区信息作为补充。要控制爬取频率,遵守目标站点 robots 协议,也不要抓取个人隐私数据。
示例 CSV 结构:
attraction_id,attraction_name,city,ticket_price,month,visitor_count,satisfaction A001,布达拉宫,拉萨,200,202401,120000,4.8 A002,大昭寺,拉萨,85,202401,90000,4.65.2 数据清洗与上传 HDFS
数据清洗是“大数据项目”的加分项。可以用 Python 的 pandas 做一次清洗,再上传到 HDFS:
hdfs dfs -mkdir -p /data/tourism/raw hdfs dfs -put ./tourism_data.csv /data/tourism/raw/查看文件:
hdfs dfs -ls /data/tourism/raw/Python 清洗示例:
import pandas as pd df = pd.read_csv("tourism_data.csv") df = df.drop_duplicates() df["visitor_count"] = df["visitor_count"].fillna(0) df = df[df["attraction_name"].notnull()] df.to_csv("tourism_data_clean.csv", index=False)5.3 Hive 建表与分析 SQL
在 Hive 中创建外部表,直接映射 HDFS 文件:
CREATE EXTERNAL TABLE IF NOT EXISTS tourism_analysis ( attraction_id STRING, attraction_name STRING, city STRING, ticket_price DOUBLE, month STRING, visitor_count BIGINT, satisfaction DOUBLE ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' STORED AS TEXTFILE LOCATION '/data/tourism/raw';分析月度热度排行:
SELECT attraction_name, city, SUM(visitor_count) AS total_visitors FROM tourism_analysis GROUP BY attraction_name, city ORDER BY total_visitors DESC LIMIT 20;分析旺季月份分布:
SELECT month, AVG(satisfaction) AS avg_satisfaction, SUM(visitor_count) AS total_visitors FROM tourism_analysis GROUP BY month ORDER BY total_visitors DESC;运行完成后,可以把结果写入 MySQL,方便后端接口查询:
INSERT INTO tourism_stats SELECT attraction_name, city, SUM(visitor_count) FROM tourism_analysis GROUP BY attraction_name, city;5.4 可视化模块
可视化可以使用 ECharts 或 Superset。最简单的方案是后端提供一个汇总查询接口,前端用 ECharts 画柱状图、地图、折线图。
关键统计指标包括:
- 西藏各城市景点数量。
- 月度游客总量波动。
- 热门景点 TOP10。
- 满意度分布。
- 门票价格区间分布。
注意:如果数据量很小,“大数据”主要体现在全链路工程能力上,分析结论的可信度要以数据来源和样本量说明为准,不要在毕设答辩时硬把模拟数据描述成官方数据。
6. AI Agent 智能规划模块
6.1 Agent 的交互链路
AI Agent 模块是这个系统区别于普通数据分析平台的核心。整体交互流程可以拆成五步:
- 用户输入自然语言诉求,比如“想用 5 天时间玩拉萨和林芝,带老人,预算控制在 6000”。
- Agent 解析用户偏好,提取天数、城市、预算、同行人标签。
- Agent 调用数据查询工具,获取候选景点、酒店价格、线路距离。
- Agent 调用大模型生成多套行程方案。
- 系统把行程与景点热度、满意度数据一起返回给前端。
这套链路里,Agent 不负责“编造天气和门票”,它只是根据数据工具返回的信息进行编排,可信度更高。
6.2 工具调用设计
在代码层面,可以把工具函数注册成一个个方法,大模型根据用户问题决定调用哪个工具。下面是一个简化示例:
def search_attractions(city: str, max_price: float = 500): # 从 Hive/MySQL 查询景点 sql = f""" SELECT attraction_name, ticket_price, satisfaction FROM tourism_stats WHERE city = '{city}' AND ticket_price <= {max_price} ORDER BY satisfaction DESC """ return query_mysql(sql) def estimate_route(start: str, end: str): # 查询两地大概距离和耗时 return distance_map[(start, end)]大模型侧只需要在系统提示词里声明可用工具:
你是西藏旅游规划助手。用户提问后,请先调用 search_attractions 获取景点信息, 再调用 estimate_route 估算路线,最后生成 5 日行程。 如果数据不足,请明确告诉用户缺少哪些信息。6.3 行程推荐逻辑
行程规划不能只靠大模型生成,否则容易出现“景点合理但路线绕路”的问题。更稳妥的做法是后端先做过滤和排序:
- 按用户预算过滤景点。
- 按游客满意度排序。
- 按城市相邻关系合并线路。
- 把同一城市景点打包成“上午 + 下午”。
实现时可以把推荐规则和 Prompt 结果都写进plan_service.py:
def build_plan(city_list, days, budget): candidate = [] for city in city_list: attractions = search_attractions(city, budget) candidate.extend(attractions[:3]) # 规则排序后再交给大模型润色文案 return candidate这样做好处很明显:Agent 生成的内容永远建立在结构化查询结果之上,不会因为大模型幻觉输出一个不存在的“错位景点”。
6.4 多轮对话与追问
现实中,用户第一次提问往往信息不足。Agent 需要在缺少关键参数时主动追问:
def extract_requirements(user_input): if "天" not in user_input: return {"ask": "请问您计划游玩几天?"} if "预算" not in user_input: return {"ask": "请问预算大概是多少?"} return {"is_complete": True}这个追问逻辑本身不复杂,但能让系统在演示时显得更“智能”,也便于毕设答辩时展示多轮对话效果。
7. API 接口与批量任务
7.1 后端接口概览
为了让前端和第三方系统调用,后端需要提供一组 REST API。基本接口可以这样设计:
| 接口 | 方法 | 说明 |
|---|---|---|
/api/health | GET | 健康检查 |
/api/attractions | GET | 景点列表查询 |
/api/stats/overview | GET | 数据总览统计 |
/api/agent/plan | POST | 智能行程规划 |
/api/agent/chat | POST | 多轮对话 |
/api/batch/import | POST | 批量导入数据 |
7.2 行程规划接口示例
使用 FastAPI 实现/api/agent/plan:
from fastapi import FastAPI, HTTPException from pydantic import BaseModel app = FastAPI() class PlanRequest(BaseModel): days: int cities: list[str] budget: float tags: list[str] = [] class PlanResponse(BaseModel): plan_id: str schedule: list[dict] @app.post("/api/agent/plan", response_model=PlanResponse) def generate_plan(req: PlanRequest): try: schedule = build_plan(req.cities, req.days, req.budget) return PlanResponse(plan_id="P001", schedule=schedule) except Exception as e: raise HTTPException(status_code=500, detail=str(e))调用示例:
curl -X POST http://localhost:8000/api/agent/plan \ -H "Content-Type: application/json" \ -d '{"days": 5, "cities": ["拉萨", "林芝"], "budget": 6000, "tags": ["老人", "慢节奏"]}'7.3 多轮对话接口示例
对话接口实现时,需要一个临时的会话记忆容器。毕设阶段可以用内存字典,生产环境需要换成 Redis:
session_memory = {} @app.post("/api/agent/chat") def chat(data: dict): session_id = data.get("session_id") user_msg = data.get("message") if session_id not in session_memory: session_memory[session_id] = [] session_memory[session_id].append({"role": "user", "content": user_msg}) # 调用大模型 API reply = call_llm_api(session_memory[session_id]) session_memory[session_id].append({"role": "assistant", "content": reply}) return {"session_id": session_id, "reply": reply}7.4 批量任务设计
批量任务主要用于两类场景:
- 批量导入历史月份数据。
- 批量生成多个用户的行程方案。
批量导入可以使用目录监听或手动上传,导入后写入 HDFS:
hdfs dfs -put ./import_batch/ /data/tourism/batch/批量生成路线时,建议加日志和失败重试:
import time from loguru import logger task_queue = [ {"days": 3, "cities": ["拉萨"], "budget": 4000, "user": "U001"}, {"days": 4, "cities": ["拉萨", "林芝"], "budget": 5000, "user": "U002"}, ] for task in task_queue: for retry in range(3): try: plan = generate_plan(task["days"], task["cities"], task["budget"]) save_plan(task["user"], plan) logger.info(f"用户 {task['user']} 规划成功") break except Exception: logger.warning(f"用户 {task['user']} 失败,重试 {retry + 1} 次") time.sleep(2)8. 资源占用与性能观察
8.1 Hadoop 服务内存观察
Hadoop 伪分布式启动后,最直观的问题是内存占用偏高。启动start-dfs.sh和start-yarn.sh后,可以用jps查看进程,再用top观察内存。
常见情况是 NameNode、DataNode、ResourceManager、NodeManager 四个 Java 进程分别占用几百 MB 到 1GB 内存。如果机器只有 8GB 内存,建议在hadoop-env.sh中调低 JVM 参数:
export HADOOP_HEAPSIZE=512 export HADOOP_NAMENODE_OPTS="-Xmx512m" export HADOOP_DATANODE_OPTS="-Xmx512m"8.2 Hive 查询性能观察
Hive 默认底层引擎可能是 MapReduce,小数据量下查询也要等任务调度,体感“比较慢”。如果希望查询响应更快,可以用 Spark 作为 Hive 执行引擎,也可以开启 Tez。毕设阶段如果数据量只有几千条,不用太在意性能,重点是把血缘和流程讲清楚。
写 SQL 时注意:
- 尽量在分区字段上过滤,避免全表扫描。
- 减少嵌套子查询。
- 分析结果可以预聚合写入 MySQL,不要每次展示都重跑 Hive。
8.3 Agent 接口延迟
Agent 对话接口的延迟主要来自大模型 API。如果每次交互都调用一次大模型,整体耗时可能在几秒到十几秒之间。优化思路有两个:
- 对常用景点和固定天数行程做缓存。
- 把“数据查询”和“文案润色”拆开,数据查询走本地库,文案润色再调大模型。
9. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
JAR does not exist or is not a normal file | Hive 依赖目录配置错误 | 检查 Hive 安装路径下的 lib JAR 是否存在 | 重新设置HIVE_HOME和HIVE_AUX_JARS_PATH |
| HDFS 启动后 NameNode 无法启动 | 格式化路径或 tmp 目录权限错误 | 查看/opt/hadoop/logs/hadoop-*-namenode-*.log | 删除hadoop.tmp.dir下残留目录后重新格式化 |
| 端口被占用 | NameNode 或 ResourceManager 端口冲突 | ss -lntp | 修改配置文件中的端口或关闭冲突进程 |
| Hive 连接 MySQL 失败 | MySQL 驱动或账号权限问题 | 测试 JDBC 连接 | 下载对应mysql-connector-javaJAR 放入 Hive lib 目录并授权 |
| 后端 API 调用超时 | Agent 调用大模型 API 时间过长 | 查看后端日志和 API 耗时 | 增加超时时间,缓存常用请求 |
| 批量任务卡住 | 任务依赖 HDFS 文件未就绪 | 查看日志中的任务 ID 和 HDFS 路径 | 确保文件上传成功后再触发任务 |
| 显存不足 | 如果买了本地大模型推理,显存可能不够 | nvidia-smi查看显存占用 | 改用云端 API 或减小模型规格 |
| 输出结果质量不稳定 | Agent 提示词不够明确或数据缺失 | 调整 System Prompt | 增加结构化工具调用,限制模型输出格式 |
10. 最佳实践与使用建议
第一条建议:第一周不要追求“全功能完美”,先打通“HDFS 上传 -> Hive 建表 -> 后端查询 -> 前端展示”这条主链路。主链路通了,剩下都是加分项。
目录管理要提前规划好。建议把所有模块放在一个 repo 下,按职责分目录:
tourism_agent_system/ ├── data/ # 原始数据和清洗后数据 ├── hdfs_utils/ # HDFS 上传与下载脚本 ├── hive_sql/ # 建表和分析 SQL ├── backend/ # FastAPI 后端 ├── agent/ # AI Agent 编排模块 ├── frontend/ # 可视化页面 └── docs/ # 设计文档和答辩材料批量任务一定要加日志。跑 1000 条批量生成任务时,如果没有日志,中途出错根本不知道哪条数据出了问题。用loguru或 Pythonlogging都可以,重点是记录用户 ID、任务状态、失败原因。
接口服务要注意访问范围。如果只是本地毕设演示,后端服务绑定127.0.0.1就够了;如果要部署到服务器,需要加访问控制,避免接口被外部任意调用。
AI Agent 部分要守住合规边界。系统生成的行程只能算“参考建议”,不能保证景点开放时间、门票价格和天气状况实时准确。前端页面应该加上“结果仅供参考”的说明,避免用户误把模型输出当官方信息。
数据准备阶段建议做一套“可复现数据集”。把爬虫脚本、数据清洗脚本、Hive SQL 都放在data/目录下,这样答辩时评委随时可以复现,比只看截图更有说服力。
11. 总结
这个系统最值得尝试的地方,是把 Hadoop 大数据分析、可视化、AI Agent 三件事放在了一个完整项目里。对一个毕设来说,它能覆盖的答辩点很多:HDFS 存储、Hive SQL 分析、数据清洗、后端接口设计、Prompt 工程、工具调用、多轮对话、批量任务。对想进入大数据或 AI 应用方向的开发者来说,也是一个可以快速改成简历项目的模板。
建议拿到源码或参考思路后,先做三件事:
- 第一,在本地把 Hadoop 伪分布式跑起来,确认 HDFS 和 YARN 页面能打开。
- 第二,用一份模拟的西藏旅游 CSV,走通“上传 HDFS -> Hive 建表 -> SQL 统计”流程。
- 第三,调通 FastAPI 后端和
/api/agent/plan接口,验证 Agent 能否根据参数生成路线。
最容易踩的坑集中在两个地方:Hadoop 环境配置和 Agent 提示词。前端页面、可视化图表反而都是相对成熟的技术,花不了太多时间。只要主链路通了,后续就能按需加功能。比如把 Hive 换成 Spark SQL,把模拟爬虫换成真实公开数据,把对话接口接入企业微信机器人,扩展空间很大。
如果这篇内容对你有帮助,建议收藏备用。后面我也会继续补 Hive 调优和 AI Agent 工具调用相关的实战记录。