跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonAI算法

基于大模型的自然语言数据库查询与数据分析

利用大语言模型结合 LlamaIndex 框架,通过自然语言生成 SQL 语句查询数据库的技术方案。内容涵盖环境搭建、基础查询实现、流式输出支持、模糊查询优化及提示词工程调整。文章分析了不同模型在 NL2SQL 任务中的表现差异,探讨了本地模型与云端模型的适用场景,并补充了安全注意事项与最佳实践,为开发者提供从原型验证到生产部署的参考路径。

奇形怪状发布于 2025/2/6更新于 2026/9/1259 浏览
基于大模型的自然语言数据库查询与数据分析

使用大模型进行自然语言查询数据库

利用大语言模型(LLM)通过自然语言生成 SQL 语句,从结构化数据库中获取结果,是目前大模型与数据交互的主流形式之一。这种技术通常被称为 NL2SQL(Natural Language to SQL)。

核心流程

以查询朝阳区高中学校招生信息为例,当用户提问 陈经纶招多少人? 时,系统处理的大致步骤如下:

  1. 上下文注入:将数据库的 DDL(建表语句)加入对话上下文,使大模型感知表结构。
  2. SQL 生成:大模型将提示词转化为 SQL 查询语句,例如 select * from school_info where school_name like '%陈经纶%'。
  3. 结果解释:大模型根据 SQL 查询结果,生成自然语言的回答,如 北京市陈经纶中学招收的学生人数为 279 名。

以下示例基于 Jupyter Notebook 环境实现,主要涉及 SQLAlchemy、LlamaIndex 以及本地或云端模型调用。

准备数据

首先使用 SQLAlchemy 在 SQLite 内存数据库中创建表结构和记录。

from sqlalchemy import (
    create_engine,
    MetaData,
    Table,
    Column,
    String,
    Integer,
    select,
    insert,
)

# 建立连接和表
engine = create_engine("sqlite:///:memory:")
metadata_obj = MetaData()

# 创建学校信息表结构
table_name = "school_info"
school_info_table = Table(
    table_name,
    metadata_obj,
    Column("school_name", String(200), primary_key=True),
    Column("students_enrolled", Integer, nullable=False),
)
metadata_obj.create_all(engine)

# 插入学校信息记录
rows = [
    {"school_name": "北京市第八十中学", "students_enrolled": 260},
    {"school_name": "北京市陈经纶中学", "students_enrolled": 279},
    {"school_name": "北京市日坛中学", "students_enrolled": 403},
    {"school_name": "中国人民大学附属中学朝阳学校", "students_enrolled": 247},
    {"school_name": "北京工业大学附属中学", "students_enrolled": 418},
    {"school_name": "北京中学", "students_enrolled": 121},
]
for row in rows:
    stmt = insert(school_info_table).values(**row)
    with engine.begin() as connection:
        cursor = connection.execute(stmt)

数据可以通过 pandas 查询显示,确保数据已正确写入。

最基本的使用

需要配置 LLM 和嵌入模型,设置到 LlamaIndex 全局 Settings 中,这样后续方法无需重复设置参数。

from llama_index.core import Settings
from llama_index.llms.openai_like import OpenAILike
from llama_index.embeddings.ollama import OllamaEmbedding

# 设置 LLM (以本地 Ollama 为例)
Settings.llm = OpenAILike(
    model="qwen2",
    api_base="http://localhost:11434/v1",
    api_key="ollama",
    is_chat_model=True,
    temperature=0.1,
    request_timeout=60.0
)

# 设置 Embedding 模型
Settings.embed_model = OllamaEmbedding(
    model_name="quentinz/bge-large-zh-v1.5",
    base_url="http://localhost:11434",
    ollama_additional_kwargs={"mirostat": 0}
)

执行基础查询:

from llama_index.core.sql_database import SQLDatabase
from llama_index.core.query_engine import NLSQLTableQueryEngine

sql_database = SQLDatabase(engine)
query_engine = NLSQLTableQueryEngine(
    sql_database=sql_database, 
    tables=["school_info"],
)
query_str = "招生最多的是哪个学校?"
response = query_engine.query(query_str)
print(response)
# 输出示例:'招生最多的是北京工业大学附属中学,共有 418 名学生。'

局限性分析:

  • 不支持对话流式输出,用户体验较卡顿。
  • 当表数量较多时,可能受到对话上下文长度限制,导致关键元数据丢失。

支持流式输出回答

为了提升体验,需要使用 LlamaIndex 底层的检索 API 来实现流式响应。

from llama_index.core.retrievers import NLSQLRetriever
from llama_index.core.query_engine import RetrieverQueryEngine

nl_sql_retriever = NLSQLRetriever(
    sql_database, tables=["school_info"], return_raw=True
)

query_engine = RetrieverQueryEngine.from_args(
    nl_sql_retriever,
    streaming=True
)

response = query_engine.query("招生最多的前三个学校?")
response.print_response_stream()

运行效果将逐字打印出答案,显著提升交互流畅度。

支持模糊查询

默认情况下,NL2SQL 对模糊匹配的支持较弱。直接询问 陈经纶招多少? 可能因无法精确匹配表结构而返回空结果。

优化方案

需要增加提示词约束,并依赖能力更强的 LLM 模型。本地小模型(如 Qwen 7B/14B)可能难以生成准确的模糊查询 SQL,建议尝试云端高级模型。

from llama_index.core.prompts import PromptTemplate

