Skip to content
Spring AI 文档版本 2.1.0-SNAPSHOT 源快照 b71dde6c 更新于 2026-10-16

提示词工程模式

基于 Comprehensive Prompt Engineering Guide 的提示词工程技术实用实现。 该指南涵盖有效提示词工程的理论、原则与模式,而这里我们演示如何借助 Spring AI 流式的 ChatClient API 把这些概念转化为可运行的 Java 代码。 本文所用的演示源码位于:Prompt Engineering Patterns Examples。

1. 配置

配置一节概述如何用 Spring AI 设置并调优你的大语言模型(LLM)。它涵盖为你的用例选择合适的 LLM 服务商,以及配置控制模型输出质量、风格与格式的重要生成参数。

LLM 服务商选择

对于提示词工程,你会从选一个模型开始。 Spring AI 支持多个 LLM 服务商(如 OpenAI、Anthropic、Google GenAI、AWS Bedrock、Ollama 等),让你无需改动应用代码即可切换服务商——只需更新配置。 只需添加所选的 starter 依赖 spring-ai-starter-model-<MODEL-PROVIDER-NAME>。 例如,下面是启用 Anthropic Claude API 的方式:

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

你可以像这样指定 LLM 模型名:

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

启用每个模型的详细信息见参考文档。

LLM 输出配置

在我们深入提示词工程技术之前,先理解如何配置 LLM 的输出行为至关重要。Spring AI 提供若干配置选项,让你通过 ChatOptions 构建器控制生成的各个方面。

所有配置都能像下面的示例那样以编程方式应用,或在启动时通过 Spring 应用属性应用。

温度

温度控制模型响应的随机性或“创造性”。

  • 较低值(0.0-0.3):更确定、更聚焦的响应。更适合事实性问题、分类,或一致性至关重要的任务。
  • 中等值(0.4-0.7):在确定性与创造性之间平衡。适合一般用例。
  • 较高值(0.8-1.0):更有创造性、更多样、可能出人意料的响应。更适合创意写作、头脑风暴,或生成多样的选项。
java
.options(ChatOptions.builder()
        .temperature(0.1)  // Very deterministic output
        .build())

理解温度对提示词工程至关重要,因为不同技术受益于不同的温度设置。

输出长度(MaxTokens)

maxTokens 参数限制模型在响应中能生成多少令牌(词片)。

  • 较低值(5-25):用于单个词、长短语或分类标签。
  • 中等值(50-500):用于段落或简短解释。
  • 较高值(1000+):用于长文内容、故事或复杂解释。
java
.options(ChatOptions.builder()
        .maxTokens(250)  // Medium-length response
        .build())

设置恰当的输出长度,对确保你得到完整响应而又无冗余很重要。

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

这些参数让你在生成期间对令牌选择过程有细粒度控制。

  • Top-K:把令牌选择限制在 K 个最可能的下一令牌。较高的值(例如 40-50)引入更多多样性。
  • Top-P(核采样):从累计概率超过 P 的最小令牌集动态选择。常用值为 0.8-0.95。
java
.options(ChatOptions.builder()
        .topK(40)      // Consider only the top 40 tokens
        .topP(0.8)     // Sample from tokens that cover 80% of probability mass
        .build())

这些采样控制与温度协同工作,以塑造响应特征。

结构化的响应格式

除了纯文本响应(用 .content()),Spring AI 还用 .entity() 方法轻松地把 LLM 响应直接映射到 Java 对象。

java
enum Sentiment {
    POSITIVE, NEUTRAL, NEGATIVE
}

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

当与让模型返回结构化数据的系统提示词结合时,这一特性尤其强大。

模型特定选项

虽然可移植的 ChatOptions 在不同 LLM 服务商间提供一致接口,Spring AI 也提供暴露服务商特定特性与配置的、模型特定的选项类。这些模型特定选项让你能利用每个 LLM 服务商的独特能力。

java
// 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
        .thinkingEnabled(1000)                              // Anthropic-specific thinking configuration
        .build();

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

每个模型服务商都有自己的聊天选项实现(例如 OpenAiChatOptions、AnthropicChatOptions、MistralAiChatOptions),它们在实现通用接口的同时暴露服务商特定参数。这种方式让你既能用可移植选项做跨服务商兼容,也能在需要某服务商独特能力时用模型特定选项。

注意,使用模型特定选项时,你的代码会被绑定到那个特定服务商,降低可移植性。这是在访问高级服务商特定特性与在应用中保持服务商独立性之间的一个权衡。

2. 提示词工程技术

下面每一节都实现指南中的一项特定提示词工程技术。通过同时参阅“Prompt Engineering”指南与这些实现,你将不仅透彻了解有哪些提示词工程技术可用,还了解如何在生产 Java 应用中有效地实现它们。

2.1 零样本提示

