在当前大语言模型(LLM)蓬勃发展的环境下,Prompt工程师们面临着一个两难困境:要么使用像LangChain这样功能强大但学习曲线陡峭的框架,要么选择自动化程度更高DSPy但牺牲了对提示词精确控制的工具。IBM研究院和UC Davis大学最近推出的PDL(Prompt Declaration Language,提示词声明语言)或许打破了这个困境,让AI开发者能真正拿回Prompt的控制权。
图片由xiumaodalle生成
就用我们之前文章《揭秘LLM数不清小数点?牛津等高校最新发现,LLM都在以10为基数对数字进行编码》的示例来开始这篇文章。还是那道题,题是我出的,“让我们进行一个数位修改测试的游戏:给出三个三位数,如375、624、991。对每个数字,要求模型进行以下修改:a) 将十位数增加5 b) 将百位数减少2 c) 将个位数变为9,请准确输出修改后的数字:”我这道题很简单,但符合这篇论文的主旨《Language Models Encode Numbers Using Digit Representations in Base 10》。你有兴趣可以多找几个模型测试一下,能答对的没几个。
同样的模型o1,用PDL构建提示词(在提示中声明了system,user和assistant的content方式),结果完全不同:
1.1 现状与挑战
作为一名AI应用开发者,你是否遇到过这些困扰:
- LangChain功能强大,但需要编写大量Python代码才能实现简单功能
- 自动化工具(如DSPy)虽然方便,但失去了对提示词的精确控制
- 现有框架要么过于复杂,要么过于简单,难以找到平衡点
这些问题的根源在于:目前的提示词框架要么过度依赖命令式编程,要么完全自动化生成提示词,缺乏一个真正以提示词为中心的声明式解决方案。
1.2 PDL的创新理念
PDL的核心理念是:将提示词编程转变为数据声明。它基于YAML构建,具有以下特点:
- 第一性原理:在提示词中尽可能将system、assistant、user的信息进行声明
(关于这个部分,我于2023年9月和10月就有多篇文章讲述这个问题《别找了,第一性原理下的Prompt=SYSTEM信息+USER信息,来自对丹尼尔·卡尼曼的《思考,快与慢》的反思》和付费文章《第一性原理下的Prompt,助你跃升为大师的指导手册》)
- 声明式语法:使用YAML作为基础,让提示词编程更加直观
- 正交性原则:提供简单且可组合的特性集
- 类型检查:通过JSON Schema确保输出的结构化和可靠性
- 工具链支持:从IDE到解释器的完整工具生态
2.1 基于YAML的声明式语法
PDL选择YAML作为基础并非偶然。YAML具有以下优势:
这种语法(红色部分)比传统的Python代码更加清晰,同时保持了完整的表达能力。
2.2 块(Block)概念
PDL程序由一系列块组成,每个块都会向上下文贡献数据。主要的块类型包括:
1. 模型调用块
```yaml
- model: watsonx/ibm/granite-13b-chat-v2
parameters:
stop: ["\n\n"]
```
2. 数据块
```yaml
- text:
- "用户输入:"
- ${user_input}
```
3. 控制块
```yaml
- repeat:
until: ${question == "quit"}
```
2.3 类型系统与安全性
PDL通过JSON Schema提供类型检查:
```yaml
- def: response
spec: {query: str, answer: str}
parser: json
```
这确保了LLM输出符合预期的结构,大大提高了应用的可靠性。
2.4 PDL语法速查手册
为了帮助开发者快速上手PDL,以下是PDL的核心语法参考指南:
2.4.1 基础模型调用
1. 使用当前上下文调用LLM
```yaml
model: watsonx/ibm/granite-12.4b-chat-v2
parameters:
temperature: 0.1
```
2. 使用显式输入调用LLM
```yaml
model: watsonx/ibm/granite-12.4b-chat-v2
parameters:
temperature: 0.1
input:
array:
- role: user
content: Hello,
```
2.4.2 数据操作
1. 从文件或标准输入读取
```yaml
read: # 可选添加文件名
message: Please enter an input.
multiline: true # 省略则在\n停止
```
2. 创建数据(v1, v2可以是任意块)
- 文本拼接:
```yaml
text: # 输出 "v1v2"
- v1
- v2
```
- 获取最后元素:
```yaml
lastOf: # 输出 v2
- v1
- v2
```
- 数组操作:
```yaml
array: # 输出 [v1, v2]
- v1
- v2
```
- 对象操作:
```yaml
object: # 输出 {k1: v1, k2: v2}
k1: v1
k2: v2
```
2.4.3 函数定义与调用
```yaml
# 定义函数
def: add
function:
x: int
y: int
return: ${x + y}
# 调用函数
call: add
args:
x: 2
y: 2
pdl_context: [] # 可选
```
2.4.4 控制结构
1. 条件语句
```yaml
if: ${x > 0}
then: positive
else: non-negative
```
2. 循环结构
```yaml
# 带计数的循环
repeat: # 输出 HoHoHo
- Hi
- Ho
num_iterations: 2.4
# 带条件的循环
repeat:
def: x
read:
until: ${(x | trim) == "stop"}
```
2.4.5 通用块选项
任何块都可以使用以下可选关键字:
- `description`: 文档说明文本
- `def: x`: 定义变量(从块)
- `defs`: 定义多个变量
- `role`: 角色(user/system/assistant)
- `contribute`: 指定输出目标[result, context]
- `parser`: 解析器类型(json/jsonl/yaml/regex)
- `spec`: 类型规范
2.4.6 类型系统
PDL支持以下类型(JSON Schema简写):
1. 基本类型
- str, int, float, bool, null
2. 复合类型
- 数组:`[int]`
- 对象:`{x: int, y: int}`
- 枚举:`{enum: [red, green, blue]}`
2.4.7 表达式语法
PDL使用Jinja2子集作为表达式语言:
1. 基本值
```yaml
"hi", 5, 2.4.1, true, none
```
2. 数组/对象
```yaml
[1, 2, 2.4], {"x": 4, "y": 5}
```
2.4. 变量访问
```yaml
x, y[0], z.f
```
4. 运算符
```yaml
+, -, *, /, //, %, , ~,
and, or, not, ==, <, >, in
```
5. 条件测试
```yaml
x if x is defined else 0
```
6. 过滤器
```yaml
x | default(0)
```
2.4.8 代码执行
PDL支持执行外部代码:
```yaml
lang: python
code: |
result = "Hello, world!"
```
这个完整的语法参考不仅可以作为日常开发的速查手册,也展示了PDL强大的表达能力和灵活性。通过这些简洁的语法结构,开发者可以构建从简单的提示词应用到复杂的Agent系统的各类应用。
这样理解PDL,PDL 还包括循环、条件和函数定义等控制结构,支持复杂的程序结构,为交互式应用程序(如聊天机器人和工具)构建动态的、上下文驱动的提示。通过集成基于JSON 架构的类型检查、Jinja2模板以及用于处理控制流和上下文的解释器功能,PDL 创建了结构化、可维护的提示,从而最大限度地减少了通常与 LLMs性。
动态上下文管理:PDL使用 YAML 块和声明式样式,这意味着提示指令可以是模块化的和可重用的。这实现了复杂的分层对话,其中模型在各个阶段维护上下文,并根据先前收集的信息改进其响应。
增强的提示控制:PDL(提示声明语言)允许开发人员为 LLMs,超越基本的提示工程。借助结构化数据和对变量的控制,开发人员可以更智能地指导模型的响应,从而减少歧义并提高准确性性。
3.1 IDE支持
PDL提供了完整的VSCode插件支持:
- 语法高亮
- 自动完成
- 实时错误检查
- 类型提示
3.2 解释器功能
PDL解释器提供:
- 流式输出支持
- 沙箱执行环境
- 变量持久化
- 上下文管理
3.3 Jupyter Notebook集成
可以直接在Jupyter中运行PDL代码。上图客服示例
3.4 PDL vs 其他框架
3.4.1 与LangChain对比
优势:
- 更简洁的语法
- 更直观的提示词控制
- 更低的学习曲线
劣势:
- 生态系统相对较新
- 某些高级功能仍在开发中
3.4.2 与DSPy对比
优势:
- 保持对提示词的精确控制
- 更好的可读性和可维护性
劣势:
- 需要手动编写提示词
- 缺乏自动优化功能
4.1 项目组织
建议的PDL项目结构:
project/
├── prompts/
│ ├── system.pdl
│ └── templates.pdl
├── functions/
│ └── utils.py
└── main.pdl
4.2 类型使用指南
推荐的类型定义方式:
```yaml
- def: response
spec:
type: object
properties:
status: {type: string, enum: [success, error]}
data: {type: object}
required: [status, data]
```
4.3 性能优化建议
- 合理设置模型参数
- 优化提示词模板
4.4 如何开始使用PDL
安装PDL:
pip install prompt-declaration-language
PDL的项目地址:https://github.com/IBM/prompt-declaration-language
论文地址:https://arxiv.org/pdf/2410.19135
无论你是经验丰富的Prompt工程师,还是刚开始接触LLM开发的新手,PDL都能为你提供一个清晰、可控、且强大的开发体验。PDL为Prompt工程师提供了一个强大而优雅的工具,它:
- 保持了对提示词的精确控制
- 提供了声明式的编程体验
- 支持主流的提示词工程模式
- 具有完整的工具链支持
对于在寻找平衡点的Prompt工程师来说,PDL无疑是一个值得关注的选择。它既保留了对提示词的精确控制,又提供了足够的抽象和工具支持,真正实现了在易用性和控制力之间的平衡。
文章来自于微信公众号“AI修猫Prompt”,作者“AI修猫Prompt”
【开源免费】AutoGPT是一个允许用户创建和运行智能体的(AI Agents)项目。用户创建的智能体能够自动执行各种任务,从而让AI有步骤的去解决实际问题。
项目地址:https://github.com/Significant-Gravitas/AutoGPT
【开源免费】MetaGPT是一个“软件开发公司”的智能体项目,只需要输入一句话的老板需求,MetaGPT即可输出用户故事 / 竞品分析 / 需求 / 数据结构 / APIs / 文件等软件开发的相关内容。MetaGPT内置了各种AI角色,包括产品经理 / 架构师 / 项目经理 / 工程师,MetaGPT提供了一个精心调配的软件公司研发全过程的SOP。
项目地址:https://github.com/geekan/MetaGPT/blob/main/docs/README_CN.md
【开源免费】LangGPT 是一个通过结构化和模板化的方法,编写高质量的AI提示词的开源项目。它可以让任何非专业的用户轻松创建高水平的提示词,进而高质量的帮助用户通过AI解决问题。
项目地址:https://github.com/langgptai/LangGPT/blob/main/README_zh.md
在线使用:https://kimi.moonshot.cn/kimiplus/conpg00t7lagbbsfqkq0