微信扫码
与创始人交个朋友
我要投稿
对业务数据库中的表实现问答。输入是用户的问题,输出是该问题的答案。
这是很典型的Text2SQL的应用场景了,为了实现这一需求,很容想到的是把创建的表和表的描述都放进prompt里,让LLM去根据表的结构生成SQL语句,再利用工具去执行SQL语句,拿到查询结果后,再丢给LLM,让LLM根据给定的内容回答问题。我一开始也是这么想的,但是,当你的业务表非常多的时候,比如有上千个,你应该选择哪个表或者哪些表去给到LLM呢?根据问题去检索可能会用到的表是比较容易想到的一种方式。
于是,我带着我的疑惑,去调研了目前一些比较火的text2sql的框架。惊奇地发现,他们确实也是这样做的。比较典型的就是vanna[1]了
从上图可以看出,Vanna实际上分了三个部分做RAG:
•DDL 语句检索:对建表的语句做语义检索,建表时的表描述和字段注释•文档检索:包括对一些专有名字的解释,以及拼接表的每个字段组成的字符串等一些其他相关文档•Query 与 对应的SQL检索:用户的问题与对应的SQL语句
DDL语句向量化: 对于每一个建表语句,进行embedding,表和字段的描述,对结果的影响非常大,如果只有简单的建表语句,效果如何完全取决于大模型能不能猜对你这个表是干嘛的。
文档向量化: 这里可以将数据库中的所有数据,按一定的规则拼接成自然语言,然后向量化。还可以将一些LLM比较难理解的专有名词的解释向量化,在有相关的Query进来时,专有名词的解释也会被召回,一起放进Prompt中,帮助LLM理解Query
Query与SQL语句向量化: 在Vanna中,这一步的做法是将Query与SQL dumps成一个字符串,一起向量化。
Vanna对比过不同策略加入后对最终效果的影响:
从下表可以看出,仅仅给出表的结构,LLM生成正确的SQL还是比较困难的,但是给了few shot后,效果立马飙升。
可以看到,使用上下文相关的fewshot,效果又提升了一小截。上下文相关的fewshot就是那些检索出来的相关的DDL、文档、以及Query-SQL对。
既然Vanna也是RAG,那么RAG的那些奇技淫巧,便可以在Text2SQL也派上用场了。咱们可以看看Vanna相比那些奇技淫巧少了哪些部分,给它安排上就完事了,核心目标就是为了提升检索相关度。
通过阅读Vanna的源码,发现Vanna只做了粗排,那么咱们就给它安排上重排,这不就好起来了么,简单粗暴。
class MyChromaDB(ChromaDB_VectorStore):
def __init__(self, config=None):
super().__init__(config)
self.rerank_model = CrossEncoder('bge-reranker-large',
max_length=512)
def get_similar_question_sql(self, question: str, **kwargs) -> list:
documents = ChromaDB_VectorStore._extract_documents(
self.sql_collection.query(
query_texts=[question],
n_results=self.n_results_sql,
)
)
if documents != []:
scores = self.rerank_model.predict([(question, doc["question"]) for doc in documents])
combined = list(zip(documents, scores))
sorted_combined = sorted(combined, key=lambda x: x[1], reverse=True)
documents = [item[0] for item in sorted_combined]
return documents
def get_related_ddl(self, question: str, **kwargs) -> list:
documents = ChromaDB_VectorStore._extract_documents(
self.ddl_collection.query(
query_texts=[question],
n_results=self.n_results_ddl,
)
)
if documents != []:
scores = self.rerank_model.predict([(question, doc) for doc in documents])
combined = list(zip(documents, scores))
sorted_combined = sorted(combined, key=lambda x: x[1], reverse=True)
documents = [item[0] for item in sorted_combined]
return documents
def get_related_documentation(self, question: str, **kwargs) -> list:
documents = ChromaDB_VectorStore._extract_documents(
self.documentation_collection.query(
query_texts=[question],
n_results=self.n_results_documentation,
)
)
if documents != []:
scores = self.rerank_model.predict([(question, doc) for doc in documents])
combined = list(zip(documents, scores))
sorted_combined = sorted(combined, key=lambda x: x[1], reverse=True)
documents = [item[0] for item in sorted_combined]
return documents
对了,BCE的模型在Text2SQL场景的效果不咋地,不建议使用。我这里使用的是BGE,有条件的同学甚至可以微调一下。
我这里没有对Query-SQL对中的SQL做检索,主要是考虑到用户的Query与SQL语句的相关性并不大,当然,获取数据这里修改成只计算Query的相关性时,你还需要对Query-SQL的向量化部分进行相应修改,应改成只对Query embedding。
53AI,企业落地应用大模型首选服务商
产品:大模型应用平台+智能体定制开发+落地咨询服务
承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2024-11-16
通过Reranking来优化RAG:提升信息检索的精准度
2024-11-16
从RAG到TAG:探索表增强生成(TAG)的力量
2024-11-15
复旦发布:最佳RAG方案
2024-11-15
破解PDF解析难题:RAG中高效解析复杂PDF的最佳选择
2024-11-15
RAG技术全解析:从基础到前沿,掌握智能问答新动向
2024-11-15
RAG在未来会消失吗?附RAG的5种切分策略
2024-11-15
HtmlRAG:利用 HTML 结构化信息增强 RAG 系统的知识检索能力和准确性
2024-11-15
打造自己的RAG解析大模型:表格数据标注的三条黄金规则
2024-07-18
2024-07-09
2024-05-05
2024-07-09
2024-05-19
2024-06-20
2024-07-07
2024-07-07
2024-07-08
2024-07-09
2024-11-06
2024-11-06
2024-11-05
2024-11-04
2024-10-27
2024-10-25
2024-10-21
2024-10-21