LLM大模型如何访问MySQL业务数据库

目录

一、LLM大模型如何访问MySQL业务数据库

1.1 为什么需要SQL Agent?

1.2 什么是 create_sql_agent?

1.3 什么是SQLDatabaseToolkit?

二、SQL Agent智能体操作MySQL数据库

三、本地启动服务 验证效果

四、怎么提高SQL Agent智能体的回复准确性?


文章首先讲解了create_sql_agentSQLDatabaseToolkit的核心作用,展示了如何通过LangChain框架连接数据库并创建具备SQL解析能力的智能代理。随后结合实际应用场景,构建了一个基于FastAPI的文件查询系统,演示了如何将自然语言问题转化为结构化数据响应,并确保数据安全与准确性。最后,探讨了提升SQL Agent回复准确性的关键因素,如提示词工程、表结构描述优化、示例引导(Few-Shot Learning)等方法

一、LLM大模型如何访问MySQL业务数据库

1.1 为什么需要SQL Agent?

用户更倾向于用自然语言提问(如“销售额最高的产品是什么?”),而非编写复杂 SQL。

非技术人员(如产品经理、业务人员)无需学习 SQL 即可查询数据库。

包括开发对应的业务智能体,实现数据库的查询和操作

1.2 什么是 create_sql_agent?

创建能通过自然语言与SQL数据库交互的AI智能体,自动生成/执行SQL查询并解析结果

核心能力:

将用户问题(如“统计每个地区的销量”)转化为 SQL 查询语句。

连接数据库执行 SQL,默认只读模式防止数据误修改。

将数据库返回的原始数据(如 [1500, 2000])转换为用户友好的回答(如“总销售额为 $3500”)。

自动修正 SQL 语法错误或逻辑问题(如字段名拼写错误)。

1.3 什么是SQLDatabaseToolkit?

LangChain 中专门用于 连接 SQL 数据库并集成相关操作工具 的模块包

#使用 SQLDatabase.from_uri 连接数据库,自动读取表结构。
db = SQLDatabase.from_uri(
  database_uri="数据库连接信息",
  include_tables=['a***ount_file', 'storage'],
  custom_table_info={"a***ount": "查询账号相关的表"}) 

#SQLDatabaseToolkit 封装了查询执行、表结构查看等底层操作。
toolkit = SQLDatabaseToolkit(db=db, llm=ChatOpenAI())

agent = create_sql_agent(
    llm=ChatOpenAI(temperature=0, model="gpt-5"),  # 必需:大模型
    toolkit=toolkit,    # 必需:数据库工具包
    agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION,  # Agent类型
    verbose=True,          # 显示详细执行过程
    prefix="""你是一个专业的MySQL专家...""",  # 自定义提示前缀
    suffix="""请始终检查你的查询结果..."""     # 自定义提示后缀
)

快速的看一个demo 这会更好理解流程:

import os
from langchain_***munity.agent_toolkits.sql.base import create_sql_agent
from langchain_***munity.agent_toolkits.sql.toolkit import SQLDatabaseToolkit
from langchain_***munity.utilities import SQLDatabase
from langchain_openai import ChatOpenAI
from langchain.agents.agent_types import AgentType

# 设置OpenAI API密钥
llm = ChatOpenAI(
    model_name="qwen-plus",
    base_url="https://dashscope.aliyuncs.***/***patible-mode/v1",
    api_key="sk-xxxxxxxxxxxx",
    temperature=0,
)

# 1. 连接数据库
db = SQLDatabase.from_uri(
    f"mysql+pymysql://root:xxxxxxx@93.179.111.1111:3306/mysql",
    include_tables=["a***ount_file"],
    custom_table_info={"a***ount_file": "查询文件夹和文件内容相关的表"},  # 自定义表描述
)

# 初始化工具包
toolkit = SQLDatabaseToolkit(db=db, llm=llm)
print(f"包含的工具个数:{len(toolkit.get_tools())}")
print("工具列表", [tool.name for tool in toolkit.get_tools()])

# 创建SQLAgent
agent = create_sql_agent(
    llm=llm,
    toolkit=toolkit,
    verbose=True,
    agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
    handle_parsing_errors=True,
    max_iterations=10,
    prefix="You are a helpful assistant that answers questions about the database.",
    suffix="",
)


def ask_question(question: str) -> str:
    print(f"问题:{question}")
    result = agent.invoke({"input": question})
    return result["output"]


questions = ["有多少个文件"]

for question in questions:
    answer = ask_question(question)
    print(f"答案:{answer}")
    print("-" * 50)

用户请求->创建代理->执行查询->返回结果

二、SQL Agent智能体操作MySQL数据库

需求:通过自然语言查看文件列表、查看文件详细信息、查看文件夹内容

流程说明:

用户请求: 用户发送自然语言查询、获取用户ID

参数处理:处理查询参数、注入用户ID

创建代理:初始化SQL代理、准备查询环境

执行查询:执行数据库查询、获取查询结果

