大模型之路7-6:中国人都会喜欢的知识库——中华诗词知识库(同步Github)人工智能应用集成
2026/7/30 17:14:05 网站建设 项目流程

📊 中华诗词知识库 · 第六章:人工智能应用集成

Knowledge Base of Chinese Poetry (KBCP) — Chapter 6: AI in Action

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


🎯 前言

前五章我们完成了数据收集 → 数据清洗 → Schema 设计 → Web 系统 → AI 自动打标,知识库已经"能存、能看、能管、能标"。但"标好标签"只是起点——真正的价值在于:让使用者用自然语言与这 6.2 万首诗词对话

本章是系列的收官之作,聚焦"人工智能的应用层":一个用户问题从输入到回答,背后究竟经过了哪些智能处理?

💡核心观点:真正的"智能"不是把数据一股脑丢给大模型,而是让大模型在确定的边界内"思考"。本章要讲的,正是一套"确定性 + 语义 + 推理"三者协作的混合智能架构。


一、整体架构:混合智能(Hybrid Intelligence)

一个常见的误区是:RAG 万能,把所有诗词塞进向量库、召回 top-k、丢给 LLM 生成,就完事了。这都是技术不成熟的人的表现,相当于硬吃LLM, 完全不是正确使用人工智能的方式。
这种方式都是半吊子人工智能,完全没有弄明白LLM的能力:

向量库

距离计算召回

LLM 生成答案

比如,在诗词知识库这个场景里,纯 RAG 有三个致命软肋:

RAG 的软肋具体表现本项目的解法
算不了数"李白写了多少首诗"需要COUNT(*),向量相似度给不出精确数字走确定性 SQL 计数快路径
比不了"李白和杜甫谁写月亮的诗更多"需要 JOIN + 聚合走 Text-to-SQL 生成聚合查询
容易幻觉LLM 凭记忆补出"杜甫有 1500 首"之类错误工具返回结构化事实,LLM 只负责"串讲"

正确的方法应该是:

向量库

LLM 辅助查询

召回答案

LLM 生成答案

本项目的智能化RAG架构是在已有数据库(知识库)的基础上,使用LLM提升智能理解能力:

作者实体

诗作实体 / 找诗

统计类

标签类 / 比较类

分析类

用户自然语言问题

意图分析
别名 / 实体消歧

意图归类
规则分类 7 类

SQL: 查作者信息

SQL: 标题 / 诗句溯源

确定性 COUNT
失败则 SQLAssist

SQLAssist
Text-to-SQL

Agent 中枢
LLM 调度工具

查询诗词 / get_author ...

semantic_search → RAG 向量

ResultFormatter
统一格式化

自然语言回答

一句话总结:确定性事实交给 SQL,语义联想交给向量检索,综合表达与多步推理交给 LLM——各司其职,互不越界。


二、第一关:别名映射与查询理解(实体消歧)

2.1 别名映射 AliasMapper

用户不会规规矩矩地输入"苏轼",他可能说"子瞻"“东坡”“苏东坡”。系统启动时从author表一次性加载name / courtesy_name(字) / art_name(号) / other_names(别名),构建{别名小写 → 标准名}的哈希索引:

# KBCP_AliasMapper.py 核心逻辑(示意)forainauthors:self._add_alias(a['name'],'author',aid)# 标准名forfldin('courtesy_name','art_name','other_names'):foraliasinself._split(a[fld]):self._add_alias(alias,'author',aid,a['name'])# 子瞻→苏轼

resolve("子瞻")直接返回{"matches": [("子瞻","苏轼","author","F0282")]},后续所有路径都基于标准名查询,从根本上消除"同名不同实"的歧义。
同时,通过数据库中的作者信息等,组成最好的答案。

2.2 查询分类 QueryClassifier

分类器完全基于规则、不调用 LLM,毫秒级、零成本、结果可复现:

优先级类型触发特征路由去向
1STATS含"多少/几首/最多/总数"确定性计数 / SQLAssist
2COMPARE含"与/和/对比/区别"且有两实体SQLAssist 聚合
3ENTITY_AUTHOR含"是谁/介绍/生平"SQL 查作者
4FIND_POEM像诗句(含标点或 5/7 字句式)SQL 诗句溯源
5ENTITY_POEM含《》书名号标题SQL 查作品
6TAG_BASED含"主题/风格/情感/意象"SQLAssist 标签检索
7ANALYTICAL其余(赏析、联想等)Agent + RAG

💡为什么不用 LLM 做分类?分类是高频、低熵、强模式匹配任务,规则引擎在准确率、延迟、成本上全面优于 LLM,且不会因为模型"心情"而抖动。把 LLM 留给真正需要语义理解的地方。


