小白举手02-青训营ai笔记-提示篇 | 豆包MarsCode AI 刷题

162 阅读15分钟

一、概念

(一)提示的结构

  • 指令(Instuction)告诉模型这个任务大概要做什么、怎么做,比如如何使用提供的外部信息、如何处理查询以及如何构造输出。这通常是一个提示模板中比较固定的部分。一个常见用例是告诉模型“你是一个有用的XX助手”,这会让他更认真地对待自己的角色。
  • 上下文(Context)则充当模型的额外知识来源。这些信息可以手动插入到提示中,通过矢量数据库检索得来,或通过其他方式(如调用API、计算器等工具)拉入。一个常见的用例时是把从向量数据库查询到的知识作为上下文传递给模型。
  • 提示输入(Prompt Input)通常就是具体的问题或者需要大模型做的具体事情,这个部分和“指令”部分其实也可以合二为一。但是拆分出来成为一个独立的组件,就更加结构化,便于复用模板。这通常是作为变量,在调用模型之前传递给提示模板,以形成具体的提示。
  • 输出指示器(Output Indicator)标记​​要生成的文本的开始。这就像我们小时候的数学考卷,先写一个“解”,就代表你要开始答题了。如果生成 Python 代码,可以使用 “import” 向模型表明它必须开始编写 Python 代码(因为大多数 Python 脚本以import开头)。这部分在我们和ChatGPT对话时往往是可有可无的,当然LangChain中的代理在构建提示模板时,经常性的会用一个“Thought:”(思考)作为引导词,指示模型开始输出自己的推理(Reasoning)。

(二)提示模板导入

(1).prompt-

from langchain.prompts.prompt import PromptTemplate

  • 适用于需要明确指定模块路径的情况,确保代码的可读性和结构清晰。

(2)直接导入

  • 这种方式从langchain的顶层直接导入PromptTemplate类。
  • 更加简洁,适合快速使用,但可能在大型项目中导致命名冲突或不清晰。

from langchain import PromptTemplate

(三)提示模板类型

FewShotPromptTemplate是重点

image.png

(四)CoT思考链 Chain of Thought

概念

如果生成一系列的中间推理步骤,就能够显著提高大型语言模型进行复杂推理的能力。

思考链类型

Few-Shot CoT:

假设我们正在开发一个AI花店助手,它的任务是帮助用户选择他们想要的花,并生成一个销售列表。在这个过程中,我们可以使用CoT来引导AI的推理过程。

? 整体指导:你需要跟着下面的步骤一步步的推理。

  1. 问题理解:首先,AI需要理解用户的需求。例如,用户可能会说:“今天要参加朋友的生日Party,想送束花祝福她。”我们可以给AI一个提示模板,里面包含示例:“遇到XX问题,我先看自己有 没有 *相关知识,有的话,就提供答案;没有,就调用工具搜索,有了知识后再试图解决。 *”—— 这就是给了AI一个思维链的示例。  
  2. 信息搜索:接下来,AI需要搜索相关信息。例如,它可能需要查找哪些花最适合生日派对。  
  3. 决策制定:基于收集到的信息,AI需要制定一个决策。我们可以通过思维链让他详细思考决策的流程,先做什么后做什么。例如,我们可以给它一个示例:“*遇到生日派对送花的情况,我先考虑用户的需求,然后查看鲜花的库存,最后决定推荐一些玫瑰和百合,因为这些花通常适合生日派对。 *”—— 那么有了生日派对这个场景做示例,大模型就能把类似的思维流程运用到其它场景。  
  4. 生成销售列表:最后,AI使用OutputParser生成一个销售列表,包括推荐的花和价格。

在这个过程中,整体上,思维链引导AI从理解问题,到搜索信息,再到制定决策,最后生成销售列表。这种方法不仅使AI的推理过程更加清晰,也使得生成的销售列表更加符合用户的需求。具体到每一个步骤,也可以通过思维链来设计更为详细的提示模板,来引导模型每一步的思考都遵循清晰准确的逻辑。

Zero-Shot CoT

