Chainlit集成LlamaIndex实现知识库高级检索(组合对象检索)

检索原理

对象组合索引的原理 是利用IndexNode索引节点,将两个不同类型的检索器作为节点对象,使用 SummaryIndex (它可以用来构建一个包含多个索引节点的索引结构。这种索引通常用于从多个不同的数据源或索引方法中汇总信息,并能够基于这些信息进行更复杂的查询操作,如摘要生成。)当查询SummaryIndex时,它会考虑所有包含在内的索引节点,并根据需要综合它们的信息来生成最终的响应或摘要。

组合对象索引检索器的优缺点

结合向量检索(Vector Retrieval)和BM25检索的方式,具有其独特的优点和缺点。下面是对这两种检索方式及其组合使用的优缺点的概述:

向量检索(Vector Retrieval)

优点:
  1. 语义理解:向量检索基于嵌入模型,能够更好地理解文本之间的语义关系,而不仅仅是关键字匹配。
  2. 上下文感知:向量检索可以捕捉句子或段落之间的上下文关系,对于长文本的理解更为有效。
  3. 泛化能力:即使查询词不在文档中出现,只要语义上相关,也可以找到相关的文档。
缺点:
  1. 计算成本:向量检索需要对文档进行嵌入编码,这可能会增加计算资源的需求。
  2. 索引维护:维护一个大型的向量索引可能较为复杂,并且随着文档数量的增加,索引的更新和存储可能变得昂贵。
  3. 精确度依赖于模型质量:向量检索的效果高度依赖于所使用的嵌入模型的质量,如果模型训练不当,效果可能会大打折扣。

BM25 检索

优点:
  1. 简单高效:BM25是一种基于统计的检索模型,不需要复杂的机器学习模型即可实现高效的文档检索。
  2. 可解释性强:因为它是基于关键词频率和文档频率等统计特征,所以结果更容易理解和解释。
  3. 广泛支持:许多搜索引擎和数据库系统已经内置了BM25支持,易于集成。
缺点:
  1. 缺乏语义理解:BM25主要依赖关键词匹配,对于文本的深层语义理解不如向量检索。
  2. 短查询局限性:对于短的或非常特定的查询,BM25可能无法提供最佳的相关性排序。
  3. 忽略上下文:BM25没有考虑到句子或段落之间的上下文关系,这可能导致某些情况下相关性较低。

组合使用的优势

  1. 互补优势:结合两种方法可以在保持简单高效的检索速度的同时,提高检索结果的相关性和准确性。
  2. 灵活性:可以根据具体应用场景灵活调整检索策略,比如对于某些需要强语义理解的任务,可以更依赖向量检索;而对于简单的关键词搜索,可以更多地使用BM25。
  3. 鲁棒性增强:通过融合两种检索方式,可以降低单一方法带来的风险,提高系统的整体性能。

组合使用的挑战

  1. 复杂性增加:维护两种检索机制会增加系统的复杂性,包括数据预处理、索引构建、查询处理等多个环节。
  2. 权衡问题:如何平衡两种检索方法的贡献度是一个需要仔细设计的问题,可能需要通过实验和调参来优化。
  3. 性能开销:虽然理论上可以提高检索质量,但在实际部署中可能需要考虑额外的计算资源消耗。

总的来说,结合向量检索和BM25检索可以利用各自的优势,以期达到更好的检索效果。但在实际应用中,需要根据具体需求和资源条件来进行权衡和选择。

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

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文件,代码如下:

  • 此代码使用摘要索引和向量索引,利用RetrieverQueryEngine 路由检索器,根据问题分类提示,选择摘要索引和向量索引进行索引。
import os
import timeimport chainlit as cl
from llama_index.core import (Settings,VectorStoreIndex,load_index_from_storage, StorageContext, SimpleDirectoryReader, SummaryIndex, )
from llama_index.core.node_parser import SentenceSplitter
from llama_index.core.schema import IndexNode
from llama_index.embeddings.dashscope import DashScopeEmbedding, DashScopeTextEmbeddingModels, \DashScopeTextEmbeddingType
from llama_index.llms.dashscope import DashScope, DashScopeGenerationModels
from llama_index.retrievers.bm25 import BM25RetrieverSettings.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_obj"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)index = VectorStoreIndex.from_documents(documents)index.storage_context.persist(persist_dir=storage_dir)return indexvector_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()vector_retriever = vector_store_index.as_retriever(similarity_top_k=5)bm25_retriever = BM25Retriever.from_defaults(docstore=vector_store_index.docstore, similarity_top_k=5)vector_obj = IndexNode(index_id="vector", obj=vector_retriever, text="Vector Retriever")bm25_obj = IndexNode(index_id="bm25", obj=bm25_retriever, text="BM25 Retriever")summary_index = SummaryIndex(objects=[vector_obj, bm25_obj])query_engine = summary_index.as_query_engine(response_mode="tree_summarize", streaming=True, verbose=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.nodesource_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 是和上下文本块的重合文本的大小。
  • 代码中IndexNode是索引节点
    • IndexNode对象
      在代码片段中,vector_obj和bm25_obj都是IndexNode实例。每个IndexNode对象包含了三个主要属性:

      • index_id:索引的唯一标识符。
      • obj:实际的检索对象,这里是指向实际检索逻辑的对象,例如vector_retriever或bm25_retriever。
      • text:描述性文本,用于标识节点的作用

