📊 中华诗词知识库 · 第三章:数据结构设计

Knowledge Base of Chinese Poetry (KBCP) — Chapter 3: Schema

🌟GitHub 开源地址:https://github.com/liang1057/Knowledge-Base-of-Chinese-Poetry
🌟 如果资源对你有帮助,欢迎 Star 支持!
📥 JSON数据下载https://download.csdn.net/download/sdust_dx/92826598


🎯 前言

前两章讲到了数据和数据清洗,本章将正式进入数据层的核心设计——Schema(模式)定义。

中华诗词的数据结构有一个显著特点:半结构化与非结构化并存。一首诗的正文是自由文本,但体裁、格律、意象、情感等属性又需要高度标准化。如果 Schema 设计过于简单,后续 RAG 检索和知识图谱构建将举步维艰;如果设计过于臃肿,又会给数据清洗和入库带来巨大成本。

因此,本章的核心目标是:在“文学自由表达”与“机器可理解”之间找到最佳平衡点


🗂️ 一、总体的数据结构:五表联动与词汇标准化

整个知识库的底层采用 SQLite 作为关系型存储引擎,Schema 层通过 ORM 风格封装了 5 张核心表,形成如下关系:

表名 职责 关键关联
poem 诗词作品主表 外键关联 dynastyauthor
author 诗人/作者信息 通过 dynasty_id 关联朝代
dynasty 朝代元数据 独立基础表,统一时间轴
vocab 受控词汇表 全库标签体系的标准化源头
myschema 元数据记录 记录 Schema 自身版本与变更

注意:所有标签类字段(如 genreformthemestyleemotion 等)均不存储自由文本,而是指向 vocab 表的标准化键值。这为后续的多义词消歧、同义词扩展和向量检索打下了基础。这也是我重构了两次得到的经验。


🏗️ 二、核心表

2.1 诗词表 table_poem — 这也是全库最复杂的实体

poem 表是知识库的核心,字段设计遵循**“分层存储、逐层解析”**的原则。经过多次完善,已经达到了 40+ 个字段,将其划分为 8 个逻辑层:

分层设计思路:

层级 设计意图 典型应用
基础信息 唯一标识与溯源 全库去重、跨库对齐
结构化内容 将自由文本拆解为机器可处理的单元 按句检索、格律校验、文本比对
文学属性 建立体裁与格律的标准化分类 筛选“所有七言律诗”、检索“平水韵作品”
扩展信息 保留人类可读的释义与背景 RAG 生成回答时的引用素材
标签体系 多维度语义标注 向量检索的元数据过滤、主题冲突检测
检索优化 倒排索引与 faceted search 支持 “春天的离别诗”“涉及长安的边塞诗”
RAG 相关 为向量库与知识图谱预留接口 相似作品推荐、引用溯源
管理字段 数据治理与版本控制 审核流程、增量更新
class table_poem(EntityBase):
    def __init__(self):
        super().__init__()
        self.SetTableName('poem')
        
        # 1. 基础信息层
        self.AddColumn(colName='poem_id', colType='text', ...)
        self.AddColumn(colName='title', colType='text', ...)
        self.AddColumn(colName='author', colType='text', ...)
        self.AddColumn(colName='dynasty', colType='text', ...)
        
        # 2. 结构化内容层
        self.AddColumn(colName='content', colType='text', ...)
        self.AddColumn(colName='paragraphs', colType='varchar', ...)
        self.AddColumn(colName='sentences', colType='varchar', ...)
        self.AddColumn(colName='line_count', colType='int', ...)
        self.AddColumn(colName='char_count', colType='int', ...)
        
        # 3. 文学属性层
        self.AddColumn(colName='genre', colType='text', ...)   # 诗/词/曲/赋
        self.AddColumn(colName='form', colType='varchar', ...) # 五言绝句/七言律诗...
        self.AddColumn(colName='meter', colType='text', ...)   # 平水韵/中华新韵
        
        # 4. 扩展信息层
        self.AddColumn(colName='description', colType='text', ...)
        self.AddColumn(colName='translation', colType='text', ...)
        self.AddColumn(colName='appreciation', colType='text', ...)
        self.AddColumn(colName='background', colType='text', ...)
        
        # 5. 知识增强与标签体系层
        self.AddColumn(colName='theme', colType='varchar', ...)
        self.AddColumn(colName='style', colType='varchar', ...)
        self.AddColumn(colName='emotion', colType='varchar', ...)
        self.AddColumn(colName='imagery', colType='varchar', ...)
        self.AddColumn(colName='allusions', colType='varchar', ...)
        
        # 6. 检索优化层
        self.AddColumn(colName='keywords', colType='varchar', ...)
        self.AddColumn(colName='season', colType='text', ...)
        self.AddColumn(colName='festival', colType='text', ...)
        self.AddColumn(colName='places_involved', colType='varchar', ...)
        self.AddColumn(colName='people_involved', colType='varchar', ...)
        
        # 7. RAG 相关层
        self.AddColumn(colName='citation_text', colType='text', ...)
        self.AddColumn(colName='aliases', colType='varchar', ...)
        self.AddColumn(colName='related_poem_ids', colType='varchar', ...)
        
        # 8. 管理层
        self.AddColumn(colName='created_at', colType='text', ...)
        self.AddColumn(colName='data_version', colType='text', ...)
        self.AddColumn(colName='review_status', colType='text', ...)

