提示词使用模式#
使用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字符串的主要区别在于变量现在使用双括号{{ }}
而非单括号{ }
。
让我们看一个更复杂的示例,它使用循环生成多模态提示。
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']
请注意,提示词会以其所属子模块作为"命名空间"进行前缀标注。
更新提示词#
你可以在任何实现了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}
)
修改查询引擎中使用的提示词#
对于查询引擎,您还可以在查询时直接传入自定义提示(即针对索引执行查询并合成最终响应)。
还有两种等效的方式来覆盖提示词:
- 通过高级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则能进行更精细的控制。
有关哪些类使用哪些提示的更多详情,请访问 查询类参考。
查看参考文档获取所有提示及其方法/参数的完整集合。
[高级] 高级提示功能#
在本节中,我们将展示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")