提示工程模式
基于全面的提示工程指南,本文介绍了 Prompt Engineering 技术的实用实现。该指南涵盖了有效提示工程的理论、原则和模式,而本文则展示了如何利用 Spring AI 流式的 ChatClient API 将这些概念转化为可运行的 Java 代码。本文使用的演示源代码可在以下位置获取:Prompt Engineering Patterns Examples。
1. 配置
配置部分介绍了如何使用 Spring AI 设置和调整大语言模型(LLM)。内容涵盖根据使用场景选择合适的 LLM 提供商,以及配置影响模型输出质量、风格和格式的重要生成参数。
LLM 提供商选择
在提示工程(Prompt Engineering)中,首先需要选择一个模型。Spring AI 支持多种 LLM 提供商(例如 OpenAI、Anthropic、Google GenAI、AWS Bedrock、Ollama 等),允许你在不修改应用代码的情况下切换提供商,只需更新配置即可。只需添加所选的 starter 依赖 spring-ai-starter-model-<MODEL-PROVIDER-NAME>。例如,以下是启用 Anthropic Claude API 的方法:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-anthropic</artifactId>
</dependency>
你可以这样指定 LLM 模型名称:
.options(ChatOptions.builder()
.model("claude-sonnet-4-6") // Use Anthropic's Claude model
.build())
有关启用每个模型的详细信息,请参阅参考文档。
LLM 输出配置

