此版本仍在开发中,尚未被视为稳定版。如需最新的快照版本,请使用 Spring AI 1.1.3spring-doc.cadn.net.cn

提示工程模式

基于全面的 提示工程指南 的提示工程技术的实际实现。 该指南涵盖了有效提示工程的理论、原则和模式,而在这里我们演示如何使用 Spring AI 的流畅 ChatClient API 将这些概念转化为可工作的 Java 代码。 本文中使用的演示源代码可在以下位置获取:提示工程模式示例spring-doc.cadn.net.cn

1. 配置

配置部分概述了如何使用 Spring AI 设置和调整您的大型语言模型(LLM)。 它包括为您的用例选择合适的 LLM 提供商,以及配置控制模型输出质量、风格和格式的重要生成参数。spring-doc.cadn.net.cn

LLM 提供商选择

对于提示工程,您将首先选择一个模型。 Spring AI 支持 多个 LLM 提供商(如 OpenAI、Anthropic、Google Vertex AI、AWS Bedrock、Ollama 等),让您无需更改应用程序代码即可切换提供商——只需更新您的配置。 只需添加所选的Starters依赖项 spring-ai-starter-model-<MODEL-PROVIDER-NAME>。 例如,以下是启用 Anthropic Claude API 的方法:spring-doc.cadn.net.cn

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

您可以像这样指定 LLM 模型名称:spring-doc.cadn.net.cn

.options(ChatOptions.builder()
        .model("claude-sonnet-4-6")  // Use Anthropic's Claude model
        .build())

参考文档 中查找启用每个模型的详细信息。spring-doc.cadn.net.cn

LLM 输出配置

chat options flow

在深入探讨提示工程技术之前,了解如何配置 LLM 的输出行为至关重要。Spring AI 提供了多种配置选项,让您可以通过 ChatOptions 构建器控制生成的各个方面。spring-doc.cadn.net.cn

所有配置都可以通过编程方式应用,如下面的示例所示,或者在启动时通过 Spring 应用程序属性进行配置。spring-doc.cadn.net.cn

温度

温度控制模型响应的随机性或“创造力”。spring-doc.cadn.net.cn

  • 较低的值(0.0-0.3):更具确定性、更专注的回答。更适合事实性问题、分类任务或对一致性要求较高的场景。spring-doc.cadn.net.cn

  • 中等数值 (0.4-0.7): 在确定性和创造性之间取得平衡。适用于一般用例。spring-doc.cadn.net.cn

  • 较高的值(0.8-1.0):更具创造性、多样性且可能令人惊讶的回答。更适合创意写作、头脑风暴或生成多样化的选项。spring-doc.cadn.net.cn

.options(ChatOptions.builder()
        .temperature(0.1)  // Very deterministic output
        .build())

理解温度对于提示工程至关重要,因为不同的技术可以从不同的温度设置中受益。spring-doc.cadn.net.cn

输出长度(最大Tokens数)

maxTokens 参数限制了模型在其响应中可以生成的 token(词片段)的数量。spring-doc.cadn.net.cn

.options(ChatOptions.builder()
        .maxTokens(250)  // Medium-length response
        .build())

设置适当的输出长度很重要,以确保您获得完整的响应,而不会出现不必要的冗长。spring-doc.cadn.net.cn

采样控制(Top-K 和 Top-P)

这些参数使您能够在生成过程中精细控制Tokens的选择过程。spring-doc.cadn.net.cn

  • Top-K: 限制Tokens选择为 K 个最可能的下一个Tokens。较高的值(例如 40-50)会引入更多多样性。spring-doc.cadn.net.cn

  • Top-P (nucleus sampling): 动态地从累积概率超过 P 的最小Tokens集合中选择。常见值为 0.8-0.95。spring-doc.cadn.net.cn

.options(ChatOptions.builder()
        .topK(40)      // Consider only the top 40 tokens
        .topP(0.8)     // Sample from tokens that cover 80% of probability mass
        .build())

