如何避免大语言模型绕过知识库乱答的情况?LlamaIndex 原理与应用简介

news2025/2/24 5:38:28

本文首发于博客 LLM 应用开发实践

随着 LangChain + LLM 方案快速普及,知识问答类应用的开发变得容易,但是面对回答准确度要求较高的场景,则暴露出一些局限性,比如向量查询方式得到的内容不匹配,LLM 对意图识别不准。所以 LlamaIndex(也称为 GPT Index)由社区顺势推出,是一个开发者友好的接口,它将外部数据连接到 LLM,提供了一系列工具来简化流程,包括可以与各种现有数据源和格式(如 api、pdf、文档和 SQL 等)集成的数据连接器,极大的改善了上述问题。本文译自 LlamaIndex: How to Use Index Correctly,翻译内容并非原版无对照翻译,有所增减。

LlamaIndex索引

列表索引

它对于综合跨多个数据源的信息的答案非常有用

列表索引是一种简单的数据结构,其中节点按顺序存储。在索引构建期间,文档文本被分块、转换为节点并存储在列表中。

在查询期间,如果没有指定其他查询参数,LlamaIndex只是将列表中的所有node加载到Response Synthesis模块中。

列表索引提供了许多查询列表索引的方法,从基于嵌入的查询中获取前k个邻居,或者添加一个关键字过滤器,如下所示:

img

LlamaIndex为列表索引提供Embedding支持。除了每个节点存储文本之外,每个节点还可以选择存储Embedding。在查询期间,我们可以在调用LLM合成答案之前,使用Embeddings对节点进行最大相似度检索。

索引构建过程中,LlamaIndex不会生成Embedding,而是在查询时生成,这种设计避免了在索引构建期间为所有文本块生成Embeddings,这可能会导致大量数据的开销。

向量存储索引

它是最常见且易于使用的,允许对大型数据语料库回答查询

默认情况下,GPTVectorStoreIndex 使用内存中的 SimpleVectorStore作为默认存储上下文的一部分初始化,基于向量存储的索引在索引构建期间生成Embeddings

img

树状索引

它对总结一组文件很有用

树状索引是树结构索引,其中每个节点是子节点的摘要。在索引构建期间,树以自下而上的方式构建,直到我们最终得到一组根节点。树状索引从一组节点(成为该树中的叶节点)构建层次树。

查询树状索引涉及从根节点向下遍历到叶节点。默认情况下(child_branch_factor=1 ),查询在给定父节点的情况下选择一个子节点。如果child_branch_factor=2,则查询在每个级别选择两个子节点。

img

为了在查询期间构建树状索引,我们需要将retriver_moderesponse_mode添加到查询引擎,并将GPTTreeIndex中的build_tree参数设置为False

index_light = GPTTreeIndex.from_documents(documents, build_tree=False)
query_engine = index_light.as_query_engine(
    retriever_mode="all_leaf",
    response_mode='tree_summarize',
)
query_engine.query("What is net operating income?")

关键词表索引

他对于将查询路由到不同的数据源非常有用

关键字表索引从每个Node提取关键字,并构建从每个关键字到该关键字对应的Node的映射。

在查询时,从查询中提取相关关键字,并将其与预提取的Node关键字进行匹配,获取相应的Node。提取的节点被传递到响应合成模块。

img

  • GPTKeywordTableIndex- 使用LLM从每个文档中提取关键字,这意味着它确实需要在构建期间调用LLM

  • GPTSimpleKeywordTableIndex- 使用regex关键字提取器从每个文档中提取关键字,在构建期间不会调用LLM

可组合性图索引

它对于构建知识图谱很有用

使用LlamaIndex,您可以通过在现有索引之上构建索引来创建复合索引。该特性使您能够有效地索引完整的文档层次结构,并为GPT提供量身定制的知识。

通过利用可组合性,可以在多个级别定义索引,例如为单个文档定义低级索引,为文档组定义高级索引。考虑下面的例子:

  • 可以为每个文档中的文本创建树索引。
  • 生成一个列表索引,涵盖所有的树索引为整个文档集合。

