Chainlit集成LlamaIndex实现知识库高级检索(BM25全文检索器)

news2024/11/20 13:43:01

检索原理

BM25Retriever类是一个基于BM25算法设计的检索器,它主要用于从一组文档或节点中检索出与查询最相关的文档或节点。这个类的设计目的是为了提高文本检索的效率和准确性,尤其是在处理大量文本数据时。

BM25(Best Matching 25)算法是一种在信息检索领域广泛应用的经典算法,它是对传统的TF-IDF(Term Frequency-Inverse Document Frequency)算法的一种改进。BM25算法的核心思想是利用词频(TF)和逆文档频率(IDF)来衡量文档与查询之间的相关性,同时考虑到文档长度信息对相关性的影响。以下是对BM25算法的一些关键特性和原理的介绍:

原理

BM25算法基于这样一个假设:对于一个特定的查询项,它在相关文档中出现的频率应该高于在非相关文档中的频率。该算法通过结合词项频率(TF)和文档频率(DF)来计算文档的得分。具体来说,BM25算法包括以下几个组成部分:

  1. 词项频率(TF):词项频率是指一个词项在文档中出现的次数。BM25对传统的TF计算方法进行了调整,引入了饱和度和长度归一化,以防止长文档由于包含更多词项而获得不公平的高评分。

  2. 逆文档频率(IDF):逆文档频率是衡量词项稀有程度的一个指标。它基于整个文档集合来计算,用来降低常见词项的权重,并提升罕见词项的权重。

  3. 文档长度信息:BM25算法引入了文档长度信息,以进一步调整相关性的计算。这样可以避免因为文档长度不同而导致的相关性偏差。

计算公式

BM25算法的计算公式可以表述为:

在这里插入图片描述

其中:

  • ( tf_{t,d} ) 是词项 ( t ) 在文档 ( d ) 中的词频;
  • ( IDF(t) ) 是词项 ( t ) 的逆文档频率;
  • ( k_1 ) 和 ( b ) 是自由参数,用于调节计算过程中的影响;
  • ( |d| ) 是文档 ( d ) 的长度;
  • ( avgdl ) 是文档集合中所有文档长度的平均值。

改进与变种

除了标准的BM25算法之外,还有几种重要的变种,如BM25FBM25L

  • BM25F:这是BM25的一个重要扩展,可以在多个文档域上进行计算。
  • BM25L:该变种考虑了文档长度对得分的影响,通过引入文档长度规范化项来平衡不同长度的文档。

应用场景

BM25算法因其在处理词频和相关性之间非线性关系上的优势,被广泛应用于搜索引擎和相关领域。在实际应用中,如Elasticsearch和Lucene这样的全文搜索引擎,默认使用的就是Okapi BM25算法。

总结来说,BM25算法是一种强大而灵活的信息检索算法,它通过对TF-IDF模型的改进,提高了搜索结果的相关性,同时通过引入文档长度因子等改进措施,增强了算法的实用性。

该检索技术的优缺点

LlamaIndex是一个基于语言模型(LLM)的开源信息检索系统,它提供了高效的数据索引和查询功能,适用于大规模文本数据集的快速检索。其中,BM25Retriever是LlamaIndex提供的一个检索器,它基于BM25算法,这是一种广泛使用的信息检索排序函数,专门用于文档检索,尤其擅长处理长文档和短查询。下面将详细探讨BM25Retriever在LlamaIndex中的优缺点。

优点

  1. 优化的TF-IDF: BM25Retriever是基于TF-IDF(词频-逆文档频率)的改进版本,它解决了标准TF-IDF方法的一些局限性,如长文档可能得到过高评分的问题。BM25通过调整参数k1和b来考虑文档长度的影响,从而使得检索结果更加准确。

  2. 文档长度的考虑: BM25Retriever的一个关键特性是它考虑了文档长度对评分的影响。对于长文档,BM25Retriever会调整评分,确保不会因为文档较长而产生不公平的优势,这有助于提高检索结果的相关性。

  3. 灵活性: BM25Retriever可以很容易地与其他检索技术相结合,例如与向量检索混合使用,形成一种称为混合检索的技术。这种组合可以利用各自的优势,提供更加全面的检索服务。