几个关键字段的深入说明:

  • poem_id 编码规则:采用 朝代编号-作者编号-诗词编号 的三段式结构,例如 T-12345-678901。这种设计天然支持按朝代、按作者分片,且无需 JOIN 即可快速定位。
  • paragraphssentences:词有上下阕,曲有牌调,诗有联句。保留段落切分和句子切分两套数组,既方便前端渲染,也方便 NLP 模型做句级嵌入。
  • citation_text:RAG 输出时必须给出可溯源的原文。该字段强制保留标准原文(含标点),避免在检索-生成链路中出现“篡改原文”的幻觉。

2.2 作者表 table_author — 别名体系

诗人往往有名、字、号、谥号、别称等多重身份标识。如果把这些混在一个字段里,检索“东坡居士”时将无法关联到“苏轼”。

class table_author(EntityBase):
    def __init__(self):
        self.SetTableName('author')
        self.AddColumn(colName='author_id', colType='text', ...)
        self.AddColumn(colName='name', colType='text', ...)          # 标准名:苏轼
        self.AddColumn(colName='courtesy_name', colType='text', ...) # 字:子瞻
        self.AddColumn(colName='art_name', colType='varchar', ...)   # 号:['东坡居士']
        self.AddColumn(colName='other_names', colType='varchar', ...)# 别名:['苏东坡',...]
        self.AddColumn(colName='style_summary', colType='varchar', ...)
        self.AddColumn(colName='major_themes', colType='varchar', ...)
        self.AddColumn(colName='common_imagery', colType='varchar', ...)

设计要点other_namesart_name 均采用 varchar(数组序列化)存储。在入库阶段,通过 OpenCC 进行繁简转换预处理,确保“蘇軾”与“苏轼”指向同一实体。


2.3 朝代表 table_dynasty — 时间轴统一
class table_dynasty(EntityBase):
    def __init__(self):
        self.SetTableName('dynasty')
        self.AddColumn(colName='dynasty_id', colType='text', ...)   # 如 'T'
        self.AddColumn(colName='name', colType='text', ...)         # '唐'
        self.AddColumn(colName='another_name', colType='varchar', ...)# ['李唐','大唐']
        self.AddColumn(colName='start_year', colType='int', ...)
        self.AddColumn(colName='end_year', colType='int', ...)

特别说明name 字段标注为“用于诗词的”标准朝代名。例如“先秦”作为一个统一朝代节点,涵盖夏、商、周、春秋、战国等子时期,避免在诗词分类上过度碎片化。


2.4 词汇表 table_vocab — 全库可控的“语义字典”

