使用LangChain LCEL生成RAG应用、使用LangChain TruLens对抗RAG幻觉

# 导入LangChain的库
from langchain import *

# 加载数据源
loader = WebBaseLoader()
doc = loader.load("https://xxx.html")

# 分割文档对象
splitter = RecursiveCharacterTextSplitter(max_length=512)
docs = splitter.split(doc)

# 转换文档对象为嵌入,并存储到向量存储器中
embedder = OpenAIEmbeddings()
vector_store = ChromaVectorStore()
for doc in docs:
    embedding = embedder.embed(doc.page_content)
    vector_store.add(embedding, doc)

# 创建检索器
retriever = VectorStoreRetriever(vector_store, embedder)

# 创建聊天模型
prompt = hub.pull("rlm/rag-prompt")
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)

# 创建一个问答应用
def format_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)


rag_chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

# 启动应用
rag_chain.invoke("What is main purpose of xxx.html?")

LangChain提供了一种专门的表达式语言,叫做LCEL(LangChain Expression Language),它可以让你用简洁和灵活的语法来定义和操作Chain。

LCEL语法基础

LCEL是一个用于构建复杂链式组件的语言,它支持流式处理、并行化、日志记录等功能。LCEL的基本语法规则是使用|符号将不同的组件连接起来,形成一个链式结构。|符号类似于Unix的管道操作符,它将一个组件的输出作为下一个组件的输入,从而实现数据的传递和处理。

为什么要用LCEL?

LCEL语法的核心思想是:一切皆为对象,一切皆为链。这意味着,LCEL语法中的每一个对象都实现了一个统一的接口:Runnable,它定义了一系列的调用方法(invoke, batch, stream, ainvoke, …)。这样,你可以用同样的方式调用不同类型的对象,无论它们是模型、函数、数据、配置、条件、逻辑等等。而且,你可以将多个对象链接起来,形成一个链式结构,这个结构本身也是一个对象,也可以被调用。这样,你可以将复杂的功能分解成简单的组件,然后用LCEL语法将它们组合起来,形成一个完整的应用。

LCEL语法还提供了一些组合原语,让你可以更灵活地控制链式结构的行为,例如:

  • 并行化:你可以使用parallel原语将多个对象并行执行,提高效率和性能。
  • 回退:你可以使用fallback原语为某个对象指定一个备选对象,当主对象执行失败时,自动切换到备选对象,保证应用的可用性和稳定性。
  • 动态配置:你可以使用config原语为某个对象指定一个配置对象,根据运行时的输入或条件,动态地修改对象的参数或属性,增加应用的灵活性和适应性。

TruLens

TruLens是面向神经网络应用的质量评估工具,它可以帮助你使用反馈函数来客观地评估你的基于LLM(语言模型)的应用的质量和效果。反馈函数可以帮助你以编程的方式评估输入、输出和中间结果的质量,从而加快和扩大实验评估的范围。你可以将它用于各种各样的用例,包括问答、检索增强生成和基于代理的应用。

TruLens的核心思想是,你可以为你的应用定义一些反馈函数,这些函数可以根据你的应用的目标和期望,对你的应用的表现进行打分或分类。例如:

  • 定义一个反馈函数来评估你的问答应用的输出是否与问题相关,是否有依据,是否有用。
  • 定义一个反馈函数来评估你的检索增强生成应用的输出是否符合语法规则,是否有创造性,是否有逻辑性。
  • 定义一个反馈函数来评估你的基于代理的应用的输出是否符合道德标准,是否有友好性,是否有诚实性。

TruLens可以让你在开发和测试你的应用的过程中,实时地收集和分析你的应用的反馈数据,从而帮助你发现和解决你的应用的问题,提高你的应用的质量和效果。你可以使用TruLens提供的易用的用户界面,来查看和比较你的应用的不同版本的反馈数据,从而找出你的应用的优势和劣势,以及改进的方向。

# 导入LangChain和TruLens
from langchain.chains import LLMChain
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate
from langchain.prompts.chat import ChatPromptTemplate,HumanMessagePromptTemplate
from trulens_eval import TruChain,Feedback, Huggingface, Tru, OpenAI as TruOpenAI
from trulens_eval.feedback.provider.langchain import Langchain

tru = Tru()

# 定义一个问答应用的提示模板
full_prompt = HumanMessagePromptTemplate(
    prompt=PromptTemplate(
        template=
        "Provide a helpful response with relevant background information for the following: {prompt}",
        input_variables=["prompt"],
    )
)

