4. 知识图谱辅助的大模型推理增强

任务说明

本案例构建一个知识图谱辅助的大模型推理增强系统。系统接收用户自然语言问题,通过命名实体识别与关系映射,从知识图谱中检索相关事实三元组,将检索结果拼接为上下文提示词,调用大模型生成最终答案。目标是通过外部结构化知识弥补大模型参数化知识的不足,提升事实性问题的回答准确率。

系统架构

用户问题 "周杰伦的妻子是谁?" 实体识别 + 关系映射 实体: 周杰伦 → kg:QID_zhoujielun 关系: 妻子 → kg:spouse 知识图谱检索 SPARQL/Cypher查询 返回三元组列表 提示词构造 知识上下文 + 原始问题 大模型 生成答案 最终答案 "昆凌" 知识图谱存储 (周杰伦, spouse, 昆凌) (周杰伦, bornIn, 台湾) (昆凌, occupation, 演员) 查询 实体映射

核心实现

以下代码实现了一个最小可运行的完整闭环:内置小型知识图谱(以Python字典模拟三元组存储),通过基于规则的关键词匹配完成实体识别与关系映射,检索返回匹配的三元组,构造增强提示词后调用大模型API(以兼容接口为例)。

# kg_enhanced_llm.py
"""知识图谱辅助的大模型推理增强 - 最小可运行实现"""
import json
from typing import Dict, List, Tuple, Optional
import requests  # 需安装: pip install requests

# ---------- 1. 知识图谱存储(以字典模拟三元组) ----------
# 格式: {(head, relation): [tail1, tail2, ...]}
KNOWLEDGE_GRAPH: Dict[Tuple[str, str], List[str]] = {
    ("周杰伦", "妻子"): ["昆凌"],
    ("周杰伦", "出生地"): ["中国台湾省新北市"],
    ("周杰伦", "职业"): ["歌手", "音乐制作人", "演员"],
    ("昆凌", "职业"): ["演员", "模特"],
    ("昆凌", "丈夫"): ["周杰伦"],
    ("中国台湾省新北市", "所属国家"): ["中国"],
}

# ---------- 2. 实体识别与关系映射(基于规则) ----------
# 实体词典: 别名 → 标准实体名
ENTITY_DICT = {
    "周杰伦": "周杰伦", "周董": "周杰伦", "杰伦": "周杰伦",
    "昆凌": "昆凌", "Hannah": "昆凌",
    "新北市": "中国台湾省新北市", "台湾": "中国台湾省新北市",
}

# 关系词典: 自然语言表达 → 标准关系名
RELATION_DICT = {
    "妻子": "妻子", "老婆": "妻子", "配偶": "妻子",
    "出生地": "出生地", "出生于": "出生地", "哪里出生": "出生地",
    "职业": "职业", "做什么": "职业", "工作": "职业",
    "丈夫": "丈夫", "老公": "丈夫",
    "国家": "所属国家", "哪个国家": "所属国家",
}

def extract_entities_and_relation(question: str) -> Tuple[Optional[str], Optional[str]]:
    """从问题中提取实体和关系"""
    entity = None
    for alias, std_name in ENTITY_DICT.items():
        if alias in question:
            entity = std_name
            break
    
    relation = None
    for expr, std_rel in RELATION_DICT.items():
        if expr in question:
            relation = std_rel
            break
    
    return entity, relation

# ---------- 3. 知识图谱检索 ----------
def query_kg(entity: str, relation: str) -> List[str]:
    """在知识图谱中查询 (entity, relation) 对应的所有tail值"""
    return KNOWLEDGE_GRAPH.get((entity, relation), [])

# ---------- 4. 提示词构造 ----------
def build_prompt(question: str, kg_results: List[str]) -> str:
    """将知识图谱检索结果与原始问题拼接为增强提示词"""
    if not kg_results:
        return f"请回答以下问题:{question}\n(注意:知识库中未找到相关事实,请基于自身知识回答。)"
    
    knowledge_text = ";".join(kg_results)
    prompt = f"""请基于以下已知事实回答问题。

已知事实:{knowledge_text}

问题:{question}

请直接给出答案,不要解释过程。"""
    return prompt

