Chainlit集成LlamaIndex实现知识库高级检索(路由检索器)

news/2024/11/16 22:11:01/

检索原理

llamaindex 是一个用于构建和部署基于文档的问答系统的框架。其中,RouterRetriever 是一个特定的检索器组件,它设计用于根据输入查询选择最佳的检索策略。RouterRetriever 的主要功能是在多个不同的检索器之间进行路由,根据输入的特性选择最适合的检索器来处理请求。下面是 RouterRetriever 的检索原理概览:

  1. 多策略支持RouterRetriever 可以集成多种检索策略,比如基于关键词的检索、基于向量相似性的检索、甚至是更复杂的多模态检索方法。每种策略都有其特定的优势场景。

  2. 输入分析:当接收到一个查询时,RouterRetriever 会对输入进行分析,这可能包括理解查询的意图、识别查询的关键元素或者是评估查询的复杂性等。

  3. 策略选择:根据输入分析的结果,RouterRetriever 决定哪一个检索策略最适合当前查询。这个决策过程可能会依据预先定义的规则或通过机器学习模型来实现。

  4. 路由执行:一旦确定了最佳策略,RouterRetriever 就会将查询传递给相应的检索器。检索器然后根据其特定的方法来执行检索操作。

  5. 结果整合:如果使用了多个检索策略,则 RouterRetriever 可能还需要负责整合不同检索器返回的结果,以便提供一个统一的答案或结果集给用户。

  6. 反馈优化:一些高级的 RouterRetriever 实现可能会包含反馈机制,允许系统根据用户的反馈调整其路由决策逻辑,从而不断优化选择策略的能力。

这种设计的好处在于它能够灵活地适应不同类型的数据源和查询需求,通过智能地选择最适合的检索策略来提高检索的准确性和效率。同时,这也意味着 RouterRetriever 需要有一个强大的输入理解和策略选择机制,以确保每次都能做出正确的决策。

RouterRetriever检索器的优缺点

RouterRetriever 是一种用于在多个检索策略之间进行智能路由的检索器,它的主要目标是根据输入查询的特点选择最优的检索策略。下面分别概述 RouterRetriever 的优点和缺点:

优点

  1. 灵活性RouterRetriever 可以整合多种检索技术,如基于关键词的检索、基于向量的检索等,因此能够在面对不同类型的查询时选择最合适的方法。

  2. 性能优化:通过智能选择检索策略,RouterRetriever 可以减少不必要的计算负担,从而提高整体检索性能。

  3. 适应性强:它可以针对不同场景和数据类型进行优化,适用于多种应用场景,如问答系统、信息检索等。

  4. 扩展性好:随着新的检索技术和策略的发展,RouterRetriever 可以轻松地添加新的检索器,从而增强系统的功能。

  5. 个性化推荐:通过学习用户的查询习惯和偏好,RouterRetriever 可以为用户提供更加个性化的检索体验。

缺点

  1. 复杂性增加:由于需要集成多种检索策略并进行智能路由,RouterRetriever 的实现和维护相对复杂,增加了系统的复杂度。

  2. 决策难度:正确地选择合适的检索策略需要强大的输入理解和决策机制,这本身就是一个挑战,特别是在面对模糊或多样化的查询时。

  3. 训练成本:如果使用机器学习模型来辅助决策,那么需要收集大量的训练数据,并且训练模型可能会消耗较多的时间和资源。

  4. 潜在延迟:虽然理论上 RouterRetriever 能够提高检索效率,但在实际应用中,额外的决策层可能会引入一定的延迟,尤其是在系统负载较高时。

  5. 依赖质量RouterRetriever 的表现依赖于所集成的各种检索器的质量及其相互之间的协调性。如果某个检索器表现不佳,可能会影响到整个系统的性能。

