跳转到内容

提示词使用模式

使用 RichPromptTemplate 和 Jinja 语法

Section titled “Using RichPromptTemplate and Jinja Syntax”

通过利用Jinja语法,您可以构建包含变量、逻辑、解析对象等功能的提示模板。

让我们来看几个示例:

from llama_index.core.prompts import RichPromptTemplate
template = RichPromptTemplate(
"""We have provided context information below.
---------------------
{{ context_str }}
---------------------
Given this information, please answer the question: {{ query_str }}
"""
)
# format as a string
prompt_str = template.format(context_str=..., query_str=...)
# format as a list of chat messages
messages = template.format_messages(context_str=..., query_str=...)

Jinja 模板与 f-strings 的主要区别在于变量现在使用双花括号 {{ }} 而非单花括号 { }

让我们来看一个更复杂的示例,它使用循环生成多模态提示。

from llama_index.core.prompts import RichPromptTemplate
template = RichPromptTemplate(
"""
{% chat role="system" %}
Given a list if images and text from each image, please answer the question to the best of your ability.
{% endchat %}
{% chat role="user" %}
{% for image_path, text in images_and_texts %}
Here is some text: {{ text }}
And here is an image:
{{ image_path | image }}
{% endfor %}
{% endchat %}
"""
)
messages = template.format_messages(
images_and_texts=[
("page_1.png", "This is the first page of the document"),
("page_2.png", "This is the second page of the document"),
]
)

在这个示例中,你可以看到几个特性:

  • {% chat %} 代码块用于将消息格式化为聊天消息并设置角色
  • {% for %} 循环用于遍历传入的 images_and_texts 列表
  • 使用 {{ image_path | image }} 语法将图像路径格式化为图像内容块。此处,| 用于对变量应用“过滤器”以帮助将其识别为图像。

让我们来看另一个示例,这次是关于使用检索器中的节点创建模板:

from llama_index.core.prompts import RichPromptTemplate
template = RichPromptTemplate(
"""
{% chat role="system" %}
You are a helpful assistant that can answer questions about the context provided.
{% endchat %}
{% chat role="user" %}
{% for node in nodes %}
{{ node.text }}
{% endfor %}
{% endchat %}
"""
)
nodes = retriever.retrieve("What is the capital of the moon?")
messages = template.format_messages(nodes=nodes)

截至本文撰写时,许多旧版组件和示例仍将使用 f-string 提示。

定义自定义提示就像创建一个格式化字符串一样简单

from llama_index.core import PromptTemplate
template = (
"We have provided context information below. \n"
"---------------------\n"
"{context_str}"
"\n---------------------\n"
"Given this information, please answer the question: {query_str}\n"
)
qa_template = PromptTemplate(template)
# you can create text prompt (for completion API)
prompt = qa_template.format(context_str=..., query_str=...)
# or easily convert to message prompts (for chat API)
messages = qa_template.format_messages(context_str=..., query_str=...)

您也可以从聊天消息中定义一个模板

from llama_index.core import ChatPromptTemplate
from llama_index.core.llms import ChatMessage, MessageRole
message_templates = [
ChatMessage(content="You are an expert system.", role=MessageRole.SYSTEM),
ChatMessage(
content="Generate a short story about {topic}",
role=MessageRole.USER,
),
]
chat_template = ChatPromptTemplate(message_templates=message_templates)
# you can create message prompts (for chat API)
messages = chat_template.format_messages(topic=...)
# or easily convert to text prompt (for completion API)
prompt = chat_template.format(topic=...)

由于LlamaIndex是一个多步骤的流水线,识别您想要修改的操作并在正确位置传入自定义提示非常重要。

例如,提示词被用于响应合成器、检索器、索引构建等模块;其中部分模块嵌套在其他模块中(合成器嵌套在查询引擎中)。

查看本指南了解访问/自定义提示的完整详情。

最常用的提示词将是 text_qa_templaterefine_template

  • text_qa_template - 用于通过检索到的节点获取查询的初始答案
  • refine_template - 当检索到的文本无法通过单次LLM调用(使用默认的response_mode="compact")容纳时,或当使用response_mode="refine"检索到多个节点时使用。第一个查询的答案将作为existing_answer插入,LLM必须根据新上下文更新或重复现有答案。