# ---------- 5. 大模型调用(兼容接口) ----------
def call_llm(prompt: str, api_url: str, : str, model: str = "-turbo") -> str:
    """调用大模型API,返回生成的文本"""
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {}"
    }
    payload = {
        "model": model,
        "messages": [{"role": "user", "content": prompt}],
        "temperature": 0.2
    }
    try:
        resp = requests.post(f"{api_url}/chat/completions", headers=headers, json=payload, timeout=30)
        resp.raise_for_status()
        data = resp.json()
        return data["choices"][0]["message"]["content"].strip()
    except Exception as e:
        return f"[大模型调用失败: {e}]"

# ---------- 6. 主流程 ----------
def kg_enhanced_qa(question: str, api_url: str, : str, model: str = "-turbo") -> Dict:
    """知识图谱增强的问答主流程"""
    # 步骤1: 实体识别与关系映射
    entity, relation = extract_entities_and_relation(question)
    
    # 步骤2: 知识图谱检索
    kg_results = []
    if entity and relation:
        kg_results = query_kg(entity, relation)
    
    # 步骤3: 构造提示词
    prompt = build_prompt(question, kg_results)
    
    # 步骤4: 调用大模型
    answer = call_llm(prompt, api_url, , model)
    
    return {
        "question": question,
        "entity": entity,
        "relation": relation,
        "kg_results": kg_results,
        "prompt": prompt,
        "answer": answer
    }

# ---------- 7. 演示入口 ----------
if __name__ == "__main__":
    # 配置(请替换为真实API信息)
    API_URL = "https://api..com/v1"  # 或你的兼容端点
     = "sk-your-key-here"
    
    test_questions = [
        "周杰伦的妻子是谁?",
        "昆凌的职业是什么?",
        "周杰伦出生在哪里?",
        "周杰伦的宠物叫什么?"  # 知识图谱中不存在的事实
    ]
    
    for q in test_questions:
        print(f"\n{'='*50}")
        print(f"问题: {q}")
        result = kg_enhanced_qa(q, API_URL, )
        print(f"识别实体: {result['entity']}")
        print(f"识别关系: {result['relation']}")
        print(f"图谱检索结果: {result['kg_results']}")
        print(f"构造的提示词:\n{result['prompt']}")
        print(f"模型回答: {result['answer']}")

运行与验证

依赖安装:

pip install requests

运行方式:将代码保存为 kg_enhanced_llm.py,在文件末尾的 __main__ 块中填入真实的API地址与密钥,然后执行:

python kg_enhanced_llm.py

验证方法与判定标准:

  1. 实体与关系识别验证:观察输出中“识别实体”和“识别关系”字段。对于问题“周杰伦的妻子是谁?”,应分别输出“周杰伦”和“妻子”。若识别为None,说明词典未覆盖该表达,需扩充ENTITY_DICT或RELATION_DICT。
  2. 图谱检索验证:对于上述问题,“图谱检索结果”应输出['昆凌']。对于知识图谱中不存在的事实(如“周杰伦的宠物”),应输出空列表[],此时提示词会包含“知识库中未找到相关事实”的说明。
  3. 提示词构造验证:检查“构造的提示词”是否包含检索到的知识文本与原始问题,格式正确。
  4. 端到端验证:配置真实API后运行,观察“模型回答”字段。对于“周杰伦的妻子是谁?”,若模型输出“昆凌”或包含“昆凌”的表述,则判定通过。对于图谱未覆盖的问题,模型应基于自身知识回答,此时回答质量取决于模型本身能力。

预期输出(确定性部分):在不调用大模型的情况下,前三个测试问题的实体识别、关系映射与图谱检索结果可确定如下:

问题: 周杰伦的妻子是谁?
识别实体: 周杰伦
识别关系: 妻子
图谱检索结果: ['昆凌']

问题: 昆凌的职业是什么?
识别实体: 昆凌
识别关系: 职业
图谱检索结果: ['演员', '模特']

问题: 周杰伦出生在哪里?
识别实体: 周杰伦
识别关系: 出生地
图谱检索结果: ['中国台湾省新北市']

问题: 周杰伦的宠物叫什么?
识别实体: 周杰伦
识别关系: None
图谱检索结果: []

以上为代码逻辑直接推出的确定性结果,不涉及模型输出。模型回答部分需配置真实API后实测验证。