缺点

  1. 中文支持问题: 默认情况下,BM25Retriever的tokenizer可能不支持中文处理,这意味着在处理中文文本时需要额外的步骤或定制的解决方案,如使用jieba分词器来处理中文文本。

  2. 计算资源需求: 尽管BM25Retriever在文档检索方面表现优秀,但它需要进行大量的计算来确定文档与查询的相关性得分,尤其是在大型数据集中,这可能会导致较高的计算资源需求。

  3. 参数调优: BM25算法依赖于一些参数(如k1, b等),这些参数可能需要根据具体的应用场景进行调优才能达到最佳性能。如果不正确地设置这些参数,可能会影响检索结果的质量。

综上所述,BM25Retriever在LlamaIndex中提供了一种强大的检索机制,尤其适用于需要精确排序结果的应用场景。然而,在使用时需要注意其对于特定语言的支持情况以及可能产生的计算开销等问题。在实际应用中,根据具体的业务需求选择合适的检索器,并且合理地调整参数以优化性能是非常重要的。

LlamaIndex官方地址 https://docs.llamaindex.ai/en/stable/

快速上手

创建一个文件,例如“chainlit_chat”

mkdir chainlit_chat

进入 chainlit_chat文件夹下,执行命令创建python 虚拟环境空间(需要提前安装好python sdkChainlit 需要python>=3.8。,具体操作,由于文章长度问题就不在叙述,自行百度),命令如下:

python -m venv .venv
  • 这一步是避免python第三方库冲突,省事版可以跳过
  • .venv是创建的虚拟空间文件夹可以自定义

接下来激活你创建虚拟空间,命令如下:

#linux or mac
source .venv/bin/activate
#windows
.venv\Scripts\activate

在项目根目录下创建requirements.txt,内容如下:

chainlit
llama-index-core
llama-index-llms-dashscope
llama-index-embeddings-dashscope
llama-index-retrievers-bm25~=0.3.0

执行以下命令安装依赖:

pip install -r .\requirements.txt
  • 安装后,项目根目录下会多出.chainlit.files文件夹和chainlit.md文件

代码创建

只使用通义千问的DashScope模型服务灵积的接口

在项目根目录下创建.env环境变量,配置如下:

DASHSCOPE_API_KEY="sk-api_key"
  • DASHSCOPE_API_KEY 是阿里dashscope的服务的APIkey,代码中使用DashScope的sdk实现,所以不需要配置base_url。默认就是阿里的base_url。
  • 阿里模型接口地址 https://dashscope.console.aliyun.com/model

在项目根目录下创建app.py文件,代码如下:

import os
import time

import chainlit as cl
from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.retrievers.bm25 import BM25Retriever
from llama_index.core import (
    Settings,
    VectorStoreIndex,
    SimpleDirectoryReader, load_index_from_storage, StorageContext,
)
from llama_index.core.node_parser import SentenceSplitter
from llama_index.embeddings.dashscope import DashScopeEmbedding, DashScopeTextEmbeddingModels, \
    DashScopeTextEmbeddingType
from llama_index.llms.dashscope import DashScope, DashScopeGenerationModels

Settings.llm = DashScope(
    model_name=DashScopeGenerationModels.QWEN_TURBO, api_key=os.environ["DASHSCOPE_API_KEY"], max_tokens=512
)
Settings.embed_model = DashScopeEmbedding(
    model_name=DashScopeTextEmbeddingModels.TEXT_EMBEDDING_V2,
    text_type=DashScopeTextEmbeddingType.TEXT_TYPE_DOCUMENT,
)
Settings.node_parser = SentenceSplitter(chunk_size=512, chunk_overlap=20)
Settings.num_output = 512
Settings.context_window = 6000


@cl.cache
def get_vector_store_index():
    storage_dir = "./storage_bm25_512"
    if os.path.exists(storage_dir):
        storage_context = StorageContext.from_defaults(persist_dir=storage_dir)
        index = load_index_from_storage(storage_context)
    else:
        documents = SimpleDirectoryReader("./data_file").load_data(show_progress=True)
        node_parser = SentenceSplitter.from_defaults(chunk_size=512, chunk_overlap=20)
        nodes = node_parser.get_nodes_from_documents(documents)
        print(f"nodes: {len(nodes)}")
        index = VectorStoreIndex(nodes=nodes)
        index.storage_context.persist(persist_dir=storage_dir)
    return index


vector_store_index = get_vector_store_index()


@cl.on_chat_start
async def start():
    await cl.Message(
        author="Assistant", content="你好! 我是泰山AI智能助手. 有什么可以帮助你的吗?"
    ).send()