Few-Shot CoT,指的就是在带有示例的提示过程中,加入思考的步骤,从而引导模型给出更好的结果。而Zero-Shot CoT,就是直接告诉模型要一步一步地思考,慢慢地推理。你只要简单地告诉模型“让我们一步步的思考(Let's think step by step) ”,模型就能够给出更好的答案!

(五)思维树Tree of Thoughts

image.png 概念:ToT是一种解决复杂问题的框架,它在需要多步骤推理的任务中,引导语言模型搜索一棵由连贯的语言序列(解决问题的中间步骤)组成的思维树,而不是简单地生成一个答案。ToT框架的核心思想是:让模型生成和评估其思维的能力,并将其与搜索算法(如广度优先搜索和深度优先搜索)结合起来,进行系统性地探索和验证。

ToT 框架为每个任务定义具体的思维步骤和每个步骤的候选项数量。例如,要解决一个数学推理任务,先把它分解为3个思维步骤,并为每个步骤提出多个方案,并保留最优的5个候选方案。然后在多条思维路径中搜寻最优的解决方案。

这种方法的优势在于,模型可以通过观察和评估其自身的思维过程,更好地解决问题,而不仅仅是基于输入生成输出。这对于需要深度推理的复杂任务非常有用。此外,通过引入强化学习、集束搜索等技术,可以进一步提高搜索策略的性能,并让模型在解决新问题或面临未知情况时有更好的表现。

二、不同提示模板的使用

(一)PromptTemplate

from langchain import PromptTemplate

template = """\
你是业务咨询顾问。
你给一个销售{product}的电商公司,起一个好的名字?
""" 
#这里定义了一个多行字符串模板,使用了三重引号(`"""`)来允许字符串跨越多行
prompt = PromptTemplate.from_template(template)

print(prompt.format(product="鲜花"))
# `format`方法被调用,并传入一个字典,其中键为占位符名称(在这里是`product`),值为要替换进去的具体内容(在这里是“鲜花”)
你是业务咨询顾问。
你给一个销售鲜花的电商公司,起一个好的名字?
prompt = PromptTemplate(
    input_variables=["product", "market"], 
    template="你是业务咨询顾问。对于一个面向{market}市场的,专注于销售{product}的公司,你会推荐哪个名字?"
)
print(prompt.format(product="鲜花", market="高端"))

(二)ChatPromptTemplate

【说明】: 消息必须是消息对象的数组,其中每个对象都有一个角色(系统、用户或助理)和内容。对话可以短至一条消息,也可以来回多次。  

通常,对话首先由系统消息格式化,然后是交替的用户消息和助理消息。  

系统消息有助于设置助手的行为。例如,你可以修改助手的个性或提供有关其在整个对话过程中应如何表现的具体说明。但请注意,系统消息是可选的,并且没有系统消息的模型的行为可能类似于使用通用消息,例如“你是一个有用的助手”。  

用户消息提供助理响应的请求或评论。  

助理消息存储以前的助理响应,但也可以由你编写以给出所需行为的示例。

# 导入聊天消息类模板
from langchain.prompts import (
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
)
# 模板的构建
template="你是一位专业顾问,负责为专注于{product}的公司起名。"
system_message_prompt = SystemMessagePromptTemplate.from_template(template)
human_template="公司主打产品是{product_detail}。"
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
prompt_template = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])

# 格式化提示消息生成提示
prompt = prompt_template.format_prompt(product="鲜花装饰", product_detail="创新的鲜花设计。").to_messages()

# 下面调用模型,把提示传入模型,生成结果
import os
os.environ["OPENAI_API_KEY"] = '你的OpenAI Key'
from langchain.chat_models import ChatOpenAI
chat = ChatOpenAI()
result = chat(prompt)
print(result)

(三) FewShot

1、概念

Few-Shot(少样本)、One-Shot(单样本)和Zero-Shot(零样本)学习是机器学习中的三种不同的学习策略,主要用于处理训练数据稀缺的情况。以下是对这三种学习方法的详细解释。

Zero-Shot Learning(零样本学习)

定义:Zero-Shot Learning(ZSL)是一种机器学习技术,允许模型在没有见过某个类别的情况下对其进行分类。模型在训练时只接触到某些类别的数据,但可以利用已知类别的特征或描述来推断未知类别。工作原理:

  • 语义关联:ZSL通常依赖于语义信息或属性来建立已知类别与未知类别之间的联系。例如,如果模型了解马和老虎的特征,并且被告知斑马有类似马的外形和老虎的条纹,那么它就可以推测出斑马的特征。

  • 应用场景:ZSL在计算机视觉和自然语言处理等领域非常有用,尤其是在标注数据稀缺的情况下,如医学图像分析或罕见物体的分类

One-Shot Learning(单样本学习)

定义:One-Shot Learning是一种特殊的Few-Shot学习方法,旨在通过仅提供一个样本来训练模型,使其能够识别新类别。这意味着模型在见到新类别时,只需一张图片或一个示例就能进行有效分类。工作原理:

  • 知识迁移:One-Shot Learning通常依赖于从大规模数据集中获得的通用知识,通过这种知识来帮助模型理解新类别。例如,在人脸识别中,系统可以通过一张新员工的照片来识别该员工,而无需重新训练整个模型。

  • 应用场景:这种方法特别适合于需要快速适应新类别的场景,如人脸识别、物体检测等

Few-Shot Learning(少样本学习)

