Spring AI 中的提示詞工程技術

工程 | Christian Tzolov | 2025 年 4 月 14 日 | ...

這篇博文演示瞭如何使用 Spring AI 來實現提示詞工程技術的實際應用。

本文中的示例和模式基於全面的 提示詞工程指南,該指南涵蓋了有效提示詞工程的理論、原則和模式。

這篇博文展示瞭如何使用 Spring AI 流暢的 ChatClient API 將這些概念轉化為可執行的 Java 程式碼。

為方便起見,示例的結構遵循了原始指南中概述的相同模式和技術。

本文中使用的演示原始碼可從以下地址獲取: https://github.com/spring-projects/spring-ai-examples/tree/main/prompt-engineering/prompt-engineering-patterns

1. 配置

配置部分概述瞭如何使用 Spring AI 設定和調整您的大型語言模型 (LLM)。它涵蓋了為您的用例選擇合適的 LLM 提供商,以及配置控制模型輸出質量、風格和格式的重要生成引數。

LLM 提供商選擇

對於提示詞工程,您將首先選擇一個模型。Spring AI 支援 多個 LLM 提供商(例如 OpenAI、Anthropic、Google Vertex AI、AWS Bedrock、Ollama 等),這允許您無需更改應用程式程式碼即可切換提供商——只需更新您的配置即可。只需新增選定的啟動器依賴項 spring-ai-starter-model-<MODEL-PROVIDER-NAME>。例如,以下是如何啟用 Anthropic Claude API

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-anthropic</artifactId>
</dependency>

以及一些連線屬性: spring.ai.anthropic.api-key=${ANTHROPIC_API_KEY}

您可以像這樣指定特定的 LLM 模型名稱

.options(ChatOptions.builder()
        .model("claude-3-7-sonnet-latest")  // Use Anthropic's Claude model
        .build())

有關啟用和配置首選 AI 模型的詳細資訊,請參閱 參考文件

LLM 輸出配置

在我們深入探討提示詞工程技術之前,瞭解如何配置 LLM 的輸出行為至關重要。Spring AI 提供了幾個配置選項,允許您透過 ChatOptions 構建器控制生成的各個方面。

所有配置都可以按以下示例所示透過程式設計方式應用,或者在啟動時透過 Spring 應用程式屬性應用。

Temperature(溫度)

Temperature 引數控制模型響應的隨機性或“創造力”。

  • 較低的值 (0.0-0.3):更具確定性、更集中的響應。適用於事實類問題、分類或對一致性要求嚴格的任務。
  • 中等值 (0.4-0.7):在確定性和創造力之間取得平衡。適用於一般用例。
  • 較高值 (0.8-1.0):更具創造力、多樣化且可能帶來驚喜的響應。適用於創意寫作、頭腦風暴或生成多樣化選項。
.options(ChatOptions.builder()
        .temperature(0.1)  // Very deterministic output
        .build())

理解 Temperature 引數對於提示詞工程至關重要,因為不同的技術會受益於不同的 Temperature 設定。

輸出長度 (MaxTokens)

maxTokens 引數限制了模型在其響應中可以生成的 token(詞片段)數量。

  • 較低值 (5-25):適用於單個詞、短語或分類標籤。
  • 中等值 (50-500):適用於段落或簡短解釋。
  • 較高值 (1000+):適用於長篇內容、故事或複雜解釋。
.options(ChatOptions.builder()
        .maxTokens(250)  // Medium-length response
        .build())

設定適當的輸出長度很重要,以確保您獲得完整的響應而不會出現不必要的冗餘。

取樣控制 (Top-K 和 Top-P)

這些引數允許您對生成過程中的 token 選擇進行細粒度控制。

  • Top-K:將 token 選擇限制在 K 個最有可能的下一個 token 中。較高的值(例如 40-50)會引入更多多樣性。
  • Top-P (核取樣):從累積機率超過 P 的最小 token 集合中動態選擇。常見的值如 0.8-0.95。
.options(ChatOptions.builder()
        .topK(40)      // Consider only the top 40 tokens
        .topP(0.8)     // Sample from tokens that cover 80% of probability mass
        .build())

