文章目录
前置体验
PromptTemplate【字符串模板替换】
from langchain_core.prompts import PromptTemplate
prompt_template = PromptTemplate.from_template("我今天心情{feel},我想{content}")
message = prompt_template.format(feel = "非常开心",content = "去吃一顿火锅好好庆祝一下")
print(message)
我今天心情非常开心,我想去吃一顿火锅好好庆祝一下
给变量feel和content赋值,达到动态输出内容
ChatPromptTemplate【具有角色的模板替换】
注意:需要在.env文件中设置
OPENAI_API_KEY=sk-XXXXXXXXXXXXXXXX
OPENAI_API_BASE=https://xxx
from dotenv import load_dotenv, find_dotenv
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
load_dotenv(find_dotenv())
chat_prompt_template = ChatPromptTemplate.from_messages(
[
("system","你是一个厨师"),
("human","{user_input}")
]
)
model = ChatOpenAI()
chain = chat_prompt_template | model
response = chain.invoke({
"user_input":"你会做什么饭?"})
print(response.content)
我可以做各种不同类型的菜肴,包括中式、西式、日式、意式等等。无论是炒菜、烤肉、炖汤、烘培,我都可以应对。我也可以根据你的口味和饮食习惯来调整菜谱,让你的用餐体验更加愉快。
什么是提示工程(Prompt Engineering)
我们发给大模型的指令就叫提示词,比如:
【我今天心情不好,讲一个笑话给我听】
【我女朋友生气了,怎么哄好她】
【我的代码出现问题了,报这个错误,怎么解决】
这些都叫做提示词。
案例体验
哄哄模拟器 ,不知道怎么哄好女朋友的可以提前练习一下。
地址:https://hong.greatdk.com/
Prompt调优
找到好的 prompt 是个持续迭代的过程,需要不断调优。
如果知道训练数据是怎样的,参考训练数据来构造 prompt 是最好的。
「当人看」类比:
你知道 ta 喜欢三国演义,就和 ta 聊三国演义
你知道 ta 是个吃货,就和 ta 说美食
你知道 ta 喜欢健身,就夸 ta 身材好
Prompt 的典型构成
角色:指定具体的角色
指示:对任务进行描述
上下文:给出与任务相关的其它背景信息(尤其在多轮交互中)
例子:必要时给出举例
输入:任务的输入信息;在提示词中明确的标识出输入
输出:输出的格式描述,以便后继模块自动解析模型的输出结果,比如(JSON、XML)
如果换做成生活中,我们如何和别人沟通,同样都是确定好彼此的角色
如果我参观动物园的大熊猫,但是不知道具体位置,就要和工作人员沟通
描述好我的诉求,并且告诉 ta 我希望得到什么样的结果
【推荐流量包的智能客服】调优案例
某运营商的流量包产品:
名称 | 流量(G/月) | 价格(元/月) | 适用人群 |
---|---|---|---|
经济套餐 | 10 | 50 | 无限制 |
畅游套餐 | 100 | 180 | 无限制 |
无限套餐 | 1000 | 300 | 无限制 |
校园套餐 | 200 | 150 | 在校生 |
需求:智能客服根据用户的咨询,推荐最适合的流量包。
导入依赖
from dotenv import find_dotenv, load_dotenv
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
加载.env环境变量设置
load_dotenv(find_dotenv())
任务描述、用户输入、输出格式、模板定义
# 任务描述
instruction = """
你的任务是识别用户对手机流量套餐产品的选择条件。
每种流量套餐产品包含三个属性:名称,月费价格,月流量。
根据用户输入,识别用户在上述三种属性上的需求是什么。
"""
#输出格式
output_format = """
以 JSON 格式输出
"""
# 用户输入
input_text = """
办个100G的套餐。
"""
template = """
{instruction}
{output_format}
用户输入:
{input_text}
"""
设置chain并测试结果
prompt = ChatPromptTemplate.from_template(template)
llm = ChatOpenAI()
out = StrOutputParser()
chain =prompt | llm | out
message = chain.invoke(
{
"instruction": instruction,
"output_format": output_format,
"input_text": input_text
}
)
print(message)
输出结果
{
"需求": {
"名称": null,
"月费价格": null,
"月流量": "100G"
}
}
大模型是懂 JSON 的,但需要对 JSON 结构做严格定义。
把输出格式定义的更精细再试试呢
【改进】增加输出格式
from dotenv import find_dotenv, load_dotenv
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
from langchain_openai import ChatOpenAI
load_dotenv(find_dotenv())
# 任务描述
instruction = """
你的任务是识别用户对手机流量套餐产品的选择条件。
每种流量套餐产品包含三个属性:名称(name),月费价格(price),月流量(data)。
根据用户输入,识别用户在上述三种属性上的需求是什么,符合哪个套餐。
已知产品包括:
经济套餐:月费50元,月流量10G
畅游套餐:月费180元,月流量100G
无限套餐:月费300元,月流量1000G
校园套餐:月费150元,月流量200G,限在校学生办理
"""
#输出格式
output_format = """
以JSON格式输出。
1. name字段的取值为string类型,取值必须为以下之一:经济套餐、畅游套餐、无限套餐、校园套餐 或 null;
2. price字段的取值为套餐的价格
3. data字段的取值为取值为一个结构体 或 null,包含两个字段:
(1) operator, string类型,取值范围:'<='(小于等于), '>=' (大于等于), '=='(等于)
(2) value, int类型或string类型,string类型只能是'无上限'
4. 用户的意图可以包含按price或data排序,以sort字段标识,取值为一个结构体:
(1) 结构体中以"ordering"="descend"表示按降序排序,以"value"字段存储待排序的字段
(2) 结构体中以"ordering"="ascend"表示按升序排序,以"value"字段存储待排序的字段
只输出中只包含用户提及的字段,不要猜测任何用户未直接提及的字段。
"""
# 用户输入
input_text = """
办个200G的套餐。
"""
template = """
{instruction}
{output_format}
用户输入:
{input_text}
"""
prompt = ChatPromptTemplate.from_template(template)
llm = ChatOpenAI()
out = StrOutputParser()
chain = prompt | llm | out
print("任务描述:" + instruction)
for c in range(5):
print(f"=====