大模型 LLM RAG在 Text2SQL 上的应用实践

这篇具有很好参考价值的文章主要介绍了大模型 LLM RAG在 Text2SQL 上的应用实践。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 前言

在上篇文章中「LLM Agent在Text2SQL应用上的实践」介绍了基于AI Agent来优化LLM的Text2SQL转换效果的实践,除此之外我们还可以使用RAG(Retrieval-Augmented Generation)来优化大模型应用的效果。

本文将从以下4个方面探讨通过RAG来优化LLM的Text2SQL转换效果。

1. RAG概述

2. 基于LangChain的RAG实现

3. RAG优化Text2SQL应用的实践

4. 后续计划

Text2SQL 系列

  • 如何通过 Prompt 优化大模型 Text2SQL 的效果
  • 大模型LLM在 Text2SQL 上的应用实践
  • 大模型LLM Agent在 Text2SQL 应用上的实践

技术交流

技术要学会分享、交流,不建议闭门造车。一个人走的很快、一堆人可以走的更远。

建立了大模型技术交流群,大模型学习资料、数据代码、技术交流提升, 均可加知识星球交流群获取,群友已超过2000人,添加时切记的备注方式为:来源+兴趣方向,方便找到志同道合的朋友。

方式①、微信搜索公众号:机器学习社区,后台回复:技术交流
方式②、添加微信号:mlc2060,备注:技术交流

大模型 LLM RAG在 Text2SQL 上的应用实践,大模型,自然语言,深度学习,RAG,大语言模型,人工智能

2. RAG概述

2.1 RAG概念

RAG(Retrieval-Augmented Generation)检索增强生成,即大模型LLM在回答问题或生成文本时,会先从大量的文档中检索出相关信息,然后基于这些检索出的信息进行回答或生成文本,从而可以提高回答的质量,而不是任由LLM来发挥。

RAG技术使得开发者没有必要为每个特定的任务重新训练整个大模型,只需要外挂上相关知识库就可以,即可为模型提供额外的信息输入,提高回答的准确性。RAG技术工作流程如下图所示。

大模型 LLM RAG在 Text2SQL 上的应用实践,大模型,自然语言,深度学习,RAG,大语言模型,人工智能

2.2 RAG能解决LLM的哪些问题

即使在LLM有较强的解决问题的能力,仍然需要RAG技术的配合,因为能够帮助解决LLM存在的以下几个问题。

(1)模型幻觉问题:LLM文本生成的底层原理是基于概率进行生成的,在没有已知事实作为支撑的情况下,不可避免的会出现一本正经的胡说八道的情况。而这种幻觉问题的区分是比较困难的,因为它要求使用者自身具备相应领域的知识。

(2)知识的局限性:模型自身的知识完全源于它的训练数据,而现有的主流大模型(ChatGPT、文心一言、通义千问…)的训练集基本都是构建于网络公开的数据,对于一些实时性的、非公开的或离线的数据是无法获取到的,这部分知识也就无从具备。

(3)数据安全问题:开源的大模型是没有企业内部数据和用户数据的,如果企业想在保证数据安全的前提下使用LLM,一种比较好的解决办法就是把数据放在本地,企业数据的业务计算全部放在本地完成。而在线的LLM只是完成一个归纳总结的作用。

2.3 RAG架构

简单来讲,RAG就是通过检索获取相关的知识并将其融入Prompt,让大模型能够参考相应的知识从而给出合理回答。

因此,可以将RAG的核心理解为“检索+生成”,前者主要是利用向量数据库的高效存储和检索能力,召回目标知识;后者则是利用大模型和Prompt工程,将召回的知识合理利用,生成目标答案。

完整的RAG应用流程主要包含两个阶段:

(1)数据准备阶段:数据提取–>文本分割–>向量化(embedding)–>数据入库;

(2)应用阶段:用户提问–>数据检索(检索)–>注入Prompt(增强)–>LLM生成答案(生成)。

