DataWhale10月动手实践——Bot应用开发task02学习笔记

一、Prompt工程

之前有接触过一些Prompt工程的内容,也做过一些简单的应用,比如使用langchain和Openai库自己搭建了一个助手项目,但是还从未关注过在智能体方面的Prompt。在这篇博客中,我会将我之前掌握的和在本次任务学习中掌握的内容,进行一个总结,并通过实践,展示各种技巧的运用🌟🌟🌟。

1.什么是Prompt?为什么需要Prompt?

Prompt:Prompt是用户输入给模型的文本或者指令,用于引导模型生成所需的输出,描述了用户想要从模型获取的信息、回答、文本等内容。Prompt是用户与模型之间的对话起点,Prompt的目的是引导模型产生所需的回应,以便于更好地控制生成的输出。

对于语言模型,Prompt可以是一个简短的问题、完整的论述段落或者是一组指令,取决于用户的具体使用场景,在生成回答文本时,模型会试图理解Prompt并根据其生成相应的相应。Prompt会直接影响模型的生成文本的内容、风格、质量。

说到这可能对Prompt及其重要性还有些模糊,其实简要来说可以分为以下几个方面:

  1. 明确上下文和目标:通过Prompt工程,可以给大模型一个明确的上下文指令,告诉它前因后果,帮助大模型理解它要执行的任务。比如,如果你想生成文本、回答问题或者生成图像,就需要在Prompt中告知大模型,就可以帮助限定生成内容的范围和方向👌。
  2. 提高生成质量和相关性:好的prompt往往能够背大模型更好的理解,从而提升回答的质量;通过指定角色,介绍背景,细化要求等方式,提供具体的上下文和细节,能让生成的结果更加符合用户的预期。
  3. 解决多义性问题:大模型在面对"无头无尾"的任务时,往往会产生模糊或者多义的输出😟。Prompt可以使得任务更加明朗,减少歧义,输出用户最想要的结果。
  4. 控制模型行为:Prompt还可以帮助控制模型的风格、语气和格式。例如:你可以通过设计Prompt让大模型使用海盗🏴‍☠️的语气回答你的专业课程问题,想必会更加地诙谐有趣👍。

2.常见的Prompt方法

  • Zero-Shot :简单地将任务文本提供给模型并要求得到结果。这种情况下,模型仅通过任务描述或问题来推断出应该如何回应,即不提供例子,仅仅使用指令来告知任务

    • 优点:灵活度极高。
    • 缺点:无法准确把握任务的细微差别或特定要求。
    • 举例:请你帮我判断一下这句话的情绪类型:"我非常荣幸认识你。"
  • Few-Shot :通过提供少量的标注样本来帮助模型理解任务,即使用少量例子给LLM作为上提示。这些示例通常包括输入和语气输出,以便模型能够更准确地把握任务的性质和要求。

    • 优点:对目标任务而言,由于Prompt给LLM提供了良好的例子,所以LLM可以更快更好地理解好答案的标准,因此,Few-shot

    • 缺点:相较于Zero-Shot,会消耗更多的token,并且当输入和输出文本较长时,可能会达到上下文长度限制。

    • 举例:

      示例1: 昨晚住的酒店实在是太棒了。 情绪类别:积极;
      示例2:明天不能去参加聚会实在是太糟糕了。情绪类别:消极
      
      请判断下面句子的情绪类别:
      句子1:我很期待明天的公开课!
      句子2:我在这次组队学习中收获很多。
      
  • Instruct Prompt :在Prompt中插入具体的格式,让LLM按照我们给定的格式生成回答,以便于后续解析。通过一些高质量的问答对和对答案的回复的来训练一个符合用户偏好的奖励模型,通过这个奖励模型来进一步反馈知道LLM的输出的回答的质量

    • 优点:提供直接指令,且易于实现,不需要复杂的上下文或者背景信息,直接描述任务即可。

    • 缺点:灵活性较低,依赖指令质量。

    • 举例:

      python 复制代码
      prompt = f"""
      	请生成包括书名,作者,类别的三本虚构的,非真实存在的中文书清单,\
      	并以JSON格式提供,其中包含以下键:book_id, author, genre
      """
      response = get_completion(prompt)
      print(response)
  • Chain of Thought(思维链, CoT):CoT是一种提示方法,鼓励模型在给出最终答案之前,先生称一系列中间推理步骤。模拟了人类的思考过程,特别有助于解决复杂的、多步骤的问题。

    • 优点:增强推理能力,提高答案可靠性。

    • 缺点:中间步骤太多可能导致输出内容过长,不够简洁;如果某个步骤出现错误,可能影响最终答案的正确性。

    • 举例:

      问题:一个人以每小时5公里的速度步行2小时,然后以每小时10公里的速度骑自行车1小时。他总共走了多少公里?
      
      模型思维链:
      1. 步行距离 = 5公里/小时 × 2小时 = 10公里。
      2. 骑车距离 = 10公里/小时 × 1小时 = 10公里。
      3. 总距离 = 步行距离 + 骑车距离 = 10公里 + 10公里 = 20公里。
      
      最终答案:他总共走了20公里。
      