chat_prompt_template = ChatPromptTemplate.from_messages([full_prompt])


# 创建一个LLMChain对象,使用llm和chat_prompt_template作为参数
llm = OpenAI()
chain = LLMChain(llm=llm, prompt=chat_prompt_template, verbose=True)


# Initialize Huggingface-based feedback function collection class:
# Define a language match feedback function using HuggingFace.
hugs = Huggingface()
f_lang_match = Feedback(hugs.language_match).on_input_output()
# Question/answer relevance between overall question and answer.
provider = TruOpenAI()
f_qa_relevance = Feedback(provider.relevance).on_input_output()

# 使用TruChain类来包装chain对象,指定反馈函数和应用ID
tru_recorder = TruChain(
    chain,
    app_id='Chain1_QAApplication',
    feedbacks=[f_lang_match,f_qa_relevance])


# 使用with语句来运行chain对象,并记录反馈数据
with tru_recorder as recording:
    # 输入一个问题,得到一个回答
    chain("What is langchain?")
    # 查看反馈数据
    tru_record = recording.records[0]
    # 打印反馈数据
    print("tru_record:",tru_record)
# 启动tru展示控制台
tru.run_dashboard()

为了评估RAG的质量和效果,可以使用TruLens提供的RAG三角形(RAG Triad)的评估方法。RAG三角形是由三个评估指标组成的,分别是:

  • 上下文相关性(Context Relevance):评估输入和检索出的文档之间的相关性,以及文档之间的一致性。上下文相关性越高,说明检索系统越能找到与输入匹配的知识和信息,从而为LLM提供更好的上下文。
  • 有根据性(Groundedness):评估输出和检索出的文档之间的一致性,以及输出的可信度。有根据性越高,说明LLM越能利用检索出的文档来生成有依据的输出,从而避免产生幻觉或错误。
  • 答案相关性(Answer Relevance):评估输出和输入之间的相关性,以及输出的有用性。答案相关性越高,说明LLM越能理解输入的意图和需求,从而生成有用的输出,满足用户的目的。

RAG三角形的评估方法可以让我们从不同的角度来检验RAG的质量和效果,从而发现和改进RAG的问题。我们可以使用TruLens来实现RAG三角形的评估方法,具体步骤如下:

  1. 在LangChain中,创建一个RAG对象,使用RAGPromptTemplate作为提示模板,指定检索系统和知识库的参数。
  2. 在TruLens中,创建一个TruChain对象,包装RAG对象,指定反馈函数和应用ID。反馈函数可以使用TruLens提供的f_context_relevance, f_groundness, f_answer_relevance,也可以自定义。
  3. 使用with语句来运行RAG对象,并记录反馈数据。输入一个问题,得到一个回答,以及检索出的文档。
  4. 查看和分析反馈数据,根据RAG三角形的评估指标,评价RAG的表现。

下面是一个简单的示例,展示了如何在LangChain中使用TruLens来评估一个RAG问答应用:

# 导入LangChain和TruLens
from IPython.display import JSON

# Imports main tools:
from trulens_eval import TruChain, Feedback, Huggingface, Tru
from trulens_eval.schema import FeedbackResult
tru = Tru()
tru.reset_database()

# Imports from langchain to build app
import bs4
from langchain import hub
from langchain.chat_models import ChatOpenAI
from langchain.document_loaders import WebBaseLoader
from langchain.embeddings import OpenAIEmbeddings
from langchain.schema import StrOutputParser
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain_core.runnables import RunnablePassthrough
from trulens_eval.feedback.provider import OpenAI
import numpy as np
from trulens_eval.app import App
from trulens_eval.feedback import Groundedness


# 加载文件
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()
# 分词
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
# 存入到向量数据库
vectorstore = Chroma.from_documents(documents=splits, embedding=OpenAIEmbeddings(
))
# 定义一个RAG Chain

retriever = vectorstore.as_retriever()

prompt = hub.pull("rlm/rag-prompt")
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)

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

