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

news2024/9/28 19:46:04

检索原理

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 time

import 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, DashScopeGenerationModels

Settings.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_index1


summary_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.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 是和上下文本块的重合文本的大小。
  • 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.coloradmin.cn/o/2174575.html

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

相关文章

STM32单片机编程调试常见问题(一) HardFault_Handler故障分析与解决

文章目录 一.概要二.什么是Hard fault三.Hard fault 产生的原因分析四.制作一个Hard fault程序并定位出问题原因1.查看堆栈指针SP的地址以及内容2.找到Return address地址3.查看汇编界面4.输入Return address地址,查找到问题代码 小结 一.概要 在嵌入式开发中&…

AR传送门+特定区域显示内容+放大镜 效果着色器使用

AR传送门特定区域显示内容放大镜 效果 关键词:Portal Mask 1、教程链接: AR 传送门教程 Unity - Portal Mask Implementation - Part 4_哔哩哔哩_bilibili 应用案例效果: 2、案例下载地址:使用unity 2021.3.33f1 obi 工具…

三分钟让你掌握PDF转音频:PDF2Audio背后的秘密

你有没有过这样的经历?工作繁忙,眼睛被一份又一份的PDF文件轰炸,盯得头昏眼花,却还得继续阅读。如果我告诉你,有一个简单的工具,可以把那些厚厚的PDF文档变成语音,让你在通勤、做家务时“听”文件,而不是“看”文件,你会不会心动? 今天,我们就来聊聊一个叫做PDF…

**CentOS7安装redis**

CentOS7安装redis 首先解压压缩包 redis-7.0.0.tar.gz tar -xvf redis-7.0.0.tar.gz接着进入到redis中 cd redis-7.0.0.tar.gz执行make命令编译 make接着执行安装命令 make install之后编译安装完后 程序都会在/usr/local/bin目录下 这里需要将在redis目录中redis.conf配置…

交通 | ACM SIGSPATIAL 24 深度强化学习求解多周期设施选址问题

论文作者信息:Changhao Miao, Yuntian Zhang, Tongyu Wu, Fang Deng, and Chen Chen. 2024. Deep Reinforcement Learning for Multi-Period Facility Location: p k p_{k} pk​-median Dynamic Location Problem. In The 32nd ACM International Conference on Ad…

如何评估和观测 IoTDB 所需的网络带宽?

IoTDB 推荐网络配置监控网络 I/O 一网打尽! 网络数据传输速度太慢?延迟太高? 网络的硬件配置如何确定? 网络流量过大导致拥塞? 在现代计算机系统和应用程序中,网络 I/O 性能是决定整体系统表现的关键因素之…

微服务 OpenFeign 解析部署使用全流程

目录 1、什么是OpenFeign 1、Feign是什么??http请求 2、OpenFeign是什么 3、Feign和openFeign有什么区别 2、应用 1、 需要开启nacos 和redis 2、准备工作 【1.对springsession做改动】 【2.对springsession-1做改动】 3、实现http请求管理 4、…

借助spring的IOC能力消除条件判断

shigen坚持更新文章的博客写手,记录成长,分享认知,留住感动。个人IP:shigen 在前边讲到了如何借助HashMap、枚举类、switch-case消除条件判断,这里讲到我们最常见的用spring的IOC能力来消除代码中的逻辑判断。其实大部…

精准测试在基金团队应用实践

以下为作者观点: 一、引言 精准测试是一套计算机测试辅助分析系统,精准测试的核心组件包含,软件覆盖率分析、用例和代码的双向追踪、智能回归测试用例选取、缺陷定位、测试用例聚类分析、测试用例自动生成系统,这些功能完整的构…

3-2 AUTOSAR RTE对Runnable的作用

返回总目录->返回总目录<- 一、前言 通过RTE给runnable提供触发事件。 runnable是可以被触发的,但是需要通过RTE来实现这个触发和调用runnable通过RTE给runnable提供所需资源。 RTE将runnable需要的一些资源通过接口传输给它(Port的实现)将BSW和SWC做隔绝。 因此OS和r…

前端大模型入门:使用Transformers.js手搓纯网页版RAG(二)- qwen1.5-0.5B - 纯前端不调接口

