Skip to content

提示词使用模式#

使用 RichPromptTemplate 和 Jinja 语法#

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

让我们看几个示例:

from llama_index.core.prompts import RichPromptTemplate

template = RichPromptTemplate(
    """我们提供了以下上下文信息。
---------------------
{{ context_str }}
---------------------
根据这些信息,请回答问题:{{ query_str }}
"""
)

# 格式化为字符串
prompt_str = template.format(context_str=..., query_str=...)

# 格式化为聊天消息列表
messages = template.format_messages(context_str=..., query_str=...)

Jinja 提示词与 f-string 的主要区别在于变量现在使用双括号 {{ }} 而不是单括号 { }

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

from llama_index.core.prompts import RichPromptTemplate

template = RichPromptTemplate(
    """
{% chat role="system" %}
给定一组图像及其对应的文本描述,请尽可能准确地回答问题。
{% endchat %}

{% chat role="user" %}
{% for image_path, text in images_and_texts %}
以下是文本内容:{{ text }}
这是对应的图像:
{{ image_path | image }}
{% endfor %}
{% endchat %}
"""
)

messages = template.format_messages(
    images_and_texts=[
        ("page_1.png", "这是文档的第一页"),
        ("page_2.png", "这是文档的第二页"),
    ]
)

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

  • {% chat %} 块用于将消息格式化为聊天消息并设置角色
  • {% for %} 循环用于遍历传入的 images_and_texts 列表
  • {{ image_path | image }} 语法用于将图像路径格式化为图像内容块。这里的 | 用于对变量应用"过滤器"以标识其为图像

再看一个示例,这次是为检索器节点创建模板:

from llama_index.core.prompts import RichPromptTemplate

template = RichPromptTemplate(
    """
{% chat role="system" %}
您是一个能够根据提供的上下文回答问题的助手。
{% endchat %}

{% chat role="user" %}
{% for node in nodes %}
{{ node.text }}
{% endfor %}
{% endchat %}
"""
)

nodes = retriever.retrieve("月亮的首都是什么?")

messages = template.format_messages(nodes=nodes)

使用 f-string 提示词模板#

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

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

from llama_index.core import PromptTemplate

template = (
    "我们提供了以下上下文信息。\n"
    "---------------------\n"
    "{context_str}"
    "\n---------------------\n"
    "根据这些信息,请回答问题:{query_str}\n"
)
qa_template = PromptTemplate(template)

# 可以创建文本提示词(用于补全API)
prompt = qa_template.format(context_str=..., query_str=...)

# 或轻松转换为消息提示词(用于聊天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="您是一个专家系统。", role=MessageRole.SYSTEM),
    ChatMessage(
        content="生成一个关于{topic}的短篇故事",
        role=MessageRole.USER,
    ),
]
chat_template = ChatPromptTemplate(message_templates=message_templates)

# 可以创建消息提示词(用于聊天API)
messages = chat_template.format_messages(topic=...)

# 或轻松转换为文本提示词(用于补全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 获得的提示词字典中的键。

例如,对于上面的示例,我们可以这样做:

# 莎士比亚风格!
qa_prompt_tmpl_str = (
    "上下文信息如下。\n"
    "---------------------\n"
    "{{ context_str }}\n"
    "---------------------\n"
    "根据上下文信息而非先验知识,"
    "以莎士比亚戏剧的风格回答问题。\n"
    "查询:{{ query_str }}\n"
    "回答:"
)
qa_prompt_tmpl = RichPromptTemplate(qa_prompt_tmpl_str)

query_engine.update_prompts(
    {"response_synthesizer:text_qa_template": qa_prompt_tmpl}
)

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

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

有两种等效的方法可以覆盖提示词:

  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):
    # 用项目符号格式化上下文
    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(
    "这是上下文:{{ context_str }} 这是查询:{{ query_str }}",
    template_var_mappings=template_var_mappings,
)

prompt_str = prompt_tmpl.format(my_context="context", my_query="query")