定义:Few-Shot Learning是指在训练集中每个类别只有少量样本(通常是几个到十几个)的情况下,模型仍然能够进行有效分类。与One-Shot Learning不同,Few-Shot Learning可以使用多个样本来帮助模型理解新类别。工作原理:

  • 样本利用:通过给定少量样本,模型可以学习到该类别的一般特征,从而在遇到新的测试样本时进行准确分类。例如,如果给模型看几张熊猫的照片,它就能在动物园中识别出熊猫。

  • 应用场景:Few-Shot Learning适用于需要快速适应新环境或新任务的情况,如图像分类、语义分割等

总结

这三种学习方法各有特点:

  • Zero-Shot Learning强调的是对完全未见过类别的推理能力,依赖于已有知识进行类比。
  • One-Shot Learning则是在极少数据情况下,通过一个示例进行有效学习。
  • Few-Shot Learning则允许使用少量样本进行学习,适合于数据稀缺但仍希望进行有效分类的场景。 Few-Shot(少样本) One-Shot(单样本) Zero-Shot(零样本)

2、代码示例

# 1. 创建一些示例
samples = [
    {
        "flower_type": "玫瑰",
        "occasion": "爱情",
        "ad_copy": "玫瑰,浪漫的象征,是你向心爱的人表达爱意的最佳选择。",
    },
    {
        "flower_type": "康乃馨",
        "occasion": "母亲节",
        "ad_copy": "康乃馨代表着母爱的纯洁与伟大,是母亲节赠送给母亲的完美礼物。",
    },
    {
        "flower_type": "百合",
        "occasion": "庆祝",
        "ad_copy": "百合象征着纯洁与高雅,是你庆祝特殊时刻的理想选择。",
    },
    {
        "flower_type": "向日葵",
        "occasion": "鼓励",
        "ad_copy": "向日葵象征着坚韧和乐观,是你鼓励亲朋好友的最好方式。",
    },
]

__import__("pysqlite3")
import sys

sys.modules["sqlite3"] = sys.modules.pop("pysqlite3")



# 2. 创建一个提示模板
from langchain.prompts.prompt import PromptTemplate

prompt_sample = PromptTemplate(
    input_variables=["flower_type", "occasion", "ad_copy"],
    template="鲜花类型: {flower_type}\n场合: {occasion}\n文案: {ad_copy}",
)
print(prompt_sample.format(**samples[0]))
#`**samples`表示将`samples`字典中的键值对解包为关键字参数传递给`format()`方法。假设`samples`是一个字典,包含与模板中占位符对应的键值



# 3. 创建一个FewShotPromptTemplate对象
from langchain.prompts.few_shot import FewShotPromptTemplate

prompt = FewShotPromptTemplate(
    examples=samples,
    example_prompt=prompt_sample,
    suffix="鲜花类型: {flower_type}\n场合: {occasion}",
    input_variables=["flower_type", "occasion"],
)
print(prompt.format(flower_type="野玫瑰", occasion="爱情"))

# 4. 把提示传递给大模型
import os

# os.environ["OPENAI_API_KEY"] = '你的OpenAI API Key'
from langchain_openai import ChatOpenAI

model = ChatOpenAI(
    model=os.environ.get("LLM_MODELEND"),
)
result = model(prompt.format(flower_type="野玫瑰", occasion="爱情"))
print(result)

# 5. 使用示例选择器
from langchain.prompts.example_selector import SemanticSimilarityExampleSelector
from langchain_community.vectorstores import Chroma

# 初始化Embedding类
from volcenginesdkarkruntime import Ark
from typing import List, Any
from langchain.embeddings.base import Embeddings
from langchain.pydantic_v1 import BaseModel


class DoubaoEmbeddings(BaseModel, Embeddings):
    client: Ark = None
    api_key: str = ""
    model: str

    def __init__(self, **data: Any):
        super().__init__(**data)
        if self.api_key == "":
            self.api_key = os.environ["OPENAI_API_KEY"]
        self.client = Ark(
            base_url=os.environ["OPENAI_BASE_URL"],
            api_key=self.api_key
        )

    def embed_query(self, text: str) -> List[float]:
        """
        生成输入文本的 embedding.
        Args:
            texts (str): 要生成 embedding 的文本.
        Return:
            embeddings (List[float]): 输入文本的 embedding,一个浮点数值列表.
        """
        embeddings = self.client.embeddings.create(model=self.model, input=text)
        return embeddings.data[0].embedding

    def embed_documents(self, texts: List[str]) -> List[List[float]]:
        return [self.embed_query(text) for text in texts]

    class Config:
        arbitrary_types_allowed = True


# 初始化示例选择器
example_selector = SemanticSimilarityExampleSelector.from_examples(
    samples,
    DoubaoEmbeddings(
        model=os.environ.get("EMBEDDING_MODELEND"),
    ),
    Chroma,
    k=1,
)

