Rerank
即重新排序,是信息检索、推荐系统、自然语言处理和机器学习领域中的一种常见技术。它的目的是提高搜索结果、推荐列表或生成内容的相关性,使其更符合用户的需求或期望。
在RAG里,我们主要利用Rerank 模型来对初步检索出的文档(比如通过BM25或者向量检索召回的文档)进行重排序 和过滤 。
支持一种语言的嵌入模型
英语 bge-large-en
中文 bge-large-zh
支持双语 的嵌入模型
网易有道 BCEmbedding
优势
双语和跨语种能力 :基于有道翻译引擎的强大能力,BCEmbedding实现强大的中英双语和跨语种语义表征能力。
RAG适配 :面向RAG做针对性优化,可适配大多数相关任务,比如翻译,摘要,问答 等。此外,针对 问题理解(query understanding) 也做了针对优化
高效且精确的语义检索 :EmbeddingModel采用双编码器,可以在第一阶段实现高效的语义检索。RerankerModel采用交叉编码器,可以在第二阶段实现更高精度的语义顺序精排。
更好的领域泛化性 :为了在更多场景实现更好的效果,我们收集了多种多样的领域数据。
用户友好 :语义检索时不需要特殊指令前缀。也就是,你不需要为各种任务绞尽脑汁设计指令前缀。
有意义的重排序分数 :RerankerModel可以提供有意义的语义相关性分数(不仅仅是排序),可以用于过滤无意义文本片段,提高大模型生成效果。
产品化检验 :BCEmbedding已经被有道众多产品检验。
模型列表
https://github.com/netease-youdao/BCEmbedding/blob/master/README_zh.md#-%E6%A8%A1%E5%9E%8B%E5%88%97%E8%A1%A8
模型下载
嵌入模型:https://www.modelscope.cn/models/maidalun/bce-embedding-base_v1/files
1 git clone https://www.modelscope.cn/maidalun/bce-embedding-base_v1.git
Rerank 模型:https://www.modelscope.cn/models/maidalun/bce-reranker-base_v1/summary
1 git clone https://www.modelscope.cn/maidalun/bce-reranker-base_v1.git
模型性能:
关键参数
RerankerModel支持 长 passage(超过512 tokens,不超过32k tokens)rerank ;
RerankerModel可以给出有意义 相关性分数 (区别于cosine分数 ),帮助 过滤低质量召回 ;
EmbeddingModel 768 维度
安装 BCEmbedding
理解Rerank 和 cosine 语义相似 的不同
问题:你最喜欢的电影是什么? 和下面这些回答的cosine语义相似度
bce-embedding-base_v1 和 bge_large_zh 结果一致
1 2 3 4 5 6 7 8 9 10 [1 ] 我最喜欢的电影是《阿甘正传》。 Score:0.6105921907574262 [2 ] 我最喜欢的电影类型是恐怖片。 Score:0.5381861816884799 [3 ] 我最喜欢的电影导演是斯皮尔伯格。 Score:0.4905046919817628 [4 ] 我最喜欢的书是《哈利波特》。 Score:0.4652198126696215 [5 ] 我不喜欢看电影。 Score:0.44154025662995605 [6 ] 我喜欢看科幻电影,尤其是《星际穿越》。 Score:0.4249389530579074 [7 ] 我最喜欢的音乐是爵士乐。 Score:0.39165986473334957 [8 ] 昨天晚上我看了一部很好的电影。 Score:0.35591581297344105 [9 ] 我最喜欢的运动是篮球。 Score:0.3554765233404198 [10 ] 我喜欢吃披萨。 Score:0.34989368275228544
经过re-rank,效果非常明显!
1 2 3 4 5 6 7 8 9 10 我最喜欢的电影是《阿甘正传》。 [1 ] 我最喜欢的电影类型是恐怖片 [2 ] 我喜欢看科幻电影,尤其是《星际穿越》。 [6 ] 我最喜欢的电影导演是斯皮尔伯格。 [3 ] 昨天晚上我看了一部很好的电影。 [8 ] 我最喜欢的书是《哈利波特》。 [4 ] 我不喜欢看电影。 [5 ] 我最喜欢的音乐是爵士乐。 [7 ] 我喜欢吃披萨。 [10 ] 我最喜欢的运动是篮球。 [9 ]
嵌入模型使用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 embedding_model_name = 'D:\LLM\\bce_modesl\\bce-embedding-base_v1' embedding_model_kwargs = {'device' : 'cpu' } embedding_encode_kwargs = {'batch_size' : 32 , 'normalize_embeddings' : True , } embed_model = HuggingFaceEmbeddings( model_name=embedding_model_name, model_kwargs=embedding_model_kwargs, encode_kwargs=embedding_encode_kwargs ) query = '你好呀兄弟!' passages = ['天真热' , '嗯呢' ] query_embedding = embed_model.embed_query(query) passages_embeddings = embed_model.embed_documents(passages)
Rerank 模型使用方法
非langchain 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 query = '你最喜欢的电影是什么?' passages = [ '我最喜欢的电影是《阿甘正传》。' , '我最喜欢的电影类型是恐怖片' , '我最喜欢的电影导演是斯皮尔伯格。' , '我最喜欢的书是《哈利波特》。' , '我不喜欢看电影。' , '我喜欢看科幻电影,尤其是《星际穿越》。' , '我最喜欢的音乐是爵士乐。' , '昨天晚上我看了一部很好的电影。' , '我最喜欢的运动是篮球。' , '我喜欢吃披萨。' ] sentence_pairs = [[query, passage] for passage in passages] reranker_model = 'D:\LLM\\bce_modesl\\bce-reranker-base_v1' model = RerankerModel(model_name_or_path=reranker_model) scores = model.compute_score(sentence_pairs) rerank_results = model.rerank(query, passages) doc_list = rerank_results['rerank_passages' ] for line in doc_list: print (line) pass
langchain 调用方法: 可以作为compressor直接传给ContextualCompressionRetriever
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 reranker_args = {'model' : 'D:\LLM\\bce_modesl\\bce-reranker-base_v1' , 'top_n' : 10 , 'device' : 'cuda:0' } reranker = BCERerank(**reranker_args) compression_retriever = ContextualCompressionRetriever( base_compressor=reranker, base_retriever=retriever ) docs = compression_retriever.get_relevant_documents('你最喜欢的电影是什么?' ) text_splitter = RecursiveCharacterTextSplitter(chunk_size=400 ) embedding_filter = EmbeddingsFilter(embeddings=embed_model, similarity_threshold=0.6 ) redundant_filter = EmbeddingsRedundantFilter(embeddings=embed_model) llm_extractor = LLMChainExtractor.from_llm(qianfan_chat) pipeline_compressor = DocumentCompressorPipeline( transformers=[text_splitter, embedding_filter, redundant_filter, reranker, llm_extractor] ) pipeline_retriever = ContextualCompressionRetriever( base_compressor=pipeline_compressor, base_retriever=retriever ) docs = pipeline_retriever.get_relevant_documents(query)
召回了20个文档,经过 分割 、向量过滤 、文档去重 、rerank ,只有3个文档到了 信息抽取 环节
相关代码
测试数据放到数据库
langchain中rerank 查询
非langchain 调用方法
测试数据放到数据库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 import osfrom langchain.text_splitter import RecursiveCharacterTextSplitterfrom langchain_community.chat_models import QianfanChatEndpointfrom langchain_community.document_loaders import TextLoader, DirectoryLoaderfrom langchain_community.embeddings import QianfanEmbeddingsEndpoint, HuggingFaceEmbeddingsfrom langchain import hubfrom langchain_community.vectorstores.elasticsearch import ElasticsearchStorefrom langchain_core.documents import Documentfrom langchain_core.output_parsers import StrOutputParserfrom langchain_core.runnables import RunnablePassthroughimport numpy as npdef cosine_similarity (vec1, vec2 ): dot_product = np.dot(vec1, vec2) norm_vec1 = np.linalg.norm(vec1) norm_vec2 = np.linalg.norm(vec2) return dot_product / (norm_vec1 * norm_vec2) if __name__ == '__main__' : embedding_model_name = 'D:\LLM\\bce_modesl\\bce-embedding-base_v1' embedding_model_kwargs = {'device' : 'cuda:0' } embedding_encode_kwargs = {'batch_size' : 32 , 'normalize_embeddings' : True , } embed_model = HuggingFaceEmbeddings( model_name=embedding_model_name, model_kwargs=embedding_model_kwargs, encode_kwargs=embedding_encode_kwargs ) doc_list = [ '我最喜欢的电影是《阿甘正传》。' , '我最喜欢的电影类型是恐怖片' , '我最喜欢的电影导演是斯皮尔伯格。' , '我最喜欢的书是《哈利波特》。' , '我不喜欢看电影。' , '我喜欢看科幻电影,尤其是《星际穿越》。' , '我最喜欢的音乐是爵士乐。' , '昨天晚上我看了一部很好的电影。' , '我最喜欢的运动是篮球。' , '我喜欢吃披萨。' ] docs = [] index =1 for line in doc_list: tmp_doc = Document(page_content=line) tmp_doc.metadata['num' ] = index index += 1 docs.append(tmp_doc) pass vectorstore = ElasticsearchStore( es_url=os.environ['ELASTIC_HOST_HTTP' ], index_name="index_ex_768_vectors" , embedding=embed_model, es_user="elastic" , vector_query_field='question_vectors' , es_password=os.environ['ELASTIC_ACCESS_PASSWORD' ] ) vectorstore.add_documents(docs) print ('Done!' )
langchain中rerank 查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 import osfrom uuid import uuid4from langchain.retrievers import ContextualCompressionRetrieverfrom langchain.retrievers.document_compressors import DocumentCompressorPipeline, EmbeddingsFilter, LLMChainExtractorfrom langchain.text_splitter import RecursiveCharacterTextSplitterfrom langchain_community.chat_models import QianfanChatEndpointfrom langchain_community.document_loaders import TextLoader, DirectoryLoaderfrom langchain_community.document_transformers import EmbeddingsRedundantFilterfrom langchain_community.embeddings import QianfanEmbeddingsEndpoint, HuggingFaceEmbeddingsfrom langchain import hubfrom langchain_community.vectorstores.elasticsearch import ElasticsearchStorefrom langchain_core.documents import Documentfrom langchain_core.output_parsers import StrOutputParserfrom langchain_core.runnables import RunnablePassthroughfrom BCEmbedding.tools.langchain import BCERerankimport numpy as npos.environ["QIANFAN_ACCESS_KEY" ] = os.getenv('MY_QIANFAN_ACCESS_KEY' ) os.environ["QIANFAN_SECRET_KEY" ] = os.getenv('MY_QIANFAN_SECRET_KEY' ) qianfan_chat = QianfanChatEndpoint( model="ERNIE-Bot-4" ) unique_id = uuid4().hex [0 :8 ] os.environ["LANGCHAIN_PROJECT" ] = f" [一条龙] qianfan Tracing Walkthrough - {unique_id} " os.environ["LANGCHAIN_API_KEY" ] = os.getenv('MY_LANGCHAIN_API_KEY' ) if __name__ == '__main__' : embedding_model_name = 'D:\LLM\\bce_modesl\\bce-embedding-base_v1' embedding_model_kwargs = {'device' : 'cpu' } embedding_encode_kwargs = {'batch_size' : 32 , 'normalize_embeddings' : True , } embed_model = HuggingFaceEmbeddings( model_name=embedding_model_name, model_kwargs=embedding_model_kwargs, encode_kwargs=embedding_encode_kwargs ) vectorstore = ElasticsearchStore( es_url=os.environ['ELASTIC_HOST_HTTP' ], index_name="index_ex_768_vectors" , embedding=embed_model, es_user="elastic" , vector_query_field='question_vectors' , es_password=os.environ['ELASTIC_ACCESS_PASSWORD' ] ) retriever = vectorstore.as_retriever(search_kwargs={"k" : 20 }) query = '粥余知识库' reranker_args = {'model' : 'D:\LLM\\bce_modesl\\bce-reranker-base_v1' , 'top_n' : 10 , 'device' : 'cuda:0' } reranker = BCERerank(**reranker_args) compression_retriever = ContextualCompressionRetriever( base_compressor=reranker, base_retriever=retriever ) text_splitter = RecursiveCharacterTextSplitter(chunk_size=400 ) embedding_filter = EmbeddingsFilter(embeddings=embed_model, similarity_threshold=0.6 ) redundant_filter = EmbeddingsRedundantFilter(embeddings=embed_model) llm_extractor = LLMChainExtractor.from_llm(qianfan_chat) pipeline_compressor = DocumentCompressorPipeline( transformers=[text_splitter, embedding_filter, redundant_filter, reranker, llm_extractor] ) pipeline_retriever = ContextualCompressionRetriever( base_compressor=pipeline_compressor, base_retriever=retriever ) docs = pipeline_retriever.get_relevant_documents(query) pass
非langchain 调用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 from BCEmbedding import RerankerModel, EmbeddingModelif __name__ == '__main__' : embedding_model_name = 'D:\LLM\\bce_modesl\\bce-embedding-base_v1' sentences = ['哈喽啊兄弟' , '明天去上学了' ] model = EmbeddingModel(model_name_or_path=embedding_model_name) query = '你最喜欢的电影是什么?' passages = [ '我最喜欢的电影是《阿甘正传》。' , '我最喜欢的电影类型是恐怖片' , '我最喜欢的电影导演是斯皮尔伯格。' , '我最喜欢的书是《哈利波特》。' , '我不喜欢看电影。' , '我喜欢看科幻电影,尤其是《星际穿越》。' , '我最喜欢的音乐是爵士乐。' , '昨天晚上我看了一部很好的电影。' , '我最喜欢的运动是篮球。' , '我喜欢吃披萨。' ] sentence_pairs = [[query, passage] for passage in passages] reranker_model = 'D:\LLM\\bce_modesl\\bce-reranker-base_v1' model = RerankerModel(model_name_or_path=reranker_model) scores = model.compute_score(sentence_pairs) rerank_results = model.rerank(query, passages) doc_list = rerank_results['rerank_passages' ] for line in doc_list: print (line) pass
其实如果要达到一个好的效果,还是需要根据使用场景去选择适合的ReRank和embedding
Langchain系列[16]下载和使用Rerank模型
转载前请阅读本站 版权协议 ,文章著作权归 粥余 所有,转载请注明出处。