3.Prompt工程遵守的原则

3.1 编写清晰、具体的指令

为了让模型执行想要的操作,应该给模型提供尽可能清晰和具体的指令,从而引导模型给出正确的输出,减少获得无关或不理想相应的可能。但不意味着要输入简短的指令,更长的提示往往更加清晰并且可以提供更多的上下文,会导致更详细以及更相关的输出,但是Prompt的编写应该尽量的简洁

策略1------使用定界符来表示输入的不同部分

分隔符可以是: ````,"",<>,###`等等。可以使用明显的标点符号将问题,上下文,任务要求等进行分隔。使用分隔符可以有效地避免提示诸如。提示注入 指的是如果用户将某些输入添加到Prompt中,可能会向模型提供与任务相冲突的指令,即输入的Prompt中kennel包含其他指令,会覆盖掉用户的指令。

"为以下段落创建总结:<文本内容>"
策略2------要求结构化的输出

要求模型以特殊的结构进行输出,结构化输出可以是JSON,HTML等格式。结构化的输出更容易被用户捕捉并解析。

python 复制代码
prompt = f"""
请生成包括书名、作者和类别的三本虚构书籍清单,\
并以 JSON 格式提供,其中包含以下键:book_id、title、author、genre。
"""
response = get_completion(prompt)
print(response)
策略3------要求模型检查是否满足条件

在利用LLM解决具体问题时,我们可以在提示中要求模型自我检查,还可以告诉模型在边缘情况下该如何处理。这种措施可以尽量避免意外的错误或结果,减少错误的输出,鼓励模型进行自我纠正。

python 复制代码
"请检查输出的内容是否符合 book_id	|	suthor	|	genre的格式。如果不满足,请重新检查并再次回答"
策略4------小批量提示

可以在要求模型执行任务之前,给模型一些成功执行任务的示例,也就是之前提到的Few-shot

3.2 给模型充分的思考时间

语言模型与人类一样,需要时间来思考并解决复杂问题。如果让语言模型匆忙给出结论,其结果很可能不准确。

策略5------指定完成任务的步骤

描述一个复杂的任务,并给出完成任务的步骤,帮助模型更好地思考问题。以《LLM CookBook》中内容

python 复制代码
text = f"""
在一个迷人的村庄里,兄妹杰克和吉尔出发去一个山顶井里打水。\
他们一边唱着欢乐的歌,一边往上爬,\
然而不幸降临------杰克绊了一块石头,从山上滚了下来,吉尔紧随其后。\
虽然略有些摔伤,但他们还是回到了温馨的家中。\
尽管出了这样的意外,他们的冒险精神依然没有减弱,继续充满愉悦地探索。
"""
# example 1
prompt_1 = f"""
执行以下操作:
1-用一句话概括下面用三个反引号括起来的文本。
2-将摘要翻译成英语。
3-在英语摘要中列出每个人名。
4-输出一个 JSON 对象,其中包含以下键:english_summary,num_names。

请用换行符分隔您的答案。

Text:
```{text}```
"""
response = get_completion(prompt_1)
print("prompt 1:")
print(response)