零样本提示让 AI 在不提供任何示例的情况下执行一项任务。这种方式测试模型从零理解和执行指令的能力。大语言模型在海量文本语料上训练,使它们无需显式演示就能理解“翻译”“摘要”或“分类”这类任务意味着什么。

零样本非常适合模型可能在训练中见过相似示例的简单任务,以及当你想最小化提示词长度时。不过,性能会随任务复杂度和指令表述的好坏而波动。

java
// 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 枚举。

Reference: Brown, T. B., et al. (2020). "Language Models are Few-Shot Learners." arXiv:2005.14165. https://arxiv.org/abs/2005.14165

2.2 单样本与少样本提示

少样本提示给模型提供一个或多个示例以帮助引导其响应,对需要特定输出格式的任务尤其有用。通过向模型展示期望的输入-输出对示例,它能学会该模式并把新输入套用上,而无需显式的参数更新。

单样本提供一个示例,在示例成本高或模式相对简单时很有用。少样本使用多个示例(通常 3-5 个),帮助模型在更复杂的任务中更好地理解模式,或展示正确输出的不同变体。

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

少样本提示对需要特定格式的任务、处理边界情况,或在没有示例时任务定义可能有歧义时,特别有效。示例的质量与多样性显著影响性能。

Reference: Brown, T. B., et al. (2020). "Language Models are Few-Shot Learners." arXiv:2005.14165. https://arxiv.org/abs/2005.14165

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

系统提示

系统提示为语言模型设定整体上下文与目的,定义模型应在做什么的“大局”。它建立行为框架、约束,以及模型响应的高层目标,区别于具体的用户查询。

系统提示在整段对话中充当一份持久的“使命声明”,让你能设定输出格式、语气、伦理边界或角色定义等全局参数。不同于聚焦特定任务的用户提示,系统提示框定所有用户提示应被如何解读。

java
// 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 的实体映射能力结合时尤其强大:

java
// 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 输出等格式约束。

Reference: OpenAI. (2022). "System Message." https://platform.openai.com/docs/guides/chat/introduction

角色提示

角色提示指示模型采用某个特定角色或人格,这会影响它如何生成内容。通过给模型赋予一个特定的身份、专长或视角,你能影响其响应的风格、语气、深度与框架。

角色提示利用模型模拟不同专长领域与沟通风格的能力。常见角色有专家(例如“你是一位有经验的数据科学家”)、职业(例如“担任一名旅行向导”)或风格化人物(例如“像莎士比亚那样解释”)。

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

角色提示可用风格指令来增强:

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

这一技术对专门领域知识、在各响应间达成一致的语气,以及与用户创造更引人入胜、更个性化的交互,都特别有效。

Reference: Shanahan, M., et al. (2023). "Role-Play with Large Language Models." arXiv:2305.16367. https://arxiv.org/abs/2305.16367

上下文提示

上下文提示通过传入 context 参数为模型提供额外的背景信息。这一技术丰富了模型对特定情境的理解,使响应更相关、更贴切,而又不使主指令变得杂乱。

通过提供上下文信息,你帮助模型理解与当前查询相关的具体领域、受众、约束或背景事实。这会带来更准确、更相关、框架更恰当的响应。

java
// 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() 方法注入上下文变量,使上下文提示很清爽。当模型需要特定的领域知识、当为特定受众或场景调整响应,以及为确保响应与特定约束或要求一致时,这一技术尤其有价值。

Reference: Liu, P., et al. (2021). "What Makes Good In-Context Examples for GPT-3?" arXiv:2101.06804. https://arxiv.org/abs/2101.06804

2.4 退后一步提示

退后一步提示通过先获取背景知识,把复杂请求拆解为更简单的步骤。这一技术鼓励模型先从眼前的问题“退后一步”,考虑问题更广的上下文、基本原则或通用知识,再去处理具体查询。

通过把复杂问题分解为更可控的组件并先建立基础知识,模型能对难题给出更准确的响应。

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

退后一步提示对复杂推理任务、需要专门领域知识的问题,以及当你想要更全面、更深思熟虑而非即时作答的响应时,特别有效。

Reference: Zheng, Z., et al. (2023). "Take a Step Back: Evoking Reasoning via Abstraction in Large Language Models." arXiv:2310.06117. https://arxiv.org/abs/2310.06117

2.5 思维链(CoT)

思维链提示鼓励模型逐步对一个问题进行推理,这提升了复杂推理任务的准确性。通过显式地让模型展示其工作、或以逻辑步骤思考一个问题,你能大幅提升需要多步推理的任务表现。

CoT 通过鼓励模型在产出最终答案前生成中间推理步骤来起作用,类似于人类解决复杂问题的方式。这让模型的思考过程变得显式,帮助它得出更准确的结论。

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

关键短语“Let's think step by step”触发模型展示其推理过程。CoT 对数学问题、逻辑推理任务,以及任何需要多步推理的问题都特别有价值。它通过使中间推理显式来帮助减少错误。