代码解读

这段代码是一个使用Chainlit框架构建的简单聊天机器人应用,它集成了向量检索(Vector Retrieval)和BM25检索机制,并使用了来自DashScope的LLM(Large Language Model)和服务。下面是代码的详细解释:

  1. 导入模块

    • 导入了ostime模块用于操作系统路径和计时。
    • chainlit是一个用于快速构建交互式AI应用的Python库。
    • llama_index提供了一系列工具用于创建和查询知识库索引。
  2. 设置LLM和Embedding模型

    • 设置了DashScope作为默认的LLM和Embedding模型,并指定了API密钥和模型名称。
    • 这些设置影响了如何处理文本输入以及如何生成响应。
  3. 定义获取向量存储索引的函数get_vector_store_index

    • 如果指定的存储目录存在,则从存储加载索引。
    • 否则,从指定的数据目录读取文档来创建一个新的向量存储索引并保存到存储目录中。
  4. 定义聊天开始时触发的函数start

    • 发送一条欢迎消息给用户。
  5. 定义处理用户消息的函数main

    • 创建一个向量检索器和一个BM25检索器,两者都设置为返回前5个最相似的结果。
    • 创建两个IndexNode对象,分别代表向量检索器和BM25检索器。
    • 创建一个SummaryIndex来包含这两个检索器节点。
    • 使用这个总结索引来创建一个查询引擎,该引擎以树状总结模式运行,并且支持流式传输结果。
    • 对于用户的每条消息,使用查询引擎异步查询,并通过流式传输的方式发送每个token给用户。
    • 记录并打印查询所需的时间。
    • 收集并显示源文档的名字作为数据来源。

    代码展示了一个完整的流程,从加载或创建索引,到处理用户输入,再到生成并发送响应。这是一个典型的问答系统的实现方式,特别是当需要从大量的文档中提取信息时。

在项目根目录下创建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

启动后界面如下:

在这里插入图片描述
在这里插入图片描述

总结

在chunk_size大小为512,chunk_overlap为20时,整体回复表现良好。但是也有很大的局限性,模型在选择问题时,能否正确选择,这个变得很关键,但实际上往往很难做到正确选择,就比如,我提问2023年的财务报表,模型会倾向于这是一个总结摘要类的问题,会去摘要索引里查找,但是实际上023年的财务报表数据实在向量索引存储的。

相关文章推荐

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

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

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

相关文章

golang学习笔记19-面向对象(一):面向对象的引入

注:本人已有C,C,Python基础,只写本人认为的重点。 这节开始就是面向对象的内容了,为方便复用结构体等类型,本人定义了一个utils包,用于定义这些类型,之后的文章也会用到,希望读者注意…

Java如何将Object转换成指定Class对象