您可以在LlamaIndex的许多模块上调用get_prompts,以获取该模块及嵌套子模块中使用的扁平化提示列表。

例如,请看以下代码片段。

query_engine = index.as_query_engine(response_mode="compact")
prompts_dict = query_engine.get_prompts()
print(list(prompts_dict.keys()))

您可能会得到以下键:

['response_synthesizer:text_qa_template', 'response_synthesizer:refine_template']

请注意,提示词会以其子模块作为“命名空间”进行前缀标识。

您可以在任何实现 get_prompts 的模块上使用 update_prompts 函数自定义提示词。只需传入参数值,其键名与通过 get_prompts 获取的提示词字典中显示的键名保持一致。

例如,针对上述示例,我们可能会执行以下操作

# shakespeare!
qa_prompt_tmpl_str = (
"Context information is below.\n"
"---------------------\n"
"{{ context_str }}\n"
"---------------------\n"
"Given the context information and not prior knowledge, "
"answer the query in the style of a Shakespeare play.\n"
"Query: {{ query_str }}\n"
"Answer: "
)
qa_prompt_tmpl = RichPromptTemplate(qa_prompt_tmpl_str)
query_engine.update_prompts(
{"response_synthesizer:text_qa_template": qa_prompt_tmpl}
)

修改查询引擎中使用的提示词

Section titled “Modify prompts used in query engine”

对于查询引擎,您也可以在查询时直接传入自定义提示(即针对索引执行查询并合成最终响应)。

还有两种等效的方式来覆盖提示词:

  1. 通过高级API
query_engine = index.as_query_engine(
text_qa_template=custom_qa_prompt, refine_template=custom_refine_prompt
)
  1. 通过底层组合API
retriever = index.as_retriever()
synth = get_response_synthesizer(
text_qa_template=custom_qa_prompt, refine_template=custom_refine_prompt
)
query_engine = RetrieverQueryEngine(retriever, response_synthesizer)

以上两种方法是等效的,其中方法1本质上是方法2的语法糖,隐藏了底层的复杂性。您可能希望使用方法1来快速修改某些常见参数,而使用方法2来进行更细粒度的控制。

有关哪些类使用哪些提示的更多详细信息,请访问 查询类参考

查看参考文档获取完整提示词及其方法/参数的全套信息。

在本节中,我们将展示LlamaIndex中的一些高级提示功能。

相关指南:

将函数作为模板变量传入,而非固定值。

这相当先进且功能强大;允许您进行动态少样本提示等操作。

以下是一个重新格式化 context_str 的示例。

from llama_index.core.prompts import RichPromptTemplate
def format_context_fn(**kwargs):
# format context with bullet points
context_list = kwargs["context_str"].split("\n\n")
fmtted_context = "\n\n".join([f"- {c}" for c in context_list])
return fmtted_context
prompt_tmpl = RichPromptTemplate(
"{{ context_str }}", function_mappings={"context_str": format_context_fn}
)
prompt_str = prompt_tmpl.format(context_str="context", query_str="query")

部分格式化提示,填充部分变量,同时保留其他变量供后续填充。

from llama_index.core.prompts import RichPromptTemplate
template = RichPromptTemplate(
"""
{{ foo }} {{ bar }}
"""
)
partial_prompt_tmpl = template.partial_format(foo="abc")
fmt_str = partial_prompt_tmpl.format(bar="def")

LlamaIndex 提示抽象通常期望特定的键。例如,我们的 text_qa_prompt 期望 context_str 作为上下文,query_str 作为用户查询。

但如果你试图将一个字符串模板适配到LlamaIndex中使用,更换模板变量可能会很麻烦。

相反,定义 template_var_mappings

from llama_index.core.prompts import RichPromptTemplate
template_var_mappings = {"context_str": "my_context", "query_str": "my_query"}
prompt_tmpl = RichPromptTemplate(
"Here is some context: {{ context_str }} and here is a query: {{ query_str }}",
template_var_mappings=template_var_mappings,
)
prompt_str = prompt_tmpl.format(my_context="context", my_query="query")