第七章 Spring AI API中文版 - prompts

Spring AI > Spring AI API > Prompts

大家可以直接看官网:https://docs.spring.io/spring-ai/reference/api/prompt.html

Prompts

提示是指导AI模型生成特定输出的输入。这些提示的设计和措辞显著影响模型的响应。

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

随着Spring AI的发展,它将引入与AI模型交互的更高级别的抽象。本节描述的基础类可以类比为JDBC在其角色和功能上。例如,ChatClient类类似于JDK中的核心JDBC库。在此基础上,Spring AI可以提供类似于JdbcTemplate、Spring Data Repositories的辅助类,最终还有考虑与模型过去交互的更高级的结构,如ChatEngines和Agents。

提示的结构在AI领域内随着时间的推移而发展。最初,提示是简单的字符串。随着时间的推移,它们发展到包括特定输入的占位符,如“AI:”,AI模型可以据此做出相应的响应。OpenAI通过将多个消息字符串分类为不同的角色,然后再由AI模型处理,引入了更多结构化的提示方法。

API概览

提示

通常使用ChatClient的generate方法,该方法接受一个Prompt实例并返回一个ChatResponse。

Prompt类作为一个容器,包含一系列有组织的消息对象,每个对象形成提示的一个部分。每个Message在提示中扮演一个独特的角色,其内容和意图各不相同。这些角色可以包括各种元素,从用户询问到AI生成的响应或相关的背景信息。这种安排使得与AI模型的复杂和详细交互成为可能,因为提示是由多个消息构建的,每个消息在对话中扮演一个特定的角色。

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

public class Prompt {

    private final List<Message> messages;

    // constructors and utility methods omitted
}

消息

Message接口封装了一个文本消息、一个属性集合作为Map、一个称为MessageType的分类,以及对于那些多模态模型的媒体对象列表。接口定义如下:

public interface Message {

	String getContent();

	List<Media> getMedia();

	Map<String, Object> getProperties();

	MessageType getMessageType();

}

AI模型可以处理的各种消息类型的不同实现。一些模型,如来自OpenAI的模型,根据会话角色区分消息类别。这些角色通过MessageType有效映射,如下所述。

角色

AI中提示的发展已经从基本的、直接的文本转变为具有特定角色和结构的更有组织和复杂的格式。

最初,提示是简单的字符串——只是文本行。随着时间的推移,这发展到包括这些字符串中的特定占位符,如“用户:”,AI模型可以据此做出相应的响应。这是朝着更结构化提示迈出的一步。

OpenAI随后引入了一种更有组织的方法。在他们的模型中,提示不仅仅是单个字符串,而是一系列消息。尽管每个消息仍然是文本形式,但被分配了一个特定的角色。这些角色对消息进行分类,为AI模型澄清了每个提示段的上下文和目的。这种结构化的方法增强了与AI沟通的细微差别和有效性,因为提示的每个部分在交互中都扮演了一个独特而明确的角色。

主要角色包括:

系统角色:指导AI的行为和响应风格,为AI解释和回复输入设置参数或规则。这类似于在开始对话之前向AI提供指令。

用户角色:代表用户的输入——他们的问题、命令或对AI的陈述。这个角色是基础,因为它构成了AI响应的基础。

助手角色:AI对用户输入的响应。不仅仅是一个答案或反应,对于维持对话的流畅性至关重要。通过跟踪AI之前的响应(其“助手角色”消息),系统确保交互是连贯和上下文相关的。

功能角色:这个角色处理对话中的特定任务或操作。虽然系统角色设置了AI的总体行为,但功能角色专注于执行用户要求的某些动作或命令。这就像AI中的一个特殊功能,需要时用于执行特定功能,如计算、获取数据或其他超出仅仅对话的任务。这个角色允许AI除了对话响应之外,还提供实际帮助。

在Spring AI中,角色以枚举的形式表示,如下所示:

public enum MessageType {

	USER("user"),

	ASSISTANT("assistant"),

	SYSTEM("system"),

	FUNCTION("function");

	private final String value;

	MessageType(String value) {
		this.value = value;
	}

	public String getValue() {
		return value;
	}

	public static MessageType fromValue(String value) {
		for (MessageType messageType : MessageType.values()) {
			if (messageType.getValue().equals(value)) {
				return messageType;
			}
		}
		throw new IllegalArgumentException("Invalid MessageType value: " + value);
	}

}

提示模板

Spring AI中提示模板的关键组件是PromptTemplate类。这个类使用由Terence Parr开发的StringTemplate引擎来构建和管理提示。

PromptTemplate类旨在便于创建结构化的提示,然后将这些提示发送给AI模型进行处理。

public class PromptTemplate implements PromptTemplateActions, PromptTemplateMessageActions {

