大模型之路7-4:中国人都会喜欢的知识库——中华诗词知识库(同步Github)Web与AI智能化设计
📊 中华诗词知识库 · 第四章:Web与AI智能化设计
Knowledge Base of Chinese Poetry (KBCP) — Chapter 4: Web & AI
🌟GitHub 开源地址:https://github.com/liang1057/Knowledge-Base-of-Chinese-Poetry
🌟 如果资源对你有帮助,欢迎 Star 支持!
📥 JSON数据下载:https://download.csdn.net/download/sdust_dx/92826598
🎯 前言
前三章完成了数据收集、清洗与 Schema 设计。本章将在此基础上,构建一套完整的 Web 可视化系统,并引入 大语言模型(LLM) 实现诗词的智能化分析与自动标注。
本章的 Web 系统围绕 Schema 展开——前端展示诗词的文学属性,后端通过 LLM 自动为 6.2 万首诗词打上主题、风格、情感等多维度标签。
本章的核心目标是:从"结构化数据"到"可视化交互",再到"AI 智能增强"的完整链路实现。
一、Web 开发:用大模型辅助,但不止于大模型
1.1 为什么需要大模型
首先,从业内的AI经验来看,Web开发是非常适合大模型的一个工作:Web 开发是一个"细节密集、样板重复"的工程。 从页面布局、CSS 样式到 API 接口、数据库查询,大量代码属于"知道怎么做,但写起来费时"的机械劳动。对于个人开发者或小团队,这种重复性工作会严重挤压核心功能的开发时间。
其次,对我个人来说,我知道Web开发的大概步骤,略懂Web的Python开发和HTML语法,但是个人的技术储备不足以完成开发 ,AI模型则是让我具备了六边形战士的能力。
大模型的核心价值在于将"写代码"转化为"描述需求"。不再需要手写 jQuery 事件绑定、Flask 路由注册或 SQLAlchemy 关系定义,而是直接用自然语言描述意图——“左侧树形导航点击诗人后异步加载诗词列表”——模型即可生成可运行的代码骨架。这相当于把开发效率从"逐行编码"提升到"逐块组装"。
更关键的是跨栈整合能力。本项目涉及前端(jsTree + Bootstrap)、后端(Flask + SQLAlchemy)、数据库(SQLite 外键约束)和 AI(LLM Provider 抽象层)四个技术栈。大模型能够同时理解这些栈的交互逻辑,生成前后端联调的完整代码,避免"前端写完了,发现后端接口格式不对"的返工。
但大模型不是替代开发者思考,而是加速从"想法"到"可验证原型"的跨越。你仍然需要理解生成的代码、判断架构合理性、处理边界情况。大模型负责"写出来",你负责"想明白"——这才是"用大模型辅助,但不止于大模型"的本意。
1.2 需要什么样的 Web 系统?
第三章的 Schema 设计解决了"数据如何存"的问题,但 6.2 万首诗词躺在 SQLite 数据库里,对普通人而言毫无意义。真正要读诗词,需要一个网页作为载体:
- 浏览层:按朝代-诗人-诗词的树形导航,快速定位作品
- 编辑层:管理员可修正正文、赏析、翻译,维护数据质量
- 标签层:为每首诗打上主题、风格、情感等标签,支撑后续 RAG 检索
- 管理层:朝代、作者、受控词表的 CRUD,保证数据一致性
1.3 技术选型思路
本项目的技术栈选择遵循"轻量、可控、易部署"原则:
| 层级 | 技术 | 选择理由 |
|---|---|---|
| 后端 | Python 3 + Flask + Flask-SQLAlchemy | 轻量框架,ORM 直接映射第三章的 Schema,开发效率高 |
| 前端 | HTML/CSS/JS + jQuery + Bootstrap 5 | 无需构建工具,直接引用 CDN,降低部署门槛 |
| 树控件 | jsTree | 支持异步加载、搜索、多选,完美适配朝代-诗人层级 |
| 数据库 | SQLite | 第三章已设计好的 Schema,FK 约束 + 复合主键,单文件部署 |
| AI 层 | Ollama / DeepSeek / 智谱 API | 本地+云端双模式,零成本起步 |
💡 为什么不选 Vue/React + Django?
本项目面向个人研究者和小型团队,Flask + jQuery 的组合足够支撑功能,
且无需配置 Node.js 构建环境,树莓派上也能直接运行(AI要选用云端实现)。
二、系统架构与项目结构
2.1 整体架构
┌─────────────────────────────────────────────────────────────┐
│ 用户层 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 诗词浏览 │ │ 标签管理 │ │ 后台管理 │ │ AI 打标 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
├─────────────────────────────────────────────────────────────┤
│ API 层 (Flask) │
│ /api/dynasties /api/poems /api/poem/save /api/search │
├─────────────────────────────────────────────────────────────┤
│ 数据层 (SQLite) │
│ poem │ author │ dynasty │ vocab │ poem_tag │
├─────────────────────────────────────────────────────────────┤
│ AI 层 │
│ KBCP_AutoTag.py → KBCP_LLM_Provider.py │
│ (Ollama / DeepSeek / 智谱) │
└─────────────────────────────────────────────────────────────┘
2.2 项目结构
Prj_Poetry_China/
├── dataset/
│ └── kbcp.db # 数据库文件(第三章 Schema v2)
├── data/
│ ├── Poetry_China_all.json # 原始诗词数据
│ ├── Dynasty.json # 朝代数据
│ └── Author.json # 诗人数据
├── KBCP_RAG_Poem_Schema.py # Schema 定义(第三章)
├── KBCP_RAG_Poetry_DB.py # 数据库构建脚本(第三章)
├── KBCP_web/ # Web 应用(本章核心)
│ ├── KBCP_app.py # Flask 主程序
│ ├── KBCP_auth.py # 认证模块(session + 密码哈希)
│ ├── KBCP_models.py # SQLAlchemy ORM 模型(映射第三章 Schema)
│ ├── config.py # 配置文件
│ ├── templates/ # Jinja2 模板
│ │ ├── KBCP_base.html # 基础模板(导航栏 + 布局框架)
│ │ ├── KBCP_index.html # 首页(四栏布局:树形导航 + 诗词列表 + 详情 + 标签)
│ │ ├── KBCP_admin.html # 管理后台(Tab 页:朝代/作者/诗词/词表/用户)
│ │ ├── KBCP_admin_modals.html # 管理 Modal(添加/编辑弹窗)
│ │ └── KBCP_login.html # 登录页
│ └── static/
│ ├── css/
│ │ └── KBCP_style.css # 自定义样式(诗词楷体展示、标签配色)
│ └── js/
│ ├── KBCP_tree.js # jsTree 异步加载 + 点击事件
│ ├── KBCP_editor.js # 诗词编辑器 + 标签增删
│ └── KBCP_admin.js # 管理后台 CRUD 操作
├── KBCP_AutoTag.py # AI 自动打标主程序(本章重点)
├── KBCP_LLM_Provider.py # LLM 提供者抽象层
├── KBCP_LLM_config.ini # LLM 配置文件(含 API Key,已加入 .gitignore)
└── KBCP_LLM_config.example.ini # 配置模板(无 Key,可提交 Git)
三、前端设计:四栏布局与交互逻辑
3.1 页面布局
首页采用经典的 四栏布局,左侧树形导航、中间诗词列表、右侧详情与标签:
┌──────────────────────────────────────────────────────────────────┐
│ [导航栏] 诗词库 v2 | 首页 | 管理 | 搜索 | [用户名/退出] │
├──────────┬──────────┬──────────────────────┬────────────────────┤
│ 左一栏 │ 左二栏 │ 左三栏 │ 左四栏 │
│ 朝代-诗人 │ 诗词列表 │ 标题 / 作者 │ 诗词标签 │
│ 树形导航 │ │ 正文(可编辑) │ [+增加标签] │
│ │ │ 赏析(可编辑) │ [清除标签] │
│ 先秦(4) │ 静夜思 │ 翻译(可编辑) │ # 体裁 │
│ 唐(2475)│ 望庐山 │ [保存修改] │ 诗 [×] │
│ │─李白 │ 瀑布 │ │ # 主题 │
│ │─杜甫 │ 将进酒 │ │ 思乡 [×] 月夜 [×] │
│ 宋(1497)│ ... │ │ # 情感 │
│ ... │ │ │ 悲伤 [×] │
├──────────┴──────────┴──────────────────────┴────────────────────┤
│ 统计栏: **朝代 | xxx 诗人 | xxxxx 诗词 | xxx 标签 │
└──────────────────────────────────────────────────────────────────┘
3.2 交互设计要点
| 交互场景 | 实现方式 | 说明 |
|---|---|---|
| 朝代展开 | jsTree 异步加载 | 点击"唐",AJAX 请求 /api/authors/T,返回李白、杜甫等诗人列表 |
| 诗人点击 | 加载诗词列表 | 点击"李白",中间栏显示其全部诗词标题 |
| 诗词点击 | 详情 + 标签联动 | 点击"静夜思",右三栏显示正文/赏析/翻译,右四栏显示所有标签 |
| 标签删除 | 即时反馈 | 点击标签旁的 [×],AJAX 删除,无需刷新页面 |
| 标签添加 | Modal 多选 | 弹出标签选择器,按类别(主题/风格/情感等)分组,支持批量勾选 |
| 正文编辑 | ContentEditable | 管理员模式下,正文、赏析、翻译可直接编辑,点击保存后 AJAX 提交 |
四、后端设计:Flask API 与权限控制
4.1 核心 API 设计
API 分为三类:公开接口(无需登录)、管理接口(需管理员权限)、超级管理员接口。
| 类别 | 方法 | 路由 | 说明 |
|---|---|---|---|
| 公开 | GET | /api/dynasties |
获取朝代树一级节点(含诗词数量) |
| 公开 | GET | /api/authors/<dynasty_id> |
获取某朝代诗人列表(含诗词数量) |
| 公开 | GET | /api/poems/<author_id> |
获取某诗人诗词列表 |
| 公开 | GET | /api/poem/detail?poem_id= |
获取诗词详情(含标签) |
| 公开 | GET | /api/search?q= |
全文搜索诗词(标题/作者/正文) |
| 公开 | GET | /api/stats |
统计数据(朝代/诗人/诗词/标签数) |
| 管理 | POST | /api/poem/save |
保存诗词编辑(正文/赏析/翻译) |
| 管理 | POST | /api/poem/tag/add |
批量添加标签 |
| 管理 | POST | /api/poem/tag/remove |
移除单个标签 |
| 管理 | POST | /api/author/add |
添加作者 |
| 管理 | POST | /api/author/delete/<author_id> |
删除作者(级联删除其所有诗词) |
| 管理 | POST | /api/vocab/add |
添加受控词条 |
| 超级管理 | POST | /api/user/add |
添加管理员账号 |
4.2 权限控制实现
采用 Session + 装饰器 的轻量方案,这个内容不论是Deepseek还是Kimi、智谱、GPT、豆包等待,都能实现
4.3 关键后端代码:ORM 映射第三章 Schema
KBCP_models.py 直接映射第三章设计的五张核心表:
# 具体实现略了
db = SQLAlchemy()
class Dynasty(db.Model):
__tablename__ = 'dynasty'
class Author(db.Model):
__tablename__ = 'author'
class Poem(db.Model):
__tablename__ = 'poem'
class Vocab(db.Model):
__tablename__ = 'vocab'
class PoemTag(db.Model):
__tablename__ = 'poem_tag'
💡 设计要点:
PoemTag作为中间表,实现了poem与vocab的多对多关系。这与第三章的 Schema 设计完全一致,保证了标签的标准化——所有标签必须从vocab表中选取,杜绝自由文本标签。
五、智能诗词打标签:LLM 的工程化实践
5.1 为什么需要 AI 打标?
6.2 万首诗词,人工标注不现实。但标签质量直接决定后续 RAG 检索的效果。我的方案是:
- 受控词表约束:LLM 只能从
vocab表中选择标签,不能自创 - 多维度标注:主题、风格、情感、意象、季节、节令,每首诗最多 3 个标签/类别
- 增量更新:支持断点续传,已分析的诗不会重复处理
- 多模型后端:本地 Ollama(免费)+ 云端 API(快速),按需切换
5.2 架构设计
KBCP_AutoTag.py (分析主控)
├── 读取 poem 表(跳过已分析)
├── 读取 vocab 表(获取受控词表)
├── 构建 Prompt(诗词 + 可用标签列表)
├── 调用 KBCP_LLM_Provider.py
│ ├── OllamaProvider (本地: http://localhost:11434)
│ ├── DeepSeekProvider (云端: api.deepseek.com)
│ └── ZhipuProvider (云端: open.bigmodel.cn)
├── 解析 LLM 返回的 JSON
├── 匹配 vocab_id → 写入 poem_tag 表
└── 写入 auto_tag_log(断点续传)
5.3 Prompt 工程:为什么用 XML 标签?
在 Prompt 设计中,采用了 XML 标签结构化 的方式。这与传统纯文本 Prompt 相比,有显著优势:
根据 Anthropic 官方《Prompt Engineering Guide》的推荐,XML 标签能利用 LLM 在预训练阶段阅读大量代码(HTML/XML)的特性,强制给 Token 加上"路标"和"围栏",从而把概率猜测变成确定性执行。
我的 Prompt 模板:
你是一位精通中华诗词的分析专家。分析下面这首诗,为每个类别
从可用标签中选择最合适的标签(每个类别最多选3个)。
要求:
1. 只输出 JSON 格式,不要输出任何其他内容
2. 仅从下方"可用标签"中选择,不要自创标签
3. 类别名称使用英文
4. 如果某类别无法确定,省略该字段
输出示例:
{"theme":"思乡","style":"清新","emotion":"哀愁","imagery":"月","season":"秋"}
可用标签:
【theme】思乡、送别、边塞、怀古、山水、田园……
【style】豪放、婉约、沉郁、清新、雄浑……
……
诗题:静夜思
作者:李白
诗歌正文:
床前明月光
疑是地上霜
……
5.4 LLM 结果解析:先提取 JSON,再清洗
许多开发者的习惯是"先清洗思考链,再提取 JSON",但这容易误删 JSON 中的方括号。采用 “先定位 JSON,再解析” 的策略:
import re
import json
def parse_llm_response(response_text, vocab_dict):
"""解析 LLM 返回的文本,提取 JSON 标签结果"""
# 策略:先定位 JSON 对象(防止方括号被误当作思考链清除)
# 1. 直接定位 JSON 对象
json_match = re.search(r'\{.*\}', response_text, re.DOTALL)
if not json_match:
return None, "未找到 JSON 对象"
json_str = json_match.group()
# 2. 自动修复常见格式问题
json_str = json_str.replace("'", '"') # 单引号转双引号
json_str = re.sub(r',\s*\}', '}', json_str) # 去除末尾逗号
json_str = re.sub(r',\s*\]', ']', json_str) # 去除数组末尾逗号
# 3. 解析 JSON
try:
result = json.loads(json_str)
except json.JSONDecodeError as e:
return None, f"JSON 解析失败: {e}"
# 4. 标签匹配:精确优先 → 模糊匹配兜底
tags = {}
for cat in ['theme', 'style', 'emotion', 'imagery', 'season', 'festival']:
label = result.get(cat, "")
if not label:
continue
# 精确匹配
if label in vocab_dict.get(cat, {}):
tags[cat] = label
else:
# 模糊匹配:包含关系
for vocab_label in vocab_dict.get(cat, {}):
if label in vocab_label or vocab_label in label:
tags[cat] = vocab_label
break
return tags, "ok"
5.5 多模型提供者设计
通过抽象层 KBCP_LLM_Provider.py,实现无缝切换:
具体的代码可以看Github。
5.7 性能与成本对比
| 提供者 | 模型 | 每首耗时 | 1万首耗时 | 成本 | 适用场景 |
|---|---|---|---|---|---|
| Ollama 本地 | deepseek-r1:8b | 5-15s | 14-42h | 免费 | 本地开发、数据敏感 |
| DeepSeek API | deepseek-chat | 1-3s | 3-8h | ~¥0.5/百万token | 批量标注、快速验证 |
| 智谱 GLM API | glm-4-flash | 1-3s | 3-8h | ~¥0.5/百万token | 国内稳定、薅羊毛 |
💡 实际经验:智谱 GLM-4-Flash 对中文诗词的理解能力出色,且新用户有免费额度,6.2 万首诗词的标注成本可控制在极低水平。
下一章,将会介绍诗词的Web可视化的效果和初步运行的一些统计。
🌟 如果本文对你有帮助,欢迎 Star 支持!
GitHub 开源地址:https://github.com/liang1057/Knowledge-Base-of-Chinese-Poetry
CSDN 专栏:中华诗词知识库(KBCP)系列文章
📧 交流邮箱:liang1057@163.com
更多推荐
所有评论(0)