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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

递增链表去重

题目描述: 题目思路: 1.链表内的val是递增的,所以相同的值只会连续重复地出现。 2.设置三个指针: ①指向头结点指针,用于返回链表 ②指向返回链表链尾的指针,用于在新链表添加结点 ③遍历旧链表结点的…

基于地理坐标的高阶几何编辑工具算法(5)——合并相交面

文章目录 工具步骤应用场景算法输入算法输出算法示意图算法原理 工具步骤 选中一个面,点击“合并相交面”工具,选择其他相邻面,空格执行合并。 应用场景 用于将相邻或相交的同类型几何面进行合并,达到综合效果。 算法输入 待…

单元测试—BMI脚本设计

BMI例题如下: BMI中国计算标准:体质指数(BMI)体重(kg)身高^2(m) 例如:一个人的身高为1.75米,体重为68千克,他的BMI68/(1.75^2)22.2(千克/米^2&a…

【堡垒机小知识】堡垒机和接口机的重要区别分析

在企业IT架构管理中,接口机和堡垒机各自扮演着不可或缺的角色。但不少IT小伙伴对于两者不是很了解,不知道两者之间有什么区别,今天我们就来一起分析一下。 堡垒机和接口机的重要区别分析 1、功能区别 接口机主要用于数据库层面的数据交换和…

构建进攻性的网络安全防护策略

进攻性安全(Offensive security)是指一系列主动安全策略,这些策略与恶意行为者在现实世界的攻击中使用的策略相同,区别在于其目的是加强而非损害网络安全。常见的进攻性安全方法包括红队、渗透测试和漏洞评估。 进攻性安全行动通…

【漏洞复现】用友U8 CRM uploadfile 文件上传致RCE漏洞

0x01 产品简介 用友U8 Cloud是用友推出的新一代云ERP,主要聚焦成长型、创新型企业,提供企业级云ERP整体解决方案。 0x02 漏洞概述 用友 U8 CRM客户关系管理系统 uploadfle.php 文件存在任意文件上传漏洞,未经身份验证的攻击者通过漏洞上传…

Go 切片常用操作与使用技巧

1.什么是切片 在 Go 语言中的切片(slice)是一种灵活的动态数组,它可以自动扩展和收缩,是 Go 语言中非常重要的数据结构之一。切片是基于数组实现的,它的底层是数组,可以理解为对底层数组的抽象。它会生成一…

二十五篇:嵌入式系统揭秘:基础理论与实践探索

嵌入式系统揭秘:基础理论与实践探索 1. 嵌入式系统的定义与特性 1.1 详细解释 嵌入式系统,作为一种特殊的计算机系统,其设计目的是为了执行一个或多个特定的功能。与通用计算机相比,嵌入式系统通常被集成到更大的设备中&#xf…

基于地理坐标的高阶几何编辑工具算法(8)——整形面

文章目录 工具步骤应用场景算法输入算法输出算法示意图算法原理工具步骤 选中面,点击“整形面”工具,绘制一条和面至少两个交点的线,双击结束。 应用场景 快速修改一个几何面的局部形状。 算法输入 一个待修改的面p,和一条绘制的线l 算法输出 修改后的面 算法示意图…

(Qt) 默认QtWidget应用包含什么?

文章目录 ⭐前言⭐创建🛠️选择一个模板🛠️Location🛠️构建系统🛠️Details🛠️Translation🛠️构建套件(Kit)🛠️汇总 ⭐项目⚒️概要⚒️构建步骤⚒️清除步骤 ⭐Code🔦untitled…

Java——抽象类与接口的区别

定义区分: 抽象类:抽象类是用来捕捉子类的通用特性的 。它不能被实例化,只能被用作子类的超类。抽象类是被用来创建继承层级里子类的模板 接口:接口是抽象方法的集合。如果一个类实现了某个接口,那么它就继承了这个接…

第二证券今日投资参考:5月国产游戏版号发放 猪价加速上涨

昨日,两市股指盘中震荡上扬,沪指盘中续创年内新高,创业板指一度涨超1%。到收盘,沪指涨0.54%报3171.15点,深证成指涨0.43%报9750.82点,创业板指涨0.59%报1875.93点,上证50指数涨0.34%&#xff1b…

我的第一个JAVA程序IDEA版

目录 第一步 新建一个空项目第二步 新建模块第三步 新建包第四步 新建类第五步 新建main方法 第一步 新建一个空项目 第二步 新建模块 第三步 新建包 第四步 新建类 然后在包文件夹下新建类 第五步 新建main方法

使用Python生成一束玫瑰花

520到了,没时间买花?我们来生成一个电子的。 Python不仅是一种强大的编程语言,用于开发应用程序和分析数据,它也可以用来创造美丽的艺术作品。在这篇博客中,我们将探索如何使用Python生成一束玫瑰花的图像。 准备工作…

国内快速下载hugging face大模型的方法

由于众所周知的原因,从hugging face下载大模型比较困难,幸好国内有人做了镜像站,可以通过国内的镜像站进行快速下载,以下是配置方法。 我的系统是ubuntu 22,这里记录的方法只对debian/ubuntu有效。 git-lfs/INSTALLI…

民国漫画杂志《时代漫画》第14期.PDF

时代漫画14.PDF: https://url03.ctfile.com/f/1779803-1247458399-6732ac?p9586 (访问密码: 9586) 《时代漫画》的杂志在1934年诞生了,截止1937年6月战争来临被迫停刊共发行了39期。 ps:资源来源网络!

压摆率SR、增益带宽积GBP、开环增益Aol

运放的选型对运放电路的实际效果非常关键,一定要理解运放重要参数的概念。下面几天将对运放的选型进行系统学习并做实验 运放的压摆率(Slew Rate,简称SR)是指闭环放大器在输入为阶跃信号时,输出电压时间变化率的平均值…

Python 全栈体系【四阶】(五十二)

第五章 深度学习 十二、光学字符识别(OCR) 2. 文字检测技术 2.1 CTPN(2016) 2.1.1 概述 CTPN全称Detecting Text in Natural Image with Connectionist Text Proposal Network(基于连接文本提议网络的自然图像文本…

测试驱动编程(2)进阶单元测试(上)

文章目录 测试驱动编程(2)进阶单元测试(上)单元测试单元测试正确打开方式各类测试比较 TDD中的单元测试 测试驱动编程(2)进阶单元测试(上) 单元测试 要打造出出类拔萃的作品,你必须专注于最小的细节 单元测试正确打…

Vue3 实现共享数据三种方式

1. Vuex 1.1 安装vuex npm install vuexlatest 1.2 创建store文件夹,创建index.js文件 在vuex4.x中 创建vuex实例需要使用createStore方法 // store/index.js import { createStore } from vuex import useLoginStore from ./modules/loginexport default cre…