又到了每年毕业设计季最焦灼的时候。后台经常有人甩给我一个题目,问这个能不能做、那个能不能过。今天我想拿一个非常有代表性的题目来聊:Python知识图谱中华古诗词可视化、古诗词情感分析、智能问答系统、AI大模型自动写诗。这个题目表面上是“一个毕设”,实际上是把自然语言处理、知识图谱、数据可视化、大模型应用四个方向的活儿串在了一起。做完之后,系统既能展示图谱、出可视化图表,又能回答古诗词相关问题,还能现场生成诗,答辩现场基本不会冷场。
适合什么样的同学?计算机、大数据、人工智能方向的毕业设计选型,以及想快速入门NLP和知识图谱的初学者。哪怕你Python只停留在“会写循环”的水平,只要按步骤来,这个项目是完全能够复现的。我下面会把整体架构、落地顺序、核心代码、踩坑点一次讲清楚,尽量让你少走弯路。
1. 内容整体设计与思路拆解
1.1 这个毕设到底在做什么
拿到这个项目标题,第一件事不是写代码,而是把需求拆开。按我自己的理解,它其实由四个相对独立、但又能串联起来的功能模块组成。
- 知识图谱部分:把古诗词领域的数据整理成“实体—关系—实体”结构,比如诗人李白、诗作《静夜思》、朝代唐代、意象明月,这些是实体;“李白创作了《静夜思》”“《静夜思》提到明月”“李白是唐代诗人”这些是关系。存到图数据库里,再通过前端把关系网络可视化出来。
- 情感分析部分:对古诗词文本做情感倾向判断,至少要把“愁、悲、喜、乐、闲、愤”这类情绪区分出来,还可以按诗人、朝代做统计,画成图表。
- 智能问答系统部分:用户输入“李白写过哪些诗”“《静夜思》是哪个朝代的”“有哪些关于明月的诗句”,系统通过解析意图、查询知识图谱,返回答案。
- AI大模型自动写诗部分:输入主题或关键词,比如“春天”“明月”“送别”,由大模型生成一首符合诗词格式的诗句,或者先给用户一个提示词模板,再调用大模型接口生成。
四个模块各自有亮点,合起来就成了一个“什么都有”的综合项目。对毕业设计来说,这种结构的好处是答辩时有东西可讲:算法部分讲情感分析,架构部分讲知识图谱,工程部分讲Web系统,前沿部分讲大模型应用。每一项都能单独拉出来回答问题,不会被老师追问到无话可说。
1.2 为什么选这套技术组合
很多同学会纠结:知识图谱一定要用Neo4j吗?情感分析一定要用深度学习吗?大模型一定要本地部署吗?我当时的判断是:不要追求“最难的方案”,要追求“最容易讲清楚、又能稳定跑通”的方案。
- Python是首选,没有争议。做NLP、数据清洗、Web后端、模型调用,Python生态最全,写起来最快。热搜词里大量出现“python安装教程”“python入门”,说明不少同学基础还比较薄弱,Python恰恰能把这部分门槛降到最低。
- 图数据库选Neo4j,因为它是目前资料最多、社区最活跃、可视化工具最完整的图数据库。你搜“知识图谱构建”关键词,出来的案例十个里有八个是Neo4j。毕设阶段用Neo4j,遇到问题基本都能搜到答案,这本身就是巨大的优势。
- 情感分析先做“规则方法”再做“深度学习方法”,两条腿走路。只用深度学习模型,容易出现训练时间长、标注数据不足、效果不稳定等问题;只用规则词典,又会显得技术含量不高。两者结合以后,论文里既有对比实验,也有改进空间。
- 大模型自动写诗,优先接成熟的大模型接口,而不是从零训练生成模型。从零训练一个古诗词生成模型需要数据、算力、调参经验,对毕设来说风险太高。用大模型接口,能快速出效果,还能在论文里讨论“提示工程设计”和“生成内容校验”,同样是合理的研究点。
技术选型这件事,关键在于“稳”。答辩老师不会因为你用了最复杂的模型就高看你,但会因为你能解释清楚每一个模块为什么这么做、效果如何,而给出不错的评价。
2. 环境准备与工具链搭建
2.1 Python环境与核心依赖安装
这一步看似基础,但我在实际帮人调试时发现,至少有三成同学的项目跑不起来,根本不是代码问题,而是环境问题。Python版本不对、依赖包互相冲突、Neo4j驱动版本不匹配,都会让你在起步阶段卡上一整天。
先装Python。建议直接装3.9或3.10,不要追求最新。太新的版本某些第三方库可能还没做好适配,太旧的版本又会有安全问题和兼容问题。装好之后,在命令行里敲python --version能看到版本号,就说明成功了。然后建一个虚拟环境,避免把系统全局环境搞乱。
python -m venv venv venv\Scripts\activate # Windows source venv/bin/activate # Linux/Mac接下来安装依赖。我给出一个能跑通我这边项目的版本组合,你可以参考:
flask==3.0.0 py2neo==2021.2.4 jieba==0.42.1 snownlp==0.12.3 requests==2.31.0 numpy==1.24.3 pandas==2.0.3注意:py2neo版本和Neo4j版本必须匹配。py2neo 2021.2.4对应Neo4j 4.x,如果装Neo4j 5.x,驱动写法会有变化。毕设求稳,建议直接装Neo4j 4.4社区版。
安装命令很简单:pip install -r requirements.txt。装完后,建议先跑一段测试代码,确认所有包都能正常导入,再进入下一步。
2.2 Neo4j图数据库与前端可视化工具准备
Neo4j的安装包直接去官网下载Community版本,Windows下是一个exe,Linux下是tar包。安装过程中要设置一个初始密码,这个密码后面连接时会用到,千万别忘。启动服务后,浏览器打开http://localhost:7474,能看到Neo4j Browser的页面,说明服务正常。
图数据库和MySQL这类关系数据库最大的区别在于:它的核心数据结构就是“节点”和“关系”,查询语言是Cypher。举个例子,查“李白所有的诗作”,在Neo4j里写:
MATCH (p:Poet {name: '李白'})-[:WROTE]->(poem:Poem) RETURN poem.title这种写法非常接近自然语言,新手学起来比SQL还快。而且Neo4j Browser自带可视化能力,输入查询语句后能直接看到图结构,这对中期检查、演示系统都非常有帮助。
前端可视化部分,推荐用ECharts的graph系列。ECharts是百度开源的可视化库,文档齐全,示例丰富,国内开发者用起来没有障碍。你不需要自己从零写Canvas绘图,只需要把节点和边数据组织成它需要的格式,就能出一个可拖拽的力导向图。后面我会在3.3节给出具体的配置思路。
2.3 模型文件与知识数据的准备
这一节容易被人忽略,但实际上决定了整个项目能不能做出深度。古诗词领域的原始数据,比较理想的是“全唐诗”“全宋词”这类公开文本,一般可以从开源数据集或爬取古诗文网站获得。考虑到毕设时间有限,我建议直接用结构化程度较高的公开数据集,比如带作者、朝代、诗名、正文的CSV或JSON文件,尽量避免自己写爬虫去解析HTML页面,那个坑太多。
预训练模型方面,如果只做情感分析,可以使用SnowNLP,它内置了一个中文情感分析模型,虽然主要针对现代文本,但做基础测试完全够用。想进一步提升效果,可以下载HuggingFace上的中文BERT模型,做微调。不过这里要注意,古诗词和现代汉语差异很大,直接用BERT预测古诗词情感往往不太准,后面我会讲如何针对古诗词做优化。
大模型自动写诗部分,我建议在项目里预留一个接口层。系统先判断有没有配置大模型的API密钥,有就调用远程接口,没有就降级成规则生成,这样即使现场演示时网络不稳定,也不会尴尬。至于“本地部署ai大模型”这个词,如果机器配置不够,完全不用硬上,用远程接口就是最务实的方案。
3. 知识图谱构建与可视化实现
3.1 数据采集与清洗:从全唐诗到结构化三元组
知识图谱构建的核心不在代码,而在数据清洗。你拿到的原始数据往往长这样:
{ "title": "静夜思", "author": "李白", "dynasty": "唐", "content": "床前明月光,疑是地上霜。举头望明月,低头思故乡。" }这些数据不能直接进图数据库,因为图谱要求的是“实体”和“关系”,不是一篇一篇的原文。你要做的第一步,是把每条诗作拆成一个基础三元组:诗人—创作—诗作,诗作—属于—朝代,诗作—提到—意象。拆完以后,还需要去重。比如“李白”可能被写成“李太白”“青莲居士”,如果不合并,图谱里会出现好几个节点,查询时就乱了。
我的做法是在入库之前维护一个“别名表”。例如:
| 实体名 | 别名 |
|---|---|
| 李白 | 李太白、青莲居士、诗仙 |
| 杜甫 | 杜子美、少陵野老、诗圣 |
| 苏轼 | 苏东坡、东坡居士 |
| 明月 | 月、婵娟、玉盘、瑶台镜 |
清洗时遍历诗句,凡是命中了别名表中的词,统一替换成标准实体名。这一步做完,图谱质量会立刻上一个台阶。数据清洗向来不性感,但它是整个项目里最容易被答辩老师追问的部分,你能说出“怎么解决异名实体合并”这个问题,就已经超过很多人了。
3.2 实体识别与关系抽取的实现细节
古诗词和应用文不一样,里面有很多古代地名、特定意象、词牌名,通用NLP工具不一定认识。拿“影入平羌江水流”来说,如果分词器不认识“平羌”,很可能把它切碎,后面做实体识别就找不到“平羌江”这个地点实体。
我的实践经验是:不要一开始就上BERT做序列标注,先用“自定义词典 + 正则 + 词典匹配”把基础实体抽出来,成功率已经很高。用jieba加载自定义词典,示例代码如下:
import jieba jieba.load_userdict("poetry_dict.txt") text = "床前明月光,疑是地上霜。" words = list(jieba.cut(text)) print(words) # ['床前', '明月', '光', ',', '疑', '是', '地上', '霜', '。']poetry_dict.txt里可以按行写入这些词:
明月 100 n 诗仙 150 nr 峨眉山 100 ns 平羌江 100 ns 将进酒 50 nz有了分词结果之后,再根据词性和预先定义好的实体词表做匹配。实体类型的规划可以参考这样的表格:
| 实体类型 | 示例 | 图谱标签 |
|---|---|---|
| 诗人 | 李白、杜甫、苏轼 | Poet |
| 诗作 | 静夜思、春望、水调歌头 | Poem |
| 朝代 | 唐代、宋代 | Dynasty |
| 地点 | 长安、洛阳、峨眉山 | Place |
| 意象 | 明月、酒、花、柳 | Imagery |
| 词牌名 | 水调歌头、念奴娇 | Cipai |
关系类型随之确定:
| 关系 | 示例 | 图谱关系标签 |
|---|---|---|
| 创作关系 | 李白 -> 静夜思 | WROTE |
| 朝代归属 | 静夜思 -> 唐代 | BELONGS_TO |
| 地点关联 | 李白 -> 长安 | TRAVELED_TO |
| 意象使用 | 静夜思 -> 明月 | MENTIONS |
| 词牌归属 | 水调歌头 -> 苏轼 | AUTHORED_BY |
实体抽取的代码写起来不算复杂,但要注意一个细节:同一个词在不同诗句里可能扮演不同实体。比如“花”在“花间一壶酒”里是意象,在地名“花都”里可能就不是。因此,我建议在匹配到实体之后,加一个上下文的消歧规则。比如“花”后面跟着“间”“前”“落”等字,优先判为意象;后面跟着“都”“城”等字,优先判为地点。虽然做不到100%准确,但已经能满足毕设展示和论文分析的场景。
关系抽取其实和实体抽取是联动的。你抽出了“李白”和“静夜思”,同时知道“李白”是诗人、“静夜思”是诗作,且来源于同一条诗作记录,那么“WROTE”关系就自然建立了,不需要再做复杂的句法分析。这就是为什么我建议用JSON数据集而不是纯文本语料——因为JSON里已经隐含了一部分结构信息,你只需要把它转成图谱结构,难度低得多。
3.3 Neo4j入库与可视化页面开发
数据清洗完毕,接下来就是把节点和关系写进Neo4j。我推荐使用py2neo库,原因是API简洁、文档多。入库前先清空旧数据,然后按批次导入,避免一次性提交太多导致内存爆炸。
from py2neo import Graph, Node, Relationship graph = Graph("http://localhost:7474", auth=("neo4j", "your_password")) graph.run("MATCH (n) DETACH DELETE n") def create_poet(poet_id, name, dynasty): node = Node("Poet", id=poet_id, name=name, dynasty=dynasty) graph.merge(node, "Poet", "id")merge方法是一个很重要的细节。它相当于“有则更新、无则创建”,可以避免重复导入时产生重复节点。关系创建也类似:
poet_node = graph.nodes.match("Poet", name="李白").first() poem_node = graph.nodes.match("Poem", title="静夜思").first() if poet_node and poem_node: rel = Relationship(poet_node, "WROTE", poem_node) graph.create(rel)全部入库之后,可以在Neo4j Browser里跑一句查询验证:
MATCH p=(:Poet {name:'李白'})-[:WROTE]->(:Poem) RETURN p LIMIT 25能出图,说明图谱构建完成。接下来是可视化页面。我遇到过很多人在这一步被热搜词里的“知识图谱只显示25个标签”搞懵:明明数据很多,页面上却只显示了一小部分节点。其实这是ECharts渲染策略的问题,当节点数量很大时,一次性把几千个节点全部渲染到SVG或Canvas上,浏览器会很卡。所以正确做法是,前端默认只加载部分核心节点,用户点击节点后再动态查询它的邻居关系。
具体思路是:后端暴露两个接口。一个接口返回全局统计信息和核心节点,比如每个朝代的主要诗人;另一个接口接收某个节点的ID,返回它的一跳邻居。前端用用户点击事件触发第二类请求,形成“逐级探索”的交互效果。这样页面永远保持流畅,也让演示过程更有层次感。
ECharts的图配置中,最关键的是给每个节点设置category字段,代表实体类型,然后用不同颜色区分诗人、诗作、朝代、意象。再看一眼初始化代码:
option = { series: [{ type: 'graph', layout: 'force', roam: true, categories: [ { name: 'Poet' }, { name: 'Poem' }, { name: 'Dynasty' }, { name: 'Imagery' } ], data: nodes, links: edges }] };力导向图布局是系统自动计算的,节点会相互排斥,最终形成相对稳定的网络结构。实际在页面上看到的效果,比静态图要漂亮得多,这也是答辩演示时最容易打动老师的一环。
4. 情感分析模块实现
4.1 基于情感词典的轻量级方法
古诗词情感分析和微博评论情感分析完全是两码事。你拿现代汉语的情感词典去分析“商女不知亡国恨,隔江犹唱后庭花”,大概率会得出“不知”带否定、“亡国”偏负面这类草率结论,但原诗真正的核心情绪是“讽刺”和“悲痛”。所以,针对古诗词,第一步要构建一个专门的情感词典。
我的做法是准备一份古诗词情感词表,按情绪类别分组,比如:
| 情绪类别 | 示例词 |
|---|---|
| 悲 | 愁、泪、断肠、孤、寒、苦 |
| 喜 | 喜、欢、乐、闲、醉 |
| 思 | 思、念、忆、望、乡 |
| 愤 | 愤、怒、不平、恨 |
| 静 | 静、幽、清、淡、空 |
每个词给一个权重分。越强烈的词分数越高,比如“断肠”给-3,“愁”给-2,“愁绪”甚至可以给-2.5,“轻轻”这类词就给0.5。然后对整首诗做加权求和,再接上否定词和程度副词的判断规则。
一段简单的示例代码:
import jieba emotion_dict = {"愁": -2, "泪": -2, "断肠": -3, "喜": 2, "闲": 1} neg_words = {"不", "无", "莫", "未", "非"} degree_words = {"极": 1.5, "非常": 1.5, "微": 0.5, "稍": 0.8} def emotion_score_by_dict(text): score = 0 neg_multiplier = 1 degree_multiplier = 1 for word in jieba.cut(text): if word in neg_words: neg_multiplier = -1 if word in degree_words: degree_multiplier = degree_words[word] if word in emotion_dict: score += emotion_dict[word] * neg_multiplier * degree_multiplier neg_multiplier = 1 degree_multiplier = 1 return score这只是一个简化版。实际项目里,我还会加入“句间情感转折”的处理:如果前半句出现“虽好”,后半句出现“独愁”,那么整诗情绪应该偏向后者。毕设论文里能把这些细节写出来,比只说“调用了一个情感打分模型”有价值得多。
4.2 基于深度学习模型的进阶方案
词典方法的优点是快、可解释性强,缺点是对未见过的表达方式无能为力。比如“莫听穿林打叶声”这句,如果不认识“莫听”这个结构,词典可能会误解它的情感方向。这时候就需要深度学习模型兜底。
我推荐的进阶路线是:先用SnowNLP做快速情感打分,再针对古诗词场景进行简单微调。SnowNLP的模型本质是朴素贝叶斯,使用起来非常简单:
from snownlp import SnowNLP s = SnowNLP("独在异乡为异客,每逢佳节倍思亲。") print(s.sentiments) # 输出 0~1 的情感积极程度如果直接用,你会发现结果不一定理想,因为训练语料主要来自电商评论。改进思路是收集几百首带有明确情感倾向的古诗词,人工打好标签,比如“乐观积极”和“悲伤消极”两类,然后用这些数据对模型做增量训练。不需要太多样本,几百条就能看到明显效果。
如果想进一步提高论文深度,可以使用BERT模型做文本分类。加载一个中文BERT,把诗句当作输入序列,输出情感类别。代码大致是:
from transformers import AutoTokenizer, AutoModelForSequenceClassification tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese") model = AutoModelForSequenceClassification.from_pretrained("bert-base-chinese", num_labels=6) inputs = tokenizer("独在异乡为异客,每逢佳节倍思亲。", return_tensors="pt") outputs = model(**inputs) pred = outputs.logits.argmax(dim=-1)不过这里有一个实际问题:BERT输入长度有限制,古诗整篇通常没问题,但《长恨歌》这种长诗会被截断。我的建议是,情感分析默认针对单首绝句或律诗,长诗则分段分析,再取加权平均或主要情绪。这样处理逻辑清楚,答辩时也能讲明白。
4.3 情感分析结果如何上图
情感分析结果光存储成数字没意义,必须可视化出来才有展示效果。我做了两个层面的可视化:单诗情感标签和多维度统计。
单诗分析页面:用户输入或选择一首诗,系统显示这首诗的“情感雷达图”,六个维度分别是“悲、喜、思、愤、静、愁”,每个维度的分数由模型输出归一化得到。雷达图用的还是ECharts,配置不复杂,但视觉冲击力很强。演示的时候,选一首明显悲伤的诗和一首明显欢快的诗对比,老师一眼就能明白这个模块做了什么。
多维度统计图:按朝代统计情感分布,用堆叠柱状图展示;按诗人统计情感倾向,用横向条形图展示。比如“李白的情感分布”“杜甫的情感分布”并排对比,能直观看出李白诗作中“思乡”和“怀古”占比高,杜甫诗作中“忧国忧民”占比高。这样的分析结论可以直接写进论文的“情感分析结果讨论”一节,让系统显得有分析价值。
5. 智能问答与AI写诗模块实现
5.1 规则模板问答:先跑通再谈智能
智能问答系统最忌讳一上来就做大模型意图识别。模型理解能力确实强,但响应不稳定、生成内容不可控,在演示现场容易翻车。我的建议是分两层:底层用规则模板保证高频问题的准确率,上层再挂大模型处理发散性问题。
先定义意图模板:
| 用户问法例子 | 意图ID | 对应查询 |
|---|---|---|
| “李白写过哪些诗” | poems_by_poet | 根据诗人查诗作 |
| “静夜思是哪个朝代的” | dynasty_of_poem | 根据诗作查朝代 |
| “有哪些关于明月的诗句” | poems_by_imagery | 根据意象查诗作 |
| “李白和杜甫是什么关系” | relationship_of_poets | 查询两位诗人的共同点和关系 |
| “唐代有哪些著名诗人” | poets_by_dynasty | 根据朝代查诗人 |
规则实现用正则匹配就行:
import re def parse_question(question): patterns = [ (r"^(.{2,4})写过哪些诗", "poems_by_poet"), (r"^(《?.{2,10}?》?)是哪个朝代的", "dynasty_of_poem"), (r"^有哪些关于(.{2,6})的诗", "poems_by_imagery"), ] for pattern, intent in patterns: m = re.search(pattern, question) if m: return intent, m.group(1) return "unknown", None命中意图之后,再拼Cypher查询语句。比如用户问“李白写过哪些诗”,系统解析出poems_by_poet意图和实体“李白”,就去执行:
MATCH (p:Poet {name: '李白'})-[:WROTE]->(poem:Poem) RETURN poem.title拿到结果后,拼装成一句自然语言,比如“李白一共写过X首诗,代表作品包括《静夜思》《望庐山瀑布》《将进酒》等。”这一步简单但很重要,因为直接返回图数据库里的原始结果,阅读体验太差,会显得系统很粗糙。
5.2 大模型辅助问答与自动写诗
规则问答能覆盖大约80%的常见问题,剩下20%的发散性问题,比如“李白为什么被称为诗仙”“《静夜思》表达了什么情感”,就要交给大模型。做法是设计一个系统提示词,把回答范围限定在古诗词领域,然后把知识图谱查到的结构化信息作为上下文一起发给模型,让它基于事实生成更自然、更有深度的回答。
提示词大致长这样:
def ask_llm_with_context(question, context): prompt = f""" 你是中国古诗词研究助手。 请基于以下知识图谱信息回答问题,如果信息不足,再结合你的知识补充,但不要把话说死。 知识图谱信息: {context} 用户问题: {question} """ return call_llm_api(prompt)这里的关键是,先查知识图谱,再生成回答。大模型只是负责把碎片信息组织成通顺的答案,而不是凭空编造。这样做的好处是回答可控性强,不会一本正经地胡说八道。
自动写诗模块同样走大模型路线。用户输入主题,系统生成一段写诗提示词,再调用接口。我习惯在提示词里给模型明确的格式要求,避免它生成现代诗或者格式混乱的句子:
def generate_poem(topic, keywords): prompt = f""" 请以“{topic}”为主题写一首七言绝句。 要求: 1. 符合平仄和押韵,风格接近唐诗; 2. 尽量包含以下意象或关键词:{keywords}; 3. 每句7个字,共4句; 4. 不要输出解释,只输出诗本身。 """ return call_llm_api(prompt)实际生成之后,还可以加一个后处理校验:统计每句字数是否为7个字,如果不是就重新调用一次。这个“生成后校验”的细节写进论文里,能体现工程严谨性,答辩老师也会觉得你做的不只是简单的API调用。
5.3 回答效果的取舍与兼顾
大模型接入后,有一个容易被忽视的问题:大模型可能直接用它的知识回答,而没有真正使用你的知识图谱数据。这样你的图谱就变成了摆设。所以我在设计问答流程时,采用“图谱优先、大模型辅助”的策略。
流程是这样的:用户提问后,先尝试正则意图解析,如果能命中,就直接查图谱返回答案;如果没命中,再把问题发给大模型,并把图谱中相关的实体和关系作为提示词上下文一起发给它。这样既保证核心问题回答准确,也让大模型的发散回答建立在图谱数据之上。
在调试阶段,我发现一个很有意思的现象:大模型有时候会编造诗句,比如用户问“李白写过哪些诗”,它可能会把《水调歌头》也算进去,因为苏轼确实写过《水调歌头》,但李白并没有。这说明纯粹的生成式回答在事实性问题上并不可靠。因此,事实类问题一定用知识图谱查询,审美类问题才交给大模型发挥。这个结论写进论文里,是一个非常加分的分析和思考点。
6. 联调、打包与毕业设计交付
6.1 项目结构建议
代码写完之后,千万别把所有文件堆在一个文件夹里。答辩时需要交源码和说明文档,一个清晰的项目结构会让老师觉得你工程素养很好。我推荐这样的目录:
poetry_kg/ ├── app.py # Web入口 ├── requirements.txt # 依赖列表 ├── config.py # 配置文件,包含Neo4j和API密钥 ├── data/ │ ├── raw/ # 原始数据 │ ├── cleaned/ # 清洗后的数据 │ └── dict/ # 自定义词典 ├── graph/ │ ├── import_graph.py # 图谱构建脚本 │ └── query_graph.py # 图谱查询封装 ├── emotion/ │ ├── dict_analyzer.py # 词典情感分析 │ └── bert_analyzer.py # 深度学习情感分析 ├── qa/ │ ├── intent.py # 意图解析 │ └── answer_generator.py# 答案组装 ├── llm/ │ └── poem_generator.py # 大模型写诗 ├── static/ │ └── js/ # 前端可视化脚本 └── templates/ └── index.html # 前端页面配套的LW文档,指的是“论文+外文翻译”这类学校要求的材料。论文结构一般包括摘要、绪论、需求分析、系统设计、系统实现、系统测试、总结。不过我更建议你按照自己的模块顺序来写:先写知识图谱构建,再写情感分析,再写问答和大模型写诗,这样逻辑上更顺畅,也更容易凑够字数。
PPT的页面控制在20页左右。我的习惯是:前面3页讲背景和意义,中间8页讲功能和设计,后面看到能跑的演示效果,最后3页写总结和展望。千万不要把大段代码贴进PPT,老师看不完,也没兴趣看。
6.2 演示与答辩注意事项
到了答辩这个环节,技术能力反而次要,稳定演示才是第一优先级。我吃过亏,所以总结了几条非常实际的建议:
- 演示前把Neo4j启动好,把Web服务启动好,不要当着老师的面打开终端滚日志。
- 准备一份“最小演示数据”,比如只保留20位诗人、200首诗、50个意象。这样图谱加载快,页面不卡,老师体验反而比海量数据更好。
- 如果要用到大模型写诗功能,提前准备好一个稳定的网络环境。如果现场网络不好,就直接展示预先缓存好的几首生成结果,并解释“由于现场网络限制,我准备了离线缓存案例”。
- 老师在追问情感分析准确率时,不要回避问题。直接说“我用词典方法作为baseline,准确率约72%,加入BERT微调后提升到84%,但因为标注语料规模有限,进一步提升需要更多人工标注”,这句话已经足以体现你对问题的真实理解。
- 准备1-2个“失败案例”也是加分项。比如“这首《登高》被规则方法判断为中性,因为诗里没有明显情感词,但BERT能识别出悲凉情绪”,说明你能发现规则方法的缺陷并知道为什么深度学习能补上。
答辩最怕的不是答不上来,而是老师一眼看出项目是“照搬教程”。所以哪怕你确实是照着教程做的,也一定要在论文和答辩PPT里加入自己的思考过程,哪怕只是数据分析里的一个小改动,都要讲出来。
6.3 踩坑记录与优化方向
这里把我自己和身边的人在实际开发中踩过的坑整理成一个速查表,希望能帮你节省排查时间:
| 问题现象 | 常见原因 | 解决方案 |
|---|---|---|
| py2neo连接报“The client is unauthorized” | Neo4j密码错误或未修改默认密码 | 用浏览器打开7474端口重置密码 |
| 导入数据后Neo4j页面卡死 | 一次性创建太多节点关系 | 分批导入,每批不超过1000条 |
| 图谱页面只显示25个标签/节点 | ECharts渲染全部节点导致性能问题 | 默认只显示核心节点,点击后再动态加载邻居 |
| 中文诗句在页面显示乱码 | 文件编码不是UTF-8 | 所有脚本统一用utf-8读取写入 |
| 大模型生成的诗句字数不对 | 提示词约束不够强 | 增加字数校验,不合格就重新生成一次 |
| 情感分析结果全部趋近0.5 | 词典权重设置不合理 | 扩大情感词表,增加否定词和程度副词规则 |
| 问答系统命中率低 | 正则模板太少 | 把用户问法收集成一个测试集,反复扩充模板 |
这些坑几乎每个人都会踩一遍,提前知道就能跳过一大半。除此之外,我还建议你在论文最后写几段“系统优化方向”,比如:增加实体链接,把同名不同义的概念进一步区分;引入图算法,比如最短路径、社区发现,分析诗人之间的“朋友圈”;把情感分析从单诗拓展到诗人整体风格画像;在问答系统里加入多轮对话能力。这些内容不需要全部实现,但写出来能展示你的思考深度。
7. 写在最后:一些个人体会
做这个项目最大的体会是:知识图谱的价值不在于技术炫酷,而在于它能把零散的信息组织成可查询、可推理的网络。古诗词领域恰好非常适合做这件事,因为实体关系明确、数据量适中、可视化效果好,做完之后你会对自然语言处理从理论到工程都有整体认知,再回头看教科书,很多概念就通了。
如果让我给时间紧张的同学排优先级,我的建议是:先把知识图谱构建和可视化做出来,这是项目的骨架;再把规则问答跑通,这是功能完整性的底线;情感分析用词典方法先出结果,有余力再微调模型;大模型写诗放在最后作为亮点,因为它的接入成本最低,但对整体观感提升很大。按照这个顺序推进,即使中途卡住,也至少能保证一个能演示、能写进论文的完整系统。
最后分享一个小技巧:开发过程中,把所有测试用户的问法、每首诗的原始文本、情感分析结果都保留下来,整理成一个测试集。这台功夫看起来不起眼,但后面写论文、做答辩PPT、应付老师提问时,你会发现它就是你的底气所在。毕竟,一个能拿出真实数据说话的项目,远比一个只靠截图和口头描述的项目更有说服力。