通过一个场景来演示可组合性图索引的能力:

  • 从多个文档创建树索引
  • 从树索引生成摘要
  • 接下来在3个树索引的顶部创建一个列表索引的图,因为列表索引适合于合成跨多个数据源组合信息的答案
  • 最后查询图
from llama_index.indices.composability import ComposableGraph

from langchain.chat_models import ChatOpenAI
from llama_index import LLMPredictor

# setting up vector indicies for each year
service_context = ServiceContext.from_defaults(chunk_size_limit=512)
index_set = {}
for year in years:
    storage_context = StorageContext.from_defaults()
    cur_index = GPTVectorStoreIndex.from_documents(
        documents=doc_set[year],
        service_context=service_context,
        storage_context=storage_context
    )
    index_set[year] = cur_index
    # store index in the local env, so you don't need to do it over again
    storage_context.persist(f'./storage_index/apple-10k/{year}')

# define an LLMPredictor set number of output tokens
llm_predictor = LLMPredictor(llm=ChatOpenAI(temperature=0, max_tokens=512, model_name='gpt-3.5-turbo'))
service_context = ServiceContext.from_defaults(llm_predictor=llm_predictor)
storage_context = StorageContext.from_defaults()\

## define a list index over the vector indicies 
## allow us to synthesize information across  each index
index_summary = [index_set[year].as_query_engine().query("Summary this document in 100 words").response for year in years]
graph = ComposableGraph.from_indices(
    GPTListIndex,
    [index_set[y] for y in years],
    index_summaries=index_summary,
    service_context=service_context,
    storage_context=storage_context
)

root_id = graph.root_id

#save to disk
storage_context.persist(f'./storage_index/apple-10k/root')

## querying graph
custom_query_engines = {
    index_set[year].index_id: index_set[year].as_query_engine() for year in years
}

query_engine = graph.as_query_engine(
    custom_query_engines=custom_query_engines
)

response = query_engine.query("Outline the financial statement of Q2 2023")
response.response

Pandas索引和SQL索引

它对结构化数据很有用

from llama_index.indices.struct_store import GPTPandasIndex
import pandas as pd

df = pd.read_csv("titanic_train.csv")

index = GPTPandasIndex(df=df)

query_engine = index.as_query_engine(
    verbose=True
)
response = query_engine.query(
    "What is the correlation between survival and age?",
)

文档摘要索引

这是一个全新的LlamaIndex数据结构,它是为了问答而制作的。

通常,大多数用户以以下方式开发基于LLM的QA系统:

  1. 获取源文档并将其分成文本块。
  2. 然后将文本块存储在矢量数据库中。
  3. 在查询期间,通过使用相似度和/或关键字过滤器进行Embedding来检索文本块。
  4. 执行整合后的响应。

然而,这种方法存在一些影响检索性能的局限性:

  1. 文本块没有完整的全局上下文,这通常限制了问答过程的有效性。
  2. 需要仔细调优top-k /相似性分数阈值,因为过小的值可能会导致错过相关上下文,而过大的值可能会增加不相关上下文的成本和延迟。
  3. Embeddings可能并不总是为一个问题选择最合适的上下文,因为这个过程本质上是分别决定文本和上下文的。

为了增强检索结果,一些开发人员添加了关键字过滤器。然而,这种方法有其自身的挑战,例如通过手工或使用NLP关键字提取/主题标记模型为每个文档确定适当的关键字,以及从查询中推断正确的关键字。

img

这就是 LlamaIndex 引入文档摘要索引的原因,它可以为每份文档提取非结构化文本摘要并编制索引,从而提高检索性能,超越现有方法。该索引比单一文本块包含更多信息,比关键字标签具有更多语义。它还允许灵活的检索,包括基于 LLM 和嵌入的方法。在构建期间,该索引接收文档并使用 LLM 从每个文档中提取摘要。在查询时,它会根据摘要使用以下方法检索相关文档:

  • 基于 LLM 的检索:获取文档摘要集合并请求 LLM 识别相关文档+相关性得分
  • 基于嵌入的检索:利用摘要嵌入相似性来检索相关文档,并对检索结果的数量施加顶k限制。