返回结果:返回JSON格式响应

 先思考几个问题:

问题一:大模型操作Mysql数据库如何做到个人数据隔离,不会查询到别人的数据?

问题二:大模型响应给调用方的内容格式如何限制?

问题三:大模型如何更精确的执行用户的查询需求?

解决方案:【!!!!提示词工程!!!】 

 定义返回结果的实体pan_schemas.py文件 

from pydantic import BaseModel
from typing import Optional, Dict, Any, List
from datetime import datetime

class PanQueryRequest(BaseModel):
    """文件查询请求模型"""
    a***ount_id: Optional[int] = None  # 从token中获取,请求中可选
    query: str

class FileInfo(BaseModel):
    """文件信息模型"""
    id: int  # a***ount_file表的ID
    file_id: int  # 实际存储的文件ID
    file_name: str
    file_type: str
    file_suffix: str
    file_size: int
    gmt_create: datetime
    gmt_modified: datetime

class PanQueryResponse(BaseModel):
    """文件查询响应模型"""
    type: str
    data: Dict[str, Any] 

创建路由文件file.py

from fastapi import APIRouter, Depends
from models.pan_schemas import PanQueryRequest
from agents.pan_agent import process_pan_query
from core.auth import get_current_user
import logging


logger = logging.getLogger(__name__)
# 创建路由
router = APIRouter(prefix="/api/pan", tags=["文件查询"])


@router.post("/query")
async def pan_query(request: PanQueryRequest):

    request.a***ount_id = 1
    logger.info(f"用户{request.a***ount_id}开始查询文件")
    # 调用智能体进行查询
    return await process_pan_query(request)

file_agent.py

process_pan_query 这个异步方法主要是创建agent ->构建输入->执行获取输出->解析结果返回

async def process_pan_query(request: PanQueryRequest) -> JsonData:
    agent = create_pan_agent()

    # 构建查询输入,可以做更多事情,包括检查过滤用户的输入
    query_input = f"用户ID为{request.a***ount_id}的{request.query}"

    # 获取代理的输出
    response = await agent.ainvoke({"input": query_input})

    if "output" not in response:
        return JsonData.error("查询失败,请换种方式再重试下")

    output = response["output"]

    # 解析数据
    try:
        data = json.loads(output) if isinstance(output, str) else output
        logger.info(f"解析数据成功: {data}")
        return JsonData.su***ess({"type": data.get("type"), "data": data.get("data")})

    except json.JSONDecodeError as e:
        logger.error(f"解析数据失败: {str(e)}")
        return JsonData.su***ess(data={"content": str(output)})

def create_pan_agent() -> Any:
    """创建网盘查询agent"""
    # 创建数据库连接,只读模式
    db = SQLDatabase.from_uri(
        f"mysql+pymysql://{settings.MYSQL_USER}:{settings.MYSQL_PASSWORD}@{settings.MYSQL_HOST}:{settings.MYSQL_PORT}/{settings.MYSQL_DATABASE}",
        include_tables=["a***ount_file"],
    )

    # 创建大模型
    llm = get_default_llm()

    # 创建数据库工具包
    tookit = SQLDatabaseToolkit(db=db, llm=llm)

    # 创建提示词
    # 创建提示模板
    prompt = ChatPromptTemplate.from_messages(
        [
            (
                "system",
                """你是一个智能网盘助手,专门用于查询用户的网盘文件信息。你只能执行查询操作,不能执行任何修改数据的操作。

        重要警告:
        1. 你绝对不能生成或编造任何数据
        2. 你只能返回实际查询到的数据
        3. 如果查询没有结果,必须返回空结果
        4. 任何生成或编造数据的行为都是严重错误
        5. 你只能使用数据库中的实际数据
        6. 不能对查询结果进行任何修改或补充
        7. 不能生成示例数据或占位数据
        8. 不能假设或推测数据
        9. 不能使用模板或示例数据
        10. 不能对数据进行任何形式的加工或美化

        数据库表结构说明:
        - a***ount_file: 用户文件表
          - id: 文件ID(a***ount_file表的主键)
          - a***ount_id: 用户ID
          - is_dir: 是否为文件夹(0不是,1是)
          - parent_id: 上层文件夹ID(顶层为0)
          - file_id: 实际存储的文件ID
          - file_name: 文件名称
          - file_type: 文件类型(***mon/***press/excel/word/pdf/txt/img/audio/video/ppt/code/csv)
          - file_suffix: 文件后缀名
          - file_size: 文件大小(字节)
          - del: 是否删除(0未删除,1已删除)
          - del_time: 删除时间
          - gmt_create: 创建时间
          - gmt_modified: 更新时间
        
        你可以处理以下类型的查询请求:
        1. 文件查询
           - 查看我的文件列表
           - 搜索特定文件
           - 查看文件详细信息
           - 查看文件夹内容
           - 查看最近修改的文件
              

        重要限制:
        1. 你只能执行 SELECT 查询,不能执行任何修改数据的操作
        2. 所有查询必须包含 a***ount_id 条件,确保数据安全
        3. 不能执行以下操作:
           - 删除文件
           - 修改文件
           - 创建文件
           - 移动文件
           - 重命名文件
           - 清空回收站
           - 修改存储空间
        4. 如果用户请求执行任何修改操作,请礼貌地拒绝并说明原因
        5. 如果查询没有结果,必须返回空结果,不能生成示例数据
        6. 绝对不能生成或编造任何数据
        7. 只能返回实际查询到的数据
        8. 不能对数据进行任何形式的加工或美化

        处理请求时请注意:
        1. 必须使用 a***ount_id 过滤用户数据,确保数据安全
        2. 对于文件夹查询,使用 is_dir=1 和 parent_id
        3. 对于文件类型查询,使用 file_type 字段
        4. 对于模糊查询,使用 LIKE 和通配符
        5. 对于时间相关的查询,使用 gmt_create 和 gmt_modified
        7. 结果要简洁明了,突出重点
        8. 所有查询必须包含 a***ount_id 条件
        9. 查询文件信息时,必须返回 a***ount_file 表的 id 和 file_id
        10. 所有响应必须返回 JSON 格式的数据,包含完整的文件信息
        11. 如果查询没有结果,返回空数组或空对象,不要生成示例数据
        12. 绝对不能生成或编造任何数据

        响应格式必须符合以下模型结构:
        1. 文件列表响应:
           {{
               "type": "file_list",
               "data": List[FileInfo]  # FileInfo包含id, file_id, file_name, file_type, file_suffix, file_size, gmt_create, gmt_modified
           }}
            
        请根据用户的问题,使用 SQL 查询来获取信息,并返回符合上述格式的 JSON 数据。
        重要警告:你绝对不能生成或编造任何数据,只能返回实际查询到的数据。任何生成或编造数据的行为都是严重错误。""",
            ),
            ("human", "{input}"),
            MessagesPlaceholder(variable_name="agent_scratchpad"),
        ]
    )
  # 创建SQLAgent
    agent = create_sql_agent(
        llm=llm,
        toolkit=tookit,
        agent_type="openai-tools",
        verbose=True,
        return_intermediate_steps=True,
        max_iterations=15,
        handle_parsing_errors=True,
        prompt=prompt,
    )

    return agent