在深入探讨提示工程技巧之前,了解如何配置 LLM 的输出行为至关重要。Spring AI 提供了多种配置选项,允许你通过 ChatOptions builder 来控制生成的各个方面。
所有配置均可通过程序化方式进行应用,如下面的示例所示,也可以在启动时通过 Spring 应用属性进行配置。
温度
Temperature 控制模型响应的随机性,即“创造性”。
-
较低值 (0.0-0.3):更确定、更聚焦的响应。适用于事实性问题、分类,或一致性至关重要的任务。
-
中等值 (0.4-0.7):在确定性与创造性之间取得平衡。适用于通用场景。
-
较高值 (0.8-1.0):更具创造性、多样性,且可能带来惊喜的响应。适用于创意写作、头脑风暴或生成多样化选项。
.options(ChatOptions.builder()
.temperature(0.1) // Very deterministic output
.build())
理解温度对于提示工程至关重要,因为不同的技术受益于不同的温度设置。
输出长度(MaxTokens)
maxTokens 参数限制模型在响应中可以生成的 token(词元)数量。
-
低值 (5-25): 适用于单个单词、短短语或分类标签。
-
中值 (50-500): 适用于段落或简短说明。
-
高值 (1000+): 适用于长文本内容、故事或复杂解释。
.options(ChatOptions.builder()
.maxTokens(250) // Medium-length response
.build())
设置适当的输出长度对于确保获取完整回复且避免冗余至关重要。
采样控制(Top-K 与 Top-P)
这些参数使您可以在生成过程中对 token 选择过程进行细粒度控制。
-
Top-K:将候选词元限制为 K 个最可能的下一词元。较高的数值(例如 40-50)会引入更多的多样性。
-
Top-P(核采样):从累积概率超过 P 的最小词元集合中动态选择。常见的取值如 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())
这些采样控制参数与温度参数协同工作,以塑造响应特性。
结构化响应格式
除了纯文本响应(使用 .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-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 零样本提示
零样本提示(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-sonnet-4-6")
.temperature(0.1)
.maxTokens(5)
.build())
.call()
.entity(Sentiment.class);
System.out.println("Output: " + reviewSentiment);
}
此示例展示了如何在不提供示例的情况下对影评情感进行分类。注意,采用较低的温度值(0.1)以获取更具确定性的结果,并直接通过 .entity(Sentiment.class) 映射到 Java 枚举。
参考文献: Brown, T. B., et al. (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_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 prompting)在需要特定格式、处理边界情况或任务定义可能模糊的情况下尤为有效。示例的质量和多样性会显著影响性能。
**参考文献:**Brown, T. B., et al. (2020). "Language Models are Few-Shot Learners." arXiv:2005.14165. https://arxiv.org/abs/2005.14165
2.3 系统、上下文和角色提示
系统提示词
系统提示(System prompting)为语言模型设定整体上下文和目的,定义模型应当执行的“宏观框架”。它独立于具体的用户查询,为模型的响应建立行为框架、约束条件以及高层级目标。
系统提示(System prompts)在整个对话过程中充当持续性的“使命宣言”,允许你设定全局参数,例如输出格式、语气、伦理边界或角色定义。与专注于特定任务的用户提示不同,系统提示框定了所有用户提示应被解释的方式。
// 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 的实体映射功能结合使用时,其效果尤为强大:
// 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);
System prompts 在多轮对话中尤为宝贵,它们能确保在多次查询过程中保持行为的一致性,同时还可用于建立适用于所有响应的格式约束(如 JSON 输出)。
参考: OpenAI. (2022). "System Message." https://platform.openai.com/docs/guides/chat/introduction
角色提示
角色提示(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)通过传递上下文参数,为模型提供额外的背景信息。该技术增强了模型对特定情境的理解能力,从而在不使主要指令变得杂乱的情况下,生成更相关且更有针对性的响应。
通过提供上下文信息,您可以帮助模型理解与当前查询相关的特定领域、受众、约束条件或背景事实。这将带来更准确、更相关且框架更合适的响应。
// 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., et al. (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-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 在处理复杂推理任务、需要特定领域知识的问题,以及希望获得更全面且深思熟虑的回答(而非即时答案)时尤为有效。
参考文献: 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 Chain of Thought (CoT)
思维链(Chain of Thought)提示方法鼓励模型通过逐步推理来解决复杂问题,从而提升其在复杂推理任务上的准确率。通过明确要求模型展示解题过程或按逻辑步骤思考问题,你可以显著提升需要多步推理的任务性能。
CoT 通过鼓励模型在生成最终答案之前产生中间推理步骤来发挥作用,这与人类解决复杂问题的方式类似。这使模型的思考过程变得显式,并有助于其得出更准确的结论。
// 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(思维链)对于数学问题、逻辑推理任务以及任何需要多步推理的问题尤其有价值。它通过使中间推理过程显性化,有助于减少错误。
参考文献: 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 自洽性
自一致性(Self-consistency)涉及多次运行模型并对结果进行聚合,以获得更可靠的答案。该技术通过针对同一问题采样多样化的推理路径,并利用多数投票选出最具一致性的答案,从而解决大语言模型(LLM)输出中的变异性问题。
通过生成具有不同温度或采样设置的多条推理路径,然后聚合最终答案,自一致性(self-consistency)可提高复杂推理任务的准确性。它本质上是一种针对 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., et al. (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)是一种高级推理框架,通过同时探索多条推理路径来扩展 Chain of Thought。它将问题求解视为一个搜索过程,模型生成不同的中间步骤,评估其潜力,并探索最具潜力的路径。
这种技术在处理具有多种可能解决方案的复杂问题,或需要在找到最优路径之前探索各种替代方案时,尤其强大。
原始的“Prompt Engineering”指南未提供 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., et al. (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., et al. (2022). "Large Language Models Are Human-Level Prompt Engineers." arXiv:2211.01910. https://arxiv.org/abs/2211.01910
2.9 代码提示
代码提示(Code prompting)是指针对代码相关任务的专门技术。这些技术利用了大语言模型理解和生成编程语言的能力,使其能够编写新代码、解释现有代码、调试问题以及在不同语言之间进行转换。
高效的代码提示通常涉及清晰的规范、适当的上下文(如库、框架、风格指南),有时还包括类似代码的示例。为了获得更具确定性的输出,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();
}
代码提示(Code prompting)在自动化代码文档编写、原型设计、学习编程概念以及编程语言之间的转换中尤为有价值。结合少样本提示(few-shot prompting)或思维链(chain-of-thought)等技术,可进一步提升其有效性。
参考: 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,用于实现主流的提示工程(prompt engineering)技术。通过将上述技术与 Spring 强大的实体映射(entity mapping)及流式 API(fluent API)相结合,开发者能够使用清晰且易于维护的代码,构建功能复杂的 AI 驱动型应用。
最有效的方案通常涉及结合多种技术——例如,将系统提示(system prompts)与少样本示例(few-shot examples)结合,或将思维链(chain-of-thought)与角色提示(role prompting)结合。Spring AI 灵活的 API 使得这些组合方式易于实现。
对于生产环境中的应用,请记住:
-
使用不同的参数(temperature、top-k、top-p)测试提示词
-
考虑在关键决策时使用自一致性(self-consistency)
-
利用 Spring AI 的实体映射(entity mapping)实现类型安全的响应
-
使用上下文提示(contextual prompting)来提供特定于应用程序的知识
借助这些技术和 Spring AI 的强大抽象,您可以创建功能强大的 AI 驱动应用程序,从而交付稳定且高质量的成果。
引用
-
Brown, T. B., et al. (2020). "Language Models are Few-Shot Learners." arXiv:2005.14165.
-
Wei, J., et al. (2022). "Chain-of-Thought Prompting Elicits Reasoning in Large Language Models." arXiv:2201.11903.
-
Wang, X., et al. (2022). "Self-Consistency Improves Chain of Thought Reasoning in Language Models." arXiv:2203.11171.
-
Yao, S., et al. (2023). "Tree of Thoughts: Deliberate Problem Solving with Large Language Models." arXiv:2305.10601.
-
Zhou, Y., et al. (2022). "Large Language Models Are Human-Level Prompt Engineers." arXiv:2211.01910.
-
Zheng, Z., et al. (2023). "Take a Step Back: Evoking Reasoning via Abstraction in Large Language Models." arXiv:2310.06117.
-
Liu, P., et al. (2021). "What Makes Good In-Context Examples for GPT-3?" arXiv:2101.06804.
-
Shanahan, M., et al. (2023). "Role-Play with Large Language Models." arXiv:2305.16367.
-
Chen, M., et al. (2021). "Evaluating Large Language Models Trained on Code." arXiv:2107.03374.