AI--构建检索增强生成 (RAG) 应用程序

news2024/11/17 13:25:22

LLM 所实现的最强大的应用之一是复杂的问答 (Q&A) 聊天机器人。这些应用程序可以回答有关特定源信息的问题。这些应用程序使用一种称为检索增强生成 (RAG) 的技术。
典型的 RAG 应用程序有两个主要组件

  • 索引:从源中提取数据并对其进行索引的管道。这通常在线下进行。
  • 检索和生成:实际的 RAG 链,它在运行时接受用户查询并从索引中检索相关数据,然后将其传递给模型。

从原始数据到答案最常见的完整序列如下:

  1. 加载:首先我们需要加载数据。这是通过DocumentLoaders完成的。
  2. 拆分:文本拆分器将大块内容拆分Documents成小块内容。这对于索引数据和将数据传递到模型都很有用,因为大块内容更难搜索,并且不适合模型的有限上下文窗口。
  3. 存储:我们需要一个地方来存储和索引我们的分割,以便以后可以搜索它们。这通常使用VectorStore和Embeddings模型来完成
    在这里插入图片描述

检索和生成
4. 检索:根据用户输入,使用检索器从存储中检索相关分割。
5. 生成:ChatModel / LLM使用包含问题和检索到的数据的提示生成答案
在这里插入图片描述


#创建embedding 模型
from langchain.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_community.vectorstores.utils import DistanceStrategy
from config import EMBEDDING_PATH
  
# init embedding model
model_kwargs = {'device': 'cuda'}
encode_kwargs = {'batch_size': 64, 'normalize_embeddings': True}

embed_model = HuggingFaceEmbeddings(
    model_name=EMBEDDING_PATH,
    model_kwargs=model_kwargs,
    encode_kwargs=encode_kwargs
  )

#导入相关库
from langchain_openai import ChatOpenAI
import bs4
from langchain import hub
from langchain_community.vectorstores import FAISS
from langchain_community.document_loaders import WebBaseLoader
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_text_splitters import RecursiveCharacterTextSplitter

chat = ChatOpenAI()

loader = WebBaseLoader(
    web_paths=("https://lilianweng.github.io/posts/2023-06-23-agent/",),
    bs_kwargs=dict(
        parse_only=bs4.SoupStrainer(
            class_=("post-content", "post-title", "post-header")
        )
    ),
)
docs = loader.load()

documents = RecursiveCharacterTextSplitter(chunk_size=1000,chunk_overlap=200).split_documents(docs)

vetorstors = FAISS.from_documents(documents,embed_model)

retriever = vetorstors.as_retriever()

promt = hub.pull("rlm/rag-prompt")

promt


def format_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)

#创建链
chain =(
    {"context":retriever | format_docs ,"question":RunnablePassthrough()}
    | promt
    | chat
    | StrOutputParser()
)

chain.invoke("What is Task Decomposition?")

输出结果

‘Task decomposition is the process of breaking down a problem into multiple thought steps to create a tree structure. It can be achieved through LLM with simple prompting, task-specific instructions, or human inputs. The goal is to transform big tasks into smaller and simpler steps to enhance model performance on complex tasks.’

首先:这些组件(retriever、prompt、chat等)中的每一个都是Runnable的实例。这意味着它们实现相同的方法——例如sync和async .invoke、、.stream或.batch——这使得它们更容易连接在一起。它们可以通过运算符|连接到RunnableSequence(另一个 Runnable)。
当遇到|操作符时,LangChain 会自动将某些对象转换为 Runnable。这里,format_docs转换为RunnableLambda"context" ,带有和的字典"question"转换为RunnableParallel。细节并不重要,重要的是,每个对象都是一个 Runnable。

让我们追踪一下输入问题如何流经上述可运行程序。
正如我们在上面看到的,输入prompt预计是一个带有键"context"和 的字典"question"。因此,该链的第一个元素构建了可运行对象,它将根据输入问题计算这两个值:
retriever | format_docs: 将文本传递给检索器,生成Document对象,然后将Document对象format_docs生成字符串;
RunnablePassthrough()不变地通过输入问题。

内置Chain

from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import ChatPromptTemplate

system_prompt = (
    "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, say that you "
    "don't know. Use three sentences maximum and keep the "
    "answer concise."
    "\n\n"
    "{context}"
)

prompt = ChatPromptTemplate.from_messages(
    [
        ("system", system_prompt),
        ("human", "{input}"),
    ]
)


