使用 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 框架,又多了一个选择,不妨一试。

参考链接:

相关推荐
专注VB编程开发20年几秒前
asp.net mvc如何简化控制器逻辑
后端·asp.net·mvc
用户67570498850231 分钟前
告别数据库瓶颈!用这个技巧让你的程序跑得飞快!
后端
千|寻1 小时前
【画江湖】langchain4j - Java1.8下spring boot集成ollama调用本地大模型之问道系列(第一问)
java·spring boot·后端·langchain
程序员岳焱1 小时前
Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解
后端·sql·mysql
龚思凯1 小时前
Node.js 模块导入语法变革全解析
后端·node.js
天行健的回响1 小时前
枚举在实际开发中的使用小Tips
后端
wuhunyu1 小时前
基于 langchain4j 的简易 RAG
后端
techzhi1 小时前
SeaweedFS S3 Spring Boot Starter
java·spring boot·后端
写bug写bug2 小时前
手把手教你使用JConsole
java·后端·程序员