大模型之路7-6:中国人都会喜欢的知识库——中华诗词知识库(同步Github)人工智能应用集成

发布时间:2026/7/30 17:14:22
大模型之路7-6:中国人都会喜欢的知识库——中华诗词知识库(同步Github)人工智能应用集成 中华诗词知识库 · 第六章人工智能应用集成Knowledge Base of Chinese Poetry (KBCP) — Chapter 6: AI in ActionGitHub 开源地址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失败则 SQLAssistSQLAssistText-to-SQLAgent 中枢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含多少/几首/最多/总数确定性计数 / SQLAssist2COMPARE含与/和/对比/区别且有两实体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(rSELECT\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 余弦相似度示意dotnp.dot(query_vec,emb_vec)normnp.linalg.norm(query_vec)*np.linalg.norm(emb_vec)simdot/normifnorm0else0同一套向量还能做语义推荐给定一首诗按余弦相似度排序召回意境相近的作品实现读这首诗的人也喜欢。五、第四关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_tagvocabcompare_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_TURNS5与多轮对话指代消解用户问完李白接着说他写月亮的诗多吗他会被替换为李白再处理。⚠️反幻觉铁律写进 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-PoetryCSDN 专栏中华诗词知识库KBCP系列文章 交流邮箱liang1057163.com版权声明本文为博主原创文章转载请附上原文出处链接和本声明。