這些取樣控制與 Temperature 協同工作,以塑造響應特徵。

結構化響應格式

除了純文字響應(使用 .content())外,Spring AI 還支援使用 .entity() 方法將 LLM 響應直接對映到 Java 物件。

enum Sentiment {
    POSITIVE, NEUTRAL, NEGATIVE
}

Sentiment result = chatClient.prompt("...")
        .call()
        .entity(Sentiment.class);

當與指示模型返回結構化資料的系統提示詞結合使用時,此功能尤其強大。

模型特定選項

雖然可移植的 ChatOptions 為不同的 LLM 提供商提供了一致的介面,但 Spring AI 也提供了模型特定選項類,這些類暴露了提供商特定的功能和配置。這些模型特定選項允許您利用每個 LLM 提供商的獨特能力。

// Using OpenAI-specific options
OpenAiChatOptions openAiOptions = OpenAiChatOptions.builder()
        .model("gpt-4o")
        .temperature(0.2)
        .frequencyPenalty(0.5)      // OpenAI-specific parameter
        .presencePenalty(0.3)       // OpenAI-specific parameter
        .responseFormat(new ResponseFormat("json_object"))  // OpenAI-specific JSON mode
        .seed(42)                   // OpenAI-specific deterministic generation
        .build();

String result = chatClient.prompt("...")
        .options(openAiOptions)
        .call()
        .content();

// Using Anthropic-specific options
AnthropicChatOptions anthropicOptions = AnthropicChatOptions.builder()
        .model("claude-3-7-sonnet-latest")
        .temperature(0.2)
        .topK(40)                   // Anthropic-specific parameter
        .thinking(AnthropicApi.ThinkingType.ENABLED, 1000)  // Anthropic-specific thinking configuration
        .build();

String result = chatClient.prompt("...")
        .options(anthropicOptions)
        .call()
        .content();

每個模型提供商都有其自己的聊天選項實現(例如, OpenAiChatOptionsAnthropicChatOptions,和 MistralAiChatOptions),它們暴露了提供商特定的引數,同時仍然實現了通用介面。這種方法讓您可以靈活地使用可移植選項來實現跨提供商相容性,或者在需要訪問特定提供商的獨特功能時使用模型特定選項。

請注意,當使用模型特定選項時,您的程式碼將繫結到特定的提供商,從而降低了可移植性。這是在訪問提供商高階功能與在應用程式中保持提供商獨立性之間的權衡。

2. 提示詞工程技術

以下各節實現了指南中的特定提示詞工程技術。透過結合遵循《提示詞工程》指南和這些實現,您將對可用的提示詞工程技術有透徹的理解,並瞭解如何在生產 Java 應用程式中有效地實現它們。

2.1 Zero-Shot Prompting(零樣本提示)

零樣本提示(Zero-shot prompting)是指在不提供任何示例的情況下要求 AI 執行任務。這種方法測試了模型從零開始理解和執行指令的能力。大型語言模型經過大量文字語料庫的訓練,這使得它們無需明確演示即可理解諸如“翻譯”、“摘要”或“分類”等任務的含義。

零樣本非常適合模型在訓練期間可能已經見過類似示例的直接任務,以及當您希望最小化提示詞長度時。然而,效能可能會因任務複雜性和指令的制定方式而異。

// Implementation of Section 2.1: General prompting / zero shot (page 15)
public void pt_zero_shot(ChatClient chatClient) {
    enum Sentiment {
        POSITIVE, NEUTRAL, NEGATIVE
    }

    Sentiment reviewSentiment = chatClient.prompt("""
            Classify movie reviews as POSITIVE, NEUTRAL or NEGATIVE.
            Review: "Her" is a disturbing study revealing the direction
            humanity is headed if AI is allowed to keep evolving,
            unchecked. I wish there were more movies like this masterpiece.
            Sentiment:
            """)
            .options(ChatOptions.builder()
                    .model("claude-3-7-sonnet-latest")
                    .temperature(0.1)
                    .maxTokens(5)
                    .build())
            .call()
            .entity(Sentiment.class);

    System.out.println("Output: " + reviewSentiment);
}

