引言
在处理大型数据库进行SQL问答时,生成有效查询需要将表名、表模式和特征值传递给模型。然而,当表、列数量庞大或列的基数较高时,我们无法在每次提示中提供数据库的完整信息。因此,我们需要找到方法,动态插入最相关的信息进行查询生成。
本文介绍了识别相关信息的方法,并演示如何将其输入到查询生成步骤中。主要内容包括:
- 识别相关的表子集
- 识别相关的列值子集
主要内容
1. 环境设置
首先,安装所需的软件包并设置环境变量:
%pip install --upgrade --quiet langchain langchain-community langchain-openai
安装并配置Chinook数据库,以便进行SQL操作:
# 创建Chinook.db
sqlite3 Chinook.db
.read Chinook_Sqlite.sql
SELECT * FROM Artist LIMIT 10;
2. 处理多个表
当表数量巨大时,我们无法将所有表模式放入单次提示中。解决方案是提取与用户输入相关的表名,并仅包含它们的模式。
示例中,我们使用langchain库进行此操作,并采用tool-calling方法来获取符合所需格式的输出。
from langchain_community.utilities import SQLDatabase
db = SQLDatabase.from_uri("sqlite:///Chinook.db")
llm = ChatOpenAI(model="gpt-4o-mini")
table_names = "\n".join(db.get_usable_table_names())
system = f"""Return the names of ALL the SQL tables that MIGHT be relevant to the user question. \
The tables are:\n\n{table_names}\n\nRemember to include ALL POTENTIALLY RELEVANT tables, even if you're not sure that they're needed."""
prompt = ChatPromptTemplate.from_messages(
[
("system", system),
("human", "{input}"),
]
)
llm_with_tools = llm.bind_tools([Table])
output_parser = PydanticToolsParser(tools=[Table])
table_chain = prompt | llm_with_tools | output_parser
table_chain.invoke({"input": "What are all the genres of Alanis Morisette songs"})
3. 处理高基数列
对于包含专有名词如地址、歌曲名称或艺术家名的列,我们需要在过滤数据前仔细校对拼写。
一种策略是创建一个向量库,存储数据库中所有不同的专有名词,并在每次用户输入时查询向量库,将最相关的专有名词注入提示中。
import ast
import re
def query_as_list(db, query):
res = db.run(query)
res = [el for sub in ast.literal_eval(res) for el in sub if el]
res = [re.sub(r"\b\d+\b", "", string).strip() for string in res]
return res
proper_nouns = query_as_list(db, "SELECT Name FROM Artist")
# 继续从其他表格中提取专有名词
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
vector_db = FAISS.from_texts(proper_nouns, OpenAIEmbeddings())
retriever = vector_db.as_retriever(search_kwargs={"k": 15})
代码示例
以下是处理“高基数列”的完整代码示例,使用查询构建链进行拼写纠正:
# With retrieval
query = chain.invoke({"question": "What are all the genres of elenis moriset songs"})
print(query)
db.run(query)
SELECT DISTINCT g.Name
FROM Genre g
JOIN Track t ON g.GenreId = t.GenreId
JOIN Album a ON t.AlbumId = a.AlbumId
JOIN Artist ar ON a.ArtistId = ar.ArtistId
WHERE ar.Name = 'Alanis Morissette';
# 应用API代理服务提高访问稳定性
常见问题和解决方案
-
如何处理拼写错误?
使用向量库匹配最接近的专有名词,以提高检索准确性。
-
如何在提示中动态包含信息?
结合使用工具调用和查询链,可以自动化动态信息插入。
总结和进一步学习资源
在SQL问答中,处理大型数据库需要智能选择相关信息以提高查询性能。希望本文为您提供了实用的方法和见解。更多资源请参考LangChain文档和SQL相关教程。
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---