langchain教程-9.Retriever/检索器
前言
该系列教程的代码: https://github.com/shar-pen/Langchain-MiniTutorial
我主要参考 langchain 官方教程, 有选择性的记录了一下学习内容
这是教程清单
- 1.初试langchain
- 2.prompt
- 3.OutputParser/输出解析
- 4.model/vllm模型部署和langchain调用
- 5.DocumentLoader/多种文档加载器
- 6.TextSplitter/文档切分
- 7.Embedding/文本向量化
- 8.VectorStore/向量数据库存储和检索
- 9.Retriever/检索器
- 10.Reranker/文档重排序
- 11.RAG管道/多轮对话RAG
- 12.Agent/工具定义/Agent调用工具/Agentic RAG
VectorStore-backed Retriever
基于VectorStore的检索器 是一种文档检索系统,它利用向量存储根据文档的向量表示来进行搜索。这种方法使得基于相似度的搜索变得高效,特别适用于处理非结构化数据。
RAG系统中的文档搜索和响应生成步骤包括:
- 文档加载:导入原始文档。
- 文本切分:将文本切分成可管理的块。
- 向量嵌入:使用嵌入模型将文本转换为数值向量。
- 存储到向量数据库:将生成的嵌入向量存储到向量数据库中,以便高效检索。
在查询阶段:
- 流程:用户查询 → 嵌入 → 在向量存储中搜索 → 检索相关块 → LLM生成响应
- 用户的查询被转化为一个嵌入向量,使用嵌入模型。
- 该查询嵌入向量与向量数据库中存储的文档向量进行比较,以 检索最相关的结果。
- 检索到的文档块被传递给大语言模型(LLM),该模型基于检索到的信息生成最终响应。
import faiss
from langchain_core.documents import Document
from langchain_community.vectorstores import FAISS
from langchain_community.docstore.in_memory import InMemoryDocstore
from langchain_openai import OpenAIEmbeddingsopenai_embedding = OpenAIEmbeddings(model="bge-m3",base_url='http://localhost:9997/v1',api_key='cannot be empty',# dimensions=1024,
)embed_dim = len(openai_embedding.embed_query("hello world"))
texts = ["AI helps doctors diagnose diseases faster, improving patient outcomes.","AI can analyze medical images to detect conditions like cancer.","Machine learning predicts patient outcomes based on health data.","AI speeds up drug discovery by predicting the effectiveness of compounds.","AI monitors patients remotely, enabling proactive care for chronic diseases.","AI automates administrative tasks, saving time for healthcare workers.","NLP extracts insights from electronic health records for better care.","AI chatbots help with patient assessments and symptom checking.","AI improves drug manufacturing, ensuring better quality and efficiency.","AI optimizes hospital operations and reduces healthcare costs."
]documents = [Document(text, metadata={"source":text})for text in texts
]db = FAISS.from_documents(documents, openai_embedding)
一旦向量数据库创建完成,就可以使用检索方法,如 相似度搜索 和 最大边际相关性(MMR),加载并查询数据库,从中搜索相关的文本。
as_retriever
方法允许你将一个向量数据库转换为一个检索器,从而实现从向量库中高效地搜索和检索文档。
工作原理:
as_retriever()
方法将一个向量库(如 FAISS)转换为一个检索器对象,使其与 LangChain 的检索工作流兼容。- 这个检索器可以直接用于 RAG 流水线,或与大型语言模型(LLM)结合,用于构建智能搜索系统。
retriever = db.as_retriever()
高级检索器配置
as_retriever
方法允许你配置高级检索策略,如 相似度搜索、最大边际相关性(MMR) 和 基于相似度分数阈值的过滤。
参数:
**kwargs
:传递给检索函数的关键字参数:search_type
:指定搜索方法。"similarity"
:基于余弦相似度返回最相关的文档。"mmr"
:利用最大边际相关性算法,平衡 相关性 和 多样性。"similarity_score_threshold"
:返回相似度分数超过指定阈值的文档。
search_kwargs
:其他用于微调结果的搜索选项:k
:返回的文档数量(默认值:4
)。score_threshold
:用于"similarity_score_threshold"
搜索类型的最小相似度分数(例如:0.8
)。fetch_k
:在 MMR 搜索过程中最初检索的文档数量(默认值:20
)。lambda_mult
:控制 MMR 结果中的多样性(0
= 最大多样性,1
= 最大相关性,默认值:0.5
)。filter
:用于选择性文档检索的元数据过滤。
返回值:
VectorStoreRetriever
:初始化后的检索器对象,可以直接用于文档搜索任务。
注意事项:
- 支持多种搜索策略(
similarity
、MMR
、similarity_score_threshold
)。 - MMR 通过减少结果中的冗余,提升结果多样性同时保持相关性。
- 元数据过滤使得根据文档属性选择性地检索文档成为可能。
tags
参数可以用于给检索器加标签,以便更好地组织和识别。
警告:
- 使用 MMR 时的多样性控制:
- 小心调整
fetch_k
(最初检索的文档数量)和lambda_mult
(多样性控制因子)以获得最佳平衡。 lambda_mult
:- 较低值(< 0.5)→ 优先考虑多样性。
- 较高值(> 0.5)→ 优先考虑相关性。
- 为有效的多样性控制,设置
fetch_k
大于k
。
- 小心调整
- 阈值设置:
- 使用较高的
score_threshold
(例如 0.95)可能会导致没有结果。
- 使用较高的
- 元数据过滤:
- 在应用过滤器之前,确保元数据结构已经定义好。
- 平衡配置:
- 为了获得最佳的检索性能,保持
search_type
和search_kwargs
设置之间的适当平衡。
- 为了获得最佳的检索性能,保持
retriever = db.as_retriever(search_type="similarity_score_threshold", search_kwargs={"k": 5, # Return the top 5 most relevant documents"score_threshold": 0.5 # Only return documents with a similarity score of 0.4 or higher}
)query = "How does AI improve healthcare?"
results = retriever.invoke(query)# Display search results
for doc in results:print(doc.page_content)
No relevant docs were retrieved using the relevance score threshold 0.5
检索器的 invoke()
方法
invoke()
方法是与检索器交互的主要入口点。它用于根据给定的查询搜索并检索相关的文档。
工作原理:
- 查询提交:用户提交查询字符串作为输入。
- 嵌入生成:如果需要,查询会被转换成向量表示。
- 搜索过程:检索器使用指定的搜索策略(如相似度、MMR 等)在向量数据库中进行搜索。
- 结果返回:该方法返回一组相关的文档片段。
参数:
-
input
(必需):- 用户提供的查询字符串。
- 查询会被转换成向量,并与存储的文档向量进行相似度比较,以进行基于相似度的检索。
-
config
(可选):- 允许对检索过程进行细粒度控制。
- 可用于指定 标签、元数据插入和搜索策略。
-
**kwargs
(可选):- 允许直接传递
search_kwargs
进行高级配置。 - 示例选项包括:
k
:返回的文档数量。score_threshold
:文档被包括的最低相似度分数。fetch_k
:MMR 搜索中最初检索的文档数量。
- 允许直接传递
返回值:
List[Document]
:- 返回包含检索到的文本和元数据的文档对象列表。
- 每个文档对象包括:
page_content
:文档的主要内容。metadata
:与文档相关联的元数据(例如,来源、标签)。
用例 1
docs = retriever.invoke("What is an embedding?")for doc in docs:print(doc.page_content)print("=========================================================")
Machine learning predicts patient outcomes based on health data.
=========================================================
AI monitors patients remotely, enabling proactive care for chronic diseases.
=========================================================
AI chatbots help with patient assessments and symptom checking.
=========================================================
用例 2
# search options: top 5 results with a similarity score ≥ 0.7
docs = retriever.invoke("What is a vector database?",search_kwargs={"k": 5, "score_threshold": 0.7}
)
for doc in docs:print(doc.page_content)print("=========================================================")
Machine learning predicts patient outcomes based on health data.
=========================================================
AI monitors patients remotely, enabling proactive care for chronic diseases.
=========================================================
AI chatbots help with patient assessments and symptom checking.
=========================================================
最大边际相关性 (MMR)
最大边际相关性 (MMR) 搜索方法是一种文档检索算法,旨在通过平衡相关性和多样性来减少冗余,从而返回结果时提高多样性。
MMR 的工作原理:
与仅根据相似度分数返回最相关文档的基本相似度搜索不同,MMR 考虑了两个关键因素:
- 相关性:衡量文档与用户查询的匹配程度。
- 多样性:确保检索到的文档彼此不同,避免重复的结果。
关键参数:
search_type="mmr"
:启用 MMR 检索策略。k
:应用多样性过滤后返回的文档数量(默认值:4
)。fetch_k
:应用多样性过滤前最初检索的文档数量(默认值:20
)。lambda_mult
:多样性控制因子(0 = 最大多样性
,1 = 最大相关性
,默认值:0.5
)。
相似度分数阈值搜索
相似度分数阈值搜索是一种检索方法,只有当文档的相似度分数超过预定义的阈值时才会返回。该方法有助于筛选出低相关性的结果,确保返回的文档与查询高度相关。
关键特性:
- 相关性过滤:仅返回相似度分数高于指定阈值的文档。
- 可调精度:通过
score_threshold
参数调整阈值。 - 启用搜索类型:通过设置
search_type="similarity_score_threshold"
启用此搜索方法。
这种搜索方法非常适用于需要高度精确结果的任务,例如事实核查或回答技术性查询。
配置 top_k
(调整返回文档的数量)
-
参数
k
指定在向量搜索过程中返回的文档数量。它决定了从向量数据库中检索到的 排名最高(基于相似度分数)的文档数量。 -
通过在
search_kwargs
中设置k
值,可以调整检索到的文档数量。 -
例如,设置
k=1
将仅返回 最相关的 1 篇文档,该文档基于相似度排序。
ContextualCompressionRetriever
ContextualCompressionRetriever
是 LangChain 中的一种强大工具,旨在通过根据上下文压缩检索到的文档来优化检索过程。这个检索器特别适用于需要对大量数据进行动态总结或过滤的场景,确保只有最相关的信息传递到后续处理步骤。
ContextualCompressionRetriever
的主要特点包括:
- 上下文感知压缩:文档会根据特定的上下文或查询进行压缩,确保相关性并减少冗余。
- 灵活的集成:与其他 LangChain 组件无缝工作,便于集成到现有的管道中。
- 可定制的压缩:支持使用不同的压缩技术,包括摘要模型和基于嵌入的方法,来根据需求定制检索过程。
ContextualCompressionRetriever
特别适用于以下应用:
- 为问答系统总结大量数据。
- 通过提供简洁且相关的回答来提升聊天机器人性能。
- 提高文档密集型任务(如法律分析或学术研究)的效率。
通过使用这个检索器,开发者可以显著减少计算开销,并提高提供给最终用户的信息质量。
from langchain_community.document_loaders import TextLoader
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import CharacterTextSplitter# 1. Generate Loader to lthe text file using TextLoader
loader = TextLoader("./data/appendix-keywords.txt")\# 2. Generate text chunks using CharacterTextSplitter and split the text into chunks of 300 characters with no overlap.
text_splitter = CharacterTextSplitter(chunk_size=400, chunk_overlap=0)
texts = loader.load_and_split(text_splitter)# 3. Generate vector store using FAISS and convert it to retriever
embedder = OpenAIEmbeddings(model="bge-m3",base_url='http://localhost:9997/v1',api_key='cannot be empty',# dimensions=1024,
)
retriever = FAISS.from_documents(texts, embedder).as_retriever(search_kwargs={"k": 10})# 4. Query the retriever to find relevant documents
docs = retriever.invoke("What is the definition of Multimodal?")# 5. Print the relevant documents
for i, d in enumerate(docs):print(f"document {i+1}:\n\n" + d.page_content)
Created a chunk of size 419, which is longer than the specified 400document 1:Semantic Search
document 2:Definition: Semantic search is a search method that goes beyond simple keyword matching by understanding the meaning of the user’s query to return relevant results.
Example: If a user searches for “planets in the solar system,” the system might return information about related planets such as “Jupiter” or “Mars.”
Related Keywords: Natural Language Processing, Search Algorithms, Data Mining
document 3:Definition: A token refers to a smaller unit of text obtained by splitting a larger text. It can be a word, sentence, or phrase.
Example: The sentence “I go to school” can be split into tokens: “I”, “go”, “to”, “school”.
Related Keywords: Tokenization, Natural Language Processing, ParsingTokenizer
document 4:Definition: A tokenizer is a tool that splits text data into tokens. It is commonly used in natural language processing for data preprocessing.
Example: The sentence “I love programming.” can be tokenized into [“I”, “love”, “programming”, “.”].
Related Keywords: Tokenization, Natural Language Processing, ParsingVectorStore
document 5:Definition: A vector store is a system for storing data in vector form. It is used for tasks like retrieval, classification, and other data analysis.
Example: Word embedding vectors can be stored in a database for quick access.
Related Keywords: Embedding, Database, VectorizationSQL
document 6:Definition: SQL (Structured Query Language) is a programming language for managing data in databases. It supports operations like querying, modifying, inserting, and deleting data.
Example: SELECT * FROM users WHERE age > 18; retrieves information about users older than 18.
Related Keywords: Database, Query, Data ManagementCSV
document 7:Definition: CSV (Comma-Separated Values) is a file format for storing data where each value is separated by a comma. It is often used for simple data storage and exchange in tabular form.
Example: A CSV file with headers “Name, Age, Job” might contain data like “John Doe, 30, Developer”.
Related Keywords: File Format, Data Handling, Data ExchangeJSON
document 8:Definition: JSON (JavaScript Object Notation) is a lightweight data exchange format that represents data objects in a human- and machine-readable text format.
Example: {"name": "John Doe", "age": 30, "job": "Developer"} is an example of JSON data.
Related Keywords: Data Exchange, Web Development, APITransformer
document 9:Definition: A transformer is a type of deep learning model used in natural language processing for tasks like translation, summarization, and text generation. It is based on the attention mechanism.
Example: Google Translate uses transformer models to perform translations between languages.
Related Keywords: Deep Learning, Natural Language Processing, AttentionHuggingFace
document 10:Definition: HuggingFace is a library that provides pre-trained models and tools for natural language processing, making NLP tasks more accessible to researchers and developers.
Example: HuggingFace’s Transformers library can be used for tasks like sentiment analysis and text generation.
Related Keywords: Natural Language Processing, Deep Learning, LibraryDigital Transformation
使用 LLMChainExtractor
创建的 DocumentCompressor
正是应用于检索器的,即 ContextualCompressionRetriever
。
ContextualCompressionRetriever
会通过去除无关信息并专注于最相关的信息来压缩文档。
LLMChainFilter
LLMChainFilter
是一个简单但强大的压缩器,它使用 LLM 链来决定从最初检索到的文档中哪些应该被过滤,哪些应该被返回。
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor
from langchain_openai import ChatOpenAI# Before applying ContextualCompressionRetriever
docs = retriever.invoke("What is the definition of Multimodal?")
for i, d in enumerate(docs):print(f"document {i+1}:\n\n" + d.page_content)
print("="*62)
print("="*15 + "After applying LLMChainExtractor" + "="*15)# After applying ContextualCompressionRetriever
# 1. Generate LLM
llm = ChatOpenAI(base_url='http://localhost:5551/v1',api_key='EMPTY',model_name='Qwen2.5-7B-Instruct',temperature=0.2,
)# 2. Generate compressor using LLMChainExtractor
compressor = LLMChainExtractor.from_llm(llm)# 3. Generate compression retriever using ContextualCompressionRetriever
compression_retriever = ContextualCompressionRetriever(base_compressor=compressor,base_retriever=retriever,
)# 4. Query the compression retriever to find relevant documents
compressed_docs = (compression_retriever.invoke( "What is the definition of Multimodal?")
)# 5. Print the relevant documents
for i, d in enumerate(compressed_docs):print(f"document {i+1}:\n\n" + d.page_content)
document 1:Semantic Search
document 2:Definition: Semantic search is a search method that goes beyond simple keyword matching by understanding the meaning of the user’s query to return relevant results.
Example: If a user searches for “planets in the solar system,” the system might return information about related planets such as “Jupiter” or “Mars.”
Related Keywords: Natural Language Processing, Search Algorithms, Data Mining
document 3:Definition: A token refers to a smaller unit of text obtained by splitting a larger text. It can be a word, sentence, or phrase.
Example: The sentence “I go to school” can be split into tokens: “I”, “go”, “to”, “school”.
Related Keywords: Tokenization, Natural Language Processing, ParsingTokenizer
document 4:Definition: A tokenizer is a tool that splits text data into tokens. It is commonly used in natural language processing for data preprocessing.
Example: The sentence “I love programming.” can be tokenized into [“I”, “love”, “programming”, “.”].
Related Keywords: Tokenization, Natural Language Processing, ParsingVectorStore
document 5:Definition: A vector store is a system for storing data in vector form. It is used for tasks like retrieval, classification, and other data analysis.
Example: Word embedding vectors can be stored in a database for quick access.
Related Keywords: Embedding, Database, VectorizationSQL
document 6:Definition: SQL (Structured Query Language) is a programming language for managing data in databases. It supports operations like querying, modifying, inserting, and deleting data.
Example: SELECT * FROM users WHERE age > 18; retrieves information about users older than 18.
Related Keywords: Database, Query, Data ManagementCSV
document 7:Definition: CSV (Comma-Separated Values) is a file format for storing data where each value is separated by a comma. It is often used for simple data storage and exchange in tabular form.
Example: A CSV file with headers “Name, Age, Job” might contain data like “John Doe, 30, Developer”.
Related Keywords: File Format, Data Handling, Data ExchangeJSON
document 8:Definition: JSON (JavaScript Object Notation) is a lightweight data exchange format that represents data objects in a human- and machine-readable text format.
Example: {"name": "John Doe", "age": 30, "job": "Developer"} is an example of JSON data.
Related Keywords: Data Exchange, Web Development, APITransformer
document 9:Definition: A transformer is a type of deep learning model used in natural language processing for tasks like translation, summarization, and text generation. It is based on the attention mechanism.
Example: Google Translate uses transformer models to perform translations between languages.
Related Keywords: Deep Learning, Natural Language Processing, AttentionHuggingFace
document 10:Definition: HuggingFace is a library that provides pre-trained models and tools for natural language processing, making NLP tasks more accessible to researchers and developers.
Example: HuggingFace’s Transformers library can be used for tasks like sentiment analysis and text generation.
Related Keywords: Natural Language Processing, Deep Learning, LibraryDigital Transformation
==============================================================
===============After applying LLMChainExtractor===============
大模型把无关内容都过滤了, 虽然我 embedding 很拉, 没能抽到相关内容
以下是一个过滤效果的展示, 把定义成功保留, 示例被过滤掉
text = \
"""
Multimodal
Definition: Multimodal refers to the technology that combines multiple types of data modes (e.g., text, images, sound) to process and extract richer and more accurate information or predictions.
Example: A system that analyzes both images and descriptive text to perform more accurate image classification is an example of multimodal technology.
Relate
"""
docs = [Document(text)]
query = "What is the definition of Multimodal?"
compressed_docs = compressor.compress_documents(docs, query)
print(compressed_docs[0].page_content)
Multimodal
Definition: Multimodal refers to the technology that combines multiple types of data modes (e.g., text, images, sound) to process and extract richer and more accurate information or predictions.
源码分析
这是 ContextualCompressionRetriever
的检索函数 _get_relevant_documents
的关键代码:
docs = self.base_retriever.invoke(query, config={"callbacks": run_manager.get_child()}, **kwargs)if docs:compressed_docs = self.base_compressor.compress_documents(docs, query, callbacks=run_manager.get_child())return list(compressed_docs)else:return []
首先还是 base_retriever 支持返回检索结果, 再接过 base_compressor 压缩
这是 base_compresser 类 LLMChainExtractor
的 compress_documents
函数关键部分:
compressed_docs = []for doc in documents:_input = self.get_input(query, doc) # 产生 {"question": query, "context": doc.page_content}output_ = self.llm_chain.invoke(_input, config={"callbacks": callbacks}) # 调用大模型抽取内容if isinstance(self.llm_chain, LLMChain):output = output_[self.llm_chain.output_key]if self.llm_chain.prompt.output_parser is not None:output = self.llm_chain.prompt.output_parser.parse(output)else:output = output_if len(output) == 0:continuecompressed_docs.append(Document(page_content=cast(str, output), metadata=doc.metadata))return compressed_docs
这是调用大模型抽取内容的 prompt 模板
"""
Given the following question and context, extract any part of the context *AS IS* that is relevant to answer the question. If none of the context is relevant return {no_output_str}. Remember, *DO NOT* edit the extracted parts of the context.> Question: {{question}}
> Context:
>>>
{{context}}
>>>
Extracted relevant parts:
"""
EmbeddingsFilter
对每个检索到的文档执行额外的 LLM 调用既昂贵又缓慢。
EmbeddingsFilter
提供了一个更经济且更快速的选项,通过嵌入文档和查询,只返回那些与查询的嵌入相似度足够高的文档。
这种方法在保持搜索结果相关性的同时,节省了计算成本和时间。
该过程涉及使用 EmbeddingsFilter
和 ContextualCompressionRetriever
压缩并检索相关文档。
EmbeddingsFilter
用于过滤超过指定相似度阈值(0.86)的文档。
from langchain.retrievers.document_compressors import EmbeddingsFilter
from langchain_openai import OpenAIEmbeddings# 1. Generate embeddings using OpenAIEmbeddings
embeddings = OpenAIEmbeddings(model="bge-m3",base_url='http://localhost:9997/v1',api_key='cannot be empty',# dimensions=1024,
)# 2. Generate EmbedingsFilter object that has similarity threshold of 0.86
embeddings_filter = EmbeddingsFilter(embeddings=embeddings, similarity_threshold=0.86)# 3. Generate ContextualCompressionRetriever object using EmbeddingsFilter and retriever
compression_retriever = ContextualCompressionRetriever(base_compressor=embeddings_filter, base_retriever=retriever
)# 4. Query the compression retriever to find relevant documents
compressed_docs = compression_retriever.invoke("What is the definition of Multimodal?"
)# 5. Print the relevant documents
for i, d in enumerate(compressed_docs):print(f"document {i+1}:\n\n" + d.page_content)
这个方法也只是将 base_retriever 的返回结果经过 EmbeddingsFilter 的相似度阈值过滤, 可以选择更强的 embedding model 来强化相似度准确度
Ensemble Retriever 多路召回
EnsembleRetriever
集成了稀疏和密集检索算法的优点,通过使用权重和运行时配置来定制性能。
关键特点
- 集成多个检索器:接受不同类型的检索器作为输入并结合结果。
- 结果重新排序:使用倒排排名融合算法重新排序结果。
- 混合检索:主要使用
稀疏检索器
(例如 BM25)和密集检索器
(例如 嵌入相似度)相结合。
优势
- 稀疏检索器:有效进行基于关键词的检索。
- 密集检索器:有效进行基于语义相似度的检索。
由于这些互补特性,EnsembleRetriever
可以在各种检索场景中提供更好的性能。
from langchain.retrievers import BM25Retriever, EnsembleRetriever
from langchain.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings# list sample documents
doc_list = ["I like apples","I like apple company","I like apple's iphone","Apple is my favorite company","I like apple's ipad","I like apple's macbook",
]# Initialize the bm25 retriever and faiss retriever.
bm25_retriever = BM25Retriever.from_texts(doc_list,
)
bm25_retriever.k = 2 # Set the number of search results for BM25Retriever to 1.embedding = OpenAIEmbeddings(model="bge-m3",base_url='http://localhost:9997/v1',api_key='cannot be empty',# dimensions=1024,)faiss_vectorstore = FAISS.from_texts(doc_list,embedding,
)
faiss_retriever = faiss_vectorstore.as_retriever(search_kwargs={"k": 2})# Initialize the ensemble retriever.
ensemble_retriever = EnsembleRetriever(retrievers=[bm25_retriever, faiss_retriever],weights=[0.7, 0.3],
)
# Get the search results document.
query = "my favorite fruit is apple"
ensemble_result = ensemble_retriever.invoke(query)
bm25_result = bm25_retriever.invoke(query)
faiss_result = faiss_retriever.invoke(query)# Output the fetched documents.
print("[Ensemble Retriever]")
for doc in ensemble_result:print(f"Content: {doc.page_content}")print()print("[BM25 Retriever]")
for doc in bm25_result:print(f"Content: {doc.page_content}")print()print("[FAISS Retriever]")
for doc in faiss_result:print(f"Content: {doc.page_content}")print()
[Ensemble Retriever]
Content: Apple is my favorite companyContent: I like apple companyContent: I like apples[BM25 Retriever]
Content: Apple is my favorite companyContent: I like apple company[FAISS Retriever]
Content: Apple is my favorite companyContent: I like apples
源码分析
EnsembleRetriever
的 rank_fusion
函数:
retriever_docs = [retriever.invoke(query,patch_config(config, callbacks=run_manager.get_child(tag=f"retriever_{i + 1}")),)for i, retriever in enumerate(self.retrievers)
]# Enforce that retrieved docs are Documents for each list in retriever_docs
for i in range(len(retriever_docs)):retriever_docs[i] = [Document(page_content=cast(str, doc)) if isinstance(doc, str) else docfor doc in retriever_docs[i]]# apply rank fusion
fused_documents = self.weighted_reciprocal_rank(retriever_docs)
每个 retriever 单独调用, 返回多组 Documents, 再经过 weighted_reciprocal_rank
:
rrf_score: Dict[str, float] = defaultdict(float)
for doc_list, weight in zip(doc_lists, self.weights):for rank, doc in enumerate(doc_list, start=1):rrf_score[(doc.page_contentif self.id_key is Noneelse doc.metadata[self.id_key])] += weight / (rank + self.c)# Docs are deduplicated by their contents then sorted by their scores
all_docs = chain.from_iterable(doc_lists)
sorted_docs = sorted(unique_by_key(all_docs,lambda doc: (doc.page_contentif self.id_key is Noneelse doc.metadata[self.id_key]),),reverse=True,key=lambda doc: rrf_score[doc.page_content if self.id_key is None else doc.metadata[self.id_key]],
)
基于 weights 对 Documents 重排序
Long Context Reorder
无论模型的架构如何,当检索的文档超过 10 个时,性能都会显著下降。
简单来说,当模型需要在长上下文的中间部分访问相关信息时,它往往会忽视提供的文档。
更多细节,请参阅以下论文:
- https://arxiv.org/abs/2307.03172
为了避免这个问题,您可以在检索后重新排序文档,从而防止性能下降。
可以创建一个检索器,它使用 Chroma 向量数据库存储和搜索文本数据。然后,使用检索器的 invoke
方法,针对给定的查询搜索出高度相关的文档。
from langchain_core.prompts import PromptTemplate
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings# Get embeddings
embeddings = OpenAIEmbeddings(model="bge-m3",base_url='http://localhost:9997/v1',api_key='cannot be empty',# dimensions=1024,)texts = ["This is just a random text I wrote.","ChatGPT, an AI designed to converse with users, can answer various questions.","iPhone, iPad, MacBook are representative products released by Apple.","ChatGPT was developed by OpenAI and is continuously being improved.","ChatGPT has learned from vast amounts of data to understand user questions and generate appropriate answers.","Wearable devices like Apple Watch and AirPods are also part of Apple's popular product line.","ChatGPT can be used to solve complex problems or suggest creative ideas.","Bitcoin is also called digital gold and is gaining popularity as a store of value.","ChatGPT's capabilities are continuously evolving through ongoing learning and updates.","The FIFA World Cup is held every four years and is the biggest event in international football.",
]# Create a retriever (Set K to 10)
retriever = Chroma.from_texts(texts, embedding=embeddings).as_retriever(search_kwargs={"k": 10}
)
query = "What can you tell me about ChatGPT?"# Retrieves relevant documents sorted by relevance score.
docs = retriever.invoke(query)
docs
[Document(metadata={}, page_content='Bitcoin is also called digital gold and is gaining popularity as a store of value.'),Document(metadata={}, page_content='The FIFA World Cup is held every four years and is the biggest event in international football.'),Document(metadata={}, page_content="Wearable devices like Apple Watch and AirPods are also part of Apple's popular product line."),Document(metadata={}, page_content='iPhone, iPad, MacBook are representative products released by Apple.'),Document(metadata={}, page_content='This is just a random text I wrote.'),Document(metadata={}, page_content='ChatGPT, an AI designed to converse with users, can answer various questions.'),Document(metadata={}, page_content='ChatGPT was developed by OpenAI and is continuously being improved.'),Document(metadata={}, page_content='ChatGPT has learned from vast amounts of data to understand user questions and generate appropriate answers.'),Document(metadata={}, page_content='ChatGPT can be used to solve complex problems or suggest creative ideas.'),Document(metadata={}, page_content="ChatGPT's capabilities are continuously evolving through ongoing learning and updates.")]
创建一个 LongContextReorder
类的实例。
- 调用
reordering.transform_documents(docs)
来重新排序文档列表。 - 相关性较低的文档会被置于列表的中间,而相关性较高的文档会被放置在列表的开头和结尾。
from langchain_community.document_transformers import LongContextReorder
reordering = LongContextReorder()
reordered_docs = reordering.transform_documents(docs)reordered_docs
[Document(metadata={}, page_content='The FIFA World Cup is held every four years and is the biggest event in international football.'),Document(metadata={}, page_content='iPhone, iPad, MacBook are representative products released by Apple.'),Document(metadata={}, page_content='ChatGPT, an AI designed to converse with users, can answer various questions.'),Document(metadata={}, page_content='ChatGPT has learned from vast amounts of data to understand user questions and generate appropriate answers.'),Document(metadata={}, page_content="ChatGPT's capabilities are continuously evolving through ongoing learning and updates."),Document(metadata={}, page_content='ChatGPT can be used to solve complex problems or suggest creative ideas.'),Document(metadata={}, page_content='ChatGPT was developed by OpenAI and is continuously being improved.'),Document(metadata={}, page_content='This is just a random text I wrote.'),Document(metadata={}, page_content="Wearable devices like Apple Watch and AirPods are also part of Apple's popular product line."),Document(metadata={}, page_content='Bitcoin is also called digital gold and is gaining popularity as a store of value.')]
源码分析
documents.reverse()
reordered_result = []
for i, value in enumerate(documents):if i % 2 == 1:reordered_result.append(value)else:reordered_result.insert(0, value)
原顺序是相似度由高到低的, 他只是在原顺序的基础上把高相似度的放散在头部和尾部, 低相关的放在中部.
当模型需要在长上下文的中间部分访问相关信息时,它往往会忽视提供的文档
按这种说法, 模型会更注重头部和尾部的文档
相关文章:
langchain教程-9.Retriever/检索器
前言 该系列教程的代码: https://github.com/shar-pen/Langchain-MiniTutorial 我主要参考 langchain 官方教程, 有选择性的记录了一下学习内容 这是教程清单 1.初试langchain2.prompt3.OutputParser/输出解析4.model/vllm模型部署和langchain调用5.DocumentLoader/多种文档…...
凝思60重置密码
凝思系统重置密码 - 赛博狗尾草 - 博客园 问题描述 凝思系统进入单用户模式,在此模式下,用户可以访问修复错误配置的文件。也可以在此模式下安装显卡驱动,解决和已加载驱动的冲突问题。 适用范围 linx-6.0.60 linx-6.0.80 linx-6.0.100…...
指针基础知识1
1.内存和地址 1.案例 我们可以借助一个生活在的案例来熟悉电脑中内存和地址的关系: 假设有⼀栋宿舍楼,把你放在楼里,楼上有100个房间,但是房间没有编号,你的⼀个朋友来找你玩, 如果想找到你,…...
大数据学习之Spark分布式计算框架RDD、内核进阶
一.RDD 28.RDD_为什么需要RDD 29.RDD_定义 30.RDD_五大特性总述 31.RDD_五大特性1 32.RDD_五大特性2 33.RDD_五大特性3 34.RDD_五大特性4 35.RDD_五大特性5 36.RDD_五大特性总结 37.RDD_创建概述 38.RDD_并行化创建 演示代码: // 获取当前 RDD 的分区数 Since ( …...
Windows本地部署DeepSeek-R1大模型并使用web界面远程交互
文章目录 前言1. 安装Ollama2. 安装DeepSeek-r1模型3. 安装图形化界面3.1 Windows系统安装Docker3.2 Docker部署Open WebUI3.3 添加Deepseek模型 4. 安装内网穿透工具5. 配置固定公网地址 前言 最近爆火的国产AI大模型Deepseek详细大家都不陌生,不过除了在手机上安…...
【Linux系统】线程:线程控制
一、POSIX线程库 与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以“pthread_”打头的。使用这些函数库,要通过引入头文件 <pthread.h>。链接这些线程函数库时要使用编译器命令的 -lpthread 选项。 二、轻量级进程创建:…...
GoFrame 微服务开发指南
基本介绍 GoFrame 框架支持微服务模式开发,提供了常用的微服务组件、开发工具、开发教程帮助团队快速微服务转型。 微服务组件简介 GoFrame 微服务组件具有低耦合及通用化设计,组件化使用支持大部分的微服务通信协议。在官方文档中,主要以…...
Python-基于PyQt5,Pillow,pathilb,imageio,moviepy,sys的GIF(动图)制作工具(进阶版)
前言:在抖音,快手等社交平台上,我们常常见到各种各样的GIF动画。在各大评论区里面,GIF图片以其短小精悍、生动有趣的特点,被广泛用于分享各种有趣的场景、搞笑的瞬间、精彩的动作等,能够快速吸引我们的注意…...
PhpStorm下载、安装、配置教程
前面的文章中,都是把.php文件放在WampServer的www目录下,通过浏览器访问运行。这篇文章就简单介绍一下PhpStorm这个php集成开发工具的使用。 目录 下载PhpStorm 安装PhpStorm 配置PhpStorm 修改个性化设置 修改字符编码 配置php的安装路径 使用Ph…...
春节假期旅游热潮下,景区医疗安全如何全面升级?
春节假期旅游热潮下,景区医疗安全如何全面升级? 随着旅游业的不断繁荣,春节假期期间,各大景区再次迎来了游客的高峰期。面对如此庞大的客流量,景区不仅要在服务接待上下功夫,更要将医疗安全保障工作提升到…...
惠普HP工作站如何关闭关闭RAID?
惠普HP工作站如何关闭关闭RAID? 前言进入BIOS进入“先进”选项卡,点击“系统选项”。取消勾选“sSATA控制器RAID模式”,按下F10保存重启。 前言 惠普工作站默认启用了RAID模式,导致许多PE工具无法识别RAID模式下的硬盘。可以通过…...
ESP-Skainet智能语音助手,ESP32-S3物联网方案,设备高效语音交互
在科技飞速发展的今天,智能语音助手正逐渐渗透到我们生活的方方面面,而智能语音助手凭借其卓越的技术优势,成为了智能生活领域的一颗璀璨明星。 ESP-Skainet智能语音助手的强大之处在于其支持唤醒词引擎(WakeNet)、离…...
mac下生成.icns图标
笔记原因: 今日需要在mac下开发涉及图标文件的使用及icons文件的生成,所以记录一下。 网络上都是一堆命令行需要打印太麻烦了,写一个一键脚本。 步骤一 将需要生成的png格式文件重命名为“pic.png” mv xxxx.png pic.png 步骤二 下载我…...
【MySQL】centos 7 忘记数据库密码
vim /etc/my.cnf文件; 在[mysqld]后添加skip-grant-tables(登录时跳过权限检查) 重启MySQL服务:sudo systemctl restart mysqld 登录mysql,输入mysql –uroot –p;直接回车(Enter) 输…...
【kafka的零拷贝原理】
kafka的零拷贝原理 一、零拷贝技术概述二、Kafka中的零拷贝原理三、零拷贝技术的优势四、零拷贝技术的实现细节五、注意事项一、零拷贝技术概述 零拷贝(Zero-Copy)是一种减少数据拷贝次数,提高数据传输效率的技术。 在传统的数据传输过程中,数据需要在用户态和内核态之间…...
【JavaEE】Spring Web MVC
目录 一、Spring Web MVC简介 1.1 MVC简介1.2 Spring MVC1.3 RequestMapping注解1.3.1 使用1.3.2 RequestMapping的请求设置 1.3.2.1 方法11.3.2.2 方法2 二、Postman介绍 2.1 创建请求2.2 界面如下:2.3 传参介绍 一、Spring Web MVC简介 官方文档介绍ÿ…...
《解锁GANs黑科技:打造影视游戏的逼真3D模型》
在游戏与影视制作领域,逼真的3D模型是构建沉浸式虚拟世界的关键要素。从游戏中栩栩如生的角色形象,到影视里震撼人心的宏大场景,高品质3D模型的重要性不言而喻。随着人工智能技术的飞速发展,生成对抗网络(GANs…...
【大数据技术】词频统计样例(hadoop+mapreduce+yarn)
词频统计(hadoop+mapreduce+yarn) 搭建完全分布式高可用大数据集群(VMware+CentOS+FinalShell) 搭建完全分布式高可用大数据集群(Hadoop+MapReduce+Yarn) 在阅读本文前,请确保已经阅读过以上两篇文章,成功搭建了Hadoop+MapReduce+Yarn的大数据集群环境。 写在前面 Wo…...
deepseek与openai关系
DeepSeek与OpenAI之间的关系主要体现在技术竞争和合作的可能性上。 首先,DeepSeek是由中国的深度求索公司开发的,成立于2023年,专注于人工智能技术研发。其大模型DeepSeek-R1在数学、代码、自然语言推理等任务上的性能能够比肩OpenAI的G…...
51页精品PPT | 数据中台与数据治理服务及案例
案例的核心内容围绕数据中台与数据治理服务展开,详细介绍了数据治理的整体方法论、数据中台的建设路径以及如何通过数据治理和数据中台提升业务效率和数据质量。本案例强调了数据治理的重要性,包括数据标准、数据质量、数据安全等方面的管理,…...
使用 cipher /w 清除磁盘删除残留数据(Windows) - 随笔
cipher命令是Windows 系统自带的一个用于管理文件加密和磁盘数据清除的工具。通过 cipher /w 命令,可以清除磁盘上已删除文件的残留数据,确保这些数据无法被恢复。以下是一个简易的批处理脚本,用于清除指定磁盘上的加密数据。 echo off :: 清…...
RuntimeWarning: invalid value encountered in sqrt
代码出处: GitHub - wangsen1312/joints2smpl: fit smpl parameters model using 3D joints RuntimeWarning: invalid value encountered in sqrt 你可以通过以下几种方式解决这个问题: 1. 检查负值或零行列式 确保协方差矩阵是正半定的,这…...
3步打造C# API安全密盾
引言:API 安全的重要性 在数字化浪潮中,应用程序编程接口(API)已成为不同软件系统之间通信和数据交互的关键桥梁。无论是企业内部的微服务架构,还是面向外部用户的在线服务,API 都承担着数据传输和业务逻辑…...
项目实操:windows批处理拉取git库和处理目录、文件
初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 源码指引:github源…...
接入 deepseek 实现AI智能问诊
1. 准备工作 注册 DeepSeek 账号 前往 DeepSeek 官网 注册账号并获取 API Key。 创建 UniApp 项目 使用 HBuilderX 创建一个新的 UniApp 项目(选择 Vue3 或 Vue2 模板)。 安装依赖 如果需要在 UniApp 中使用 HTTP 请求,推荐使用 uni.requ…...
ubuntu22.04源码编译mysql8.0.X详细流程【由deepseek提供】
以下是在 Ubuntu 22.04 上从源代码编译安装 MySQL 8.0.X(以 MySQL 8.0.37 为例)的详细操作流程: 一、准备工作 1. 更新系统 sudo apt update && sudo apt upgrade -y sudo apt install -y build-essential cmake pkg-config libssl…...
富唯智能复合机器人拓展工业新维度
富唯智能复合机器人是富唯智能倾力打造的一款集高度自动化、智能化和多功能性于一体的机器人。它融合了机械、电子、计算机、传感器等多个领域的前沿技术,通过精密的算法和控制系统,实现了对复杂生产环境的快速适应和高效作业。 富唯智能复合机器人的特点…...
【2】高并发导出场景下,服务器性能瓶颈优化方案-异步导出
Java 异步导出是一种在处理大量数据或复杂任务时优化性能和用户体验的重要技术。 1. 异步导出的优势 异步导出是指将导出操作从主线程中分离出来,通过后台线程或异步任务完成数据处理和文件生成。这种方式可以显著减少用户等待时间,避免系统阻塞&#x…...
verdi 查看覆盖率
点击Tools -> Coverage,会出现一个Verdi:vdCoverage:1页面点击File->Open/Add Database, 会出现一个 Open/Add Coverage Database页面, 在Design Hierarchy/Testbench Location 中输入 vdb路径点击… , 会出现当前路径下的文件…...
【React】路由处理的常见坑与解决方法,React Router 的动态路由与懒加载问题
在使用 React Router 时,动态路由和懒加载是非常常见的需求,但也可能会遇到一些坑。以下是常见问题以及对应的解决方法。 一、React Router 动态路由常见问题 1. 动态路由匹配问题 动态路由通常通过 :param 定义路径参数,但如果路径参数与静态路由有重叠,可能会导致匹配问…...
OKHttp拦截器解析
OKHttp涉及到拦截器大概的执行步骤为: 1.通过newCall生成RealCall对象 具体代码如下: Override public Call newCall(Request request) {return new RealCall(this, request, false /* for web socket */);}2.调用Call的execute方法 当然这也可以是执…...
顺序表和链表
线性表 线性表(linear list)是n 个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构。 常见的线性表:顺序表、链表、栈、队列、字符串… 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物…...
若依框架使用(低级)
克隆源码 浏览器搜索若依,选择 RuoYi-Vue RuoYi-Vue RuoYi-Vue 重要的事情说三遍,进入gitee 下面这个页面(注意红色框起来的部分) 进入Gitee进行下载 我下载的是最新的springboot3 下载好后我们可以选择一个文件夹࿰…...
Spring JDBC模块解析 -深入SqlParameterSource
在前面的博客中,我们探讨了Spring Data Access Module中的主要组件: JdbcTemplate和SimpleJdbcInsert。在这两部分的基础上,我们将继续探讨更详细 的用法,包括如何使用RowMapper和SqlParameterSource等高级主题。 JdbcTemplate …...
SQL中Limit的用法详解
SQL中的LIMIT关键字是一个非常有用的工具,它可以用来限制查询结果返回的记录数量。文章将详细解析LIMIT关键字的使用方法,包括它的基本用法,以及在查询数据时如何配合使用LIMIT与OFFSET。我会通过示例代码演示LIMIT在单行结果集和多行结果集情…...
mac 安装 dotnet 环境
目录 一、安装准备 二、安装方法(两种任选) 方法 1:使用官方安装包(推荐新手) 方法 2:使用 Homebrew(适合开发者) 1. 安装 Homebrew(如未安装) 2. 通过 …...
DeepSeek辅助学术写作【句子重写】效果如何?
句子重写(功能指数:★★★★★) 当我们想引用一篇文章中的一-些我们认为写得很好的句子时,如果直接将原文加人自己的文章,那么即使我们标注上了引用,也依旧会被查重软件计算在重复比例中。查重比例过高的话,会影响投稿或毕业答辩送…...
SpringUI Web高端动态交互元件库
Axure Web高端动态交互元件库是一个专为Web设计与开发领域设计的高质量资源集合,旨在加速原型设计和开发流程。以下是关于这个元件库的详细介绍: 一、概述 Axure Web高端动态交互元件库是一个集成了多种预制、高质量交互组件的工具集合。这些组件经过精…...
QT +FFMPEG4.3 拉取 RTMP/http-flv 流播放 AVFrame转Qimage
QT FFMPEG4.3 拉取 RTMP/http-flv 流播放 Cc_Video_thread.h #ifndef CC_VIDEO_THREAD_H #define CC_VIDEO_THREAD_H#include <QThread> #include <QAtomicInt> #include <QImage>#ifdef __cplusplus extern "C" { #endif #include <libavfor…...
Docker最佳实践:安装Nacos
文章目录 Docker最佳实践:安装Nacos一、引言二、安装 Nacos1、拉取 Nacos Docker 镜像2、启动 Nacos 容器 三、配置 Nacos(可选)四、使用示例1、服务注册2、服务发现 五、总结 Docker最佳实践:安装Nacos 一、引言 Nacos 是阿里巴…...
106,【6】 buuctf web [SUCTF 2019]CheckIn
进入靶场 文件上传 老规矩,桌面有啥传啥 过滤了<? 寻找不含<?的一句话木马 文件名 123(2).php.jpg 文件内容 GIF89a? <script language"php">eval($_GET[123]);</script> 123即密码,可凭借个人喜好更换 再上传一个文…...
【Linux】27.Linux 多线程(1)
文章目录 1. Linux线程概念1.1 线程和进程1.2 虚拟地址是如何转换到物理地址的1.3 线程的优点1.4 线程的缺点1.5 线程异常1.6 线程用途 2. Linux进程VS线程2.1 进程和线程2.2 关于进程线程的问题 3. Linux线程控制3.1 POSIX线程库3.2 创建线程3.3 线程终止3.4 线程等待3.5 分离…...
旋转变压器工作及解调原理
旋转变压器 旋转变压器是一种精密的位置、速度检测装置,广泛应用在伺服控制、机器人、机械工具、汽车、电力等领域。但是,旋转变压器在使用时并不能直接提供角度或位置信息,需要特殊的激励信号和解调、计算措施,才能将旋转变压器…...
字符串转浮点数函数atof、strtod、strtof和strtold使用场景
字符串转浮点数函数 atof、strtod、strtof 和 strtold 在 C 语言标准库中都有各自的使用场景,它们的主要功能是将字符串转换为浮点数,但在处理的浮点数类型、错误处理机制和精度方面有所不同。 一、atof 函数使用场景 atof(ASCII to Float&…...
GD32F4xx系列微控制器中,定时器的主模式(Master Mode)和从模式(Slave Mode)
在GD32F4xx系列微控制器中,定时器的主模式(Master Mode)和从模式(Slave Mode)是两种不同的工作模式,它们的主要区别在于定时器的操作是否依赖于外部信号或另一个定时器的输出信号。以下是对这两种模式的详细…...
深度学习系列--03.激活函数
一.定义 激活函数是一种添加到人工神经网络中的函数,它为神经网络中神经元的输出添加了非线性特性 在神经网络中,神经元接收来自其他神经元的输入,并通过加权求和等方式计算出一个净输入值。激活函数则根据这个净输入值来决定神经元是否应该…...
在linux 中搭建deepseek 做微调,硬件配置要求说明
搭建 可参考 使用deepseek-CSDN博客 官方网站:DeepSeek DeepSeek 是一个基于深度学习的开源项目,旨在通过深度学习技术来提升搜索引擎的准确性和效率。如果你想在 Linux 系统上搭建 DeepSeek,你可以遵循以下步骤。这里我将提供一个基本的指…...
机器学习之数学基础:线性代数、微积分、概率论 | PyTorch 深度学习实战
前一篇文章,使用线性回归模型逼近目标模型 | PyTorch 深度学习实战 本系列文章 GitHub Repo: https://github.com/hailiang-wang/pytorch-get-started 本篇文章内容来自于 强化学习必修课:引领人工智能新时代【梗直哥瞿炜】 线性代数、微积分、概率论 …...
MySQL - Navicat自动备份MySQL数据
对于从事IT开发的工程师,数据备份我想大家并不陌生,这件工程太重要了!对于比较重要的数据,我们希望能定期备份,每天备份1次或多次,或者是每周备份1次或多次。 如果大家在平时使用Navicat操作数据库&#x…...
javaEE-9.HTML入门
目录 一.什么是html 二.认识html标签 1.标签的特点: 2.html文件基本结构 3.标签的层次结构 三、html工具 四、创建第一个文件 五.html常见标签 1标题标签h1-h6 2.段落标签:p 3.换行标签:br 4.图片标签:img 图片路径有1三种表示形式: 5.超链接:a 链接的几种形式: …...