question_answer_chain = create_stuff_documents_chain(chat, prompt)
rag_chain = create_retrieval_chain(retriever, question_answer_chain)

response = rag_chain.invoke({"input":"What is Task Decomposition?"})
print(response)

输出结果:

{‘input’: ‘What is Task Decomposition?’, ‘context’: [Document(page_content=‘Tree of Thoughts (Yao et al. 2023) extends CoT by exploring multiple reasoning possibilities at each step. It first decomposes the problem into multiple thought steps and generates multiple thoughts per step, creating a tree structure. The search process can be BFS (breadth-first search) or DFS (depth-first search) with each state evaluated by a classifier (via a prompt) or majority vote.\nTask decomposition can be done (1) by LLM with simple prompting like “Steps for XYZ.\n1.”, “What are the subgoals for achieving XYZ?”, (2) by using task-specific instructions; e.g. “Write a story outline.” for writing a novel, or (3) with human inputs.’, metadata={‘source’: ‘https://lilianweng.github.io/posts/2023-06-23-agent/’}), Document(page_content=‘Fig. 1. Overview of a LLM-powered autonomous agent system.\nComponent One: Planning#\nA complicated task usually involves many steps. An agent needs to know what they are and plan ahead.\nTask Decomposition#\nChain of thought (CoT; Wei et al. 2022) has become a standard prompting technique for enhancing model performance on complex tasks. The model is instructed to “think step by step” to utilize more test-time computation to decompose hard tasks into smaller and simpler steps. CoT transforms big tasks into multiple manageable tasks and shed lights into an interpretation of the model’s thinking process.’, metadata={‘source’: ‘https://lilianweng.github.io/posts/2023-06-23-agent/’}), Document(page_content=‘Fig. 2. Examples of reasoning trajectories for knowledge-intensive tasks (e.g. HotpotQA, FEVER) and decision-making tasks (e.g. AlfWorld Env, WebShop). (Image source: Yao et al. 2023).\nIn both experiments on knowledge-intensive tasks and decision-making tasks, ReAct works better than the Act-only baseline where Thought: … step is removed.\nReflexion (Shinn & Labash 2023) is a framework to equips agents with dynamic memory and self-reflection capabilities to improve reasoning skills. Reflexion has a standard RL setup, in which the reward model provides a simple binary reward and the action space follows the setup in ReAct where the task-specific action space is augmented with language to enable complex reasoning steps. After each action a t a_t at, the agent computes a heuristic h t h_t ht and optionally may decide to reset the environment to start a new trial depending on the self-reflection results.’, metadata={‘source’: ‘https://lilianweng.github.io/posts/2023-06-23-agent/’}), Document(page_content=‘Here are a sample conversation for task clarification sent to OpenAI ChatCompletion endpoint used by GPT-Engineer. The user inputs are wrapped in {{user input text}}.\n[\n {\n “role”: “system”,\n “content”: “You will read instructions and not carry them out, only seek to clarify them.\nSpecifically you will first summarise a list of super short bullets of areas that need clarification.\nThen you will pick one clarifying question, and wait for an answer from the user.\n”\n },\n {\n “role”: “user”,\n “content”: “We are writing {{a Super Mario game in python. MVC components split in separate files. Keyboard control.}}\n”\n },\n {\n “role”: “assistant”,’, metadata={‘source’: ‘https://lilianweng.github.io/posts/2023-06-23-agent/’})], ‘answer’: ‘Task decomposition involves breaking down a complex task into smaller and simpler steps to make it more manageable. This technique allows models or agents to utilize more computational resources at test time by thinking step by step. By decomposing tasks, models can better understand and interpret the thinking process involved in solving difficult problems.’}

create_stuff_documents_chain

def create_stuff_documents_chain(
    llm: LanguageModelLike,
    prompt: BasePromptTemplate,
    *,
    output_parser: Optional[BaseOutputParser] = None,
    document_prompt: Optional[BasePromptTemplate] = None,
    document_separator: str = DEFAULT_DOCUMENT_SEPARATOR,
) -> Runnable[Dict[str, Any], Any]:

    _validate_prompt(prompt)
    _document_prompt = document_prompt or DEFAULT_DOCUMENT_PROMPT
    _output_parser = output_parser or StrOutputParser()

    def format_docs(inputs: dict) -> str:
        return document_separator.join(
            format_document(doc, _document_prompt) for doc in inputs[DOCUMENTS_KEY]
        )

    return (
        RunnablePassthrough.assign(**{DOCUMENTS_KEY: format_docs}).with_config(
            run_name="format_inputs"
        )
        | prompt
        | llm
        | _output_parser
    ).with_config(run_name="stuff_documents_chain")

从源代码看出来,就是chain

create_retrieval_chain

def create_retrieval_chain(
    retriever: Union[BaseRetriever, Runnable[dict, RetrieverOutput]],
    combine_docs_chain: Runnable[Dict[str, Any], str],
) -> Runnable:

    if not isinstance(retriever, BaseRetriever):
        retrieval_docs: Runnable[dict, RetrieverOutput] = retriever
    else:
        retrieval_docs = (lambda x: x["input"]) | retriever

    retrieval_chain = (
        RunnablePassthrough.assign(
            context=retrieval_docs.with_config(run_name="retrieve_documents"),
        ).assign(answer=combine_docs_chain)
    ).with_config(run_name="retrieval_chain")

    return retrieval_chain

create_retrieval_chain调用过程就是先检索,然后调用combine_docs_chain

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1684171.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FRAUDARCatchSync算法简介

参考:https://blog.51cto.com/u_15127663/2778705 1. 背景 Fraudar 要解决的问题是:找出社交网络中最善于伪装的虚假用户簇。虚假用户会通过增加和正常用户的联系来进行伪装,而这些伪装(边)会形成一个很密集的子网络,可以通过定义…

数据结构(二)单链表

一、链表 (一)概念 逻辑结构:线性 存储结构:链式存储,在内存中不连续 分为有头链表和无头链表 同时又细分为单向、循环、双向链表 (二)有头单向链表示意图 以下数据及地址只是为了方便理解…

STM32_ADC

1、ADC简介 ADC,即Analog-Digital Converter,模拟-数字转换器。 ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁。 12位逐次逼近型ADC,1us转换时间。 输入电压范围:0~3.3…

MySQL数据库单表查询中查询条件的写法

1.使用比较运算符作为查询条件 ; !; >; >; <; <; 如上图所示&#xff0c;可以使用命令select 字段&#xff0c;字段 from 表名 where Gender “M”; 即挑选出Gender “M” 的教师&#xff0c; 如上图所示&#xff0c;可以使用命令select 字段&#xff0c;…

fastadmin 树状菜单展开,合并;简要文件管理系统界面设计与实现

一&#xff0c;菜单合并效果图 源文件参考&#xff1a;fastadmin 子级菜单展开合并、分类父级归纳 - FastAdmin问答社区 php服务端&#xff1a; public function _initialize() {parent::_initialize();$this->model new \app\admin\model\auth\Filetype;$this->admin…

chatGPT预训练模型范例之GPT3系列模型的解密

目录 前言 一、GPT的背景 二、GPT的架构 那么如何实现零样本&#xff08;zero-shot&#xff09;学习呢? 这里我们还是主要来看一下 GPT-3 中所谓的 few-/one-/zero- shot 方式分别是什么意思&#xff1f; 三、GPT的应用 四、GPT3的局限性 前言 近年来&#xff0c;预训练…

分割训练日志的可视化

这一部分主要是将mmdetection训练得到的json文件可视化&#xff0c;代码主要源于github&#xff0c;具体哪一个忘记了&#xff08;readme里面没有原址…&#xff09;是专门做的mmdetection 结果可视化的&#xff0c;非常强&#xff01;&#xff01;。使用时如果出现keyerror的话…

MT3041 多项式变换求值

注意点&#xff1a; 1.使用单调栈 2.用ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);避免超时 3.此题除了ans最好不要用long long&#xff0c;如果a[]和b[]都是long long 类型&#xff0c;可能会超内存 4.ans (ans % p p) % p;防止负数 5.使用秦九韶算法计算指数…

MySQL用户管理操作

用户权限管理操作 DCL语句 一.用户管理操作 MySQL软件内部完整的用户格式&#xff1a; 用户名客户端地址 admin1.1.1.1这个用户只能从1.1.1.1的客服端来连接服务器 admin1.1.1.2这个用户只能从1.1.1.2的客服端来连接服务器 rootlocal host这个用户只能从服务器本地进行连…

ptrade从零开始学习量化交易第11期【ptrade策略引擎简介之on_order_response - 委托主推(可选)】

策略引擎简介 更加详细的调用方法&#xff0c;后续会慢慢整理。 也可找寻博主历史文章&#xff0c;搜索关键词使用方案&#xff0c;比如本文涉及函数on_order_response &#xff01; 感谢关注&#xff0c;咨询开通量化回测与获取实盘权限&#xff0c;欢迎和博主联系&#xf…

经验分享:C++ error:‘syscall’ was not declared in this scope

明明已经加了头文件 #include <sys/syscall.h>#define gettid() syscall(__NR_gettid)但是依旧不能使用 syscall() 函数&#xff0c; 检查源码后&#xff1a; sys/syscall.h 内部表示&#xff0c;他封装了 打开对应的 syscall.h 文件内部依旧没有 syscall()函数的声明…

Vue02-黑马程序员学习笔记

一、今日学习目标 1.指令补充 指令修饰符v-bind对样式增强的操作v-model应用于其他表单元素 2.computed计算属性 基础语法计算属性vs方法计算属性的完整写法成绩案例 3.watch侦听器 基础写法完整写法 4.综合案例 &#xff08;演示&#xff09; 渲染 / 删除 / 修改数量 …

炫酷gdb

在VS里面调试很方便对吧&#xff1f;&#xff08;F5直接调试&#xff0c;F10逐过程调试--不进函数&#xff0c;F11逐语句调试--进函数&#xff0c;F9创建断点&#xff09;&#xff0c;那在Linux中怎么调试呢&#xff1f; 我们需要用到一个工具&#xff1a;gdb 我们知道VS中程…

qt中使用tableWidget不显示表头和内容的可能原因

需求是想要把sqlite数据库中的内容通过tableWidget显示出来&#xff0c;但是在使用过程中发现了一些问题 使用ui->tableWidget->setHorizontalHeaderLabels设置表头的时候&#xff0c;发现怎么样都不显示表头&#xff0c;参考这篇文章&#xff0c;应该使用ui->tableW…

Sping6 笔记(一)【优秀的轻量级框架】

Spring6 介绍&#xff1a; 发布时间&#xff1a;2022年11月Spring 框架是一款优秀的轻量级开源框架&#xff0c;为了解决企业应用开发的复杂性而出现Spring 框架的用途&#xff1a;服务器端的开发特点&#xff1a;简单性、可测试性、松耦合性 学习 Spring6 的前置知识&#x…

react组件中的共享数据

在前面的示例中&#xff0c;每个 MyButton 都有自己独立的 count&#xff0c;当每个按钮被点击时&#xff0c;只有被点击按钮的 count 才会发生改变&#xff1a; 然而&#xff0c;你经常需要组件 共享数据并一起更新。 为了使得 MyButton 组件显示相同的 count 并一起更新&…

Socket同步通讯

目录 引言 1. 建立连接 2. 数据传输 3. 同步机制 4. 处理延迟 5. 安全性 6、一对一Socket同步通讯 客户端 代码分析 服务端 代码分析 7、服务端操作 1、首先我们先运行客户端代码 2、服务端点击Connect连接客户端 3、服务端输入信息传输到客户端 4、断开连接 引…

芯片设计公司外协ERP数字化运营:科技与管理的融合

随着信息技术的快速发展&#xff0c;ERP(企业资源计划)系统已经成为现代企业管理不可或缺的一部分。在芯片设计行业&#xff0c;由于产品的复杂性、技术的高要求以及市场的快速变化&#xff0c;外协ERP数字化运营显得尤为重要。 芯片设计公司的外协ERP数字化运营&#xff0c;主…

javaSwing员工工资管理系统(文档+视频+源码)

摘要 由Java swing mysql数据库实现的员工工资管理系统&#xff0c;该项目功能相对完善&#xff0c;有管理员和普通用户两个角色&#xff0c;分别实现了一些列功能&#xff0c;数据库采用的是mysql 系统实现 我们先以员工的身份查询一下&#xff1a; 接下来我们以管理员身份…

Qt | QCalendarWidget 类(日历)

01、QCalendarWidget 类 1、QCalendarWidget 类是 QWidget 的直接子类,该类用于日历,见下图 02、QCalendarWidget 属性 ①、dateEditAcceptDelay:int 访问函数:int dateEditAcceptDelay()const; void setDateEditAcceptDelay(int) 获取和设置日期编辑器的延迟时间(以毫秒…