@cl.on_message
async def main(message: cl.Message):
    start_time = time.time()
    retriever = BM25Retriever.from_defaults(docstore=vector_store_index.docstore, similarity_top_k=5)
    query_engine = RetrieverQueryEngine.from_args(
        retriever, streaming=True
    )
    msg = cl.Message(content="", author="Assistant")
    res = await query_engine.aquery(message.content)
    async for token in res.response_gen:
        await msg.stream_token(token)
    print(f"代码执行时间: {time.time() - start_time} 秒")
    source_names = []
    for idx, node_with_score in enumerate(res.source_nodes):
        node = node_with_score.node
        source_name = f"source_{idx}"
        source_names.append(source_name)
        msg.elements.append(
            cl.Text(content=node.get_text(), name=source_name, display="side")
        )
    await msg.stream_token(f"\n\n **数据来源**: {', '.join(source_names)}")
    await msg.send()
  • 代码中的persist_dir=storage_dir 不设置的默认是 ./storage.
  • 代码中chunk_size是将长文档分割的文本块的大小,chunk_overlap 是和上下文本块的重合文本的大小。
  • 代码中 node_parser = HierarchicalNodeParser.from_defaults( node_parser_ids=node_parser_ids, node_parser_map=node_parser_map ) 可以简写为 node_parser = HierarchicalNodeParser.from_defaults() 会按照 [2048,512,128]三种层次分割,经过我测试不使用默认的效果会更好
  • similarity_top_k=5 返回5条最相关的数据

代码解读

这段代码是一个使用ChainLit框架构建的聊天机器人应用,它集成了向量数据库索引和检索功能,以从文档中检索信息并回答用户的问题。下面是代码的逐部分解释:

  1. 导入模块

    • ostime 是标准库模块,分别用于操作系统相关功能和计时功能。
    • chainlit as cl 用于创建交互式的Web应用程序。
    • llama_index 是一个用于构建索引、检索器和查询引擎的库,帮助处理文本数据并进行问答系统开发。
  2. 设置环境变量

    • 设置了DashScope的LLM(Language Model)和Embedding模型,并指定了使用的模型类型以及API密钥位置。这些设置是根据环境变量DASHSCOPE_API_KEY来获取的。
  3. 向量存储索引函数 (get_vector_store_index)

    • 这个函数首先检查是否存在一个持久化的存储目录。如果存在,则加载已有的索引;如果不存在,则读取指定目录下的文档,将其分割成节点,创建向量存储索引,并将其持久化到指定目录。
  4. 聊天开始时的事件处理器 (start)

    • 当聊天会话开始时,发送一条消息给用户作为问候。
  5. 接收消息时的事件处理器 (main)

    • 当收到用户的输入消息时,使用BM25检索器来检索最相关的文档,并通过RetrieverQueryEngine生成答案。
    • 使用异步生成器流式传输响应给用户,并记录每个源文档的信息,以便显示数据来源。

这段代码展示了一个基于文档检索的问答系统的实现方式,利用了现代语言模型的能力来生成高质量的回答。注意,在实际部署时需要确保环境变量DASHSCOPE_API_KEY已经正确设置,并且指定的数据文件夹路径是正确的。此外,还需确保所有依赖项已安装,并且与ChainLit框架兼容。

在项目根目录下创建data_file文件夹

在这里插入图片描述
将你的文件放到data_file文件夹下。
llama_index 库支持多种文件格式的加载,以便从中提取文本内容用于索引构建和后续的信息检索或问答任务。以下是一些常见的文件格式支持:

  1. 文本文件 (.txt):简单的纯文本文件。
  2. PDF 文件 (.pdf):便携文档格式,广泛用于书籍、报告等文档。
  3. Microsoft Word 文档 (.doc, .docx):Word 文档格式。
  4. CSV 文件 (.csv):逗号分隔值文件,常用于表格数据。
  5. HTML 文件 (.html, .htm):超文本标记语言文件。
  6. Markdown 文件 (.md, .markdown):轻量级标记语言。
  7. JSON 文件 (.json):JavaScript 对象表示法,常用于数据交换。
  8. EPUB 文件 (.epub):电子书格式。
  9. PPTX 文件 (.pptx):PowerPoint 演示文稿。

除了上述文件格式外,llama_index 可能还支持其他一些格式,具体取决于其内部依赖库的支持情况。例如,它可能通过第三方库支持解析像 .xls, .xlsx 这样的 Excel 文件。

