Text2SQL-自助式数据报表开发

更新时间: 2026-03-19 14:34:23

# 结构化和非结构化数据

  • 非结构化数据类型
    常见类型: 包括PDF、Word文档、图片(以图片形式存在的表格)等
    特点: 格式不固定,难以直接进行结构化查询和分析

  • 结构化和非结构化数据的区别
    核心差异: 数据格式是否固定
    结构化示例: Excel表格具有固定的行列结构
    价值对比: 结构化数据更便于查询和分析,价值密度更高

  • 结构化与非结构化数据库的争论与价值变化
    技术阵营:
    SQL代表结构化数据阵营
    NoSQL代表非结构化数据阵营
    发展趋势: 大模型出现前SQL数据库(如Oracle)价值更高;大模型出现后非结构化数据价值提升

  • 结构化数据的应用与优势
    运算能力: 天生格式清晰,便于进行各种运算
    典型应用: 生成数据看板和决策报表
    工作场景: 业务人员日常需要频繁提取结构化数据

  • 大模型在结构化数据处理中的应用
    传统方式: 由技术人员编写SQL语句
    痛点: 业务人员提数需求频繁,打断技术人员核心工作
    解决方案: 通过大模型自动生成SQL语句

  • 大模型写SQL语句的背景与需求
    历史尝试: 曾培训业务人员学习SQL但效果有限
    变革契机: 大模型出现后业务人员可直接用自然语言获取数据
    价值: 解放技术人员,使其专注于更高价值的数据分析工作

  • Function calling功能与思考助手搭建
    关键技术: 使用function calling功能连接大模型和数据库
    实现方式: 基于此功能搭建SQL查询助手
    优势: 实现自助式数据提取,减少工作打断

  • 大模型开发自入型数据报表的模式
    模式一: 使用LangChain封装的SQL Agent工具
    模式二: 自定义提示词工程,让大模型理解表结构和需求
    最佳实践: 探索不同提示词写法对结果的影响

# Text to SQL技术

Text-to-SQL (文本转SQL)
将自然语言问题自动转换为结构化的SQL查询语句,可以让用户更直观的与数据库进行交互。

Text-to-SQL的技术演变经历了3个阶段:

  • 早期阶段:依赖于人工编写的规则模板来匹配自然语言和SQL语句之间的对应关系。
  • 机器学习阶段:采用序列到序列模型等机器学习方法来学习自然语言和SQL之间的映射关系。
  • LLM阶段:借助LLM强大的语言理解和代码生成能力,利用提示工程、微调等方法将Text-to-SQL性能提升到新的高度。

我们目前已处于LLM阶段,基于LLM的Text-to-SQL系统会包含以下几个步骤:

  • 自然语言理解:分析用户输入的自然语言问题,理解其意图和语义。
  • 模式链接:将问题中的实体与数据库模式中的表和列进行链接。
  • SQL生成:根据理解的语义和模式链接结果,生成相应的SQL查询语句。
  • SQL执行:在数据库上执行SQL查询,将结果返回给用户。

# LLM模型选择(闭源模型)

  • GPT-o1/o3: o1模型开启了新的Scaling Law,更专注于推理阶段,在编程和Text to SQL中能力优于gpt-4o,同时mini模型速度更快,价格更低。
  • Claude 3.7-sonnet: Anthropic公司于2025年2月发布,号称迄今为止最智能的模型,首款混合推理模型 Claude 3.7-sonnet实现了两种思考方式的结合,既能提供接近即时的响应,也能展示分步骤的详细思考过程
  • Claude 3.5-sonnet:2024年推出的模型,支持20万tokens上下文,性能超过GPT-4o,在Cursor中使用非常顺滑。
  • Gemini 2.0:性能强悍,支持100万token上下文。
  • Qwen-Turbo:支持100万token上下文,速度快,价格非常便宜。

# LLM模型选择(开源模型)

  • DeepSeek-V3:在代码生成任务中表现出色,能够快速生成高质量的代码片段。它通过从DeepSeek-R1中蒸馏推理能力,显著提升了代码生成的准确性和效率
  • DeepSeek-R1: R1在代码生成和复杂逻辑推理方面表现卓越,特别是在处理复杂的编程任务和数学问题时,准确率更高。例如,在CodeforcesElo评分中,R1达到2029分,超越96.3%的人类参赛者
  • Qwen:Qwen系列从0.5B,1.5B,3B,7B,14B,32B,72B等多种尺寸,性能优于Llama3.1。

# LLM模型选择(代码大模型)

  • Qwen-Coder:能力强,接近闭源一线大模型,其中Qwen2.5-Coder-32B能力与GPT-4o持平
  • CodeGeeX:智谱开源的代码大模型,基于GLM底座,性能卓越,在vscode等编辑器中可以找到对应的插件。
  • SQLCoder:专为SQL生成而设计的开源模型,但是维护更新慢。
  • DeepSeek-Coder:在多种编程语言中与开源代码模型中实现了先进的性能,但模型更新不及时

部署现状:
企业多部署通用大模型(如Qwen3-8B/32B)
个人使用推荐闭源SaaS模型(如豆包、Qwen系列)
代码大模型实际应用较少,主流仍是通用模型

# 国外模型:

  • Claude系列:最新4.1版本代码生成能力最强,适合编程场景
  • GPT系列:GPT-5理解能力存在争议,图表处理仍有缺陷
  • Gemini:即将推出3.0版本,代码质量整体不错但有小瑕疵

# 国内模型:

  • Qwen系列:当前主流,含8B/32B等版本及MOE中量级模型
  • DeepSeek:年初流行但换血频繁,现多转向Qwen
  • Code专用:Qwen-Coder性能接近Claude4.0,DeepSeek-Coder使用较少

