跳转到正文
Silasye 的博客
返回

提示词工程-结构化提示词

从年初,哦不,应该是去年开始,Agent 开发在国内就逐渐火起来了,但是现在工作中给我的感觉是,这个东西其实不足以成为一个专门的岗位,而应该是每个开发者都应该掌握的一项技能,就像每个程序员都应该掌握一门编程语言一样。

但是说归说闹归闹,还是有提要体系化的学习一下,毕竟 Agent 开发还是和传统开发有些不一样。

我们还需要提示词工程吗?

或者说,我们还需要学习怎么写一个好的提示词吗?

在 2023 年 ChatGPT 火起来之后,就出现了“提示词工程”这个概念,甚至当时还有调侃招提示词工程师的,我没求证过是否属实,但是现在看来提示词工程只是基础,写出一个好的提示词也只是开始,真正的 Agent 开发,其实还涉及了很多技术上的挑战。随着现在大模型能力越来越强,也有人说提示词工程不重要了,因为提示词的不足,模型能力能弥补,但是我觉得这个不对,因为我觉得最终的产物的质量,并不遵循 交付质量 = 模型能力 + 提示词工程,而应该是 交付质量 = 模型能力 ✕ 提示词工程,因为不管怎样,模型输出都是不确定的,至少好的提示词更能约束模型的输出,工程上最基本的要求,至少也有稳定的输出结构。

换个方向看,我们和 AI 对话时,很多时候是把 AI 当成一个人的,人在接收信息的时候,肯定也是更希望能看见一个结构化的,突出重点、次要信息的文档。

提示词工程常见玩法

“提示词工程”这个名字,听起来就很唬人,以往我理解的“工程”,意味着严谨、复杂,感觉“提示词工程”应该至少是一个很复杂的事。

其实确实不简单,哈哈。

提示词工程的关键,首先是结构化提示词,就像有代码洁癖的人写代码一样,都追求有清晰的结构,方便人更快速的理解,而结构化提示词则是方便 LLM 理解。然后就是思维的具象化,当我们做一件事,最后我们会知道结果是对是错,复盘之后还会知道对错在哪里,以后要如何改进,甚至可能还会产生一个 SOP(Standard Operating Procedure),这其实是我们的思考过程的外显,提示词其实也是做这件事,就是明确告诉 LLM 如何做,可能有哪些坑,哪些必须做,哪些不能做,以及参考示例(让我想起了产品常常说的“参考 xxx”这种一句话需求)。

提示词工程分了很多种模式,但都是结构化的提示词,加上不同思维的玩法,所以也不一定非要按照这些模型来。

RTF(Role-Task-Format)

RTF 是一种结构化的提示词模式,从名字上就能看出来,提示词主要有三部分:

  1. 角色,你是谁
  2. 任务,你要干什么
  3. 格式,你要按照什么格式输出

提示词示例:

# 角色
你是一个 Java 开发专家,擅长编写稳定的 Java 代码。

# 任务
根据描述,建立完整的 Java Bean 模型

# 要求
1. 有完整的属性列表
2. getter、setter 方法
3. 如果是请求、响应对象,不能使用基础类型,要使用封装类型,比如你必须使用 Integer 代替 int,使用 Long 代替 long
4. 如果是请求对象,最外层对象命名以 Req 结尾,如果是子对象,以 DTO 结尾,比如一个登录请求中有用户信息,那就有 LoginReq、UserDTO这种命名,其中 LoginReq 中有 UserDTO类型的属性
5. 如果是 boolean 或者 Boolean 类型,属性名称不能以 is 开头,比如这种属性命名是禁止的:isSuccess、isFailed

# 输出格式
当用户说:用户信息包含用户名
输出的文件名为 User.java,文件内容为:
public class User {
    private String username;
        
    public User setUsername(String username) {
        this.username = username;
        return this;
    }
    
    public String getUsername(String username) {
        return this.username;
    }
}

一个想法但不一定对,这里的角色的定义,其实按人的角度我是理解的,就像告诉我,我的工作岗位是什么,但是我觉得这就一个机器,给他一个角色定义又能怎样呢,能按照我给的任务输出结构不就行了嘛,哈哈,可能是因为我对注意力机制不够了解吧。

关于输出格式,在实际的生产实践中,很多时候是期望 LLM 能返回一个 json 的数据的,但是因为模型输出的随机性,返回的结果可能不是一个标准的 json 格式,所以对结果进行 json 解析时,可能会发现根本就不是一个有效 json,这是一个常见的问题,至少我最近调 Minimax 2.7 是会出现这种情况的。

应对返回的 json 无效的情况,我觉得有以下几个途径:

  1. 模型 max_token 数量限制不能太短,不然输出的 json 可能被截断,这个我确实遇见过,当时 max_token 随便写了个 1000,输出的 json 死活解析不了,排查了很久才发现可能是 max_token 太小了。
  2. 提示词优化,强化对 json 格式的描述,像 Spring AI 里面,是把输出对象的 json schema 作为提示词的一部分,这样模型输出的 json 就更符合预期了。
  3. 耍无赖,换个更强的模型,指令遵循会更强。
  4. 增加重试机制,模型输出无效时,增加重试,大多数时候第二次就是完整的 json 了。
  5. python 有个修复 json 的库 json_repair,但不一定能解决所有问题就是了,我也没过多了解过原理。

ICIO(Instruction-Context-Input-Output)

清晰分割的指令、上下文、输入、输出。

# Instructioin
生成有完整属性列表,getter、setter 方法的 java bean

# Context
你是一个资深的 Java 后端开发专家,当用户表达出某个业务模型的时候,你要能创建相应的 Java bean,生成相应的 Java 文件,并且每个属性都有合适的数据类型,有 getter、setter 方法

# Input
用户输入:现在一个订单的核心要素有订单号、下单日期、订单金额、订单状态

# Output
其中的 getter、setter方法直接使用 lombok 提供的@Data 注解来替代,以下是输出示例:
@Data
public class Order {
    private String orderNo;
    private Date submitTime;
    private BigDecimal amount;
    private OrderStatus orderStatus;
}

CRISPE

适合学术、科研、内容创作领域。

这让我想到了在 Telegram 上加过一个 AI 群,里面有 AI 的角色扮演。

CO-STAR

这个比较适合一些报告、课程之类有明确格式要求的内容生成。

TIDD-EC

适合法律咨询、技术支持这类有明确规范的场景。

BROKE

适用于一些需要持续改进的场景。

目前了解到的结构化提示词模式就这些,就是把结构化+思维玩出花了。

这么多的写法看起来其实挺烦的,但是会发现这其实就是不同场景下,作为人,我们会以什么样的方式去拆解问题,那提示词就会怎么写。所以,有人说 AI 时代定义问题的人更稀缺,这倒是对的。


分享这篇文章: