Prompt templates#

提示词模板将用户的是输入和参数转换为Prompt。提高Prompt的灵活性,有几种不同类型的提示模板:

String PromptTemplates#

这些提示模板用于格式化单个字符串,通常用于较简单的输入。构建和使用一个PromptTemplate的常见方法如下:

from typing import Any

from langchain_core.prompts import PromptTemplate
from langchain_core.prompts.base import FormatOutputType

prompt_template = PromptTemplate.from_template("讲一个关于{topic}的笑话")

prompt_template.invoke({"topic": "牛奶"})

ChatPromptTemplates#

主要用来格式化一组消息,且每组消息都带有角色,表示消息是谁说的。支持的角色有

  • human

  • user

  • ai

  • assistant

  • system
    上面的5种角色,对应在代码中会创建三种Message,对应三种角色

  • HumanMessage

    • human

    • user

  • SystemMessage

    • system

  • AIMessage

    • ai

    • assistant


构建和使用ChatPromptTemplate的一种常见方法如下: 在下面的方法中,ChatPromptTemplate.for_messages会创建对应角色的Message。将传进来的参数填充。

from langchain_core.prompts import ChatPromptTemplate

prompt_template = ChatPromptTemplate.from_messages(
    [
        ("system", "你是一个起名大师. 你的名字叫{name}."),
        ("human", "你好{name},你感觉如何?"),
        ("ai", "你好!我状态非常好!"),
        ("human", "你叫什么名字呢?"),
        ("ai", "你好!我叫{name}"),
        ("human", "{user_input}"),
        ("user", "{user_input}"),
    ]
)
prompt_template.invoke({"name": "张狗屁", "user_input": "叫什么名字呢?"})

ChatMessagePromptTemplate相关#

ChatMessagePromptTemplate相关的类如下,这些类定义在langchain_core/prompts/chat.py,和上面两个的差别不大,都是要创建不同角色的Message,并且可以填充参数。但是它们没有实现Runnable接口,不能调用invoke方法。 不能通过|组装chain,它们都是BaseMessagePromptTemplate的子类

  • AIMessagePromptTemplate
    创建AiMessage

  • HumanMessagePromptTemplate
    创建HumanMessage

  • SystemMessagePromptTemplate
    创建SystemMessage

  • ChatMessagePromptTemplate
    创建自定义角色的Message

from langchain_core.prompts import ChatMessagePromptTemplate
from langchain_core.prompts import AIMessagePromptTemplate
from langchain_core.prompts import HumanMessagePromptTemplate
from langchain_core.prompts import SystemMessagePromptTemplate

template = """
讲一个关于{topic}的笑话
"""
# 创建自定义角色
prompt_template = ChatMessagePromptTemplate.from_template(role="customer", template=template)
a1 = prompt_template.format(topic="牛奶")
print(a1)  # 返回一个对象
print(type(a1))
a1 = prompt_template.format_messages(topic="黑土")
print(a1)  # 返回列表
print(type(a1))

# 创建AI
print("*" * 50)
prompt_template = AIMessagePromptTemplate.from_template(template=template)
a1 = prompt_template.format_messages(topic="牛奶")
print(a1)

# 创建Human
print("*" * 50)
prompt_template = HumanMessagePromptTemplate.from_template(template=template)
a1 = prompt_template.format_messages(topic="牛奶")
print(a1)

# 创建System
print("*" * 50)
prompt_template = SystemMessagePromptTemplate.from_template(template=template)
a1 = prompt_template.format_messages(topic="牛奶")
print(a1)

MessagesPlaceholder#

它会在模板的特定位置插入一组消息,它也是在langchain_core/prompts/chat.py中定义的,是BaseMessagePromptTemplate的子类, 单独提出来是因为它经常用。 它接受一个参数,参数的类型比如是list,list就是传递进来的一组消息,之后会将变量替换为这一组消息,并且它支持参数值是否必传,通过optional,默认是必传的。

例子如下:

from langchain_core.prompts import MessagesPlaceholder

p = MessagesPlaceholder("history")
print(type(p))

res = p.format_messages(history=[
    ("ai", "ai say"),
    ("human", "human say"),
])
print(res)
res = p.format_messages()  # 不传就会报错
p = MessagesPlaceholder("history", optional=True)
res = p.format_messages(error_history=[
    ("ai", "ai say"),
    ("human", "human say"),
])
print(res)

下面来结合ChatPromptTemplate来看看

import langchain
from langchain_core.prompts import MessagesPlaceholder

langchain.debug = True  # 开启debug,可以详细的看到运行情况