此示例展示瞭如何在不提供示例的情況下對電影評論的情感進行分類。請注意,為了獲得更具確定性的結果,使用了較低的 temperature (0.1),並且透過直接的 .entity(Sentiment.class) 對映到 Java 列舉型別。

參考文獻:Brown, T. B., 等。(2020)。《Language Models are Few-Shot Learners》。arXiv:2005.14165。 https://arxiv.org/abs/2005.14165

2.2 One-Shot & Few-Shot Prompting(單樣本與少樣本提示)

少樣本提示(Few-shot prompting)為模型提供一個或多個示例,以幫助指導其響應,這對於需要特定輸出格式的任務特別有用。透過向模型展示期望的輸入-輸出對示例,它可以學習模式並將其應用於新的輸入,而無需顯式引數更新。

單樣本(One-shot)提供單個示例,這在示例成本較高或模式相對簡單時很有用。少樣本(Few-shot)使用多個示例(通常 3-5 個)來幫助模型更好地理解更復雜任務中的模式或展示正確輸出的不同變體。

// Implementation of Section 2.2: One-shot & few-shot (page 16)
public void pt_ones_shot_few_shots(ChatClient chatClient) {
    String pizzaOrder = chatClient.prompt("""
            Parse a customer's pizza order into valid JSON

            EXAMPLE 1:
            I want a small pizza with cheese, tomato sauce, and pepperoni.
            JSON Response:
            ```
            {
                "size": "small",
                "type": "normal",
                "ingredients": ["cheese", "tomato sauce", "pepperoni"]
            }
            ```

            EXAMPLE 2:
            Can I get a large pizza with tomato sauce, basil and mozzarella.
            JSON Response:
            ```
            {
                "size": "large",
                "type": "normal",
                "ingredients": ["tomato sauce", "basil", "mozzarella"]
            }
            ```

            Now, I would like a large pizza, with the first half cheese and mozzarella.
            And the other tomato sauce, ham and pineapple.
            """)
            .options(ChatOptions.builder()
                    .model("claude-3-7-sonnet-latest")
                    .temperature(0.1)
                    .maxTokens(250)
                    .build())
            .call()
            .content();
}

少樣本提示對於需要特定格式、處理邊緣情況或在沒有示例的情況下任務定義可能模糊的任務特別有效。示例的質量和多樣性顯著影響效能。

參考文獻:Brown, T. B., 等。(2020)。《Language Models are Few-Shot Learners》。arXiv:2005.14165。 https://arxiv.org/abs/2005.14165

2.3 System、Contextual 和 Role Prompting(系統、上下文和角色提示)

System Prompting(系統提示)

系統提示(System prompting)為語言模型設定整體上下文和目的,定義了模型應該做什麼的“大局”。它為模型的響應建立了行為框架、約束和高層次目標,與具體使用者查詢分開。

系統提示在整個對話過程中充當持久的“任務說明”,允許您設定全域性引數,如輸出格式、語氣、道德界限或角色定義。與側重於特定任務的使用者提示不同,系統提示框定了如何解釋所有使用者提示。

// Implementation of Section 2.3.1: System prompting
public void pt_system_prompting_1(ChatClient chatClient) {
    String movieReview = chatClient
            .prompt()
            .system("Classify movie reviews as positive, neutral or negative. Only return the label in uppercase.")
            .user("""
                    Review: "Her" is a disturbing study revealing the direction
                    humanity is headed if AI is allowed to keep evolving,
                    unchecked. It's so disturbing I couldn't watch it.

                    Sentiment:
                    """)
            .options(ChatOptions.builder()
                    .model("claude-3-7-sonnet-latest")
                    .temperature(1.0)
                    .topK(40)
                    .topP(0.8)
                    .maxTokens(5)
                    .build())
            .call()
            .content();
}

當與 Spring AI 的實體對映功能結合使用時,系統提示尤其強大

// Implementation of Section 2.3.1: System prompting with JSON output
record MovieReviews(Movie[] movie_reviews) {
    enum Sentiment {
        POSITIVE, NEUTRAL, NEGATIVE
    }