rag_chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)
# 使用TruChain类来包装rag对象,指定反馈函数和应用ID
# Initialize provider class
provider = OpenAI()
# select context to be used in feedback. the location of context is app specific.
context = App.select_context(rag_chain)
grounded = Groundedness(groundedness_provider=provider)
# f_context_relevance, f_groundness, f_answer_relevance 定义反馈函数
# Define a groundedness feedback function
f_groundedness = (
    Feedback(grounded.groundedness_measure_with_cot_reasons)
    .on(context.collect()) # collect context chunks into a list
    .on_output()
    .aggregate(grounded.grounded_statements_aggregator)
)

# Question/answer relevance between overall question and answer.
f_qa_relevance = Feedback(provider.relevance).on_input_output()
# Question/statement relevance between question and each context chunk.
f_context_relevance = (
    Feedback(provider.qs_relevance)
    .on_input()
    .on(context)
    .aggregate(np.mean)
    )
# 使用with语句来运行rag对象,并记录反馈数据
tru_recorder = TruChain(rag_chain,
    app_id='Chain1_ChatApplication',
    feedbacks=[f_qa_relevance, f_context_relevance, f_groundedness])

with tru_recorder as recording:
    # 输入一个问题,得到一个回答,以及检索出的文档
    llm_response = rag_chain.invoke("What is Task Decomposition?")
    # 查看反馈数据
    rec = recording.get() # use .get if only one record
    # 打印反馈数据
    print(rec)
# 启动tru展示控制台
tru.run_dashboard()

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

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

相关文章

2024年目前阿里云服务器一个月收费价格表多少钱?

阿里云服务器一个月多少钱?最便宜5元1个月。阿里云轻量应用服务器2核2G3M配置61元一年,折合5元一个月,2核4G服务器30元3个月,2核2G3M带宽服务器99元12个月,轻量应用服务器2核4G4M带宽165元12个月,4核16G服务…

创建AI智能体

前言 灵境矩阵是百度推出的基于文心大模型的智能体(Agent)平台,支持广大开发者根据自身行业领域、应用场景,选取不同类型的开发方式,打造大模型时代的产品能力。开发者可以通过 prompt 编排的方式低成本开发智能体&am…

Spring 自定义 CustomQualifier

为什么写这篇文章 Spring 支持类型注入,并且可以通过Qualifier 或者Mate 调整类型注入的范围。但是通过自定义注解结合现有的 Qualifier 使用起来有种种困难。 将 Qualifier 融合在自定义注解中,在使用 AliasFor 遇到问题仅仅检查注解中的一部分内容是否…

Linux系统使用Docker部署Jupyter Notebook结合内网穿透实现公网访问本地笔记

文章目录 1. 选择与拉取镜像2. 创建容器3. 访问Jupyter工作台4. 远程访问Jupyter工作台4.1 内网穿透工具安装4.2 创建远程连接公网地址4.3 使用固定二级子域名地址远程访问 本文主要介绍如何在Ubuntu系统中使用Docker本地部署Jupyter Notebook,并结合cpolar内网穿透…

YOLOv9改进策略:IoU优化 | Wasserstein Distance Loss,助力小目标涨点

💡💡💡本文独家改进:基于Wasserstein距离的小目标检测评估方法 Wasserstein Distance Loss | 亲测在多个数据集能够实现涨点,对小目标、遮挡物性能提升明显 💡💡💡MS COCO和PASC…

【Linux】模拟实现shell(bash)

目录 常见的与shell互动场景 实现代码 全部代码 homepath()接口 const char *getUsername()接口 const char *getHostname()接口 const char *getCwd()接口 int getUserCommand(char *command, int num)接口 void commandSplit(char *in, char *out[])接口 int execut…

TCP重传机制详解——02SACK

文章目录 TCP重传机制详解——02 SACKSACK是什么?为什么要有SACK?实际场景抓包具体显示信息流程 实战抓包讲解SACK关闭场景下,三次重复ACK后会快速重传SACK打开但是不携带SACK块信息场景下,三次重复ACK也不会快速重传SACK打开并且…

P8649 [蓝桥杯 2017 省 B] k 倍区间:做题笔记