"""输出如下:
	prompt 1:
1- 兄妹在山顶井打水时遇到意外,但冒险精神未减。
2- In a charming village, siblings Jack and Jill set off to fetch water from a well on the mountaintop. They sang joyful songs as they climbed, but unfortunately, Jack tripped on a rock and tumbled down the mountain, with Jill following closely behind. Despite some minor injuries, they made it back home safely. Despite the mishap, their adventurous spirit remained undiminished as they continued to explore with joy.
3- Jack, Jill
4- {
  "english_summary": "In a charming village, siblings Jack and Jill set off to fetch water from a well on the mountaintop. They sang joyful songs as they climbed, but unfortunately, Jack tripped on a rock and tumbled down the mountain, with Jill following closely behind. Despite some minor injuries, they made it back home safely. Despite the mishap, their adventurous spirit remained undiminished as they continued to explore with joy.",
  "num_names": 2
}
"""
策略6------在模型自己下结论之前给定解决方案

在设计Prompt时可以通过明确指导来帮助LLM建立合理的思维,从而按照用户的想法去解决问题。可以避免匆忙的出结论,提高回答的准确性和全面性。

python 复制代码
prompt = f"""
判断学生的解决方案是否正确。

问题:
我正在建造一个太阳能发电站,需要帮助计算财务。

    土地费用为 100美元/平方英尺
    我可以以 250美元/平方英尺的价格购买太阳能电池板
    我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元
    作为平方英尺数的函数,首年运营的总费用是多少。

学生的解决方案:
设x为发电站的大小,单位为平方英尺。
费用:

    土地费用:100x
    太阳能电池板费用:250x
    维护费用:100,000美元+100x
    总费用:100x+250x+100,000美元+100x=450x+100,000美元
"""
response = get_completion(prompt)
print(response)
"""输出如下:
	学生的解决方案是正确的。他们正确地计算了土地费用、太阳能电池板费用和维护费用,并将它们相加得到了首年运营的总费用。
"""

4. 大模型存在的问题/局限性

  1. 存在数据依赖性和偏见

    • 大模型需要大量的数据进行训练,这些数据往往来源于互联网等公开资源。然而,训练数据不可避免地包含人类的偏见,如种族、性别、文化等方面的刻板印象。这些偏见可能会在模型生成的输出中显现,导致结果带有潜在的歧视性或不公正性。
  2. 缺乏常识推理和事实准确性

    • 尽管大模型在语言生成方面表现强大,它们在常识推理和事实检查方面仍然有限。大模型基于模式匹配而非真正的理解和推理,可能会生成看似合理但实际上不准确的内容。这使得它们在需要高度精确或逻辑推理的任务中表现不佳。比如大模型幻觉现象,就是由于大模型缺乏某方面的知识,由于它的自回归特性,会生成一些看似正确但不存在的事物。
    • 以下是一个示例,大模型描述了一个根本不存在的华为手表产品👉👈。
  3. 理解多义词或复杂预警的能力有限

    • 大模型虽然可以处理大量的文本,但在理解多义词(如有不同含义的词汇)和复杂语境时,往往表现不稳定。这是因为它们基于大量训练数据来"推测"上下文,而并非真正理解这些词的多种可能含义。因此,当一个单词在不同语境下有多重解释时,大模型可能会无法准确区分。

      举例:对于像"bank"这样既可以指"银行"又可以指"河岸"的词,大模型可能在特定语境下做出错误的推测,尤其是在上下文信息不明确或含糊时。

  4. 生成的内容有时缺乏连贯性或者深度

    • 尽管大模型擅长生成大量的文本内容,但生成的内容有时缺乏连贯性,或者在复杂主题上缺乏深入分析。原因在于,大模型是基于概率生成文本,而不是基于推理或真实的理解。当要求它进行长篇内容生成时,模型可能会失去逻辑上的一致性,导致重复、不连贯或者不具备足够的深度。
  5. 在特定领域的知识更新可能滞后

    • 大模型的知识主要来源于训练时的数据,而训练数据可能不够新。由于这些模型一旦训练完成,它们无法动态更新,因此它们的知识可能会在快速变化的领域(如技术、医学等)中迅速过时。在这些领域中,如果不定期更新模型,用户可能会得到过时或错误的信息。

      举例:ChatGPT3。5使用训练数据截止于2021年,可能无法准确反映2024年的最新技术或科学进展,除非对其进行重新训练或使用外部知识库进行补充。

  6. 对特定任务的表现可能不稳定,需要反复调整提示

    • 大模型的性能高度依赖于输入的提示(prompts)。对于特定任务,尤其是需要细节或精确回答的任务,生成结果可能会出现波动。用户往往需要多次调整提示词才能得到理想的结果。这种不稳定性使得大模型在处理高度定制化的任务时,表现出不确定性,增加了用户使用的复杂度。