Reference: Wei, J., et al. (2022). "Chain-of-Thought Prompting Elicits Reasoning in Large Language Models." arXiv:2201.11903. https://arxiv.org/abs/2201.11903

2.6 自我一致性

自我一致性涉及多次运行模型并聚合结果以获得更可靠的答案。这一技术通过为同一问题采样多样的推理路径、并经由多数投票选出最一致的答案,来应对 LLM 输出的可变性。

通过用不同的温度或采样设置生成多条推理路径,再聚合最终答案,自我一致性提升了复杂推理任务的准确性。它本质上是 LLM 输出的一种集成方法。

java
// 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 调用而增加的计算成本与延迟。

Reference: Wang, X., et al. (2022). "Self-Consistency Improves Chain of Thought Reasoning in Language Models." arXiv:2203.11171. https://arxiv.org/abs/2203.11171

2.7 思维树(ToT)

思维树(ToT)是一种高级推理框架,它通过同时探索多条推理路径来扩展思维链。它把问题求解视为一个搜索过程:模型生成不同的中间步骤、评估它们的前景,并探索最有前景的路径。

这一技术对有多种可能方法的复杂问题,或当求解需要先探索各种备选再找到最优路径时,特别强大。

NOTE

原始的“Prompt Engineering”指南没有为 ToT 提供实现示例,可能因为它很复杂。下面是一个演示其核心概念的简化示例。

游戏求解 ToT 示例:

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

Reference: Yao, S., et al. (2023). "Tree of Thoughts: Deliberate Problem Solving with Large Language Models." arXiv:2305.10601. https://arxiv.org/abs/2305.10601

2.8 自动提示词工程

自动提示词工程用 AI 来生成并评估备选提示词。这一元技术利用语言模型本身来创建、打磨并基准比较不同的提示词变体,为特定任务找到最优的表述。

通过系统地生成并评估提示词变体,APE 能比人工工程找到更有效的提示词,尤其对复杂任务。这是用 AI 来提升它自身表现的一种方式。

java
// 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:


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

APE 对为生产系统优化提示词、应对人工提示词工程已触及极限的棘手任务,以及在规模上系统地提升提示词质量,都特别有价值。

Reference: Zhou, Y., et al. (2022). "Large Language Models Are Human-Level Prompt Engineers." arXiv:2211.01910. https://arxiv.org/abs/2211.01910

2.9 代码提示

代码提示指用于代码相关任务的专门技术。这些技术利用 LLM 理解和生成编程语言的能力,使其能编写新代码、解释既有代码、调试问题,以及在语言之间翻译。

有效的代码提示通常涉及清晰的规格、恰当的上下文(库、框架、风格指南),有时还有相似代码的示例。温度设置往往偏低(0.1-0.3)以获得更确定的输出。

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

代码提示对自动化代码文档、原型设计、学习编程概念,以及在编程语言之间翻译,尤其有价值。其有效性可通过与少样本提示或思维链等技术结合来进一步增强。

Reference: Chen, M., et al. (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. 用不同参数(温度、top-k、top-p)测试提示词
  2. 考虑在关键决策时使用自我一致性
  3. 利用 Spring AI 的实体映射获得类型安全的响应
  4. 使用上下文提示提供应用专有的知识

有了这些技术与 Spring AI 强大的抽象,你能创造出交付一致、高质量结果的健壮 AI 驱动应用。

参考

  1. Brown, T. B., et al. (2020). "Language Models are Few-Shot Learners." arXiv:2005.14165.
  2. Wei, J., et al. (2022). "Chain-of-Thought Prompting Elicits Reasoning in Large Language Models." arXiv:2201.11903.
  3. Wang, X., et al. (2022). "Self-Consistency Improves Chain of Thought Reasoning in Language Models." arXiv:2203.11171.
  4. Yao, S., et al. (2023). "Tree of Thoughts: Deliberate Problem Solving with Large Language Models." arXiv:2305.10601.
  5. Zhou, Y., et al. (2022). "Large Language Models Are Human-Level Prompt Engineers." arXiv:2211.01910.
  6. Zheng, Z., et al. (2023). "Take a Step Back: Evoking Reasoning via Abstraction in Large Language Models." arXiv:2310.06117.
  7. Liu, P., et al. (2021). "What Makes Good In-Context Examples for GPT-3?" arXiv:2101.06804.
  8. Shanahan, M., et al. (2023). "Role-Play with Large Language Models." arXiv:2305.16367.
  9. Chen, M., et al. (2021). "Evaluating Large Language Models Trained on Code." arXiv:2107.03374.
  10. Spring AI Documentation
  11. ChatClient API Reference
  12. Google's Prompt Engineering Guide

BytesRouter 是社区翻译站点,所有译文仅供参考,一切以官方英文原文为准。