提示词使用模式#
使用 RichPromptTemplate
和 Jinja 语法#
通过利用 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-string 的主要区别在于变量现在使用双大括号 {{ }}
,而不是单大括号 { }
。
我们来看一个更复杂的例子,它使用循环来生成多模态提示词。
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
提示词模板#
截至本文撰写之时,许多旧组件和示例会使用 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_template
和 refine_template
。
text_qa_template
- 用于使用检索到的节点获取查询的初始答案refine_template
- 当检索到的文本不适合在response_mode="compact"
(默认)下进行单个 LLM 调用时,或当使用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']
请注意,提示词会以其子模块作为“命名空间”进行前缀。
更新提示词#
您可以使用 update_prompts
函数自定义任何实现 get_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}
)
修改查询引擎中使用的提示词#
对于查询引擎,您还可以在查询时直接传入自定义提示词(即,对索引执行查询并合成最终响应)。
还有两种等效的方法可以覆盖提示词
- 通过高级 API
query_engine = index.as_query_engine(
text_qa_template=custom_qa_prompt, refine_template=custom_refine_prompt
)
- 通过低层级组合 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 来获得更精细的控制。
有关哪些类使用哪些提示词的更多详细信息,请访问查询类参考。
请查看参考文档,了解所有提示词及其方法/参数的完整集。
[高级] 高级 Prompt 能力#
在本节中,我们将展示 LlamaIndex 中的一些高级 prompt 能力。
相关指南
函数映射#
将函数作为模板变量传入,而非固定值。
这非常高级且强大;它允许您执行动态 few-shot prompt 等。
这是一个重新格式化 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")
部分格式化#
部分格式化 prompt,填写一些变量,而将其他变量留待稍后填写。
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 的 prompt 抽象通常期望某些键。例如,我们的 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")