这是整个知识库标准化程度最高的表,也是后续 RAG 检索质量的决定性因素:

class table_vocab(EntityBase):
    def __init__(self):
        self.SetTableName('vocab')
        self.AddColumn(colName='vocab_id', colType='text', ...)
        self.AddColumn(colName='name', colType='text', ...)   # 标准类目名,如"主题"
        self.AddColumn(colName='key', colType='text', ...)   # 键:如 "theme"
        self.AddColumn(colName='value', colType='text', ...)  # 值:如 "山水"

为什么必须独立建表?

theme(主题)为例,如果允许自由录入,会出现“山水”“山水田园”“自然山水”等多种写法,导致向量检索时同主题无法聚合。通过 vocab 表强制收敛,所有主题必须从预设词表中选取,保证了** faceted search 的精确性**。这也是我做数据治理和数据标准化工作积累的经验。


2.5 元数据记录表 table_myschema — Schema 的自描述
class table_myschema(EntityBase):
    def __init__(self):
        self.SetTableName('myschema')
        # 记录每个表的字段中文名、键名、类型
        self.AddColumns(colNames=['schema_id','table_name','column_label',
                                  'column_name','type'], ...)

这张表看似“元数据的元数据”,但在实际项目中非常有用:当后续通过代码自动生成前端表单、API 文档或向量库字段映射时,可以直接读取 myschema 获得人类可读的字段说明,避免硬编码。


🔧 三、工程实现亮点

3.1 EntityBase 的 ORM 风格封装

所有表均继承自 EntityBase,通过 AddColumn / AddColumns 链式调用完成字段注册。这种设计的优势在于:

  • 自文档化:字段定义即注释,源码即 Schema 文档。
  • 可扩展:新增字段只需追加一行,不需要去搞SQL。
  • 驱动生成:可基于 EntityBase 的元数据自动生成建表 SQL、Pydantic Model 和前端表单。
3.2 OpenCC 的预处理集成
from opencc import OpenCC
sc2tc = OpenCC('s2t')  # 简体转繁体
tc2sc = OpenCC('t2s')  # 繁体转简体

在数据入库管道中,所有 titlecontentauthor 等字段均会经过繁简双向转换校验。这确保了无论原始数据源是《全唐诗》的繁体版本还是现代整理的简体版本,最终都能归一化处理。

3.3 字段类型的刻意选择
类型 使用场景 原因
text 大段文本 SQLite 的 TEXT 无长度限制,适合正文、赏析
varchar 数组/列表 存储 JSON 序列化的标签数组,如 ["月","霜"]
int 统计值 行数、字数、年份,便于范围查询

🧩 四、与 RAG 架构的衔接

当前 Schema 中,与 RAG 直接相关的字段已预留了三个层次:

  1. 文本层contentparagraphssentences → 用于向量嵌入(Embedding)
  2. 元数据层themestyleemotionimagery → 用于向量检索时的过滤条件(Metadata Filtering)
  3. 关系层related_poem_ids → 用于知识图谱构建和跨文档主题关联

💡 预留说明:源码中注释掉的 relatedsimilarrelated_author 等字段,将在第四章(向量库设计)中决定是保留为关系表,还是直接存入向量数据库的 payload。


📝 五、本章小结

设计目标 实现方式
标准化 vocab 受控词表 + 全库唯一编号
结构化 正文/段落/句子三级切分 + 行数字数统计
可扩展 EntityBase 链式字段注册 + 版本管理字段
RAG 友好 标签体系 + 引用文本 + 相关作品 ID
多语言兼容 OpenCC 繁简转换 + 别名体系

下一章,将会介绍诗词的Web可视化以及使用大数据模型进行的智能化分析。


🌟 如果本文对你有帮助,欢迎 Star 支持!

GitHub 开源地址:https://github.com/liang1057/Knowledge-Base-of-Chinese-Poetry

CSDN 专栏:中华诗词知识库(KBCP)系列文章

📧 交流邮箱:liang1057@163.com

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

更多推荐