使用 LlamaIndex 框架搭建 RAG 应用基础实践

前言

上一篇文章检索增强生成 Retrieval-Augmented Generation介绍了什么是 RAG ,并详细对比了和大模型微调方式的区别。

目前实现 RAG 的主流框架就是 LangChainLlamaIndex,LangChain 更适合需要复杂对话流程、上下文管理、以及多步骤任务的应用场景,如聊天机器人、任务自动化等。LlamaIndex 当应用场景主要涉及大量数据的快速检索和查询时,LlamaIndex更加适用,如企业知识问答系统、文档搜索引擎等。

这次主要来聊聊如何利用 LlamaIndex 框架来搭建 RAG 应用,以及其中遇到的一些问题。

LlamaIndex 基础实践

其实官方有很详细的文档,Doc - LlamaIndex,也给出了几个 demo 教你如何使用。框架是比较开放的,很多类都是可以自定义的,以下是我在使用中的一些笔记。

0. 安装

安装其实很简单,直接 pip 安装即可,但是这也只是一些核心的包,再用到一些自定义功能时,需要安装额外的包,后面有介绍。

perl 复制代码
pip3 install llama-index -i https://pypi.tuna.tsinghua.edu.cn/simple

1. 自定义 LLM

LlamaIndex 默认是使用 OpenAI 的 gpt-3.5-turbo 模型,当然你得提供 OPENAI_API_KEY, 由于众所周知的原因,用起来不是很方便。因此可以使用 OpenAILike 这个类来使用我们自己的本地模型,参考文档 LocalAI - LlamaIndex

我这边用的模型是 Qwen/Qwen1.5-7B-Chat,然后用 vllm 框架的 openai 方式跑起来,命令如下:

bash 复制代码
python3 -m vllm.entrypoints.openai.api_server \
  --trust-remote-code \
  --model /models/Qwen1.5-7B-Chat \
  --host 0.0.0.0 \
  --port 7859 \
  --served-model-name qwen-7b-chat \
  --max-model-len 8192

启动之后,就可以初始化类了,这里要提前安装 llama-index-llms-openai-like 这个包。

python 复制代码
from llama_index.llms.openai_like import OpenAILike
from llama_index.core import Settings

llm = OpenAILike(
    api_key="EMPTY", # vllm 启动时没有配置,默认就是 EMPTY
    api_base="http://192.168.0.1:7859/v1", # 启动 vllm 的ip地址
    model="qwen-7b-chat", # 启动 vllm 时设置的模型名字
    temperature="0.8", max_tokens=512,
    context_window=8192, is_chat_model=True, timeout=60
)

# 这是默认模型为本地模型
Settings.llm = llm

可以测试一下:

python 复制代码
>>> llm = OpenAILike(
...     api_key="EMPTY", api_base="http://192.168.0.1:7859/v1", model="qwen-7b-chat",
...     temperature="0.8", max_tokens=512, context_window=8192,
...     is_chat_model=True, timeout=60
... )
>>> res = llm.chat(messages=[ChatMessage(content="你好")])
>>> res
ChatResponse(message=ChatMessage(role=<MessageRole.ASSISTANT: 'assistant'>, content='你好!有什么我能为你效劳的吗?\n', additional_kwargs={}), raw={'id': 'cmpl-3ca35554649449d9908291bfb983f9b6', 'choices': [Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content='你好!有什么我能为你效劳的吗?\n', role='assistant', function_call=None, tool_calls=None))], 'created': 5364155, 'model': 'qwen-7b-chat', 'object': 'chat.completion', 'system_fingerprint': None, 'usage': CompletionUsage(completion_tokens=13, prompt_tokens=19, total_tokens=32)}, delta=None, additional_kwargs={})
>>> res.message.content
'你好!有什么我能为你效劳的吗?\n'

2. embedding