    record Movie(Sentiment sentiment, String name) {
    }
}

MovieReviews movieReviews = chatClient
        .prompt()
        .system("""
                Classify movie reviews as positive, neutral or negative. Return
                valid JSON.
                """)
        .user("""
                Review: "Her" is a disturbing study revealing the direction
                humanity is headed if AI is allowed to keep evolving,
                unchecked. It's so disturbing I couldn't watch it.

                JSON Response:
                """)
        .call()
        .entity(MovieReviews.class);

系統提示對於多輪對話特別有價值,可以確保在多個查詢中行為一致,並且可以建立格式約束,例如 JSON 輸出格式,該格式應適用於所有響應。

參考文獻:OpenAI。(2022)。《System Message》。 https://platform.openai.com/docs/guides/chat/introduction

Role Prompting(角色提示)

角色提示(Role prompting)指示模型扮演特定的角色或人格,這會影響其生成內容的方式。透過為模型分配特定的身份、專業知識或視角,您可以影響其響應的風格、語氣、深度和框架。

角色提示利用了模型模擬不同專業領域和溝通風格的能力。常見的角色包括專家(例如,“你是一位經驗豐富的資料科學家”)、專業人士(例如,“扮演旅行導遊”)或風格化人物(例如,“像莎士比亞一樣解釋”)。

// Implementation of Section 2.3.2: Role prompting
public void pt_role_prompting_1(ChatClient chatClient) {
    String travelSuggestions = chatClient
            .prompt()
            .system("""
                    I want you to act as a travel guide. I will write to you
                    about my location and you will suggest 3 places to visit near
                    me. In some cases, I will also give you the type of places I
                    will visit.
                    """)
            .user("""
                    My suggestion: "I am in Amsterdam and I want to visit only museums."
                    Travel Suggestions:
                    """)
            .call()
            .content();
}

可以使用風格指令來增強角色提示

// Implementation of Section 2.3.2: Role prompting with style instructions
public void pt_role_prompting_2(ChatClient chatClient) {
    String humorousTravelSuggestions = chatClient
            .prompt()
            .system("""
                    I want you to act as a travel guide. I will write to you about
                    my location and you will suggest 3 places to visit near me in
                    a humorous style.
                    """)
            .user("""
                    My suggestion: "I am in Amsterdam and I want to visit only museums."
                    Travel Suggestions:
                    """)
            .call()
            .content();
}

這項技術對於專業領域知識特別有效,有助於在響應中保持一致的語氣,並建立更具吸引力、個性化的使用者互動。

參考文獻:Shanahan, M., 等。(2023)。《Role-Play with Large Language Models》。arXiv:2305.16367。 https://arxiv.org/abs/2305.16367

Contextual Prompting(上下文提示)

上下文提示(Contextual prompting)透過傳遞上下文引數,為模型提供額外的背景資訊。這項技術豐富了模型對特定情況的理解,從而實現更相關、更定製化的響應,而不會使主要指令變得混亂。

透過提供上下文資訊,您可以幫助模型理解與當前查詢相關的特定領域、受眾、約束或背景事實。這會產生更準確、更相關且框架恰當的響應。

// Implementation of Section 2.3.3: Contextual prompting
public void pt_contextual_prompting(ChatClient chatClient) {
    String articleSuggestions = chatClient
            .prompt()
            .user(u -> u.text("""
                    Suggest 3 topics to write an article about with a few lines of
                    description of what this article should contain.

                    Context: {context}
                    """)
                    .param("context", "You are writing for a blog about retro 80's arcade video games."))
            .call()
            .content();
}

Spring AI 使用 param() 方法注入上下文變數,使上下文提示變得簡潔。這項技術在模型需要特定領域知識、根據特定受眾或場景調整響應以及確保響應符合特定約束或要求時特別有價值。

參考文獻:Liu, P., 等。(2021)。《What Makes Good In-Context Examples for GPT-3?》。arXiv:2101.06804。 https://arxiv.org/abs/2101.06804

2.4 Step-Back Prompting(退一步提示)