部署方式: 闭源模型:通过API按token计费(如阿里云百炼)
开源模型:可本地部署(如ModelScope下载Qwen/DeepSeek系列)
企业首选开源模型以保证数据安全

# SQL Copilot

# 方法一: SQLDatabase

采用LangChain框架

提供了sqlchain,prompt,retriever,tools, agent,让用户通过自然语言,执行SQL查询

优点:使用方便,自动通过数据库连接,获取数据库的metadata

不足:执行不灵活,需要多次判断哪个表适合复杂查询很难胜任,对于复杂查询通过率低

总结

SQL + LLM使用:

  • 通过SQLDatabase可以访问到数据库的Schema
  • agent_executor作为SQL Agent,可以执行用户的各种SQL需求(通过自然语言=>编写SQL =>查询结果返回)
  • 如果数据库中没有找到对应的表,会报OutputParseException错误
  • 如果有多张表,会分别执行,然后判断哪个数据表可以得到结果
#!/usr/bin/env python
# coding: utf-8

# ## 使用DeepSeek进行数据表的查询

# In[1]:


from langchain.agents import create_sql_agent
from langchain_community.utilities import SQLDatabase
from langchain_community.agent_toolkits import SQLDatabaseToolkit
from langchain_community.llms import OpenAI
from langchain.agents import AgentExecutor

db_user = "root"
db_password = "123456"
#db_host = "localhost:3306"
db_host = "localhost:3306"
db_name = "action"
db = SQLDatabase.from_uri(f"mysql+pymysql://{db_user}:{db_password}@{db_host}/{db_name}")

# In[3]:


from langchain.chat_models import ChatOpenAI
import os

# 从环境变量获取 dashscope 的 API Key
api_key = "your api key"

# 通过LLM => 撰写SQL
llm = ChatOpenAI(
    temperature=0.01,
    model="deepseek-v3",
    openai_api_base = "https://dashscope.aliyuncs.com/compatible-mode/v1",
    openai_api_key  = api_key
)

# 需要设置llm
toolkit = SQLDatabaseToolkit(db=db, llm=llm)

# SQL智能体:给它目标,它自己会进行规划,最终把结果给你
agent_executor = create_sql_agent(
    llm=llm,
    toolkit=toolkit,
    verbose=True
)

# Task: 描述数据表
agent_executor.run("描述与订单相关的表及其关系")

# 这个任务,实际上数据库中 没有HeroDetails表
agent_executor.run("描述HeroDetails表")

agent_executor.run("描述Hero表")

agent_executor.run("找出英雄攻击力最高的前5个英雄")


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

直接使用SQL + LLM会有什么问题?

  • 多个相似的数据表=>导致LangChain会尝试多次生成SQL
  • 用户Prompt太宽泛=>生成的结果,不是用户想要的

# LangChain的局限性

性能瓶颈:

  • 处理速度:需要遍历所有数据,耗时较长
  • 扩展性问题:当数据量达10万级时效率显著下降

应用场景限制:

  • 金融行业案例:银行/证券公司通常有数万至数十万张数据表
  • 成本考量:大规模数据处理时时间成本和计算成本过高

# 方法2:自己编写

本质是:LLM + RAG

选择适合的LLM,比如:ChatModel: DeepSeek-V3,CodeModel: Qwen2.5-Coder, CodeGeeX2-6B

RAG,可以分成:向量数据库检索+固定文件(比如本地数据表说明等)

优点:重心在于RAG的提供上,准确性高,配置灵活

不足:需要设置的条件规则多

# SQL +向量数据库+ LLM

SQL +向量数据库+ LLM:

  • 向量数据库可以提供领域知识,当用户检索某个问题的时候=>从向量数据库中找到相关的内容,放到prompt中=>提升SQL查询的相关性

RAG技术:

  • 在prompt中增加few-shot examples
  • 专门定制检索工具,从向量数据库中 检索到与用户query相近的知识

除了对用户query,补充领域知识外,针对专门名词(用户可以拼写错误的),也可以进行纠正

# Prompt works!

  • 以下哪种prompt可以写出更好的SQL?

写法1:

prompt = f"""# language: SQL
/*
{query}你需要先判断需要哪个数据表和字段,
然后基于它们编写SQL。数据库中有以下数
据表:
=====
{table_description}
*/
# {query}"""
1
2
3
4
5
6
7
8
9

写法2:

prompt = f"""
--language: SQL
/*{query}
以下是数据表
=====
{table_description}
=====
编写一条SQL: {query}
*/"""
1
2
3
4
5
6
7
8
9

写法3:

prompt = f"""--language: SQL
### Question: {query}
### Input: {create_sql}
### Response:
Here is the SQL query I have generated to
answer the question `{query}`:
```sql
"""
1
2
3
4
5
6
7
8

table_description是数据表的中文描述,create_sql是数据表的建表语句,query是用户查询的问题

答案是第三个!

选择依据:

  • 因其提供最完整的元数据信息
  • 建表语句包含字段数据类型,避免类型错误
  • 可补充字段注释和示例值提高准确性

实现要点:

  • 使用标准SQL注释语法(--)
  • 字段应包含数据类型定义
  • 建议添加取值示例(如Gender字段可注明取值是"男/女"或"Male/Female")

# 大模型的补全能力与SQL生成

补全模型原理:

  • 工作机制:

    • 本质是代码补全而非聊天对话
    • 基于大量预训练代码数据(如GitHub数十亿代码)
    • 使用```SQL触发自动补全模式
  • 优势体现:

    • 更符合代码生成场景需求
    • 减少不必要的解释性输出
    • 直接生成可执行SQL语句

提示词模板设计

  • 核心要素:
    • 前置完整DDL语句
    • 明确的问题描述
    • 使用--标准SQL注释
    • 结尾添加```SQL触发补全