为了加载这些不同类型的文件,llama_index 提供了多个不同的读取器(readers),如 SimpleDirectoryReader 可以用来加载一个目录中的多个文件,而针对特定文件格式(如 PDF 或 Word 文档),则有专门的读取器类。

例如,如果你有一个包含多种文件格式的目录,你可以使用 SimpleDirectoryReader 来加载它们。如果你只处理一种类型的文件,比如 PDF 文件,你可以选择使用更具体的读取器,比如 PDFReader

运行应用程序

要启动 Chainlit 应用程序,请打开终端并导航到包含的目录app.py。然后运行以下命令:

 chainlit run app.py -w   
  • -w标志告知 Chainlit 启用自动重新加载,因此您无需在每次更改应用程序时重新启动服务器。您的聊天机器人 UI 现在应该可以通过http://localhost:8000访问。
  • 自定义端口可以追加--port 80

启动后界面如下:

在这里插入图片描述
在这里插入图片描述
BM25Retriever索引器还可以与向量检索器等其他索引器,利用QueryFusionRetriever类将其融合查询。

后续会出更多关于LlamaIndex高级检查的技术文章教程,感兴趣的朋友可以持续关注我的动态!!!

相关文章推荐

《Chainlit快速实现AI对话应用的界面定制化教程》
《Chainlit接入FastGpt接口快速实现自定义用户聊天界面》
《使用 Xinference 部署本地模型》
《Fastgpt接入Whisper本地模型实现语音输入》
《Fastgpt部署和接入使用重排模型bge-reranker》
《Fastgpt部署接入 M3E和chatglm2-m3e文本向量模型》
《Fastgpt 无法启动或启动后无法正常使用的讨论(启动失败、用户未注册等问题这里)》
《vllm推理服务兼容openai服务API》
《vLLM模型推理引擎参数大全》
《解决vllm推理框架内在开启多显卡时报错问题》
《Ollama 在本地快速部署大型语言模型,可进行定制并创建属于您自己的模型》

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

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

相关文章

OpenHarmony(鸿蒙南向)——平台驱动开发【Regulator】

往期知识点记录: 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~ 持续更新中…… 概述 功能简介 Regulator模块用于控制系统中各类设备的电压/电流…

大数据毕业设计选题推荐-豆瓣电子图书推荐系统-数据分析-Hive-Hadoop-Spark

✨作者主页:IT毕设梦工厂✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、PHP、.NET、Node.js、GO、微信小程序、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇…

17年数据结构考研真题解析

第一题&#xff1a; 解析&#xff1a; 我们说递归要找出口&#xff0c;这道题的出口是sum<n&#xff0c;经过观察可以得知&#xff1a;sum123。。。k 设第k次循环跳出&#xff0c;则有sum123。。。k<n k<,很显然答案选B 第二题&#xff1a; 解析&#xff1a; 第一句&a…

10.Lab Nine —— file system-下

Symbolic links 添加符号链接 1.添加有关symlink系统调用的定义声明&#xff0c;包括kernel/syscall.h, kernel/syscall.c, user/usys.pl 和 user/user.h. 2.添加新的文件类型T_SYMLINK到kernel/stat.h中&#xff0c;添加新的文件标识位O_NOFOLLOW到kernel/fcntl.h中 3.在ken…

Rust和Go谁会更胜一筹

在国内&#xff0c;我认为Go语言会成为未来的主流&#xff0c;因为国内程序员号称码农&#xff0c;比较适合搬砖&#xff0c;而Rust对心智要求太高了&#xff0c;不适合搬砖。 就个人经验来看&#xff0c;Go语言简单&#xff0c;下限低&#xff0c;没有什么心智成本&#xff0c…

828华为云征文|华为云Flexus X实例Windows Server 2019安装护卫神防火墙——为企业运维安全发挥重要作用!!!

前言 公司最近需要选购一台华为云Windows服务器部署产品应用&#xff0c;但是考虑到Windows的安全性至关重要。护卫神防火墙无疑是守护Windows系统安全的得力助手。 华为云以其强大的性能和稳定的服务&#xff0c;为众多企业和开发者提供了可靠的云端基础设施。在网络环境日益复…

微信小程序-分包加载

文章目录 微信小程序-分包加载概述基本使用打包和引用原则独立分包分包预下载 微信小程序-分包加载 概述 小程序的代码通常是由许多页面、组件以及资源等组成&#xff0c;随着小程序功能的增加&#xff0c;代码量也会逐渐增加&#xff0c;体积过大就会导致用户打开速度变慢&a…

