RAG 系统中 Excel/表格数据的正确处理方式

RAG 系统中 Excel/表格数据的正确处理方式:从向量检索到 Text-to-SQL 的架构演进


文章目录

  • [RAG 系统中 Excel/表格数据的正确处理方式:从向量检索到 Text-to-SQL 的架构演进](#RAG 系统中 Excel/表格数据的正确处理方式:从向量检索到 Text-to-SQL 的架构演进)
    • 前言
    • [一、问题复现:Excel 走 RAG 链路的灾难](#一、问题复现:Excel 走 RAG 链路的灾难)
      • [1.1 当前链路](#1.1 当前链路)
      • [1.2 一个典型的失败案例](#1.2 一个典型的失败案例)
      • [1.3 根因分析](#1.3 根因分析)
    • [二、方案对比:临时表 vs 永久表](#二、方案对比:临时表 vs 永久表)
      • [2.1 方案 A:临时表 + Text-to-SQL](#2.1 方案 A:临时表 + Text-to-SQL)
      • [2.2 方案 B:永久数据库表(✅ 推荐)](#2.2 方案 B:永久数据库表(✅ 推荐))
      • [2.3 对比总结](#2.3 对比总结)
    • [三、架构设计:与 RAG 知识库隔离](#三、架构设计:与 RAG 知识库隔离)
      • [3.1 为什么必须隔离](#3.1 为什么必须隔离)
      • [3.2 整体架构图](#3.2 整体架构图)
      • [3.3 模块划分](#3.3 模块划分)
    • 四、核心实现设计
      • [4.1 数据源注册表](#4.1 数据源注册表)
      • [4.2 动态建表的安全约束](#4.2 动态建表的安全约束)
      • [4.3 Schema 推断](#4.3 Schema 推断)
      • [4.4 SQL Tool(给 Agent 用)](#4.4 SQL Tool(给 Agent 用))
      • [4.5 Agent 工厂改造(多 Tool 支持)](#4.5 Agent 工厂改造(多 Tool 支持))
    • [五、进阶:PDF/DOCX 中的表格如何处理?](#五、进阶:PDF/DOCX 中的表格如何处理?)
      • [5.1 PDF 中的表格 vs Excel 文件的本质区别](#5.1 PDF 中的表格 vs Excel 文件的本质区别)
      • [5.2 三种处理策略](#5.2 三种处理策略)
        • [策略 A:作为 Chunk 的一部分向量化(默认)](#策略 A:作为 Chunk 的一部分向量化(默认))
        • [策略 B:提取建表(和 Excel 一样)](#策略 B:提取建表(和 Excel 一样))
        • [策略 C:智能分层处理(✅ 最终推荐)](#策略 C:智能分层处理(✅ 最终推荐))
      • [5.3 表格分类规则](#5.3 表格分类规则)
      • [5.4 数据密集型表格的处理流程](#5.4 数据密集型表格的处理流程)
    • [六、Text-to-SQL 查询流程详解](#六、Text-to-SQL 查询流程详解)
      • [6.1 完整流程](#6.1 完整流程)
      • [6.2 多 Tool 协同示例](#6.2 多 Tool 协同示例)
    • 七、总结
      • [7.1 核心原则](#7.1 核心原则)
      • [7.2 最终架构一览](#7.2 最终架构一览)
      • [7.3 避坑清单](#7.3 避坑清单)

前言

在构建 RAG(检索增强生成)系统时,很多人会踩一个坑:把 Excel 表格和 PDF/DOCX 文档一视同仁,全部丢给 MinerU 解析成 Markdown,再切片向量化存入 Milvus。

这样做会导致一系列严重问题:

  • ❌ 无法做聚合操作(SUM、AVG、COUNT)
  • ❌ 无法排序、比较、筛选
  • ❌ 浪费 LLM Token 去"理解"纯数字文本
  • ❌ 查询精度极低,"产品A 3月销售额"这种精确问题答不上来

本文将完整梳理这个问题的根因分析、方案对比、架构设计,以及最终的落地方案。


一、问题复现:Excel 走 RAG 链路的灾难

1.1 当前链路

复制代码
Excel 文件 → MinerU 解析 → Markdown(HTML <table>)→ 切片 → Embedding → Milvus 向量存储

1.2 一个典型的失败案例

用户上传了一份 2024年Q1销售报表.xlsx

产品 1月 2月 3月 合计
产品A 12,500 15,800 18,200 46,500
产品B 8,300 9,100 11,400 28,800
产品C 22,000 19,500 25,300 66,800

用户提问:"Q1 各产品总销售额排名?"

RAG 系统的回答:语义检索返回了"可能相关"的文本片段,LLM 试图从模糊的 chunk 中拼凑答案------结果要么答错,要么回答"知识库中未找到相关内容"。

1.3 根因分析

本质原因:Excel 是结构化数据,应该走 SQL 路径,而不是 RAG 语义检索路径。

问题类型 需要的操作 向量检索能力
"Q1 各产品总销售额排名" SUM + GROUP BY + ORDER BY ❌ 无法聚合
"产品A 3月的销售额" 精确查找 WHERE 产品='A' AND 月份='3月' ❌ 语义模糊匹配
"销售额前10的产品" ORDER BY + LIMIT ❌ 无法排序
"Q1 和 Q2 销售额对比" 跨表/跨行计算 ❌ 无法计算
"公司退货政策是什么" 语义理解 ✅ 向量检索擅长

结论:不是所有数据都适合向量化。结构化数据需要结构化的查询方式。


二、方案对比:临时表 vs 永久表

2.1 方案 A:临时表 + Text-to-SQL

复制代码
上传 Excel → 存储原始文件 → 提取文件名/表头
                                    ↓
用户提问 → LLM 生成 SQL → 创建临时表 → 导入数据 → 执行 SQL → 返回结果

优点:

  • 不污染数据库,数据随用随弃

致命缺点:

缺点 说明
每次查询都要重新导入 10MB 的 Excel 每次 CREATE TEMP TABLE + COPY,延迟 2-5 秒
无法跨查询复用 用户连续问 3 个问题,数据要导入 3 次
无索引 临时表没有索引,大表查询慢
并发问题 多用户同时查询同一文件,要创建多份临时表
生命周期管理复杂 临时表何时清理?会话结束?超时?

2.2 方案 B:永久数据库表(✅ 推荐)

复制代码
上传 Excel → 解析 Schema → CREATE TABLE(永久)→ 批量 INSERT → 建立索引
                                                         ↓
用户提问 → LLM Text-to-SQL → 直接查询永久表 → 返回结果

优点:

优点 说明
零延迟查询 数据已在数据库中,直接 SQL,毫秒级
支持索引 对高频查询列建索引,大表也快
数据可复用 一次导入,N 次查询
支持复杂查询 JOIN、子查询、窗口函数、聚合,全部可用
生命周期清晰 跟随 data_sourcedel_flag,删除文档时 DROP TABLE
与现有架构一致 已有 PostgreSQL,不需要额外组件

需要注意的问题:

问题 解决方案
动态建表的安全风险 表名用 excel_ 前缀隔离,列名做白名单校验
Schema 推断准确性 用 pandas 读取前 N 行推断类型,支持人工修正
多 Sheet 处理 每个 Sheet 一张表,表名 excel_{doc_id}_{sheet_name}
存储空间 Excel 数据通常不大(< 100MB),PostgreSQL 完全能承载

2.3 对比总结

维度 临时表方案 永久表方案(推荐)
查询延迟 高(每次导入 2-5s) 低(直接查询 ms 级)
索引支持 ❌ 无 ✅ 可建索引
并发支持 ❌ 多份临时表 ✅ 共享同一张表
生命周期 复杂(超时/会话) 简单(跟随文档删除)
存储开销 低(临时) 中(永久,但可控)
实现复杂度

三、架构设计:与 RAG 知识库隔离

3.1 为什么必须隔离

维度 RAG 知识库 Excel/结构化数据
数据类型 非结构化文本(PDF/DOCX/图片) 结构化表格数据
存储 Milvus 向量库 + rag_chunk 表 PostgreSQL 业务表
检索方式 语义相似度(Embedding) 精确 SQL 查询
适用问题 "公司退货政策是什么" "Q1 各产品销售额排名"
处理链路 MinerU → 切片 → Embedding → Milvus openpyxl/pandas → CREATE TABLE → INSERT
Tool 语义 knowledge_search(query) execute_sql(query)

核心原则:RAG 管语义,SQL 管数据,Agent 负责路由判断。

3.2 整体架构图

复制代码
┌──────────────────────────────────────────────────────────────┐
│                      用户上传文件                              │
└──────────────────┬───────────────────────────────────────────┘
                   │
            ┌──────┴──────┐
            │  文件类型判断  │
            └──────┬──────┘
                   │
     ┌─────────────┼─────────────┐
     ▼                           ▼
 PDF/DOCX/PPTX/图片          XLSX/XLS/CSV
     │                           │
     ▼                           ▼
┌──────────┐              ┌──────────────┐
│ module_rag│              │ module_data   │
│          │              │              │
│ MinerU   │              │ 解析 Schema   │
│   ↓      │              │   ↓          │
│ 切片     │              │ CREATE TABLE │
│   ↓      │              │   ↓          │
│ Embedding│              │ 批量 INSERT   │
│   ↓      │              │   ↓          │
│ Milvus   │              │ 存储元数据    │
└──────────┘              └──────────────┘
     │                           │
     ▼                           ▼
┌──────────────────────────────────────────┐
│           Agent (FunctionAgent)          │
│                                          │
│  ┌────────────────┐  ┌────────────────┐  │
│  │ knowledge_search│  │  data_query    │  │
│  │     Tool       │  │    Tool        │  │
│  └───────┬────────┘  └───────┬────────┘  │
│          │                   │           │
│    语义类问题            数据类问题         │
│   "退货政策是什么"     "销售额前10排名"     │
└──────────────────────────────────────────┘

3.3 模块划分

复制代码
module_data/                          ← 新建:结构化数据管理模块
├── controller/
│   └── data_source_controller.py     ← Excel 上传/管理 API
├── service/
│   ├── data_source_service.py        ← 业务逻辑(解析、建表、导入)
│   └── text_to_sql_service.py        ← Text-to-SQL 核心
├── dao/
│   └── data_source_dao.py            ← 数据源 CRUD
├── entity/
│   ├── do/
│   │   └── data_source_do.py         ← 数据源表 ORM 模型
│   └── vo/
│       └── data_source_vo.py         ← 请求/响应模型
└── tools/
    └── sql_tool.py                   ← 给 Agent 用的 SQL Tool

module_agent/                         ← 现有:Agent 模块(改造)
├── tools/
│   ├── rag_tool.py                   ← 现有:知识检索 Tool
│   └── (sql_tool.py 从 module_data 导入)
├── service/
│   ├── agent_factory.py              ← 改造:支持注入多个 Tool
│   └── agent_service.py              ← 改造:多 Tool 协同

四、核心实现设计

4.1 数据源注册表

sql 复制代码
CREATE TABLE data_source (
    id                VARCHAR PRIMARY KEY,          -- UUID
    file_name         VARCHAR NOT NULL,             -- 原始文件名
    file_path         VARCHAR NOT NULL,             -- 文件存储路径
    table_name        VARCHAR NOT NULL,             -- 实际 PG 表名 (excel_{uuid})
    sheet_name        VARCHAR,                      -- 原始 Sheet 名
    column_info       JSONB NOT NULL,               -- 列信息
    table_description TEXT,                         -- LLM 生成的表描述
    row_count         INTEGER,                      -- 数据行数
    source_type       VARCHAR NOT NULL,             -- 'excel' | 'csv' | 'pdf_table'
    source_doc_id     VARCHAR,                      -- 来源文档 ID(PDF 提取的表格)
    create_by         VARCHAR,
    create_time       TIMESTAMP DEFAULT NOW(),
    del_flag          CHAR(1) DEFAULT '0'
);

column_info 示例:

json 复制代码
[
  {"name": "产品", "pg_type": "TEXT", "nullable": false, "sample": "产品A", "description": "产品名称"},
  {"name": "1月", "pg_type": "NUMERIC", "nullable": false, "sample": "12500", "description": "1月销售额(元)"},
  {"name": "2月", "pg_type": "NUMERIC", "nullable": false, "sample": "15800", "description": "2月销售额(元)"}
]

4.2 动态建表的安全约束

python 复制代码
import re
import uuid

TABLE_PREFIX = "excel_"

def _sanitize_table_name(doc_id: str) -> str:
    """生成安全的表名:固定前缀 + UUID,杜绝 SQL 注入"""
    safe_id = re.sub(r'[^a-zA-Z0-9]', '', doc_id)
    return f"{TABLE_PREFIX}{safe_id}"

def _sanitize_column_name(name: str) -> str:
    """列名清洗:保留中文、字母、数字、下划线"""
    cleaned = re.sub(r'[^\w\u4e00-\u9fff]', '_', str(name).strip())
    return cleaned or 'unnamed_column'

# SQL 安全校验
ALLOWED_SQL_KEYWORDS = {'SELECT', 'FROM', 'WHERE', 'GROUP BY', 'ORDER BY',
                        'HAVING', 'LIMIT', 'OFFSET', 'JOIN', 'ON', 'AS',
                        'AND', 'OR', 'NOT', 'IN', 'BETWEEN', 'LIKE', 'IS',
                        'NULL', 'ASC', 'DESC', 'COUNT', 'SUM', 'AVG', 'MAX', 'MIN'}

def validate_sql(sql: str) -> bool:
    """只允许 SELECT 查询,禁止任何写操作"""
    upper_sql = sql.upper().strip()
    if not upper_sql.startswith('SELECT'):
        raise ValueError('只允许 SELECT 查询')
    forbidden = {'INSERT', 'UPDATE', 'DELETE', 'DROP', 'ALTER', 'CREATE',
                 'TRUNCATE', 'EXEC', 'EXECUTE', 'GRANT', 'REVOKE'}
    for keyword in forbidden:
        if re.search(rf'\b{keyword}\b', upper_sql):
            raise ValueError(f'禁止的 SQL 关键字: {keyword}')
    # 强制追加 LIMIT(防止大结果集)
    if 'LIMIT' not in upper_sql:
        sql = sql.rstrip(';') + ' LIMIT 1000'
    return True

4.3 Schema 推断

python 复制代码
import pandas as pd

def infer_schema(file_path: str, sheet_name: str) -> list[dict]:
    """读取 Excel 前 100 行,推断每列的数据类型"""
    df = pd.read_excel(file_path, sheet_name=sheet_name, nrows=100)
    columns = []
    for col in df.columns:
        pg_type = _pandas_dtype_to_pg_type(df[col].dtype)
        sample = str(df[col].dropna().iloc[0]) if not df[col].dropna().empty else None
        columns.append({
            "name": _sanitize_column_name(col),
            "original_name": str(col),
            "pg_type": pg_type,
            "nullable": bool(df[col].isnull().any()),
            "sample": sample,
            "description": "",  # 后续由 LLM 补充描述
        })
    return columns

def _pandas_dtype_to_pg_type(dtype) -> str:
    """pandas 数据类型 → PostgreSQL 类型映射"""
    import numpy as np
    if np.issubdtype(dtype, np.integer):
        return 'BIGINT'
    elif np.issubdtype(dtype, np.floating):
        return 'NUMERIC'
    elif np.issubdtype(dtype, np.datetime64):
        return 'TIMESTAMP'
    else:
        return 'TEXT'

4.4 SQL Tool(给 Agent 用)

python 复制代码
from llama_index.core.tools import FunctionTool

def create_sql_tool(data_source_ids: list[str] | None = None) -> FunctionTool:
    """
    创建 SQL 查询工具,供 Agent 查询结构化数据。
    
    Agent 用自然语言描述问题,系统自动:
    1. 获取相关数据源的 Schema
    2. 构建 Text-to-SQL Prompt
    3. LLM 生成 SQL
    4. 安全校验 + 执行
    5. 返回格式化结果
    """
    async def execute_data_query(query: str) -> str:
        """对用户上传的 Excel/CSV 数据执行查询。
        
        当用户的问题涉及数据统计、排名、对比、聚合(如求和、平均、最大最小)
        或需要精确数值时,必须调用此工具。
        
        Args:
            query: 自然语言查询问题
        """
        # 1. 获取数据源 Schema
        schemas = await get_schemas_by_ids(data_source_ids)
        
        # 2. 构建 Text-to-SQL Prompt
        prompt = _build_text_to_sql_prompt(query, schemas)
        
        # 3. LLM 生成 SQL
        sql = await llm_generate_sql(prompt)
        
        # 4. 安全校验
        validate_sql(sql)
        
        # 5. 执行查询
        result = await execute_readonly_query(sql)
        
        # 6. 格式化返回
        return format_query_result(result)

    return FunctionTool.from_defaults(
        async_fn=execute_data_query,
        name='data_query',
        description=(
            '查询用户上传的 Excel/CSV 数据。'
            '当问题涉及数据统计、排名、对比、聚合或精确数值时使用此工具。'
            '参数: query=自然语言查询问题'
        ),
    )

4.5 Agent 工厂改造(多 Tool 支持)

python 复制代码
class AgentFactory:
    @classmethod
    def create_agent(
        cls,
        kb_id: str,
        collection_name: str,
        data_source_ids: list[str] | None = None,  # 新增参数
        system_prompt: str | None = None,
    ) -> FunctionAgent:
        tools = []
        
        # 1. RAG 工具(始终可用)
        tools.append(create_rag_tool(kb_id, collection_name))
        
        # 2. SQL 工具(有数据源时才注入)
        if data_source_ids:
            tools.append(create_sql_tool(data_source_ids))
        
        # 系统提示也要调整
        final_prompt = system_prompt or _build_system_prompt(has_sql_tool=bool(data_source_ids))
        
        return FunctionAgent(
            name='knowledge_assistant',
            description='基于知识库和数据的智能问答助手',
            system_prompt=final_prompt,
            tools=tools,
            llm=get_llm(),
            streaming=True,
        )

五、进阶:PDF/DOCX 中的表格如何处理?

5.1 PDF 中的表格 vs Excel 文件的本质区别

维度 PDF/DOCX 中的表格 独立 Excel 文件
定位 文档的一部分,有上下文包裹 独立的数据源
目的 通常是摘要/展示,给读者看 通常是原始数据,给分析用
完整性 往往是汇总后的子集(5-10行) 完整的数据集(几百到几万行)
例子 合同里的"费用明细表" "2024年全年销售明细.xlsx"

5.2 三种处理策略

策略 A:作为 Chunk 的一部分向量化(默认)

MinerU 已经把表格转成了 Markdown/HTML 格式,切片时表格自然包含在 chunk 里:

markdown 复制代码
## 3.2 费用明细

| 项目 | 单价(元) | 数量 | 合计(元) |
|------|---------|------|---------|
| 设计费 | 50,000 | 1 | 50,000 |
| 施工费 | 30,000 | 3 | 90,000 |
| 监理费 | 15,000 | 2 | 30,000 |

如上表所示,本项目总费用为 17 万元...

整块一起向量化,用户问"设计费是多少"时,语义检索能命中这个 chunk,LLM 直接从表格文本中读取答案。

适用场景:表格较小(< 50 行)、表格是描述性/摘要性的、用户问的是"是什么"而不是"算一下"。

策略 B:提取建表(和 Excel 一样)

把 PDF 中的表格从文档中"抠出来",单独建一张 PostgreSQL 表。

适用场景:表格很大(100+ 行)、表格是结构化的数据集、用户经常需要对表格数据做聚合查询。

缺点:表格脱离了文档上下文,丢失语义;管理复杂。

策略 C:智能分层处理(✅ 最终推荐)

核心思路:默认走策略 A(向量化),遇到"数据密集型表格"时自动升级到策略 B。

复制代码
MinerU 输出 Markdown
        │
    表格检测
        │
   ┌────┴────┐
   │ 有表格? │
   └────┬────┘
        │
   ┌────┴────────────────────┐
   ▼                         ▼
描述性表格               数据密集型表格
(< 20行,              (> 50行,
 有上下文包裹)           纯数据无叙述)
   │                         │
   ▼                         ▼
保留在 Chunk 中          提取建表到 PostgreSQL
→ 向量化到 Milvus        → 原文替换为摘要
                         → 通过 sql_tool 查询

5.3 表格分类规则

python 复制代码
def classify_table(headers: list[str], row_count: int, surrounding_text: str) -> bool:
    """
    判断表格是"描述性"还是"数据密集型"
    
    返回 True 表示数据密集型,需要建表
    
    判断依据:
    1. 行数阈值(> 50 行)
    2. 列头含数值关键词(金额、数量、合计、%...)
    3. 周围文本是否缺少叙述性描述
    """
    # 规则 1: 行数阈值
    if row_count > 50:
        return True
    
    # 规则 2: 列头含数值关键词占比超过 50%
    numeric_keywords = ['金额', '数量', '合计', '总计', '单价', '比例', '%', '元', '万']
    numeric_count = sum(1 for h in headers if any(kw in h for kw in numeric_keywords))
    if numeric_count >= len(headers) * 0.5:
        return True
    
    # 规则 3: 周围文本很短(< 50 字符),说明表格是独立的数据罗列
    if len(surrounding_text.strip()) < 50:
        return True
    
    return False

5.4 数据密集型表格的处理流程

python 复制代码
async def process_data_heavy_table(table_info, document):
    """处理数据密集型表格:提取建表 + 原文替换为摘要"""
    
    # 1. 提取数据,动态建 PostgreSQL 表
    table_name = f"doc_{document.id}_table_{uuid4().hex[:8]}"
    await create_table_from_html(table_name, table_info.table_html, table_info.headers)
    await insert_data_to_table(table_name, table_info.table_html)
    
    # 2. 注册到 data_source 表(和 Excel 共用同一套体系)
    await save_data_source(
        doc_id=document.id,
        table_name=table_name,
        column_info=table_info.headers,
        source_type='pdf_table',      # 标记来源是 PDF 中的表格
        original_file=document.file_name,
    )
    
    # 3. 在原文中替换为摘要(保留上下文)
    summary = (
        f"\n> 📊 此处有一张数据表({table_info.row_count}行),"
        f"列:{', '.join(table_info.headers)}。"
        f"可通过数据查询工具精确查询。\n"
    )
    return summary  # 替换原文中的表格 HTML

六、Text-to-SQL 查询流程详解

6.1 完整流程

复制代码
用户: "Q1 各产品总销售额排名,取前10"
    │
    ▼
Agent 判断: 这是数据查询问题,调用 data_query Tool
    │
    ▼
data_query Tool 内部:
    │
    ├── 1. 从 data_source 表获取 column_info + table_description
    │
    ├── 2. 构建 Prompt:
    │      "你是一个 SQL 专家。以下是可用的数据表:
    │       表名: excel_a1b2c3d4 (2024年Q1销售报表)
    │       列: 产品(TEXT), 1月(NUMERIC), 2月(NUMERIC), 3月(NUMERIC)
    │       
    │       用户问题: Q1 各产品总销售额排名,取前10
    │       请生成 SELECT 语句。"
    │
    ├── 3. LLM 生成 SQL:
    │      SELECT "产品", ("1月"+"2月"+"3月") AS q1_total
    │      FROM excel_a1b2c3d4
    │      ORDER BY q1_total DESC LIMIT 10
    │
    ├── 4. 安全校验: 只含 SELECT ✅,表名在白名单内 ✅
    │
    └── 5. 执行 SQL,返回结果
    │
    ▼
Agent 拿到结果,组织自然语言回答:
    "Q1 销售额前10的产品如下:
     1. 产品A: 46,500 元
     2. 产品B: 28,800 元
     ..."

6.2 多 Tool 协同示例

复制代码
用户: "合同里的费用明细是多少?另外和预算表对比一下"
    │
    ▼
Agent 判断: 这个问题涉及两部分
    │
    ├── 1. "合同里的费用明细" 
    │      → knowledge_search(语义检索合同 PDF 中的表格 chunk)
    │
    └── 2. "和预算表对比"
           → data_query(SQL 查询预算表 Excel 的数据)
    │
    ▼
Agent 综合两个 Tool 的结果,生成最终回答

七、总结

7.1 核心原则

  1. 结构化数据走 SQL,非结构化数据走向量 --- 不要把所有东西都塞进 Milvus
  2. RAG 管语义,SQL 管数据,Agent 管路由 --- 各司其职
  3. Excel 永久建表 --- 一次导入,N 次查询,毫秒级响应
  4. PDF 中的表格智能分层 --- 小表格向量化,大表格建表
  5. 统一查询入口 --- 无论数据来源是 Excel 还是 PDF 提取,都通过同一个 sql_tool 查询

7.2 最终架构一览

数据类型 处理方式 存储 查询 Tool 适用问题
PDF/DOCX 文本 MinerU → 切片 → Embedding Milvus knowledge_search "退货政策是什么"
PDF 中的小表格 保留在 chunk 中向量化 Milvus knowledge_search "设计费是多少"
PDF 中的大表格 提取建表 + 原文摘要 PostgreSQL data_query "费用明细合计"
Excel/CSV 文件 直接建表 PostgreSQL data_query "Q1 销售额排名"

7.3 避坑清单

❌ 错误做法 ✅ 正确做法
Excel 每行转文本 → 向量化 Excel → 建表 → Text-to-SQL
PDF 中所有表格都建表 智能分类:小表格向量化,大表格建表
临时表方案(每次查询重新导入) 永久表方案(一次导入,多次查询)
RAG 和结构化数据混在一起 隔离为独立模块,通过 Agent Tool 统一入口
直接传 LLM 生成的 SQL 执行 安全校验:只允许 SELECT + 白名单表名 + LIMIT 保护

作者:RAG 不是万能的。结构化数据天然就有更好的查询方式(SQL),强行走向量化是在用错误工具解决正确问题。好的架构是让每种数据走最适合它的路径。

相关推荐
苏灿烤鱼1 小时前
九个编码 Agent 共用免费额度,本地代理是路由还是绕开?
python·agent·claude
copyer_xyf2 小时前
Neo4j:给 RAG 补上关系检索
python·agent
whcyhhh2 小时前
CTF‑MISC 隐写术完整学习笔记|图片隐写全题型 + 工具 + 实战例题
python·网络安全·ctf·misc·信息隐藏
码视野3 小时前
多宠 RFID 颈圈识别与湿粮半导体制冷保鲜分餐喂食器解决方案(软硬件一体化)
大数据·人工智能·python
未若君雅裁3 小时前
让模型按契约返回数据,LangChain 结构化输出实战
python·langchain
学习中.........4 小时前
Transformer 训练资源估算:以 CS336 GPT-2 XL 配置为例
人工智能·python·算法·机器学习·自然语言处理
小陈的进阶之路10 小时前
Claude Code辅助测试:导入篇skills
python·自动化
whcyhhh11 小时前
头歌实践教学平台:大数据存储2023(六)
大数据·数据库·python
for_ever_love__11 小时前
python基础语法学习: 闭包
开发语言·python·学习·闭包