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.rhkb.cn/news/435922.html

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

相关文章

第18章 中断和异常的处理与抢占式多任务

第18章 中断和异常的处理与抢占式多任务 中断和异常 中断和异常概述 中断(Interrupt): 硬件中断是由外围硬件设备发出的中断信号引发的,以请求处理器提供服务。软中断是由int n指令引发的中断处理,n是中断号或者叫…

【Python】数据可视化之分布图

分布图主要用来展示某些现象或数据在地理空间、时间或其他维度上的分布情况。它可以清晰地反映出数据的空间位置、数量、密度等特征,帮助人们更好地理解数据的内在规律和相互关系。 目录 单变量分布 变量关系组图 双变量关系 核密度估计 山脊分布图 单变量分布…

5.数据结构与算法-类C语言的有关操作

元素类型说明 数组定义 C语言的动态内存分配 C动态存储分配 C的参数传递 传值方式 传地址方式 形参变化影响实参 形参变化不影响实参 数组名做参数 引用类型做参数

高通AI应用程序开发3:网络模型(一)

1. 支持的网络模型 Qualcomm神经处理SDK支持下表所列的网络模型。 有关支持的运行时和单个图层类型的限制和约束的详细信息,请参阅 限制 。 GPU运行时中支持的所有层对两种GPU模式都有效:GPU_FLOAT32_16_HYBRID和GPU_FLAAT16。GPU_FLOAT32_16_HYBRID-…

【刷点笔试面试题试试水】找错—使用strlen()函数代替sizeof计算字符串长度

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: #include <iostream> using namespace std;void UpperCase(ch…

Qt Linguist手册-翻译员

翻译人员 Qt Linguist 是为 Qt 应用程序添加翻译的工具。一旦安装了 Qt&#xff0c;就可以像开发主机上的其他应用程序一样启动 Qt Linguist。 Qt Linguist 主窗口包含一个菜单栏和以下视图&#xff1a; 上下文 (F6) 用于从上下文列表中选择要翻译的字符串。字符串 (F7) 用于…

信号处理快速傅里叶变换(FFT)的学习

FFT是离散傅立叶变换的快速算法&#xff0c;可以将一个信号变换到频域。有些信号在时域上是很难看出什么特征的&#xff0c;但是如果变换到频域之后&#xff0c;就很容易看出特征了。这就是很多信号分析采用FFT变换的原因。另外&#xff0c;FFT可以将一个信号的频谱提取出来&am…

leetcode每日一题day19(24.9.29)——买票需要的时间

思路&#xff1a;在最开始的情况下每人需要买的票数减一是能保持相对位置不变的&#xff0c; 如果再想减一就有可能 有某些人只买一张票&#xff0c;而离开了队伍&#xff0c; 所有容易想到对于某个人如果比当前的人买的多就按当前的人数量算 因为在一次次减一的情况下&#xf…

从零开始手写STL库:Stack

从零开始手写STL库–Stack的实现 Gihub链接&#xff1a;miniSTL 文章目录 从零开始手写STL库–Stack的实现一、stack是什么&#xff1f;二、stack要包含什么函数总结 一、stack是什么&#xff1f; 栈是一种后进先出&#xff08;LIFO&#xff0c;Last In First Out&#xff09…

计算机网络--TCP、UDP抓包分析实验

计算机网络实验 目录 实验目的 实验环境 实验原理 1、UDP协议 2、TCP协议 实验具体步骤 实验目的 1、掌握使用wireshark工具对UDP协议进行抓包分析的方法&#xff0c;掌握UDP协议的报文格式&#xff0c;掌握UDP协议校验和的计算方法&#xff0c;理解UDP协议的优缺点&am…

【数据库文档】数据库设计说明书(Word原件参考)

一、 总述 &#xff08;一&#xff09; 编写目的 二、 外部设计 &#xff08;一&#xff09; 环境说明 &#xff08;二&#xff09; 指导 三、 物理实现 &#xff08;一&#xff09; 物理结构 &#xff08;二&#xff09; 安全设计 四、 表设计结构 &#xff08;一&#xff09;…

