一、系统功能概述
本项目构建了一个基于大语言模型(GLM-4)的自然语言到SQL查询的智能问答系统。其主要目标是让用户使用中文提出问题,系统能够自动完成“生成SQL语句 → 执行数据库查询 → 返回自然语言形式答案”的完整流程。该系统具备以下核心能力:
- 理解用户输入的中文自然语言问题,并转换为符合MySQL语法规范的SQL查询语句;
- 自动执行所生成的SQL语句,从指定的MySQL数据库中提取数据结果;
- 整合原始问题、生成的SQL以及查询返回的数据,形成易于理解的中文回答;
- 适配智谱AI提供的GLM-4模型API接口,确保在SQL生成与最终回答输出上的准确性和稳定性。
二、整体运行流程说明
1. 初始化配置阶段
设置MySQL数据库连接参数(包括地址、端口、用户名、密码等),同时配置GLM-4模型相关参数(如API Key、模型版本、温度值等),并初始化数据库连接实例。
2. SQL语句生成阶段
接收用户以自然语言提出的查询请求 → 自动获取当前数据库中的表结构信息 → 调用GLM-4模型生成对应的SQL语句 → 对输出内容进行清洗处理(去除Markdown代码块标记和多余空格)。
clean_sql_output
3. 数据库查询执行阶段
将清洗后的SQL语句发送至MySQL数据库执行 → 获取查询结果集并准备用于后续响应生成。
create_sql_query_chain
4. 自然语言回答生成阶段
将用户的原始问题、已生成的SQL语句及实际查询结果一并传入GLM-4模型 → 模型据此生成通顺易懂的中文回复 → 输出最终结果给用户。
三、代码模块详细解析(含关键注释说明)
# 引入必要的依赖库
from operator import itemgetter
# 用于从字典或对象中提取特定字段,例如提取LLM输出中的SQL文本
import os
# 读取环境变量中的智谱API密钥,避免敏感信息硬编码在代码中
from langchain_community.utilities import SQLDatabase
# LangChain提供的数据库封装工具,简化对MySQL等数据库的连接与操作
from langchain_community.tools import QuerySQLDataBaseTool
# 安全执行SQL查询的工具类,防止恶意语句注入,保障执行过程可控
from langchain_openai import ChatOpenAI
# 兼容OpenAI接口格式的LLM客户端,此处用于调用智谱AI的GLM-4模型服务
from langchain_core.runnables import RunnablePassthrough, RunnableLambda
# LangChain的核心可运行组件:
# - RunnablePassthrough:实现输入透传,不改变数据流
# - RunnableLambda:封装自定义处理函数,便于链式调用
from langchain_core.prompts import ChatPromptTemplate, PromptTemplate
# 构建提示词模板,定义大模型的输入结构与上下文格式
from langchain_core.output_parsers import StrOutputParser
# 输出解析器,将模型返回的复杂对象(如AIMessage)转换为纯字符串
# 清洗LLM输出的SQL内容:解决常见格式问题(如包含```sql代码块符号)
def clean_sql_output(ai_msg):
# 判断是否具有content属性(如AIMessage类型),优先提取content
sql = ai_msg.content if hasattr(ai_msg, 'content') else str(ai_msg)
# 去除首尾空白字符,移除可能存在的Markdown代码块前缀和后缀
return sql.strip().removeprefix('```sql').removesuffix('```').strip()
# 构建SQL生成链:集成“获取表结构→生成SQL→清洗输出”全流程
def create_sql_query_chain(llm, database: SQLDatabase):
# 内部函数:获取所有表的结构信息(字段名、类型、约束等)
def get_table_info(_):
return database.get_table_info()
# 定义提示词模板:设定角色为SQL专家,要求根据表结构和用户问题生成合法SQL
prompt = ChatPromptTemplate.from_messages([
("system", "You are an expert SQL assistant. Given the following database schema:\n{table_info}\n"
"Write a syntactically correct SQL query that answers the user's question. "
"Only return the SQL statement without any additional explanation or formatting.")
])
# === 数据库配置 ===
HOSTNAME = '127.0.0.1' # MySQL服务器地址
PORT = '3306' # MySQL端口号
DATABASE = 'test' # 目标数据库名
USERNAME = 'test' # 数据库登录用户名
PASSWORD = '123456' # 数据库登录密码
# 构建MySQL连接URI:使用pymysql驱动,指定utf8mb4字符集避免中文乱码
MYSQL_URI = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4'
# === 模型配置 ===
api_key = os.getenv('Zhipu_API_KEY') # 从环境变量读取智谱API Key(安全最佳实践)
model = ChatOpenAI(
model='glm-4-0520', # 指定使用GLM-4 0520版本模型
temperature=0, # 温度设为0,保证生成结果的确定性(适合SQL生成场景)
api_key=api_key, # 传入智谱API Key
base_url='https://open.bigmodel.cn/api/paas/v4' # 智谱API的base_url(兼容OpenAI格式)
)
# === 初始化数据库和工具 ===
db = SQLDatabase.from_uri(MYSQL_URI) # 初始化数据库连接实例
create_sql = create_sql_query_chain(llm=model, database=db) # 初始化SQL生成链
execute_sql = QuerySQLDataBaseTool(db=db) # 初始化SQL执行工具(绑定数据库实例)
# === 回答模板 ===
# 定义自然语言回答的提示词模板:整合问题、SQL、结果,要求模型生成中文回答
answer_prompt = PromptTemplate.from_template(
"""根据用户问题、对应 SQL 查询和查询结果,用中文回答问题:
问题:{question}
SQL 查询:{query}
查询结果:{result}
最终答案:"""
)
# 组装回答生成链:提示词模板 → 调用LLM → 解析为字符串输出
answer_chain = answer_prompt | model | StrOutputParser()
# === 组装SQL生成链 ===
# 1. 接收用户问题并透传,同时获取表结构信息
# 2. 将问题与表结构代入提示词模板生成完整prompt
# 3. 调用大模型生成SQL语句
# 4. 对生成的SQL进行格式清洗,确保可被数据库执行
return (
{"question": RunnablePassthrough(), "table_info": RunnableLambda(get_table_info)}
| prompt
| llm
| RunnableLambda(clean_sql_output)
)
# === 最终链:端到端问答流程 ===
# 流程说明:
# 1. 保持原始输入,并通过SQL生成链创建 query 字段(存放生成的SQL)
# 2. 使用 itemgetter 获取上一步生成的SQL语句,并通过执行工具运行,得到 result 字段
# 3. 将 question、query、result 全部传入 answer_chain,生成自然语言回复
chain = (
RunnablePassthrough.assign(query=create_sql)
.assign(result=itemgetter('query') | execute_sql)
| answer_chain
)
# 示例输入数据结构说明(仅用于理解流程,不参与实际输出):
# input_data = {"question": "一共有多少员工?"}
#
# 经过 RunnablePassthrough.assign 处理后,新增字段逻辑如下:
# - 保留原始字段 "question"
# - 使用 create_sql_chain 生成 SQL 并赋值给 "query" 字段
#
# 最终数据结构示例:
# {
# "question": "一共有多少员工?", // 原始字段透传
# "query": "SELECT COUNT(*) FROM employees;", // 自动生成的SQL语句
# "result": [(105,)] // 执行SQL后的查询结果
# }
四、关键组件核心作用说明
在系统架构中,各个组件与函数承担着不同的职责,协同完成从用户提问到数据库查询再到自然语言回复的完整流程。以下是各核心模块的功能解析:
| 组件/函数名称 | 核心作用 |
|---|---|
|
适配智谱GLM-4 API的LLM客户端,兼容LangChain框架中的链式调用方式,确保模型请求格式统一且可扩展 |
|
负责与MySQL数据库建立连接,并提供基础能力支持,包括获取表结构信息和执行SQL语句 |
|
对大语言模型生成的SQL语句进行清洗处理,去除如Markdown代码块标记等非必要格式,保障SQL可直接提交执行 |
|
实现用户输入数据的透传机制,同时支持动态添加计算类字段(例如query、result),增强上下文传递灵活性 |
|
安全地执行SQL操作,通过封装数据库游标管理逻辑,避免对外暴露底层连接对象,提升系统安全性 |
|
将用户的原始问题、生成的SQL语句以及查询结果整合,转化为流畅的自然语言回答,优化最终输出体验 |
|
集成SQL生成的全流程:从获取数据库表结构开始,构建提示词模板,调用LLM生成SQL,最后进行格式清洗,形成闭环处理 |
五、使用说明
为确保系统正常运行,请按照以下步骤完成配置与环境准备:
- 环境依赖安装:需提前安装必要的Python依赖包,具体可通过标准包管理工具进行安装 —— 对应依赖项标识为
。langchain-community langchain-core openai pymysql - 环境变量配置:需要在操作系统层面设置环境变量,用于存储第三方服务密钥 —— 其中
代表智谱AI平台所需的API密钥,必须正确配置方可调用模型接口。Zhipu_API_KEY - 数据库适配:根据实际部署环境,修改代码中「数据库配置」区域的相关参数,如HOSTNAME、PORT、DATABASE等,以匹配目标MySQL实例的连接信息。
- 模型适配:可根据应用场景灵活调整所使用的模型名称(如切换至glm-4-flash)或调节temperature参数值,从而在生成内容的创造性和准确性之间取得平衡。
测试示例
以下为两个典型的测试场景及其执行逻辑:
测试场景1:聚合查询(统计员工总数)
if __name__ == "__main__":
# 测试1:查询员工总人数
print("=== 测试1:员工总数 ===")
resp1 = chain.invoke({"question": "请问:一共有多少个员工?"})
print(resp1)
测试场景2:条件查询(查找权限最高的员工及其权限级别)
# 测试2:获取权限最高的员工信息及对应权限
print("\n=== 测试2:权限最高员工 ===")
resp2 = chain.invoke({"question": "请问:哪个员工的权限最高?并且返回该员工的权限"})
print(resp2)


雷达卡


京公网安备 11010802022788号