def get_default_llm():
    return ChatOpenAI(
       model = settings.LLM_MODEL_NAME,
       base_url = settings.LLM_BASE_URL,
       api_key = settings.LLM_API_KEY,
       temperature = settings.LLM_TEMPERATURE,
       streaming = settings.LLM_STREAMING
    )

最主要的就是上面的这些提示词,用来给大模型做各种限制,给大模型提供样例

三、本地启动服务 验证效果

这些是数据库中存在的数据:

使用ApiFox 请求api 

{
    "code": 0,
    "data": {
        "type": "file_list",
        "data": [
            {
                "id": 2,
                "file_id": 101,
                "file_name": "Resume.pdf",
                "file_type": "pdf"
            }
        ]
    },
    "msg": "",
    "type": "text"
}

成功返回~ 

四、怎么提高SQL Agent智能体的回复准确性?

 SQL Agent智能体的回复准确性,和大模型参数、温度、能力、提示词工程强相关,也包括用户的提问内容

比如更详细的表结构Schema说明,提问改写,提供FewShot样例等,都是可以提高准确度

增强 Schema 理解

 # 在提示词中添加增强元数据描述
prefix = """
你连接的数据库包含以下关键表:
[Customers] 客户表(重要字段:CustomerId, FirstName, LastName, Country)
[Invoices] 发票表(与 Customers 通过 CustomerId 关联)
优先使用 JOIN 代替子查询,注意 Country 字段存储的是国家全称
"""

Few-Shot Learning 通过示例引导生成模式

 examples = [
    {
        "input": "法国客户数量是多少?",
        "query": "SELECT COUNT(*) FROM Customers WHERE Country = 'France'"
    },
    {
        "input": "显示最新的5张发票", 
        "query": "SELECT * FROM Invoices ORDER BY InvoiceDate DESC LIMIT 5"
    }

总结:

本文围绕如何构建一个能够通过自然语言与MySQL数据库交互的SQL Agent智能体展开,涵盖了从环境搭建到本地验证的完整流程。首先介绍了使用create_sql_agentSQLDatabaseToolkit来实现自然语言转SQL的核心机制,并给出了代码示例,帮助开发者快速上手。接着,通过构建一个网盘文件查询服务,展示了如何将智能体集成到实际业务场景中,包括定义数据模型、设计API接口、编写异步处理逻辑等内容。特别强调了提示词工程在控制模型行为、保证数据真实性和避免编造信息方面的重要性。最后,文章分析了影响SQL Agent性能的关键因素,并提出了多种优化策略,如增强Schema理解、提供示例引导等

转载请说明出处内容投诉
CSS教程网 » LLM大模型如何访问MySQL业务数据库

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买