跳到主要内容

提示

DeepSeek V3 中英对照 Prompts

**提示词(Prompts)**是引导 AI 模型生成特定输出的输入内容。这些提示词的设计和措辞会显著影响模型的响应。

在 Spring AI 中与 AI 模型进行最低级别的交互时,处理提示(prompt)的方式与在 Spring MVC 中管理“视图”(View)有些相似。这涉及到创建包含占位符的广泛文本,以便动态内容可以插入其中。然后,这些占位符会根据用户请求或应用程序中的其他代码进行替换。另一个类比是包含某些表达式占位符的 SQL 语句。

随着 Spring AI 的发展,它将引入更高层次的抽象来与 AI 模型进行交互。本节中描述的基础类在角色和功能上可以与 JDBC 相类比。例如,ChatModel 类类似于 JDK 中的核心 JDBC 库。ChatClient 类可以类比为 JdbcClient,它建立在 ChatModel 之上,并通过 Advisor 提供更高级的构造,以考虑与模型的过去交互、使用额外的上下文文档增强提示,并引入代理行为。

提示词(prompts)的结构在人工智能领域随着时间的推移而不断发展。最初,提示词仅是简单的字符串。渐渐地,它们开始包含特定输入的占位符,例如 "USER:",这些占位符被 AI 模型识别。OpenAI 进一步为提示词引入了更多结构,即在 AI 模型处理之前,将多个消息字符串分类为不同的角色。

API 概述

提示

通常使用 ChatModelcall() 方法,该方法接受一个 Prompt 实例并返回一个 ChatResponse

Prompt 类作为一个容器,用于存储一系列组织有序的 Message 对象和一个请求 ChatOptions。每个 Message 在提示中体现了一个独特的角色,其内容和意图各不相同。这些角色可以涵盖多种元素,从用户查询到 AI 生成的响应,再到相关的背景信息。这种安排使得与 AI 模型的交互更加复杂和详细,因为提示是由多个消息构建的,每个消息在对话中都被分配了特定的角色。

以下是 Prompt 类的截断版本,为了简洁起见,省略了构造函数和实用方法:

public class Prompt implements ModelRequest<List<Message>> {

private final List<Message> messages;

private ChatOptions chatOptions;
}
java

消息

Message 接口封装了一个 Prompt 文本内容、一组元数据属性以及一种称为 MessageType 的分类。

接口定义如下:

public interface Content {

String getContent();

Map<String, Object> getMetadata();
}

public interface Message extends Content {

MessageType getMessageType();
}
java

多模态消息类型也实现了 MediaContent 接口,该接口提供了一组 Media 内容对象列表。

public interface MediaContent extends Content {

Collection<Media> getMedia();

}
java

Message 接口的各种实现对应于 AI 模型可以处理的不同类别的消息。模型根据对话角色来区分消息类别。

Spring AI 消息 API

这些角色有效地通过 MessageType 进行映射,如下所述。

角色

每条消息都被赋予一个特定的角色。这些角色对消息进行分类,明确了提示中每个部分的上下文和目的,以便 AI 模型理解。这种结构化的方法增强了与 AI 沟通的细微差别和有效性,因为提示的每个部分在交互中都扮演着独特且定义明确的角色。

主要角色包括:

  • 系统角色(System Role):指导 AI 的行为和响应风格,设定 AI 如何解释和回应用户输入的参数或规则。这类似于在开始对话之前向 AI 提供指令。

  • 用户角色(User Role):代表用户的输入——他们向 AI 提出的问题、命令或陈述。这一角色至关重要,因为它构成了 AI 响应的基础。

  • 助手角色(Assistant Role):AI 对用户输入的响应。它不仅仅是一个答案或反应,更重要的是维持对话的流畅性。通过跟踪 AI 之前的响应(即其“助手角色”消息),系统确保交互的一致性和上下文相关性。助手消息还可能包含函数工具调用(Function Tool Call)请求信息。这是 AI 中的一项特殊功能,用于在需要时执行特定任务,如计算、获取数据或其他超出单纯对话的任务。

  • 工具/函数角色(Tool/Function Role):工具/函数角色专注于返回额外的信息,以响应工具调用助手消息(Tool Call Assistant Messages)。

在 Spring AI 中,角色被表示为枚举类型,如下所示

public enum MessageType {

USER("user"),

ASSISTANT("assistant"),

SYSTEM("system"),

TOOL("tool");

...
}
java

PromptTemplate

在 Spring AI 中,用于提示模板化的一个关键组件是 PromptTemplate 类。该类使用由 Terence Parr 开发的 OSS StringTemplate 引擎来构建和管理提示。PromptTemplate 类的设计旨在促进结构化提示的创建,这些提示随后会被发送到 AI 模型进行处理。

public class PromptTemplate implements PromptTemplateActions, PromptTemplateMessageActions {

// Other methods to be discussed later
}
java