    // Other methods to be discussed later
}

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

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

PromptTemplateMessageActions专门用于通过生成和操作Message对象来创建提示。

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

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

实现的接口是:

public interface PromptTemplateStringActions {

	String render();

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

}

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

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

public interface PromptTemplateMessageActions {

	Message createMessage();

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

}

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

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

public interface PromptTemplateActions extends PromptTemplateStringActions {

	Prompt create();

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

}

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

方法Prompt create(Map<String, Object> model):扩展提示创建功能以包括动态内容,接受一个Map,其中每个map条目是提示模板中的占位符及其相关的动态值。

示例使用

以下是一个简单的示例,取自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 chatClient.call(prompt).getResult();

另一个示例取自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 response = chatClient.call(prompt).getResults();

这展示了如何通过使用SystemPromptTemplate创建具有系统角色的消息并传递占位符值来构建Prompt实例。然后,将具有用户角色的消息与具有系统角色的消息结合起来形成提示。然后将提示传递给ChatClient以获得生成性响应。

使用资源而不是原始字符串

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

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

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

SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource);

提示工程

在生成性AI中,创建提示是开发者的关键任务。这些提示的质量和结构显著影响AI输出的有效性。投入时间和精力设计周到的提示可以极大地改善AI的结果。

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

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

掌握提示的有效使用,特别是随着AI技术的快速发展,是一个持续的挑战。您应该认识到提示工程的重要性,并考虑使用社区和研究的见解来改进提示创建策略。

创建有效的提示

在开发提示时,重要的是整合几个关键组件,以确保清晰和有效性:

指令:向AI提供清晰直接的指令,类似于您如何与人交流。这种清晰度
对于帮助AI“理解”预期非常重要。

外部上下文:在必要时包括相关的背景信息或对AI响应的具体指导。这种“外部上下文”为提示提供了框架,并帮助AI把握整体场景。

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

输出指示:这个方面可能有些棘手。它涉及指定AI响应的期望格式,例如JSON。但是,请注意,AI可能不总是严格遵循这种格式。例如,它可能在实际JSON数据之前加上一个短语,如“这是你的JSON”,或者有时生成一个类似JSON的结构,但不是准确的。在制作提示时,提供AI预期问题和答案格式的示例可能非常有益。这种做法帮助AI“理解”您的查询的结构和意图,从而产生更精确和相关的响应。虽然这份文档没有深入探讨这些技术,但它们为进一步探索AI提示工程提供了起点。

以下是一些资源列表,供进一步调查。

简单技术

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

问题回答:+ 专注于从提供的文本中得出特定答案,基于用户提出的问题。它是关于根据查询精确定位和提取相关信息。

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

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

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

高级技术

[Few-shot Learning](https://www.promptingguide.ai/techniques/zeroshot[Zero-shot], https://www.promptingguide.ai/techniques/fewshot):+ 使模型能够在对特定问题类型的示例最少或没有的情况下进行准确的预测或响应,利用学习的概括来理解和处理新任务。

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

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

微软指导

提示创建和优化框架

微软提供了一个结构化的方法来开发和完善提示。这个框架指导用户创建有效的提示,从AI模型中引出期望的响应,优化交互以实现清晰和高效。

标记

标记在AI模型处理文本的方式中至关重要,它们作为一座桥梁,将单词(按我们的理解)转换为AI模型可以处理的格式。这种转换分为两个阶段:单词在输入时被转换为标记,然后这些标记在输出时再转换回单词。

将文本分解为标记的过程是AI模型理解和处理语言的基础。AI模型使用这种标记化格式来理解和响应提示。

为了更好地理解标记,可以将它们视为单词的部分。通常,一个标记代表大约四分之三的单词。例如,莎士比亚的全部作品,总计约90万字,将转换为大约120万个标记。

尝试使用OpenAI Tokenizer UI,看看单词是如何转换为标记的。

标记除了在AI处理中的技术角色之外,还具有实际影响,特别是关于计费和模型能力:

计费:AI模型服务通常根据标记使用情况进行计费。输入(提示)和输出(响应)都贡献了总标记计数,使较短的提示更具成本效益。

模型限制:不同的AI模型有不同的标记限制,定义了它们的“上下文窗口”——它们一次能够处理的最大信息量。例如,GPT-3的限制是4K标记,而其他模型如Claude 2和Meta Llama 2的限制是100K标记,一些研究模型可以处理高达1百万标记。

上下文窗口:模型的标记限制决定了它的上下文窗口。超过此限制的输入不会被模型处理。重要的是只发送最小有效集的信息进行处理。例如,当询问“哈姆雷特”时,无需包括莎士比亚其他作品的所有标记。

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

  • 16
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明爷们儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值