【使用 langchain 创建RAG知识库完整教程】

RAG

Let’s look at adding in a retrieval step to a prompt and LLM, which adds up to a “retrieval-augmented generation” chain

安装对应的库

!pip install langchain openai faiss-cpu tiktoken

 导入工具包

from operator import itemgetterfrom langchain.chat_models import ChatOpenAI
from langchain.embeddings import OpenAIEmbeddings
from langchain.prompts import ChatPromptTemplate
from langchain.vectorstores import FAISS
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableLambda, RunnablePassthrough

初始化一些东西(向量库,模板,模型LLM)

vectorstore = FAISS.from_texts(["harrison worked at kensho"], embedding=OpenAIEmbeddings()
)
retriever = vectorstore.as_retriever()template = """Answer the question based only on the following context:
{context}Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)model = ChatOpenAI()

构建chain, 使用LCEL技术

chain = ({"context": retriever, "question": RunnablePassthrough()}| prompt| model| StrOutputParser()
)

开始使用

chain.invoke("where did harrison work?")# outout
'Harrison worked at Kensho.'
'Harrison worked at Kensho.'
template = """Answer the question based only on the following context:
{context}Question: {question}Answer in the following language: {language}
"""
prompt = ChatPromptTemplate.from_template(template)chain = ({"context": itemgetter("question") | retriever,"question": itemgetter("question"),"language": itemgetter("language"),}| prompt| model| StrOutputParser()
)
chain.invoke({"question": "where did harrison work", "language": "italian"})
'Harrison ha lavorato a Kensho.'

Conversational Retrieval Chain​

We can easily add in conversation history. This primarily means adding in chat_message_history

添加记录对话历史的能力

from langchain.schema import format_document
from langchain_core.messages import AIMessage, HumanMessage, get_buffer_string
from langchain_core.runnables import RunnableParallel
from langchain.prompts.prompt import PromptTemplate_template = """Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question, in its original language.Chat History:
{chat_history}
Follow Up Input: {question}
Standalone question:"""
CONDENSE_QUESTION_PROMPT = PromptTemplate.from_template(_template)
template = """Answer the question based only on the following context:
{context}Question: {question}
"""
ANSWER_PROMPT = ChatPromptTemplate.from_template(template)
DEFAULT_DOCUMENT_PROMPT = PromptTemplate.from_template(template="{page_content}")def _combine_documents(docs, document_prompt=DEFAULT_DOCUMENT_PROMPT, document_separator="\n\n"
):doc_strings = [format_document(doc, document_prompt) for doc in docs]return document_separator.join(doc_strings)
_inputs = RunnableParallel(standalone_question=RunnablePassthrough.assign(chat_history=lambda x: get_buffer_string(x["chat_history"]))| CONDENSE_QUESTION_PROMPT| ChatOpenAI(temperature=0)| StrOutputParser(),
)
_context = {"context": itemgetter("standalone_question") | retriever | _combine_documents,"question": lambda x: x["standalone_question"],
}
conversational_qa_chain = _inputs | _context | ANSWER_PROMPT | ChatOpenAI()
conversational_qa_chain.invoke({"question": "where did harrison work?","chat_history": [],}
)
AIMessage(content='Harrison was employed at Kensho.')
conversational_qa_chain.invoke({"question": "where did he work?","chat_history": [HumanMessage(content="Who wrote this notebook?"),AIMessage(content="Harrison"),],}
)
AIMessage(content='Harrison worked at Kensho.')

With Memory and returning source documents​

This shows how to use memory with the above. For memory, we need to manage that outside at the memory. For returning the retrieved documents, we just need to pass them through all the way.

添加返回检索到的文档的能力

from operator import itemgetterfrom langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory(return_messages=True, output_key="answer", input_key="question"
)
# First we add a step to load memory
# This adds a "memory" key to the input object
loaded_memory = RunnablePassthrough.assign(chat_history=RunnableLambda(memory.load_memory_variables) | itemgetter("history"),
)
# Now we calculate the standalone question
standalone_question = {"standalone_question": {"question": lambda x: x["question"],"chat_history": lambda x: get_buffer_string(x["chat_history"]),}| CONDENSE_QUESTION_PROMPT| ChatOpenAI(temperature=0)| StrOutputParser(),
}
# Now we retrieve the documents
retrieved_documents = {"docs": itemgetter("standalone_question") | retriever,"question": lambda x: x["standalone_question"],
}
# Now we construct the inputs for the final prompt
final_inputs = {"context": lambda x: _combine_documents(x["docs"]),"question": itemgetter("question"),
}
# And finally, we do the part that returns the answers
answer = {"answer": final_inputs | ANSWER_PROMPT | ChatOpenAI(),"docs": itemgetter("docs"),
}
# And now we put it all together!
final_chain = loaded_memory | standalone_question | retrieved_documents | answer
inputs = {"question": "where did harrison work?"}
result = final_chain.invoke(inputs)
result
{'answer': AIMessage(content='Harrison was employed at Kensho.'),'docs': [Document(page_content='harrison worked at kensho')]}

 

# Note that the memory does not save automatically
# This will be improved in the future
# For now you need to save it yourself
memory.save_context(inputs, {"answer": result["answer"].content})
memory.load_memory_variables({})
{'history': [HumanMessage(content='where did harrison work?'),AIMessage(content='Harrison was employed at Kensho.')]}

 

inputs = {"question": "but where did he really work?"}
result = final_chain.invoke(inputs)
result
{'answer': AIMessage(content='Harrison actually worked at Kensho.'),'docs': [Document(page_content='harrison worked at kensho')]}

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

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

相关文章

从零开始:神经网络(1)——神经元和梯度下降

声明:本文章是根据网上资料,加上自己整理和理解而成,仅为记录自己学习的点点滴滴。可能有错误,欢迎大家指正。 一. 神经网络 1. 神经网络的发展 先了解一下神经网络发展的历程。从单层神经网络(感知器)开…

HCIP --- BGP 综合实验

实验拓扑图: 实验要求: 1.AS1存在两个环回,一个地址为192.168.1.0/24该地址不能 在任何协议中宣告 AS3中存在两个环回,一个地址为192.168.2.0/24该地址不能在任何协议中宣告,最终要求这两个环回可以互相通讯. 2.整个…

C语言--函数指针变量和函数指针数组的区别(详解)

函数指针变量 函数指针变量的作用 函数指针变量是指向函数的指针,它可以用来存储函数的地址,并且可以通过该指针调用相应的函数。函数指针变量的作用主要有以下几个方面: 回调函数:函数指针变量可以作为参数传递给其他函数&…

字典Trie树

字典树 : 概念 建字典树 查询 : 代码模板 : const int N100010; int n; char s[N]; int ch[N][26],cnt[N],idx;void insert(char *s){int p0;for(int i0; s[i]; i ){int js[i]-a;//字母映射if(!ch[p][j])ch[p][j]idx;pch[p][j];}cnt[p];//插入次数 } int query(char *s){i…

零知识玩转AVH(1)—— 初次接触

零、引言 近期,CSDN上的一位工作人员让我参加一个嵌入式的活动。她的原话是这样:“咱们这个主要是百度智能云虚拟硬件的活动,就是根据ARM的avh硬件(虚拟硬件)铲平,去开发一个demo,以及根据demo…

全栈的自我修养 ———— css中常用的布局方法flex和grid

在项目里面有两种常用的主要布局:flex和grid布局(b站布局),今天分享给大家这两种的常用的简单方法! 一、flex布局1、原图2、中心对齐3、主轴末尾或者开始对其4、互相间隔 二、grid布局1、基本效果2、加间隔3、放大某一个元素 一、…

AcWing算法基础课——简单算法模板

说明 本篇文章只给出代码模板,以及自己对该模板的理解。如果想看正确的算法思路,可以移步AcWing官网看详情。链接:常用代码模板1——基础算法 - AcWing 如有理解错误,欢迎大家批评指正。 简单算法模板 一、排序 1.1 快…

1950-2022年各区县逐年平均降水量数据

1950-2022年各区县逐年平均降水量数据 1、时间:1950-2022年 2、指标:省逐年平均降水量 3、范围:33省(不含澳门)、360地级市、2800个县 4、指标解释:逐年平均降水数据是指当年的日降水量的年平均值&…

力扣面试经典150 —— 11-15题

力扣面试经典150题在 VScode 中安装 LeetCode 插件即可使用 VScode 刷题,安装 Debug LeetCode 插件可以免费 debug本文使用 python 语言解题,文中 “数组” 通常指 python 列表;文中 “指针” 通常指 python 列表索引 文章目录 11. [中等] H指…

【Web - 框架 - Vue】随笔 - Vue CLI - 快速上手

Vue CLI 创建Vue CLI项目 【步骤】 命名项目空间:在电脑里创建文件夹,用于存储所有项目;定位项目空间:在"CMD窗口"里定位到工程的项目空间上; 方法1:(a)用"WINR"打开运行窗口&#x…

Fastjson 1.2.24 反序列化导致任意命令执行漏洞复现(CVE-2017-18349)

写在前面 CVE-2017-18349 指的是 fastjson 1.2.24 及之前版本存在的反序列化漏洞&#xff0c;fastjson 于 1.2.24 版本后增加了反序列化白名单&#xff1b; 而在 2019 年&#xff0c;fastjson 又被爆出在 fastjson< 1.2.47 的版本中&#xff0c;攻击者可以利用特殊构造的 …

retrofit2中,响应参数的int类型会被转为double小数点的解决办法。

背景 retrofit2版本&#xff1a;2.3.0 我使用retrofit2作为接口请求框架。 但是我发现在响应时&#xff0c;解析的响应内容总会有问题。 例如&#xff1a; {"msg":"","code":0.0,"data":"123"}其中的"code"应该…

简述epoll实现

所有学习笔记&#xff1a;https://github.com/Dusongg/StudyNotes 文章目录 epoll数据结构的选择&#xff1f;以tcp为例&#xff0c;网络io的可读可写如何判断&#xff1f;epoll如何做到线程安全&#xff1f;LT和ET如何实现&#xff1f;tcp状态和io的读写有哪些关系&#xff1…

新概念英语第二册(73)

【New words and expressions】生词和短语&#xff08;9&#xff09; record-holder 纪录保持者 truant n. 逃学的孩子unimaginative adj. 缺乏想像力的shame n. 惭愧&#xff0c;羞耻 hitchhike v. 搭便车旅行 m…

Linux fbset命令教程:如何使用fbset命令修改帧缓冲设备设置(附实例详解和注意事项)

Linux fbset命令介绍 fbset是一个系统实用程序&#xff0c;用于显示或更改帧缓冲设备的设置。帧缓冲设备提供了一个简单且独特的接口&#xff0c;用于访问不同类型的图形显示。帧缓冲设备通过位于/dev目录中的特殊设备节点进行访问。 Linux fbset命令适用的Linux版本 fbset命…

【C语言】linux内核tcp_write_xmit和tcp_write_queue_purge

tcp_write_xmit 一、讲解 这个函数 tcp_write_xmit 是Linux内核TCP协议栈中的一部分&#xff0c;其基本作用是发送数据包到网络。这个函数会根据不同情况推进发送队列的头部&#xff0c;确保只要远程窗口有空间&#xff0c;就可以发送数据。 下面是对该函数的一些主要逻辑的中…

Spring Boot单元测试与热部署简析

1 Spring Boot的简介 Spring Boot是一个用于构建独立的、生产级别的Spring应用程序的框架。它简化了Spring应用程序的开发过程&#xff0c;提供了自动配置和默认配置&#xff0c;使得开发者只需专注于业务逻辑的实现&#xff0c;而不用去关注繁琐的配置问题。 Spring …

ElasticSearch 底层读写原理

ElasticSearch 底层读写原理 ​ 写请求是写入 primary shard&#xff0c;然后同步给所有的 replica shard&#xff1b;读请求可以从 primary shard 或 replica shard 读取&#xff0c;采用的是随机轮询算法。 1、ES写入数据的过程 1.选择任意一个DataNode发送请求&#xff0c…

Java17 --- springCloud之LoadBalancer

目录 一、LoadBalancer实现负载均衡 1.1、创建两个相同的微服务 1.2、在客户端80引入loadBalancer的pom 1.3、80服务controller层&#xff1a; 一、LoadBalancer实现负载均衡 1.1、创建两个相同的微服务 1.2、在客户端80引入loadBalancer的pom <!--loadbalancer-->&…

WPF 窗口添加投影效果Effect

BlurRadius&#xff1a;阴影半径 Color&#xff1a;颜色 Direction&#xff1a;投影方向 ShadowDepth&#xff1a;投影的深度 <Window.Effect><DropShadowEffect BlurRadius"10" Color"#FF858484" Direction"300" ShadowDepth&quo…