资讯详情 基于Django与DeepSeek大模型的古诗词情感分析及推荐系统
📅 2026/10/18 19:29:57
还在纠结毕设题目看到标题里计算机毕业设计DjangoDeepSeek大模型知识图谱古诗词情感分析 古诗词推荐系统 古诗词可视化 大数据毕业设计这一长串关键词我大概能猜到你需要的是一个既能在答辩时讲出技术深度、又能现场展示出视觉效果、还能让评委一眼看懂这不是拼凑项目的选题。古诗词平台这类题目本身不算冷门但一旦把大模型情感分析、知识图谱和推荐系统这三个关键能力糅在一起整个项目的含金量就上来了。这篇博文我围绕自己实际摸过的同款架构展开把从选题拆解、数据库设计、大模型接口调通、推荐算法落地到可视化看板打包的全过程讲清楚参考价值和回忆录都会有一点。先说定位这套系统定位是文化内容个性化服务方向不是单纯的增删改查管理系统。它要解决的痛点很明确——传统古诗词检索网站只能按标题、作者、朝代查用户面对上万首诗不知道从哪读起也感受不到诗词之间、诗人和作品之间的深层关联。因此系统核心能力锁定在三件事读懂一诗的情感倾向、讲清诗人与作品的关联脉络、按用户兴趣把合适的诗推到眼前。正是这三个能力构成了毕设答辩时最容易被追问、也最能体现思考深度的技术点。1. 项目整体设计与思路拆解1.1 选型落点为什么是Django DeepSeek 知识图谱技术选型不是拍脑袋每一步都是冲着可解释、可维护、有亮点这三个要求去的。后端我没犹豫就选了Django。原因很实际毕设周期短Django自带ORM、Admin后台、模板引擎和一套完整的请求/响应体系能把用户模块、数据管理模块和审核逻辑快速串起来。加上Python生态对大模型调用、数据处理天然友好不用像Java那边还要额外包装一层HTTP客户端。数据模型建好后Django的迁移机制能随时改表结构对开发期频繁调整字段的场景非常省事。你可以把这个选型类比成装修时选了一套模块化家具单个零件拆装方便整体风格统一出了问题也好定位。AI能力这块采用的是DeepSeek大模型的对话式推理接口。传统的情感分析大多依赖词典和机器学习分类器遇到古汉语里特有的借景抒情、用典、反衬效果崩塌得厉害。比如感时花溅泪恨别鸟惊心字面是一片春色实际是沉痛到了极点词典法基本抓瞎。大模型能理解上下文语义和意象背后的文化含义情感标签的质量直接高出一个档次。更关键的是DeepSeek是国产模型接入方式和OpenAI兼容文档规范、离线可用知识储备里有大量古诗词语料对中文古文的把握明显优于通用翻译模型。知识图谱要解决的是关联问题。诗词不是一座座孤岛诗人与诗人之间存在师承、唱和作品与作品之间存在用典、意向朝代影响创作风格风格反过来又决定情感底色。把这些关系建模成实体—关系—实体的三元组比如李白——创作——《静夜思》《静夜思》——包含意象——月就能支撑起两类很有价值的产出一是知识图谱可视化让评委直观看到整个诗词世界的结构二是图谱路径推荐从用户当前读的诗出发顺着诗人的风格分支找到下一首推荐结果可解释性极强。1.2 功能模块拆解与业务流程整个系统按用户视角可以切成四条线数据展示线诗词列表、诗人主页、朝代聚合页、搜索与筛选。这是系统的底子所有其他功能都挂在上面。情感分析线对每首诗词调用大模型接口返回情感类别、情感强度、判断理由和典型意象标签。个性化推荐线用户浏览、收藏、搜索行为被记录后系统从内容相似、图谱路径、行为协同三个维度产出推荐结果。可视化与图谱线后台统计各朝代数量、情感分布、高频意象前端用图表呈现知识图谱页面展示诗人—诗作—意象的关联网络。业务闭环是这样的用户进入系统浏览某首诗词前端把行为事件异步写入后端行为日志后端根据行为日志和当前页面上的诗词实时拉取推荐接口返回一个长度为10的诗词列表用户点击推荐中的某一首下一次推荐计算会把这个点击作为新的权重因子。整体上推荐效果会随着使用行为增多而慢慢养起来这本身就是数据量的积累过程也是论文里可以写数据实验的部分。1.3 技术栈与数据流转总览系统技术栈大概是这个结构后端核心Django Django REST Framework用于搭建API接口、用户鉴权和数据持久化。AI层DeepSeek对话接口OpenAI兼容格式负责情感分析文本向量化使用中文句子向量模型负责内容相似度计算。存储层MySQL放业务数据Redis做推荐结果缓存和热点诗词排行。可视化层ECharts绘制朝代统计、情感分布、词云、力导向图知识图谱展示页面用纯前端渲染。部署与辅助Nginx Gunicorn部署演示环境整个系统可运行在单台服务器上。数据流转上是典型的读多写少场景数据初始化时跑一遍全量情感分析结果落库后续用户访问时直接查表不回源AI接口。推荐计算优先查Redis缓存缓存未命中才做实时计算。这种方式既控制了成本又能保住演示时接口不超时。2. 核心细节解析与实操要点2.1 古诗词情感分析的两种路径情感分析是整个项目的创新牌但做的时候千万别只押一条路。我实际采用的是双路径并联规则兜底方案。路径一是大模型推理路径。系统把诗词全文、作者、朝代、背景信息塞进提示词模板要求模型输出严格JSON格式。实际操作中提示词写得越结构化返回结果就越稳定。我的提示词大致是这样的明确要求模型扮演古诗词研究助理指定情感类别候选集合喜、怒、哀、乐、思、愁、闲适、豪放、婉约要求输出强度值0到1之间需要罗列三个以内的核心意象标签最后用一句话描述判断依据。这样返回的数据可以直接解析进数据库不需要再做一堆字符串清洗。路径二是传统情感词典路径。我用公开的汉语情感词库为基础手工补充一批古诗词高频情感词比如断肠浮萍轩冕谪仙这类词再结合否定词、程度副词做加权计算。这个路径准确率只有五成到六成左右但它的价值在于大模型接口抖动或者网络超时时系统可以自动降级到词典规则保证演示不会当场黑屏。这在答辩现场是救命的。双路径之间还做一个简单的一致性校验两条路径结果一致时写入高置信度标记不一致时以大模型结果为准但保留词典结果字段论文里可以专门写一段分析方法对比。2.2 知识图谱数据建模建模这块需要先想清楚两个问题实体有哪些关系有哪些。我最终定了五类实体和四类关系。实体类型包括诗人、诗作、朝代、意象、风格流派。诗人属性有姓名、字号、生卒年、朝代、籍贯、作品数量、风格标签诗作属性有标题、体裁、正文、译文、赏析、创作背景朝代属性有起止时间、主要诗人和代表作品意象属性有名称、出现频次、典型诗句示例风格流派有流派名、代表人物、主张和代表作品。关系类型设计为诗人—创作—诗作诗人—属于—流派诗人—生活于—朝代诗作—包含意象诗作—体现情感。其中体现情感这个关系实际上是由后面要做的情感分析结果反哺生成的也就是说大模型输出的情感类别如愁会作为图里诗作节点的属性同时在图上形成一个按情感分类的聚合视图。存储方式我选了关系型数据库表加前端图谱渲染的双层结构没有上Neo4j。原因有两层一是毕设答辩现场如果评委想看架构图你可以讲清楚图谱逻辑模型二是Neo4j部署和运维成本对一个毕设系统来说偏重而将三元组数据直接存在MySQL的三张表里实体表、关系表、属性表在数据量几千条级别下查询性能完全够用。图谱页面需要的数据只是把关系表一次性导出成ECharts的nodes和links结构前端渲染根本不吃力。2.3 推荐系统算法取舍推荐不能只做一个猜你喜欢的浅层功能评委追问两句就会露馅。我是按字典式三层推荐设计的每层解决一个特定问题。第一层是内容相似推荐。先把所有诗词的标题、正文、译文、标签拼成一个长字符串用中文句子向量模型转成向量再计算当前诗词与全部诗词的余弦相似度取Top10。这一层的优点是无需用户历史新用户进来也能推缺点是只看文本表面相似风格差异大的诗可能在向量空间里距离很远。第二层是知识图谱路径推荐。核心逻辑是利用刚才建好的图谱关系做多跳查询。比如当前用户在看苏轼的词图谱路径可以这样走苏轼属于豪放派豪放派关联了辛弃疾辛弃疾的代表作有《破阵子》于是把《破阵子》推荐给用户。实现上用BFS宽度优先算法跑两跳路径附带路径详情返回给前端这样推荐列表旁边可以直接显示因为你也喜欢豪放派作品所以推荐了这首可解释性直接拉满。第三层是协同过滤推荐ItemCF。逻辑是统计喜欢诗A的人还喜欢哪首诗。考虑到毕设数据量不大我在内存里构建用户—诗作评分矩阵按是否点击过、是否收藏过、浏览量高低给加权分数然后用余弦相似度计算诗作之间的相似度取TopN。这一层适合在用户产生一定行为数据之后工作冷启动时作用有限。三层推荐的聚合策略很简单但有效内容相似结果占权重40%图谱路径结果占35%协同过滤占25%最终去重后按综合分数排序。如果你的数据量实在太少协同过滤层甚至可以降到10%不会影响整体效果。2.4 可视化看板设计思路可视化是本项目的门面工程一口气拉低了答辩时评委的理解成本。第一个看板是朝代产量图横轴朝代纵轴作品数量一眼看出唐诗宋词的量级差异。第二块是情感分布雷达图标注各朝代情感类别占比能看出宋代词的愁情绪比例远高于唐诗这类对比在论文里可以写成情感演变的时代因素。第三个是高频意象词云把月、酒、花、风、雨、舟、柳、春、秋、山这些高频词用词云组件渲染视觉冲击力很强。第四个是力导向知识图谱诗人、诗作、意象作为图节点节点大小映射作品数量节点颜色映射流派关系线用不同颜色区分类型。可视化这块最有心得的一点是别让后端一次返回所有数据再让前端慢慢渲染。几十个节点没问题但几千个节点浏览器会卡死。我采用分层渲染策略第一层只渲染诗人节点点击某个诗人后第二层渲染该诗人的诗作节点再点击诗作节点展开意象节点。这样一次最多渲染几十个节点动态交互体验非常好。3. 实操过程与核心环节实现3.1 数据准备与清洗数据来源这块我建议优先从开放的古诗文数据库中获取尽量选择带作者、朝代、正文、注释的结构化数据集。我最终整理出约2000首唐诗宋词、200多位诗人的数据量作为项目运行的基石。这个体量对情感分析和推荐实验已经足够出效果对演示环境的内存压力也小。清洗是最费时间但又必须做的活。实际会遇到的问题包括繁体字与简体字混排、标点符号不统一、诗作正文里混入注释文字、同一作者在不同数据源里的名称不一致比如李白和李太白。我统一用字符映射表把繁体转简体用正则把正文里的括号注释和序号剔除同时建了一个作者别名映射字典所有入库数据归一化处理。对这个环节我的经验是别指望一次清洗到位建议清洗完成后随机抽三十首人工核对一遍出错率高于5%就再跑一轮。3.2 数据表设计与核心字段数据库由六张核心表和两张辅助表组成。直接上关键字段诗人表poet主键poet_id姓名name朝代dynasty字号courtesy_name籍贯hometown风格标签style_tags作品数poem_count简介description。诗作表poem主键poem_id标题title作者poet_id外键朝代dynasty体裁genre正文content译文translation赏析appreciation标签tags浏览数view_count。情感分析表emotion主键emotion_id诗作poem_id外键情感类别emotion_type强度intensity判断理由reason意象标签imagery_tags分析方式methodLM或DICT置信度confidence。图关系表kg_relation主键relation_id头实体head尾实体tail关系类型relation_type权重weight附加属性extra_info。用户表user用户ID、用户名、密码哈希、创建时间、偏好风格。行为日志表behavior主键behavior_id用户user_id诗作poem_id行为类型behavior_typeVIEW、LIKE、COLLECT、SEARCH行为时间。有了这套表结构前后端联调就不用反复改字段了。我在设计阶段就把情感分析结果合并进诗作展示详情页避免前端需要同时请求两个接口才能拼出数据的情况。3.3 大模型情感分析接口的实现这一部分是代码实现的重点。整体设计是批量任务与单条实时分析两种模式并存。批量任务在数据初始化时跑用异步循环逐首调用实时分析在管理员后台对单首诗词触发也供前端展示AI情感解构详情。下面是核心实现代码直接可复用import requests import json import time DEEPSEEK_API_URL https://api.deepseek.com/chat/completions API_KEY 你的API_KEY # 建议放到环境变量或Django settings中 def analyze_poem_emotion(poem_text: str, author: str , dynasty: str ) - dict: prompt f你是资深古诗词研究者精通古典文学情感解析。 请分析下面这首诗词的情感倾向并严格按照JSON格式返回结果。 诗词内容 {poem_text} 作者{author} 朝代{dynasty} 要求返回 {{emotion: 喜/怒/哀/乐/思/愁/闲/豪/婉, intensity: 0-1的小数, tags: [核心意象1, 核心意象2], reason: 一句话判断依据}} headers { Authorization: fBearer {API_KEY}, Content-Type: application/json } payload { model: deepseek-chat, messages: [{role: user, content: prompt}], temperature: 0.3 } for attempt in range(3): try: response requests.post(DEEPSEEK_API_URL, headersheaders, jsonpayload, timeout20) response.raise_for_status() data response.json() content data[choices][0][message][content] content content.replace(json, ).replace(, ).strip() parsed json.loads(content) return { emotion: parsed.get(emotion, 未知), intensity: float(parsed.get(intensity, 0.5)), tags: parsed.get(tags, []), reason: parsed.get(reason, ), method: LM } except Exception as e: print(f第{attempt 1}次调用失败: {e}) time.sleep(2 ** attempt) return fallback_dict_analysis(poem_text) # 降级到词典规则这个接口有几个细节值得注意。一是temperature调低到0.3让模型尽量稳定输出减少随机性影响。二是做了三次指数退避重试每次失败等待时间翻倍避免接口临时限流导致整体任务失败。三是返回结果强制JSON解析如果模型偶尔输出多余文字把json标记和反引号去掉再解析。四是超时异常全部捕获后降级到词典分析这是演示保底的最后一道防线。批量跑2000首诗词时实际用时会比较长建议把结果直接写入情感分析表然后在前端直接读取。我当时一台普通笔记本跑全量大约花了四十多分钟完全可接受。3.4 知识图谱查询与推荐接口实现图谱查询部分BFS两跳路径可以这样实现def graph_recommend(poem_id: str, top_n: int 5, max_depth: int 2): poem Poem.objects.get(poem_idpoem_id) poet poem.poet # 第一跳当前诗人的流派和朝代 first_jump KG_Relation.objects.filter( headpoet.name, relation_type__in[属于流派, 生活于朝代] ) reco_scores {} for rel in first_jump: tail rel.tail # 第二跳同流派或同朝代的诗人 second_jump KG_Relation.objects.filter( headtail, relation_type代表作家 ) for sj in second_jump: same_poet sj.tail if same_poet poet.name: continue # 第三跳该诗人的重要作品 poems Poem.objects.filter(poet__namesame_poet) for p in poems[:3]: score 0.7 if rel.relation_type 属于流派 else 0.3 reco_scores[p.poem_id] reco_scores.get(p.poem_id, 0) score top_reco sorted(reco_scores.items(), keylambda x: x[1], reverseTrue)[:top_n] return [Poem.objects.get(poem_idpid) for pid, score in top_reco]内容相似推荐和协同过滤我放在同一个推荐聚合服务里def aggregate_recommend(user, current_poem, top_n10): results {} # 1. 内容相似推荐 content_scores content_similar_recommend(current_poem, top_n5) for pid, score in content_scores.items(): results[pid] results.get(pid, 0) 0.4 * score # 2. 图谱路径推荐 graph_results graph_recommend(current_poem.poem_id, top_n5) for pid, score in graph_results: results[pid] results.get(pid, 0) 0.35 * score # 3. 协同过滤推荐用户有行为时才生效 if user and user.behavior_exists(): cf_scores itemcf_recommend(user, current_poem, top_n5) for pid, score in cf_scores.items(): results[pid] results.get(pid, 0) 0.25 * score sorted_res sorted(results.items(), keylambda x: x[1], reverseTrue) return [poem_id for poem_id, _ in sorted_res[:top_n]]这个聚合接口就是前端推荐栏的单一数据源返回结果是排序好的诗作ID列表。每次请求还支持携带用户行为日志ID后端用于更新用户画像。3.5 前端可视化与API联调前端我采用的是Vue单页应用加ECharts的方案Django后端只提供JSON接口。从实际联调效率看前后端分离比Django模板直出省太多事尤其图谱数据这种高频变化的结构后端模板做起来极其痛苦。关键页面的API约定是这样的GET /api/poems/参数支持分页、朝代筛选、风格筛选、关键词搜索GET /api/poems/{id}/返回详情附带情感分析结果POST /api/behavior/接收用户行为行为类型和诗作IDGET /api/recommend/?poem_idxxx返回推荐列表GET /api/stats/overview/返回看板统计GET /api/knowledge-graph/?center_poetxxx返回分层图谱数据可视化接收到数据的结构约定为朝代统计返回名称数组和数值数组情感分布返回情感类别和各类别数量高频意象词云返回词与权重列表知识图谱返回nodes和links两个数组每个节点带category用于着色。调试中最容易出问题的点在于跨域配置。Django默认不允许跨域请求需要在INSTALLED_APPS里加django-cors-headers并在settings里配置允许的域名。这个坑几乎每个前后端分离项目都会踩一次提前配好可以省下很多排查时间。4. 常见问题与排查技巧实录4.1 大模型接口返回不稳定这是使用外部大模型接口几乎必踩的坑。症状包括偶尔返回超时、偶尔返回内容不全是JSON、偶尔返回结果情感类别跑到候选项之外。我的应对方案第一是重试上一节代码里已经实现了指数退避。第二是严格校验自动降级解析结果前先检查emotion字段是否在预定义类别集合里不在就判定本次解析失败直接降级到词典结果。第三是异步批量跑任务时对单首诗词失败次数做统计连续失败三次就记录待办状态全部跑完后自动重试一次尽量避免人工干预。还有一点很实用把每次大模型请求的输入输出都记录在日志表里。答辩时你会有真实的数据支撑来展示AI分析过程中遇到哪些典型诗词评委很吃这一套。4.2 情感分析结果不准古诗词的情感确实容易判偏。我遇到过一个典型例子是诗句醉卧沙场君莫笑古来征战几人回表面是豪迈洒脱大模型把它标成豪但仔细品其实是悲凉到了极点。这类由豪转悲的复杂性暂时没有万全之策但我摸索出一个补救办法从模型返回的reason字段里提取判断逻辑在前端展示情感分析详情时把判断理由高亮显示这样即便标签有争议用户也能看到系统思考的依据。论文里则如实写大模型情感标签与传统词典方法存在不一致以深度语义为准把严谨性自然表达出来。另一个优化技巧是给模型喂创作背景信息。同一首《静夜思》脱离背景和加入写于羁旅思乡之时的分析结果会有细微差别加入背景后的判断往往更贴近公认解读。数据准备阶段有创作背景字段的诗尽量保留没有的可以用译文和赏析代替。4.3 数据量不足导致推荐不理想有段时间我把数据压缩到只有200首内容相似推荐出来的东西跟自己太像协同过滤完全没有效果。后来尝试了一个补救方案把搜索行为也算进协同过滤矩阵用户搜过月这个关键词那么在诗作相似度上给所有包含月意象的诗统一加权重。搜索结果对推荐的影响立竿见影。还有个更简单的冷启动兜底当推荐结果列表不足10首时用情感分布作为填充依据即优先推荐与当前诗词情感类别相同但朝代不同的诗。这样用户浏览一首悲伤的宋词推荐列表里可能带上一首同样悲伤的唐诗逻辑上说得通演示效果也不错。4.4 答辩演示与源码包整理快到答辩阶段有几个实用经验值得提前说。环境依赖务必用requirements.txt锁版本别让评委演示时现场装依赖装出兼容性问题。演示时优先展示知识图谱力导向图和情感分析详情页这两个页面视觉冲击力最强且能自然引出大模型知识图谱推荐的组合讲法。代码仓库里建议区分业务代码和模型标注数据两类资源。所有涉及API密钥的文件一律用环境变量注入千万别硬编码到源码里然后发给评委。答辩前在全新环境里跑一遍从安装到启动的完整流程这一步能提前暴露一堆你开发机上根本不会遇到的依赖坑。论文部分正文的算法设计章节建议重点写情感分析双路径对比实验用准确率、召回率和F1值来量化大模型与传统词典的差距推荐系统则用推荐命中率和覆盖度作为评价指标。项目文档LW跟源码交付物保持一致的数据结构和接口说明PPT就围绕为什么要做大模型分析、图谱怎么建、推荐怎么算、可视化怎么呈现四个问题展开现场讲解的节奏十到十五分钟最合适。5. 一些个人体会这套系统从立项到完整跑通我个人最大的感受是一个看起来花哨的毕设题目能不能做出真实深度关键不在技术本身而在你愿不愿意把其中一条链路彻底钻透。大模型接口调用并不复杂知识图谱建模也不烧脑但把两者的结果真正串起来、让它影响推荐排序、再呈现在可视化页面上这个闭环才是评委最看重的工程思维。如果你正在做类似方向建议不要贪多先把情感分析结果写入图谱节点这一个打通剩下的功能会自然而然跟着长出来。就算现场出了Bug你只要能讲清楚每一条数据的来路和算法的设计逻辑评委一般都不会为难反而会觉得你是真的做进去了。