自定义embedding-model 可以参考文档 Local Embeddings with HuggingFace - LlamaIndex,HuggingFace 做了一个 embedding 的排行榜 MTEB Leaderboard,也可以在这里挑个喜欢的,我用的是 BAAI/bge-m3

注意,这里需要额外安装 llama-index-embeddings-huggingface 包。

python 复制代码
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
embed_model = HuggingFaceEmbedding(model_name="/models/bge-m3")

3. 向量数据库

LlamaIndex 支持市面上主流的向量数据库,可以在这里查支持列表 Vector Stores - LlamaIndex,因为我这边知识库不大,所有没有选择 Milvus,而是选择用更轻量级的 Chroma,直接 docker 起一个 chroma 服务。

注意,这里需要额外安装 llama-index-vector-stores-chroma 包。

python 复制代码
import chromadb
from chromadb.config import Settings as ChromadbSettings # 防止和llamaindex的设置类冲突
from llama_index.vector_stores.chroma import ChromaVectorStore

# 初始化向量数据库客户端
chroma_client = chromadb.HttpClient(
    host='192.168.0.1', port=8000,
    settings=ChromadbSettings(
        chroma_client_auth_provider="chromadb.auth.token.TokenAuthClientProvider",
        chroma_client_auth_credentials="your_chroma_password"
    )
)

# 设置集合
chroma_collection = chroma_client.get_or_create_collection(name="rag_test")

# 初始化类
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)

下面插入一段文本进数据库,模拟一下本地知识库。这里我们选择一篇介绍 小米 14 Ultra 的文章,我删除了图片信息。

python 复制代码
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, StorageContext, Settings

# 加载数据
docs = SimpleDirectoryReader(input_files=["/docs/xiaomi.txt"]).load_data()

# 这里设置一下chunk大小,用于切割大文本
Settings.chunk_size = 512
Settings.chunk_overlap = 25

# 向量插入
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(docs, storage_context=storage_context, embed_model=embed_model)

到此数据就插入完毕了,下次就可以直接读取向量数据库的数据,不需要每次都执行插入。

4. 对话查询

python 复制代码
from llama_index.core import VectorStoreIndex

# 从指定的向量数据库查询
index = VectorStoreIndex.from_vector_store(vector_store, embed_model=embed_model)
# 初始化对话引擎,
chat_engine = index.as_chat_engine(
    similarity_top_k=5, # 设置匹配相似度前 5 的知识库片段
    chat_mode="condense_plus_context" # 设置聊天模型
)

Available Chat Modes - LlamaIndex 这里可以看到所有可用聊天模型的类别。

