有不少计算机专业的同学看到“Django + LLM 大模型 + 滴滴出行分析”这种组合,第一反应是:这到底是毕设还是造火箭?等真把题目拆开看,你会发现它本质上是一个“数据可视化 + 算法建模 + 大模型应用”三位一体的综合性项目,难度不低,但也没有想象中那么高不可攀。今天我就以这套出租车供需平衡优化系统为例,完整拆解一遍从选题、技术选型、数据设计到落地的全流程,把那些贯穿项目始终的坑和心得一次说清楚。
这套系统能做什么、解决了什么问题?一句话概括:基于滴滴平台开放的出行订单数据,通过大数据分析手段还原城市出租车的供需时空分布,再结合机器学习模型对短期供需缺口做预测,最终用Django搭建Web平台呈现可视化大屏,并引入大语言模型作为智能分析助手,让用户用自然语言就能查数据、看结论、拿对策。它适合计算机、大数据、人工智能方向的学生作为毕业设计,也适合想快速上手“大模型+行业应用”这套打法的开发者参考。
1. 整体设计与技术选型思路
1.1 为什么选择Django作为主框架
做毕设选Web框架,很多人会纠结Flask、FastAPI和Django。这个项目我最终推荐Django,理由很直接:Django自带Admin后台、ORM、认证体系和模板引擎,这些功能对于毕业设计来说不是“臃肿”,而是“白送的基础设施”。
Django的ORM在操作MySQL或SQLite时非常省心,尤其是数据分析结果需要落库、查询、再渲染到前端大屏的场景。你用Pandas处理完的DataFrame,可以很自然地写入Django模型对应表,前端通过API或者模板直接读取展示,整个数据流是闭环的,不会像Flask那样需要自己拼一堆SQL和路由逻辑。
另一个现实因素是答辩。Django的MVT模式架构清晰,目录结构规范,评委老师看到你的项目分层合理、代码整洁,本身就是一个加分项。再加上Django有完善的Admin后台,你可以在后台直接管理用户、管理数据、配置模型参数,演示时可操作性强,临场翻车概率低。
我见过不少同学用FastAPI写这类项目,性能确实好,但如果你需要快速出效果、又要兼顾行政后台和用户权限管理,Django的“全家桶”优势会非常明显。一句话总结:追求性能上限选FastAPI,追求交付速度和稳定性选Django,毕设的话Django是更稳妥的选择。
1.2 大模型在系统里的角色定位
“LLM大模型”在毕设里听起来很高端,但你要想清楚它到底承担什么职责,功能搞复杂反而容易失控。在出租车供需分析这个场景中,大模型常见的合理落点有三个:
第一是自然语言查询入口。用户输入“昨天晚高峰哪个区域的打车难度最大”,系统调用大模型,将这句话解析成结构化查询条件,例如时间范围、区域筛选、指标名称,再去后端SQL或API执行,最后把结果返回给用户。这个过程比传统的固定筛选项体验好得多,也给答辩增加了亮点。
第二是智能解读分析结论。供需预测模型输出一组数字,比如“未来1小时国贸区域供需缺口指数为0.82”,大模型可以自动生成一段可读性强的业务解读,告诉用户该区域需要增加多少运力、什么时段最紧张、和上周同期比有什么变化,相当于一个自动化的分析师。
第三是策略建议生成。当系统识别到某个区域的供需失衡达到阈值时,调用大模型输出调度建议和原因解释。这里要注意,不要指望大模型生成的建议能真正上生产调度系统,对于毕设来说,它更像是决策辅助和产品能力展示。
1.3 LLM必须遵守的两条红线
大模型项目最常出问题的不是模型效果,而是密钥安全和成本失控,这两点必须从架构层面提前规避。
密钥安全方面,后端调用大模型API时,密钥只能存在服务端环境变量中,任何情况下都不能下发到浏览器端或者出现在前端JS代码里。我见过有同学直接把API Key写死在Vue项目里,结果测试的时候被同学抓包抓到了,一晚上把账户额度刷爆。正确的做法是:Django后端通过 os.environ 读取密钥,对前端只暴露一个封装好的API接口。
成本控制方面,毕设阶段建议用普通版对话模型,不要开超长上下文,也不要用max_tokens很大的配置。实测下来,出租车分析的查询语句普遍在200~500个token,折算成API成本极低,但如果你不做限制、让模型的回复长度不受约束,成本很快会超标。另一个实用技巧是所有Prompt模板优先在本地拼接,尽量减少发送给模型的文本量,同时加上最大回答长度限制。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 供需平衡分析的核心方法论
2.1 什么是出租车供需失衡
要做一个供需平衡优化系统,你得先把“失衡”这个概念量化出来,否则后面所有分析都是空谈。出租车供需关系可以理解为:某个区域在某个时间段内,乘客的出行需求量和周围可用的空驶出租车数量之间的匹配度。
最理想的状态是供需相等,乘客秒上车、司机不空驶。真实世界几乎不可能,所以我们需要定义一个指标来衡量失衡程度。我推荐使用“订单响应率”加“供需缺口指数”双指标组合,这在滴滴出行等平台的公开研究中是主流做法。
订单响应率 = 成功匹配的订单数 / 用户发单总量,反映的是整体服务水平。供需缺口指数则更细化,计算公式为:
code复制supply_demand_index = (1 - order_response_rate) * log1p(wait_time + 1) * demand_intensity
其中 log1p 是为了压缩等待时间的量纲,demand_intensity 是归一化后的发单密度。指数越高,说明供需失衡越严重。这个公式的好处是它同时考虑了响应率、等待时间和需求量,比单纯看某一个指标全面得多。
2.2 时空维度的数据组织方式
出行数据天然具备时空属性,分析时你必须把“时间”和“空间”这两个维度拆开来看,再叠加分析。
时间维度上,我建议把数据粒度做到15分钟一个时段,因为出租车需求变化很快,按小时分析会严重损失细节,按5分钟分析又太碎,数据波动大、规律不明显。按一周七日区分工作日和周末,早高峰、晚高峰、夜间三个重点时段重点观察。
空间维度上,核心是按网格或区域编码聚合。滴滴公开数据集里通常带有经纬度字段,你可以用GeoHash或者自定义网格划分把连续经纬度映射到离散区域。我实际做的时候用了一个比较简便的方案:固定经纬度步长,将城市地图分割成约500米×500米的六边形网格,统计每个网格在不同时段的发单量、完单量、平均等待时间、响应率等指标,存储在中间表里供查询。
2.3 供需预测模型的选择
毕设阶段的预测模型不需要上复杂的深度学习,时序基线模型+轻量机器学习就已经足够。我常用的组合是LightGBM加时间窗口特征,效果稳定,训练速度快,可解释性好。
特征工程方面,建议构造这些类别:
- 时间特征:小时、星期、是否节假日、是否早晚高峰
- 历史特征:过去1小时、过去24小时的订单量均值、标准差
- 空间特征:该区域周边热度、区域所属商圈等级
- 天气特征:温度、降水量、风力等级,这部分如果数据集里没有,可以爬公开天气API,或者用空值填充后由模型自行忽略
预测目标设为未来15分钟的订单量或供需缺口指数,这是一个可落地的短期预测任务。用MAE或RMSE评估模型,实测误差控制在15%以内,答辩时拿这个数字说事很有说服力。
3. 系统落地实操与关键实现
3.1 整体功能模块划分
为了避免“全都要做但全都没做深”的毕设通病,我建议把系统切成四个核心模块,每个模块都能独立演示:
- 数据管理模块:负责数据集的导入、清洗、存储,提供后台管理页面
- 供需分析模块:按时段、区域输出供需热力图、订单量趋势、响应率分析
- 预测优化模块:短期订单量预测、供需缺口预警
- 大模型交互模块:自然语言查询生成、智能解读、调度建议
这四个模块组成了一条完整的数据流:原始数据 → 清洗聚合 → 分析洞察 → 预测 → 模型辅助决策 → 大模型交互,功能闭环,逻辑链条清晰,答辩时按这条线讲述,评委很容易跟上你的思路。
3.2 Django项目搭建与关键模型设计
项目结构上,建议创建一个Django项目和一个名为 analysis 的app,后续按业务功能再拆模块。关键的表结构设计如下:
用户表(User)可以用Django自带的,不必额外设计。核心业务模型重点看这几个:
- 区域表Region:维护区域编码、名称、中心经纬度
- 订单表Order:原始订单字段,包括发起时间、完成时间、上车点经纬度、行程距离
- 区域时段统计表RegionHourlyStat:按区域和时段聚合后的指标,这是分析和可视化的主要数据源
- 供需预测表PredictionResult:模型预测的结果
- 用户查询日志表QueryLog:记录用户通过大模型发起的查询,便于分析
这些模型定义完成后,用Django的迁移命令一键建表,配合Admin后台可以快速验证数据存储逻辑是否正常,比自己在数据库里手动建表高效得多。
3.3 数据清洗与聚合的核心代码实现
数据分析前最关键的一步是数据清洗,真实订单数据里的脏数据比你想象的多得多。常见的要做这几步处理:
- 删除经纬度缺失或明显越界的记录
- 过滤订单时长、订单距离为负数的异常记录
- 去除同一用户同一秒重复提交的刷单记录
- 对司机接单等待时间做对数变换,降低极端值的影响
清洗之后做聚合统计,核心代码逻辑大致是:
python复制# 以15分钟为粒度聚合区域时段指标
import pandas as pd
from django_pandas.io import read_frame
df_orders = read_frame(Order.objects.all(),
fieldnames=['order_id', 'region_id', 'timestamp', 'status', 'wait_time'])
df_orders['time_bucket'] = pd.to_datetime(df_orders['timestamp']).dt.floor('15min')
df_orders['date'] = df_orders['time_bucket'].dt.date
df_orders['hour'] = df_orders['time_bucket'].dt.hour
# 聚合订单量、完单量、响应率
daily_stats = df_orders.groupby(['region_id', 'date', 'hour']).agg(
total_orders=('order_id', 'count'),
completed_orders=('status', lambda x: (x == 'COMPLETED').sum()),
avg_wait_time=('wait_time', 'mean')
).reset_index()
daily_stats['response_rate'] = daily_stats['completed_orders'] / daily_stats['total_orders']
聚合完成后,把结果批量写入 RegionHourlyStat 表,后续所有查询和可视化都基于这张宽表进行,大幅降低前端响应延迟。
我在实际开发中用Django自带ORM做这种批量聚合其实有点慢,数据量大了以后建议直接用Pandas处理再批量 bulk_create 写库,速度提升明显。实测10万条订单数据从清洗到聚合入库,大约15秒内可以搞定。
3.4 ECharts可视化大屏的实现思路
可视化是这套系统的颜值担当,建议用ECharts实现核心大屏,比Highcharts和AntV更主流,查资料也方便。
我的页面布局方案是:顶部显示系统标题和核心KPI卡片(今日总订单量、平均响应率、当前供需缺口指数、活跃车辆数),中间用地图热力图展示各区域实时供需分布,下方分列三块:订单量趋势折线图、区域响应率排行条形图、预测结果对比图。
地图部分用ECharts的 scatter 或 effectScatter 系列做热力叠加,通过上文提到的六边形网格坐标定位,地图切换缩放时动态加载不同层级的聚合数据。
大屏的数据刷新机制我用的是前端定时请求,每30秒轮询一次后端API接口,返回最新聚合结果。这里有个经验:后端API返回的JSON字段名一定要和前端图表配置里的字段名完全一致,否则查错能查到怀疑人生。建议前后端先约定一份完整的接口字段文档再动手写代码。
4. 大模型集成中的实战问题与排查记录
4.1 自然语言转查询的Prompt工程实践
大模型在这个项目里的核心难点不是API调用,而是如何稳定地把用户自然语言转换成可执行查询。我测试了不少Prompt方案,最终稳定生效的是一套“三层结构”提示词:
- 系统层:定义角色为“数据分析助手”,明确输入输出格式
- 示例层:提供3-5组典型的用户提问和对应JSON查询结果示例
- 约束层:限定只能查询哪些字段值和时间范围,超出范围给出提示而不是编造
核心Prompt结构大致如下:
code复制你是出行数据分析助手。请将用户的自然语言查询转换为JSON格式的查询条件。
可选字段:time_range, region, indicator, comparison。
输出格式:{"time_range": "...", "region": "...", "indicator": "...", "comparison": "..."}
如果用户问题不在可选范围内,返回 {"error": "无法识别的查询"}
示例1:用户:“昨晚7点国贸附近好不好打车?”
输出:{"time_range": "yesterday 19:00", "region": "国贸", "indicator": "response_rate", "comparison": "none"}
注意在“约束层”里一定要给大模型一个“不知道就拒答”的口子,不然模型会硬编一个看似合理的错误结果,这对系统来说是很严重的信任问题。实测加了约束层之后,查询解析准确率能从70%左右提升到90%以上。
4.2 API调用失败与异常中断的排查记录
集成过程中踩过的坑主要在这几个环节,单独列出来供大家排查时参考。
第一是密钥相关报错。Django后端读取密钥后,如果出现“401 Unauthorized”错误,优先检查是否在代码中误加了空格或换行。我碰到过一次,os.getenv 读出来的密钥带了一个换行符,导致所有请求都鉴权失败,排查了很久。解决方案是在读取时统一 strip() 掉首尾空白。
第二是请求超时问题。当用户问得太复杂、Prompt过长时,模型响应时间会超过后端默认请求超时时间。这里需要在调用大模型API时显式指定超时参数,我设置在60秒以上,同时前端配合loading状态避免用户重复点击。
第三是返回非结构化文本。大模型返回结果有时会带Markdown标记,解析JSON时直接抛异常。后来我强制在Prompt里加了一条“只输出JSON,不要添加任何解释和Markdown”,并在代码里写了一个容错解析函数,先尝试标准 json.loads,失败再尝试提取所有大括号内容重新解析。
4.3 数据隐私与内容合规的自检机制
这一块容易被忽略,但很重要。系统里会存用户的查询记录和部分订单数据,虽然毕设用的脱敏数据,但前端大屏展示的时候我仍然做了两个处理:一是所有地图热力图的数值只展示相对热度等级,不展示具体订单明细;二是用户查询日志表只记录查询时间和问题摘要,不做关键信息的持久化。
另外,大模型生成长文本时可能出现内容不可控的情况。我在系统里做了一层简单的敏感词过滤和长度限制,对模型输出做前置校验,超过设定长度自动截断。虽然做不到商业级内容审核,但作为毕设来说已经体现了一定的工程完整性。
5. 常见问题速查表与避坑经验
5.1 常见问题与排查方案速查表
| 问题现象 | 可能原因 | 排查思路与解决方案 |
|---|---|---|
| 前端ECharts地图不显示 | 地图GeoJSON数据路径错误 | 检查地图JSON文件是否在static目录下,F12看Network请求是否404 |
| 大屏接口返回慢 | 聚合SQL没有走索引 | 给RegionHourlyStat表的region_id和hour字段加联合索引 |
| LLM返回JSON解析失败 | Prompt未约束输出格式 | 增加“只输出JSON”约束;代码侧增加容错解析函数 |
| 预测结果全部偏向平均 | 特征缺少周期项 | 增加星期、节假日、近1小时均值特征,避免只用时间戳 |
| 热力图数据覆盖不全 | 网格划分与坐标系统不一致 | 确认经纬度统一使用WGS84坐标系,转换后再做聚合 |
| 密钥泄露风险 | 前端代码中硬编码API Key | 密钥只放服务端环境变量,前端仅调用后端封装API |
5.2 调试阶段最实用的三个技巧
第一个技巧是“先本地打印再连库”。我在项目前期会把所有Pandas聚合结果先 print 出来核对,确认字段名和数值无误,再写库。直接连数据库调试很容易被类型和空值问题绕进去,效率很低。
第二个技巧是“先用真实数据的一小块做功能验证”。比如先选一个热门时段、两个重点区域做全流程联调,确认无误后再扩展到全量数据。全量数据跑起来耗时很久,一旦报错很难定位是数据问题还是代码问题。
第三个技巧是“用Django的Debug Toolbar监控SQL查询次数”。这个工具能直观看到每个页面的SQL执行次数和耗时。很多响应慢的问题不是Python代码慢,而是ORM查询次数太多,N+1查询在数据量大时非常致命。
5.3 关于版本依赖的一点忠告
Django当前主流版本是4.x/5.x,LLM相关的Python依赖库更新也很快。强烈建议在项目开始时就用虚拟环境管理依赖,并导出一份 requirements.txt:
bash复制pip freeze > requirements.txt
很多同学做到一半发现项目跑不起来,不是代码问题,是因为依赖版本冲突。把环境锁死,后续部署和答辩演示都会省很多心力。如果怕包冲突,另一个方案是直接用Anaconda管理Python环境,实测在Windows上跑Django项目体验更顺滑。
6. 后续扩展建议
如果做完上面这些还有精力,有几个扩展方向不会增加太多工作量,但能让项目档次再上一层。
一个是把预测模型换成时序模型对比实验。比如在现有LightGBM基础上,加一个Prophet的预测结果做对比,答辩时展示多模型效果对比,这属于“算法深度”上的加分项。
另一个是打通Django Rest Framework提供纯净API,把前后端完全分离。如果你想往全栈方向展示,前端用Vue3写大屏页面,后端用DRF提供接口,整体架构更现代,也方便后续扩展移动端。
再有一个方向是引入流处理概念,用Redis或者消息队列模拟“准实时”订单数据流,而不是一次静态导入。这可以让系统演示效果更逼真,数据刷新看起来是动态的。
我个人在实际操作中的体会是:这类综合性毕业设计项目,最关键的不是每个模块用到多牛的技术,而是把数据流完整串通,让每个模块之间衔接自然、有逻辑。你不需要真的做出一套滴滴级别的调度系统,但你要让评委看到你对数据采集、清洗、存储、分析、建模、可视化和智能化应用这套完整链路有清晰的认知和实践能力。
最后再分享一个答辩技巧:演示的时候先跑通一个“用户提问 → 大模型解析 → 后端查询 → 图表联动展示 → 模型给出预测结论 → 大模型生成优化建议”的完整场景,这一套流程走下来,项目亮点基本全展示了。剩下的细节问题,评委问什么你答什么,整套系统的逻辑闭环就是你最有力的底气。