退一步提示(Step-back prompting)透過首先獲取背景知識,將複雜的請求分解為更簡單的步驟。這項技術鼓勵模型先“退一步”,考慮與問題相關的更廣泛的上下文、基本原理或通用知識,然後再處理具體的查詢。

透過將複雜問題分解為更易於管理的組成部分,並首先建立基礎知識,模型可以對難題提供更準確的響應。

// Implementation of Section 2.4: Step-back prompting
public void pt_step_back_prompting(ChatClient.Builder chatClientBuilder) {
    // Set common options for the chat client
    var chatClient = chatClientBuilder
            .defaultOptions(ChatOptions.builder()
                    .model("claude-3-7-sonnet-latest")
                    .temperature(1.0)
                    .topK(40)
                    .topP(0.8)
                    .maxTokens(1024)
                    .build())
            .build();

    // First get high-level concepts
    String stepBack = chatClient
            .prompt("""
                    Based on popular first-person shooter action games, what are
                    5 fictional key settings that contribute to a challenging and
                    engaging level storyline in a first-person shooter video game?
                    """)
            .call()
            .content();

    // Then use those concepts in the main task
    String story = chatClient
            .prompt()
            .user(u -> u.text("""
                    Write a one paragraph storyline for a new level of a first-
                    person shooter video game that is challenging and engaging.

                    Context: {step-back}
                    """)
                    .param("step-back", stepBack))
            .call()
            .content();
}

退一步提示對於複雜的推理任務、需要專業領域知識的問題以及當您希望獲得更全面和周到的響應而不是立即答案時特別有效。

參考文獻:Zheng, Z., 等。(2023)。《Take a Step Back: Evoking Reasoning via Abstraction in Large Language Models》。arXiv:2310.06117。 https://arxiv.org/abs/2310.06117

2.5 Chain of Thought (CoT)(思維鏈)

思維鏈提示(Chain of Thought prompting)鼓勵模型逐步推理問題,這提高了複雜推理任務的準確性。透過明確要求模型展示其工作或按邏輯步驟思考問題,您可以顯著提高需要多步驟推理的任務的效能。

思維鏈的工作原理是鼓勵模型在生成最終答案之前生成中間推理步驟,類似於人類解決複雜問題的方式。這使得模型的思維過程顯式化,並幫助它得出更準確的結論。

// Implementation of Section 2.5: Chain of Thought (CoT) - Zero-shot approach
public void pt_chain_of_thought_zero_shot(ChatClient chatClient) {
    String output = chatClient
            .prompt("""
                    When I was 3 years old, my partner was 3 times my age. Now,
                    I am 20 years old. How old is my partner?

                    Let's think step by step.
                    """)
            .call()
            .content();
}

// Implementation of Section 2.5: Chain of Thought (CoT) - Few-shot approach
public void pt_chain_of_thought_singleshot_fewshots(ChatClient chatClient) {
    String output = chatClient
            .prompt("""
                    Q: When my brother was 2 years old, I was double his age. Now
                    I am 40 years old. How old is my brother? Let's think step
                    by step.
                    A: When my brother was 2 years, I was 2 * 2 = 4 years old.
                    That's an age difference of 2 years and I am older. Now I am 40
                    years old, so my brother is 40 - 2 = 38 years old. The answer
                    is 38.
                    Q: When I was 3 years old, my partner was 3 times my age. Now,
                    I am 20 years old. How old is my partner? Let's think step
                    by step.
                    A:
                    """)
            .call()
            .content();
}

關鍵短語“讓我們一步一步思考”會觸發模型展示其推理過程。思維鏈對於數學問題、邏輯推理任務以及任何需要多步驟推理的問題特別有價值。透過使中間推理明確化,它有助於減少錯誤。

參考文獻:Wei, J., 等。(2022)。《Chain-of-Thought Prompting Elicits Reasoning in Large Language Models》。arXiv:2201.11903。 https://arxiv.org/abs/2201.11903

2.6 Self-Consistency(自我一致性)

