第 3 课
← 返回系列列表

知识图谱与 RAG 结合实战

Advanced RAG — 构建与评估高级 RAG 应用

财务文档知识图谱构建与图增强检索的完整实战。

知识图谱与 RAG 结合实战

课程简介

财务文档知识图谱构建与图增强检索的完整实战。

🎬 本课程视频:Advanced RAG — 构建与评估高级 RAG 应用


知识图谱与 RAG 结合实战:金融文档案例

一、为什么选择金融文档?

金融文档是知识图谱与 RAG 结合的理想应用场景,原因有三:

  1. 信息结构化程度高:财报、公告、研报中涉及大量结构化信息——公司名称、财务数据、时间、人物关系等,这些天然适合用知识图谱来建模
  2. 精准性要求极高:金融领域的问答对准确性要求极高,0.1% 的误差可能导致重大决策失误。知识图谱的确定性推理能力在这里尤为重要
  3. 多跳推理需求频繁:金融分析经常涉及多跳推理,如「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 公司有哪些共同的投资方?”
- 通过图谱多跳查询,可以发现跨多个层级的间接关联

六、部署与性能优化

  1. 索引优化:为常用查询模式建立索引
  2. 缓存策略:缓存热点查询结果
  3. 查询超时:设置执行超时防止慢查询拖垮系统
  4. 结果限制:限制返回结果数量减少 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 公司有哪些共同的投资方?”
- 通过图谱多跳查询,可以发现跨多个层级的间接关联

六、部署与性能优化

  1. 索引优化:为常用查询模式建立索引
  2. 缓存策略:缓存热点查询结果
  3. 查询超时:设置执行超时防止慢查询拖垮系统
  4. 结果限制:限制返回结果数量减少 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 公司有哪些共同的投资方?”
- 通过图谱多跳查询,可以发现跨多个层级的间接关联

六、部署与性能优化

  1. 索引优化:为常用查询模式建立索引
  2. 缓存策略:缓存热点查询结果
  3. 查询超时:设置执行超时防止慢查询拖垮系统
  4. 结果限制:限制返回结果数量减少 Token 消耗

七、总结

知识图谱与 RAG 的结合是构建高精度问答系统的关键技术路线。

关键要点回顾:
- 金融文档中的实体关系天然适合用 KG 建模
- LLM 可以从非结构化文档中自动抽取知识
- 多阶段抽取提升实体关系质量
- 图查询+向量检索的混合策略优于单一方案
- 事实准确率可从 82% 提升到 96%

延伸阅读

← RAG 三元组评估