2. 知识图谱增强的大模型问答系统
任务说明
构建一个知识图谱增强的大模型问答系统:当用户提出问题时,系统先从知识图谱中检索相关事实,将检索结果与原始问题拼接为增强提示词,再交由大模型生成最终答案。本案例聚焦于“检索-增强-生成”链路的最小可复现实现,使用小型示例知识图谱与模拟大模型接口完成闭环。
系统架构
核心实现
以下代码实现了一个完整的知识图谱增强问答链路。知识图谱以Python字典存储三元组,实体识别通过关键词匹配完成,检索模块返回与问题实体相关的事实,增强模块将事实拼接到提示词中,最后调用模拟的大模型接口生成答案。
# kg_qa_system.py
"""知识图谱增强的大模型问答系统 - 最小可复现实现"""
class KnowledgeGraph:
"""基于字典的简易知识图谱存储"""
def __init__(self):
# 存储形式: (头实体, 关系, 尾实体)
self.triples = [
("图灵奖", "获奖者", "姚期智"),
("图灵奖", "获奖者", "约翰·霍普克罗夫特"),
("图灵奖", "设立年份", "1966年"),
("姚期智", "国籍", "中国"),
("姚期智", "研究领域", "计算理论"),
("约翰·霍普克罗夫特", "国籍", "美国"),
("约翰·霍普克罗夫特", "研究领域", "算法设计"),
("清华大学", "教授", "姚期智"),
]
# 构建索引: 头实体 -> [(关系, 尾实体)]
self.head_index = {}
for h, r, t in self.triples:
self.head_index.setdefault(h, []).append((r, t))
def query_by_head(self, head_entity):
"""根据头实体查询所有关联事实"""
return self.head_index.get(head_entity, [])
class EntityRecognizer:
"""基于词典的实体识别器"""
def __init__(self, kg):
self.entities = set()
for h, r, t in kg.triples:
self.entities.add(h)
self.entities.add(t)
def recognize(self, question):
"""从问题中识别出知识图谱中存在的实体"""
matched = []
for entity in self.entities:
if entity in question:
matched.append(entity)
return matched
class PromptAugmenter:
"""提示词增强器"""
@staticmethod
def augment(question, facts):
"""将检索到的事实拼接到问题后"""
if not facts:
return question
fact_str = ";".join([f"{h}的{r}是{t}" for h, r, t in facts])
return f"已知事实:{fact_str}。\n问题:{question}\n请基于以上事实回答问题。"
class MockLLM:
"""模拟大模型接口(真实场景替换为实际LLM API调用)"""
def generate(self, prompt):
# 模拟:从增强提示词中提取答案
# 实际项目中替换为: .ChatCompletion.create(...) 等
if "已知事实" in prompt:
# 简单模拟:返回提示词中最后的事实
lines = prompt.split("\n")
for line in lines:
if line.startswith("已知事实"):
facts = line.replace("已知事实:", "").replace("。", "").split(";")
if facts:
return f"根据知识图谱,{facts[0]}。"
return "抱歉,我没有足够的信息回答这个问题。"
class KGEnhancedQA:
"""知识图谱增强问答主流程"""
def __init__(self):
self.kg = KnowledgeGraph()
self.recognizer = EntityRecognizer(self.kg)
self.augmenter = PromptAugmenter()
self.llm = MockLLM()
def answer(self, question):
# 1. 实体识别
entities = self.recognizer.recognize(question)
if not entities:
return "无法从问题中识别出知识图谱中的实体。"
# 2. 知识图谱检索
all_facts = []
for entity in entities:
facts = self.kg.query_by_head(entity)
for r, t in facts:
all_facts.append((entity, r, t))
# 3. 提示词增强
enhanced_prompt = self.augmenter.augment(question, all_facts)
# 4. 大模型生成
answer = self.llm.generate(enhanced_prompt)
return answer
# ===== 使用示例 =====
if __name__ == "__main__":
qa_system = KGEnhancedQA()
# 测试问题1
q1 = "谁是图灵奖得主?"
print(f"问题: {q1}")
print(f"答案: {qa_system.answer(q1)}\n")
# 测试问题2
q2 = "姚期智的研究领域是什么?"
print(f"问题: {q2}")
print(f"答案: {qa_system.answer(q2)}\n")
# 测试问题3(无匹配实体)
q3 = "今天天气怎么样?"
print(f"问题: {q3}")
print(f"答案: {qa_system.answer(q3)}")
运行与验证
运行方式:将上述代码保存为 kg_qa_system.py,在Python 3.6+环境中执行 python kg_qa_system.py。
预期输出:基于代码逻辑可直接推出的结果如下:
问题: 谁是图灵奖得主?
答案: 根据知识图谱,图灵奖的获奖者是姚期智。
问题: 姚期智的研究领域是什么?
答案: 根据知识图谱,姚期智的研究领域是计算理论。
问题: 今天天气怎么样?
答案: 无法从问题中识别出知识图谱中的实体。
验证判定标准:
- 问题1和问题2能返回包含知识图谱事实的答案,证明“检索-增强-生成”链路已打通;
- 问题3返回实体识别失败提示,证明系统对图谱外问题有兜底处理;
- 将
MockLLM.generate替换为真实大模型API调用(如、智谱等),保持输入输出接口不变,即可接入实际大模型。
扩展说明:本案例使用字典模拟知识图谱和关键词匹配实体识别,用于演示核心增强链路。生产环境中可将KnowledgeGraph替换为Neo4j等图数据库,将EntityRecognizer替换为基于NLP的命名实体识别模型,将MockLLM替换为实际大模型API,各模块接口保持不变即可平滑迁移。