4.1 提示词工程基础
4.1.1 提示词的重要性
提示词工程是AI应用开发中的核心技能,直接影响AI模型的输出质量。Spring AI提供了强大的提示词管理和模板系统。
提示词设计原则: 1. 明确性:指令清晰、具体 2. 上下文:提供充分的背景信息 3. 结构化:使用格式化的输入 4. 示例驱动:提供few-shot示例 5. 约束条件:明确输出格式和限制
4.1.2 Spring AI提示词架构
// Prompt类层次结构
public class Prompt {
private final List<Message> instructions;
private final ChatOptions chatOptions;
public Prompt(String text) {
this(List.of(new UserMessage(text)));
}
public Prompt(List<Message> instructions) {
this(instructions, null);
}
public Prompt(List<Message> instructions, ChatOptions chatOptions) {
this.instructions = instructions;
this.chatOptions = chatOptions;
}
}
// 消息类型
public abstract class Message {
protected final String content;
protected final Map<String, Object> properties;
}
public class SystemMessage extends Message {
public SystemMessage(String content) {
super(content);
}
}
public class UserMessage extends Message {
public UserMessage(String content) {
super(content);
}
}
public class AssistantMessage extends Message {
public AssistantMessage(String content) {
super(content);
}
}
4.2 提示词模板系统
4.2.1 基础模板使用
// PromptTemplateService.java
package com.example.springai.service;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
public class PromptTemplateService {
/**
* 基础字符串模板
*/
public String createBasicPrompt(String userInput) {
String template = """
你是一个专业的AI助手。请根据以下用户输入提供帮助:
用户输入:{input}
请提供详细、准确的回答。
""";
PromptTemplate promptTemplate = new PromptTemplate(template);
return promptTemplate.create(Map.of("input", userInput)).getContents();
}
/**
* 系统消息模板
*/
public String createSystemPrompt(String role, String task, String context) {
String template = """
你是一个{role}。你的任务是{task}。
背景信息:
{context}
请按照以下要求回答:
1. 保持专业性
2. 提供具体建议
3. 考虑实际可行性
""";
PromptTemplate promptTemplate = new PromptTemplate(template);
Map<String, Object> variables = Map.of(
"role", role,
"task", task,
"context", context
);
return promptTemplate.create(variables).getContents();
}
/**
* 从资源文件加载模板
*/
public String createFromResource(Resource templateResource, Map<String, Object> variables) {
PromptTemplate promptTemplate = new PromptTemplate(templateResource);
return promptTemplate.create(variables).getContents();
}
/**
* 多消息模板
*/
public String createMultiMessagePrompt(String systemRole, String userQuery) {
SystemPromptTemplate systemTemplate = new SystemPromptTemplate(
"你是一个{role}。请专业地回答用户问题。"
);
PromptTemplate userTemplate = new PromptTemplate(
"用户问题:{query}\n\n请提供详细回答。"
);
String systemPrompt = systemTemplate.create(Map.of("role", systemRole)).getContents();
String userPrompt = userTemplate.create(Map.of("query", userQuery)).getContents();
return systemPrompt + "\n\n" + userPrompt;
}
}
4.2.2 高级模板功能
// AdvancedPromptService.java
package com.example.springai.service;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class AdvancedPromptService {
/**
* Few-shot学习模板
*/
public String createFewShotPrompt(String task, List<Map<String, String>> examples, String input) {
String template = """
任务:{task}
示例:
{examples}
现在请处理以下输入:
输入:{input}
输出:
""";
String examplesText = examples.stream()
.map(example -> String.format("输入:%s\n输出:%s",
example.get("input"), example.get("output")))
.collect(Collectors.joining("\n\n"));
PromptTemplate promptTemplate = new PromptTemplate(template);
Map<String, Object> variables = Map.of(
"task", task,
"examples", examplesText,
"input", input
);
return promptTemplate.create(variables).getContents();
}
/**
* 链式思维(Chain of Thought)模板
*/
public String createChainOfThoughtPrompt(String problem) {
String template = """
问题:{problem}
请按照以下步骤思考:
步骤1:理解问题
- 问题的核心是什么?
- 需要什么信息?
步骤2:分析方法
- 可以使用什么方法?
- 每种方法的优缺点?
步骤3:逐步解决
- 具体的解决步骤
- 每一步的推理过程
步骤4:验证答案
- 答案是否合理?
- 是否还有其他可能?
最终答案:
""";
PromptTemplate promptTemplate = new PromptTemplate(template);
return promptTemplate.create(Map.of("problem", problem)).getContents();
}
/**
* 角色扮演模板
*/
public String createRolePlayPrompt(String role, String scenario, String objective) {
String template = """
【角色设定】
你现在是:{role}
【场景描述】
{scenario}
【目标任务】
{objective}
【行为准则】
1. 完全沉浸在角色中
2. 使用符合角色身份的语言和思维方式
3. 基于角色的专业知识和经验回答
4. 保持角色的一致性
现在开始扮演这个角色,准备好了吗?
""";
PromptTemplate promptTemplate = new PromptTemplate(template);
Map<String, Object> variables = Map.of(
"role", role,
"scenario", scenario,
"objective", objective
);
return promptTemplate.create(variables).getContents();
}
/**
* 结构化输出模板
*/
public String createStructuredOutputPrompt(String input, String outputFormat) {
String template = """
请分析以下内容并按照指定格式输出:
输入内容:
{input}
输出格式要求:
{format}
请严格按照格式要求输出,不要添加额外的解释。
""";
PromptTemplate promptTemplate = new PromptTemplate(template);
Map<String, Object> variables = Map.of(
"input", input,
"format", outputFormat
);
return promptTemplate.create(variables).getContents();
}
/**
* 多语言模板
*/
public String createMultiLanguagePrompt(String content, String sourceLanguage, String targetLanguage) {
String template = """
请将以下{sourceLanguage}内容翻译成{targetLanguage}:
原文:
{content}
翻译要求:
1. 保持原意不变
2. 语言自然流畅
3. 符合目标语言的表达习惯
4. 保留专业术语的准确性
译文:
""";
PromptTemplate promptTemplate = new PromptTemplate(template);
Map<String, Object> variables = Map.of(
"content", content,
"sourceLanguage", sourceLanguage,
"targetLanguage", targetLanguage
);
return promptTemplate.create(variables).getContents();
}
}
4.3 模板资源管理
4.3.1 模板文件组织
src/main/resources/
├── prompts/
│ ├── chat/
│ │ ├── general-chat.st
│ │ ├── technical-support.st
│ │ └── creative-writing.st
│ ├── analysis/
│ │ ├── text-analysis.st
│ │ ├── sentiment-analysis.st
│ │ └── code-review.st
│ ├── generation/
│ │ ├── code-generation.st
│ │ ├── content-creation.st
│ │ └── documentation.st
│ └── system/
│ ├── system-messages.st
│ └── safety-guidelines.st
4.3.2 模板资源加载器
// PromptResourceLoader.java
package com.example.springai.service;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Service
public class PromptResourceLoader {
private final Map<String, String> templateCache = new ConcurrentHashMap<>();
/**
* 加载模板文件
*/
public String loadTemplate(String templatePath) {
return templateCache.computeIfAbsent(templatePath, this::loadTemplateFromFile);
}
/**
* 从文件加载模板
*/
private String loadTemplateFromFile(String templatePath) {
try {
Resource resource = new ClassPathResource("prompts/" + templatePath);
return resource.getContentAsString(StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException("无法加载模板文件: " + templatePath, e);
}
}
/**
* 创建模板实例
*/
public PromptTemplate createTemplate(String templatePath) {
String templateContent = loadTemplate(templatePath);
return new PromptTemplate(templateContent);
}
/**
* 创建并填充模板
*/
public String createPrompt(String templatePath, Map<String, Object> variables) {
PromptTemplate template = createTemplate(templatePath);
return template.create(variables).getContents();
}
/**
* 清除缓存
*/
public void clearCache() {
templateCache.clear();
}
/**
* 预加载常用模板
*/
public void preloadTemplates() {
String[] commonTemplates = {
"chat/general-chat.st",
"analysis/text-analysis.st",
"generation/code-generation.st",
"system/system-messages.st"
};
for (String template : commonTemplates) {
loadTemplate(template);
}
}
}
4.3.3 模板文件示例
<!-- src/main/resources/prompts/chat/general-chat.st -->
你是一个专业的AI助手,名字叫{assistantName}。
你的特点:
- 友好、耐心、专业
- 能够理解用户的需求
- 提供准确、有用的信息
- 承认不知道的事情
当前对话上下文:
{context}
用户问题:{userMessage}
请根据上下文和用户问题,提供有帮助的回答。
<!-- src/main/resources/prompts/analysis/text-analysis.st -->
请对以下文本进行{analysisType}分析:
文本内容:
{text}
分析要求:
{requirements}
请按照以下格式输出分析结果:
## 分析摘要
[简要概述]
## 详细分析
{detailedFormat}
## 结论
[主要发现和建议]
<!-- src/main/resources/prompts/generation/code-generation.st -->
请生成{language}代码来实现以下功能:
功能描述:
{description}
技术要求:
{requirements}
代码规范:
- 使用清晰的变量和函数命名
- 添加适当的注释
- 遵循{language}的最佳实践
- 包含错误处理
{#if examples}
参考示例:
{examples}
{/if}
请提供完整的代码实现:
4.4 动态提示词生成
4.4.1 上下文感知提示词
// ContextAwarePromptService.java
package com.example.springai.service;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
@Service
public class ContextAwarePromptService {
private final PromptResourceLoader promptResourceLoader;
public ContextAwarePromptService(PromptResourceLoader promptResourceLoader) {
this.promptResourceLoader = promptResourceLoader;
}
/**
* 基于用户历史生成个性化提示词
*/
public String createPersonalizedPrompt(String userId, String currentQuery, List<String> chatHistory) {
// 分析用户偏好
UserPreference preference = analyzeUserPreference(chatHistory);
Map<String, Object> variables = Map.of(
"userId", userId,
"currentQuery", currentQuery,
"preferredStyle", preference.getStyle(),
"expertiseLevel", preference.getExpertiseLevel(),
"recentTopics", String.join(", ", preference.getRecentTopics()),
"timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
);
return promptResourceLoader.createPrompt("chat/personalized-chat.st", variables);
}
/**
* 基于时间的动态提示词
*/
public String createTimeAwarePrompt(String query) {
LocalDateTime now = LocalDateTime.now();
String timeContext = getTimeContext(now);
Map<String, Object> variables = Map.of(
"query", query,
"timeContext", timeContext,
"currentTime", now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")),
"dayOfWeek", now.getDayOfWeek().toString()
);
return promptResourceLoader.createPrompt("chat/time-aware-chat.st", variables);
}
/**
* 基于领域的专业提示词
*/
public String createDomainSpecificPrompt(String domain, String query, String expertiseLevel) {
Map<String, Object> variables = Map.of(
"domain", domain,
"query", query,
"expertiseLevel", expertiseLevel,
"domainKnowledge", getDomainKnowledge(domain),
"terminology", getDomainTerminology(domain)
);
return promptResourceLoader.createPrompt("domain/" + domain.toLowerCase() + "-expert.st", variables);
}
/**
* 分析用户偏好
*/
private UserPreference analyzeUserPreference(List<String> chatHistory) {
// 简化的偏好分析逻辑
UserPreference preference = new UserPreference();
// 分析对话风格
long formalCount = chatHistory.stream()
.mapToLong(msg -> countFormalWords(msg))
.sum();
preference.setStyle(formalCount > chatHistory.size() * 2 ? "formal" : "casual");
// 分析专业程度
long technicalCount = chatHistory.stream()
.mapToLong(msg -> countTechnicalTerms(msg))
.sum();
if (technicalCount > chatHistory.size() * 3) {
preference.setExpertiseLevel("expert");
} else if (technicalCount > chatHistory.size()) {
preference.setExpertiseLevel("intermediate");
} else {
preference.setExpertiseLevel("beginner");
}
// 提取最近话题
preference.setRecentTopics(extractTopics(chatHistory));
return preference;
}
/**
* 获取时间上下文
*/
private String getTimeContext(LocalDateTime dateTime) {
int hour = dateTime.getHour();
if (hour >= 6 && hour < 12) {
return "早上好!新的一天开始了";
} else if (hour >= 12 && hour < 18) {
return "下午好!希望你今天过得愉快";
} else if (hour >= 18 && hour < 22) {
return "晚上好!辛苦了一天";
} else {
return "夜深了,注意休息";
}
}
/**
* 获取领域知识
*/
private String getDomainKnowledge(String domain) {
return switch (domain.toLowerCase()) {
case "programming" -> "编程语言、算法、数据结构、软件工程";
case "medicine" -> "医学诊断、治疗方案、药物知识、医疗程序";
case "finance" -> "投资理论、风险管理、金融产品、市场分析";
case "education" -> "教学方法、课程设计、学习理论、教育技术";
default -> "通用知识和常识";
};
}
/**
* 获取领域术语
*/
private String getDomainTerminology(String domain) {
return switch (domain.toLowerCase()) {
case "programming" -> "变量、函数、类、对象、算法、数据结构";
case "medicine" -> "症状、诊断、治疗、药物、病理、生理";
case "finance" -> "资产、负债、收益、风险、投资、回报";
case "education" -> "课程、教学、学习、评估、反馈、目标";
default -> "基础术语";
};
}
// 辅助方法
private long countFormalWords(String text) {
String[] formalWords = {"请", "您", "敬请", "恳请", "谢谢", "感谢"};
return java.util.Arrays.stream(formalWords)
.mapToLong(word -> text.split(word, -1).length - 1)
.sum();
}
private long countTechnicalTerms(String text) {
String[] technicalWords = {"算法", "数据结构", "API", "框架", "架构", "设计模式"};
return java.util.Arrays.stream(technicalWords)
.mapToLong(word -> text.split(word, -1).length - 1)
.sum();
}
private List<String> extractTopics(List<String> chatHistory) {
// 简化的话题提取逻辑
return List.of("编程", "技术", "学习");
}
/**
* 用户偏好类
*/
public static class UserPreference {
private String style;
private String expertiseLevel;
private List<String> recentTopics;
// Getters and Setters
public String getStyle() { return style; }
public void setStyle(String style) { this.style = style; }
public String getExpertiseLevel() { return expertiseLevel; }
public void setExpertiseLevel(String expertiseLevel) { this.expertiseLevel = expertiseLevel; }
public List<String> getRecentTopics() { return recentTopics; }
public void setRecentTopics(List<String> recentTopics) { this.recentTopics = recentTopics; }
}
}
4.4.2 A/B测试提示词
// PromptABTestService.java
package com.example.springai.service;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
@Service
public class PromptABTestService {
private final PromptResourceLoader promptResourceLoader;
private final Random random = new Random();
private final Map<String, ABTestMetrics> testMetrics = new ConcurrentHashMap<>();
public PromptABTestService(PromptResourceLoader promptResourceLoader) {
this.promptResourceLoader = promptResourceLoader;
}
/**
* A/B测试提示词选择
*/
public ABTestResult selectPromptVariant(String testName, Map<String, Object> variables) {
ABTestConfig config = getTestConfig(testName);
String selectedVariant = selectVariant(config);
String prompt = promptResourceLoader.createPrompt(
config.getVariantPath(selectedVariant),
variables
);
return new ABTestResult(testName, selectedVariant, prompt);
}
/**
* 记录测试结果
*/
public void recordTestResult(String testName, String variant, boolean success, double score) {
ABTestMetrics metrics = testMetrics.computeIfAbsent(
testName + ":" + variant,
k -> new ABTestMetrics()
);
metrics.recordResult(success, score);
}
/**
* 获取测试统计
*/
public Map<String, ABTestMetrics> getTestStatistics(String testName) {
return testMetrics.entrySet().stream()
.filter(entry -> entry.getKey().startsWith(testName + ":"))
.collect(java.util.stream.Collectors.toMap(
entry -> entry.getKey().substring(testName.length() + 1),
Map.Entry::getValue
));
}
/**
* 选择变体
*/
private String selectVariant(ABTestConfig config) {
double rand = random.nextDouble();
double cumulative = 0.0;
for (Map.Entry<String, Double> entry : config.getVariantWeights().entrySet()) {
cumulative += entry.getValue();
if (rand <= cumulative) {
return entry.getKey();
}
}
return config.getVariantWeights().keySet().iterator().next();
}
/**
* 获取测试配置
*/
private ABTestConfig getTestConfig(String testName) {
// 这里可以从配置文件或数据库加载
return switch (testName) {
case "chat-style" -> new ABTestConfig(
Map.of(
"formal", 0.5,
"casual", 0.5
),
Map.of(
"formal", "chat/formal-chat.st",
"casual", "chat/casual-chat.st"
)
);
case "code-generation" -> new ABTestConfig(
Map.of(
"detailed", 0.4,
"concise", 0.4,
"example-driven", 0.2
),
Map.of(
"detailed", "generation/detailed-code.st",
"concise", "generation/concise-code.st",
"example-driven", "generation/example-code.st"
)
);
default -> throw new IllegalArgumentException("未知的测试: " + testName);
};
}
/**
* A/B测试配置
*/
public static class ABTestConfig {
private final Map<String, Double> variantWeights;
private final Map<String, String> variantPaths;
public ABTestConfig(Map<String, Double> variantWeights, Map<String, String> variantPaths) {
this.variantWeights = variantWeights;
this.variantPaths = variantPaths;
}
public Map<String, Double> getVariantWeights() { return variantWeights; }
public String getVariantPath(String variant) { return variantPaths.get(variant); }
}
/**
* A/B测试结果
*/
public static class ABTestResult {
private final String testName;
private final String variant;
private final String prompt;
public ABTestResult(String testName, String variant, String prompt) {
this.testName = testName;
this.variant = variant;
this.prompt = prompt;
}
public String getTestName() { return testName; }
public String getVariant() { return variant; }
public String getPrompt() { return prompt; }
}
/**
* A/B测试指标
*/
public static class ABTestMetrics {
private int totalRequests = 0;
private int successfulRequests = 0;
private double totalScore = 0.0;
public synchronized void recordResult(boolean success, double score) {
totalRequests++;
if (success) {
successfulRequests++;
}
totalScore += score;
}
public synchronized double getSuccessRate() {
return totalRequests == 0 ? 0.0 : (double) successfulRequests / totalRequests;
}
public synchronized double getAverageScore() {
return totalRequests == 0 ? 0.0 : totalScore / totalRequests;
}
public synchronized int getTotalRequests() { return totalRequests; }
public synchronized int getSuccessfulRequests() { return successfulRequests; }
}
}
4.5 提示词优化策略
4.5.1 提示词质量评估
// PromptQualityEvaluator.java
package com.example.springai.service;
import org.springframework.ai.chat.ChatModel;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
@Service
public class PromptQualityEvaluator {
private final ChatModel chatModel;
public PromptQualityEvaluator(ChatModel chatModel) {
this.chatModel = chatModel;
}
/**
* 评估提示词质量
*/
public PromptQualityScore evaluatePrompt(String promptText, List<String> testInputs) {
double totalScore = 0.0;
int validResponses = 0;
for (String input : testInputs) {
try {
String fullPrompt = promptText.replace("{input}", input);
Prompt prompt = new Prompt(fullPrompt);
ChatResponse response = chatModel.call(prompt);
String output = response.getResult().getOutput().getContent();
double score = evaluateResponse(input, output);
totalScore += score;
validResponses++;
} catch (Exception e) {
// 记录错误但继续评估
System.err.println("评估失败: " + e.getMessage());
}
}
double averageScore = validResponses > 0 ? totalScore / validResponses : 0.0;
return new PromptQualityScore(averageScore, validResponses, testInputs.size());
}
/**
* 评估单个响应质量
*/
private double evaluateResponse(String input, String output) {
double score = 0.0;
// 相关性评分(0-30分)
score += evaluateRelevance(input, output) * 30;
// 完整性评分(0-25分)
score += evaluateCompleteness(output) * 25;
// 准确性评分(0-25分)
score += evaluateAccuracy(output) * 25;
// 清晰度评分(0-20分)
score += evaluateClarity(output) * 20;
return Math.min(score, 100.0);
}
/**
* 评估相关性
*/
private double evaluateRelevance(String input, String output) {
// 简化的相关性评估
String[] inputWords = input.toLowerCase().split("\\s+");
String outputLower = output.toLowerCase();
long matchingWords = java.util.Arrays.stream(inputWords)
.filter(word -> word.length() > 3) // 忽略短词
.mapToLong(word -> outputLower.contains(word) ? 1 : 0)
.sum();
return Math.min(1.0, (double) matchingWords / Math.max(1, inputWords.length));
}
/**
* 评估完整性
*/
private double evaluateCompleteness(String output) {
// 基于长度和结构的完整性评估
if (output.length() < 50) return 0.3;
if (output.length() < 100) return 0.6;
if (output.length() < 200) return 0.8;
return 1.0;
}
/**
* 评估准确性
*/
private double evaluateAccuracy(String output) {
// 简化的准确性评估
// 检查是否包含常见的错误指示词
String[] errorIndicators = {"不确定", "可能", "也许", "不知道", "无法确定"};
long errorCount = java.util.Arrays.stream(errorIndicators)
.mapToLong(indicator -> output.contains(indicator) ? 1 : 0)
.sum();
return Math.max(0.0, 1.0 - (errorCount * 0.2));
}
/**
* 评估清晰度
*/
private double evaluateClarity(String output) {
// 基于句子结构和可读性的清晰度评估
String[] sentences = output.split("[.!?]+");
if (sentences.length == 0) return 0.0;
double avgSentenceLength = (double) output.length() / sentences.length;
// 理想句子长度在20-100字符之间
if (avgSentenceLength >= 20 && avgSentenceLength <= 100) {
return 1.0;
} else if (avgSentenceLength < 20) {
return avgSentenceLength / 20.0;
} else {
return Math.max(0.0, 1.0 - (avgSentenceLength - 100) / 200.0);
}
}
/**
* 提示词质量分数
*/
public static class PromptQualityScore {
private final double score;
private final int validResponses;
private final int totalTests;
public PromptQualityScore(double score, int validResponses, int totalTests) {
this.score = score;
this.validResponses = validResponses;
this.totalTests = totalTests;
}
public double getScore() { return score; }
public int getValidResponses() { return validResponses; }
public int getTotalTests() { return totalTests; }
public double getSuccessRate() { return (double) validResponses / totalTests; }
public String getGrade() {
if (score >= 90) return "A";
if (score >= 80) return "B";
if (score >= 70) return "C";
if (score >= 60) return "D";
return "F";
}
}
}
4.5.2 提示词优化建议
// PromptOptimizer.java
package com.example.springai.service;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
@Service
public class PromptOptimizer {
/**
* 分析提示词并提供优化建议
*/
public PromptOptimizationReport analyzeAndOptimize(String prompt) {
List<OptimizationSuggestion> suggestions = new ArrayList<>();
// 检查长度
suggestions.addAll(analyzeLengthIssues(prompt));
// 检查结构
suggestions.addAll(analyzeStructureIssues(prompt));
// 检查清晰度
suggestions.addAll(analyzeClarityIssues(prompt));
// 检查指令明确性
suggestions.addAll(analyzeInstructionClarity(prompt));
// 生成优化版本
String optimizedPrompt = generateOptimizedPrompt(prompt, suggestions);
return new PromptOptimizationReport(prompt, optimizedPrompt, suggestions);
}
/**
* 分析长度问题
*/
private List<OptimizationSuggestion> analyzeLengthIssues(String prompt) {
List<OptimizationSuggestion> suggestions = new ArrayList<>();
if (prompt.length() < 50) {
suggestions.add(new OptimizationSuggestion(
"LENGTH_TOO_SHORT",
"提示词过短,可能缺乏足够的上下文信息",
"添加更多背景信息和具体要求",
"HIGH"
));
} else if (prompt.length() > 2000) {
suggestions.add(new OptimizationSuggestion(
"LENGTH_TOO_LONG",
"提示词过长,可能影响模型理解",
"精简内容,突出核心要求",
"MEDIUM"
));
}
return suggestions;
}
/**
* 分析结构问题
*/
private List<OptimizationSuggestion> analyzeStructureIssues(String prompt) {
List<OptimizationSuggestion> suggestions = new ArrayList<>();
// 检查是否有明确的任务描述
if (!containsTaskDescription(prompt)) {
suggestions.add(new OptimizationSuggestion(
"MISSING_TASK_DESCRIPTION",
"缺少明确的任务描述",
"在开头添加清晰的任务说明",
"HIGH"
));
}
// 检查是否有输出格式要求
if (!containsOutputFormat(prompt)) {
suggestions.add(new OptimizationSuggestion(
"MISSING_OUTPUT_FORMAT",
"缺少输出格式说明",
"指定期望的输出格式和结构",
"MEDIUM"
));
}
return suggestions;
}
/**
* 分析清晰度问题
*/
private List<OptimizationSuggestion> analyzeClarityIssues(String prompt) {
List<OptimizationSuggestion> suggestions = new ArrayList<>();
// 检查模糊词汇
String[] vagueWords = {"一些", "可能", "大概", "差不多", "类似"};
for (String word : vagueWords) {
if (prompt.contains(word)) {
suggestions.add(new OptimizationSuggestion(
"VAGUE_LANGUAGE",
"包含模糊词汇: " + word,
"使用更具体、明确的表达",
"MEDIUM"
));
break;
}
}
// 检查句子长度
String[] sentences = prompt.split("[.!?]+");
for (String sentence : sentences) {
if (sentence.trim().length() > 150) {
suggestions.add(new OptimizationSuggestion(
"LONG_SENTENCES",
"存在过长的句子",
"将长句拆分为多个短句",
"LOW"
));
break;
}
}
return suggestions;
}
/**
* 分析指令明确性
*/
private List<OptimizationSuggestion> analyzeInstructionClarity(String prompt) {
List<OptimizationSuggestion> suggestions = new ArrayList<>();
// 检查是否包含动作词
String[] actionWords = {"分析", "生成", "创建", "解释", "总结", "比较", "评估"};
boolean hasActionWord = java.util.Arrays.stream(actionWords)
.anyMatch(prompt::contains);
if (!hasActionWord) {
suggestions.add(new OptimizationSuggestion(
"MISSING_ACTION_WORDS",
"缺少明确的动作指令",
"使用具体的动作词(如:分析、生成、解释等)",
"HIGH"
));
}
return suggestions;
}
/**
* 生成优化后的提示词
*/
private String generateOptimizedPrompt(String originalPrompt, List<OptimizationSuggestion> suggestions) {
StringBuilder optimized = new StringBuilder();
// 添加结构化开头
optimized.append("## 任务描述\n");
// 如果原提示词缺少任务描述,添加一个
boolean needsTaskDescription = suggestions.stream()
.anyMatch(s -> "MISSING_TASK_DESCRIPTION".equals(s.getType()));
if (needsTaskDescription) {
optimized.append("请根据以下要求完成任务:\n\n");
}
// 添加原始内容(可能经过修改)
String processedContent = originalPrompt;
// 应用一些基本优化
processedContent = processedContent.replaceAll("一些", "具体的");
processedContent = processedContent.replaceAll("可能", "应该");
optimized.append(processedContent);
// 如果缺少输出格式,添加一个
boolean needsOutputFormat = suggestions.stream()
.anyMatch(s -> "MISSING_OUTPUT_FORMAT".equals(s.getType()));
if (needsOutputFormat) {
optimized.append("\n\n## 输出要求\n");
optimized.append("请按照以下格式输出结果:\n");
optimized.append("1. 简要概述\n");
optimized.append("2. 详细内容\n");
optimized.append("3. 总结建议\n");
}
return optimized.toString();
}
// 辅助方法
private boolean containsTaskDescription(String prompt) {
String[] taskIndicators = {"任务", "要求", "请", "需要", "目标"};
return java.util.Arrays.stream(taskIndicators)
.anyMatch(prompt::contains);
}
private boolean containsOutputFormat(String prompt) {
String[] formatIndicators = {"格式", "输出", "结果", "返回", "显示"};
return java.util.Arrays.stream(formatIndicators)
.anyMatch(prompt::contains);
}
/**
* 优化建议
*/
public static class OptimizationSuggestion {
private final String type;
private final String description;
private final String recommendation;
private final String priority;
public OptimizationSuggestion(String type, String description, String recommendation, String priority) {
this.type = type;
this.description = description;
this.recommendation = recommendation;
this.priority = priority;
}
// Getters
public String getType() { return type; }
public String getDescription() { return description; }
public String getRecommendation() { return recommendation; }
public String getPriority() { return priority; }
}
/**
* 优化报告
*/
public static class PromptOptimizationReport {
private final String originalPrompt;
private final String optimizedPrompt;
private final List<OptimizationSuggestion> suggestions;
public PromptOptimizationReport(String originalPrompt, String optimizedPrompt, List<OptimizationSuggestion> suggestions) {
this.originalPrompt = originalPrompt;
this.optimizedPrompt = optimizedPrompt;
this.suggestions = suggestions;
}
// Getters
public String getOriginalPrompt() { return originalPrompt; }
public String getOptimizedPrompt() { return optimizedPrompt; }
public List<OptimizationSuggestion> getSuggestions() { return suggestions; }
public int getHighPrioritySuggestions() {
return (int) suggestions.stream()
.filter(s -> "HIGH".equals(s.getPriority()))
.count();
}
}
}
4.6 提示词管理控制器
4.6.1 提示词API
// PromptController.java
package com.example.springai.controller;
import com.example.springai.service.*;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/prompts")
public class PromptController {
private final PromptTemplateService promptTemplateService;
private final AdvancedPromptService advancedPromptService;
private final ContextAwarePromptService contextAwarePromptService;
private final PromptABTestService promptABTestService;
private final PromptQualityEvaluator promptQualityEvaluator;
private final PromptOptimizer promptOptimizer;
public PromptController(
PromptTemplateService promptTemplateService,
AdvancedPromptService advancedPromptService,
ContextAwarePromptService contextAwarePromptService,
PromptABTestService promptABTestService,
PromptQualityEvaluator promptQualityEvaluator,
PromptOptimizer promptOptimizer
) {
this.promptTemplateService = promptTemplateService;
this.advancedPromptService = advancedPromptService;
this.contextAwarePromptService = contextAwarePromptService;
this.promptABTestService = promptABTestService;
this.promptQualityEvaluator = promptQualityEvaluator;
this.promptOptimizer = promptOptimizer;
}
/**
* 创建基础提示词
*/
@PostMapping("/basic")
public String createBasicPrompt(@RequestBody String userInput) {
return promptTemplateService.createBasicPrompt(userInput);
}
/**
* 创建系统提示词
*/
@PostMapping("/system")
public String createSystemPrompt(
@RequestParam String role,
@RequestParam String task,
@RequestParam String context
) {
return promptTemplateService.createSystemPrompt(role, task, context);
}
/**
* 创建Few-shot提示词
*/
@PostMapping("/few-shot")
public String createFewShotPrompt(
@RequestParam String task,
@RequestBody Map<String, Object> request
) {
@SuppressWarnings("unchecked")
List<Map<String, String>> examples = (List<Map<String, String>>) request.get("examples");
String input = (String) request.get("input");
return advancedPromptService.createFewShotPrompt(task, examples, input);
}
/**
* 创建链式思维提示词
*/
@PostMapping("/chain-of-thought")
public String createChainOfThoughtPrompt(@RequestBody String problem) {
return advancedPromptService.createChainOfThoughtPrompt(problem);
}
/**
* 创建个性化提示词
*/
@PostMapping("/personalized")
public String createPersonalizedPrompt(
@RequestParam String userId,
@RequestParam String query,
@RequestBody List<String> chatHistory
) {
return contextAwarePromptService.createPersonalizedPrompt(userId, query, chatHistory);
}
/**
* A/B测试提示词
*/
@PostMapping("/ab-test/{testName}")
public PromptABTestService.ABTestResult abTestPrompt(
@PathVariable String testName,
@RequestBody Map<String, Object> variables
) {
return promptABTestService.selectPromptVariant(testName, variables);
}
/**
* 记录A/B测试结果
*/
@PostMapping("/ab-test/{testName}/result")
public void recordABTestResult(
@PathVariable String testName,
@RequestParam String variant,
@RequestParam boolean success,
@RequestParam double score
) {
promptABTestService.recordTestResult(testName, variant, success, score);
}
/**
* 获取A/B测试统计
*/
@GetMapping("/ab-test/{testName}/stats")
public Map<String, PromptABTestService.ABTestMetrics> getABTestStats(@PathVariable String testName) {
return promptABTestService.getTestStatistics(testName);
}
/**
* 评估提示词质量
*/
@PostMapping("/evaluate")
public PromptQualityEvaluator.PromptQualityScore evaluatePrompt(
@RequestBody Map<String, Object> request
) {
String promptText = (String) request.get("prompt");
@SuppressWarnings("unchecked")
List<String> testInputs = (List<String>) request.get("testInputs");
return promptQualityEvaluator.evaluatePrompt(promptText, testInputs);
}
/**
* 优化提示词
*/
@PostMapping("/optimize")
public PromptOptimizer.PromptOptimizationReport optimizePrompt(@RequestBody String prompt) {
return promptOptimizer.analyzeAndOptimize(prompt);
}
}
4.7 本章总结
4.7.1 核心要点
- 提示词工程:设计有效提示词的原则和技巧
- 模板系统:Spring AI的模板管理和动态生成
- 高级技术:Few-shot学习、链式思维、角色扮演
- 质量评估:提示词效果评估和优化建议
- A/B测试:提示词变体测试和性能比较
4.7.2 最佳实践
- 结构化设计:使用清晰的提示词结构
- 上下文管理:提供充分的背景信息
- 模板复用:建立提示词模板库
- 持续优化:基于反馈不断改进
- 测试验证:使用A/B测试验证效果
4.7.3 练习题
基础练习
- 创建一个代码生成的提示词模板
- 实现一个简单的Few-shot学习示例
- 设计一个文本分析的提示词
进阶练习
- 实现上下文感知的个性化提示词
- 创建A/B测试系统比较不同提示词效果
- 开发提示词质量评估工具
高级练习
- 构建智能提示词优化系统
- 实现多轮对话的上下文管理
- 创建领域特定的提示词生成器
下一章我们将学习向量数据库与文档处理的相关技术。