赞
踩
response_synthesizer = get_response_synthesizer( response_mode="refine", use_async=True )
(我是对refine和tree_summarize进行了尝试,refine构建知识库的速度很慢很慢)
改了这里的response_mode之后,在使用query_engine的时候也修改了一下engine的response_mode:(use_async仅限于tree_summarize)
query_engine = index.as_query_engine( response_mode="refine", use_async=False )
refine实在是太慢了,engine的mode改成了compact,然后设置了一下topk:
similarity_top_k=1, sparse_top_k=3, vector_store_query_mode="hybrid",
topk越多,模型回答速度就越慢,所以这里就设置了1和3。
使用query engine的问题就是对于知识库没有的问题回答的不太好,不论是refine还是summray tree。但是对知识库里面有的问题,个人感觉refine匹配的更好一点。
Response Mode 配置(翻译自官网):
refine(细化):通过顺序处理每个检索到的文本片段来创建和完善答案。这会使每个节点/检索到的片段都进行单独的 LLM 调用。
详细信息:使用 text_qa_template 提示中的第一个片段进行查询。然后使用答案和下一个片段(以及原始问题)在另一个查询中使用 refine_template 提示。如此往复,直到所有片段都被解析。
如果一个片段太大而无法适应窗口(考虑到提示的大小),则使用 TokenTextSplitter 进行分割(允许片段之间的一些文本重叠),并将(新的)额外片段视为原始片段集合的片段(因此也使用 refine_template 进行查询)。
适用于更详细的答案。
compact(紧凑,默认):类似于 refine,但在此之前会紧凑(连接)片段,从而减少 LLM 调用。
详细信息:尽可能地将文本(从检索到的片段中连接/打包)填充到上下文窗口中(考虑到 text_qa_template 和 refine_template 之间的最大提示大小)。如果文本过长而无法适应一个提示,则根据需要分割为多个部分(使用 TokenTextSplitter 并允许一些文本片段之间的重叠)。
每个文本部分被视为“片段”,并发送到 refine 合成器。
简而言之,类似于 refine,但 LLM 调用更少。
tree_summarize(树形摘要):使用 summary_template 提示多次查询 LLM,以便对连接的所有片段进行查询,结果是产生与树形摘要 LLM 调用中的递归使用的片段相同数量的答案,直到只剩下一个片段,因此只剩下一个最终答案。
详细信息:尽可能地连接片段以适应上下文窗口,使用 summary_template 提示,并根据需要分割它们(再次使用 TokenTextSplitter 和一些文本重叠)。然后,对每个结果片段/分割使用 summary_template 进行查询(没有 refine 查询!)并获取尽可能多的答案。
如果只有一个答案(因为只有一个片段),那么它就是最终答案。
如果有多个答案,则将它们视为片段并递归地发送到 tree_summarize 过程中(连接/分割以适应/查询)。
适用于摘要目的。
simple_summarize(简单摘要):将所有文本片段截断以适应单个 LLM 提示。适用于快速摘要目的,但由于截断可能会丢失细节。
no_text(无文本):仅运行检索器以获取本应发送到 LLM 的节点,而不实际发送它们。然后可以通过检查 response.source_nodes 进行检查。
accumulate(累积):给定一组文本片段和查询,对每个文本片段应用查询,同时将响应累积到数组中。返回所有响应的连接字符串。适用于需要对每个文本片段单独运行相同查询的情况。
compact_accumulate(紧凑累积):与 accumulate 相同,但会像 compact 一样“紧凑”每个 LLM 提示,并对每个文本片段运行相同的查询。
node的rerank时间有点长,比chat_engine慢的比较多,而且跟topk和batch size等参数也有关,而rerank的效果也时好时坏,难以控制。
- def make_rerank_query_engine(index):
- query_engine = index.as_query_engine(
- similarity_top_k=6,
- node_postprocessors=[
- LLMRerank(
- choice_batch_size=3,
- top_n=2,
- )
- ],
- response_mode="tree_summarize",
- )
- return query_engine
效果变得更不好了,或许chat engine不适合rerank
- def make_rerank_chat_engine(index):
- chat_engine = index.as_chat_engine(
- chat_mode='condense_plus_context', use_async=True, system_prompt=SYSTEM_PROMPT,
- node_postprocessors=[
- LLMRerank(
- choice_batch_size=5,
- top_n=2,
- )
- ],
- # verbose=True
- )
- return chat_engine
知识库有两种:SI(summary index),refine
engine有两个:chat engine 和 query engine
node有两个选择:rerank或者不rerank
效果都不好,初步推测rerank对chat engine可能并没有正向效果
不稳定,二者各有千秋,但是主观上感觉SI可能对于chat engine来说更智能一点,但refine效果也不错,这两个很难选择...
因为rerank对query engine还是有正向效果的,所以拿来跟chat engine比较一下。
总的来说,rerank效果比较不稳定,有的问题匹配的很好,有的就不太好,而且几个数值参数影响也比较大,有一个很大的问题就是rerank需要的时间很久,比不rerank慢很多
主观感觉not rerank+SI+chat engine效果比较好。
仅代表个人观点,因为都是凭借主观感觉的,并没有一个标准打分机制:
rerank对query engine的提升还是有的,只不过要耗费多一点时间;但是对于chat engine来说还是不rerank比较好。
refine知识库和SI知识库感觉差不多,但是对于chat engine来说可能SI更灵活更智能一点?其实各有千秋,挺难选择。
随手记一个llamaindex使用技巧:如果后续需要插入index:更多细节可以查看Document Management How-To,链接:https://gpt-index.readthedocs.io/en/stable/how_to/index/document_management.html。
- from llama_index import VectorStoreIndex
-
- index = VectorStoreIndex([])
- for doc in documents:
- index.insert(doc)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。