Prompt 编写模式:如何将思维框架赋予机器,以设计模式的形式来思考 prom
上图为 Cohere AI 官网的示例图,对应的聊天记录如下:
English: Writing about language models is fun.
Roish: Writingro aboutro languagero modelsro isro funro.
English: The weather is lovely!
Roish:
符号化模式
符号化方法通常通过定义符号、符号之间的关系以及基于这些关系的规则来表示知识。
简单来说,我们可以创建一个符号来表示特写的规则,诸如于:
"""我们来玩一个名为 gkzw 的写作游戏,每当我说 gkzw,你开始写作,规则如下:
1. 字数不少于 200 字。2. 文中必须出现 "小明"。
明白了吗?"""
围绕这个模式,我们可以创建复制的规则。
反向 Prompt 模式
Negative prompt(负向提示)是一种在使用语言模型时,针对模型输出不希望的结果而设置的一种文本输入方式。通过使用负向提示,可以帮助模型避免输出不良、不准确或不恰当的文本。
具体来说,负向提示通常是以否定的形式呈现的,例如在文本生成任务中,使用"不要写..."、"不要提及..."、"不要使用..."等方式来限制模型生成不想要的文本。在情感分析任务中,使用"不是..."、"并不..."等方式来指示模型识别出一段文本的负面情感。在 QA(问答)任务中,使用"不是..."、"不包括..."等方式来指示模型回答问题时避免输出错误或不准确的答案。
Negative Prompt 在 Stable Diffusion 被广泛使用,相似的,在 ChatGPT 中,我们也会经常使用到。
诸如于:
我们能玩一个名为 kfc 的谜语创作游戏,当我说 "kfc",你写一个谜题,要求:
1. 不少于 200 字2. 谜题不能出现肯德基、星期四、KFC3. 正文可以夹杂小语种语言,如 """他说:Ciao"""4. 谜底必须是 ###原来今天是肯德基疯狂星期四!!###
格式类似于:
....
再生成模式
根据 AI 提供的信息,再让 AI 生成内容。
例子 1,当我们无法确定我们的 prompt 是否准确,便可以通过 AI 来帮我们丰富 prompt 。
如我在:基于编程、绘画、写作的 AI 探索与总结的例子一样phodal: 我想写一段话描述一张照片,帮我美化一下:一年轻女子穿着裙子,背对着镜头,在海边看着日落,太阳已经到地平线下面了,她的头发在风中飘动。
ChatGPT: 这张照片中的场景令人心醉,一位年轻女子穿着一条裙子,站在海边,背对着镜头,凝视着地平线下的夕阳。太阳已经沉入了海面,一片金黄色的光芒在海面上弥漫,照亮了整片海洋,仿佛这个时刻被定格在了时间的某个角落里。女子的头发随着微风轻轻飘动,轮廓被余晖映照得柔和而温暖。她的目光凝视着远方,仿佛在思考着生命的意义和无尽的未来。这张照片中蕴含着一种深刻的内涵,让人感受到时间和自然的力量,也让人思考着自己在这个宏大而美丽的世界中的角色和意义。
再去除掉不合适的词,进行润色,就可以再创作:
phodal:翻译成英语
然后再提炼直至扔至 Stable Diffusion 中:
而后,根据图片的结果,我们再反复修改。
控线模式
TODO:这里需要给出更精准的定义,如何让 ChatGPT 做到?
在没有推出 ControlNet,对于一个 Stable Diffusion 玩家,它需要反复地吟唱咒语,才能获取到满意的图案。
在有了 ControlNet 之后,我们可以创建一个 Openpose,或者是导入图片从图片生成 pose,相当于是给机器一个示例,而后生成的图片就会有令人满意的姿势。
在 GitHub Copilot,我们可以通过设置输入和输出,结合函数名三个要素,Copilot 就能生成大致准确的代码:
而在必要的情况下,添加一下注释就能更完整了:
fun listAllDirInDir(dir: String): List<File> { // ignore hidden files
}
生成的代码会更贴近我们的需求。
Language is Language对于 ChatGPT 来说,语言就是语言,他不区分自然语言和编程语言,甚至有可能编程语言对它更友好。所以我们可以直接通过编程语言与之交流:
我有下列遗留代码,我想在接口的函数名、参数名不变的情况下(可以新参数,旧的参数不能变)加入新功能:
module.exports = async function loadYamlFile(filepath, workdir = path.dirname(filepath)) { const content = await fs.readFile(filepath, 'utf8'); // 读取文件内容 // TODO: 将 content 看做ejs模板的字符串,进行渲染,如果传入了渲染ejs时的context值不为undefined,就进行渲染,否则不进行渲染。
// TODO:将渲染后的结果传给yaml.load const data = yaml.load(content); // 解析YAML为JSON对象
// 遍历JSON对象,查找$ref属性 const processRef = async (obj) => { if (typeof obj === 'object' && obj !== null) { // 如果是对象 if ('$ref' in obj) { // 如果包含$ref属性 const refPath = path.join(workdir, obj.$ref.split('#')[0]); // 获取引用文件路径 const pointer = obj.$ref.split('#')[1]; // 获取JSON指针
// TODO: 递归调用的时候,取出context中以obj.$ref的属性值作为属性名的值作为新的context向下传递 const refData = await loadYamlFile(refPath, path.dirname(refPath)); // 递归读取引用文件 const value = getValueByPointer(refData, pointer); // 修复了 # 号问题 return value; } else { // 如果不包含$ref属性,递归处理子属性 for (const prop in obj) { obj[prop] = await processRef(obj[prop]); } } } return obj; };
上述描述会比纯自然语言更容易描述我们的需求,适合于更精细的指导。同时,不一定是编程语言,结构化的声明式 DSL 它也可以很好的解析,如:
把我给定的输入输出,按照下面的格式写成一个测试用例的描述:
{ desc: 'Test with $p_ref returning array', input: { filepath: 'http://www.myzaker.com/article/641dde658e9f09332a19a7d3/test18.yml', workdir: 'http://www.myzaker.com/article/641dde658e9f09332a19a7d3/test/v2', }, expected: { "name": "Alice", "age": 20 } }
结果:
{ desc: 'Test with $p_ref returning array', input: { filepath: 'http://www.myzaker.com/article/641dde658e9f09332a19a7d3/test19.yml', workdir: 'http://www.myzaker.com/article/641dde658e9f09332a19a7d3/test/v2', }, expected: [ { "name": "Bob" }, { "name": "Alice" }, { "name": "Bob" }, { "name": "Alice" } ]}该测试用例输入了一个 YAML 文件 test19.yml,该文件中包含了一个 $flaten 属性,其值为两个 $p_ref 对象组成的数组,引用了一个返回数组的 YAML 文件 test19_ref.yml。
执行该测试用例后,期望得到的输出是一个数组,其中包含了两个 $p_ref 引用结果的 flatten 后的结果。
需要注意的是,由于该测试用例涉及到文件读取和模板渲染等操作,需要在测试前确保相关文件和依赖库已经正确安装并配置好。
通过使用DSL,还可以缩短输入和输出的token数,从而放大 ChatGPT 的能力。
概念抽象
对于 ChatGPT 尚不存在的概念,可以通过 Google 相关的内容之后,由 ChatGPT 进行总结。
根据下面的文本重新解释一下 ControlNet:
- 官网介绍:ControlNet is a neural network structure to control diffusion models by adding extra conditions.
- 模式:根据给的底图,生成一个类似建模效果(法线贴图)的中间图,再生成图片
- 场景:用来实现骨骼绑定、精准控线、线稿上色、依据深度图结构透视精准重绘等。
结果:
根据给出的文本,ControlNet是一种神经网络结构,旨在通过添加额外条件来控制扩散模型。在特定场景下,ControlNet被用于生成类似建模效果(法线贴图)的中间图和相关的图像。这种技术可以被应用于多个领域,如骨骼绑定、精准控线、线稿上色、深度图结构透视精准重绘等。
具体来说,ControlNet技术可以被用来控制模型的扩散过程,从而提取特定的信息并生成新的图像。在骨骼绑定、线稿上色等场景中,ControlNet技术可以被用来增强图像,使其更加真实和生动。在依据深度图结构透视精准重绘的场景中,ControlNet技术可以被用来根据图像的深度信息,生成精确的重绘图像,从而提高图像的真实感和逼真度。
缩短:能用一句话解释一下 ControlNet 吗
ControlNet 是一种神经网络结构,通过添加额外的条件来控制扩散模型,从而实现图像增强、重构和生成等功能。
概念对齐
第一步,定义
phodal:自举是指就编译器可以自行编译自己的编译器。实现方法就是这个编译器的作者用这个语言的一些特性来编写编译器并在该编译器中支持这些自己使用到的特性。
第二步,试探
phodal:将自举应用在游戏领域,应该是怎样的?
第三步,确认理解:
那么,抽象一下我们新定义的自举?
最后一问:
PS:mmp,他一定是故意的。
类比是指将一个事物或概念与另一个事物或概念进行比较,找出它们之间的相似之处,以此来推理或说明某个问题或情况。
CoT
CoT 是 "Chain of Thought" 的缩写,是一种针对自然语言处理 (NLP) 模型的提示方法,旨在提高模型的推理能力。通过将多步骤问题分解为中间推理步骤,CoT 提示使得模型可以更有效地处理需要多步骤推理的任务,如数学问题和常识推理。与传统提示方法不同,CoT 提示引导模型生成中间推理步骤,从而模拟人类推理的直觉过程。
TODO:(rename to Manual-Cot/Auto-CoT )
模板方法
模板方法模式是一种行为型模式,它定义了一个操作中的算法骨架,将某些步骤延迟到子类中实现,从而使得子类可以在不改变算法结构的情况下重新定义算法中的某些步骤。
在接下来的例子中,我们会创建一个 muji 游戏中。在游戏的实现可以分为多个步骤,例如初始化游戏、生成随机数、获取用户输入、计算得分等等,而这些步骤可以通过模板方法模式来进行实现。
我们来玩一个编程游戏名为 wula,包含五个步骤:
第一步. 问题分析:每一轮游戏,你将看到一个以 "wula:" 开头的问题,你需要分析这个问题并简单介绍一下通常解决这个问题的方法。
第二步. 代码编写:你需要用 JavaScript 编写解决这个问题的代码,并输出对应的代码,并介绍一下你的代码(不少于 200 字)。
第三步. 代码执行:你需要作为 JavaScript Console 执行第二步写的代码,如果没有给出测试数据,你需要自己随机生成测试数据,并将这些数据输入到代码中进行计算。
第四步. 错误处理:如果你的代码存在错误或无法正常执行,你需要输出错误,并回到第二步重新开始游戏,直到你的代码能够正常工作。
第五步. 总结:你需要用不少于 100 字左右总结一下这个问题,以及你的解决方案,让其他人可以简单了解这个问题及其解决方法。
示例如下:
"""wula: 头共10,足共28,鸡兔各几只?
简介:这是一个鸡兔同笼问题,{},
## 鸡兔同笼
// 计算鸡兔数量的函数function calcAnimals(heads, legs) { const rabbitCount = (legs - 2 * heads) / 2; const chickenCount = heads - rabbitCount; return {"chicken": chickenCount, "rabbit": rabbitCount};}
// 计算鸡兔数量const result = calcAnimals(10, 28);
// 输出结果console.log(result);
代码的输出结果是:{}
## 总结
"""
明白这个游戏怎么玩了吗?
在这个游戏里,我们结合了几种不同的模式:
Instruction:让 ChatGPT 创建了一个名为 wula 的游戏,并定义了游戏的步骤。
Specific:让 ChatGPT 用 JavaScript 编写一个程序。
Proxy:让 ChatGPT 作为 JavaScript Console 执行程序,并返回结果。
Specific:让 ChatGPT 做总结。
Demonstration:提供了一个示例,让 ChatGPT 理解游戏的步骤。
自举模式
自举(Boostrapping)的核心思想是利用一组基础工具和材料来构建和生成一个新的工具或系统,从而逐步替代掉原有的基础工具和材料。在这个过程中,新的工具或系统会逐渐变得更为高效和强大,从而实现对原有基础工具和材料的完全替代。
如下图所示:
TODO:重新解释,上图出自:《Bootstrapping in Compiler Design
先看例子 1:文章
例子 2:Wula 2.0
> wula:创作一个新游戏名为 muji,并解释一下这个游戏:"""类似于 wula,可以做简单的图形计算,如体积、面积等。这个游戏还能把解决过程解释清楚,拥有有可运行的 Python 代码,最后的输出结果是一篇文章。"""
拆解模式
对于复杂问题,ChaGPT 无法一次性输出全部内容,需要进行拆解。
已知问题:ChatGPT 当前版本会丢失上下文。
我们来定义一下 DDD 游戏的步骤,一共有 6 个步骤,步骤如下:
"""
第一步. 拆解场景。分析特定领域的所有商业活动,并将其拆解出每个场景。
第二步. 场景过程分析。选定一个场景,并使用 "{名词}已{动词}" 的形式描述过程中所有发生的事件,其中的名词是过程中的实体,其中的动词是实体相关的行为。
第三步. 针对场景建模。基于统一语言和拆解出的场景进行建模,以实现 DDD 设计与代码实现的双向绑定。
第四步. 持续建模。回到第一步,选择未完成的场景。你要重复第一到第四步,直到所有的场景完成。
第五步. 围绕模型生成子域。对模型进行分类,以划定不同的子域,需要列出所有的模型包含英语翻译。
第六步. API 生成。对于每一个子域,生成其对应的 RESTful API,并以表格的形式展现这些 API。
"""
需要注意的是,当我说 """ddd 第 {} 步: {}""" 则表示进行第几步的分析,如 """ddd 第一步: 博客系统""" 表示只对博客系统进行 DDD 第一步分析。我发的是 """ddd: {}""",则表示按 6 个步骤分析:
明白这个游戏怎么玩了吗?
完整过程见:DDD Sample
pipeline模式(TODO)
后处理 pipe,示例:当你希望给我图片的时候,用 mermaid 表达
图形化实践
phodal: 能用 uml 表示一下上文中的 """ArchGuard Pipeline 的工作流程""" 吗?
当然可以。下面是 ArchGuard Pipeline 的工作流程的 UML 类图表示:
+-----------------+ +-----------------+| ArchGuardConfig | | ArchGuardRunner |+-----------------+ +-----------------+| - configData | | - runnerType |+-----------------+ | - runnerImage | | - runnerCommands | +-----------------+ ^ | |+-----------------+ +-----------------+| ArchGuard | | RunnerPool |+-----------------+ +-----------------+| - runnerRegistry | | - runners |+-----------------+ +-----------------+| # downloadRunner| | # getRunner |+-----------------+ +-----------------+
ArchGuardConfig 类包含了 ArchGuard Pipeline 的配置信息,ArchGuardRunner 类则表示一个具体的 Runner,即一个执行 ArchGuard Scanner 或者其他工具的实例。RunnerPool 则是 Runner 的管理池,用于动态加载不同的 Runner。ArchGuard 则是整个 ArchGuard Pipeline 的控制类,用于根据 ArchGuardConfig 中的配置信息,加载对应的 Runner,执行任务。
phodal: 能用 mermaid 表示一下上文中的 """ArchGuard Pipeline 的工作流程""" 吗?
当然可以!以下是使用 Mermaid 表示的 ArchGuard Pipeline 的工作流程:
注:这与我之前用 UML 表示的工作流程是等价的。
人类如何思考问题?
人类相对于其他动物更擅长于类比、概念抽象、符号化等高级认知活动,这些认知活动可以帮助人类在面对新问题时,从已有的知识和经验中找到相似的部分,快速理解和解决新问题。
而对于机器来说,机器学习算法通过大量的数据和计算,学习到数据中的规律和模式,并将这些规律和模式应用到新的数据中,从而实现预测和决策等功能。例如,机器学习算法可以通过大量的图像数据学习到图像的特征,并在新的图像中识别出相应的物体;也可以通过大量的自然语言数据学习到语言的规律,从而生成自然语言文本。
参考资源:
本文相关的模式图片参考来源主要是:Prompt Engineering