这些采样控制与温度一起作用,以塑造响应特性。spring-doc.cadn.net.cn

结构化响应格式

除了纯文本响应(使用 .content()),Spring AI 还可以通过 .entity() 方法轻松地将 LLM 响应直接映射到 Java 对象。spring-doc.cadn.net.cn

enum Sentiment {
    POSITIVE, NEUTRAL, NEGATIVE
}

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

当与指示模型返回结构化数据的系统提示结合使用时,此功能特别强大。spring-doc.cadn.net.cn

特定模型选项

尽管可移植的 ChatOptions 为不同的 LLM 提供商提供了一致的接口,但 Spring AI 还提供了模型特定的选项类,这些类暴露了提供商特定的功能和配置。这些模型特定的选项允许您利用每个 LLM 提供商的独特能力。spring-doc.cadn.net.cn

// 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-sonnet-4-6")
        .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();

每个模型提供商都有自己的聊天选项实现(例如,OpenAiChatOptionsAnthropicChatOptionsMistralAiChatOptions),这些实现暴露了特定于提供商的参数,同时仍然实现了通用接口。这种方法为您提供了灵活性,可以使用可移植选项以实现跨提供商兼容性,或者在需要访问特定提供商的独特功能时使用模型特定选项。spring-doc.cadn.net.cn

请注意,当使用特定于模型的选项时,您的代码将依赖于该特定提供商,从而降低了可移植性。这是在访问高级提供商特定功能与在应用程序中保持提供商独立性之间的一种权衡。spring-doc.cadn.net.cn

2. 提示工程技术

下面的每个部分都实现了指南中的一种特定的提示工程技术。 通过遵循“提示工程”指南和这些实现,您将不仅全面了解有哪些提示工程技术可用,还将学会如何在生产级 Java 应用程序中有效地实现它们。spring-doc.cadn.net.cn

2.1 零样本提示

Zero-shot prompting 涉及要求 AI 在不提供任何示例的情况下执行任务。这种方法测试模型从零开始理解和执行指令的能力。大型语言模型在海量文本语料库上训练,使其能够理解诸如“翻译”、“摘要”或“分类”等任务的内容,而无需明确的演示。spring-doc.cadn.net.cn

Zero-shot 适用于简单任务,特别是在模型在训练期间可能见过类似示例的情况下,以及当你希望最小化提示长度时。然而,性能可能会因任务复杂性和指令制定的清晰度而有所不同。spring-doc.cadn.net.cn

// 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-sonnet-4-6")
                    .temperature(0.1)
                    .maxTokens(5)
                    .build())
            .call()
            .entity(Sentiment.class);

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

此示例展示了如何在未提供示例的情况下对电影评论情感进行分类。请注意低温度(0.1)以获得更确定性的结果,以及直接将 .entity(Sentiment.class) 映射到 Java 枚举。spring-doc.cadn.net.cn

参考: Brown, T. B., et al. (2020). "Language Models are Few-Shot Learners." arXiv:2005.14165. https://arxiv.org/abs/2005.14165spring-doc.cadn.net.cn

2.2 单次提示与少次提示

Few-shot 提示为模型提供一个或多个示例,以帮助引导其响应,对于需要特定输出格式的任务特别有用。通过向模型展示所需的输入-输出对示例,它可以学习模式并将其应用于新输入,而无需显式参数更新。spring-doc.cadn.net.cn

One-shot 提供单个示例,这在示例成本较高或模式相对简单时非常有用。Few-shot 使用多个示例(通常为 3-5 个)来帮助模型更好地理解复杂任务中的模式,或展示正确输出的不同变体。spring-doc.cadn.net.cn

// Implementation of Section 2.2: One-shot & few-shot (page 16)
public void pt_one_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-sonnet-4-6")
                    .temperature(0.1)
                    .maxTokens(250)
                    .build())
            .call()
            .content();
}

