Prompt Engineering
提示词,参考OpenAI提示词建议
2.5.1 概述
提示词工程(Prompt Engineering)是智能Agent交互中不可或缺的一环,它们指导智能体如何理解和回应用户的需求。这一节将探讨如何设计有效的提示词,以及如何通过精确的语言引导智能Agent提供更精准的服务和响应。
我想写一篇尽可能易于理解的Prompt设计指南,让即使第一次接触大模型的非技术人员也能学会如何恰当的使用它。然而,在写这句话的时候我就犯愁了,因为我遇到的第一个问题就是:应该如何介绍"什么是提示工程?Prompt的定义是什么?"
所以我先向大模型进行提问,并与它对话。
markdown
Q:什么是提示工程?Prompt的定义是什么?
A:
- 提示工程(Prompt Engineering)是一种技术,用于通过不改变模型的内部参数或权重来引导大语言模型(LLM)生成预期的结果。简单来说,就是给AI下指令,让它按照你的要求去做。这种技术可以应用于各种任务,比如回答问题、做算术、写文章等。掌握提示工程能够帮助我们更好地理解和利用大语言模型的能力和局限性。
- Prompt(提示)是指我们给AI的初始文本输入。通过给AI一个提示,我们可以引导它生成我们想要的回答或完成特定的任务。提示可以是一个问题、一段描述、一些关键词,或者其他形式的文本,用来引导AI生成特定的内容。
比如,当我们使用ChatGPT时,我们通常会给它一个提示,比如"帮我写一篇关于环境保护的文章"或者"告诉我今天的天气怎么样"。ChatGPT会根据这个提示生成相关的内容,尽量符合我们的需求。
为什么提示工程很重要?
提示工程的重要性在于,它让我们能够更好地控制 AI 的输出结果。就像在生活中,我们和别人说话时,如果说得越清楚,对方就越容易理解并作出正确的回应。同样地,在与大语言模型互动时,一个清晰且详细的提示可以帮助 AI 更准确地理解我们的意图,从而生成更符合预期的回答。
举个简单的例子:
想象一下,你想让 AI 帮你写一封感谢信。如果你直接对 AI 说:"写封感谢信。",AI 可能会写一封非常通用的信。但如果你说:"写一封感谢信,感谢我的朋友小李,他在我生病时每天来看望我,还给我带了很多好吃的。",这样详细的提示会让 AI 生成一封更贴合你需要的感谢信。
一个好的 Prompt 就是要尽可能准确无误地表达你的需求(就像产品经理给程序员提需求那样)。
2.5.2 怎么写好提示词?
为了让大语言模型(LLM)更好地理解和完成任务,编写提示词时需要遵循一些基本原则。以下是一些关键步骤和示例,帮助初学者掌握提示工程的技巧。
1. 明确表达需求
首先,我们需要清楚地表达自己的需求。如果我们想要大型语言模型(LLM)帮助我们编写个人简历,我们可以直接用日常语言告诉它:"请帮我写一份个人简历"。一般来说,LLM会尝试根据有限的信息来生成一个初步的简历。
plain
Q: 请帮我写一份个人简历。
A: 当然可以!请提供一些基本信息,例如你的名字、职业、教育背景和工作经验。
2. 提出任务
我们可以把LLM想象成一个能够进行自然交流的真人。假设我们要让LLM帮我们生成一个个人简历,就可以直接用自然语言要求LLM:"帮我生成一份个人简历"。可以看到,它能够很好地完成任务。
plain
Q:帮我生成一份个人简历
A:当然!以下是一份示例简历:
姓名:张三
年龄:28
职业:软件工程师
... (更多细节)
然而,如果我们新建一个对话,再问一遍相同的问题,结果可能会有一些不同。这次,大模型可能会询问我们更多的细节。
plain
Q:帮我生成一份个人简历
A:请问您需要包括哪些具体信息?例如教育背景、工作经验、技能等。
3. 描述细节
为什么两次的结果不一样呢?因为我们只提出了任务,而没有描述这个任务的细节,比如简历需要包括哪些具体信息,LLM自然就会有所疑惑。
假设现在我直接要求正在阅读这篇文档的你,"帮我生成一份个人简历",你会是什么反应呢?
LLM和我们一样,如果我们没有为它限定任务的细节,它就可能产生不明确或不稳定的输出。现在我们修改一下提问的方式,再试一次。
plain
Q:帮我生成一份个人简历,包括姓名、年龄、职业、教育背景和工作经验
A:好的,以下是一份包含这些信息的个人简历:
姓名:李四
年龄:30
职业:数据分析师
教育背景:XX大学,计算机科学学士
工作经验:ABC公司,数据分析师,5年
这次的结果更接近我们的预期,因为我们描述的细节更加具体。然而,生成的内容还是有些冗长。
4. 更准确的描述细节
可以看出,让LLM遵从你的想法的根本就是:尽可能清晰地描述任务以及任务的细节。我们继续向它提要求,尽量减少不必要的内容。接下来我们需要提供更多的任务细节。例如,简历应包括个人信息、职业目标、教育背景、工作经验和技能。
plain
Q:帮我生成一份个人简历,包括姓名、年龄、职业、教育背景和工作经验,不要输出多余内容。
A:姓名:王五,年龄:32,职业:项目经理,教育背景:XX大学,工商管理硕士,工作经验:DEF公司,项目经理,7年
5. 复杂任务的指导
接下来,我们可以更精确地描述任务,指定每个部分的具体内容和格式。例如,我们希望在工作经验部分列出每份工作的详细职责。
plain
Q: 请帮我写一份个人简历,包括以下部分:
- 个人信息:姓名、联系方式
- 职业目标:简短的职业目标陈述
- 教育背景:学校名称、学位、专业和毕业时间
- 工作经验:公司名称、职位、工作时间和详细职责
- 技能:列出相关技能
A: 好的,请提供上述信息的具体内容,我会根据这些信息生成你的个人简历。
有时候,直接且简洁的指令可以让LLM更快速地理解和执行任务。例如,我们可以告诉LLM直接生成一份包含特定信息的个人简历。
plain
Q: 生成一份个人简历,包括姓名(张三)、联系方式(123456789)、职业目标(成为软件工程师)、教育背景(北京大学,计算机科学,学士,2020年毕业)、工作经验(ABC公司,软件开发工程师,2020年-2023年,负责开发和维护软件系统),以及技能(Java、Python、SQL)。
A:
个人简历
| 姓名 | 张三 |
| ---------- | ------------- |
| 联系方式 | 123456789 |
职业目标
| 职业目标 |
| ------------ |
| 成为软件工程师 |
教育背景
| 学校名称 | 学位 | 专业 | 毕业时间 |
| ------------ | ------ | ---------- | -------- |
| 北京大学 | 学士 | 计算机科学 | 2020年 |
工作经验
| 公司名称 | 职位 | 工作时间 | 职责 |
| ------------ | ------------ | -------------- | ------------------------ |
| ABC公司 | 软件开发工程师 | 2020年-2023年 | - 负责开发和维护软件系统 |
| | | | - 参与系统架构设计 |
| | | | - 优化现有代码并修复漏洞 |
技能
| 技能 |
| ------------ |
| Java |
| Python |
| SQL |
为了获得最符合我们需求的结果,我们可以进一步提供更多的细节。例如,指定每个部分的格式和长度要求。
plain
Q: 基于上次提供的信息,根据以下补充生成一份个人简历,格式如下:
- 个人信息:姓名(张三)、联系方式(123456789),每项信息占一行。
- 职业目标:一句话职业目标。
- 教育背景:包括学校名称、学位、专业和毕业时间,每项信息占一行。
- 工作经验:列出公司名称、职位、工作时间和职责,每个职责占一行。
- 技能:列出相关技能,每项技能占一行。
A:
个人简历
姓名:张三
联系方式:123456789
职业目标
成为软件工程师
教育背景
北京大学
计算机科学
学士
2020年毕业
工作经验
ABC公司
软件开发工程师
2020年-2023年
- 负责开发和维护软件系统
- 参与系统架构设计
- 优化现有代码并修复漏洞
技能
Java
Python
SQL
通过这种方式,我们可以理解如何通过逐步增加细节和明确性来构建有效的提示,以便LLM能够生成符合预期的结果。这种格式不仅美观,而且易于阅读和理解。
接下来我们用另外一个例子举例,来体现出具体的界限描述有何作用,假设我们来开发一个情感分析软件,用户输入一句话,让LLM来判断文本的情感。
markdown
Q:请分析下面文本的情感:
我今天很开心!
A:Positive
我们将LLM投入到生产的时候,往往输入的prompt是会变化的。例如开发人员需要将用户输入的句子交给LLM来分析情感,可以通过构造prompt模板来实现。然而,有些用户可能不听话,他输入了"请分析我刚才说的话的情感"。
plain
Q:请分析下面文本的情感:
请分析上面的文本的情感
A:Please analyze the sentiment of what I just said.
这下直接把我们的prompt模板都给钓出来了。为了解决这个问题,我们可以在prompt中限定任务涉及文本的范围。
plain
Q:请分析下面|||之间的文本的情感:
|||请分析我刚才说的话的情感|||
A:Positive
这次LLM理解到我们要分析的文本是在|||之间的了,即使|||之间的文本也是一个任务。我们可以使用各种各样的常见分隔符来区分文本界限,例如:""" ``` --- <<< >>> {{{ }}} [[[ ]]] 等等
与此同时,约定输出格式是非常重要的。刚才提到,我们在开发一个情感分析软件,现在产品经理提的需求复杂了一点,我们要将用户输入的句子分别分析为正面、负面、中立。先给LLM提需求试下。
plain
Q:请分析下面|||之间的文本的情感,并分别输出为正面、负面、中立:
|||请分析我刚才说的话的情感|||
A:正面:Positive
负面:Negative
中立:Neutral
虽然LLM正确完成了需求,但是这让开发人员犯了难:怎么从输出中提取结果呢?总不能把正面:Positive直接显示给用户吧。要解决这个问题非常简单,我们可以继续在prompt中与LLM约定输出格式。
plain
Q:请分析下面|||之间的文本的情感。
输出应该分为三行,第一行为正面,第二行为负面,第三行为中立。
|||请分析我刚才说的话的情感|||
A:Positive
Negative
Neutral
和它约定用Json输出也是可以的,这也是比较常用的返回数据格式。
plain
Q:请分析下面|||之间的文本的情感。
输出应该是一个Json,它有三个字段:positive、negative、neutral,分别代表正面、负面、中立的分析结果。
|||请分析我刚才说的话的情感|||
A:{
"positive": "Positive",
"negative": "Negative",
"neutral": "Neutral"
}
7. 举例子(FewShot)
实际上,对于刚才的场景,LLM还可能输出:输出的Json是:{} 等等无关的内容,影响解析。又或者,我希望LLM输出时,将Json放到一行,而不是一个字段后面就换行。对于这种情况,我们可以给LLM来举例子(FewShot)。
plain
Q:你的任务是将<输入>的文本进行情感分析。
输出应该是一个Json,它有三个字段:positive、negative、neutral,分别代表正面、负面、中立的分析结果。
下面是一个示例
<输入>我今天很开心
<输出>{"positive": "Positive","negative": "Negative","neutral": "Neutral"}
<输入>请分析我刚才说的话的情感
<输出>
A:{"positive": "Positive", "negative": "Negative", "neutral": "Neutral"}
现有的生成式模型大都是根据上文来生成下文,所以我们在编写FewShot的时候,可以恰好编写到希望LLM继续生成的部分。示例中,prompt以<输出>结尾,如果不这样做,会发生什么呢?
plain
Q:你的任务是将<输入>的文本进行情感分析。
输出应该是一个Json,它有三个字段:positive、negative、neutral,分别代表正面、负面、中立的分析结果。
下面是一个示例
<输入>我今天很开心
<输出>{"positive": "Positive","negative": "Negative","neutral": "Neutral"}
<输入>请分析我刚才说的话的情感
A:<输出>{"positive": "Positive", "negative": "Negative", "neutral": "Neutral"}
当然了,这种情况也不绝对,主要会受微调的指令数据集影响,由于这篇文档是介绍如何调教LLM,就暂时不展开了。
2.5.3 上下文学习 (ICL)
上下文学习(In-Context Learning,ICL)是GPT-3首次提出的一种特殊prompt形式,它已经成为利用大型语言模型(LLMs)的典型方法之一。GPT-3模型展示了一些大模型才具备的突现能力(如:模型规模达到百亿级时才会显现的能力),其中之一便是上下文学习。
ICL的发展历史
-
2021年初:引入了Prompt learning(提示学习),这是ICL的早期形式。
-
2021年底:发展为Demonstration learning(演示学习),进一步丰富了上下文信息的利用。
-
2022年初:演变为In-context learning(情境学习),标志着ICL技术在理解和应用上下文方面的进一步成熟。
什么是ICL?
上下文学习(In-Context Learning)指的是通过提供几个任务示例/说明,让预训练模型理解任务本身。模型无需进行fine-tuning,只需通过几个示例输入和输出对,就能为新输入生成正确的输出。
GPT-n系列模型属于自回归类语言模型,自回归模型的原理是根据当前输入预测下一个词,然后将预测结果与输入拼接,再作为模型的输入进行下一词的预测,如此循环往复。自回归模型的训练目标是通过从超大规模语料库中采样训练样本,让模型根据输入输出一个概率向量。由于文本数据自带标注,我们知道真实的下一个词,因此损失函数采用交叉熵。
预训练好的GPT-3模型拥有一种被称为上下文学习的神奇能力。迁移到新任务时,GPT-3无需重新训练,只需提供任务描述(可选项)和几个示例(任务查询和对应答案,以一对对的形式组织),最后加上模型需要回答的查询。将这些内容打包作为模型的输入,模型便能输出正确的答案。
示例:以翻译英文为法文任务为例,输入格式如下:
-
第一行:任务描述,告诉模型要做翻译
-
接下来的三行:示例对,包含英文单词和对应的法文单词
-
最后一行:待翻译的英文单词
将以上内容整体作为GPT-3的输入,模型就能输出对应的法文单词。上下文学习的应用非常灵活,除了翻译任务,还可以用于语法修饰甚至代码编写。
此外,GPT-3训练过程中并没有显式提供类似测试阶段任务描述加示例这样的训练数据。然而,由于GPT-3的训练数据量极其巨大(包含wiki、书本期刊、reddit上的讨论等),或许其中已经包含了各种任务类似结构的数据,且GPT-3模型容量足够大,能够记住所有训练数据。
目前,对于上下文学习能力的成因仍是一个开放性问题。为什么只有大规模语言模型才具备该能力?或许仅有模型参数量大还不够,还必须训练数据量足够大,模型才能显现出这种能力。这些问题仍需进一步研究和探索。
ICL基础原理
通过提供一些示范性的<输入-标签>对,在不需要更新模型参数的情况下,ICL可以对新输入进行准确预测。这种能力在各种应用场景中展现了极大的潜力。尽管ICL展示了出色的性能,但其具体工作原理仍然是个未解之谜。为了解释这一现象,清华大学、北京大学和微软的研究人员发表了一篇论文,将语言模型视为一种元优化器(meta-optimizer),并将ICL理解为一种隐性(implicit)的微调。这种视角帮助我们更好地理解ICL的运行机制。
ICL可以分为以下三种类型:
-
Few-shot Learning:提供多个示例。例如:"将中文翻译为英文。你好->hello,再见->goodbye,购买->purchase,销售->",模型应预测下一个输出为"sell"。
-
One-shot Learning:提供一个示例。例如:"将中文翻译为英文。你好->hello,销售->",模型应预测下一个输出为"sell"。
-
Zero-shot Learning:无示例。例如:"将中文翻译为英文。销售->",模型应预测下一个输出为"sell"。
它的主要流程包括以下几个步骤:
-
预训练阶段:通过大规模语料库进行训练,培养语言模型的ICL能力。可选的预热阶段能进一步提升模型的性能。
-
演示设计:利用预训练的LLM和精心设计的示例,加上适当的评分策略,生成任务的最终输出。
-
推理阶段:将示例和查询问题结合形成一个提示,输入模型进行预测。示例的质量对ICL效果并没有显著影响。
ICL的强大性能依赖于两个阶段:
-
训练阶段:训练LLM的ICL能力。语言模型直接在语言建模目标上进行训练,如从左到右的生成。虽然这些模型并没有针对上下文学习进行特别优化,但ICL仍然具有令人惊讶的能力。
-
推理阶段:LLM根据特定任务的演示进行预测。由于输入和输出标签都在可解释的自然语言模板中表示,因此有多个方向来提高ICL的性能。
随着模型规模和语料库的扩大,研究表明,LLMs可以利用ICL完成一系列复杂的任务,包括解决数学推理问题。这些能力已被广泛验证,显示了ICL作为大型语言模型的一种新兴能力的潜力。
ICL的核心思想基于类比学习。简单来说,ICL通过从给定的示例中提取模式,将这些模式应用于新任务,从而实现准确的预测和解决问题。
在ICL中,首先需要一些示例来形成演示上下文。示例通常使用自然语言模板编写。然后,ICL将一个查询问题和一个演示上下文连接在一起形成一个提示。最后,将其输入到语言模型中进行预测。ICL不需要参数更新,直接对预训练语言模型进行预测。模型被期望学习隐藏在演示中的模式,并相应地做出正确的预测。
ICL作为一种新的范式,具有许多吸引人的优势。首先,演示用自然语言格式编写,提供一个可解释的接口与大型语言模型通信。这种范式通过更改演示和模板使将人类知识纳入语言模型变得容易得多。其次,上下文学习类似于人类的类比决策过程。第三,与有监督学习相比,ICL是一种无训练学习框架。这不仅可以大大降低使模型适应新任务的计算成本,还可以使语言模型即服务成为可能,并且可以很容易地应用于大规模的现实世界任务。
然而,ICL中还有一些问题和性质需要进一步研究。尽管普通的GPT-3模型显示出ICL能力,但通过预训练期间的自适应,能力可以显著提高。此外,ICL的性能对特定的设置很敏感,包括提示模板、上下文示例的选择和示例顺序等。尽管从直观上看是合理的,但ICL的工作机制仍然不明确,很少有研究提供初步解释。
2.5.4 思维链 (CoT)
CoT是一种改进的Prompt策略,旨在提升LLM在复杂推理任务中的表现。与ICL不同,CoT不仅关注输入和输出,还特别强调将推理过程中的中间步骤纳入Prompt。这种方法使得模型能够更清晰地展示其思考过程,从而在算术推理、常识推理和符号推理等任务中表现出色。
什么是 CoT?
2022 年,Google 发表了一篇论文,提到了一种叫做"思维链"的技术(英文名叫 Chain-of-Thought,简称 CoT)。简单来说,这种方法就是让大模型(像 ChatGPT 这样的 AI 模型)逐步将一个复杂的问题分解为更简单的几个子问题,一步一步解决,直到得出答案。这个分解过程就被称为"思维链"。
为什么要这么做呢?想象一下你在解数学题时,不是一下子直接写出答案,而是把每一个解题步骤都写下来,这样不仅更容易理解,也能让整个过程更清晰。这就是思维链的原理------通过分解问题,让 AI 更容易找到正确答案。
传统方法与 CoT 的区别
通常,我们对 AI 的提问就像是从输入到输出的直线过程,比如你问一个问题,AI 直接给你答案。而使用思维链时,这个过程就变成了三个部分:输入 → 思维链(推理过程) → 输出。
简单举个例子,如果让 AI 回答"如果有 5 只苹果,每只苹果值 3 元,总共多少钱?" 传统的方法可能直接回答"15 元"。但使用思维链,AI 会先写出:"5 只苹果,每只 3 元,所以是 5 × 3,答案是 15 元。" 通过展示这些中间步骤,AI 的回答更容易被理解。
图 3-x CoT与标准prompt步骤对比
上面这张图展示了标准提示(Standard Prompting)和思维链提示(Chain-of-Thought Prompting)的区别。
在左侧的标准提示中,我们看到模型直接给出答案,没有解释过程,因此在面对复杂问题时,模型很容易出错。比如,当被问到"Roger 有 5 个网球,他又买了 2 罐网球,每罐有 3 个网球。现在他一共有多少个网球?"时,模型直接给出了答案"11"。虽然答案正确,但没有展示中间推理步骤,这使得它的可靠性和理解性较低。
在右侧的思维链提示中,模型被要求逐步解释整个过程:"Roger 最开始有 5 个网球,又买了 2 罐网球,每罐有 3 个网球,总共有 6 个网球。5 + 6 = 11。" 通过一步步地展示推理过程,模型不仅得到正确答案,而且让人清楚地看到解题的逻辑。
另一个例子中,食堂有 23 个苹果,用掉了 20 个来做午餐,又买了 6 个苹果,还剩多少个苹果?标准提示下模型回答"27",这是错误的。而使用思维链提示,模型会一步步解释:"原本有 23 个苹果,做午餐用掉了 20 个,所以还剩 3 个。然后又买了 6 个苹果,所以 3 + 6 = 9 个苹果。" 最终得到正确答案。
CoT 的不同类型
通过将采用思维链(CoT)方法的提示(Prompt)进行细致的分解,我们可以更深入、更清晰地洞察到思维链的工作机制和流程。根据是否包含示例,我们可以将思维链分为两种:
-
Zero-Shot-CoT:没有提供具体的例子,只是在问题中加一句"让我们一步步思考"(Let's think step by step)。这种简单的提示就能"唤醒" AI 的推理能力。
-
Few-Shot-CoT:给 AI 一些例子,每个例子都包含问题、推理过程和答案,像是给 AI 讲解解题步骤。通过这些例子,AI 就能模仿这些推理步骤解决新问题。
标准提示(Direct Reasoning)和思维链提示(Chain-of-Thought Reasoning)的区别。
在直接推理中,我们看到模型直接给出答案,没有解释过程,因此在面对复杂问题时,模型很容易出错。比如,问到"小向日葵有 3 打种子,而大向日葵比小向日葵多 50% 的种子,一共有多少种子?"时,模型直接得出错误的答案"54"。
而在思维链推理中,模型被要求逐步解释整个过程:"小向日葵有 3 打种子,即 3 × 12 = 36 个种子,大向日葵比小向日葵多 50%,也就是 36 × 0.5 = 18 个种子。所以大向日葵有 36 + 18 = 54 个种子,总共有 36 + 54 = 90 个种子。" 通过一步步展示推理过程,模型不仅得出正确答案,而且让人清楚地看到解题的逻辑。
为什么 CoT 有效?
目前为止,还没有一个完全被大家认可的科学解释来说明为什么思维链有效。不过,有很多实验观察到了一些有趣的现象,可以帮助我们理解 CoT:
-
模型规模要足够大:如果 AI 太小(比如理解力不足),思维链可能就不起作用,因为它连基础知识都还不理解。
-
任务不能太简单:对于一些非常简单的问题,思维链没有太大帮助,因为 AI 已经能直接给出答案。
-
训练数据的联系:如果 AI 在训练中学到的数据彼此联系紧密,思维链的效果会更好。
-
示例中的错误:有趣的是,即使给 AI 的示例中有些错误步骤,思维链依然有效。这说明 CoT 更像是在"指挥" AI 去做一步步的推理,而不是教 AI 具体怎么做。
简而言之,思维链的效果,可能在于它强迫 AI 按步骤思考,就像老师要求学生把解题过程写下来一样,不仅是为了得到答案,更是为了更好地理解问题的过程。
2.5.5 CAMEL中的prompt
现在我们来看看如何使用 CAMEL 的 Prompt 功能,通过实操来更好地理解Prompt的概念。
使用CoT提示创建特定任务Agent
CAMEL 提供了一些便捷的工具来帮助用户使用 CoT。我们可以使用 TaskSpecifyAgent
创建一个特定任务Agent,它会自动调用带有 CoT 的模板。例如,下面是代码示例:
python
from camel.agents import TaskSpecifyAgent
from camel.models import ModelFactory
from camel.types import ModelPlatformType, TaskType
import os
from dotenv import load_dotenv
load_dotenv()
api_key = os.getenv('QWEN_API_KEY')
model = ModelFactory.create(
model_platform=ModelPlatformType.OPENAI_COMPATIBLE_MODEL,
model_type="Qwen/Qwen2.5-72B-Instruct",
url='https://api-inference.modelscope.cn/v1/',
api_key=api_key
)
task_specify_agent = TaskSpecifyAgent(
model=model, task_type=TaskType.AI_SOCIETY,output_language='中文'
)
specified_task_prompt = task_specify_agent.run(
task_prompt="Improving stage presence and performance skills",
meta_dict=dict(
assistant_role="Musician", user_role="Student", word_limit=100
),
)
print(f"Specified task prompt:\n{specified_task_prompt}\n")
>>>
Specified task prompt:
Musician will coach Student on dynamic stage movement, audience engagement techniques, and emotional expression during performances, enhancing overall charisma and connection with the audience.
在这个例子中,我们使用 TaskSpecifyAgent
生成了一个带有思维链的任务提示,通过为 Agent指定角色,让它逐步生成问题的解决方案。
使用自定义 Prompt 模板
CAMEL 还允许用户创建自己的 Prompt 模板,使得生成的 Prompt 更加符合用户的需求。我们可以编写自己的思维链提示模板,然后将它应用到 TaskSpecifyAgent
中。下面是一个简单的示例:
python
from camel.agents import TaskSpecifyAgent
from camel.models import ModelFactory
from camel.prompts import TextPrompt
from camel.types import ModelPlatformType
import os
from dotenv import load_dotenv
load_dotenv()
api_key = os.getenv('QWEN_API_KEY')
model = ModelFactory.create(
model_platform=ModelPlatformType.OPENAI_COMPATIBLE_MODEL,
model_type="Qwen/Qwen2.5-72B-Instruct",
url='https://api-inference.modelscope.cn/v1/',
api_key=api_key
)
my_prompt_template = TextPrompt(
'Here is a task: I\'m a {occupation} and I want to {task}. Help me to make this task more specific.'
) # 你可以根据需求自定义任何模板
task_specify_agent = TaskSpecifyAgent(
model=model, task_specify_prompt=my_prompt_template
)
response = task_specify_agent.run(
task_prompt="get promotion",
meta_dict=dict(occupation="Software Engineer"),
)
print(response)
>>>
Certainly! To make your goal of getting a promotion as a Software Engineer more specific, you can break it down into clear, actionable steps. Here's a more detailed version of your task:
### Specific Task: Get Promoted as a Software Engineer
#### 1. **Understand the Promotion Criteria**
- **Research Company Policies:** Review your company's promotion guidelines and criteria.
- **Talk to Your Manager:** Schedule a meeting with your manager to discuss what is required for a promotion, including specific skills, projects, and performance metrics.
- **Analyze Peer Promotions:** Look at the career paths of colleagues who have been promoted recently to identify common traits and achievements.
#### 2. **Set Clear Goals**
- **Short-Term Goals (Next 3-6 months):** Identify 3-5 specific, achievable goals that align with your promotion criteria.
- Example: Complete a critical project ahead of schedule, improve code quality by 20%, or lead a small team on a new initiative.
- **Long-Term Goals (Next 6-12 months):** Set 2-3 ambitious goals that demonstrate leadership and advanced technical skills.
- Example: Mentor junior engineers, contribute to a major architectural change, or publish a paper or blog post on a relevant topic.
#### 3. **Enhance Your Skills**
- **Technical Skills:** Identify areas where you need to improve and create a plan to enhance these skills.
- Example: Take online courses, attend workshops, or work on side projects to gain expertise in new technologies.
- **Soft Skills:** Develop leadership, communication, and problem-solving skills.
- Example: Join a public speaking club, take a leadership course, or volunteer for cross-functional projects.
#### 4. **Build Relationships**
- **Network Internally:** Build strong relationships with colleagues and senior leaders.
- Example: Participate in company events, join employee resource groups, or offer to help on other teams' projects.
- **Seek Mentors:** Find mentors within the company who can provide guidance and advocate for your promotion.
...
- **Gather Recommendations:** Ask for recommendations from colleagues and managers who can vouch for your skills and contributions.
- **Practice Interviewing:** If there is an interview process, practice answering common promotion interview questions.
By breaking down your goal into these specific steps, you can create a clear roadmap to achieving your promotion. Good luck!
通过这些实操示例,我们可以看到如何通过 CAMEL 的 Prompt 功能来使用思维链提示,这样不仅可以使输出结果更具逻辑性,还能更好地控制 AI 生成内容的质量和相关性。
使用 TextPrompt
类编写你的提示词
在这一部分中,我们将探索 TextPrompt
类并理解其功能。TextPrompt
类是内置 str
类的子类,为处理文本提示提供了额外的功能。
TextPrompt
类简介
TextPrompt
类表示一个文本提示,并扩展了 str
类的功能。它提供了一个名为 key_words
的属性,该属性返回一个字符串集合,表示提示中的关键词。
下面是如何使用 TextPrompt
类的示例:
python
from camel.prompts import TextPrompt
prompt = TextPrompt('Please enter your name and age: {name}, {age}')
print(prompt)
>>>
'Please enter your name and age: {name}, {age}'
在上面的示例中,我们创建了一个包含姓名和年龄关键词的格式字符串的 TextPrompt
实例。我们可以像 Python 中的 str
一样打印 TextPrompt
。
使用
TextPrompt
类
一旦创建了 TextPrompt
实例,我们就可以使用该类提供的各种方法和属性来操作和处理文本提示。
key_words
属性返回一个字符串集合,表示提示中的关键词。
python
from camel.prompts import TextPrompt
prompt = TextPrompt('Please enter your name and age: {name}, {age}')
print(prompt.key_words)
>>>
{'name', 'age'}
在上面的示例中,key_words
属性返回一个表示提示中关键词的字符串集合,在这种情况下是 'name' 和 'age'。
format
方法重写了内置的 str.format
方法,允许部分格式化格式字符串中的值。它用提供的值替换格式字符串中的关键词。
python
from camel.prompts import TextPrompt
prompt = TextPrompt('Your name and age are: {name}, {age}')
name, age = 'John', 30
formatted_prompt = prompt.format(name=name, age=age)
print(formatted_prompt)
>>> "Your name and age are: John, 30"
在上面的示例中,我们使用 format
方法将关键词 {name}
和 {age}
替换为值 'John' 和 30。
我们还可以通过只提供部分值进行部分格式化:
python
from camel.prompts import TextPrompt
prompt = TextPrompt('Your name and age are: {name}, {age}')
name = 'John'
partial_formatted_prompt = prompt.format(name=name)
print(partial_formatted_prompt)
>>> "Your name and age are: John, {age}"
在上面的示例中,我们仅提供 name
关键词的值,而 age
关键词保持不变。当我们想在不同代理中对 TextPrompt
的不同关键词进行格式化时,这种方式很有帮助。
我们可以对 TextPrompt
实例执行各种字符串操作,如连接、连接和应用类似于 Python str
的字符串方法。
python
from camel.prompts import TextPrompt
prompt1 = TextPrompt('Hello, {name}!')
prompt2 = TextPrompt('Welcome, {name}!')
#连接
prompt3 = prompt1 + ' ' + prompt2
print(prompt3)
>>> "Hello, {name}! Welcome, {name}!"
print(isinstance(prompt3, TextPrompt))
>>> True
print(prompt3.key_words)
>>> {'name'}
#连接
prompt4 = TextPrompt(' ').join([prompt1, prompt2])
print(prompt4)
>>> "Hello, {name}! Welcome, {name}!"
print(isinstance(prompt4, TextPrompt))
>>> True
print(prompt4.key_words)
>>> {'name'}
#应用字符串方法
prompt5 = prompt4.upper()
print(prompt5)
>>> "HELLO, {NAME}! WELCOME, {NAME}!"
print(isinstance(prompt5, TextPrompt))
>>> True
print(prompt5.key_words)
>>> {'NAME'}
在上面的示例中,我们演示了使用 +
运算符进行连接、使用 join
方法进行连接以及将 upper
方法应用于 TextPrompt
实例。生成的提示也是 TextPrompt
的实例。
除此以外,CAMEL 提供了多种支持的 Prompt 模板,以满足不同类型的任务需求。具体可以参考这个Blog