在Java中,将Object转换为指定类型的Class对象实际上是两个不同概念的操作: 将Object实例转换为特定类型的实例:这通常涉及到类型转换(如(MyType) myObject)或者通过反射机制(Class.cast(Object)&#xff0…

后端开发如何提高项目系统的性能

引言 提高后端PHP开发系统的性能可以从多个维度进行,例如通过代码优化、缓存优化、数据库优化、异步处理和消息队列、服务器优化、内容分发网络(CDN)的应用以及系统安全性的强化。 本文主要介绍如何通过以上方法对系统进行优化,…

删除搜狗拼音输入法,右键菜单打印及pdf操作

删除搜狗拼音输入法流氓右键菜单打印及pdf操作: 1、注册表分别搜以下字段,全部删除,可用Registry Workshop 方便搜索: {7BCE96FA-77AF-4288-9E16-2388A50EC807} {85212cfd-77ed-4add-8e24-a0a39e3dbfc3} {1BB732FA-391B-4648-BC00…

【TabBar嵌套Navigation案例-新特性页面-介绍图片 Objective-C语言】

一、接下来,我们接着来说这个介绍图片啊, 1.看一下我们的示例程序,在这一块儿,有一些介绍图片, 这个飞镖的盘子,全新娱乐场,疯狂什么玩意儿,这些东西呢,实际上,都是我们的素材啊,在素材里边,Guide里边,我们这儿有一个guide1, Open With External Editor,这张图片…

MobaXterm基本使用 -- 服务器状态、批量操作、显示/切换中文字体、修复zsh按键失灵

监控服务器资源 参考网址:https://www.cnblogs.com/144823836yj/p/12126314.html 显示效果 MobaXterm提供有这项功能,在会话窗口底部,显示服务器资源使用情况 如内存、CPU、网速、磁盘使用等: (完整窗口&#xff0…

经典sql题(十四)炸裂函数的恢复

下面是一个关于 SELECT 语句的例子,该示例展示了如何使用 CONCAT_WS 和 COLLECT_LIST 函数来处理炸裂之后学生成绩的数据。假设我们有一个名为 test 的表,结构如下: 表结构 test student_idstudent_nameclassscore1AliceClass1901AliceClas…

蓝桥杯—STM32G431RBT6(RTC时钟获取时间和日期)

一、RTC是什么,有什么用? 在 STM32 中,RTC(Real-Time Clock,实时时钟)主要有以下作用: 时间保持:即使在系统断电情况下,也能持续记录时间。(需要纽扣电池供电…

【2.使用VBA自动填充Excel工作表】

目录 前言什么是VBA如何使用Excel中的VBA简单基础入门控制台输出信息定义过程(功能)定义变量常用的数据类型Set循环For To 我的需求开发过程效果演示文件情况测试填充源文件测试填充目标文件 全部完整的代码sheet1中的代码,对应A公司工作表Us…

简易CPU设计入门:取指令(一),端口列表与变量声明

取指令这一块呢,个人觉得,不太好讲。但是呢,不好讲,我也得讲啊。那就尽量地讲吧。如果讲得不好的话,那么,欢迎大家提出好的意见,帮助我改进讲课的质量。 首先呢,还是请大家去下载本…

ip 地址查看cmd命令

ip 地址查看cmd命令 在不同的操作系统中,查看IP地址的命令可能会有所不同。以下是一些常见操作系统中查看IP地址的命令: Windows: 打开命令提示符(CMD),然后输入 ipconfig 命令。 Linux/Unix: 打开终端&#xff0…

【ARM 嵌入式 编译系列 2.8 -- GCC 编译优化参数 位置无关码】

请阅读【嵌入式开发学习必备专栏 之 ARM GCC 编译专栏】 文章目录 ARM GCC 位置无关码-fpic 编译选项无位置相关码(PIC)为什么使用 PIC?代码示例编译为目标文件链接为共享库使用共享库ARM 汇编中位置无关码编译为目标文件链接为共享库使用共享库详细解释ARM GCC 位置无关码 …

【AI大模型-文心-思维树解读-仓颉精通之路-4】

提问:对于每个解决方案,加深思考过程。生成潜在场景、实施策略、任何必要的资源、如何克服障碍与风险以及意外结果和意外结果的处理 回答:如下 版本:文心大模型3.5 解决方案一:系统化自学方案 潜在场景: …

【专题】2024年中国白酒行业数字化转型研究报告合集PDF分享(附原数据表)

原文链接:https://tecdat.cn/?p37755 消费人群趋于年轻化,消费需求迈向健康化,消费场景与渠道走向多元化,这些因素共同驱动企业凭借数据能力来适应市场的变化。从消费市场来看,消费群体、需求、场景及渠道皆展现出与…

Android中的Activity生命周期和启动流程及优化策略

目录 第一章 Activity生命周期概述 1.1 生命周期概念及状态 1.1.1 生命周期概念 1.1.2 状态转换 1.2 生命周期回调方法 1.2.1 关键回调方法 1.2.2 回调方法的作用 1.3 生命周期管理策略 1.3.1 合理管理资源 1.3.2 优化加载过程 第二章 Activity启动流程详解 2.1 Ac…

GIS中的投影坐标系

投影说明 GIS操作过程中,不可避免的涉及到处理数据的问题 而数据中有一个极为重要的东西就是其空间参考(见下图) 地理坐标系与投影坐标系 这里给出一些重要概念的简单定义 地理坐标:就是用经纬度表示地面点位的球面坐标。 地理…

Java项目实战II基于Java+Spring Boot+MySQL的新闻稿件管理系统(源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 前在信息爆…

飞腾CPU运行RTEMS6.0

1. 介绍 RTEMS (Real-Time Executive for Multiprocessor Systems) 是一个开源实时操作系统,可以用于太空飞行、医疗、网络和各类嵌入式设备。本项目发布了 Phytium 系列 CPU 的 RTEMS内核/RTEMS-LibBSD 源码使用工具,参考例程以及配置构建工具。 飞腾R…

在 NodeJs 里面如何获取 APK 的名称和 icon

最近想用 electron 写一个 adb 的可视化客户端,在展示安装的应用时遇到了如何获取 APK 的名称和 icon 的问题。下面就是一些解决问题的思路。 前提:在这里默认大家已经下载好 apk, 下面 localApkPath 就是你下载好的 apk 的路径。 小提示,示…

js采用覆盖键、覆盖鼠标滑动事件实现禁止网页通过 ctrl + +/- 和 ctrl + 滚轮 对页面进行缩放

一、兼容电脑端的禁止通过 ctrl /- 和 ctrl 滚轮 对页面进行缩放 const keyCodeMap {// 91: true, // command61: true,107: true, // 数字键盘 109: true, // 数字键盘 -173: true, // 火狐 - 号187: true, // 189: true, // -};二、覆盖ctrl||command ‘’/‘-’ // 覆…