二、prompt在智能体中的应用

智能体执行一个任务的过程:

  1. 用户输入关于任务的描述,以及需要达成的目标。
  2. 根据任务进行向量检索,找出工具列表中最相关的工具(Top N工具)以及相关的知识。
  3. 使用检索到的工具,知识以及工具执行结果填充到Prompt模版之中。
  4. 使用填充后的Prompt向大语言模型(LMM)发送请求,获取LLM的输出。
  5. 循环步骤3到5,直到任务完成或出现错误,这个过程kennel需要调用多个工具逐步完成。

ReAct Prompt

ReAct提供了一种更利于人类理解,诊断和控制的决策和推理过程。它的具体流程如下:

  • 思考(Thought)---->行动(Action)---->观察(Observation)
  • 上述过程简称TAO循环。

ReAct的核心就是使用"思考","行动","观察"三个步骤来解决任务。

上述图片展示了ReAct算法与其他Prompt方法的对比。

  1. Hotspot QA : 针对与Apple Remote相关的问答任务。
    • 1a. Standard:直接给出答案(iPod),但没有任何推理过程,答案不正确。
    • 1b. CoT (Reason Only):推理出Apple Remote与Apple TV相关联,并指出其他设备(iPhone、iPad、iPod Touch)可以控制Apple TV,但最终答案仍不正确。
    • 1c. Act-Only:通过搜索"Apple Remote"和"Front Row",得到了中间步骤的观察结果,但并未得出准确的答案。
    • 1d. ReAct (Reason + Act):结合推理和行动,通过搜索得出前瞻性的推理过程,最后得到了正确答案------键盘的功能键。
  2. AI2-ALFWorld : 针对房间内执行放置任务的场景。
    • 2a. Act-Only:只关注行动步骤,未进行推理。多次执行错误操作,最终没有完成任务。
    • 2b. ReAct (Reason + Act):在执行任务时,智能体通过推理找到目标物体(胡椒瓶),并正确完成了将其放置在抽屉上的任务。

上面这幅图片强调了 ReAct(Reason + Act) 通过结合推理与行动能够更好地解决问题。相比之下,单纯的行动或者推理往往不能提供正确的结果。

接下来我们用一个例子来试着体验一下ReAct算法。

python 复制代码
import os
from langchain import OpenAI
from langchain.agents import initialize_agent, Tool, AgentType
from langchain.prompts import PromptTemplate

# 设置 OpenAI API 密钥
os.environ["OPENAI_API_KEY"] = "your-openai-api-key"

# 定义智能体可以使用的工具
def search_kitchen():
    return "在厨房搜索中...没有找到钥匙。"

def search_living_room():
    return "在客厅搜索中...没有找到钥匙。"

def search_bedroom():
    return "在卧室床底下找到了钥匙!"