# 创建一个使用示例选择器的FewShotPromptTemplate对象
prompt = FewShotPromptTemplate(
    example_selector=example_selector,
    example_prompt=prompt_sample,
    suffix="鲜花类型: {flower_type}\n场合: {occasion}",
    input_variables=["flower_type", "occasion"],
)
print(prompt.format(flower_type="红玫瑰", occasion="爱情"))

注释: 1、创建示例。fewshotemplate这个模板基于示例

2、创建提示模板。说明这个fewshot是提示模板中特殊的一种,但是还是基于这个基本的提示模板上

3、创建fewshotemplate对象。参数说明:

1) examples:

-   `examples=samples`:这里的`samples`是一个包含多个示例的列表,通常是字典格式,每个字典包含与任务相关的输入和输出。例如:

    ```
    samples = [
        {"flower_type": "玫瑰", "occasion": "生日", "ad_copy": "送你一束美丽的玫瑰,祝你生日快乐!"},
        {"flower_type": "向日葵", "occasion": "毕业", "ad_copy": "祝贺你毕业,愿你的未来如向日葵般灿烂!"}
    ]
    ```

2) example_prompt:

example_prompt=prompt_sample`:这是之前定义的PromptTemplate实例,用于格式化示例。它将用于生成每个示例的文本表示。

3) suffix:

suffix="鲜花类型: {flower_type}\n场合: {occasion}"

这是在示例之后添加的后缀模板,包含两个占位符{flower_type}{occasion},用于生成最终输出时的格式。

4) input_variables:

input_variables=["flower_type", "occasion"]:指定了在生成最终输出时需要填充的输入变量,这里包括了“鲜花类型”和“场合”。

4、导入

5、示例选择器。在LangChain中,示例选择器(Example Selector)是一种用于从给定示例列表中动态选择示例的工具,特别是在使用少样本学习(Few-Shot Learning)时。以下是对LangChain中示例选择器的详细讲解。

目的

当你有大量示例时,直接将所有示例提供给语言模型可能会导致输入过长,从而超出模型的上下文窗口限制。这时,示例选择器可以帮助你从示例集中选择出最相关的几个示例,以提高模型的响应质量和效率。

基本接口

LangChain定义了一个基本的示例选择器接口BaseExampleSelector,该接口包含两个主要方法:

  1. add_example:用于向选择器中添加新的示例。
  2. select_examples:根据输入变量选择要使用的示例。

三、chain of thought

import os
os.environ["OPENAI_API_KEY"] = '你的OpenAI API Key'

# 创建聊天模型
from langchain.chat_models import ChatOpenAI
llm = ChatOpenAI(temperature=0)

# 设定 AI 的角色和目标
role_template = "你是一个为花店电商公司工作的AI助手, 你的目标是帮助客户根据他们的喜好做出明智的决定"

# CoT 的关键部分,AI 解释推理过程,并加入一些先前的对话示例(Few-Shot Learning)
cot_template = """
作为一个为花店电商公司工作的AI助手,我的目标是帮助客户根据他们的喜好做出明智的决定。 

我会按部就班的思考,先理解客户的需求,然后考虑各种鲜花的涵义,最后根据这个需求,给出我的推荐。
同时,我也会向客户解释我这样推荐的原因。

示例 1:
  人类:我想找一种象征爱情的花。
  AI:首先,我理解你正在寻找一种可以象征爱情的花。在许多文化中,红玫瑰被视为爱情的象征,这是因为它们的红色通常与热情和浓烈的感情联系在一起。因此,考虑到这一点,我会推荐红玫瑰。红玫瑰不仅能够象征爱情,同时也可以传达出强烈的感情,这是你在寻找的。

示例 2:
  人类:我想要一些独特和奇特的花。
  AI:从你的需求中,我理解你想要的是独一无二和引人注目的花朵。兰花是一种非常独特并且颜色鲜艳的花,它们在世界上的许多地方都被视为奢侈品和美的象征。因此,我建议你考虑兰花。选择兰花可以满足你对独特和奇特的要求,而且,兰花的美丽和它们所代表的力量和奢侈也可能会吸引你。
"""
from langchain.prompts import ChatPromptTemplate, HumanMessagePromptTemplate, SystemMessagePromptTemplate
system_prompt_role = SystemMessagePromptTemplate.from_template(role_template)
system_prompt_cot = SystemMessagePromptTemplate.from_template(cot_template)

# 用户的询问
human_template = "{human_input}"
human_prompt = HumanMessagePromptTemplate.from_template(human_template)

# 将以上所有信息结合为一个聊天提示
chat_prompt = ChatPromptTemplate.from_messages([system_prompt_role, system_prompt_cot, human_prompt])

prompt = chat_prompt.format_prompt(human_input="我想为我的女朋友购买一些花。她喜欢粉色和紫色。你有什么建议吗?").to_messages()

# 接收用户的询问,返回回答结果
response = llm(prompt)
print(response)