书接上文&#xff0c;本文完了RAG的后半部分&#xff0c;在浏览器运行qwen1.5-0.5B实现了增强搜索全流程。但受限于浏览器和模型性能&#xff0c;仅适合于研究、离线和高隐私场景&#xff0c;但对前端小伙伴来说大模型也不是那么遥不可及了&#xff0c;附带全部代码&#xff0c…

干货 | 2024大模型十大趋势(免费下载)

导读&#xff1a;近日&#xff0c;在2024世界人工智能大会上&#xff0c;腾讯正式发布了《2024大模型十大趋势——走进“机器外脑”时代》报告。目前&#xff0c;这一报告正在AI产业界各大社群快速传播。报告中&#xff0c;腾讯研究院试图通过10个关键性的趋势&#xff0c;去理…

c++(AVL树及其实现)

一、AVL树的概念 AVL树是最先发明的自平衡⼆叉查找树&#xff0c;AVL是⼀颗空树&#xff0c;或者具备下列性质的⼆叉搜索树&#xff1a;它的 左右子树都是AV树&#xff0c;且左右子树的高度差的绝对值不超过1。AVL树是⼀颗高度平衡搜索⼆叉树&#xff0c; 通过控制高度差去控…

python开源代码自学问题解决(requests+openpyxl+pymysql)

目的 解决一下在一个开源代码中遇到的问题&#xff0c;作者已经学完了python的基础内容&#xff0c;因此找了一份开源的python代码进行学习&#xff0c;下面这份开源代码主要作用就是在拉勾网上获取与Python相关的职位信息&#xff0c;并将这些信息保存到本地的MySQL数据库中&…

【Linux】初始进程

目录 基本概念 PCB task_struct task_struct内容分类 组织进程 查看进程 查看正在运行的进程信息 获取pid和ppid 创建子进程 基本概念 一个已经加载到内存中的程序&#xff0c;叫做进程&#xff0c;正在运行的程序&#xff0c;叫做进程&#xff0c;进程是担当分配系统…

如果你不愿意冒一切风险,就不要成为创业者:如何建立一个年收入 1800 万美元的支付业务

作者&#xff1a;Austin Mac Nab&#xff0c;VizyPay 的 CEO 兼创始人 在创业初期&#xff0c;如果有人告诉我&#xff0c;我需要冒一切风险才能成功&#xff0c;我大概会吓得绕道而行。但事实是&#xff0c;如果你不愿意冒一切风险&#xff0c;就不要成为创业者。本着这个信念…

「JavaScript深入」彻底搞懂JS原型与原型链

JavaScript深入 — 原型与原型链 一、原因二、使用class实现继承普通的类实现继承 三、原型四、原型链小结原型原型链prototype和proto 引申 一、原因 JavaScript中除了基础类型外的数据类型&#xff0c;都是对象&#xff08;引用类型&#xff09;。但是由于其没有类&#xff…

央行放大招!潘行长发话了,现在能“贷款炒股“,这是真的吗?

9月&#xff0c;央行掌门人潘行长最新放话了&#xff0c;二套房贷款利率也得下调。这降准的利好一出&#xff0c;股市小涨了一波后又回到了原位&#xff0c;给全球金融市场带来了一股不同寻常的暖流。而非常有意思的是&#xff0c;在这次众多的金融政策大礼包当中&#xff0c;有…

CentOS8.5.2111(3)实验之DHCP服务器架设

一、实验目标 1&#xff0e;掌握DHCP服务器的主配置文件各项申明参数及操作及其含义 2. 具备DHCP 服务器、中继服务器的配置能力 3. 具备测试客户端正常获取服务器分配地址的能力 4. 具备DHCP服务器故障排除能力 二、实训原理/流程 &#xff08;一&#xff09;项目背景 …

媒界:助力民生保障 长城“消防炮”即将批量交付硬核守护万家灯火

一大波“消防炮”即将列装&#xff01; 日前&#xff0c;长城炮官方账号发布一条“‘消防炮’来了”的视频&#xff0c;引发广泛关注。视频显示一批长城炮车型已完成消防装备加装&#xff0c;华丽变身“消防炮”&#xff0c;整装待发&#xff0c;即将交付全国消防&#xff0c;…