|
最新快照版本请使用Spring AI 1.1.0! |
提示
提示词是引导AI模型生成特定输出的输入。 这些提示的设计和措辞显著影响模型的回答。
在 Spring AI 与 AI 模型的最低级交互时,处理提示在某种程度上类似于 Spring MVC 中管理“视图”。 这包括创建带有动态内容占位符的大量文本。 这些占位符随后根据用户请求或应用程序中的其他代码被替换。 另一个类比是包含某些表达式占位符的SQL语句。
随着Spring AI的发展,它将引入更高层次的AI模型交互抽象。
本节描述的基础类在角色和功能上可与JDBC相提并论。
这聊天模型例如,类类似于JDK中的核心JDBC库。
这聊天客户端类可以比作Jdbc客户端,建在聊天模型并通过以下方式提供更高级的构造顾问回顾与模型的过往互动,补充提示词的上下文文档,并引入代理行为。
提示的结构在人工智能领域随着时间演变。 最初,提示词是简单的字符串。 随着时间推移,它们逐渐加入了特定输入的占位符,比如“USER:”,AI模型能识别。 OpenAI 通过将多个消息字符串分类为不同角色,为提示引入了更多结构,然后再由 AI 模型处理。
API 概述
提示
通常会使用call()方法聊天模型这需要一个提示实例并返回聊天回应.
这提示类作为有组织序列的容器消息对象和请求聊天选项.
每消息在提示中具有独特的角色,内容和意图各异。
这些角色涵盖多种环节,从用户提问到AI生成的相关背景信息回复。
这种安排使得与AI模型的复杂且细致的互动成为可能,提示由多条消息构成,每条信息在对话中被赋予特定角色。
以下是Prompt类的简短版本,为了简洁起见省略了构造函数和实用方法:
public class Prompt implements ModelRequest<List<Message>> {
private final List<Message> messages;
private ChatOptions chatOptions;
}
消息
这消息接口封装了提示文本内容、元数据属性集合,以及一种称为消息类型.
接口定义如下:
public interface Content {
String getContent();
Map<String, Object> getMetadata();
}
public interface Message extends Content {
MessageType getMessageType();
}
多模态消息类型还实现了媒体内容接口提供列表媒体内容对象。
public interface MediaContent extends Content {
Collection<Media> getMedia();
}
各种实现消息界面对应于AI模型能够处理的不同类别消息。
模型根据对话角色区分消息类别。
这些角色通过消息类型,如下文所述。
角色
每个消息都被分配了特定的角色。 这些角色负责对信息进行分类,明确提示中每个部分的上下文和目的,供AI模型使用。 这种结构化的方法增强了与AI沟通的细腻度和有效性,因为提示的每个部分在互动中都扮演着独特且明确的角色。
主要职责包括:
-
系统角色:指导AI的行为和响应风格,设定AI如何解释和响应输入的参数或规则。这就像在发起对话前先给AI提供指令。
-
用户角色:代表用户的输入——他们对AI的问题、命令或陈述。这一角色至关重要,因为它构成了人工智能应对的基础。
-
助理角色:AI对用户输入的回应。 这不仅仅是一个回答或反应,更对于保持对话的流畅性至关重要。 通过追踪AI之前的回复(其“助理角色”消息),系统确保互动连贯且符合上下文。 助手消息也可能包含功能工具调用请求信息。 它就像AI中的一个特殊功能,用于执行特定功能,比如计算、获取数据或其他不仅仅是说话的任务。
-
工具/功能角色:工具/功能角色专注于回复工具呼叫助手消息时返回更多信息。
Spring AI 中角色以枚举形式表示,如下所示
public enum MessageType {
USER("user"),
ASSISTANT("assistant"),
SYSTEM("system"),
TOOL("tool");
...
}
提示模板
Spring AI 中提示模板化的一个关键组件是提示模板类,旨在促进结构化提示的创建,然后发送给 AI 模型进行处理
public class PromptTemplate implements PromptTemplateActions, PromptTemplateMessageActions {
// Other methods to be discussed later
}
该类使用模板渲染器API来渲染模板。默认情况下,Spring AI 使用StTemplateRenderer该系统基于Terence Parr开发的开源StringTemplate引擎。模板变量通过语法标识,但你也可以配置分隔符使用其他语法。{}
public interface TemplateRenderer extends BiFunction<String, Map<String, Object>, String> {
@Override
String apply(String template, Map<String, Object> variables);
}
春季AI使用了模板渲染器接口处理变量实际替换到模板字符串中。
默认实现使用 [StringTemplate]。
你可以提供你自己的实现模板渲染器如果你需要自定义逻辑。
对于不需要模板渲染的场景(例如模板字符串已经完成),你可以使用提供的NoOpTemplateRenderer.
PromptTemplate promptTemplate = PromptTemplate.builder()
.renderer(StTemplateRenderer.builder().startDelimiterToken('<').endDelimiterToken('>').build())
.template("""
Tell me the names of 5 movies whose soundtrack was composed by <composer>.
""")
.build();
String prompt = promptTemplate.render(Map.of("composer", "John Williams"));
该类实现的接口支持提示创建的不同方面:
提示模板字符串动作专注于创建和渲染提示字符串,代表最基本的提示生成形式。
提示模板消息动作通过生成和作 来创建提示消息对象。
提示模板动作设计用来返回提示对象,可以传递给聊天模型以产生回应。
虽然这些界面在许多项目中可能不被广泛使用,但它们展示了不同的提示创建方法。
实现的接口包括
public interface PromptTemplateStringActions {
String render();
String render(Map<String, Object> model);
}
方法字符串渲染():将提示模板渲染成无外部输入的最终字符串格式,适用于无占位符或动态内容的模板。
方法String render(Map<String,Object> model):增强渲染功能,包含动态内容。它使用了一个Map<String,对象>其中地图键是提示模板中的占位名称,值是要插入的动态内容。
public interface PromptTemplateMessageActions {
Message createMessage();
Message createMessage(List<Media> mediaList);
Message createMessage(Map<String, Object> model);
}
方法Message createMessage():产生消息无额外数据的对象,用于静态或预定义的消息内容。
方法Message createMessage(List<Media> mediaList):产生消息具有静态文本和媒体内容的对象。
方法Message createMessage(Map<String, Object> model):扩展消息创建以整合动态内容,接受Map<String,对象>其中每个条目代表消息模板中的占位符及其对应的动态值。
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);
}
方法提示创建()生成提示无外部数据输入的对象,适合静态或预定义提示。
方法提示创建(ChatOptions modelOptions)生成提示没有外部数据输入,并且带有针对聊天请求的特定选项的对象。
方法提示创建(Map<String,对象>模型):扩展提示创建功能,涵盖动态内容,采用Map<String,对象>每个地图条目是提示模板中的占位符及其关联的动态值。
方法提示创建(Map<String,Object> model,ChatOptions modelOptions):扩展提示创建功能,涵盖动态内容,采用Map<String,对象>每个地图条目都是提示模板中的占位符及其对应的动态值,以及聊天请求的具体选项。
示例用法
下面展示了来自 AI 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();
下面展示了另一个来自角色AI研讨会的示例。
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();
这展示了如何逐步建立提示实例通过使用系统提示模板以创建消息系统角色传递占位符值。
角色传递的信息用户然后与角色的信息结合系统形成提示。
提示随后传递给ChatModel,以获得生成性回复。
使用自定义模板渲染器
你可以通过实现模板渲染器接口并将其传递给提示模板构造 函数。你也可以继续使用默认StTemplateRenderer但配置是自定义的。
默认情况下,模板变量通过语法标识。如果你打算在提示词中包含JSON,可能需要使用不同的语法以避免与JSON语法冲突。例如,你可以使用和分隔符。{}<>
PromptTemplate promptTemplate = PromptTemplate.builder()
.renderer(StTemplateRenderer.builder().startDelimiterToken('<').endDelimiterToken('>').build())
.template("""
Tell me the names of 5 movies whose soundtrack was composed by <composer>.
""")
.build();
String prompt = promptTemplate.render(Map.of("composer", "John Williams"));
使用资源代替原始字符串
Spring AI 支持org.springframework.core.io.Resource抽象,所以你可以把提示词数据放进一个可以直接用于提示模板.
例如,你可以在 Spring 管理组件中定义一个字段来检索资源.
@Value("classpath:/prompts/system-message.st")
private Resource systemResource;
然后将该资源传递给系统提示模板径直。
SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource);
提示工程
在生成式人工智能中,提示词的创建是开发者的重要任务。 这些提示的质量和结构显著影响AI输出的有效性。 投入时间和精力设计深思熟虑的提示词,可以极大提升AI的效果。
分享和讨论提示词是人工智能社区的常见做法。 这种协作方式不仅创造了共享学习环境,还促成了高效提示的识别和应用。
该领域的研究通常涉及分析和比较不同提示词,以评估其在不同情境下的有效性。 例如,一项重要研究表明,以“深呼吸,逐步解决此问题”开启题目显著提升了解决问题的效率。 这凸显了精心选择的语言对生成式人工智能系统性能的影响。
掌握提示的最有效运用,尤其是在人工智能技术快速发展的背景下,始终是一项持续的挑战。 你应认识到提示工程的重要性,并考虑利用社区和研究的见解来改进提示创作策略。
创建有效的提示
在设计提示时,整合几个关键要素以确保清晰和有效性非常重要:
-
指令:向AI提供清晰直接的指令,类似于与人交流的方式。这种清晰度对于帮助AI“理解”预期至关重要。
-
外部背景:在必要时,包含相关的背景信息或针对AI的具体响应指导。这种“外部语境”为提示构建框架,帮助AI理解整体情境。
-
用户输入:这是最直接的部分——用户的直接请求或问题构成提示的核心。
-
输出指示器:这方面可能比较棘手。它涉及指定 AI 响应所需的格式,如 JSON。不过要注意,AI并不总是严格遵守这种格式。例如,它可能会在实际的 JSON 数据前加上“这是你的 JSON”这样的短语,或者有时生成一个不准确的 JSON 结构。
在设计提示时,向AI提供预期问答格式的示例非常有益。 这种做法帮助AI“理解”你问题的结构和意图,从而给出更精准、更相关的回答。 虽然本文档未深入探讨这些技术,但它们为进一步探索AI提示工程提供了起点。
以下是进一步研究所需的资源列表。
高级技术
-
零样本、少数样本学习:
使模型能够在几乎没有特定问题类型的实例的情况下做出准确的预测或响应,利用学习到的泛化理解并执行新任务。 -
思维链:
连接多个AI反应,创建连贯且具上下文感知的对话。它帮助AI保持讨论的主线,确保相关性和连续性。 -
反应(理由+行动):
在这种方法中,人工智能首先分析(关于)输入的理由,然后确定最合适的行动方案或回应。它结合了理解与决策。
Microsoft Guidance
-
提示创建与优化框架:
Microsoft 提供结构化的提示开发和优化方法。该框架引导用户创建有效的提示,从AI模型中引出期望的响应,优化交互以实现清晰和高效。
Tokens
Tokens在AI模型处理文本时至关重要,它作为桥梁,将我们理解的单词转换为AI模型可处理的格式。 这种转换分为两个阶段:输入时词被转换为词,然后这些词在输出中再转换回词。
Tokens化,即将文本分解为Tokens的过程,是人工智能模型理解和处理语言的基础。 AI模型采用这种Tokens化格式来理解并响应提示。
为了更好地理解Tokens,可以把它们看作单词的各个部分。通常,一个Tokens代表大约三分之三的单词。例如,莎士比亚全集约90万字,约相当于120万个Tokens。
试试 OpenAI Tokenizer 界面,看看单词是如何转换成Tokens的。
Tokens在人工智能处理中的技术角色之外,还有实际意义,尤其是在计费和模型能力方面:
-
计费:AI模型服务通常根据Tokens使用量计费。输入(提示)和输出(响应)都对总Tokens数有贡献,使得更短的提示更具成本效益。
-
模型限制:不同的AI模型有不同的Tokens限制,定义了其“上下文窗口”——即它们一次能处理的信息量。例如,GPT-3的Tokens上限为4K,而Claude 2和Meta Llama 2等模型则限制为10万个Tokens,一些研究模型最多可处理100万Tokens。
-
上下文窗口:模型的Tokens限制决定其上下文窗口。超过该限制的输入不被模型处理。只发送最有效的信息进行处理至关重要。例如,询问《哈姆雷特》时,无需包含莎士比亚其他作品的所有标记。
-
响应元数据:AI模型响应的元数据包括使用的Tokens数量,这是管理使用和成本的重要信息。