该类实现的接口支持提示创建的不同方面:

PromptTemplateStringActions 专注于创建和渲染提示字符串,代表了提示生成的最基本形式。

PromptTemplateMessageActions 专为通过生成和操作 Message 对象来创建提示而设计。

PromptTemplateActions 旨在返回 Prompt 对象,该对象可以传递给 ChatModel 以生成响应。

虽然这些接口在许多项目中可能不会广泛使用,但它们展示了提示创建的不同方法。

实现的接口包括

public interface PromptTemplateStringActions {

String render();

String render(Map<String, Object> model);

}
java

方法 String render(): 将提示模板渲染为最终的字符串格式,无需外部输入,适用于没有占位符或动态内容的模板。

方法 String render(Map<String, Object> model):增强了渲染功能以包含动态内容。它使用一个 Map<String, Object>,其中映射的键是提示模板中的占位符名称,值是要插入的动态内容。

public interface PromptTemplateMessageActions {

Message createMessage();

Message createMessage(List<Media> mediaList);

Message createMessage(Map<String, Object> model);

}
java

方法 Message createMessage():创建一个不包含额外数据的 Message 对象,用于静态或预定义的消息内容。

方法 Message createMessage(List<Media> mediaList):创建一个包含静态文本和媒体内容的 Message 对象。

方法 Message createMessage(Map<String, Object> model):扩展了消息创建功能以集成动态内容,接受一个 Map<String, Object>,其中每个条目代表消息模板中的一个占位符及其对应的动态值。

public interface PromptTemplateActions extends PromptTemplateStringActions {

Prompt create();

Prompt create(ChatOptions modelOptions);

Prompt create(Map<String, Object> model);

Prompt create(Map<String, Object> model, ChatOptions modelOptions);

}
java

方法 Prompt create():生成一个 Prompt 对象,无需外部数据输入,适用于静态或预定义的提示。

方法 Prompt create(ChatOptions modelOptions):生成一个 Prompt 对象,该对象不包含外部数据输入,并且具有聊天请求的特定选项。

方法 Prompt create(Map<String, Object> model):扩展了提示创建的灵活性,使其能够包含动态内容。该方法接收一个 Map<String, Object> 参数,其中每个映射条目代表提示模板中的一个占位符及其关联的动态值。

方法 Prompt create(Map<String, Object> model, ChatOptions modelOptions):扩展了提示创建功能,以包含动态内容。它接收一个 Map<String, Object>,其中每个映射条目都是提示模板中的占位符及其关联的动态值,以及聊天请求的特定选项。

示例用法

以下是从 AI Workshop on PromptTemplates 中提取的一个简单示例。

PromptTemplate promptTemplate = new PromptTemplate("Tell me a {adjective} joke about {topic}");

Prompt prompt = promptTemplate.create(Map.of("adjective", adjective, "topic", topic));

return chatModel.call(prompt).getResult();
java

另一个例子取自 AI Workshop on Roles,如下所示。

String userText = """
Tell me about three famous pirates from the Golden Age of Piracy and why they did.
Write at least a sentence for each pirate.
""";

Message userMessage = new UserMessage(userText);

String systemText = """
You are a helpful AI assistant that helps people find information.
Your name is {name}
You should reply to the user's request with your name and also in the style of a {voice}.
""";

SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemText);
Message systemMessage = systemPromptTemplate.createMessage(Map.of("name", name, "voice", voice));

Prompt prompt = new Prompt(List.of(userMessage, systemMessage));

List<Generation> response = chatModel.call(prompt).getResults();
java

以下展示了如何使用 SystemPromptTemplate 构建 Prompt 实例,通过传入占位符值来创建具有系统角色的 Message。然后,将具有 user 角色的消息与具有 system 角色的消息结合,形成提示(prompt)。接着,将该提示传递给 ChatModel,以获取生成式响应。

使用资源而非原始字符串

Spring AI 支持 org.springframework.core.io.Resource 抽象,因此你可以将提示数据放在文件中,并直接在 PromptTemplate 中使用。例如,你可以在 Spring 管理的组件中定义一个字段来检索 Resource

@Value("classpath:/prompts/system-message.st")
private Resource systemResource;
java

然后将该资源直接传递给 SystemPromptTemplate

SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource);
java

提示工程

在生成式 AI 中,创建提示是开发者的一项关键任务。这些提示的质量和结构会显著影响 AI 输出的效果。投入时间和精力设计深思熟虑的提示可以极大地提升 AI 的结果。

在 AI 社区中,分享和讨论提示词是一种常见的做法。这种协作方式不仅创造了一个共享的学习环境,还导致了高效提示词的识别和使用。

该领域的研究通常涉及分析和比较不同的提示,以评估它们在不同情况下的有效性。例如,一项重要的研究表明,以“深呼吸,然后一步一步地解决这个问题”开头的提示显著提高了问题解决的效率。这突显了精心选择的语言对生成式 AI 系统性能的影响。