SpringAOP学习

面向切面编程&#xff0c;指导开发者如何组织程序结构 增强原始设计的功能 oop:面向对象编程 1.导入aop相关坐标&#xff0c;创建 <!--spring依赖--><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spri…

Python 读取与处理出入库 Excel 数据实战案例(HTML 网页展示)

有如下数据&#xff0c;需要对数据合并处理&#xff0c;输出到数据库。 数据样例&#xff1a;&#x1f447; excel内容&#xff1a; 出入库统计表河北库.xlsx: 出入库统计表天津库.xlsx: 01实现过程 1、创建test.py文件&#xff0c;然后将下面代码复制到里面&#xff0c;最后…

广西容县霞烟鸡,品牌兴农,助力乡村振兴!

在两广与港澳地区,流传着一句深入人心的饮食谚语——“无鸡不成宴”,它不仅是一种习俗的体现,更是对餐桌礼仪与待客之道的深刻诠释。每逢家宴欢聚、祭祖庆典或盛宴宾客,一只精心烹制的鸡总是不可或缺的主角,其缺席往往被视为对宾客的不敬。在这片美食文化的沃土上,广西容县的霞…

个性化大语言模型:PPlug——让AI更懂你

在当今数字化转型的时代&#xff0c;大型语言模型&#xff08;LLMs&#xff09;已经成为了不可或缺的工具&#xff0c;它们在自然语言理解、生成和推理方面展现了非凡的能力。然而&#xff0c;这些模型普遍采用的是“一刀切”的方式&#xff0c;即对于相同的输入给予所有用户相…

uniapp监听滚动实现顶部透明度变化

效果如图&#xff1a; 实现思路&#xff1a; 1、使用onPageScroll监听页面滚动&#xff0c;改变导航条的透明度&#xff1b; 2、关于顶部图片的高度&#xff1a; 如果是小程序&#xff1a;使用getMenuButtonBoundingClientRect获取胶囊顶部距离和胶囊高度&#xff1b; 如果…

YOLOv8改进 - 注意力篇 - 引入SCAM注意力机制

一、本文介绍 作为入门性篇章&#xff0c;这里介绍了SCAM注意力在YOLOv8中的使用。包含SCAM原理分析&#xff0c;SCAM的代码、SCAM的使用方法、以及添加以后的yaml文件及运行记录。 二、SCAM原理分析 SCAM官方论文地址&#xff1a;SCAM文章 SCAM官方代码地址&#xff1a;SC…

Google Protocol Buffers快速入门指南

声明&#xff1a;未经作者允许&#xff0c;禁止转载。 概念 Portocol Buffer是谷歌提出来的一种序列化结构数据的机制&#xff0c;它的可扩展性特别强&#xff0c;支持C、C#、Java、Go和Python等主流编程语言。使用Portocol Buffer时&#xff0c;仅需要定义好数据的结构化方式…

Mysql梳理10——使用SQL99实现7中JOIN操作

10 使用SQL99实现7中JOIN操作 10.1 使用SQL99实现7中JOIN操作 本案例的数据库文件分享&#xff1a; 通过百度网盘分享的文件&#xff1a;atguigudb.sql 链接&#xff1a;https://pan.baidu.com/s/1iEAJIl0ne3Y07kHd8diMag?pwd2233 提取码&#xff1a;2233 # 正中图 SEL…

每日OJ题_牛客_添加逗号_模拟_C++_Java

目录 牛客_添加逗号_模拟 题目解析 C代码1 C代码2 Java代码 牛客_添加逗号_模拟 添加逗号_牛客题霸_牛客网 题目解析 读取输入&#xff1a;读取一行字符串。分割字符串&#xff1a;使用空格将字符串分割成单词数组。拼接字符串&#xff1a;将单词数组中的每个单词用逗号…