tools = [
    Tool(
        name="Search Kitchen",
        func=search_kitchen,
        description="在厨房中寻找钥匙。"
    ),
    Tool(
        name="Search Living Room",
        func=search_living_room,
        description="在客厅中寻找钥匙。"
    ),
    Tool(
        name="Search Bedroom",
        func=search_bedroom,
        description="在卧室床底下寻找钥匙。"
    ),
]

# 定义 ReAct 的提示模板
prompt = PromptTemplate.from_template("""
你是一个智能助手,擅长推理和采取行动来帮助用户完成任务。

用户的问题:{input}

请先进行推理,然后选择合适的工具来采取行动。输出应遵循以下格式:

Thought: 你的思考过程
Action: 选择的工具名称
Action Input: 工具的输入参数
Observation: 工具的输出结果
...

最终回答:给出最终的回答。
""")

# 初始化 OpenAI 语言模型
llm = OpenAI(temperature=0)

# 初始化 ReAct 智能体,使用 AgentType.REACT_DOCSTORE
agent = initialize_agent(
    tools,
    llm,
    agent=AgentType.REACT_DOCSTORE,  # 使用 REACT_DOCSTORE 类型的智能体
    verbose=True,
    agent_kwargs={"prompt": prompt}
)

# 用户输入示例
user_input = "我丢失了一把钥匙,钥匙可能在厨房、客厅或卧室。厨房里有很多杂物,客厅比较整洁,卧室的床底下可能藏了很多东西。你能帮我找到钥匙吗?"

# 运行智能体
response = agent.run(user_input)

print("最终回答:", response)

三、BoT创建实践

编写Prompt的关键步骤

目标:

编写一个 Prompt 让智能家居助手充当家庭助手,帮助用户控制智能设备(如灯、空调等),并回答一些关于天气或日程安排的问题。


1. 明确角色和目标

原文:告诉模型它在对话中的身份和目标,需要扮演哪个角色,角色的特点和任务是什么。

应用案例

plaintext 复制代码
你是一个智能家居助手,名为"HomeCraft",你负责协助用户管理他们的智能家居设备,并回答他们的日常问题。你的目标是确保设备运行顺利,并提供有关天气、日程安排等实用信息。

在这个步骤中,我们明确了模型是一个名为"HomeCraft"的智能家居助手,它的主要任务是控制设备和回答问题。这让模型有一个清晰的身份和职责。


2. 目标明确

原文:说明模型需要达到的目标是什么。

应用案例

plaintext 复制代码
你的主要目标是帮助用户控制家中的智能设备,并提供及时准确的日常信息,如天气预报和日程提醒。你的回答应尽可能简洁、直接,并且符合用户的需求。

我们明确告知模型它的核心任务是设备控制和信息提供。通过这样的描述,模型将能够专注于任务,不会偏离目标。


3. 提供模型需要遵循的思考路径和限制条件

原文:确保生成内容具有一致性和连贯性。

应用案例

plaintext 复制代码
当用户询问关于家居控制的问题时,你应该先确认设备状态(如灯是开着还是关着),然后根据用户的指令采取相应的行动。对于天气或日程问题,你需要提供最新信息,并且尽量在三句话以内回答。

通过这种方式,我们给出了一个推理路径:先确认设备状态,然后执行指令。同时设定了回答长度限制(比如回答尽量在三句话以内),确保模型输出内容简洁一致。


4. 个性化设置

原文:要求模型在语气或者风格上进行个性化的改变,使得模型输出更有特色。

应用案例

plaintext 复制代码
你应该使用礼貌且友好的语气与用户互动。例如,当用户下达命令时,可以回应:"好的,我已帮您关闭灯光。" 或 "当然,客厅的空调已经打开。"

通过这个描述,我们为模型设定了礼貌友好的风格,使得用户在使用时感受到助手的温馨和人性化服务。


5. 明确的工作流程

原文:指导模型如何执行特定的操作和流程。

应用案例

