构建一个基于SQL数据的问答系统:从SQL查询到自然语言回答
引言
在现代应用程序中,能够有效地从结构化数据中提取信息是非常有价值的。本文将介绍如何使用大语言模型(LLM)构建一个问答系统,能够对SQL数据库中的数据进行查询,并返回自然语言的回答。我们将探讨如何使用链和代理两种方法进行实现,并提供安全性建议以确保系统的可靠性。
主要内容
1. 架构概览
系统的基本步骤包括:
- 将问题转换为SQL查询。
- 执行SQL查询。
- 利用查询结果回答用户问题。
2. 环境准备
首先,我们需要安装必要的依赖包并设置环境变量:
%%capture --no-stderr
%pip install --upgrade --quiet langchain langchain-community langchain-openai faiss-cpu
import getpass
import os
if not os.environ.get("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass()
# 使用LangSmith进行跟踪
if not os.environ.get("LANGCHAIN_API_KEY"):
os.environ["LANGCHAIN_API_KEY"] = getpass.getpass()
os.environ["LANGCHAIN_TRACING_V2"] = "true"
3. 数据库连接
我们将使用SQLite连接到Chinook数据库:
from langchain_community.utilities import SQLDatabase
db = SQLDatabase.from_uri("sqlite:///Chinook.db")
print(db.dialect)
print(db.get_usable_table_names())
db.run("SELECT * FROM Artist LIMIT 10;")
4. 使用链进行问答
链适用于步骤可预测的应用,我们可以创建一个简单的链来执行以下操作:
- 将问题转换为SQL查询。
- 执行查询。
- 根据结果回答问题。
4.1 问题到SQL
使用OpenAI的模型将用户问题转换为SQL查询:
from langchain_openai import ChatOpenAI
from langchain.chains import create_sql_query_chain
llm = ChatOpenAI(model="gpt-4o-mini")
chain = create_sql_query_chain(llm, db)
response = chain.invoke({"question": "How many employees are there"})
4.2 执行查询
通过QuerySQLDatabaseTool执行生成的查询:
from langchain_community.tools.sql_database.tool import QuerySQLDataBaseTool
execute_query = QuerySQLDataBaseTool(db=db)
write_query = create_sql_query_chain(llm, db)
chain = write_query | execute_query
chain.invoke({"question": "How many employees are there"})
5. 使用代理进行问答
代理提供了与SQL数据库交互的更灵活的方式,能够处理复杂的问题,如表描述和多查询。
5.1 初始化代理
使用SQLDatabaseToolkit创建工具,并初始化代理:
from langchain_community.agent_toolkits import SQLDatabaseToolkit
toolkit = SQLDatabaseToolkit(db=db, llm=llm)
tools = toolkit.get_tools()
from langchain_core.messages import SystemMessage
from langgraph.prebuilt import create_react_agent
system_message = SystemMessage(content="You are an agent ...") # 系统提示信息
agent_executor = create_react_agent(llm, tools, messages_modifier=system_message)
代码示例
完整的代理执行示例:
for s in agent_executor.stream({"messages": [HumanMessage(content="Which country's customers spent the most?")]}):
print(s)
print("----")
常见问题和解决方案
- 安全性:执行SQL查询时,确保数据库权限最小化,并考虑在执行前加入人工审核步骤。
- 高基数列处理:使用向量检索工具确保正确拼写。
总结和进一步学习资源
本文介绍了构建一个基于SQL数据的问答系统的流程,以及如何处理常见的开发挑战。对于更复杂的需求,可以查看以下资源:
- 高级提示工程技术 # 范例链接
- 查询验证和错误处理
- 处理大型数据库的技术
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---