知识图谱与 RAG 结合实战
课程简介
财务文档知识图谱构建与图增强检索的完整实战。
🎬 本课程视频:Advanced RAG — 构建与评估高级 RAG 应用
知识图谱与 RAG 结合实战:金融文档案例
一、为什么选择金融文档?
金融文档是知识图谱与 RAG 结合的理想应用场景,原因有三:
- 信息结构化程度高:财报、公告、研报中涉及大量结构化信息——公司名称、财务数据、时间、人物关系等,这些天然适合用知识图谱来建模
- 精准性要求极高:金融领域的问答对准确性要求极高,0.1% 的误差可能导致重大决策失误。知识图谱的确定性推理能力在这里尤为重要
- 多跳推理需求频繁:金融分析经常涉及多跳推理,如「A 公司供应链上游企业中有哪些上市公司受到了 B 政策的影响」
二、项目架构概览
整个系统分为四个核心模块:
非结构化文档(财报、公告、研报)
↓
模块 1:本体设计 → 定义实体类型、关系类型、属性
↓
模块 2:LLM 实体关系抽取 → 从文档中自动抽取知识
↓
模块 3:图增强检索 → 向量检索 + 图查询并行执行
↓
模块 4:融合生成 → 结合检索结果生成最终回答
三、第一步:本体设计
3.1 实体类型定义
// 金融领域知识图谱的实体类型
(:Company) // 公司:上市公司、子公司、关联公司
- name: string
- ticker: string // 股票代码
- industry: string // 行业分类
- market_cap: float // 市值
(:Person) // 人物:高管、大股东、分析师
- name: string
- title: string // 职位
- join_date: date
(:Product) // 产品:主要产品线
- name: string
- category: string // 产品品类
- launch_date: date
(:FinancialMetric) // 财务指标
- name: string // 如「营收」「净利润」「毛利率」
- value: float
- period: string // 如「2024Q1」「FY2024」
- unit: string // 单位
(:Event) // 重大事件
- type: string // 如「收购」「上市」「人事变动」
- date: date
- description: string
3.2 关系类型定义
// 公司间关系
(:Company)-[:SUBSIDIARY_OF {ownership_pct: float}]->(:Company)
(:Company)-[:COMPETES_WITH]->(:Company)
(:Company)-[:SUPPLIER_OF]->(:Company)
(:Company)-[:CUSTOMER_OF]->(:Company)
// 公司-产品关系
(:Company)-[:PRODUCES {since: date}]->(:Product)
(:Company)-[:MARKET_SHARE {value: float, period: string}]->(:Product)
// 公司-指标关系
(:Company)-[:HAS_METRIC]->(:FinancialMetric)
// 人物关系
(:Person)-[:CEO_OF {since: date}]->(:Company)
(:Person)-[:BOARD_MEMBER_OF]->(:Company)
(:Person)-[:SHAREHOLDER_OF {ownership_pct: float}]->(:Company)
// 事件关系
(:Company)-[:INVOLVED_IN]->(:Event)
(:Event)-[:AFFECTS {impact: string}]->(:Company)
四、第二步:LLM 驱动的实体关系抽取
4.1 抽取管道
class FinancialKGExtractor:
'''从金融文档中抽取实体的管道'''
def extract_from_10k(self, filing_text):
'''从 10-K 年报中抽取知识'''
# 分段处理:按章节分割
sections = self._split_sections(filing_text)
all_entities = []
all_relations = []
# 逐章节处理
for section in sections:
if section.heading in ["业务概览", "管理层讨论", "财务数据"]:
entities, relations = self._extract_section(section)
all_entities.extend(entities)
all_relations.extend(relations)
# 去重和实体链接
merged = self._deduplicate_and_link(all_entities)
return merged, all_relations
def _extract_section(self, section):
'''使用 LLM 抽取一个章节中的实体和关系'''
prompt = f'''
从以下金融文档章节中抽取实体和关系。
已知实体类型:Company, Person, Product, FinancialMetric, Event
已知关系类型:CEO_OF, PRODUCES, HAS_METRIC, COMPETES_WITH, SUBSIDIARY_OF
章节内容:
{section.content}
请输出 JSON 格式:
{{
"entities": [
{{"name": "...", "type": "Company", "properties": {{"ticker": "...", "industry": "..."}}}}
],
"relations": [
{{"subject": "...", "relation": "CEO_OF", "object": "...", "properties": {{"since": "2020"}}}}
]
}}
'''
result = llm.generate(prompt)
return self._parse_json_result(result)
4.2 实体链接与消歧
def entity_linking(candidates, existing_kg):
'''将抽取的实体链接到已有图谱中的节点'''
linked_entities = []
for entity in candidates:
# 精确匹配
exact_match = existing_kg.find_exact(entity.name)
if exact_match:
entity.kg_id = exact_match.id
linked_entities.append(entity)
continue
# 模糊匹配(同义词、缩写)
fuzzy_matches = existing_kg.find_similar(entity.name, threshold=0.85)
if fuzzy_matches:
# 如果有多个模糊匹配,让 LLM 判断
best = llm.disambiguate(entity, fuzzy_matches)
entity.kg_id = best.id
linked_entities.append(entity)
continue
# 没有匹配,创建新节点
new_node = existing_kg.create_node(entity)
entity.kg_id = new_node.id
linked_entities.append(entity)
return linked_entities
五、第三步:图增强检索
5.1 混合检索策略
class HybridFinancialRetriever:
'''金融领域的混合检索器——向量检索 + 图查询'''
def retrieve(self, question):
# 1. LLM 分析问题判断是否需要图查询
question_type = self._classify_question(question)
# 2. 并行执行两种检索
vector_results = self._vector_retrieve(question)
graph_results = self._graph_retrieve(question) if question_type.needs_graph else []
# 3. 结果融合
combined = self._fuse_results(vector_results, graph_results)
return combined
def _classify_question(self, question):
'''判断问题是需要图查询、向量检索还是两者都需要'''
prompt = f'''
分类以下问题需要的检索类型:
- vector_only: 只需要语义搜索
- graph_only: 只需要精确的图查询
- hybrid: 两者都需要
问题:{question}
请只返回分类名称。
'''
return llm.generate(prompt)
def _graph_retrieve(self, question):
'''针对金融问题的专用图查询'''
# 预定义的查询模板
templates = {
"revenue": '''
MATCH (c:Company {name: $company})-[:HAS_METRIC]->(m:FinancialMetric)
WHERE m.name = 'revenue' AND m.period = $period
RETURN m.value, m.unit
''',
"competitors": '''
MATCH (c:Company {name: $company})-[:COMPETES_WITH]->(competitor:Company)
RETURN competitor.name, competitor.market_cap
''',
"ceo_history": '''
MATCH (c:Company {name: $company})<-[:CEO_OF]-(p:Person),
(p)-[:WORKED_FOR]->(other:Company)
RETURN p.name, other.name
'''
}
# 用 LLM 选择模板并填充参数
template_name, params = self._match_template(question, templates)
if template_name:
cypher = templates[template_name]
return self.kg.run(cypher, params)
# 没有匹配模板,让 LLM 生成 Cypher
cypher = self._generate_cypher(question)
return self.kg.run(cypher)
5.2 向量检索与图查询的互补
向量检索和图查询在金融场景中的分工:
| 场景 | 向量检索 | 图查询 |
|---|---|---|
| 「新能源汽车行业最近有什么趋势?」 | ✓ 语义匹配 | ✗ |
| 「比亚迪 2024 年营收是多少?」 | ✗ | ✓ 精确数值 |
| 「特斯拉的竞争对手有哪些?」 | ✗ | ✓ 关系查询 |
| 「分析一下宁德时代在供应链中的地位」 | ✓ 解释性分析 | ✓ 供应链关系 |
六、第四步:融合生成
def generate_answer(question, vector_context, graph_context):
'''结合两种检索结果生成最终答案'''
# 格式化检索结果
formatted_vector = format_vector_results(vector_context)
formatted_graph = format_graph_results(graph_context)
prompt = f'''
你是一个金融领域 AI 分析师。请基于以下信息回答用户的问题。
用户问题:{question}
【向量检索结果 - 提供背景信息和解释】
{formatted_vector}
【知识图谱查询结果 - 提供精确的事实数据】
{formatted_graph}
请基于以上信息给出准确的回答。
引用的数据请在括号中标注来源是「知识图谱」还是「文档库」。
'''
return llm.generate(prompt)
七、质量保证与监控
7.1 数据质量检查
def quality_check(kg_data):
'''对抽取的数据进行质量检查'''
issues = []
# 完整性检查
for entity in kg_data.entities:
if entity.type == "Company" and not entity.properties.get("ticker"):
issues.append(f"公司 {entity.name} 缺少股票代码")
# 一致性检查
for rel in kg_data.relations:
if rel.type == "HAS_METRIC" and "value" not in rel.properties:
issues.append(f"指标关系缺少数值")
# 时效性检查
for metric in kg_data.financial_metrics:
if is_older_than(metric.period, "2 quarters"):
issues.append(f"指标 {metric.name} 数据已过期")
return issues
7.2 检索效果监控
定期评估图增强检索的效果:
- 图查询的准确率和召回率
- 图查询的延迟(P95 应 < 500ms)
- 向量和图的互补率(单独一种检索无法返回结果的比例)
八、总结
金融文档是知识图谱与 RAG 结合的理想场景。通过严谨的本体设计、LLM 驱动的实体关系抽取、图增强的混合检索和融合生成,可以构建一个比纯向量 RAG 更精确、更可靠的金融问答系统。这套方法可以灵活迁移到医疗、法律等结构化信息密集的领域。
五、金融文档 KG + RAG 的实际效果
5.1 性能对比
| 评估维度 | 纯向量 RAG | KG+向量混合 RAG | 提升 |
|---|---|---|---|
| 事实准确率 | 82% | 96% | +14% |
| 多跳问答 | 65% | 91% | +26% |
| 幻觉率 | 15% | 4% | -73% |
| 可解释性 | 低 | 高 | 显著 |
5.2 典型金融场景
场景一:产业链分析
问题:“华为的供应商中有哪些是 A 股上市公司?”
- 纯向量 RAG:可能返回华为的子公司、客户、合作伙伴等混杂结果
- KG+RAG:精确查询华为-供应链-上市公司路径,结果准确
场景二:关联交易检测
问题:“A 公司和 B 公司有哪些共同的投资方?”
- 通过图谱多跳查询,可以发现跨多个层级的间接关联
六、部署与性能优化
- 索引优化:为常用查询模式建立索引
- 缓存策略:缓存热点查询结果
- 查询超时:设置执行超时防止慢查询拖垮系统
- 结果限制:限制返回结果数量减少 Token 消耗
七、总结
知识图谱与 RAG 的结合是构建高精度问答系统的关键技术路线。
关键要点回顾:
- 金融文档中的实体关系天然适合用 KG 建模
- LLM 可以从非结构化文档中自动抽取知识
- 多阶段抽取提升实体关系质量
- 图查询+向量检索的混合策略优于单一方案
- 事实准确率可从 82% 提升到 96%
五、金融文档 KG + RAG 的实际效果
5.1 性能对比
| 评估维度 | 纯向量 RAG | KG+向量混合 RAG | 提升 |
|---|---|---|---|
| 事实准确率 | 82% | 96% | +14% |
| 多跳问答 | 65% | 91% | +26% |
| 幻觉率 | 15% | 4% | -73% |
| 可解释性 | 低 | 高 | 显著 |
5.2 典型金融场景
场景一:产业链分析
问题:“华为的供应商中有哪些是 A 股上市公司?”
- 纯向量 RAG:可能返回华为的子公司、客户、合作伙伴等混杂结果
- KG+RAG:精确查询华为-供应链-上市公司路径,结果准确
场景二:关联交易检测
问题:“A 公司和 B 公司有哪些共同的投资方?”
- 通过图谱多跳查询,可以发现跨多个层级的间接关联
六、部署与性能优化
- 索引优化:为常用查询模式建立索引
- 缓存策略:缓存热点查询结果
- 查询超时:设置执行超时防止慢查询拖垮系统
- 结果限制:限制返回结果数量减少 Token 消耗
七、总结
知识图谱与 RAG 的结合是构建高精度问答系统的关键技术路线。
关键要点回顾:
- 金融文档中的实体关系天然适合用 KG 建模
- LLM 可以从非结构化文档中自动抽取知识
- 多阶段抽取提升实体关系质量
- 图查询+向量检索的混合策略优于单一方案
- 事实准确率可从 82% 提升到 96%
五、金融文档 KG + RAG 的实际效果
5.1 性能对比
| 评估维度 | 纯向量 RAG | KG+向量混合 RAG | 提升 |
|---|---|---|---|
| 事实准确率 | 82% | 96% | +14% |
| 多跳问答 | 65% | 91% | +26% |
| 幻觉率 | 15% | 4% | -73% |
| 可解释性 | 低 | 高 | 显著 |
5.2 典型金融场景
场景一:产业链分析
问题:“华为的供应商中有哪些是 A 股上市公司?”
- 纯向量 RAG:可能返回华为的子公司、客户、合作伙伴等混杂结果
- KG+RAG:精确查询华为-供应链-上市公司路径,结果准确
场景二:关联交易检测
问题:“A 公司和 B 公司有哪些共同的投资方?”
- 通过图谱多跳查询,可以发现跨多个层级的间接关联
六、部署与性能优化
- 索引优化:为常用查询模式建立索引
- 缓存策略:缓存热点查询结果
- 查询超时:设置执行超时防止慢查询拖垮系统
- 结果限制:限制返回结果数量减少 Token 消耗
七、总结
知识图谱与 RAG 的结合是构建高精度问答系统的关键技术路线。
关键要点回顾:
- 金融文档中的实体关系天然适合用 KG 建模
- LLM 可以从非结构化文档中自动抽取知识
- 多阶段抽取提升实体关系质量
- 图查询+向量检索的混合策略优于单一方案
- 事实准确率可从 82% 提升到 96%
延伸阅读
- 📺 B 站播放列表:Advanced RAG — 构建与评估高级 RAG 应用
- 📚 更多学习资源,请访问 deeplearning.ai 官网