自我一致性(Self-consistency)涉及多次執行模型並聚合結果以獲得更可靠的答案。這項技術透過對同一問題取樣不同的推理路徑,並透過多數投票選擇最一致的答案來解決 LLM 輸出的變異性。

透過使用不同的 temperature 或採樣設定生成多個推理路徑,然後聚合最終答案,自我一致性提高了複雜推理任務的準確性。它本質上是一種用於 LLM 輸出的整合方法。

// Implementation of Section 2.6: Self-consistency
public void pt_self_consistency(ChatClient chatClient) {
    String email = """
            Hi,
            I have seen you use Wordpress for your website. A great open
            source content management system. I have used it in the past
            too. It comes with lots of great user plugins. And it's pretty
            easy to set up.
            I did notice a bug in the contact form, which happens when
            you select the name field. See the attached screenshot of me
            entering text in the name field. Notice the JavaScript alert
            box that I inv0k3d.
            But for the rest it's a great website. I enjoy reading it. Feel
            free to leave the bug in the website, because it gives me more
            interesting things to read.
            Cheers,
            Harry the Hacker.
            """;

    record EmailClassification(Classification classification, String reasoning) {
        enum Classification {
            IMPORTANT, NOT_IMPORTANT
        }
    }

    int importantCount = 0;
    int notImportantCount = 0;

    // Run the model 5 times with the same input
    for (int i = 0; i < 5; i++) {
        EmailClassification output = chatClient
                .prompt()
                .user(u -> u.text("""
                        Email: {email}
                        Classify the above email as IMPORTANT or NOT IMPORTANT. Let's
                        think step by step and explain why.
                        """)
                        .param("email", email))
                .options(ChatOptions.builder()
                        .temperature(1.0)  // Higher temperature for more variation
                        .build())
                .call()
                .entity(EmailClassification.class);

        // Count results
        if (output.classification() == EmailClassification.Classification.IMPORTANT) {
            importantCount++;
        } else {
            notImportantCount++;
        }
    }

    // Determine the final classification by majority vote
    String finalClassification = importantCount > notImportantCount ? 
            "IMPORTANT" : "NOT IMPORTANT";
}

自我一致性對於高風險決策、複雜推理任務以及當您需要比單個響應更能確信的答案時特別有價值。其權衡是由於多次 API 呼叫而增加的計算成本和延遲。

參考文獻:Wang, X., 等。(2022)。《Self-Consistency Improves Chain of Thought Reasoning in Language Models》。arXiv:2203.11171。 https://arxiv.org/abs/2203.11171

2.7 Tree of Thoughts (ToT)(思之樹)

思之樹(Tree of Thoughts, ToT)是一種高階推理框架,它透過同時探索多個推理路徑來擴充套件思維鏈。它將問題解決視為一個搜尋過程,模型生成不同的中間步驟,評估它們的前景,並探索最有希望的路徑。

這項技術對於具有多種可能方法或解決方案需要在找到最優路徑之前探索各種替代方案的複雜問題尤其強大。

注意:原始的《提示詞工程》指南沒有提供思之樹(ToT)的實現示例,這可能是由於其複雜性所致。下面是一個簡化示例,演示了核心概念。

遊戲求解思之樹示例

// Implementation of Section 2.7: Tree of Thoughts (ToT) - Game solving example
public void pt_tree_of_thoughts_game(ChatClient chatClient) {
    // Step 1: Generate multiple initial moves
    String initialMoves = chatClient
            .prompt("""
                    You are playing a game of chess. The board is in the starting position.
                    Generate 3 different possible opening moves. For each move:
                    1. Describe the move in algebraic notation
                    2. Explain the strategic thinking behind this move
                    3. Rate the move's strength from 1-10
                    """)
            .options(ChatOptions.builder()
                    .temperature(0.7)
                    .build())
            .call()
            .content();
    
    // Step 2: Evaluate and select the most promising move
    String bestMove = chatClient
            .prompt()
            .user(u -> u.text("""
                    Analyze these opening moves and select the strongest one:
                    {moves}
                    
                    Explain your reasoning step by step, considering:
                    1. Position control
                    2. Development potential
                    3. Long-term strategic advantage
                    
                    Then select the single best move.
                    """).param("moves", initialMoves))
            .call()
            .content();
    
    // Step 3: Explore future game states from the best move
    String gameProjection = chatClient
            .prompt()
            .user(u -> u.text("""
                    Based on this selected opening move:
                    {best_move}
                    
                    Project the next 3 moves for both players. For each potential branch:
                    1. Describe the move and counter-move
                    2. Evaluate the resulting position
                    3. Identify the most promising continuation
                    
                    Finally, determine the most advantageous sequence of moves.
                    """).param("best_move", bestMove))
            .call()
            .content();
}

