提示
提示詞是引導 AI 模型生成特定輸出的輸入。這些提示詞的設計和措辭顯著影響模型的響應。
在 Spring AI 中與 AI 模型互動的最低層,處理提示詞有點類似於在 Spring MVC 中管理“檢視”。這涉及建立包含動態內容佔位符的擴充套件文字。然後根據使用者請求或應用程式中的其他程式碼替換這些佔位符。另一個類比是包含某些表示式佔位符的 SQL 語句。
隨著 Spring AI 的發展,它將引入與 AI 模型互動的更高級別的抽象。本節中描述的基礎類在角色和功能方面可以比作 JDBC。例如,ChatModel 類類似於 JDK 中的核心 JDBC 庫。ChatClient 類可以比作 JdbcClient,它建立在 ChatModel 之上,並透過 Advisor 提供更高階的構造,以考慮與模型的過去互動,用額外的上下文文件增強提示詞,並引入代理行為。
提示詞的結構在 AI 領域中隨時間演變。最初,提示詞是簡單的字串。隨著時間的推移,它們逐漸包含特定輸入的佔位符,例如“USER:”,AI 模型可以識別。OpenAI 甚至透過在 AI 模型處理之前將多個訊息字串分類為不同的角色,為提示詞引入了更多的結構。
API 概述
提示詞
通常使用 ChatModel 的 call() 方法,該方法接受 Prompt 例項並返回 ChatResponse。
Prompt 類充當有序的 Message 物件序列和請求 ChatOptions 的容器。每個 Message 在提示詞中都扮演獨特的角色,內容和意圖各不相同。這些角色可以涵蓋各種元素,從使用者查詢到 AI 生成的響應,再到相關的背景資訊。這種安排可以透過多個訊息構建提示詞,每個訊息在對話中扮演特定角色,從而實現與 AI 模型的複雜而詳細的互動。
以下是 Prompt 類的截斷版本,為簡潔起見省略了建構函式和實用方法
public class Prompt implements ModelRequest<List<Message>> {
private final List<Message> messages;
private ChatOptions chatOptions;
}
訊息
Message 介面封裝了 Prompt 文字內容、元資料屬性集合以及稱為 MessageType 的分類。
該介面定義如下
public interface Content {
String getContent();
Map<String, Object> getMetadata();
}
public interface Message extends Content {
MessageType getMessageType();
}
多模態訊息型別還實現了 MediaContent 介面,提供 Media 內容物件列表。
public interface MediaContent extends Content {
Collection<Media> getMedia();
}
Message 介面的各種實現對應於 AI 模型可以處理的不同類別的訊息。模型根據對話角色區分訊息類別。
這些角色由 MessageType 有效對映,如下所述。
角色
每條訊息都被分配了一個特定的角色。這些角色對訊息進行分類,為 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 中提示詞模板的關鍵元件是 PromptTemplate 類,旨在促進建立結構化提示詞,然後將其傳送到 AI 模型進行處理
public class PromptTemplate implements PromptTemplateActions, PromptTemplateMessageActions {
// Other methods to be discussed later
}
此類使用 TemplateRenderer 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);
}
Spring AI 使用 TemplateRenderer 介面處理變數到模板字串的實際替換。預設實現使用 [StringTemplate]。如果需要自定義邏輯,可以提供自己的 TemplateRenderer 實現。對於不需要模板渲染的場景(例如,模板字串已完成),可以使用提供的 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"));
此介面實現支援提示詞建立的不同方面
PromptTemplateStringActions 專注於建立和渲染提示詞字串,代表提示詞生成最基本的形式。
PromptTemplateMessageActions 專為透過生成和操作 Message 物件來建立提示詞而定製。
PromptTemplateActions 旨在返回 Prompt 物件,該物件可以傳遞給 ChatModel 以生成響應。
儘管這些介面可能在許多專案中不會被廣泛使用,但它們展示了提示詞建立的不同方法。
實現的介面是
public interface PromptTemplateStringActions {
String render();
String render(Map<String, Object> model);
}
方法 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);
}
方法 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);
}
方法 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();
下面顯示了另一個來自 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();
這展示瞭如何透過使用 SystemPromptTemplate 建立一個帶有系統角色並傳入佔位符值的 Message 來構建 Prompt 例項。然後將帶有 user 角色的訊息與帶有 system 角色的訊息組合形成提示詞。然後將該提示詞傳遞給 ChatModel 以獲取生成性響應。
使用自定義模板渲染器
您可以透過實現 TemplateRenderer 介面並將其傳遞給 PromptTemplate 建構函式來使用自定義模板渲染器。您也可以繼續使用預設的 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 抽象,因此您可以將提示詞資料放在可以直接在 PromptTemplate 中使用的檔案中。例如,您可以在 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 響應以建立連貫且上下文感知的對話。它有助於 AI 保持討論的線索,確保相關性和連續性。 -
ReAct(推理 + 行動):
在此方法中,AI 首先分析(推理)輸入,然後確定最合適的行動方案或響應。它結合了理解和決策。
Microsoft 指南
-
提示詞建立和最佳化框架:
Microsoft 提供了一種開發和最佳化提示詞的結構化方法。此框架指導使用者建立有效的提示詞,從 AI 模型中獲取所需的響應,從而最佳化互動的清晰度和效率。
Token
Token 在 AI 模型處理文字的方式中至關重要,它充當將單詞(我們理解的)轉換為 AI 模型可以處理的格式的橋樑。這種轉換分兩個階段進行:單詞在輸入時轉換為 token,然後這些 token 在輸出時轉換回單詞。
分詞是將文字分解為 token 的過程,是 AI 模型理解和處理語言的基礎。AI 模型使用這種分詞格式來理解和響應提示詞。
為了更好地理解 token,可以將其視為單詞的一部分。通常,一個 token 大約代表四分之三的單詞。例如,莎士比亞的全部作品,總計大約 900,000 個單詞,將轉換為大約 120 萬個 token。
使用 OpenAI 分詞器 UI 進行實驗,檢視單詞如何轉換為 token。
除了在 AI 處理中的技術作用之外,token 還具有實際意義,尤其是在計費和模型功能方面
-
計費:AI 模型服務通常根據 token 使用量計費。輸入(提示詞)和輸出(響應)都計入總 token 數,從而使較短的提示詞更具成本效益。
-
模型限制:不同的 AI 模型具有不同的 token 限制,定義了它們的“上下文視窗”——它們一次可以處理的最大資訊量。例如,GPT-3 的限制是 4K token,而 Claude 2 和 Meta Llama 2 等其他模型的限制是 100K token,一些研究模型可以處理多達 100 萬個 token。
-
上下文視窗:模型的 token 限制決定了其上下文視窗。超出此限制的輸入不會由模型處理。傳送最少有效的處理資訊集至關重要。例如,當查詢“哈姆雷特”時,無需包含莎士比亞所有其他作品中的 token。
-
響應元資料:AI 模型響應的元資料包括使用的 token 數量,這是管理使用情況和成本的重要資訊。