python --qt5(webview)/防多开/套壳网页/多次点击激活旧窗口

pyqtwebengine=5.12 PyQt5==5.12class MyWindow(QMainWindow):def __init__(self):super(MyWindow, self).__init__()self.browser = QWebEngineView(self) # 如果不写self则新生成一个窗口self.browser.setWindowTitle(技术领域占比分析)self.browser.setWindowIcon(QIcon(LO…

嵌入式linux裸机调试之windows、linux联合gdb

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、gdb-multiarch安装二、windows、linux联合gdb1.windows下启动JLinkGDBServer.exe2.Linux下…

Axure原型系统:药企内部管理平台原型设计

在当今竞争激烈的医药行业中&#xff0c;高效的内部管理系统是企业成功的关键之一。为了满足药企对市场部与销售部精细化管理的需求&#xff0c;我们精心设计了一款基于Axure RP的药企内部管理平台原型。这款原型以管理员角色为核心&#xff0c;旨在通过直观、高效的界面和强大…

Linux系统重启后MySQL数据丢失问题的解决(磁盘挂载)

今天分享一个在Linux系统中经常遇到的问题:系统重启后发现MySQL无法启动,而且数据似乎丢失了。这个问题可能会让人惊慌失措,但别担心,通常情况下这只是因为数据盘没有正确挂载导致的。现在我们将深入探讨这个问题的原因、解决方法以及如何预防它的再次发生。 1 问题描述 想象一…

HTTP Status 404 - /brand-demo/selectAllServlet错误解决原因-Servlet/JavaWeb/IDEA

检查xml文件的包名有无错误检查html文件的url有无写错&#xff0c;是否与Servlet的urlPatterns一致检查Servlet的urlpattern有没有写错(如写成name),检查doPost、doGet是否正常运行 注&#xff1a;IDEA新建Servlet时&#xff0c;默认的WebServlet注解中name需要改urlPatterns&…

创意实现!在uni-app小程序商品详情页轮播中嵌入视频播放功能

背景介绍 通过uni-app框架实现商城小程序商品详情页的视频与图片轮播功能&#xff0c;以提升用户体验和增加商品吸引力。通过展示商品视频和图片&#xff0c;用户可以更全面地了解商品细节&#xff0c;从而提高购买决策的便利性和满意度。这种功能适用于各类商品&#xff0c;如…

【SQL】产品分组销售

目录 语法 需求 示例 分析 代码 语法 GROUP_CONCAT(DISTINCT expression1 ORDER BY expression2 SEPARATOR sep&#xff09; GROUP_CONCAT 是 SQL 中的一个聚合函数&#xff0c;主要用于将分组后的多个行的值连接成一个字符串。这个函数在 MySQL 和一些其他数据库管理系统…

VBA技术资料MF203:添加带图标的右键菜单

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

ctf.show---->re2

做题笔记。 下载 查壳 32 ida打开。 WSL先运行一下&#xff1a; &#xff1f; 创建呗。 函数如下&#xff1a; 逻辑很清晰&#xff0c;写脚本咯 &#xff1a; #include <stdio.h> #include <string.h> #include <stdlib.h>int main() {char encode[] &qu…

计算机毕业设计 养老院管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

活动策划灵感TOP10分享-华媒舍

活动策划对于推广品牌、提升知名度和增加销量具有重要的作用。在当今竞争激烈的市场中&#xff0c;如何设计出与众不同、令人难以忘怀的活动策划方案是每个市场人员关心的问题。本文将介绍10个非凡的创意灵感&#xff0c;帮助您在活动策划中取得成功。 1. 主题游戏夜 通过组织…

阿里云云效多个ssh密钥对配置

实现功能 windows本地多个ssh密钥对,分别对应不同的阿里云账号的云效 实现办法 1.生成ssh密钥对 ssh-keygen -t rsa -f C:\xxx\id_rsa_customname(我这里C:\Users\admin\.ssh\id_rsa_customname) 2.配置.ssh目录的config文件 # ruiyi Host customnameHostName codeup.al…

IPSec隧道协议学习(一)

前情回顾 前面介绍的GRE隧道协议&#xff0c;可以字LAN之间通过Internet建立隧道&#xff0c;实现网络间资源共享&#xff0c;但是GRE隧道协议不能实现加密功能&#xff0c;传输的数据不受加密保护&#xff0c;为了实现在隧道间传输数据包收到加密保护&#xff0c;需要使用IPS…