基于Django与LLM的出租车供需平衡优化系统解析
1. 项目概述1.1 核心需求解析最近有不少读者在后台问我关于大数据方向毕业设计怎么选题的事情尤其是那种看起来有技术含量、做起来又不至于劝退的题目。说实话传统的图书管理系统、商城系统这类CRUD项目在答辩时已经很难拿高分了而纯算法类项目又容易陷入调参调到头秃的窘境。今天要拆解的这套基于Django与LLM大模型的出租车供需平衡优化系统算是我认为目前毕设选题里性价比很高的一条路线——既有Django Web开发的完整工程实践又踩中了大数据分析和LLM大模型这两个当下最热的技术点而且数据源用滴滴出行开放数据集真实、可获取、有故事可讲。这个题目的本质是做一套出租车供需分析预测平台从历史订单数据中挖掘城市不同区域、不同时段的出行规律构建供需失衡的识别模型与预测模型同时借助大模型能力将复杂的分析结果转化为通俗易懂的自然语言报告与优化建议。换句话说它既有一个完整的数据分析链路——数据采集、清洗、特征工程、建模、预测又有一个像样的Web应用外壳——Django框架下的可视化大屏、权限管理、报告生成还巧妙地融入了LLM——让系统不止于展示图表而是能像一位行业分析师一样输出有洞察力的结论。那么这套系统究竟适合谁来参考如果你是计算机、大数据、软件工程等专业的应届毕业生正在为毕设选题发愁或者已经选了相关方向但不知道从何下手这篇文章都能给你一个可落地的完整参考。我会把项目的整体设计思路、核心算法实现、LLM接入方案、常见坑点都拆开讲一遍内容尽量保持拿到就能照着做的粒度。1.2 技术栈选型方向这个题目定下来之后技术选型上其实有几种不同路线但眼下这套组合是比较成熟的选择后端框架Django。Django自带了Admin后台、ORM、认证体系、模板引擎这些对于毕设项目来说都是现成的免造轮子组件。相比FlaskDjango的项目结构更规整写出来的代码可展示性强答辩时也更容易讲清楚我是怎么设计的。而且Django的MTV模式本身就是基础课考点写在论文里顺理成章。大模型接入LLM API。LLM在整个系统里承担的是智能分析报告生成与自然语言交互问答的角色。国内可选的大模型API已经非常成熟文本生成质量和成本控制都符合学生项目预算具体选择可以结合自己已有的资源来定。数据分析与建模Pandas Scikit-learn LightGBM。数据清洗、特征工程用Pandas是标配供需预测模型用LightGBM或XGBoost这类梯度提升树模型在小规模数据集上表现稳定调参空间也够论文里写几页实验对比。前端可视化ECharts Bootstrap。Django模板配合ECharts做数据可视化大屏非常顺手图表种类丰富、文档完善不需要单独搭前后端分离架构降低了整体复杂度。GIS可视化Leaflet 高德/百度地图。出租车数据天然带有经纬度坐标地图热力图是展示空间供需分布的最佳方式。这套组合选型的核心逻辑是尽量用成熟稳定的组件把非核心环节快速搞定把主要精力留给数据分析供需预测LLM融合这三个真正能拿分的地方。2. 系统整体设计与功能拆解2.1 系统功能模块规划我先把这个系统的功能结构完整列出来大家对着看会更有全局感。数据管理模块数据导入支持CSV/Excel、数据预览与清洗规则配置、数据质量报告缺失值/异常值统计、数据备份与导出。供需分析模块时间维度的供需趋势分析按小时/星期/月份聚合、空间维度的供需热力分布按地理网格或行政区聚合、供需失衡指数计算与区域排名。供需预测模块基于历史数据构建订单量预测模型支持短时预测未来1-6小时和日级预测预测结果与实际值对比评估。智能报告模块调用LLM生成日报/周报风格的供需分析报告内容涵盖整体态势、异常区域、优化建议支持报告历史存档。交互问答模块用户用自然语言提问如周五晚高峰哪个区域最难打车系统借助LLM数据查询能力返回答案。系统管理模块基于Django自带User模型扩展角色权限管理员/普通用户操作日志记录数据字典维护。这套功能设计相对完整覆盖面广论文里每个模块都能对应一个章节来写。而且模块之间的逻辑线是比较清晰的数据是基础分析和预测是核心LLM报告是亮点权限管理是工程规范性展示答辩时有故事线可讲。2.2 Django项目结构与MTV模式落地Django的MTV模式Model-Template-View在这类数据类项目中怎么落地很多初学者容易搞混。我的经验是把分析计算这类重逻辑放到独立的service层而不是全部塞进View函数里否则项目到后期会非常难以维护。建议结构如下taxi_project/ ├── manage.py ├── config/ # 项目配置 │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── apps/ │ ├── data_manager/ # 数据管理模块 │ ├── analysis/ # 供需分析模块 │ ├── prediction/ # 供需预测模块 │ ├── llm_report/ # 智能报告与大模型接入 │ ├── chat/ # 交互问答模块 │ └── system/ # 系统管理、权限 ├── static/ ├── templates/ └── scripts/ ├── data_clean.py # 数据预处理脚本 ├── feature_engineering.py ├── train_model.py # 模型训练脚本 └── llm_service.py # 大模型API封装View层只负责接收HTTP请求、调用service层方法、组织上下文数据、渲染模板这样代码读起来非常清爽。Model层用Django ORM定义核心表结构但要注意分析用的中间结果表不要和原始数据表混在一起建议用单独的表前缀区分。2.3 为什么选这些组件而不是其他方案这里我想认真展开一下选型逻辑因为答辩时老师大概率会问你为什么用这个不用那个。先说Django vs Flask。Flask确实更轻量、上手更快但正因为灵活项目结构全靠自己约定很多同学写到中期代码就开始各模块各的写法。Django则用框架强制约束了项目结构Model/Template/View/URL分层清晰配合自带Admin后台演示效果也更好。管理后台在答辩演示时是很加分的现场改一条数据、刷新页面看变化直观又有说服力。对于毕设来说工程规范性本身就是评分项Django在这方面天然占优。再说LLM的接入方式。现在很多毕业设计动不动就说基于大模型但实际情况是本地部署一个7B/13B模型对显存的要求就已经很现实了更别说微调。我的建议是项目主体用成熟的在线模型API论文里可以同时讨论API调用方案和本地部署轻量模型方案的对比这样既展示了工程落地能力又体现了对前沿技术的理解。这就像你在论文里写考虑到部署成本与推理速度系统采用API方案但针对离线环境设计了基于量化模型的替代实现这种表述在答辩时很占便宜老师会觉得你的思考层面是清晰的。可视化选ECharts而不是Highcharts或D3理由也很简单ECharts对中国地图、地图热力图的支持友好中文文档健全社区案例多遇到问题基本都能搜到答案。D3虽然更强大灵活但学习成本陡增对于毕设这种时间有限的项目并不划算。记住一个原则毕业设计的目标是完整地跑通并讲清楚不是用最底层的技术重造轮子。3. 数据准备与预处理实战3.1 数据来源与结构说明滴滴出行曾经开放过GAIA计划数据集包含了成都市、西安市等多个城市的订单数据这是目前最适合做出租车供需分析的公开数据集之一。不过需要注意这些数据有时效性在正式动手之前建议先确认数据源的可访问性。如果原始数据集无法获取也可以退而求其次使用纽约出租车数据集TLC Trip Record Data作为替换字段粒度基本一致分析思路完全可以复用。GC格式的订单数据主要字段如上图所示假设已在页面中展示此外可能还有气象数据可作为外部特征。整体数据字段可以分为订单标识、时间、位置、金额四类在特征工程阶段需要从时间和位置这两个维度重点做扩展。在论文中这部分可以专门用于解释数据集的规模与字段含义体现对数据的敏感性。3.2 数据清洗的完整流程与常见坑这里把我在实际清洗过程中踩过的坑逐一说明附上可复用的判断标准与处理策略。缺失值处理要分场景不能一删了之原始数据中经纬度空缺、订单金额为0、乘客数为0这类脏数据很常见。我的处理策略是核心坐标字段缺失的直接删掉因为后续做GIS聚合时坐标是硬依赖但时间字段缺失的可以考虑用相邻记录插值填充。实际清洗中有一个容易忽略的细节——数据集中存在大量司机取消和乘客取消的订单记录这类记录是否保留需要结合你分析的业务目标来决策如果研究的是订单需求规模那所有发起的订单都应该算入需求侧如果研究的是实际服务供给则只应保留司机到达并完成服务的订单。这个取舍必须在论文里明确说明。异常值识别用业务规则打底3σ准则只能做辅助出租车订单金额的分布带有明显的重尾特征直接用3σ准则会把大量真实的高价订单误杀。我的做法是先按业务规则排除比如订单时长超过8小时、金额超过800元的基本可以判定为异常或数据错误再做分位数截断比如取99.5%分位数作为上限。表4给出了实测中整理出的异常规则示例可作为论文附表的素材。坐标偏移问题必须处理原始数据里的经纬度通常是GCJ-02坐标系直接画在地图上会偏移。在实现地图可视化时不能跳过坐标转换这一步。Python里可以用coordinates_converter这类库做WGS-84与GCJ-02之间的互转虽然原理不复杂但没处理的话地图热力层会整体错位。这点不用太早做到地图可视化和GIS聚合那一步之前完成就行。时间字段标准化原始数据的时间字段有时是字符串格式且存在时区问题。建议统一转为datetime类型并全部转换为东八区时间然后拆出hour、weekday、is_holiday等特征列单独存储这样后续聚合分析时会快很多。3.3 特征工程从原始字段到模型输入特征工程是数据挖掘里最花时间、也最影响模型效果的环节。我先给一个基础的特征清单大家可以根据实际数据情况扩展。时间类特征小时0-23、星期几0-6、是否周末、是否节假日、一天中的时段凌晨/早高峰/午间/晚高峰/夜间、月份季节性编码。空间类特征经纬度所属的地理网格ID比如按500m×500m划分、所在行政区编码、距离市中心距离、区域POI密度写字楼/住宅/商圈数量如果能拿到POI数据的话。供需特征该区域在时间窗口T内的订单需求量发起订单数、完成订单量、供需比、取消率、平均响应时长、周边可用车辆密度估算。滞后特征与滑动窗口特征前1小时、前2小时、前24小时同时段的订单量用于捕捉时间序列的自相关性。气象特征可选温度、降水、风力等级。天气对打车需求的影响是实打实的雨天晚高峰的订单量通常比晴天高20%以上这个特征在论文实验里也容易出彩。其中供需比和取消率是刻画供需失衡的核心指标。我在项目里把供需失衡指数定义为supply_demand_ratio 完成订单量 / (完成订单量 未响应订单量) imbalance_score (1 - supply_demand_ratio) * (需求总量归一化值)^0.5这个公式的逻辑是失衡程度既跟没被满足的需求比例有关也跟需求规模有关。一个区域一小时内有500单需求、只有50单被满足和另一区域有50单需求、5单被满足虽然未满足比例都是90%但前者显然影响更大、更需要调度资源介入所以用需求总量做加权。这个指标本身就是一个可以写进论文里的创新点不需要多高深逻辑自洽即可。4. 供需预测模型构建与调优4.1 问题建模这是回归问题而不是分类问题这个项目中的预测目标就是未来某个时间窗口内某个区域的订单需求量或供需失衡指数本质是回归问题。如果要做分类可以退一步定义为是否会发生供需失衡但回归能给的信息量更大答辩时也更好展开分析。建议主模型做回归预测附带一个阈值判断逻辑输出失衡预警即可。4.2 模型选型LightGBM是性价比之选我建了几个模型做了对比线性回归作为baseline、随机森林、XGBoost、LightGBM以及一个简单的LSTM做时间序列对比。在同样的特征集下实测结果是LightGBM和XGBoost明显优于线性回归而LightGBM的训练速度又比XGBoost快一截处理缺失值的能力也更强。所以我最终主模型选的是LightGBM。以下是一个可复用的核心训练代码骨架。import lightgbm as lgb from sklearn.model_selection import TimeSeriesSplit from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score # 假设 df 已经过特征工程target_col 为目标列 feature_cols [c for c in df.columns if c not in [target, order_id, timestamp]] X df[feature_cols] y df[target] # 时间序列交叉验证注意不能用普通的KFold避免数据泄漏 tscv TimeSeriesSplit(n_splits5) params { objective: regression, metric: rmse, learning_rate: 0.05, num_leaves: 31, max_depth: -1, min_child_samples: 20, feature_fraction: 0.8, bagging_fraction: 0.8, bagging_freq: 1, verbosity: -1, } for fold_idx, (train_idx, val_idx) in enumerate(tscv.split(X)): X_train, X_val X.iloc[train_idx], X.iloc[val_idx] y_train, y_val y.iloc[train_idx], y.iloc[val_idx] train_set lgb.Dataset(X_train, labely_train) val_set lgb.Dataset(X_val, labely_val, referencetrain_set) model lgb.train( params, train_set, num_boost_round500, valid_sets[val_set], callbacks[lgb.early_stopping(50), lgb.log_evaluation(100)] ) y_pred model.predict(X_val, num_iterationmodel.best_iteration) print(fFold {fold_idx}: MAE{mean_absolute_error(y_val, y_pred):.2f}, fRMSE{mean_squared_error(y_val, y_pred, squaredFalse):.2f}, fR2{r2_score(y_val, y_pred):.4f})时间序列交叉验证的处理要注意一个关键点切分时绝对不能打乱顺序必须保证训练集的时间范围在验证集之前。否则模型会偷看未来在论文实验里给出虚高的指标就很被动了。上面代码里用TimeSeriesSplit就是干这个事的。4.3 供需失衡预测的工程实现细节预测层面还有几个细节值得说明一下。维度选择与数据聚合。如果按每小时×每个网格区域作为一条训练样本一天24小时、一个城市划分1000个网格、统计30天数据就有72万条样本这个量级对LightGBM来说非常轻松。聚合粒度建议不要低于500m网格否则样本稀疏会导致预测结果噪声很大。训练/验证/测试集的时间划分。建议前70%做训练、中间15%做验证用于early stopping和调参、最后15%做测试。测试集必须是模型从未见过的未来数据这样得到的评估指标才有说服力。分区域训练还是全局一个模型。我实测下来的结论是全局一个模型、把区域ID作为特征模型的鲁棒性更好因为数据量更充足也能学到区域之间的共性规律。分区域单独训练的效果在热门区域会略好但冷门区域因为数据太少效果很不稳定。毕设项目推荐全局模型方案逻辑更简单效果也更能打。4.4 模型解释用SHAP补上学术说服力现在的答辩老师越来越关注模型可解释性尤其是你用了树模型几乎必问哪些特征最影响预测结果。SHAPSHapley Additive exPlanations是解释树模型最通用的工具画一张特征重要性的summary plot再挑一个典型样本做force plot这部分能显著提升论文的专业度。import shap explainer shap.TreeExplainer(model) shap_values explainer.shap_values(X_val) # 特征重要性概览 shap.summary_plot(shap_values, X_val, feature_namesfeature_cols)实测下来前1小时同时段订单量和是否为晚高峰时段这两个特征在重要性排名中通常是数一数二的其次是区域历史平均需求量。这个结果在业务逻辑上也说得通打车需求本身就带有强周期性和惯性你完全可以围绕这个发现去写一段有信息量的业务分析。5. LLM大模型在系统中的融合实现5.1 LLM在系统里到底扮演什么角色有些同学可能会疑惑LLM和出租车供需分析之间到底怎么融合纯粹把数据分析做成图表LLM就没有存在感但如果只是接一个聊天机器人又显得生硬。我在这套系统里给LLM规划了两个角色数据分析师和交互问答助手。所谓数据分析师就是系统定期把核心指标——总订单量、供需失衡Top5区域、异常波动、环比变化——封装成结构化的JSON数据然后作为上下文发送给LLM让它生成一段类似本周出行供需分析周报的自然语言报告。这个报告不是泛泛而谈而是要基于真实数据得出的具体结论比如周五18:00-20:00天府广场周边区域供需失衡指数高达0.73建议增加30辆调度车辆。这需要精心设计Prompt确保LLM严格基于数据说话不瞎编。所谓交互问答助手则是让用户可以用自然语言查询系统数据比如昨晚哪个区域打车最难系统先把问题翻译成数据查询动作拿到结果后再交给LLM组织成回答返回。这样可以确保回答都有真实数据支撑而不是模型凭空生成。5.2 大模型接入的完整链路与代码实现接入大模型API并不复杂关键是怎么把链路设计得干净、可扩展。我在项目里做了一个llm_service.py模块统一封装所有大模型调用逻辑项目中其余部分都通过这个模块与模型交互避免在View层散落一堆API调用代码。import json import requests class LLMService: def __init__(self, api_key, base_url, model_name): self.api_key api_key self.base_url base_url self.model_name model_name def chat(self, messages, temperature0.3, max_tokens2000): headers { Content-Type: application/json, Authorization: fBearer {self.api_key} } payload { model: self.model_name, messages: messages, temperature: temperature, max_tokens: max_tokens } resp requests.post( f{self.base_url}/chat/completions, headersheaders, jsonpayload, timeout60 ) resp.raise_for_status() return resp.json()[choices][0][message][content] def generate_analysis_report(self, metrics_json: str) - str: prompt f你是一名城市交通数据分析专家。请根据以下系统统计的数据指标 生成一份简洁的供需分析报告。要求 1. 只基于给定数据进行分析不要编造数据。 2. 指出供需失衡最严重的区域和时段。 3. 给出可操作的调度优化建议。 4. 报告控制在400字以内。 数据指标 {metrics_json} messages [{role: user, content: prompt}] return self.chat(messages, temperature0.3)5.3 Prompt设计与输出稳定性控制LLM在实际使用中最大的问题不是不会说而是胡说以及同样的输入每次输出不稳定。这两个问题解决思路如下。关于避免胡说核心是让LLM做基于数据的总结而不是开放式创作。你需要把分析结论事先在代码侧算好比如区域排名、趋势变化幅度、环比增长率然后把它当作事实告诉LLM要求它只能基于这些事实来组织语言。也就是说关键结论不是让LLM算出来的而是让它润色表达。这样即使它发挥不稳定核心数据也差不到哪去。另一个有效做法是在Prompt中反复强调没有提供的数据不要提及并且把temperature调低比如0.2-0.3减少生成随机性。关于输出稳定性推荐让LLM返回JSON结构化数据再加一层解析和校验。比如要求输出{ summary: 本周整体供需基本平衡但周五晚高峰出现明显失衡..., hotspots: [ {region: 天府广场, time: 周五18:00-20:00, imbalance_index: 0.73, suggestion: 增加调度车辆30辆} ], trend: 环比上周整体订单量上升5.2% }然后用json.loads解析再渲染到前端页面。如果解析失败就catch异常重新调用一次或者降级为只展示图表不展示报告。这个降级机制在答辩演示时特别重要——万一大模型API临时抽风系统页面不能白屏你得有一个fallback方案。5.4 让LLM接入更稳的几个工程细节设置超时与重试大模型API通常不是100%可用需要设置请求超时时间建议30秒以上模型生成耗时较长并做重试。我一般做3次重试退避间隔为1s、2s、4s。缓存历史报告系统每天的自动分析结果建议落库保存。一方面方便用户查看历史报告另一方面也减少了重复调用API的成本。成本控制毕设没有预算压力时每天自动生成一次报告就够了不要在页面刷新时反复调用API。实测下来可以控制在一个较低的成本区间内。密钥管理API密钥绝对不能硬编码在settings.py里更不能提交到Git仓库。建议写入环境变量或者独立的.env文件并在.gitignore中排除。我之前看到不少开源项目因为密钥泄露被恶意刷爆账单的案例这个细节要养成习惯。Prompt版本管理调试Prompt时会频繁修改模板建议把Prompt模板独立成文件或数据库记录加上版本号方便回溯。这也是工程规范化的一种体现。6. 可视化大屏与地图交互实现6.1 大屏的整体布局可视化大屏的设计逻辑应该是一屏看全局层层下钻看细节。我采用的布局是顶部全局指标卡片当日订单总量、当前供需比、活跃车辆数、失衡预警数量中部主区域地图用热力图展示各区域实时供需情况红色代表供不应求绿色代表供大于求颜色越深表示失衡程度越高右侧纵向面板Top5失衡区域排名、24小时供需趋势折线图、区域下钻分析的详情弹窗底部横向面板近7天订单量柱状图、近7天供需失衡指数趋势、模型预测值与实际值对比曲线。大屏的精髓不在于花哨而在于信息层级清晰能让观者第一眼就抓住核心结论。做好这块的关键是对齐卡片之间的间距、图表的主题色、字体大小要保持一致统一用深色科技风主题比较显质感。6.2 ECharts地图热力图的实现ECharts做地图热力图有两种方式一种是基于geo坐标系的散点图加visualMap组件另一种是基于百度/高德地图的bmap扩展。前者不需要外网地图服务部署简单推荐用于毕设后者视觉效果更好但依赖地图SDK的key申请。// 基于ECharts geo坐标系的供需热力图示例 var chart echarts.init(document.getElementById(mapContainer)); $.getJSON(/api/supply_demand_heatmap/?date2026-01-01, function (data) { var option { tooltip: { trigger: item, formatter: function (params) { return 区域: params.name br/供需失衡指数: params.value[2]; } }, visualMap: { min: 0, max: 1, left: 20, bottom: 20, text: [高, 低], calculable: true, inRange: { color: [#50a3ba, #eac736, #d94e5d] } }, geo: { map: chengdu, roam: true, itemStyle: { areaColor: #1a2b3c, borderColor: #4a6b8a } }, series: [{ type: scatter, coordinateSystem: geo, data: data.points, symbolSize: function (val) { return Math.max(5, val[2] * 20); } }] }; chart.setOption(option); });这里有个细节ECharts内置的成都地图数据可能需要额外注册你需要从ECharts map数据仓库里找到对应的GeoJSON文件加载一下。如果找不到精确到区县的地图用四川省地图或者自绘网格热力图效果也行。网格热力图的做法是用Leaflet leaflet.heat插件实现渲染起来很平滑布局上可以跟ECharts图表互补。6.3 数据刷新的方案选择因为数据不是实时流式的滴滴的开放数据集是历史数据没必要做WebSocket实时推送。我的做法是每5分钟用Ajax轮询一次后端接口拉取最新计算结果这个方案简单可靠完全够用。当然如果你后续要接入真实订单流数据源再考虑用Django Channels做WebSocket也不迟但这不是毕设阶段的重点。7. Django系统实现与部署避坑7.1 核心Model设计与ORM使用Django的ORM在这个项目里主要承担数据存储与查询的任务。核心Model设计如下按模块拆分from django.db import models class OrderRecord(models.Model): 原始订单数据表 order_id models.CharField(max_length64, uniqueTrue, verbose_name订单ID) start_lat models.FloatField(verbose_name出发纬度) start_lng models.FloatField(verbose_name出发经度) end_lat models.FloatField(nullTrue, blankTrue, verbose_name到达纬度) end_lng models.FloatField(nullTrue, blankTrue, verbose_name到达经度) start_time models.DateTimeField(db_indexTrue, verbose_name出发时间) end_time models.DateTimeField(nullTrue, blankTrue, verbose_name到达时间) order_amount models.FloatField(default0, verbose_name订单金额) order_status models.CharField(max_length16, defaultcompleted, verbose_name订单状态) class Meta: db_table order_record indexes [ models.Index(fields[start_time, start_lng, start_lat]), ] class AreaGrid(models.Model): 地理网格区域定义表 grid_id models.CharField(max_length32, uniqueTrue, verbose_name网格ID) center_lat models.FloatField(verbose_name中心纬度) center_lng models.FloatField(verbose_name中心经度) district models.CharField(max_length64, blankTrue, verbose_name所属行政区) class SupplyDemandStat(models.Model): 供需统计结果表按小时网格粒度 grid models.ForeignKey(AreaGrid, on_deletemodels.CASCADE, verbose_name网格区域) stat_date models.DateField(db_indexTrue, verbose_name统计日期) hour models.IntegerField(verbose_name小时) demand_cnt models.IntegerField(default0, verbose_name需求订单量) completed_cnt models.IntegerField(default0, verbose_name完成订单量) cancel_cnt models.IntegerField(default0, verbose_name取消订单量) imbalance_score models.FloatField(default0, verbose_name供需失衡指数) class Meta: db_table supply_demand_stat unique_together (grid, stat_date, hour) class PredictionRecord(models.Model): 模型预测结果表 grid models.ForeignKey(AreaGrid, on_deletemodels.CASCADE, verbose_name网格区域) predict_date models.DateField(db_indexTrue, verbose_name预测日期) predict_hour models.IntegerField(verbose_name预测小时) actual_value models.FloatField(nullTrue, blankTrue, verbose_name实际值) predict_value models.FloatField(verbose_name预测值) is_alert models.BooleanField(defaultFalse, verbose_name是否预警) class ReportRecord(models.Model): 大模型分析报告表 report_type models.CharField(max_length16, verbose_name报告类型) report_date models.DateField(db_indexTrue, verbose_name报告日期) content_json models.TextField(verbose_name报告内容JSON) created_at models.DateTimeField(auto_now_addTrue, verbose_name生成时间)需要留意的是原始订单表数据量比较大几十万到几百万行Django ORM的常规查询如果没有索引会很慢。建议对start_time、start_lng、start_lat建联合索引并且在大量写入时用bulk_create而不是逐条save()。另外分析用的中间计算结果建议优先落库这样每次页面加载直接查结果表不至于每次都重新跑全量聚合计算。7.2 数据分析接口的封装一个合理的后端接口设计是前端所有图表统一走/api/前缀的JSON接口页面本身只负责渲染。推荐的接口列表GET /api/summary/ # 顶部指标卡片 GET /api/supply_demand_heatmap/ # 地图热力图数据 GET /api/imbalance_top/ # Top失衡区域排名 GET /api/trend/?dimensionhour # 时间趋势 GET /api/prediction/compare/ # 预测与真实值对比 GET /api/llm/report/ # 大模型生成报告 GET /api/chat/?queryxxx # 自然语言问答接口层用Django的JsonResponse返回查询逻辑放到service层Controller只负责参数校验和数据透传。这样即使后续要把前端换成Vue后端也不需要大改。7.3 权限系统实现停靠站权限验证这块这次要展开讲一下。Django自带的认证系统有User、Group、Permission模型但默认的权限粒度只到Model级——也就是你能控制某类用户能否增删改查某张表但控制不了这个用户只能看成都的数据、不能看其他城市的数据。对于毕设来说Model级权限其实已经够用。做一个简单的装饰器统一校验即可from django.contrib.auth.decorators import login_required from django.core.exceptions import PermissionDenied def role_required(allowed_roles): def decorator(view_func): login_required def wrapper(request, *args, **kwargs): if request.user.role not in allowed_roles: raise PermissionDenied return view_func(request, *args, **kwargs) return wrapper return decorator然后给User模型加一个role字段管理员/分析师/访客在View上标注允许的角色即可。这个设计在论文里可以写基于RBAC的权限管理——选定角色的访问控制算是一个标准的加分小点。7.4 本地部署与Windows环境常见坑最后聊一聊部署环节的坑这可能是整个项目里最折磨人的部分之一。如果你是Windows环境开发调试以下问题最常见Python版本兼容性多个版本并存时Django 4.x建议Python 3.10LightGBM在Windows下的pip安装一般没太大问题但如果你装的是旧版Python 3.7编译LightGBM依赖时可能报错。建议直接用3.10或3.11省去不必要的折腾。数据库选择开发阶段用SQLite足够但数据量上百万后写入和查询明显变慢。建议项目一开始就配置MySQL实测百万级数据下查询体验有明显差距。Windows装MySQL要注意编码问题建库时统一用utf8mb4避免中文乱码。静态文件不加载Django在DEBUGFalse时默认不提供静态文件服务需要额外配置whitenoise中间件这个很多人都踩过坑。开发阶段保持DEBUGTrue即可部署时再处理。生产部署组合用waitress代替runserverWindows下比gunicorn省心Nginx做反向代理和静态文件服务。这套组合在Windows环境实测下来是相对稳妥的。pip install waitress waitress-serve --listen127.0.0.1:8000 config.wsgi:application顺便说一句部署这块不用追求上云,把本机环境跑通、能在答辩现场稳定演示就已经完成任务了。8. 常见问题与排查技巧实录这节我按问题现象 → 排查思路 → 解决方案的格式整理一个速查表都是我在开发过程中真实踩过的坑希望帮大家节省排查时间。问题现象排查思路解决方案数据导入慢、导入内存爆掉一次性读入整个CSV再逐条入库分批读入Pandas的chunksize10000用bulk_create批量写入或先转存Parquet再用Django读页面图表加载特别慢SQL没有走索引查询全表扫描给时间、坐标字段建联合索引把聚合结果预计算到SupplyDemandStat表页面只查结果表ECharts地图不显示地图GeoJSON未注册或坐标系不对确认ECharts版本对应的地图注册方式检查经纬度坐标是否统一大模型返回内容不稳定未约束输出格式、temperature过高固定JSON输出格式temperature降到0.3以下Prompt中明确只基于数据回答LLM API超时生成时间较长默认请求超时太短设置timeout为60秒并实现3次重试页面端同步改为异步任务生成报告中文乱码数据库编码不是utf8mb4MySQL建库时指定utf8mb4字符集CSV导入时统一指定encodingutf-8模型预测指标虚高交叉验证时乱序切分导致数据泄漏改用TimeSeriesSplit确保训练集时间在验证集之前部署后静态文件404Django在DEBUGFalse时不自动提供静态文件配置whitenoise中间件或由Nginx直接托管static目录本地运行正常部署后地图接口跨域报错前端域名与后端API域名不同Django增加corsheaders中间件或在Nginx配置反向代理同域访问提交论文前突然模型效果变差数据预处理或特征代码有不可复现的随机步骤固定全局随机种子random.seed(42)保存模型时记下版本号和特征列名另外还有两个独家经验想多说一句。第一个是关于模型文件的管理。训练好的模型建议用joblib或pickle保存下来命名带上版本号和关键参数比如lgb_v3_hourly_20260101.pkl。我见过不少同学训练完模型没保存写论文时想重新跑一遍实验结果环境依赖变了、数据变了再跑出来的指标对不上非常被动。保存模型后预测接口直接从文件加载模型推理就行不必每次启动Django都重新训练。第二个是关于答辩演示的稳定性。答辩现场最怕两件事一是网络波动导致LLM调不动二是数据库启动失败导致页面打不开。建议准备一个离线演示方案把核心图表结果预渲染成图片把大模型报告提前生成好存在数据库里就算现场断网也能正常讲完整个故事。这不是偷懒而是一种风险意识。9. 个人实操心得与扩展建议最后聊几句掏心窝的话。这个题目做到后期我最大的感受是真正让这套系统区别于普通数据分析项目的不是某个单个技术点有多深而是**数据分析结论 — 大模型表达 — 业务优化建议这条链路的完整性**。很多毕设做到最后就是一堆图表一个网页数据结论和分析过程是割裂的。而这套系统通过LLM报告模块把数据说了什么和我们应该怎么做串了起来这在答辩时是一个非常容易引发老师兴趣的亮点。当然这个项目还可以往几个方向继续扩展。如果时间和精力允许可以做实时数据接入对接模拟的订单流数据把轮询改成WebSocket推送让大屏真正动起来也可以把单城市的模型扩展到多城市做一个城市间供需特征的对比分析还可以尝试用时序模型比如Prophet、Informer做更长期的需求预测跟LightGBM的结果做对比实验。这些扩展方向在论文的展望章节里都是很好的素材也为后续如果想继续深造或找数据相关岗位时留了可讲的故事。对于已经决定做这个题目的同学我的建议是先花两三天把数据集完整跑通确认数据质量没问题再动手写代码开发过程中保持数据—模型—页面三个轮子同步推进不要先把前端做完再回头搞数据论文尽早开始写尤其把数据预处理和实验对比部分边做边记录不要拖到最后补。祝大家的毕设都能顺利完成答辩时讲得自信、答得从容。