响应器(response_synthesizer)负责把最终节点列表 + 用户问题拼成提示词,调用大模型生成自然语言答案。它不参与检索、不过滤、不重排,只在链路最末端做“阅读-理解-回答”。
from llama_index.core import VectorStoreIndex, get_response_synthesizer
response_synthesizer = get_response_synthesizer()
query_engine = RetrieverQueryEngine(
retriever=retriever,
response_synthesizer=response_synthesizer, #响应器默认
node_postprocessors=[...] # 各种过滤器/重排/扩上下文
)
node_postprocessors处理完的节点 → response_synthesizer→ LLM→ 返回 Response
A 把节点文本切成 text_qa_template 能容纳的 token 窗口
B 响应器的两种工作状态
1.全部打包(compact 默认)
2.分块迭代(refine 先拿第一段生成初版答案,再依次把后续段落 refine 进去)
C 拼好 prompt → 调 Settings.llm.complete() → 解析返回内容 → 包成 Response 对象
更换策略 从默认的compact 变为refine
response_synthesizer = get_response_synthesizer(
response_mode="refine", # 或 "compact", "tree_summarize", "simple_summarize", "no_text"
llm=Ollama(model="qwen3-14b") # 用更大的模型专门负责生成答案
)
还可以自定义prompt模板 ,精华部分!默认compact使用text_qa_template参数;refine模式使用refine_template模板设置。
from llama_index.core import PromptTemplate
qa_tmpl = PromptTemplate(
"你是小助手,请依据下列资料回答,若信息不足请说“不知道”。\n"
"资料:{context_str}\n问题:{query_str}\n答案:"
)
response_synthesizer = get_response_synthesizer(
text_qa_template=qa_tmpl,
refine_template=... # 如果选 refine 模式再配 refine 模板
)
这两个占位符:
{context_str}– 框架会把“经过所有 postprocessor 处理后的节点文本”自动拼成一段塞进来{query_str}– 用户当前的问题
下面的模板
资料:{context_str}
问题:{query_str}
答案:
添加文章来源
在 LlamaIndex 里想“给答案加引用”有两种常用做法,都只需要改响应合成器的模板,让它把节点自带的 metadata 打印出来即可;
因此metadata数据的完善性尤为重要:
文件名称,创建时间,修改时间,上传时间,上传人,上传部门,文件类型,机密类型,hash值,上传的IP
from llama_index.core import PromptTemplate
# {file_name} 就是 metadata 里的字段,可随意加
cite_tmpl = PromptTemplate(
"资料:{context_str}\n\n"
"问题:{query_str}\n\n"
"答案:\n"
"----------\n"
"出处:{file_name}" # 这里会被替换成真实文件名
)
response_synthesizer = get_response_synthesizer(
text_qa_template=cite_tmpl,
response_mode="compact"
)
现实来源总结
- 有字段 → 自动替换
- 无字段 → 原样保留占位符
- 不会报错,也不会自动补空值