下面我们详细介绍一下各环节的技术细节和注意事项:

2.3.1 数据准备阶段

数据准备一般是一个离线的过程,主要是将私域数据向量化后构建索引并存入数据库的过程。主要包括:数据提取、文本分割、向量化、数据入库等环节。

  • 数据提取

o 数据加载:包括多格式数据加载、不同数据源获取等,根据数据自身情况,将数据处理为同一个范式。

o 数据处理:包括数据过滤、压缩、格式化等。

o 元数据获取:提取数据中关键信息,例如文件名、Title、时间等。

  • 文本分割

文本分割主要考虑两个因素:

(1)embedding模型的Tokens限制情况;

(2)语义完整性对整体的检索效果的影响。

一些常见的文本分割方式如下:

o 句分割:以”句”的粒度进行切分,保留一个句子的完整语义。常见切分符包括:句号、感叹号、问号、换行符等。

o 固定长度分割:根据embedding模型的token长度限制,将文本分割为固定长度(例如256/512个tokens),这种切分方式会损失很多语义信息,一般通过在头尾增加一定冗余量来缓解。

  • 向量化(Embedding)

向量化是一个将文本数据转化为向量矩阵的过程,该过程会直接影响到后续检索的效果。目前常见的Embedding模型基本能满足大部分需求,但对于特殊场景(例如涉及一些罕见专有词或字等)或者想进一步优化效果,则可以选择开源Embedding模型微调或直接训练适合自己场景的Embedding模型。

  • 数据入库

数据向量化后构建索引,并写入数据库的过程可以概述为数据入库过程,适用于RAG场景的数据库包括:FAISS、Chromadb、Milvus、ES等。一般可以根据业务场景、硬件、性能需求等多因素综合考虑,选择合适的数据库。

2.3.2 应用阶段

在应用阶段,我们根据用户的提问,通过高效的检索方法,召回与提问最相关的知识,并融入Prompt;大模型参考当前提问和相关知识,生成相应的答案。关键环节包括:数据检索、注入Prompt等。

  • 数据检索(Retrieval)

常见的数据检索方法包括:相似性检索、全文检索等,根据检索效果,一般可以选择多种检索方式融合,提升召回率。

o 相似性检索:即计算查询向量与所有存储向量的相似性得分,返回得分高的记录。常见的相似性计算方法包括:余弦相似性、欧氏距离、曼哈顿距离等。

o 全文检索:全文检索是一种比较经典的检索方式,在数据存入时,通过关键词构建倒排索引;在检索时,通过关键词进行全文检索,找到对应的记录,比如ES。

  • 注入Prompt(Augmented)

Prompt作为大模型的直接输入,是影响模型输出准确率的关键因素之一。在RAG场景中,Prompt一般包括任务描述、背景知识(检索得到)、任务指令(一般是用户提问)等,根据任务场景和大模型性能,也可以在Prompt中适当加入其他指令优化大模型的输出。

  • LLM生成(Generation)

在这个阶段,我们将经过检索增强的提示内容输入到大语言模型(LLM)中,以生成所需的输出。这个过程是RAG的核心,它利用LLM的强大生成能力,结合前两个阶段的信息,从而生成准确、丰富且与上下文相关的输出。

3. 基于LangChain的RAG实现

3.1 LangChain中RAG模块

LangChain有许多组件用于帮助构建RAG应用程序。为了熟悉这些内容,我们将在网络文本数据源上构建一个简单的问答应用程序。在此过程中,我们将介绍一个典型的问答架构,讨论相关LangChain组件的使用,其工作流程如图。

大模型 LLM RAG在 Text2SQL 上的应用实践,大模型,自然语言,深度学习,RAG,大语言模型,人工智能

3.2 基于LangChain实现RAG

我们将在Lilian Weng的「LLM Powered Autonomous Agents」博客文章基础上构建一个QA应用程序,该应用程序允许我们就文章内容提出问题。

1. 加载文档

