提示词工程(上):写好 Prompt 的 CO-STAR 框架
前几篇我们教会了 AI 说话、流式输出、结构化返回,甚至记住了上下文。但你是否遇到过这种情况:同样的问题,问 ChatGPT 能给出完美答案,问你自己接的模型却答非所问?。这是 AI 应用开发中最被低估、却又最能拉开差距的技能。一个好的 Prompt,能让同一个模型的表现天差地别。本篇我们先掌握一套立即可用的框架——,再用让 AI “有样学样”。整篇文章不需要引入任何新依赖,你可以在前面任意一个项
前几篇我们教会了 AI 说话、流式输出、结构化返回,甚至记住了上下文。但你是否遇到过这种情况:同样的问题,问 ChatGPT 能给出完美答案,问你自己接的模型却答非所问?问题往往不出在模型本身,而在于你给它的“指令”——也就是 Prompt。
今天开始,我们进入一个全新的主题:提示词工程(Prompt Engineering)。这是 AI 应用开发中最被低估、却又最能拉开差距的技能。一个好的 Prompt,能让同一个模型的表现天差地别。本篇我们先掌握一套立即可用的框架——CO-STAR,再用少样本提示(Few-shot Prompting) 让 AI “有样学样”。整篇文章不需要引入任何新依赖,你可以在前面任意一个项目上直接实验。
一、痛点场景:AI 为什么不听你的话?
先来看一个真实案例。假设你正在做一个“智能邮件润色”功能,你给 AI 的指令是:
帮我润色这封邮件。
然后 AI 返回了一封语气浮夸、风格像演讲稿的“润色版”,你只能手动改回原来的调调。为什么?因为你没有告诉它:
- 背景:这是发给谁的邮件?
- 目标:希望达到什么效果?
- 风格:正式还是随意?
- 语气:热情还是冷静?
- 受众:对方是老板还是客户?
- 格式:要不要保留原来的段落结构?
当你把这六条信息补全后,AI 的输出质量会直线上升。CO-STAR 框架正是这六个维度的缩写。 它最初由新加坡 GovTech 的数据科学部门提出,现已成为开发者社区中最受欢迎的 Prompt 模板之一。
二、核心概念快览
2.1 CO-STAR 框架
CO-STAR 把一条高质量的 Prompt 拆解为六个要素,每个字母代表一个维度:
| 字母 | 含义 | 解释 | 示例 |
|---|---|---|---|
| C | Context(背景) | 告诉 AI 当前的情境,它需要知道哪些上下文 | “你是一家电商公司的客服主管” |
| O | Objective(目标) | 明确希望 AI 完成的具体任务 | “请起草一封回复客户投诉的邮件” |
| S | Style(风格) | 指定写作文体或风格 | “用正式商务信函的风格” |
| T | Tone(语气) | 设定情感色彩和态度 | “语气要诚恳、有同理心,但不卑微” |
| A | Audience(受众) | 说明最终读者是谁 | “收件人是一位因物流延误而不满的客户” |
| R | Response(响应格式) | 约束输出的结构和格式 | “邮件主题单独一行,正文不超过 150 字” |
记住这个框架,你就掌握了高质量 Prompt 的“骨架”。任何场景下的 Prompt 设计都可以从这六个维度去思考。
2.2 少样本提示(Few-shot Prompting)
除了给框架,还有另一种“立竿见影”的技巧:给 AI 几个例子,让它模仿你的格式和风格。 这就是少样本提示。在 Prompt 中提供 2-3 个“输入→输出”示例,模型会从中学习到你的期望模式,比单纯用文字描述效果更好。
比如你想让 AI 把口语化的问题转换成 SQL 查询,与其长篇大论地解释语法,不如直接给两个例子:
示例1:
用户问:"上个月销售额是多少"
SQL: SELECT SUM(amount) FROM sales WHERE month = '2026-04';
示例2:
用户问:"张三最近买了什么"
SQL: SELECT product FROM orders WHERE customer = '张三' ORDER BY date DESC;
然后再说你的真实问题,AI 会顺着这个模式往下写。这就是 Few-shot 的威力。
2.3 环境说明
本篇不需要新增任何依赖或 Bean,所有示例都在 ChatClient 上完成。我们会在同一个 Controller 里展示“裸问”、“CO-STAR 优化”和“CO-STAR + Few-shot”三种效果差异,让你直观感受 Prompt 工程的价值。
三、环境准备
继续使用之前任意一篇搭建的 Spring Boot 项目,确保 spring-ai-starter-model-openai 已引入,且 application.yml 中配置好了 API Key。以 DeepSeek 为例:
spring:
ai:
openai:
api-key: ${DEEPSEEK_API_KEY}
base-url: https://api.deepseek.com
chat:
options:
model: deepseek-chat
temperature: 0.7
关于 temperature 的设定:在需要模型严格遵循指令格式的场景(如格式化输出),建议温度设在 0.1-0.3 以降低随机性;但为了对比 Prompt 优化前后的差异,0.7 更能体现提示词的引导效果。你可以根据实际测试情况微调。
四、代码实战
4.1 编写 PromptService
创建一个 PromptService,把不同级别的 Prompt 封装成方法,方便对比效果:
package com.example.springaihelloworld.service;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
@Service
public class PromptService {
private final ChatClient chatClient;
public PromptService(ChatClient chatClient) {
this.chatClient = chatClient;
}
/**
* 裸问:不给任何额外上下文
*/
public String rawPrompt(String userInput) {
return chatClient
.prompt()
.user(userInput)
.call()
.content();
}
/**
* 使用 CO-STAR 框架优化的 Prompt
*/
public String costarPrompt(String userInput) {
String systemPrompt = """
你是一个专业的客户服务代表。
## 背景(Context)
你在一家售卖智能家居产品的电商公司工作。用户可能会询问产品功能、退换货政策、物流状态等问题。
## 目标(Objective)
根据用户输入,给出一个礼貌、专业且信息准确的回复。
## 风格(Style)
简洁清晰,避免冗长,每段不超过两句话。
## 语气(Tone)
亲切但不随意,耐心但不啰嗦。
## 受众(Audience)
大多数用户是非技术背景,避免使用术语。如果必须提到技术参数,要加上简短解释。
## 响应格式(Response)
先对用户的问题表示理解,再给出核心解决方案,最后询问是否还有其他可以帮助的地方。
""";
return chatClient
.prompt()
.system(systemPrompt)
.user(userInput)
.call()
.content();
}
/**
* CO-STAR + 少样本提示(Few-shot)
* 在 CO-STAR 基础上,给出两个具体的"用户问题 → 理想回复"示例
*/
public String costarWithFewShotPrompt(String userInput) {
String systemPrompt = """
你是一个专业的客户服务代表。
## 背景(Context)
你在一家售卖智能家居产品的电商公司工作。用户可能会询问产品功能、退换货政策、物流状态等问题。
## 目标(Objective)
根据用户输入,给出一个礼貌、专业且信息准确的回复。
## 风格(Style)
简洁清晰,避免冗长,每段不超过两句话。
## 语气(Tone)
亲切但不随意,耐心但不啰嗦。
## 受众(Audience)
大多数用户是非技术背景,避免使用术语。如果必须提到技术参数,要加上简短解释。
## 响应格式(Response)
先对用户的问题表示理解,再给出核心解决方案,最后询问是否还有其他可以帮助的地方。
## 示例(Examples)
以下是你之前处理过的两个工单,供你参考回复的风格:
---示例1---
用户问题:我刚买的智能灯泡怎么连不上Wi-Fi?
客服回复:您好,非常理解您遇到连网问题的烦恼。首先请确认灯泡处于配对模式(快闪白光),然后打开App搜索设备。如果仍然不行,可以尝试将灯泡靠近路由器再试一次。还有其他问题可以随时问我哦。
---示例1结束---
---示例2---
用户问题:这个插座防水吗?能不能用在浴室里?
客服回复:您好,感谢您的关注。这款插座不具备防水功能,不建议在浴室等潮湿环境中使用,存在安全隐患。我们有专门为浴室设计的防溅水款,需要我为您推荐链接吗?
---示例2结束---
""";
return chatClient
.prompt()
.system(systemPrompt)
.user(userInput)
.call()
.content();
}
}
代码说明:
rawPrompt:直接把用户的话丢给模型,没有任何额外指引,用来做“最差情况”的参照。costarPrompt:在 System Prompt 中严格按照 CO-STAR 六要素编写了背景、目标、风格、语气、受众和响应格式。costarWithFewShotPrompt:在 CO-STAR 基础上追加了两个具体示例,让 AI 能模仿实际的回复风格。
4.2 编写对比 Controller
新建 PromptComparisonController,提供三个端点,方便你用同一个问题横向对比:
package com.example.springaihelloworld.controller;
import com.example.springaihelloworld.service.PromptService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class PromptComparisonController {
private final PromptService promptService;
public PromptComparisonController(PromptService promptService) {
this.promptService = promptService;
}
/**
* 裸问:不做任何提示词优化
*/
@GetMapping("/prompt/raw")
public String raw(@RequestParam(defaultValue = "你们家智能门铃怎么安装") String q) {
return promptService.rawPrompt(q);
}
/**
* CO-STAR 优化版
*/
@GetMapping("/prompt/costar")
public String costar(@RequestParam(defaultValue = "你们家智能门铃怎么安装") String q) {
return promptService.costarPrompt(q);
}
/**
* CO-STAR + Few-shot 增强版
*/
@GetMapping("/prompt/fewshot")
public String fewshot(@RequestParam(defaultValue = "你们家智能门铃怎么安装") String q) {
return promptService.costarWithFewShotPrompt(q);
}
}
五、运行与演示
5.1 启动项目
确认 API Key 已设置,启动 Spring Boot。
5.2 对比三种效果
用同一个问题,分别访问三个接口,观察回复的差异。建议用“你们家智能门铃怎么安装”或者“刚买的台灯有问题想退货”这种客服场景的问题。
裸问版:
http://localhost:8080/prompt/raw?q=你们家智能门铃怎么安装
可能的回复:
智能门铃安装步骤:1. 将门铃底座固定在墙上。2. 连接电源线。3. 下载App扫描二维码配对。4. 测试门铃是否正常工作。如有问题请联系客服。
像是一份说明书摘抄,缺少人情味,也没有主动提供进一步帮助。
CO-STAR 优化版:
http://localhost:8080/prompt/costar?q=你们家智能门铃怎么安装
可能的回复:
您好,很高兴为您解答智能门铃的安装问题。安装前请确保门口有稳定的Wi-Fi信号。先用底座定位钻孔位置,固定好底座后,将门铃本体扣上并接通电源。然后打开App扫描门铃背面的二维码,按照引导完成配对即可。如果在配对过程中遇到问题,可以随时告诉我,我会一步步协助您。
可以看到:开头有了打招呼、中间步骤更有人情味、最后主动提出协助。这就是 CO-STAR 中 T(语气)和 R(响应格式)的作用。
CO-STAR + Few-shot 增强版:
http://localhost:8080/prompt/fewshot?q=你们家智能门铃怎么安装
可能的回复:
您好,完全理解您对新设备的期待和一点小忐忑!安装其实很简单:找个离路由器近的位置,用自带螺丝固定底座,然后把门铃主体扣上去,听到“咔哒”一声就好了。打开App点“添加设备”,扫门铃背后的码,跟着提示走就行。如果过程中指示灯不是白色快闪,可以长按重置按钮5秒进入配对模式。需要我帮您录个安装短视频吗?
对比三个回复,你会发现 Few-shot 版不仅完全继承了 CO-STAR 的结构,还学会了示例中的“先用共情句开头”、“使用口语化短句”、“最后询问是否需要进一步帮助”等隐性风格,甚至主动提出了“录视频”这种超出基本指令的贴心服务。这就是少样本提示的独特价值——示例比描述更能精准地传递你期望的风格。
六、常见问题与避坑提示
问题一:CO-STAR 维度太多,记不住怎么办?
刚开始不需要每次都写满六个维度。你可以先抓住 C(背景)和 O(目标),这两个是最核心的。熟练后再逐步加上 S、T、A、R。很多 AI 辅助写 Prompt 的工具(包括 Cursor)也内置了 CO-STAR 模板,可以直接调用。
问题二:Few-shot 的示例要怎么选?
- 示例要覆盖你期望的主要场景。如果用户会问“安装”、“退货”、“功能”,三个场景各给一个例子。
- 示例的格式要和期望输出完全一致。
- 不要给“反面示例”,模型有时会混淆。
问题三:加了 System Prompt 后,回复还是不像示例
可能原因:
- 温度(temperature)太高,模型随机性过大,建议降到 0.3-0.5。
- 示例太少,增加到 3-4 个。
- System Prompt 中的描述和示例风格冲突(比如你要求“简洁”,但示例都很长)。这时优先调整示例,因为示例的优先级通常高于文字描述。
问题四:Prompt 太长会不会影响速度?
会。Prompt 越长,API 调用耗时越长,Token 消耗也越多。对于生产环境,建议将 System Prompt 提炼到 2000 字符以内,示例也控制在 2-3 个。如果业务场景复杂,可以考虑将长 Prompt 拆分为“核心指令 + 按需加载的知识库”(这就是 RAG 的核心思想,后面会专门讲)。
问题五:CO-STAR 只能用在客服场景吗?
当然不是。CO-STAR 是通用框架,你可以套用到任何场景。比如代码审查:
- C:你是一个资深 Java 代码审查员
- O:检查代码中的线程安全、空指针和性能问题
- S:专业但不傲慢
- T:直接、建设性
- A:有 3 年经验的 Java 开发者
- R:每条建议包含“问题”、“风险”、“改进方案”
你会发现这个框架几乎可以无限复用。
七、小结与下一步预告
本篇回顾
- 理解了 Prompt 质量对 AI 输出的决定性影响。
- 掌握了 CO-STAR 框架:Context、Objective、Style、Tone、Audience、Response。
- 学会了少样本提示(Few-shot Prompting):用示例引导模型输出。
- 通过代码实战,对比了裸问、CO-STAR 优化版、Few-shot 增强版三种效果差异。
动手建议
在你自己项目中,挑一个已有的 AI 功能,用 CO-STAR 框架重写它的 System Prompt,然后对比前后的输出质量。你会发现:很多时候不是模型不够好,而是你没有把话说明白。
下一步预告
CO-STAR 解决了“怎么说”,但遇到复杂推理任务(比如数学题、逻辑分析、多步骤决策)时,光靠格式还不够。下一篇我们将学习思维链(Chain of Thought) 和 自我一致性(Self-Consistency),让 AI 像人一样“一步一步推理”,大幅提升复杂问题的准确率。我们还会结合 Cursor Rules,把这些 Prompt 技巧沉淀为可复用的团队规范。
下一篇《提示词工程(下):思维链、自我一致与 Cursor 规则》见。
本系列博客基于 Spring AI 1.1.6 版本编写。提示词工程的最佳实践与模型能力密切相关,不同模型对同一 Prompt 的响应可能存在差异,建议在实际项目中针对所选模型进行充分测试和调优。
更多推荐




所有评论(0)