三、第二关:Text-to-SQL —— 让大模型写查询,但不许乱来

统计、对比、主题检索这类结构化查询,本质是"自然语言 → SQL"。这是 LLM 的强项,但也是幻觉重灾区:它常会编造字段名、写SELECT *、甚至想DELETE。本项目的SQLAssist用三重约束把这个能力关进笼子里。

3.1 元数据注入:给 LLM 一份"数据库说明书"

系统从第三章设计的myschema表读出字段中文名 → 键名 → 类型对照,连同外键 JOIN 路径、检索优先级、禁止事项,一起注入 Prompt:

数据库表结构(字段中文名 -> 字段键名): poem: 标题(title: text) | 正文(content: text) | 作者ID(author_id: text) ... vocab: 类目(key: text) | 标签(label: text) ... 外键关联规则(固定 JOIN 路径): poem.author_id = author.author_id poem_tag.poem_id = poem.poem_id poem_tag.vocab_id = vocab.vocab_id 禁止事项: - 只允许 SELECT,禁止 UPDATE/DELETE/INSERT/DROP/ALTER - 禁止 SELECT *(明确列出需要的字段) - 涉及标签必须 JOIN poem_tag + vocab

此外还会注入vocab表的全部标签取值(防止它写"月亮"而库里只有"月")和别名映射结果(“子瞻"→"苏轼”)。

3.2 生成后校验:把"野 SQL"挡在门外

LLM 生成的 SQL 不直接执行,而是先过校验器:

def_validate(self,sql:str)->tuple:# 1. 是否含危险操作danger=['DROP ','DELETE ','INSERT ','UPDATE ','ALTER ']ifany(dinsql.upper()fordindanger):returnFalse,f"禁止使用{d.strip()}操作"# 2. 禁止 SELECT *ifre.search(r'SELECT\s+\*',sql,re.I):returnFalse,"禁止 SELECT *,请明确列出字段"# 3. 引用的字段是否都在 myschema 中(防字段幻觉)valid_cols={row['column_name'].lower()forrowinself._schema}for_,colinre.findall(r'(\w+)\.(\w+)',sql):ifcol.lower()notinvalid_cols:returnFalse,f"字段 '{col}' 不在 myschema 中"returnTrue,''

校验失败时,把错误信息回灌给 LLM 重试(最多 3 次),让它自我修正。最终 SQL 由execute_readonly_sql只读执行,彻底杜绝写操作。

💡这是全章最重要的工程经验:LLM 写 SQL 不可怕,可怕的是"直接执行"。用元数据约束 + 字段白名单 + 只读执行 + 错误重试四道防线,就能把幻觉控制在可接受范围。


四、第三关:RAG 向量检索与语义推荐

开放性问题(“写思乡的诗有哪些”“这首诗表达了什么情感”)不适合 SQL,需要语义检索。

4.1 向量是怎么来的

每首诗词用作者《标题》正文拼接成文本块,再用嵌入模型向量化,存进poem_embedding表:

方案模型特点
主方案paraphrase-multilingual-MiniLM-L12-v2多语言、对古诗+现代提问都友好,需下载
兜底sklearnTF-IDF(字符级 n-gram 1~3)零下载、纯本地,网络受限也能跑

💡 选多语言模型而非纯中文模型,是因为用户提问常是白话(“写想家的诗”),而诗词是文言,多语言模型在跨风格语义对齐上更稳。TF-IDF 用字符级 n-gram而非词级,是因为古诗无空格、分词反而引入噪声。

4.2 多源检索与余弦相似度

RAGIndex同时从诗词(向量)、作者(LIKE)、标签(向量语义匹配)三个来源召回,合并去重后取 top-k。相似度用余弦:

[
\mathrm{sim}(q, d) = \frac{\vec q \cdot \vec d}{\lVert \vec q \rVert \lVert \vec d \rVert}
]

# KBCP_RAG_Index.py 余弦相似度(示意)dot=np.dot(query_vec,emb_vec)norm=np.linalg.norm(query_vec)*np.linalg.norm(emb_vec)sim=dot/normifnorm>0else0

同一套向量还能做语义推荐:给定一首诗,按余弦相似度排序召回"意境相近"的作品,实现"读这首诗的人也喜欢"。


五、第四关:Agent 中枢与工具调用(Function Calling)

以上三关偏"确定性"。最体现 AI 深度的,是把 LLM 当大脑、把工具当手脚的 Agent 中枢(KBCP_Agent)。

5.1 工具集:给大模型装上"手脚"

LLM 本身不会查数据库,但能"决定调用哪个工具、传什么参数"。系统向 LLM 暴露 7 个结构化工具:

工具作用内部确定性保障
search_poem按诗句片段找出处SQLLIKE精确匹配
get_poem_full返回诗词全文/译文/赏析主键查询
get_author查诗人生平字号别名解析后查表
count_poems统计收录诗数COUNT(*)精确计数
count_poems_by_tag按主题精确计数JOINpoem_tag+vocab
compare_by_tag多诗人主题对比同一标签口径聚合
semantic_search语义向量检索RAGIndex 多源召回
5.2 工具返回"结构化",而非"自然语言"

关键设计:工具返回的是JSON 结构化字典,不是拼给人看的句子。

# KBCP_Tools.py:工具返回结构化数据供 LLM 综合return{"found":True,"author":"李白","total_count":472,# 数字由 SQL 保证精确"per_label":[{"label":"月","count":472}]}

这样 LLM 拿到的是"事实原料",而不是"已完成的答案",它只能基于事实综合表达,从机制上杜绝了编造数字。

5.3 近义理解与多步推理

开启"主题词近义理解"后,用户问"写月亮的诗",系统先让 LLM 把"月亮"扩展为 vocab 中相关的近义标签集合(月/羁旅/思乡…),召回更智能;LLM 扩展不可用时,回退到向量语义匹配。

Agent 还支持多步推理MAX_TURNS=5)与多轮对话指代消解:用户问完"李白",接着说"他写月亮的诗多吗","他"会被替换为"李白"再处理。

⚠️反幻觉铁律(写进 System Prompt):严禁凭记忆作答,所有事实必须来自工具返回;若工具无结果,如实告知"未查到",绝不可臆测。这是把通用大模型改造成"可信知识库助手"的灵魂条款。

5.4 多模型编排与降级

KBCP_LLM_Provider抽象了 Ollama(本地)/ DeepSeek / 智谱 GLM,统一 OpenAI 兼容接口。推理型本地模型(如 deepseek-r1)不支持 function calling,会被自动过滤;云模型按配置优先级串联,上一个不可用自动降级下一个,全部失败时还有本地确定性兜底(直接调 SQL 回答基础问题)。

而且我测试了一个不算是RAG的问题,是一个纯粹的语义理解问题,这个回答也很赞。我感觉这个是纯LLM的回答。有这样的兜底,那就非常棒了。


六、能力全景与落地权衡

把整套 AI 应用层的能力与适用场景汇总如下:

能力技术路线何时走这条路优势
实体消歧规则哈希索引所有问题第一关毫秒级、零成本
查询分类规则引擎所有问题第二关可复现、不抖动
精确计数COUNT(*)“多少首”100% 准确、秒回
结构化检索Text-to-SQL + 校验“对比/主题统计”可聚合、防幻觉
语义联想向量检索(RAG)“赏析/意境/推荐”跨字面语义匹配
综合推理Agent + 工具调用复杂/多步问题LLM 推理 + 事实兜底

混合架构 vs 纯 RAG 的取舍:纯 RAG 实现简单,但面对"计数/对比/精确事实"会集体失灵;混合架构工程复杂度更高,却换来可引用、可解释、可追责的回答——这正是知识库区别于"聊天玩具"的本质。


📝 七、小结

设计目标实现方式
确定性SQL 计数快路径 + Text-to-SQL 只读执行 + 字段白名单
语义性多语言 Embedding + 多源 RAG 检索 + 余弦相似度推荐
智能性Agent 中枢 + 7 个结构化工具 + 多步/多轮推理
可控性别名消歧 + 规则分类 + 反幻觉铁律 + 模型自动降级
可落地Ollama/DeepSeek/智谱多后端 + TF-IDF 纯本地兜底

至此,中华诗词知识库系列六章全部完成:

第1章 数据收集 → 4600+ 诗人 / 62000+ 诗词的原始积累 第2章 数据清洗 → 分句、去重、元数据补全、入库 SQLite 第3章 数据结构设计 → 五表联动 + 受控词表,标准化与可扩展 第4章 Web 与 AI 打标 → Flask 系统 + LLM 多维自动标注 第5章 Web 实现与实例 → 四栏浏览、后台管理、智能问答落地 第6章 人工智能的应用 → 混合智能:消歧 / 分类 / Text-to-SQL / RAG / Agent

从"抓数据"到"会对话",我们走完了一条数据工程 → 知识工程 → 智能应用的完整路径。知识库的价值,不在于囤了多少文本,而在于当有人提问时,它能给出可引用、可解释、可信赖的答案——这就是人工智能在这套系统里真正的落点。

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

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

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

📧 交流邮箱:liang1057@163.com

版权声明:本文为博主原创文章,转载请附上原文出处链接和本声明。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询