Few-shot 提示在需要特定格式、处理边缘情况,或者在没有示例的情况下任务定义可能不明确时特别有效。示例的质量和多样性会显著影响性能。spring-doc.cadn.net.cn

参考: Brown, T. B., et al. (2020). "Language Models are Few-Shot Learners." arXiv:2005.14165. https://arxiv.org/abs/2005.14165spring-doc.cadn.net.cn

2.3 系统、上下文和角色提示

系统提示

系统提示为语言模型设定了整体背景和目的,定义了模型应该执行的“大局”。它建立了模型回复的行为框架、约束和高层目标,与具体的用户查询分开。spring-doc.cadn.net.cn

系统提示词在对话过程中充当持久的“使命宣言”,允许您设置全局参数,如输出格式、语调、伦理边界或角色定义。与专注于特定任务的用户提示词不同,系统提示词定义了所有用户提示词应如何被解读。spring-doc.cadn.net.cn

// 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-sonnet-4-6")
                    .temperature(1.0)
                    .topK(40)
                    .topP(0.8)
                    .maxTokens(5)
                    .build())
            .call()
            .content();
}

当结合 Spring AI 的实体映射能力时,系统提示显得尤为强大:spring-doc.cadn.net.cn

// 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输出。spring-doc.cadn.net.cn

角色提示

角色提示指示模型采用特定的角色或人设,这会影响其生成内容的方式。通过为模型分配特定的身份、专业知识或视角,您可以影响其回复的风格、语气、深度和框架。spring-doc.cadn.net.cn

角色提示利用了模型模拟不同专业领域和沟通风格的能力。常见角色包括专家(例如,“你是一位经验丰富的数据科学家”)、专业人士(例如,“扮演一名导游”)或风格化角色(例如,“像莎士比亚一样解释”)。spring-doc.cadn.net.cn

// 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();
}

角色提示可以通过风格指令得到增强:spring-doc.cadn.net.cn

// 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();
}

这种技术在特定领域知识方面特别有效,能够在回复中保持一致的语调,并创造更具吸引力、个性化的用户互动体验。spring-doc.cadn.net.cn

参考: Shanahan, M., et al. (2023). "Role-Play with Large Language Models." arXiv:2305.16367. https://arxiv.org/abs/2305.16367spring-doc.cadn.net.cn

上下文提示

上下文提示通过传递上下文参数,为模型提供了额外的背景信息。这种技术丰富了模型对特定情况的理解,使其能够在不使主要指令变得杂乱的情况下,生成更相关和更具针对性的响应。spring-doc.cadn.net.cn

通过提供上下文信息,您可以帮助模型理解与当前查询相关的特定领域、受众、约束或背景事实。这将产生更准确、相关且恰当构建的响应。spring-doc.cadn.net.cn

// 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() 方法使上下文提示变得简洁,以注入上下文变量。当模型需要特定领域知识、将响应适配到特定受众或场景,以及确保响应符合特定约束或要求时,这种技术特别有价值。spring-doc.cadn.net.cn

参考: Liu, P., et al. (2021). “GPT-3 的良好上下文示例是什么?” arXiv:2101.06804. https://arxiv.org/abs/2101.06804spring-doc.cadn.net.cn

2.4 回退提示

Step-back prompting 通过首先获取背景知识,将复杂的请求分解为更简单的步骤。这种技术鼓励模型首先从当前问题中“退一步”,考虑更广泛的背景、基本原则或与问题相关的一般知识,然后再处理具体的查询。spring-doc.cadn.net.cn

通过将复杂问题分解为更易于管理的组件,并首先建立基础知识,模型可以更准确地回答困难问题。spring-doc.cadn.net.cn

// 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-sonnet-4-6")
                    .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();
}