# 配置云端模型 (示例)
nl_sql_retriever = NLSQLRetriever(
    sql_database, tables=["school_info"], 
    return_raw=False,
    llm=OpenAILike(
        model='qwen-turbo', 
        api_base="http://api.example.com/v1", 
        api_key="<YOUR_API_KEY>", # 请替换为实际密钥
        is_chat_model=True,
        temperature=0.1,
        request_timeout=60.0
    )
)

# 修改提示词模板
old_prompt_str = nl_sql_retriever.get_prompts()['text_to_sql_prompt'].template
new_prompt = PromptTemplate(
    f"{old_prompt_str}"
    "查询关键字使用模糊查询,并且查询结果应包含关键字所属的列"
)
nl_sql_retriever.update_prompts({"text_to_sql_prompt": new_prompt})

query_engine = RetrieverQueryEngine.from_args(
    nl_sql_retriever,
    streaming=True,
)

response = query_engine.query("陈经纶招多少?")
response.print_response_stream()
# 预期输出:陈经纶招收 279 名学生。

定制回答格式

如果需要更严格的输出格式(例如必须显示全名),可以在 QA 阶段进一步定制提示词。

my_qa_prompt_template = (
    "回答中要求使用学校的完整名称 (school_name)"
    "不用再计算,给出的就是答案"
    "Context information is below.\n"
    "---------------------\n"
    "{context_str}\n"
    "---------------------\n"
    "Given the context information and not prior knowledge, "
    "answer the query.\n"
    "Query: {query_str}\n"
    "Answer: "
)
my_qa_prompt = PromptTemplate(
    my_qa_prompt_template, prompt_type="QUESTION_ANSWER"
)

query_engine = RetrieverQueryEngine.from_args(
    nl_sql_retriever,
    streaming=True,
    text_qa_template=my_qa_prompt,
)

response = query_engine.query("陈经纶招多少?")
response.print_response_stream()

模型选择与性能评估

在实际测试中,不同模型的表现差异显著:

  1. GPT-4:效果最好,理解复杂语义能力强,但成本较高。
  2. 国内云端模型:Qwen 高级模型表现较好,适合中文场景。
  3. 本地模型:Qwen2:7B 等模型在检索阶段(NL2SQL)可能需要依赖更强的云端模型辅助,否则生成的 SQL 语法错误率较高。

初步结论:

  • 如果采用 NL2SQL 方式,生产环境建议采用能力更高的云端模型,或者对本地模型进行垂直领域微调。
  • 对于简单查询,本地模型配合精心设计的 Prompt 可降低成本。

安全与最佳实践

在使用大模型查询数据库时,需注意以下安全问题:

  1. 权限控制:确保 LLM 仅拥有只读权限,严禁授予 DROP 或 DELETE 权限。
  2. Prompt 注入:警惕用户输入中包含恶意 SQL 指令,需对输入内容进行清洗。
  3. 敏感数据脱敏:在将 Schema 发送给 LLM 前,应移除包含隐私信息的字段描述。
  4. 缓存机制:对相同的查询请求进行缓存,减少 Token 消耗并提高响应速度。

总结

本文演示了如何使用大模型将自然语言转换为 SQL,并将查询结果以自然语言形式反馈给用户。关键点包括:

  • 依赖大模型能力和相关的提示词工程。
  • 本地模型与云端模型各有优劣,需根据场景权衡。
  • 流式输出和模糊查询需要通过底层 API 和 Prompt 优化来实现。
  • 生产部署需重点关注安全性与成本控制。

通过合理配置 LlamaIndex 框架及选择合适的模型,开发者可以快速构建具备自然语言交互能力的数据库应用。

目录

  1. 使用大模型进行自然语言查询数据库
  2. 核心流程
  3. 准备数据
  4. 建立连接和表
  5. 创建学校信息表结构
  6. 插入学校信息记录
  7. 最基本的使用
  8. 设置 LLM (以本地 Ollama 为例)
  9. 设置 Embedding 模型
  10. 输出示例:'招生最多的是北京工业大学附属中学,共有 418 名学生。'
  11. 支持流式输出回答
  12. 支持模糊查询
  13. 优化方案
  14. 配置云端模型 (示例)
  15. 修改提示词模板
  16. 预期输出:陈经纶招收 279 名学生。
  17. 定制回答格式
  18. 模型选择与性能评估
  19. 安全与最佳实践
  20. 总结

更多推荐文章

查看全部
  • 无人机路径规划算法详解
  • Python 素数判断与查找算法详解
  • 使用 Frontend-Design Skill 提升大模型前端设计能力
  • 小鹏 VLA 2.0 技术解析:自动驾驶与人形机器人的端到端演进
  • IDEA 创建 Spring Boot Web 项目教程
  • AIGC 从创意到创造
  • Stable Diffusion WebUI 高效提示词插件推荐与使用指南
  • 通义万相 2.1 模型升级与应用拓展实践
  • 前端开发者 Agent 工程化开发学习路线
  • Kafka vs RabbitMQ:消息中间件选型指南与 Java 实战
  • Python 爬虫核心技术原理与实战解析
  • C++ 在线判题系统(OJ)设计与实现
  • 特斯联获 20 亿融资,聚焦 AI+IoT 与模型系统落地路径
  • MiniMax-M2.5 开源发布:编程与智能体性能解析
  • FPGA 读写 DDR4 (一) MIG IP 核控制信号
  • 技术报告:在 4x Tesla P40 上训练 Llama-3.3-70B 大模型指南
  • A/B 测试效率低?AI 实时优化实验策略
  • ChatGPT GPTs 安全指南:如何防止提示词与知识库泄露
  • 2025 年跨境外贸必备 AI 工具与实战指南
  • 从空乘转行网络安全:零基础入门经验与面试技巧分享

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online