掌握提示词(prompt)的最有效使用,尤其是在人工智能技术快速发展的背景下,是一个持续的挑战。您应该认识到提示词工程(prompt engineering)的重要性,并考虑利用社区和研究的见解来改进提示词创建策略。

创建有效的提示

在开发提示(prompts)时,整合几个关键组件以确保清晰性和有效性非常重要:

  • 指令:向 AI 提供清晰且直接的指令,类似于你与一个人沟通的方式。这种清晰度对于帮助 AI “理解”期望内容至关重要。

  • 外部上下文:在必要时,包含相关的背景信息或特定的指导,以帮助 AI 理解整体场景。这种“外部上下文”为提示提供了框架,并有助于 AI 更好地把握情境。

  • 用户输入:这是最直接的部分——用户的核心请求或问题,构成了提示的核心内容。

  • 输出指示器:这一部分可能较为复杂。它涉及指定 AI 响应的所需格式,例如 JSON。但需要注意的是,AI 可能并不总是严格遵守这种格式。例如,它可能会在实际的 JSON 数据前加上类似“这是你的 JSON”的短语,或者有时生成一个不准确的类似 JSON 的结构。

在为 AI 设计提示时,提供预期的问答格式示例可能非常有益。这种做法有助于 AI “理解”查询的结构和意图,从而产生更精确和相关的响应。虽然本文档没有深入探讨这些技术,但它们为进一步探索 AI 提示工程提供了一个起点。

以下是进一步研究的资源列表。

简单技巧

  • 文本摘要:
    将大量文本缩减为简洁的摘要,捕捉关键点和主要思想,同时省略不太重要的细节。

  • 问答:
    专注于从提供的文本中根据用户提出的问题推导出具体答案。它的重点是精确定位和提取与查询相关的信息。

  • 文本分类:
    系统地将文本分类到预定义的类别或组中,分析文本并根据其内容将其分配到最合适的类别。

  • 对话:
    创建交互式对话,AI 可以与用户进行来回交流,模拟自然的对话流程。

  • 代码生成:
    根据特定的用户需求或描述生成功能代码片段,将自然语言指令翻译为可执行代码。

高级技巧

  • Zero-shot, Few-shot Learning:
    使模型能够在几乎没有特定问题类型的先验示例的情况下做出准确的预测或响应,利用学习到的泛化能力理解和执行新任务。

  • Chain-of-Thought:
    将多个 AI 响应链接起来,创建连贯且具有上下文感知的对话。它帮助 AI 保持讨论的线索,确保相关性和连续性。

  • ReAct (Reason + Act):
    在这种方法中,AI 首先分析(推理)输入,然后确定最合适的行动或响应。它将理解与决策结合起来。

Microsoft 指导

  • 提示创建与优化框架:
    Microsoft 提供了一种结构化的方法来开发和优化提示。该框架指导用户创建有效的提示,以从 AI 模型中引出所需的响应,从而优化交互的清晰度和效率。

代币

Token 在 AI 模型处理文本的过程中起着至关重要的作用,它们充当了将我们理解的单词转换为 AI 模型可以处理的格式的桥梁。这种转换分为两个阶段:输入时单词被转换为 token,输出时这些 token 又被转换回单词。

Tokenization,即将文本分解为 token 的过程,是 AI 模型理解和处理语言的基础。AI 模型通过这种 token 化格式来理解和响应提示。

为了更好地理解 token,你可以将它们视为单词的一部分。通常,一个 token 大约代表一个单词的四分之三。例如,莎士比亚的全集大约有 90 万字,这大约会转化为 120 万个 token。

实验一下 OpenAI Tokenizer UI,看看单词是如何被转换成 token 的。

除了在 AI 处理中的技术角色外,Tokens 在实际应用中还有其他重要意义,尤其是在计费和模型能力方面:

  • 计费:AI 模型服务通常基于 token 使用量计费。输入(prompt)和输出(response)都会计入总 token 数,因此较短的 prompt 更具成本效益。

  • 模型限制:不同的 AI 模型有不同的 token 限制,这定义了它们的“上下文窗口”——即它们一次可以处理的最大信息量。例如,GPT-3 的限制是 4K token,而其他模型如 Claude 2 和 Meta Llama 2 的限制为 100K token,一些研究模型甚至可以处理多达 100 万 token。

  • 上下文窗口:模型的 token 限制决定了它的上下文窗口。超过此限制的输入不会被模型处理。因此,发送仅包含最小有效信息集进行处理至关重要。例如,当询问关于《哈姆雷特》时,无需包含莎士比亚其他作品中的所有 token。

  • 响应元数据:AI 模型响应的元数据包括使用的 token 数量,这是管理使用量和成本的重要信息。