首先需要收集并加载数据,可以利用LangChain提供的众多 DocumentLoader之一来加载这些数据。这里的Document是一个包含文本和元数据的字典,为了加载文本,我们可以使用LangChain的 WebBaseLoader来加载Web url,只有加载类为“post-content”、“post-title”或“post-header”的HTML标记内容。

import bs4
from langchain_community.document_loaders import WebBaseLoader

# Only keep post title, headers, and content from the full HTML.
bs4_strainer = bs4.SoupStrainer(class_=("post-title", "post-header", "post-content"))
loader = WebBaseLoader(
    web_paths=("https://lilianweng.github.io/posts/2023-06-23-agent/",),
    bs_kwargs={"parse_only": bs4_strainer},
)
docs = loader.load()

2. 文档切分

由于原始状态下的Document可能过长,无法适应大语言模型(LLM)的上下文窗口,所以我们需要将其分成更小的部分。LangChain内置许多该功能的文本分割器。在这个简单的示例中,我们可以使用RecursiveCharacterTextSplitter,递归地分割文档,直到每个块的大小合适。这是推荐用于一般文本用例的文本拆分器。设置chunk_size约为1000和chunk_overlap约为200,增加一定的冗余量,以保持块之间的文本连续性。

from langchain.text_splitter import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000, chunk_overlap=200, add_start_index=True
)
all_splits = text_splitter.split_documents(docs)

3. 向量存储

需要为每个块生成向量embedding,并将其存储在向量数据库或向量存储中。为了生成向量embedding,我们可以使用OpenAI的embedding模型。同时,我们可以使用Chroma向量数据库来存储这些embedding。通过调用.from_documents()方法生成向量存储对象。

from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma

vectorstore = Chroma.from_documents(documents=all_splits, embedding=OpenAIEmbeddings()

4. 检索(Retrieval)

在检索过程中,系统接受用户问题,搜索与该问题相关的文档,将检索到的文档和初始问题传递给模型,并返回答案。最常见的检索器类型是VectorStoreRetriever,它使用向量存储的相似性搜索功能来简化检索。使用VectorStore.as_retriever(),任何VectorStore都可以很容易地转换为Retriever。

retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 6})