目录 思路 代码思路 代码 推荐 P8649 [蓝桥杯 2017 省 B] k 倍区间 思路 额嗯,这道题我刚上来是想到了前缀和,但是还要判断每个子序列,我就两层for嵌套,暴力解了题。就是我知道暴力肯定过不了但是写不出来其他的[留下了苦…

Transformer的前世今生 day09(Transformer的框架概述)

前情提要 编码器-解码器结构 如果将一个模型分为两块:编码器和解码器那么编码器-解码器结构为:编码器负责处理输入,解码器负责生成输出流程:我们先将输入送入编码器层,得到一个中间状态state,并送入解码器…

搜索与图论——Dijkstra

最短路算法 稠密图与稀疏图 n为点数,m为边数。m远小于n的平方为稀疏图,m接近n的平方为稠密图。 稀疏图用邻接表存,稠密图用邻接矩阵存 朴素版dijkstra时间复杂度为O(n^2),对于稠密图可以ac,但遇到稀疏图时会TLE。 dijkstra函数实…

核工业核级树脂的应用

#核工业核级树脂的应用 ​压水堆核电厂核能级树脂主要用于反应堆冷却剂净化系统、乏燃料池冷却水净化系统、蒸汽发生器排污水处理、硼回收系统、放射性废水排放系统等。 核级树脂是压水堆核电厂一回路及其辅助系统的主要水处理材料,用于净化运行过程中产生的裂变产物…

【LaTeX】7实现章节跳转

使用 LaTeX 实现章节跳转 写在最前面1. 引入 hyperref 包2. 标记章节3. 引用章节示例代码注意 小技巧总结 🌈你好呀!我是 是Yu欸 🌌 2024每日百字篆刻时光,感谢你的陪伴与支持 ~ 🚀 欢迎一起踏上探险之旅,…

C语言牛客网BC-37 牛牛的圆(求面积)

题目如下 代码实现 #include<stdio.h> int main() { float r 0;float s 0;scanf("%f",&r);s 3.14*r*r;printf("%.2f",s);return 0; } 创作不易&#xff0c;点点关注&#xff0c;感谢支持&#xff01;&#xff01;&#xff01;

leetcode代码记录(平衡二叉树

目录 1. 题目&#xff1a;2. 我的代码&#xff1a;小结&#xff1a; 1. 题目&#xff1a; 给定一个二叉树&#xff0c;判断它是否是 平衡二叉树 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;true 示例 2&#xff1a; 输入&#xff1a;…

Codeforces Round 842 (Div. 2) D. Lucky Permutation

题目 思路&#xff1a; #include <bits/stdc.h> using namespace std; #define int long long #define pb push_back #define fi first #define se second #define lson p << 1 #define rson p << 1 | 1 const int maxn 1e6 5, inf 1e18, maxm 4e4 5; c…

相位解包裹前识别有效区域和无效区域(条纹和背景区域区分)

对于不连续场进行相位解包的时候,首先要识别出图象中的哪些部分为有效数据,哪些部分为非有效数据"。这不仅关乎着相位解包算法的速度,更影响着解包算法的精度。因此在解包之前,对有效区域和无效区域的判断必须是首先要做的一件事情。下面就来介绍一下什么是有效区域和…

AI智能分析网关智慧食安监管系统方案

3.15晚会刚过不久&#xff0c;淀粉肠的“屈辱”终于得以洗清&#xff0c;但某些品牌奶茶、梅菜扣肉、预制菜等等&#xff0c;生产过程仍是触目惊心。如何提升食品安全管理水平&#xff0c;保障食品从生产到消费环节的质量和安全&#xff1f;TSINGSEE青犀智利用智能分析网关V4Ea…

主流公链 - Solana

探索Solana区块链&#xff1a;下一代高性能区块链平台 1. Solana简介 Solana是一个高性能的区块链平台&#xff08;TPS能达到10W级别&#xff09;&#xff0c;旨在实现高吞吐量和低延迟的区块链交易处理。它采用了一系列创新技术&#xff0c;其中包括Proof of History (PoH)&a…

【进程控制】超详细讲解wait和waitpid的原理(结合代码)

文章目录 前言waipid函数参数option什么叫非阻塞等待&#xff1f;参数status wait 函数 前言 在了解了进程状态这一概念之后&#xff0c;我们明白了什么叫做僵尸进程&#xff1a;子进程退出&#xff0c;父进程“不管不顾”。而一旦存在僵尸进程&#xff0c;势必也会存在内存泄…

介绍部署esxi8.0产品的方式

什么是esxi esxi的中文叫裸机虚拟机管理器 ESXi是由VMware公司开发的一种裸机虚拟机管理器&#xff0c;全称为VMware ESXi。 ESXi是一种虚拟化技术&#xff0c;专门设计用于在物理服务器上运行虚拟机&#xff0c;它的主要特点是能够最大限度地降低硬件配置要求并简化部署过程…