python 复制代码
>>> res = chat_engine.chat('介绍一下小米 14 ultra')
>>> res.response
'小米14 Ultra是一款高性能且注重影像体验的旗舰手机,它在设计、影像能力和日常使用上都有显著提升。以下是它的主要特点:\n\n1. **摄像头升级**:传感器从索尼IMX989的老旧制程升级至更先进的Lyt900,这不仅减少了功耗,还提供了更好的影像质量,支持硬件级HDR,使得照片宽容度更强。\n\n2. **HDR功能**:由于IMX989的高能耗问题,一些厂商没有普遍提供硬件级HDR功能。然而,小米14 Ultra的这种传感器克服了这个问题,使得用户能够享受到单帧的高质量照片。\n\n3. **光学镜头系统**:14 Ultra使用了全新的徕卡Summilux光学镜头系统,提高了四颗后置摄像头的光学素质,这意味着照片的清晰度和色彩表现有了很大提升。\n\n4. **影像集全功能**:主摄支持f/1.63-f4光圈,这意味着在光线充足时有更大的进光量,长焦镜头和微距镜头也提供了多样的拍摄场景设置。\n\n5. **视频能力**:支持4K 60fps全焦段变焦、4K 120fps视频录制,前置摄像头也升级到4K 60fps,强调了拍视频的专业性。\n\n6. **影像旗舰与日常使用**:尽管以影像为主,但小米14 Ultra并未完全牺牲日常使用的体验,还配备了高性能的处理器和2K分辨率的可变刷新率屏幕,提供流畅的性能和良好的视觉体验。\n\n7. **相机连拍和AI摄影**:手机的AI计算摄影平台Xiaomi AISP让手机的CPU、GPU和NPU都能参与影像处理,提供了不俗的连续拍摄速度和算法处理能力。\n\n8. **设计和手感**:虽然背面设计有所改变,但保持了摄像头模组的居中圆形,通过金属外圈和巴黎铆钉装饰来提升精致感。背部平滑设计改善了握持手感,但可能会导致厚度和重量增加,影响部分用户的握持感受。\n\n综合来说,小米14 Ultra是一款影像技术与便携性兼备的旗舰手机,无论是在影像摄影还是日常使用上,都表现出色。\n'
>>> 
>>> res = chat_engine.chat('小米 14 ultra请了谁担任影像首席顾问?')
>>> res.response
'小米宣布张艺谋担任了小米14 Ultra的影像首席顾问。这个消息在发布会上被提及,张艺谋作为知名的导演,对影像有着深厚的理解和独到的见解,他在小米14 Ultra上带来的可能是更专业的人像模式和视频拍摄功能。\n'
>>> 
>>> res = chat_engine.chat('小米 14 ultra 电池容量有多大?')
>>> res.response
'小米14 Ultra的电池容量是5300mAh。这款旗舰手机的电池续航能力非常强,即使在不玩游戏、轻度使用的情况下,也能提供10多个小时的续航,足以满足用户一整天的常规需求,而且支持90W有线和80W无线充电,快充功能进一步提升了电池续航的便利性。\n'
>>>
>>>
>>> len(res.source_nodes)
5
>>> res.source_nodes[0]
NodeWithScore(node=TextNode(id_='0f982685-0cbe-42e1-8f0d-878f2c659af6', embedding=None, metadata={'file_path': '/www/me_s_ai_chat/models/docs/xiaomi.txt', 'file_name': '/www/me_s_ai_chat/models/docs/xiaomi.txt', 'file_type': 'text/plain', 'file_size': 11539, 'creation_date': '2024-03-01', 'last_modified_date': '2024-03-01', 'last_accessed_date': None}, excluded_embed_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], excluded_llm_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], relationships={<NodeRelationship.SOURCE: '1'>: RelatedNodeInfo(node_id='0b5e5bb5-2a14-4960-9a2c-53b4c422f698', node_type=<ObjectType.DOCUMENT: '4'>, metadata={'file_path': '/www/me_s_ai_chat/models/docs/xiaomi.txt', 'file_name': '/www/me_s_ai_chat/models/docs/xiaomi.txt', 'file_type': 'text/plain', 'file_size': 11539, 'creation_date': '2024-03-01', 'last_modified_date': '2024-03-01', 'last_accessed_date': None}, hash='e8f365b59c480e2bde3f195e1e8b5df82642f0f931c0e51da0b08fbbfcfba1e4'), <NodeRelationship.PREVIOUS: '2'>: RelatedNodeInfo(node_id='d4c53173-f76d-4bb7-bad7-79dd0e2631d7', node_type=<ObjectType.TEXT: '1'>, metadata={'file_path': '/www/me_s_ai_chat/models/docs/xiaomi.txt', 'file_name': '/www/me_s_ai_chat/models/docs/xiaomi.txt', 'file_type': 'text/plain', 'file_size': 11539, 'creation_date': '2024-03-01', 'last_modified_date': '2024-03-01', 'last_accessed_date': None}, hash='05bbf8fdba0b9d4740128ad97b7e3cd89b553e9d10ca135cae896e6dd8562b76'), <NodeRelationship.NEXT: '3'>: RelatedNodeInfo(node_id='189e07ee-50a5-4e2e-aeb6-b0a58cd4a5c9', node_type=<ObjectType.TEXT: '1'>, metadata={}, hash='5097a4c16bc563774029bd81705025dc60b82fb127b08e43745ced283af1b256')}, text='而且我算是那种频闪敏感用户,用了这么多天手机,几乎每天看屏幕五小时以上,眼睛并没有感到不适,说明这块屏幕所采用的 " DC + 1920Hz 高频 PWM " 护眼调光方案也没什么问题。\n其我这段时间用下来感知最强的还是续航。\n可能是沾了小米造车的光,小米 14 Ultra 的电池在体积变小的情况下,容量却比上一代整整多出 300 mAh,它的电池足足有 5300mAh,而且还支持 90W 有线充电、80W 无线充电。\n电池容量变大带来的续航提升可以说实打实,不玩游戏轻度使用,小米 14 Ultra 的续航可以有十多个小时,一天一充问题不大,讲道理我已经好久没有在旗舰机上体验到这样的续航。\n小米 14 Ultra 支持的双向卫星通信也很有意思。\n虽然小米推出卫星通信的时间有点晚,但是它的存在感非常强,因为它可以根据不同场景提供诸如电子围栏、SOS 紧急求助等功能,而且在低电、触屏失灵等极端情况下依然能够正常使用。', start_char_idx=3514, end_char_idx=3927, text_template='{metadata_str}\n\n{content}', metadata_template='{key}: {value}', metadata_seperator='\n'), score=0.6061127998193151)