參考文獻:Yao, S., 等。(2023)。《Tree of Thoughts: Deliberate Problem Solving with Large Language Models》。arXiv:2305.10601。 https://arxiv.org/abs/2305.10601

2.8 Automatic Prompt Engineering(自動提示詞工程)

自動提示詞工程(Automatic Prompt Engineering)利用 AI 生成和評估替代提示詞。這項元技術利用語言模型本身來建立、細化和基準測試不同的提示詞變體,以找到特定任務的最佳表述。

透過系統地生成和評估提示詞變體,自動提示詞工程(APE)可以找到比手動工程更有效的提示詞,尤其是對於複雜任務。這是一種利用 AI 提高其自身效能的方式。

// Implementation of Section 2.8: Automatic Prompt Engineering
public void pt_automatic_prompt_engineering(ChatClient chatClient) {
    // Generate variants of the same request
    String orderVariants = chatClient
            .prompt("""
                    We have a band merchandise t-shirt webshop, and to train a
                    chatbot we need various ways to order: "One Metallica t-shirt
                    size S". Generate 10 variants, with the same semantics but keep
                    the same meaning.
                    """)
            .options(ChatOptions.builder()
                    .temperature(1.0)  // High temperature for creativity
                    .build())
            .call()
            .content();

    // Evaluate and select the best variant
    String output = chatClient
            .prompt()
            .user(u -> u.text("""
                    Please perform BLEU (Bilingual Evaluation Understudy) evaluation on the following variants:
                    ----
                    {variants}
                    ----

                    Select the instruction candidate with the highest evaluation score.
                    """).param("variants", orderVariants))
            .call()
            .content();
}

自動提示詞工程(APE)對於最佳化生產系統的提示詞、解決手動提示詞工程已達到極限的挑戰性任務以及系統地大規模提高提示詞質量尤其有價值。

參考文獻:Zhou, Y., 等。(2022)。《Large Language Models Are Human-Level Prompt Engineers》。arXiv:2211.01910。 https://arxiv.org/abs/2211.01910

2.9 Code Prompting(程式碼提示)

程式碼提示(Code prompting)是指用於程式碼相關任務的專門技術。這些技術利用 LLM 理解和生成程式語言的能力,使其能夠編寫新程式碼、解釋現有程式碼、除錯問題以及在不同語言之間進行翻譯。

有效的程式碼提示通常涉及清晰的規範、適當的上下文(庫、框架、程式碼風格指南)以及有時提供類似程式碼的示例。為了獲得更具確定性的輸出,Temperature 設定通常較低(0.1-0.3)。

// Implementation of Section 2.9.1: Prompts for writing code
public void pt_code_prompting_writing_code(ChatClient chatClient) {
    String bashScript = chatClient
            .prompt("""
                    Write a code snippet in Bash, which asks for a folder name.
                    Then it takes the contents of the folder and renames all the
                    files inside by prepending the name draft to the file name.
                    """)
            .options(ChatOptions.builder()
                    .temperature(0.1)  // Low temperature for deterministic code
                    .build())
            .call()
            .content();
}

// Implementation of Section 2.9.2: Prompts for explaining code
public void pt_code_prompting_explaining_code(ChatClient chatClient) {
    String code = """
            #!/bin/bash
            echo "Enter the folder name: "
            read folder_name
            if [ ! -d "$folder_name" ]; then
            echo "Folder does not exist."
            exit 1
            fi
            files=( "$folder_name"/* )
            for file in "${files[@]}"; do
            new_file_name="draft_$(basename "$file")"
            mv "$file" "$new_file_name"
            done
            echo "Files renamed successfully."
            """;

    String explanation = chatClient
            .prompt()
            .user(u -> u.text("""
                    Explain to me the below Bash code:
                    ```
                    {code}
                    ```
                    """).param("code", code))
            .call()
            .content();
}