总体而言,RouterRetriever 提供了一种灵活的方式来管理不同检索策略,但同时也带来了一些管理和技术上的挑战。正确地设计和实现 RouterRetriever 对于发挥其优势至关重要。

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,SimpleDirectoryReader, load_index_from_storage, StorageContext, SummaryIndex, )
from llama_index.core.node_parser import SentenceSplitter
from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.core.retrievers import RouterRetriever
from llama_index.core.selectors import LLMMultiSelector
from llama_index.core.tools import RetrieverTool
from llama_index.embeddings.dashscope import DashScopeEmbedding, DashScopeTextEmbeddingModels, \DashScopeTextEmbeddingType
from llama_index.llms.dashscope import DashScope, DashScopeGenerationModelsSettings.llm = DashScope(model_name=DashScopeGenerationModels.QWEN_MAX, 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_summary_index"if os.path.exists(storage_dir):summary_storage_context = StorageContext.from_defaults(persist_dir="./storage_summary_index")summary_index1 = load_index_from_storage(summary_storage_context)vector_storage_context = StorageContext.from_defaults(persist_dir="./storage_vector_index")vector_index1 = load_index_from_storage(vector_storage_context)else:documents = SimpleDirectoryReader("./data_file").load_data(show_progress=True)summary_index1 = SummaryIndex.from_documents(documents)vector_index1 = VectorStoreIndex.from_documents(documents)summary_index1.storage_context.persist(persist_dir="./storage_summary_index")vector_index1.storage_context.persist(persist_dir="./storage_vector_index")return summary_index1, vector_index1summary_index, vector_index = get_vector_store_index()DEFAULT_SUMMARY_TEXT = "Use this index for summarization queries"
DEFAULT_QA_TEXT = ("Use this index for queries that require retrieval of specific ""context from documents."
)@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()summary_retriever = summary_index.as_retriever(streaming=True, similarity_top_k=5, response_mode="tree_summarize")vector_retriever = vector_index.as_retriever(streaming=True, similarity_top_k=5)list_tool = RetrieverTool.from_defaults(retriever=summary_retriever,description=DEFAULT_SUMMARY_TEXT,)vector_tool = RetrieverTool.from_defaults(retriever=vector_retriever,description=DEFAULT_QA_TEXT,)retriever = RouterRetriever(selector=LLMMultiSelector.from_defaults(),retriever_tools=[list_tool,vector_tool,],verbose=True)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.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 是和上下文本块的重合文本的大小。
  • RouterRetriever 中selector选择器总共有四种,分别是
    • LLMSingleSelector LLM单选选择器(任意模型的抽象对象都能使用)
    • LLMMultiSelector LLM多选选择器(任意模型的抽象对象都能使用)
    • PydanticSingleSelector Pydantic单选选择器 (只能open ai的模型才能使用)
    • PydanticMultiSelector Pydantic多选选择器(只能open ai的模型才能使用)

代码解读

这段代码是一个使用 chainlit 框架构建的聊天应用示例,该应用利用 llama_index 库来处理文档索引和检索任务。以下是对代码各部分的详细解读:

导入模块

首先导入所需的模块,包括 ostimechainlitllama_index 相关类和函数。

设置环境变量

设置 DashScope API 的密钥,这是用于访问 DashScope 平台上的 LLM 和嵌入模型的。

初始化设置

通过 Settings 类初始化一些全局配置,包括使用的 LLM 模型、嵌入模型、节点分割器等参数。

定义获取向量存储索引的函数

get_vector_store_index() 函数检查是否存在预先存储的索引文件。如果存在,则加载这些索引;否则,读取指定目录下的文档,创建 SummaryIndexVectorStoreIndex,并将它们存储到指定路径。

初始化索引

调用 get_vector_store_index() 函数初始化 summary_indexvector_index

启动聊天会话

@cl.on_chat_start 装饰器定义了聊天开始时发送的消息。

处理消息

@cl.on_message 装饰器定义了当用户发送消息时触发的事件处理函数:

  1. 初始化检索器:分别为 summary_indexvector_index 创建检索器实例。
  2. 创建工具:使用 RetrieverTool 封装检索器,并提供描述信息。
  3. 创建路由检索器:使用 RouterRetriever 组件,根据输入查询选择合适的检索工具。
  4. 创建查询引擎:使用 RetrieverQueryEngine 封装检索器,并启用流式传输响应。
  5. 处理查询:接收用户输入的消息,并异步执行查询。使用 stream_token 方法逐个流式传输响应给用户。
  6. 记录来源信息:记录用于生成响应的文档片段,并将其作为来源信息返回给用户。

总结

这段代码展示了如何使用 llama_index 来构建一个具有智能路由能力的检索系统,并通过 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

启动后界面如下:

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

总结

在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.ppmy.cn/news/1531657.html

相关文章

vue+UEditor附件上传问题

🏆本文收录于《全栈Bug调优(实战版)》专栏,主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&am…

scrapy快速上手

安装 除了scrapy本身还要安装两个库 pip install scrapy pip install pywin32 pip install wheel 创建项目 在要创建项目的地方打开powershell scrapy startproject 项目名 我们得到这样的项目结构,功能如下 scrapy.cfg 项目的主配置信息 …

nvm以及npm源配置

配置 NVM 和 NPM 使用镜像源 接上一篇。国内使用会遇到网络连接问题。为了解决这个问题,我们可以配置 NVM 和 NPM 使用腾讯的源。 配置 NVM 源 首先,我们需要配置 NVM 源。可以使用以下命令: export NVM_NODEJS_ORG_MIRRORhttps://mirrors.…

基于STM32的智能家居交互终端:使用FreeRTOS与MQTT协议的流程设计

一、项目概述 简要介绍项目的目标和用途 随着智能家居的普及,家庭智能交互终端成为提升居住体验的重要设备。本文将介绍一个基于STM32的家庭智能交互终端的设计与实现,该终端能够通过触摸屏、语音识别和传感器数据采集等功能,提供家庭环境监…

【工具-VMware Workstation-ubuntu】

VMware Workstation-ubuntu ■ ubuntu 和 win11 共享文件夹出现在/mnt/hgfs 目录下。■■■■ ■ ubuntu 和 win11 共享文件夹出现在/mnt/hgfs 目录下。 执行 vmware-hgfsclient 显示有共享文件夹。ls 却查看不到 执行 sudo vmhgfs-fuse .host:/ /mnt/hgfs -o nonempty -o all…

初识C#(四)- 函数或方法

函数就是一个外挂的方法,以便我们自己自定义某个功能 文章目录 前言一、函数的使用1.1 函数的定义和使用1.2 函数参数分为(形参和实参)1.3 函数的返回值 二、函数的递归2.1 调用自身的函数就是递归函数 三、枚举类型3.1 枚举类型的声明与赋值 总结 前言 本篇笔记重…

时间序列分析算法

目录 1.背景介绍及应用2.时间序列核心概念与联系3.核心算法原理、步骤、数学模型公式详解3.1直接方法3.1.1 移动平均3.1.2 累计和 3.2 差分方法3.2.1 首差3.2.2 二差 3.3指数方法3.3.1 指数移动平均3.3.2指数差分 4.时间序列优缺点5.说明5.1时间序列分析与其他预测方法的区别在…

短视频矩阵管理系统贴牌 源码开发

抖音账号矩阵的开发核心维度包括: 多账号管理开发维度:通过运用不同类型的账号矩阵,可以实现统一且便捷的管理。目前,矩阵系统支持管理抖音、快手、视频号,b站的账号,未来计划加入小红书,tk等等的账号管理。 矩阵账号…