可以看到,大模型准确的回答关于用户的提问。对话返回的 AgentChatResponse 对象,可以查看source_nodes属性,这里面是包含了所有匹配的知识库详情,包含匹配的文本、得分排序、文档位置、更新时间等等。

如果想要流式输出,可以这样做:

python 复制代码
res = chat_engine.stream_chat('小米 14 ultra 电池容量有多大?')
for text in res.response_gen:
    print(text, end='', flush=True)

5. 相似度过滤

上一步骤中,我们查询小米 14 Ultra 的电池容量这个问题,设置的是返回相似度前 5 的文档片段,但是其实最后一个得分已经比较低了,内容也确实没有特别匹配。

python 复制代码
>>> len(res.source_nodes) 
5
>>> res.source_nodes[0].score
0.6202297085213127
>>> res.source_nodes[0].text
'而且我算是那种频闪敏感用户,用了这么多天手机,几乎每天看屏幕五小时以上,眼睛并没有感到不适,说明这块屏幕所采用的 " DC + 1920Hz 高频 PWM " 护眼调光方案也没什么问题。\n其实我这段时间用下来感知最强的还是续航。\n可能是沾了小米造车的光,小米 14 Ultra 的电池在体积变小的情况下,容量却比上一代整整多出 300 mAh,它的电池足足有 5300mAh,而且还支持 90W 有线充电、80W 无线充电。\n电池容量变大带来的续航提升可以说实打实,不玩游戏轻度使用,小米 14 Ultra 的续航可以有十多个小时,一天一充问题不大,讲道理我已经好久没有在旗舰机上体验到这样的续航。\n小米 14 Ultra 支持的双向卫星通信也很有意思。\n虽然小米推出卫星通信的时间有点晚,但是它的存在感非常强,因为它可以根据不同场景提供诸如电子围栏、SOS 紧急求助等功能,而且在低电、触屏失灵等极端情况下依然能够正常使用。'
>>>
>>> res.source_nodes[4].score
0.5111634254274936
>>> res.source_nodes[4].text
'昨晚的小米发布会,相信差友们都看了吧?\n该说不说小米动作是真快,自从去年十月份发布小米澎湃 OS,宣布集团战略升级为「人车家全生态」以来,短短几个月就把人车家生态做起来了,昨天它又给我们带来了好几款新品( 发布会传送门 )。\n不过意料之中,这场发布会的绝对主角还是小米 14 Ultra。\n我不清楚有多少人在等这台手机,不瞒各位,在今年即将推出的一众超大杯影像旗舰里,我个人最期待的就是小米 14 Ultra,原因无他,全因为小米 13 Ultra 给人留下的印象实在太过深刻。\n当其他旗舰普遍还是三摄的时候,小米 13 Ultra 直接用上了四摄,除了 1 英寸超大底,还有双长焦,真正做到了焦段覆盖和画质我全都要,搭配德味十足的徕卡影调,拿它拍照是真的顶!\n只不过像它这样在影像上疯狂堆料的代价就是 ------ 机身厚度和重量是真压不住,握持手感只能说一般,以至于我对它 " 既爱又恨 ",手机买了又卖,卖了又买,最后还是被它的拍照所折服。'