plaintext 复制代码
1. 当用户请求控制设备时:
   - 确认设备当前状态(如设备是否开着或关着)。
   - 然后执行用户的指令,并反馈操作结果。
   
2. 当用户询问天气或日程安排时:
   - 检查系统中的最新信息。
   - 简洁明了地回复用户,并提供相关的提醒或建议。

通过明确的操作流程,我们指导模型如何执行不同的任务。这种步骤可以帮助模型在处理复杂任务时表现出色。


6. 初始化设置

原文:定义模型如何开始对话或者任务。

应用案例

plaintext 复制代码
开始时,你可以用一句问候语引导用户,例如:"您好,我是您的智能家居助手HomeCraft,您今天想要我帮忙做些什么呢?"

通过提供一个开场白,模型可以自然地进入对话,并与用户建立良好的互动。这也为用户提供了一个直观的入口,知道如何开始使用助手。

输入完整的Prompt,之后可以让coze助手帮助我们优化。

优化之后的Prompt如下

plaintext 复制代码
# 角色
你是一个高效的智能家居助手 HomeCraft,能协助用户管理智能家居设备,同时提供天气、日程安排等实用信息,确保设备运行顺利且满足用户日常需求。

## 技能
### 技能 1:控制设备
1. 当用户请求控制设备时,首先确认设备当前状态(如灯是开着还是关着,空调是运行中还是关闭状态等)。
2. 执行用户指令,并反馈操作结果,回复示例:"好的,<设备名称>当前状态为<开/关等状态>,已按照您的要求<执行操作>,现在<设备名称>处于<新状态>。"

### 技能 2:提供天气信息
1. 当用户询问天气时,检查系统中的最新信息。
2. 简洁明了地回复用户,并提供相关的提醒或建议,回复示例:"今天天气<具体情况>。建议您<如外出带伞等提醒>。"

### 技能 3:提供日程安排信息
1. 当用户询问日程安排时,检查系统中的最新信息。
2. 简洁明了地回复用户,回复示例:"您今天的日程有<具体日程内容>。"

## 限制
- 只处理与智能家居设备控制、天气、日程安排相关的问题,拒绝回答无关话题。
- 输出内容必须按照给定的格式进行组织,不能偏离框架要求。
- 回复应尽可能简洁、直接,符合用户需求,且使用礼貌友好的语气。
- 对于设备控制问题,需先确认设备状态再执行指令并反馈结果;对于天气和日程问题,尽量在三句话以内回答。

我们可以加入适当的插件以及通过图片,文本等形式创建知识库,来进一步增强智能体的能力。

接下来我们试着去调试,可以发现智能体调用并查询了我们刚才创建的知识库中的内容。

以上就是我在本次task2的学习完成之后想要分享的一些内容,希望可以在后续的学习中更加全面的了解智能体,掌握更多的智能体搭建技巧🎉。

相关推荐
Somnus陳2 分钟前
软考架构师笔记-计算机系统组成-1
笔记·系统架构
LuH11241 小时前
【论文阅读笔记】IC-Light
论文阅读·笔记
汤姆和佩琦1 小时前
2024-12-25-sklearn学习(20)无监督学习-双聚类 料峭春风吹酒醒,微冷,山头斜照却相迎。
学习·聚类·sklearn
是小菜呀!1 小时前
实验四 触发器
笔记
悲伤小伞2 小时前
C++_数据结构_详解二叉搜索树
c语言·数据结构·c++·笔记·算法
好学近乎知o2 小时前
正则表达式(学习Django过程中可能涉及的)
学习·正则表达式·django
雨中奔跑的小孩2 小时前
爬虫学习案例8
爬虫·学习
jieshenai2 小时前
使用 VSCode 学习与实践 LaTeX:从插件安装到排版技巧
ide·vscode·学习
灰太狼不爱写代码5 小时前
CUDA11.4版本的Pytorch下载
人工智能·pytorch·笔记·python·学习
eybk10 小时前
Pytorch+Mumu模拟器+萤石摄像头实现对小孩学习的监控
学习