文档摘要索引的检索类为任何选定的文档检索所有节点,而不是在节点级返回相关块。

知识图谱索引

它通过在一组文档中提取知识三元组(主语、谓语、宾语)来建立索引。
在查询时,它既可以只使用知识图谱作为上下文进行查询,也可以利用每个实体的底层文本作为上下文进行查询。通过利用底层文本,我们可以针对文档内容提出更复杂的查询。

索引成本和索引时间

  • 索引的成本是一个需要考虑的重要因素,在处理海量数据集时,这一点尤为重要。
  • 索引速度,整个解决方案的运行准备时间。索引时间各不相同,但都是一次性的,通常 40 页的 PDF 文件大约需要 5 秒钟。试想一下,如果一个庞大的数据集超过 10 万页,可能需要几天时间,可以利用异步方法来缩短索引时间。

更多内容在公号:LLM 应用全栈开发

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

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

相关文章

百度测试开发工程师面试心得

百度测试开发实习生面试心得: 电话面试: 面试官:首先做一下自我介绍吧 我:我是***,来自什么大学,现在大三,在学校期间担任过部长,副主席等职务, 组织举办了很多比赛&…

linux 服务器类型Apache配置https访问

一:查看服务器类型,下载相应的SSL证书 命令:netstat -anp | grep :80 httpd是Apache超文本传输协议(HTTP)服务器的主程序,所以下载Apache证书 二:将证书解压后复制到服务器上 三个文件:xxx.key xxx_publ…

PFSK152 3BSE018877R1 有源滤波器的定义

PFSK152 3BSE018877R1 有源滤波器的定义 有源滤波器是以晶体管和运算放大器为基本元件设计的滤波电路。除了这些元件,有源滤波器的电路还包含电阻和电容,但不包含电感。 我们知道滤波器具有频率选择性。因此,有源滤波器电路使用晶体管和运算…

《FAQ专场 | smardaten及应用软件的运维管理(上)》

近期smardaten新睿友增长迅速,睿睿收到了越来越多的问题咨询,真真切切感受到了大家对smardaten的好奇和喜欢。 必须给足咱们睿友安全感,所以睿睿把大家问的多的问题都整理了,陆续以FAQ专场形式给大家统一解答。 本期FAQ是《smar…

【开源】基于正点原子alpha开发板的第三篇系统移植

系统移植的三大步骤如下: 系统uboot移植系统linux移植系统rootfs制作 一言难尽,踩了不少坑,当时只是想学习驱动开发,发现必须要将第三篇系统移植弄好才可以学习后面驱动,现将移植好的文件分享出来: 仓库&…

Android之SpannableString使用

文章目录 前言一、效果图二、实现代码总结 前言 在开发中,往往有些需求是我们不愿意遇到的,但是也不得不处理的事情,比如一段文案,需要文案中某些文字变颜色或者点击跳转,所以简单写了几句代码实现,没什么…

备战蓝桥杯,那你一定得打这场免费且有现金奖励的算法双周赛!

失踪人口回归,好久没在CSDN上与大家交流了。因为在蓝桥开了一些课程,我的重心已经完全转向读研究生和教授课程。今天,我想向大家推荐一个竞赛,考虑到大家已经学习了很长时间的算法,这个竞赛将为你提供一个不仅可以实现…

ros学习笔记(1)Mac本地安装虚拟机,安装Ros2环境

Ros与Linux的关系 Ros环境基于Linux系统内核 我们平时用的是Linux发行版,centos,ubuntu等等,机器人就用了ubunut 有时候我们经常会听到ubunue的版本,众多版本中,有一些是长期维护版TLS,有一些是短期维护…

如何使用自动化工具编写测试用例?

