1. 代码功能简要说明
该代码基于LangChain框架整合OpenAI的gpt-3.5-turbo模型和MySQL数据库,实现自然语言转SQL并自动执行查询的智能问答系统,核心流程如下:
- 数据库连接:通过SQLAlchemy语法配置MySQL连接信息,初始化数据库交互对象;
- SQL生成:利用
create_sql_query_chain将用户自然语言问题(如“员工表中有多少条数据?”)转为可执行的SQL语句; - SQL执行:通过
QuerySQLDataBaseTool自动执行生成的SQL,获取查询结果; - 结果整合:结合“用户问题+生成的SQL+执行结果”,通过提示模板和模型生成自然语言回答,全程无需手动编写/执行SQL,实现自然语言与数据库的无缝交互。
2. 带逐行详细注释的完整代码
# 导入os库:1.配置网络代理(解决国内访问OpenAI API的网络限制) 2.配置LangChain环境变量
import os
# 导入itemgetter:用于从字典中提取指定key的值(本案例提取生成的SQL语句)
from operator import itemgetter
# 导入bs4(BeautifulSoup):本代码未实际使用,预留网页数据加载能力
import bs4
# 导入create_stuff_documents_chain:(未使用)基础RAG问答链,预留检索增强能力
from langchain.chains.combine_documents import create_stuff_documents_chain
# 导入create_history_aware_retriever:(未使用)历史感知检索器,预留上下文关联能力
from langchain.chains.history_aware_retriever import create_history_aware_retriever
# 导入create_retrieval_chain:(未使用)顶层RAG链,预留检索+问答整合能力
from langchain.chains.retrieval import create_retrieval_chain
# 导入create_sql_query_chain:核心组件,将自然语言问题转为SQL语句
from langchain.chains.sql_database.query import create_sql_query_chain
# 导入Chroma:(未使用)向量数据库,预留RAG能力
from langchain_chroma import Chroma
# 导入WebBaseLoader:(未使用)网页加载器,预留外部数据加载能力
from langchain_community.document_loaders import WebBaseLoader
# 导入QuerySQLDataBaseTool:SQL执行工具,自动执行生成的SQL语句并返回结果
from langchain_community.tools import QuerySQLDataBaseTool
# 导入SQLDatabase:LangChain封装的数据库交互类,支持MySQL/PostgreSQL等
from langchain_community.utilities import SQLDatabase
# 导入StrOutputParser:输出解析器,将模型返回的消息对象转为纯字符串
from langchain_core.output_parsers import StrOutputParser
# 导入提示模板相关:
# - ChatPromptTemplate:聊天型提示模板(未使用)
# - MessagesPlaceholder:会话历史占位符(未使用)
# - PromptTemplate:基础文本提示模板(用于整合SQL结果生成回答)
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder, PromptTemplate
# 导入Runnable相关:
# - RunnableWithMessageHistory:(未使用)会话历史包装器
# - RunnablePassthrough:参数透传/赋值组件,串联SQL生成→执行→回答流程
from langchain_core.runnables import RunnableWithMessageHistory, RunnablePassthrough
# 导入RecursiveCharacterTextSplitter:(未使用)文本切割器,预留RAG能力
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 导入ChatMessageHistory:(未使用)会话历史存储,预留上下文能力
from langchain_community.chat_message_histories import ChatMessageHistory
# 导入OpenAI相关组件:
# - ChatOpenAI:gpt-3.5-turbo聊天模型,负责生成SQL和自然语言回答
# - OpenAIEmbeddings:(未使用)文本嵌入模型,预留RAG能力
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
# 配置HTTP代理:127.0.0.1:7890是代理工具的本地端口,确保访问OpenAI API
os.environ['http_proxy'] = '127.0.0.1:7890'
# 配置HTTPS代理:OpenAI API基于HTTPS,需配置该代理确保请求正常
os.environ['https_proxy'] = '127.0.0.1:7890'
# 开启LangChain Tracing V2:追踪链的执行过程(SQL生成、执行、回答),便于调试
os.environ["LANGCHAIN_TRACING_V2"] = "true"
# 配置LangChain项目名称:追踪数据归类到该项目,便于管理不同应用
os.environ["LANGCHAIN_PROJECT"] = "LangchainDemo"
# 配置LangChain API Key:认证LangChain Smith服务(追踪功能必需),替换为自己的密钥
os.environ["LANGCHAIN_API_KEY"] = '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'
# os.environ["TAVILY_API_KEY"] = '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' # 未使用Tavily,注释掉
# ===================== 核心步骤1:初始化OpenAI聊天模型 =====================
# 聊天机器人案例
# 创建ChatOpenAI模型实例:指定gpt-3.5-turbo(性价比高,适合SQL生成/简单问答)
model = ChatOpenAI(model='gpt-3.5-turbo')
# ===================== 核心步骤2:配置并连接MySQL数据库 =====================
# sqlalchemy 初始化MySQL数据库的连接(SQLAlchemy标准URL格式)
# 数据库连接参数:
HOSTNAME = '127.0.0.1' # 数据库服务器地址(本地)
PORT = '3306' # MySQL默认端口
DATABASE = 'test_db8' # 要连接的数据库名
USERNAME = 'root' # 数据库用户名
PASSWORD = '123123' # 数据库密码
# 构建MySQL连接URL(mysqlclient驱动):
# 格式:mysql+mysqldb://用户名:密码@地址:端口/数据库名?字符集
MYSQL_URI = 'mysql+mysqldb://{}:{}@{}:{}/{}?charset=utf8mb4'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
# 初始化数据库交互对象:通过URL连接MySQL,封装数据库操作(查询、执行SQL等)
db = SQLDatabase.from_uri(MYSQL_URI)
# 测试连接是否成功(注释):
# print(db.get_usable_table_names()) # 输出数据库中可访问的表名(如t_emp)
# print(db.run('select * from t_emp limit 10;')) # 执行SQL,输出前10条员工数据
# ===================== 核心步骤3:创建自然语言转SQL的链 =====================
# 直接使用大模型和数据库整合, 只能根据你的问题生成SQL
# 初始化生成SQL的chain:输入自然语言问题,输出对应的SQL语句
# - model:gpt-3.5-turbo模型(懂SQL语法和自然语言)
# - db:数据库对象(模型会读取表结构,生成适配的SQL)
test_chain = create_sql_query_chain(model, db)
# 测试SQL生成(注释):
# resp = test_chain.invoke({'question': '请问:员工表中有多少条数据?'})
# print(resp) # 输出:SELECT COUNT(*) FROM t_emp;
# ===================== 核心步骤4:创建回答提示模板 =====================
# 定义回答模板:整合“用户问题+生成的SQL+执行结果”,让模型生成自然语言回答
answer_prompt = PromptTemplate.from_template(
"""给定以下用户问题、SQL语句和SQL执行后的结果,回答用户问题。
Question: {question} # 变量:用户的自然语言问题
SQL Query: {query} # 变量:模型生成的SQL语句
SQL Result: {result} # 变量:SQL执行后的结果
回答: """ # 模型需要生成的内容
)
# ===================== 核心步骤5:创建SQL执行工具 =====================
# 创建一个执行sql语句的工具:封装db的run方法,输入SQL语句,输出执行结果
execute_sql_tool = QuerySQLDataBaseTool(db=db)
# ===================== 核心步骤6:构建完整的“生成SQL→执行→回答”链 =====================
# 1、生成SQL,2、执行SQL,3、生成回答
# 链的执行逻辑拆解:
# - RunnablePassthrough.assign(query=test_chain):透传用户输入,同时调用test_chain生成SQL,存入query变量
# - .assign(result=itemgetter('query') | execute_sql_tool):提取query变量(生成的SQL),传给execute_sql_tool执行,结果存入result变量
# - | answer_prompt:将question/query/result填充到回答模板
# - | model:模型基于填充后的模板生成自然语言回答
# - | StrOutputParser():将模型返回的消息对象转为纯字符串(便于输出)
chain = (RunnablePassthrough.assign(query=test_chain).assign(result=itemgetter('query') | execute_sql_tool)
| answer_prompt
| model
| StrOutputParser()
)
# ===================== 核心步骤7:调用链并获取回答 =====================
# 优化print:先打印用户问题,再执行链,最后打印完整结果(生成的SQL、执行结果、最终回答)
print('=== 自然语言转SQL问答结果 ===')
user_question = '请问:员工表中有多少条数据?'
print(f'用户问题:{user_question}')
# 手动获取生成的SQL(便于展示)
generated_sql = test_chain.invoke({'question': user_question})
print(f'模型生成的SQL:{generated_sql}')
# 手动执行SQL(便于展示)
sql_result = execute_sql_tool.invoke(generated_sql)
print(f'SQL执行结果:{sql_result}')
# 调用完整链获取最终回答
rep = chain.invoke(input={'question': user_question})
print(f'模型最终回答:{rep}')
3. 无任何注释的代码版本
import os
from operator import itemgetter
import bs4
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain.chains.history_aware_retriever import create_history_aware_retriever
from langchain.chains.retrieval import create_retrieval_chain
from langchain.chains.sql_database.query import create_sql_query_chain
from langchain_chroma import Chroma
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.tools import QuerySQLDataBaseTool
from langchain_community.utilities import SQLDatabase
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder, PromptTemplate
from langchain_core.runnables import RunnableWithMessageHistory, RunnablePassthrough
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
os.environ['http_proxy'] = '127.0.0.1:7890'
os.environ['https_proxy'] = '127.0.0.1:7890'
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_PROJECT"] = "LangchainDemo"
os.environ["LANGCHAIN_API_KEY"] = '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'
model = ChatOpenAI(model='gpt-3.5-turbo')
HOSTNAME = '127.0.0.1'
PORT = '3306'
DATABASE = 'test_db8'
USERNAME = 'root'
PASSWORD = '123123'
MYSQL_URI = 'mysql+mysqldb://{}:{}@{}:{}/{}?charset=utf8mb4'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
db = SQLDatabase.from_uri(MYSQL_URI)
test_chain = create_sql_query_chain(model, db)
answer_prompt = PromptTemplate.from_template(
"""给定以下用户问题、SQL语句和SQL执行后的结果,回答用户问题。
Question: {question}
SQL Query: {query}
SQL Result: {result}
回答: """
)
execute_sql_tool = QuerySQLDataBaseTool(db=db)
chain = (RunnablePassthrough.assign(query=test_chain).assign(result=itemgetter('query') | execute_sql_tool)
| answer_prompt
| model
| StrOutputParser()
)
print('=== 自然语言转SQL问答结果 ===')
user_question = '请问:员工表中有多少条数据?'
print(f'用户问题:{user_question}')
generated_sql = test_chain.invoke({'question': user_question})
print(f'模型生成的SQL:{generated_sql}')
sql_result = execute_sql_tool.invoke(generated_sql)
print(f'SQL执行结果:{sql_result}')
rep = chain.invoke(input={'question': user_question})
print(f'模型最终回答:{rep}')
4. 核心知识点详解(系统梳理+表格)
4.1 核心组件/概念对照表
| 核心组件/概念 | 导入路径 | 通俗解释 | 核心用法 | 本案例作用 |
|---|---|---|---|---|
| SQLDatabase | langchain_community.utilities.SQLDatabase | LangChain封装的数据库交互类,支持多数据库连接 | SQLDatabase.from_uri(数据库URL) | 连接MySQL数据库,提供表结构查询、SQL执行能力 |
| create_sql_query_chain | langchain.chains.sql_database.query.create_sql_query_chain | 自然语言转SQL的核心链,模型基于表结构生成适配SQL | create_sql_query_chain(模型, 数据库对象) | 将“员工表有多少条数据?”转为SELECT COUNT(*) FROM t_emp; |
| QuerySQLDataBaseTool | langchain_community.tools.QuerySQLDataBaseTool | SQL执行工具,封装数据库run方法,输入SQL输出结果 | QuerySQLDataBaseTool(db=数据库对象) | 执行生成的SQL语句,返回员工表数据条数(如50) |
| RunnablePassthrough.assign | langchain_core.runnables.RunnablePassthrough | 参数赋值组件,透传输入并新增变量(如query/result) | RunnablePassthrough.assign(变量名=链/工具) | 透传用户问题,同时生成SQL(query)、执行SQL(result) |
| itemgetter | operator.itemgetter | 字典键提取工具,快速获取指定key的值 | itemgetter('key')(字典) | 提取生成的SQL(query变量),传给执行工具 |
| PromptTemplate | langchain_core.prompts.PromptTemplate | 基础文本提示模板,支持变量填充 | PromptTemplate.from_template(模板字符串) | 整合“问题+SQL+结果”,引导模型生成自然语言回答 |
| StrOutputParser | langchain_core.output_parsers.StrOutputParser | 输出解析器,将模型消息转为纯字符串 | StrOutputParser().invoke(模型响应) | 将模型返回的AIMessage转为纯文本回答(如“员工表有50条数据”) |
4.2 关键知识点深度解释
(1)MySQL连接URL格式
本案例使用mysql+mysqldb驱动(需安装mysqlclient库),其他常见驱动格式:
mysql+pymysql:使用pymysql驱动(需安装pymysql),URL为mysql+pymysql://用户名:密码@地址:端口/数据库名;- 核心参数:
charset=utf8mb4确保支持emoji等特殊字符,避免中文乱码。
(2)create_sql_query_chain的核心能力
模型会自动:
- 读取数据库的表结构(如t_emp的字段、类型);
- 将自然语言问题转为符合MySQL语法的SQL;
- 避免危险操作(如DROP/DELETE,默认配置会过滤);
- 适配表名/字段名(如用户说“员工表”,模型匹配到t_emp)。
(3)完整链的执行流程(可视化)
flowchart TD
A[用户问题:员工表有多少条数据?] --> B[RunnablePassthrough.assign]
B --> C1[test_chain生成SQL:SELECT COUNT(*) FROM t_emp;]
B --> C2[透传question变量]
C1 --> D[itemgetter提取SQL,传给execute_sql_tool]
D --> E[执行SQL,返回结果:50]
C2 & C1 & E --> F[answer_prompt填充变量]
F --> G[gpt-3.5-turbo生成回答]
G --> H[StrOutputParser转为纯字符串]
H --> I[最终回答:员工表中有50条数据。]
(4)StrOutputParser的必要性
模型返回的原始响应是AIMessage(content='员工表中有50条数据。'),StrOutputParser会提取content字段转为纯字符串,避免直接打印出现AIMessage对象的冗余信息。
5. print函数修改说明
5.1 优化对比与原因
| 原代码print | 优化后print | 核心改进 |
|---|---|---|
print(rep) | print('=== 自然语言转SQL问答结果 ===')print(f'用户问题:{user_question}')print(f'模型生成的SQL:{generated_sql}')print(f'SQL执行结果:{sql_result}')print(f'模型最终回答:{rep}') | 1. 标注模块标题,清晰区分问答流程; 2. 分步展示“问题→生成SQL→执行结果→最终回答”,小白能理解全流程; 3. 避免仅打印最终回答导致的“黑盒感”,便于调试(如SQL生成错误可快速定位) |
5.2 输出示例(参考)
=== 自然语言转SQL问答结果 ===
用户问题:请问:员工表中有多少条数据?
模型生成的SQL:SELECT COUNT(*) FROM t_emp;
SQL执行结果:50
模型最终回答:员工表中有50条数据。
5.3 环境依赖说明
运行代码前需安装以下库(终端执行):
pip install langchain langchain-openai langchain-community chromadb beautifulsoup4 mysqlclient sqlalchemy
mysqlclient:MySQL连接驱动(若安装失败,可换pymysql,并修改URL为mysql+pymysql://...);sqlalchemy:数据库ORM框架,LangChain依赖其实现数据库连接。
总结(关键点回顾)
- 核心能力:实现“自然语言→SQL→执行→自然语言回答”的全流程自动化,无需手动编写/执行SQL;
- 核心流程:数据库连接→SQL生成→SQL执行→结果整合→自然语言回答;
- 关键组件:
create_sql_query_chain是自然语言转SQL的核心;QuerySQLDataBaseTool实现SQL自动执行;RunnablePassthrough.assign串联多步骤,StrOutputParser简化输出;
- 实用技巧:
- 数据库URL需指定
charset=utf8mb4避免中文乱码; - 测试时先打印生成的SQL,确认无误后再执行,避免误操作;
- 可通过LangChain Tracing查看SQL生成/执行的详细日志,便于调试。
- 数据库URL需指定

313

被折叠的 条评论
为什么被折叠?