回退提示(Step-back prompting)在复杂的推理任务、需要专业领域知识的问题以及当你希望获得更全面和深思熟虑的回答而非即时答案时,特别有效。spring-doc.cadn.net.cn

参考: Zheng, Z., et al. (2023). “退一步:通过抽象引发大型语言模型的推理。” arXiv:2310.06117. https://arxiv.org/abs/2310.06117spring-doc.cadn.net.cn

2.5 思维链 (CoT)

链式思维提示鼓励模型逐步推理问题,从而提高复杂推理任务的准确性。通过明确要求模型展示其工作过程或按逻辑步骤思考问题,您可以显著提升需要多步推理的任务的性能。spring-doc.cadn.net.cn

CoT 通过鼓励模型在生成最终答案之前生成中间推理步骤来工作,类似于人类解决复杂问题的方式。这使得模型的思维过程变得明确,并帮助它得出更准确的结论。spring-doc.cadn.net.cn

// 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();
}

关键短语“让我们一步步思考”触发模型展示其推理过程。CoT(思维链)对于数学问题、逻辑推理任务以及任何需要多步推理的问题尤其有价值。它通过明确中间推理步骤来帮助减少错误。spring-doc.cadn.net.cn

参考: Wei, J., et al. (2022). "Chain-of-Thought Prompting Elicits Reasoning in Large Language Models." arXiv:2201.11903. https://arxiv.org/abs/2201.11903spring-doc.cadn.net.cn

2.6 自我一致性

自洽性涉及多次运行模型并聚合结果以获得更可靠的答案。该技术通过针对同一问题采样多样化的推理路径,并通过多数投票选择最一致的答案,解决了大语言模型输出的变异性。spring-doc.cadn.net.cn

通过使用不同的温度或采样设置生成多个推理路径,然后汇总最终答案,自一致性提高了复杂推理任务的准确性。本质上,这是一种针对大型语言模型输出的集成方法。spring-doc.cadn.net.cn

// 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 调用而增加的计算成本和延迟。spring-doc.cadn.net.cn

参考: Wang, X., et al. (2022). "Self-Consistency Improves Chain of Thought Reasoning in Language Models." arXiv:2203.11171. https://arxiv.org/abs/2203.11171spring-doc.cadn.net.cn

2.7 思维树 (ToT)

Tree of Thoughts (ToT) 是一种先进的推理框架,它通过同时探索多条推理路径来扩展思维链。它将问题解决视为一个搜索过程,模型在其中生成不同的中间步骤,评估它们的潜力,并探索最有希望的路径。spring-doc.cadn.net.cn

这项技术对于具有多种可能方法的复杂问题特别强大,或者在找到最优路径之前需要探索各种替代方案时。spring-doc.cadn.net.cn

原始的“提示工程”指南没有提供 ToT 的实现示例,可能是由于其复杂性。下面是一个简化的示例,展示了核心概念。spring-doc.cadn.net.cn

游戏求解思维树示例:spring-doc.cadn.net.cn

// 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., et al. (2023). "Tree of Thoughts: Deliberate Problem Solving with Large Language Models." arXiv:2305.10601. https://arxiv.org/abs/2305.10601spring-doc.cadn.net.cn

2.8 自动提示工程

自动提示工程使用人工智能生成和评估替代提示。这种元技术利用语言模型本身来创建、细化和基准测试不同的提示变体,以找到针对特定任务的最佳表述。spring-doc.cadn.net.cn

通过系统地生成和评估提示词变体,APE 可以找到比手动工程更有效的提示词,尤其是在复杂任务中。这是一种利用 AI 提升自身性能的方法。spring-doc.cadn.net.cn

// 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 对于优化面向生产系统的提示词特别有价值,能够解决手动提示词工程已达到极限的具有挑战性的任务,并能够大规模地系统性地提升提示词质量。spring-doc.cadn.net.cn