5. 增强(Augmented

接下来,需要使用检索到的上下文信息来增强我们的提示。为此,我们需要准备一个提示模板。在LangChain中,我们可以使用ChatPromptTemplate来创建一个提示模板。这个模板会告诉LLM如何使用检索到的上下文来回答问题。

from langchain import hub
prompt = hub.pull("rlm/rag-prompt")

生成的ChatPromptTemplate为:

You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise.
Question: {question} 
Context: {context} 
Answer:

6. LLM****生成回答(Generation

最后,需要构建一个RAG流程链,将检索器、提示模板和LLM连接起来。定义好RAG链后,我们就可以调用它进行生成。这里使用OpenAI的gpt-3.5-turbo模型,其他LangChain LLM或ChatModel也可以进行替代。

from langchain.chat_models import ChatOpenAI
from langchain.schema.runnable import RunnablePassthrough
from langchain.schema.output_parser import StrOutputParser

llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)

rag_chain = (
    {"context": retriever,  "question": RunnablePassthrough()} 
    | prompt 
    | llm
    | StrOutputParser() 
)
rag_chain.invoke("What is Task Decomposition?")

输出结果:

'Task decomposition is a technique used to break down complex tasks into smaller and simpler steps. 
It involves transforming big tasks into multiple manageable tasks, allowing for a more systematic and organized approach to problem-solving.
Thanks for asking!'

原文内容如图:

大模型 LLM RAG在 Text2SQL 上的应用实践,大模型,自然语言,深度学习,RAG,大语言模型,人工智能

4. RAG优化Text2SQL应用的实践

4.1 现有问题

依然以上篇文中「大模型LLM在Text2SQL上的应用实践」的数据库Chinook为例,需求为统计“连续两个月都下订单的客户有哪些?”,示例代码可参考上文。

结果如下:

大模型 LLM RAG在 Text2SQL 上的应用实践,大模型,自然语言,深度学习,RAG,大语言模型,人工智能

可以看出生成的SQL不准确,只统计了最近两个月中都下订单的客户,和统计需求不相符。那如何解决这个问题?

4.2 RAG解决方案

尽管SQL Toolkit包含处理数据库所需的工具,但通常情况下,一些额外的工具可能对扩展代理的功能有用。当试图在解决方案中使用特定领域的知识以提高其整体性能时,这一点尤其有用。

我们使用问题列表few-shot examples作为外部知识库,为了参考该知识库,我们需要一个利用向量数据库的自定义检索工具,以便检索语义上与用户问题相似的示例。

1. 创建的问题列表few-shot example如下:

few_shots = {
    "How many employees are there?": "SELECT COUNT(*) FROM employee;",
    "在订单表中,连续两个月都下订单的客户有哪些?":"SELECT DISTINCT a.'CustomerId', a.'FirstName', a.'LastName' FROM 'Customer' a JOIN 'Invoice' b ON a.'CustomerId' = b.'CustomerId' JOIN 'Invoice' c ON a.'CustomerId' = c.'CustomerId' AND ((strftime('%Y-%m', b.'InvoiceDate') = strftime('%Y-%m', date(c.'InvoiceDate', '-1 month'))) OR (strftime('%Y-%m', b.'InvoiceDate') = strftime('%Y-%m', date(c.'InvoiceDate', '+1 month'))))",
    "同一客户的订单中连续两笔订单金额都大于1的客户有哪些?":"SELECT DISTINCT c.'CustomerId', c.'FirstName', c.'LastName' FROM 'Invoice' a JOIN 'Invoice' b ON a.'CustomerId' = b.'CustomerId' AND a.'InvoiceId' < b.'InvoiceId' JOIN 'Customer' c ON a.'CustomerId' = c.'CustomerId' WHERE a.'Total' > 1 AND b.'Total' > 1 AND NOT EXISTS ( SELECT 1 FROM 'Invoice' i WHERE i.'CustomerId' = a.'CustomerId' AND i.'InvoiceId' > a.'InvoiceId' AND i.'InvoiceId' < b.'InvoiceId')",
}

2. 可以使用问题列表创建一个检索器,将目标SQL查询分配为元数据:

from langchain.schema import Document
from langchain_community.embeddings.openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS

embeddings = OpenAIEmbeddings()

few_shot_docs = [
    Document(page_content=question, metadata={"sql_query": few_shots[question]})
    for question in few_shots.keys()
]
vector_db = FAISS.from_documents(few_shot_docs, embeddings)
retriever = vector_db.as_retriever()

3. 现在可以创建自定义工具,并将其作为新工具附加到create_sql_agent函数中:

from langchain_community.agent_toolkits import create_retriever_tool

# description注意要加 in Chinese,使用中文检索,切记!
tool_description = """
This tool will help you understand similar examples to adapt them to the user question in Chinese.
Input to this tool should be the user question.
"""

retriever_tool = create_retriever_tool(
    retriever, name="sql_get_similar_examples", description=tool_description
)
custom_tool_list = [retriever_tool]

4. 创建代理,根据我们的示例调整标准SQL Agent的后缀。尽管处理此问题的最直接方法是仅将其包含在上一步骤的“tool_description”中,但这通常是不够的,我们需要在agent prompt中使用构造函数的“suffix”参数来指定它。

from langchain.agents import AgentType, create_sql_agent
from langchain_community.agent_toolkits import SQLDatabaseToolkit
from langchain_community.chat_models import ChatOpenAI
from langchain_community.utilities import SQLDatabase

db = SQLDatabase.from_uri("sqlite:///xxxx/Chinook.db")
llm = ChatOpenAI(model_name="gpt-4", temperature=0)
toolkit = SQLDatabaseToolkit(db=db, llm=llm)

# 注意要加 in Chinese,使用中文检索,切记!
custom_suffix = """
I should first get the similar examples in Chinese I know.
If the examples are enough to construct the query, I can build it.
Otherwise, I can then look at the tables in the database to see what I can query.
Then I should query the schema of the most relevant tables
"""

agent = create_sql_agent(
    llm=llm,
    toolkit=toolkit,
    verbose=True,
    agent_type=AgentType.OPENAI_FUNCTIONS,
    extra_tools=custom_tool_list,
    suffix=custom_suffix,
)

5. 执行提问:

agent.run("连续两个月都有下订单的客户有哪些?")

结果如下:

大模型 LLM RAG在 Text2SQL 上的应用实践,大模型,自然语言,深度学习,RAG,大语言模型,人工智能

大模型 LLM RAG在 Text2SQL 上的应用实践,大模型,自然语言,深度学习,RAG,大语言模型,人工智能

效果:生成的SQL与结果基本满足我们的需求。首先使用sql_get_similar_examples工具来检索类似的示例。由于该问题与few-shot examples中的示例相似,因此不需要使用Toolkit中的任何其他工具,从而节省了时间和tokens。

6. 换个相似的问题提问:

agent.run("找出哪些客户连续两个月都有下订单?")

结果如下:

大模型 LLM RAG在 Text2SQL 上的应用实践,大模型,自然语言,深度学习,RAG,大语言模型,人工智能

大模型 LLM RAG在 Text2SQL 上的应用实践,大模型,自然语言,深度学习,RAG,大语言模型,人工智能

效果: 生成的SQL与结果基本满足我们的需求。

5. 后续计划

本文详细介绍了检索增强生成(RAG)的概念,并演示如何利用LangChain实现RAG流程,以及通过RAG来扩展SQL Agent的功能,进一步优化Text2SQL应用的效果。可以看到RAG为解决LLM在处理特定、最新和专有信息方面的不足提供了一个有效且灵活的方法,使其生成更精确、更贴合上下文的答案,有效减少误导性信息的产生。后续我们可以将数据管理中的元数据信息作为域内专业知识提供给大模型,借助RAG进一步提示LLM应用的效果。

参考文献:

https://arxiv.org/abs/2312.10997

https://python.langchain.com/docs/use_cases/question_answering

https://python.langchain.com/docs/use_cases/qa_structured/sql

https://zhuanlan.zhihu.com/p/668082024

https://zhuanlan.zhihu.com/p/666771841文章来源地址https://www.toymoban.com/news/detail-783499.html

到了这里,关于大模型 LLM RAG在 Text2SQL 上的应用实践的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • NL2SQL进阶系列(2):DAIL-SQL、DB-GPT开源应用实践详解[Text2SQL]

    NL2SQL基础系列(1):业界顶尖排行榜、权威测评数据集及LLM大模型(Spider vs BIRD)全面对比优劣分析[Text2SQL、Text2DSL] NL2SQL基础系列(2):主流大模型与微调方法精选集,Text2SQL经典算法技术回顾七年发展脉络梳理 NL2SQL任务的目标是将用户对某个数据库的自然语言问题转化为相应的

    2024年04月13日
    浏览(32)
  • TEXT2SQL-顶峰:Vanna部署及介绍

    Vanna 是一款采用 MIT 许可的开源 Python RAG (检索增强生成)框架,用于生成 SQL 语句和相关功能。 如何使用 Vanna Vanna 的使用分为两个简单步骤 - 在你的数据上训练一个 RAG \\\"模型\\\",然后提出问题,该问题将返回可设置为自动在你的数据库上运行的 SQL 查询。 1. 在你的数据上训练一

    2024年02月22日
    浏览(29)
  • NLP-语义解析(Text2SQL):技术路线【Seq2Seq、模板槽位填充、中间表达、强化学习、图网络】

      目前关于NL2SQL技术路线的发展主要包含以下几种: Seq2Seq方法: 在深度学习的研究背景下,很多研究人员将Text-to-SQL看作一个类似神经机器翻译的任务,主要采取Seq2Seq的模型框架。基线模型Seq2Seq在加入Attention、Copying等机制后,能够在ATIS、GeoQuery数据集上达到84%的精确匹配,但是在

    2024年02月12日
    浏览(43)
  • ChatGPT论文:大语言模型LLM之战:Dolly、LLaMA 、Vicuna、Guanaco、Bard、ChatGPT--在自然语言转SQL(NL2SQL、Text-to-SQL)的比较(一)

    ChatGPT的成功引发了一场AI竞赛,研究人员致力于开发新的大型语言模型(LLMs),以匹敌或超越商业模型的语言理解和生成能力。近期,许多声称其性能接近GPT-3.5或GPT-4的模型通过各种指令调优方法出现了。作为文本到SQL解析的从业者,我们感谢他们对开源研究的宝贵贡献。然

    2024年02月02日
    浏览(34)
  • 【医学大模型】Text2MDT :从医学指南中,构建医学决策树

      论文:https://arxiv.org/pdf/2401.02034.pdf 代码:https://github.com/michael-wzhu/text2dt   假设我们有一本医学指南,其中包含关于诊断和治疗某种疾病的指导。 首先,通过标准化和结构化的方法,我们定义出哪些文本片段表示条件判断(例如,病人年龄超过60岁),哪些表示决策(例如

    2024年02月20日
    浏览(33)
  • 0基础搞AI-NL2SQL数据集处理脚本(用于LLM-fine-tune)

            消失了好久好久,这次换了一家公司,然后又在忙于秋招,因此很久没有更新,最近事情也告一段落,因此终于有空回来水博客,今天给大家带来最近的工作,NL2SQL数据集,我们的工作是利用代码生成大模型(类似CodeFuse系列,CodeLlama系列)进行fine-tune,通过用户

    2024年04月11日
    浏览(33)
  • Text2Video-Zero:Text-to-Image扩散模型是Zero-Shot视频生成器

    Paper: https://arxiv.org/abs/2303.13439 Project: https://github.com/Picsart-AI-Research/Text2Video-Zero 原文链接:Text2Video-Zero:Text-to-Image扩散模型是Zero-Shot视频生成器(by 小样本视觉与智能前沿) 目录 最近的text-to-video生成方法依赖于计算量大的训练,并且需要大规模的视频数据集。 在本文中,我

    2024年02月11日
    浏览(31)
  • OpenAI LLM 应用最佳实践:提示词工程、Fine-Tune、RAG

    一、背景 本文介绍了 2023 年 11 月 OpenAI DevDay 中的一个演讲,演讲者为 John Allard 和 Colin Jarvis。演讲中,作者对 LLM 应用落地过程中遇到的问题和相关改进方案进行了总结。虽然其中用到的都是已知的技术,但是进行了很好的总结和串联,并探索了一条改进 LLM 应用的切实可行

    2024年03月11日
    浏览(32)
  • Elasticsearch:使用在本地计算机上运行的 LLM 以及 Ollama 和 Langchain 构建 RAG 应用程序

    无需 GPU 的隐私保护 LLM。在本博客中,我将演示使用不同的工具 Ollama 构建的 RAG 应用程序。 与本文相关的所有源代码均已发布在 github上。 请克隆存储库以跟随文章操作。我们可以通过如下的方式来克隆: Ollama 是一个轻量级且灵活的框架,专为在个人计算机上本地部署 LL

    2024年04月16日
    浏览(43)
  • NL2SQL进阶系列(1):DB-GPT-Hub开源应用实践

    云鲸智能渠道运营实习面经 一直想找销售实习,但是日常销售实习好难找。。。海投面试中拿到了这个岗位的offer,就给大家分享下这   题解 | #验证IP地址# /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * 验证I   题解 | #验证IP地址

    2024年04月23日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包