响应合成器#
概念#
响应合成器
(Response Synthesizer)是通过用户查询和给定文本块集合,利用大语言模型(LLM)生成响应的组件。其输出是一个Response
对象。
实现方式多种多样,从简单的文本块迭代到复杂的树状结构构建。核心目标是简化基于数据使用LLM生成响应的流程。
在查询引擎中,响应合成器在检索器获取节点后执行,且在所有节点后处理器运行完毕后生效。
Tip
不清楚响应合成器在RAG工作流中的位置?请阅读高层概念
使用模式#
单独使用响应合成器:
from llama_index.core.data_structs import Node
from llama_index.core.response_synthesizers import ResponseMode
from llama_index.core import get_response_synthesizer
response_synthesizer = get_response_synthesizer(
response_mode=ResponseMode.COMPACT
)
response = response_synthesizer.synthesize(
"query text", nodes=[Node(text="text"), ...]
)
或在创建索引后通过查询引擎使用:
query_engine = index.as_query_engine(response_synthesizer=response_synthesizer)
response = query_engine.query("query_text")
下文将详细介绍所有可用的响应合成器、模式及自定义方法。
使用模式#
快速开始#
通过response_mode
配置查询引擎的响应合成器:
from llama_index.core.data_structs import Node
from llama_index.core.schema import NodeWithScore
from llama_index.core import get_response_synthesizer
response_synthesizer = get_response_synthesizer(response_mode="compact")
response = response_synthesizer.synthesize(
"query text", nodes=[NodeWithScore(node=Node(text="text"), score=1.0), ...]
)
更常见的用法是在创建索引后通过查询引擎使用:
query_engine = index.as_query_engine(response_synthesizer=response_synthesizer)
response = query_engine.query("query_text")
Tip
学习如何构建索引,请参阅索引构建
配置响应模式#
响应合成器通常通过response_mode
参数指定。LlamaIndex已实现多种响应模式:
refine
:通过顺序处理每个检索到的文本块来创建并优化答案。每个节点/文本块都会触发独立的LLM调用。
细节: 首个文本块使用text_qa_template
提示词进行查询。随后将答案与下一个文本块(及原始问题)结合,使用refine_template
提示词进行二次查询。该过程循环直至处理完所有文本块。
若文本块超出上下文窗口限制(考虑提示词大小),则使用TokenTextSplitter
进行分割(允许文本块间存在重叠),新增块将作为原始集合的一部分继续参与refine_template
查询。
适用于需要详细答案的场景。
compact
(默认模式):类似refine
,但会预先压缩(连接)文本块,减少LLM调用次数。
细节: 将检索到的文本块尽可能多地拼接至上下文窗口(考虑text_qa_template
和refine_template
的最大提示词尺寸)。若文本过长,则使用TokenTextSplitter
分割为多个部分(允许部分重叠)。
每个文本部分视为独立"块"并发送至refine
合成器。简言之,这是减少LLM调用次数的优化版refine
。
tree_summarize
:使用summary_template
提示词递归查询LLM,直到最终生成单一答案。
细节: 尽可能拼接文本块至上下文窗口限制(使用summary_template
提示词),必要时进行分割(使用带重叠的TokenTextSplitter
)。随后查询每个生成的块/分割(不进行_refine_查询)获取多个答案。
若仅剩一个答案则直接返回;否则将这些答案视为新文本块递归执行tree_summarize
流程。
适用于摘要场景。
simple_summarize
:截断所有文本块以适应单次LLM提示词。适合快速摘要,但可能因截断丢失细节。no_text
:仅运行检索器获取节点而不发送至LLM。可通过检查response.source_nodes
查看结果。context_only
:返回所有文本块的连接字符串。accumulate
:对每个文本块分别应用查询并累积响应为数组。返回所有响应的连接字符串。适用于需对每个文本块独立运行相同查询的场景。compact_accumulate
:类似accumulate,但会像compact
模式那样压缩每个LLM提示词。
自定义响应合成器#
所有响应合成器均继承自llama_index.response_synthesizers.base.BaseSynthesizer
。基础API极其简洁,便于创建自定义合成器。
无论是想定制tree_summarize
各阶段的模板,还是根据新研究论文实现创新查询响应方式,您都可以创建专属合成器并集成至任意查询引擎,或单独使用。
以下展示__init__()
函数及必须实现的抽象方法。基本要求是处理查询和文本块,并返回字符串(或字符串生成器)响应。
from llama_index.core import Settings
class BaseSynthesizer(ABC):
"""Response builder class."""
def __init__(
self,
llm: Optional[LLM] = None,
streaming: bool = False,
) -> None:
"""Init params."""
self._llm = llm or Settings.llm
self._callback_manager = Settings.callback_manager
self._streaming = streaming
@abstractmethod
def get_response(
self,
query_str: str,
text_chunks: Sequence[str],
**response_kwargs: Any,
) -> RESPONSE_TEXT_TYPE:
"""Get response."""
...
@abstractmethod
async def aget_response(
self,
query_str: str,
text_chunks: Sequence[str],
**response_kwargs: Any,
) -> RESPONSE_TEXT_TYPE:
"""Get response."""
...
使用结构化答案过滤功能#
当使用 "refine"
或 "compact"
响应合成模块时,您可以尝试启用 structured_answer_filtering
选项以获得更好的效果。
from llama_index.core import get_response_synthesizer
response_synthesizer = get_response_synthesizer(structured_answer_filtering=True)
将 structured_answer_filtering
设为 True
后,refine 模块能够过滤掉与当前问题无关的输入节点。这对于基于 RAG 的问答系统特别有用,这类系统需要从外部向量存储中检索文本块来响应用户查询。
如果您使用的是支持函数调用的 OpenAI 模型,此选项将尤为实用。其他不具备原生函数调用支持的 LLM 提供商或模型在生成该功能依赖的结构化响应时可能可靠性较低。
使用自定义提示模板(含附加变量)#
您可能需要自定义响应合成器中使用的提示模板,并在查询时添加额外变量。
这些附加变量可以通过 get_response
的 **kwargs
参数指定。
例如:
from llama_index.core import PromptTemplate
from llama_index.core.response_synthesizers import TreeSummarize
# 注意:这里我们添加了一个额外的 tone_name 变量
qa_prompt_tmpl = (
"上下文信息如下。\n"
"---------------------\n"
"{context_str}\n"
"---------------------\n"
"请仅根据上下文信息(不使用先验知识)"
"回答查询。\n"
"并请使用{tone_name}的语气风格作答。\n"
"查询:{query_str}\n"
"回答:"
)
qa_prompt = PromptTemplate(qa_prompt_tmpl)
# 初始化响应合成器
summarizer = TreeSummarize(verbose=True, summary_template=qa_prompt)
# 获取响应
response = summarizer.get_response(
"who is Paul Graham?", [text], tone_name="莎士比亚戏剧"
)
模块#
更多详细信息请参阅完整的模块指南。