过多的不匹配内容可能反倒会对大模型的回答造成干扰,这里我们可以使用 SimilarityPostprocessor 这个类来设置匹配的阈值。

python 复制代码
>>> from llama_index.core.postprocessor import SimilarityPostprocessor
>>> postprocessor = SimilarityPostprocessor(similarity_cutoff=0.6)
>>> chat_engine = index.as_chat_engine(
...     similarity_top_k=5, chat_mode="condense_plus_context",
...     node_postprocessors=[postprocessor]
... )
>>> res = chat_engine.chat('小米 14 ultra 电池容量有多大?')
>>> len(res.source_nodes)
1
>>> res.source_nodes[0].text
'而且我算是那种频闪敏感用户,用了这么多天手机,几乎每天看屏幕五小时以上,眼睛并没有感到不适,说明这块屏幕所采用的 " DC + 1920Hz 高频 PWM " 护眼调光方案也没什么问题。\n其实我这段时间用下来感知最强的还是续航。\n可能是沾了小米造车的光,小米 14 Ultra 的电池在体积变小的情况下,容量却比上一代整整多出 300 mAh,它的电池足足有 5300mAh,而且还支持 90W 有线充电、80W 无线充电。\n电池容量变大带来的续航提升可以说实打实,不玩游戏轻度使用,小米 14 Ultra 的续航可以有十多个小时,一天一充问题不大,讲道理我已经好久没有在旗舰机上体验到这样的续航。\n小米 14 Ultra 支持的双向卫星通信也很有意思。\n虽然小米推出卫星通信的时间有点晚,但是它的存在感非常强,因为它可以根据不同场景提供诸如电子围栏、SOS 紧急求助等功能,而且在低电、触屏失灵等极端情况下依然能够正常使用。'
>>> res.source_nodes[0].score
0.6202297085213127
>>> res.response
'小米 14 Ultra 的电池容量是 5300mAh。\n'
>>>

现在返回的匹配片段就只剩下 1 个了,其余得分低于 0.6 的就全被排除了,大模型回答的结果也更简洁。

6. reranker

由于考虑召回速度,在执行向量搜索的时候存在一定随机性就会牺牲一点准确性,RAG中第一次召回的结果排序往往不太准确,具体可以参考 Rerank------RAG中百尺竿头更进一步的神器,从原理到解决方案。所以这时候就需要 rerank 一下,来对召回的结果重新排序。这里我测试了 LlamaIndex 的两个方案,一个是基于大模型的 LLMRerank 类,一个是第三方的 rerank 模型。

python 复制代码
>>> from llama_index.core.postprocessor import LLMRerank
>>> 
>>> reranker = LLMRerank(
...     top_n=2, llm=llm,
...     parse_choice_select_answer_fn=self.custom_parse_choice_select_answer_fn
... )
>>> 
>>> chat_engine = index.as_chat_engine(
...     similarity_top_k=5, chat_mode="condense_plus_context",
...     node_postprocessors=[postprocessor, reranker]
... )

下面我们就来对比一下效果,先看没有使用 rerank 的:

arduino 复制代码
>>> res.source_nodes[0].text
'如果说小米 13 Ultra 是一台为了极致影像而在手感上有所取舍的影像旗舰。\n那么这次的小米 14 Ultra,在我看来就是一台兼顾极致影像和日常使用的全能旗舰,它在设计,影像还有体验上都迎来了大幅升级,未来能够打败小米 14 Ultra 的,很可能只有下一代 Ultra。\n为啥这么说呢?首先你们也都看到了,相比上一代,小米 14 Ultra 变了但又没完全变。\n这台手机背面依旧采用居中圆形相机模组,只不过现在镜头 Deco 多了金属外圈和巴黎铆钉装饰,使得它看上去会更精致些,然而一旦给手机戴上壳,它看起来就跟 13 Ultra 基本没啥区别。\n当然如果把它侧过来看,你会发现它的背面,竟然做平了!\n之前小米 13 Ultra 手感差有两个原因,一方面是它上半部分素皮有隆起,再加上它有点头重脚轻,导致我拿它的时候食指经常无处安放,放镜头边上总担心手机拿不稳,放镜头上又很沾指纹。'
>>> res.source_nodes[1].text
'小米 14 Ultra 跟 13 Ultra 主摄虽然都是 1 英寸底,但是它从索尼 IMX989 升级成了 LYT900,传感器叫啥名字不重要,区别就在于前者是 40nm,而后者是 22nm,制程工艺更先进,功耗更低。\n实际上这两款传感器都支持硬件级的 HDR,压根用不着算法多帧合成,仅凭一帧就能获得宽容度不错的照片。\n只不过因为 IMX989 功耗太高,导致很多厂商都不敢给自家手机开放这功能,而在换成 LYT900 后就没这顾虑,我发现小米 14 Ultra 的抓拍成功率比 13 Ultra 高出不少,基本上一拍一个准。\n当然 LYT900 小米能用其他手机也能用,所以严格来说算不上是多大的优势,很多人看到另外三颗摄像头使用的还是 IMX858,可能会觉得小米在挤牙膏,小米 14 Ultra 在影像上提升不会很大。\n图片 但别忘了,小米还有徕卡。\n小米 14 Ultra 搭载了全新的徕卡 Summilux 光学镜头系统,这次小米认真打磨了手机上的四颗后置摄像头,使得它们的光学素质上了一个台阶,而且我敢说这样豪华的四摄阵容你绝对没见过。\n先来说说主摄,小米 14 Ultra 上的这颗主摄支持光圈在 f/1.63-f4.'

再看使用了 LLMRerank 的:

arduino 复制代码
>>> res.source_nodes[0].text
'小米 14 Ultra 跟 13 Ultra 主摄虽然都是 1 英寸底,但是它从索尼 IMX989 升级成了 LYT900,传感器叫啥名字不重要,区别就在于前者是 40nm,而后者是 22nm,制程工艺更先进,功耗更低。\n实际上这两款传感器都支持硬件级的 HDR,压根用不着算法多帧合成,仅凭一帧就能获得宽容度不错的照片。\n只不过因为 IMX989 功耗太高,导致很多厂商都不敢给自家手机开放这功能,而在换成 LYT900 后就没这顾虑,我发现小米 14 Ultra 的抓拍成功率比 13 Ultra 高出不少,基本上一拍一个准。\n当然 LYT900 小米能用其他手机也能用,所以严格来说算不上是多大的优势,很多人看到另外三颗摄像头使用的还是 IMX858,可能会觉得小米在挤牙膏,小米 14 Ultra 在影像上提升不会很大。\n图片 但别忘了,小米还有徕卡。\n小米 14 Ultra 搭载了全新的徕卡 Summilux 光学镜头系统,这次小米认真打磨了手机上的四颗后置摄像头,使得它们的光学素质上了一个台阶,而且我敢说这样豪华的四摄阵容你绝对没见过。\n先来说说主摄,小米 14 Ultra 上的这颗主摄支持光圈在 f/1.63-f4.'
>>> res.source_nodes[1].text
'当然普通模式下,小米 14 Ultra 的视频能力同样很顶。\n比如它这次也是率先支持上了 4K 60fps 模式下的全焦段变焦,除此之外主摄还支持录制 4K 120fps 的视频,包括它的前置摄像头录像规格也从上一代的 1080P 30fps 升级到了 4K 60fps。\n总之就拍照来说,新 1 英寸大底、无级可变光圈、全镜头全系大光圈、双长焦双微距,人像、算法还有视频能力全面进阶。我在这里说一句小米 14 Ultra 是新一代的影像旗舰,各位应该没啥意见吧?\n当然我前面也说了,这次的小米 14 Ultra,不只是一台影像旗舰,它还是一台兼顾日常使用的全能旗舰,全能也就意味这台手机非常水桶没有特别明显的短板。\n性能这块我就不多说什么了,骁龙 8Gen3 是啥表现相信大家都清楚,就是目前安卓阵营性能最强的处理器之一。\n小米 14 Ultra 搭载的屏幕,是一块 2K 分辨率可变刷新率高刷屏,实测这块屏幕激发亮度可以来到 3000nit,而且它也支持杜比视界和超动态显示,在看 HDR 视频和照片的时候观感没得说。'