参考: Zhou, Y., et al. (2022). "大型语言模型是人类水平的提示工程师。" arXiv:2211.01910. https://arxiv.org/abs/2211.01910spring-doc.cadn.net.cn

2.9 代码提示

代码提示是指针对代码相关任务的专业技术。这些技术利用大语言模型(LLM)理解和生成编程语言的能力,使它们能够编写新代码、解释现有代码、调试问题以及在不同语言之间进行翻译。spring-doc.cadn.net.cn

有效的代码提示通常包含明确的规范、适当的上下文(库、框架、风格指南),有时还包括类似代码的示例。温度设置通常较低(0.1-0.3),以获得更确定的输出。spring-doc.cadn.net.cn

// 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();
}

代码提示在自动化代码文档、原型设计、学习编程概念以及编程语言之间的转换方面特别有价值。通过结合少样本提示或思维链等技术,可以进一步提高其效果。spring-doc.cadn.net.cn

参考: Chen, M., et al. (2021). "Evaluating Large Language Models Trained on Code." arXiv:2107.03374. https://arxiv.org/abs/2107.03374spring-doc.cadn.net.cn

结论

Spring AI 提供了一个优雅的 Java API,用于实现所有主要的提示工程技巧。通过将这些技巧与 Spring 强大的实体映射和流畅 API 相结合,开发者可以使用简洁、可维护的代码构建复杂的 AI 驱动应用程序。spring-doc.cadn.net.cn

最有效的方法通常涉及结合多种技术——例如,使用系统提示结合少样本示例,或链式思维结合角色提示。Spring AI 的灵活 API 使这些组合的实现变得简单。spring-doc.cadn.net.cn

对于生产环境的应用程序,请记住:spring-doc.cadn.net.cn

  1. 使用不同参数(温度、top-k、top-p)测试提示词spring-doc.cadn.net.cn

  2. 考虑在关键决策中使用自一致性spring-doc.cadn.net.cn

  3. 利用 Spring AI 的实体映射实现类型安全的响应spring-doc.cadn.net.cn

  4. 使用上下文提示来提供特定于应用程序的知识spring-doc.cadn.net.cn

通过这些技术和 Spring AI 的强大抽象,您可以创建健壮的 AI 驱动应用程序,提供一致且高质量的结果。spring-doc.cadn.net.cn

<p>参考文献</p>

  1. Brown, T. B., 等人 (2020). "语言模型是少样本学习者." arXiv:2005.14165.spring-doc.cadn.net.cn

  2. Wei, J., et al. (2022). "思维链提示引发大型语言模型的推理能力." arXiv:2201.11903.spring-doc.cadn.net.cn

  3. Wang, X., 等人 (2022). "自洽性改进语言模型中的思维链推理." arXiv:2203.11171.spring-doc.cadn.net.cn

  4. Yao, S., 等人 (2023). “思维树:利用大型语言模型进行深思熟虑的问题解决。” arXiv:2305.10601.spring-doc.cadn.net.cn

  5. 周, Y., 等 (2022). "大型语言模型是人类水平的提示工程师." arXiv:2211.01910.spring-doc.cadn.net.cn

  6. Zheng, Z., et al. (2023). "退一步:通过抽象引发大型语言模型的推理。" arXiv:2310.06117.spring-doc.cadn.net.cn

  7. Liu, P., et al. (2021). "What Makes Good In-Context Examples for GPT-3?" arXiv:2101.06804.spring-doc.cadn.net.cn

  8. Shanahan, M., 等人 (2023). "与大型语言模型的角色扮演." arXiv:2305.16367.spring-doc.cadn.net.cn

  9. Chen, M., 等人. (2021). "评估基于代码训练的大型语言模型." arXiv:2107.03374.spring-doc.cadn.net.cn

  10. Spring AI 文档spring-doc.cadn.net.cn

  11. ChatClient API 参考spring-doc.cadn.net.cn

  12. Google 的提示工程指南spring-doc.cadn.net.cn