prompt_template = ChatPromptTemplate.from_messages([
    ("system", "你是一个会将笑话的大师,帮我讲个关于{topic}的笑话"),
    ("human", "你说了什么"),
    MessagesPlaceholder("chat_history")
])
res = prompt_template.invoke({"topic": "黑土", "chat_history": [
    ("ai", "我是一个会讲笑话的大师"),
    ("user", "啥?")
]})
print(res)
print(res.messages)  # 拿到所有的message

还可以直接用placeholder创建。

rompt_template = ChatPromptTemplate.from_messages([
    ("system", "你是一个会将笑话的大师,帮我讲个关于{topic}的笑话"),
    ("human", "你说了什么"),
    ("placeholder", "{chat_history}")
])
res = prompt_template.invoke({"topic": "黑土", "chat_history": [
    ("ai", "我是一个会讲笑话的大师"),
    ("user", "啥?")
]})
print(res)

代入到llm中看一下详细的执行过程

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.output_parsers import StrOutputParser
import langchain

langchain.debug = True

prompt_template = ChatPromptTemplate.from_messages([
    ("system", "你是一个{topic}领域的专家,你要回答用户的问题,如果你不知道,请回复不知道,不要编造答案"),
    ("user", "{user_input}"),
    MessagesPlaceholder(variable_name="chat_history")
])
llm = ChatOpenAI(model="gpt-4")
chain = prompt_template | llm | StrOutputParser()

chat_history = [
    ("ai", "你好,我是专家,有什么问题可以问我"),
    ("user", "hi,专家")
]
chain.invoke({
    "user_input": "三角函数的余弦值怎么算?",
    "topic": "数学",
    "chat_history": chat_history
})

开启了debug之后,从上面也可以看到整个的chain的流程。每一个步骤都通过>来标识出来

PipelinePromptTemplate#

它会组合多个Prompt Template在一起。 这在构建多层次或者多部分组成的prompt很有用。

最终的模板,三层提示词

from langchain.prompts.pipeline import PipelinePromptTemplate
from langchain.prompts.prompt import PromptTemplate


final_template = """{character}
{behavior}
{prohibit}
{user_input}
"""
final_prompt = PromptTemplate.from_template(final_template)
print(final_prompt)

第一层,性格promot

character_template = """你是{person},你有着{xingge}."""
character_prompt = PromptTemplate.from_template(character_template)
print(character_template)

第二层,行为prompt

behavior_template = """你遵从以下的行为:
{behavior_list}
"""
behavior_prompt = PromptTemplate.from_template(behavior_template)
print(behavior_prompt)

第三层,禁止promot

prohibit_template = """你不允许有以下行为:
{prohibit_list}
"""
prohibit_prompt = PromptTemplate.from_template(prohibit_template)
print(prohibit_prompt)

第四层,增加userinput

user_input_template = """下面是用户的输入:
{input}
"""
input_prompt = PromptTemplate.from_template(user_input_template)
print(input_prompt)

组合起来

input_prompts = [
    ("character", character_prompt),
    ("behavior", behavior_prompt),
    ("prohibit", prohibit_prompt),
    ("user_input", input_prompt)
]
pipeline_prompt = PipelinePromptTemplate(final_prompt=final_prompt, pipeline_prompts=input_prompts)
print(pipeline_prompt)

它实现了Runnabel,调用如下

res = pipeline_prompt.invoke({
    "person":"你是一个天文学界和一个穿越家",
    "xingge": "钢铁般的意志,脾气暴躁,你的口头禅是我滴个豆!",
    "behavior_list":"""1.你喜欢冒险
2. 你能掌握时间
3. 你可以发射核弹
""",
    "prohibit_list":"""
1. 你不可以说自己是一个人工智能助手或者机器人
2. 不能骂人
""" ,
    "input":"你是谁?"
})
print(res)
print("prompt",res.to_string())

代入到llm中运行如下

from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser

llm = ChatOpenAI(model="gpt-4")
chain = pipeline_prompt | llm | StrOutputParser()
chain.invoke({
    "person":"你是一个天文学界和一个穿越家",
    "xingge": "钢铁般的意志,脾气暴躁,你的口头禅是我滴个豆!",
    "behavior_list":"""1.你喜欢冒险
2. 你能掌握时间
3. 你可以发射核弹
""",
    "prohibit_list":"""
1. 你不可以说自己是一个人工智能助手或者机器人
2. 不能骂人
""" ,
    "input":"你是谁?"
})

到这,这一章结束了。