可以看到,默认匹配的情况下,小米 14 Ultra 主摄的升级这个内容被放到了第二的位置,根据整篇文章的重点来看,这个升级点应该是排第一位的,这个内容排序更符合用户提问。

在使用 LLMRerank 这个类时,会有下面两个问题。

6.1 偶尔会查询报错

perl 复制代码
  File "/usr/local/lib/python3.10/site-packages/llama_index/core/indices/utils.py", line 104, in default_parse_choice_select_answer_fn
    answer_num = int(line_tokens[0].split(":")[1].strip())
IndexError: list index out of range

这是由于这个排序是交给大模型处理的,如果大模型返回的格式不规范,那么 default_parse_choice_select_answer_fn 这个方法解析时就会报错,解决办法可以是重写解析算法,下面是个示例:

python 复制代码
from llama_index.core.indices.utils import default_parse_choice_select_answer_fn

def custom_parse_choice_select_answer_fn(answer: str, num_choices: int):
    print('====>>', answer)
    _answer = answer.split('Explanation')[0]
    return default_parse_choice_select_answer_fn(_answer, num_choices)

reranker = LLMRerank(top_n=5, llm=llm, parse_choice_select_answer_fn=custom_parse_choice_select_answer_fn)

6.2 处理时间过长

LLMRerank 这个类的原理是,将向量数据库查询的 top 片段,拼装成提示词给大模型,等待大模型按一定的格式返回,然后再将排序之后的片段作为用户提问的上下文,再次拼装成提示词给大模型回答。这里就会有两次请求大模型,就会造成响应明显变慢。解决办法就是采用第三方的 rerank 模型,替换大模型排序这个操作。

这里我用的是 BAAI/bge-reranker-large 这个模型,使用也比较简单:

python 复制代码
from llama_index.core.postprocessor import SentenceTransformerRerank

reranker = SentenceTransformerRerank(model='/models/bge-reranker-large', top_n=2)

总结

本文是介绍了使用 LlamaIndex 框架来搭建 RAG 基础应用,当然 LlamaIndex 框架远不止这些功能。确实如他的介绍,可以结合大模型快捷方便的对领域数据做检索。官方迭代也很快,几天一个小版本,社区也比较活跃,文档详细。如果想快速搭建企业级的问答系统,现在除了 LangChain 框架,又多了一个选择,不妨一试。

参考链接:

相关推荐
Chrikk15 分钟前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*17 分钟前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue18 分钟前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man20 分钟前
【go从零单排】go语言中的指针
开发语言·后端·golang
customer082 小时前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源
Yaml43 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
小码编匠4 小时前
一款 C# 编写的神经网络计算图框架
后端·神经网络·c#
AskHarries4 小时前
Java字节码增强库ByteBuddy
java·后端