// Implementation of Section 2.9.3: Prompts for translating code
public void pt_code_prompting_translating_code(ChatClient chatClient) {
    String bashCode = """
            #!/bin/bash
            echo "Enter the folder name: "
            read folder_name
            if [ ! -d "$folder_name" ]; then
            echo "Folder does not exist."
            exit 1
            fi
            files=( "$folder_name"/* )
            for file in "${files[@]}"; do
            new_file_name="draft_$(basename "$file")"
            mv "$file" "$new_file_name"
            done
            echo "Files renamed successfully."
            """;

    String pythonCode = chatClient
            .prompt()
            .user(u -> u.text("""
                    Translate the below Bash code to a Python snippet:                        
                    {code}                        
                    """).param("code", bashCode))
            .call()
            .content();
}

程式碼提示對於自動化程式碼文件、原型設計、學習程式設計概念以及在程式語言之間進行翻譯特別有價值。透過將其與少樣本提示或思維鏈等技術結合使用,可以進一步增強其有效性。

參考文獻:Chen, M., 等。(2021)。《Evaluating Large Language Models Trained on Code》。arXiv:2107.03374。 https://arxiv.org/abs/2107.03374

結論

Spring AI 提供了一個優雅的 Java API,用於實現所有主要的提示詞工程技術。透過將這些技術與 Spring 強大的實體對映和流暢的 API 相結合,開發者可以構建具有簡潔、可維護程式碼的複雜 AI 驅動應用程式。

最有效的方法通常涉及結合多種技術——例如,將系統提示與少樣本示例結合使用,或將思維鏈與角色提示結合使用。Spring AI 靈活的 API 使這些組合易於實現。

對於生產應用程式,請記住:

  1. 測試不同引數(temperature, top-k, top-p)下的提示詞
  2. 考慮在關鍵決策中使用自我一致性
  3. 利用 Spring AI 的實體對映實現型別安全的響應
  4. 使用上下文提示提供應用程式特定知識

透過這些技術和 Spring AI 強大的抽象能力,您可以建立提供一致、高質量結果的強大 AI 驅動應用程式。

參考文獻

  1. Brown, T. B., 等。(2020)。《Language Models are Few-Shot Learners》。arXiv:2005.14165。
  2. Wei, J., 等。(2022)。《Chain-of-Thought Prompting Elicits Reasoning in Large Language Models》。arXiv:2201.11903。
  3. Wang, X., 等。(2022)。《Self-Consistency Improves Chain of Thought Reasoning in Language Models》。arXiv:2203.11171。
  4. Yao, S., 等。(2023)。《Tree of Thoughts: Deliberate Problem Solving with Large Language Models》。arXiv:2305.10601。
  5. Zhou, Y., 等。(2022)。《Large Language Models Are Human-Level Prompt Engineers》。arXiv:2211.01910。
  6. Zheng, Z., 等。(2023)。《Take a Step Back: Evoking Reasoning via Abstraction in Large Language Models》。arXiv:2310.06117。
  7. Liu, P., 等。(2021)。《What Makes Good In-Context Examples for GPT-3?》。arXiv:2101.06804。
  8. Shanahan, M., et al. (2023). "與大型語言模型的角色扮演." arXiv:2305.16367.
  9. Chen, M., et al. (2021). "評估基於程式碼訓練的大型語言模型." arXiv:2107.03374.
  10. Spring AI 文件
  11. ChatClient API 參考
  12. Google 提示工程指南

獲取 Spring 新聞稿

透過 Spring 新聞稿保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,助您加速進步。

瞭解更多

獲取支援

Tanzu Spring 透過一個簡單的訂閱提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案。

瞭解更多

即將舉行的活動

檢視 Spring 社群所有即將舉行的活動。

檢視全部