AI菜鸟向前飞 — LangChain系列之十 - RAG(上篇)

166 阅读3分钟

最近比较火的AI技术,一个是RAG、另一个是Agent,今天开始先介绍RAG

    首先,先介绍一个与RAG密切相关的一个概念:向量相似度,也是上一篇结尾时给大家提到

图片

AI菜鸟向前飞 — LangChain系列之九 - RouterChain的四种实现方式

向量相似度(向量距离)

程序

from langchain.evaluation import load_evaluator, EvaluatorType
from langchain_community.chat_models.ollama import ChatOllama
from langchain.embeddings.ollama import OllamaEmbeddings

model = "llama3"

evaluator = load_evaluator(llm=ChatOllama(model=model), embeddings=OllamaEmbeddings(model=model), evaluator=EvaluatorType.PAIRWISE_EMBEDDING_DISTANCE)

distance = evaluator.evaluate_string_pairs(prediction="电脑", prediction_b="苹果")

print("向量距离", distance)

输出结果

向量距离 {'score': 0.2855118731748122}

程序片段

distance = evaluator.evaluate_string_pairs(prediction="什么是硬件开发?", prediction_b="硬件电源开发分为哪几步?")

输出结果

  • 1
向量距离 {'score': 0.09122176283788064}

                这个值越小,说明两个词越相似,它们就越“匹配”

下面回到今天的正题:

RAG简介

    Retrieval Augmented Generation——即:检索 增强 生成 三个单词的缩写

用通俗的句子来表述:

  • 大语言模型自身的知识没办法满足需求,借助第三方文档的知识合并来回答用户所提出的问题
  • 根据文档的内容进行大语言模型大脑的加工,把结果呈现给提问者

    拿官网的图例给大家进一步解释

检索之前的准备阶段

图片

根据问题(Question)给出回答(Answer)

图片

图片

    用一个程序,进一步阐述:

    这里面我们用到了向量数据库(即:VectorDatabase),之前给大家介绍了好几种,这里先用Chroma

名称官网地址是否开源
PineConewww.pinecone.io
Milvusmilvus.io
Qdrantqdrant.tech
PGVectorgithub.com/pgvector/pg…
RediSearchredis.io
Weaviateweaviate.io
FAISSfaiss.ai
Chromatrychroma.com

AI菜鸟向前飞 — 一些AI术语和TA的朋友们

程序

from langchain.document_loaders.text import TextLoader
from langchain.embeddings.ollama import OllamaEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores.chroma import Chroma
from langchain.prompts import PromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
from langchain_community.chat_models.tongyi import ChatTongyi

import os
text_path = os.path.join(os.path.dirname(__file__), "test.txt")

# 加载文档
loader = TextLoader(text_path)
docs = loader.load()

# 把文档进行分块
chunks = CharacterTextSplitter(separator="\n", chunk_size=15, chunk_overlap=10, add_start_index=True).split_documents(documents=docs)

# 向量化
embedding = OllamaEmbeddings(model="llama3")
vector_store = Chroma.from_documents(documents=chunks, embedding=embedding)

# 获取Retriever
rag_retriever = vector_store.as_retriever()

prompt_template = PromptTemplate.from_template("""
        你是一名对答如流的专家,请根据如下的内容回答问题
        {context}
        请如实地回答用户所提出的问题:{question},如果遇到你不知道的(包含在上述内容中也没有提到的),请回复“我不知道”。
        """)

# 使用Expression Language语法组合成Chain
rag_chain = {"context": rag_retriever, "question": RunnablePassthrough()} | prompt_template | ChatTongyi(model_name="qwen-turbo") | StrOutputParser()

# 提问&回答
response = rag_chain.invoke("对内容做总结,不要超过80个字")

print(response)

输出结果

  • 1
这段文本包含了问候语和一些关于生活地点、未来计划以及年龄的问题。
八种高级检索器

LangChain封装了一个系列检索器

Retriever检索器中文含义
MultiQueryRetriever多查询检索器
ContextualCompressionRetriever上下文压缩检索器
EnsembleRetriever组合检索器
LongContextReorder长上下文重排检索器
MultiVectorRetriever多向量检索器
ParentDocumentRetriever父文档检索器
SelfQueryRetriever自查询检索器
TimeWeightedVectorStoreRetriever时间权重向量存储检索器

先给大家介绍MultiQueryRetriever,我们一起看下使用效果吧

程序

logging.basicConfig()
logging.getLogger("langchain.retrievers.multi_query").setLevel(logging.INFO)

llm = ChatTongyi(model_name="qwen-turbo")

rag_chain = (
                {
                "context": MultiQueryRetriever.from_llm(retriever=rag_retriever, llm=llm),
                "question": RunnablePassthrough()
                }
                | prompt_template
                | llm
                | StrOutputParser()
            )

response = rag_chain.invoke("对内容做一个总结,不要超过80个字")
print(response)

输出结果

INFO:langchain.retrievers.multi_query:Generated queries: ['1. 请为我提炼一份内容概要,限制在80字以内。', '2. 我需要一个简洁的概述,不超过80字,请帮我完成。', '3. 请为这段文本生成一个80字以内的精炼概括。']
内容总结:对话涉及当前生活地点、未来计划和个人年龄,以朋友互相问候开始。

由一个提问生成了三个相似的不同提问,然后一起提问给大语言模型

为啥是三个,我们翻一下源码看看吧

图片