在快速变化的软件开发领域,保证应用程序的可靠性和质量至关重要。随着应用程序复杂性和规模的不断增加,仅手动测试无法满足行业需求。 这就是测试自动化发挥作用的地方,它使软件测试人员能够提高效率、增加测试覆盖率并自信地交付高质量的产品…

嵌入式学习笔记(54)S5PV210的ADC控制器

11.3.1 ADC和(电阻式)触摸屏的关系 (1)ADC在210数据手册的section 10.7 (2)电阻式触摸屏本身工作时就依赖于AD转换,所以在210的SoC中电阻触摸屏接口本身和ADC接口是合二为一的。或者说电阻触摸屏接口使用了(复用了)A…

C语言_用于ADC数据的均值滤波算法

C语言_用于ADC数据的均值滤波算法 说明: 在采集ADC值的时候一般都是多次采集然后,然后取平均值,改进型做法就是去掉最大最小值剩下的再取平均值 unsigned short average(unsigned short arr[], unsigned char size) {unsigned int sum 0;for…

CVE-2020-36189 jackson-databind java反序列化漏洞

漏洞原理 jackson-databind是一套开源的java序列化与反序列化工具框架,可将java对象序列化为xml和json格式的字符串及提供对应的反序列化过程。由于其解析效率较高,目前是Spring MVC中内置使用的解析方式,该漏洞的触发条件是ObjectMapper反序…

JUC第二十八讲:JUC工具类: Semaphore详解

JUC工具类: Semaphore详解 本文是JUC第二十八讲,JUC工具类: Semaphore详解。Semaphore底层是基于AbstractQueuedSynchronizer来实现的。Semaphore称为计数信号量,它允许n个任务同时访问某个资源,可以将信号量看做是在向外分发使用资源的许可证…

智源发布最强开源可商用中英文语义向量模型 BGE,超越同类模型,解决大模型制约问题

0.介绍 语义向量模型(Embedding Model)已经被广泛应用于搜索、推荐、数据挖掘等重要领域。 在大模型时代,它更是用于解决幻觉问题、知识时效问题、超长文本问题等各种大模型本身制约或不足的必要技术。然而,当前中文世界的高质量语义向量模型仍比较稀缺,且很少开源。 为…

数字化教育的未来:数字孪生技术助力校园创新

随着科技的飞速发展,智慧校园成为教育领域的新宠。数字孪生技术,作为一项新兴技术,正日益深刻地影响着校园的运营和管理。它为学校提供了前所未有的工具和资源,使校园管理更加高效、智能化。本文将探讨数字孪生技术如何助力智慧校…

LeetCode 1488. 避免洪水泛滥【贪心,二分,有序集合】1973

本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…

nginx的重定向

nginx重定向--rewrite重写功能介绍 rewrite 的功能介绍 rewrite功能就是,使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标记位实现URL重写以及重定向。 比如:更换域名后需要保持旧的域名能跳转到新的域名上、某网页发生改变需…

pytest中fixture的使用方法

一、pytest中的fixture是什么 为可靠的和可重复执行的测试提供固定的基线(可以理解为测试的固定配置,使不同范围的测试都能够获得统一的配置),fixture提供了区别于传统单元测试(setup/teardown)风格的令人…

来自云仓酒庄品牌雷盛红酒分享为什么高海拔的酒价格更高?

为高海拔地区的葡萄园提供资源的成本也是一个需要考虑的关键因素,并且肯定会影响最终葡萄酒的价格。来自云仓酒庄品牌雷盛红酒分享虽然融雪在没有降雨的月份为自然灌溉系统提供水,但在世界上许多受保护的优质葡萄园地区,灌溉葡萄树通常是不允…

【Spring源码分析】Bean的元数据和一些Spring的工具

Bean的元数据和一些Spring工具 一、BeanDefinition1、认识 BeanDifinition2、AbstractBeanDefinition3、GenericBeanDefinition测试 二、BeanDefinition 注册器三、加载BeanDefinition四、包扫描过程分析包扫描过程总结 五、内省 API六、反射工具Bean 的创建批量构造Resolvable…