☰
四、LangChain——三大提示词模板的使用(PromptTemplate、FewShotPromptTemplate和ChatPromptTemplate)
2026/10/25 19:41:18 网站建设 项目流程

一、PromptTemplate(通用提示词模板)

LangChain提供了PromptTemplate类,用来协助优化提示词
PromptTemplate表示提示词模板,可以构建一个自定义的基础提示词模板,支持变量的注入,最终生成所需的提示词

zone-shot思想:没有任何提示,完全基于模型内部训练的数据完成答复,完全信赖模型

1. 标准写法

Ⅰ 提示词文本占位测试

PromptTemplate通过from_template来创建带有占位符的字符串提示词
通过format对PromptTemplate对象的占位字符串提示词赋值

导包:from langchain_core.prompts import PromptTemplate

# 导包fromlangchain_core.promptsimportPromptTemplate prompt_template=PromptTemplate.from_template("我最喜欢的乐队是{bandname},我最喜欢的歌手是{singer},可以帮我简单介绍一下嘛?")# 调用.format方法注入信息prompt_text=prompt_template.format(bandname="beyond",singer="黄家驹")print(prompt_text)# 我最喜欢的乐队是beyond,我最喜欢的歌手是黄家驹,可以帮我简单介绍一下嘛?
Ⅱ 完整示例

有了上面的占位符的测试,可以拿到完整的字符串提示词,喂给大模型即可

# 标准写法fromlangchain_core.promptsimportPromptTemplatefromlangchain_ollamaimportOllamaLLM''' # 和romptTemplate.from_template看起来比较类似,但没办法加入Chain链 # PromptTemplate.from_templat得到是PromptTemplate类对象,可以加入到链中,但字符串不可以 bandname="beyond", singer="黄家驹" prompt_text = f"我最喜欢的乐队是{bandname},我最喜欢的歌手是{singer},可以帮我简单介绍一下嘛?" '''prompt_template=PromptTemplate.from_template("我最喜欢的乐队是{bandname},我最喜欢的歌手是{singer},可以帮我简单介绍一下嘛?")# 调用.format方法注入信息prompt_text=prompt_template.format(bandname="beyond",singer="黄家驹")print(prompt_text)# 我最喜欢的乐队是beyond,我最喜欢的歌手是黄家驹,可以帮我简单介绍一下嘛?model=OllamaLLM(model="gemma4:12b")res=model.stream(input=prompt_text)forchunkinres:print(chunk,end="",flush=True)

2. 基于Chain链写法

chain = prompt_template | model,将prompt_template作为输出作为model的输入
chain.stream(input={"bandname": "beyond","singer":"黄家驹"})喂给模型的时候,加入对应prompt_template的占位值

完整流程:chain = prompt_template | model
①chain.stream(input={"bandname": "beyond","singer":"黄家驹"}),拿到占位值
②填充PromptTemplate.from_template里面的字符串对应的占位符的值,得到完整的prompt
③将完整的prompt喂给model

fromlangchain_core.promptsimportPromptTemplatefromlangchain_ollamaimportOllamaLLM prompt_template=PromptTemplate.from_template("我最喜欢的乐队是{bandname},我最喜欢的歌手是{singer},可以帮我简单介绍一下嘛?")model=OllamaLLM(model="gemma4:12b")chain=prompt_template|model res=chain.stream(input={"bandname":"beyond","singer":"黄家驹"})forchunkinres:print(chunk,end="",flush=True)

3. 小结

基于PromptTemplate类可以得到提示词模板,支持基于模板注入变量得到最终提示词。

  • zero-shot思想(不给任何提示,全靠模型输出),可以基于PromptTemplate直接完成
  • few-shot思想(给少量的demo,供模型参考),需要更换为FewShotPromptTemplate

使用PromptTemplate类的优势:

  • 使用Template模板构建提示词,在大型工程中更容易做标准化模板
  • Template模板类,支持LangChain框架的链式调用(Runnable接口等);字符串没办法加入chain
    • PromptTemplate
    • FewShotPromptTemplate
    • ChatPromptTemplate

二、FewShotPromptTemplate(FewShot提示词模板)

导包:from langchain_core.prompts import FewShotPromptTemplate

1. 基本格式

FewShotPromptTemplate(example_prompt=None,# 示例数据的模板,list,内套字典examples=None,# 示例的数据,用来注入动态数据,list内嵌套字典prefix=None,# 示例之前的提示词suffix=None,# 示例之后的提示词input_variables=None# 声明在前缀或后缀中所需要注入的变量名)

2. 提示词文本占位测试

fromlangchain_core.promptsimportPromptTemplate,FewShotPromptTemplate# 示例模板example_template=PromptTemplate.from_template("心情: {feel}, 听歌:{song}")# 示例动态数据注入,必须是list内部嵌套字典;后续不需要动模板,直接在这里加数据即可examples_data=[{"feel":"犹豫不决","song":"不再犹豫"},{"feel":"想妈妈了","song":"真的爱你"},{"feel":"失恋","song":"喜欢你"}]few_shot_template=FewShotPromptTemplate(example_prompt=example_template,# 示例数据的模板examples=examples_data,# 示例的数据,用来注入动态数据,list内嵌套字典prefix="我是beyond的fan,当处于某种心情时应该听beyond的哪些歌,给你如下的示例:",# 示例之前的提示词suffix="基于上面的示例,请告诉我当我的心情是{now_feel}时,我应该听beyond的什么歌?",# 示例之后的提示词input_variables=['now_feel']# 声明在前缀或后缀中所需要注入的变量名)prompt_text=few_shot_template.invoke(input={"now_feel":"开心"}).to_string()print(prompt_text)

运行内容:

有了提示词,直接喂给模型即可

3. 完整示例

fromlangchain_core.promptsimportPromptTemplate,FewShotPromptTemplatefromlangchain_ollamaimportOllamaLLM# 示例模板example_template=PromptTemplate.from_template("心情: {feel}, 听歌:{song}")# 示例动态数据注入,必须是list内部嵌套字典;后续不需要动模板,直接在这里加数据即可examples_data=[{"feel":"犹豫不决","song":"不再犹豫"},{"feel":"想妈妈了","song":"真的爱你"},{"feel":"失恋","song":"喜欢你"}]few_shot_template=FewShotPromptTemplate(example_prompt=example_template,# 示例数据的模板examples=examples_data,# 示例的数据,用来注入动态数据,list内嵌套字典prefix="我是beyond的fan,当处于某种心情时应该听beyond的哪些歌,给你如下的示例:",# 示例之前的提示词suffix="基于上面的示例,请告诉我当我的心情是{now_feel}时,我应该听beyond的什么歌?",# 示例之后的提示词input_variables=['now_feel']# 声明在前缀或后缀中所需要注入的变量名)prompt_text=few_shot_template.invoke(input={"now_feel":"开心"}).to_string()model=OllamaLLM(model="gemma4:12b")res=model.stream(input=prompt_text)forchunkinres:print(chunk,end="",flush=True)

运行结果:

4. 小结

FewShotPromptTemplate类对象构建需要五个核心参数

  • example_prompt: 示例数据的提示词模板
  • examples: 示例数据,list内嵌字典
  • prefix: 组装提示词,示例数据前内容
  • suffix: 组装提示词,示例数据后内容
  • input_variables: 列表,注入的变量列表

三、模板类的format和invoke方法

1. 模板对象的format方法

prompt_template.format

prompt_template=PromptTemplate.from_template("我最喜欢的乐队是{bandname},我最喜欢的歌手是{singer},可以帮我简单介绍一下嘛?")# 调用.format方法注入信息prompt_text=prompt_template.format(bandname="beyond",singer="黄家驹")

2. 模板对象的invoke方法

few_shot_template.invoke

# 示例模板example_template=PromptTemplate.from_template("心情: {feel}, 听歌:{song}")# 示例动态数据注入,必须是list内部嵌套字典;后续不需要动模板,直接在这里加数据即可examples_data=[{"feel":"犹豫不决","song":"不再犹豫"},{"feel":"想妈妈了","song":"真的爱你"},{"feel":"失恋","song":"喜欢你"}]few_shot_template=FewShotPromptTemplate(example_prompt=example_template,# 示例数据的模板examples=examples_data,# 示例的数据,用来注入动态数据,list内嵌套字典prefix="我是beyond的fan,当处于某种心情时应该听beyond的哪些歌,给你如下的示例:",# 示例之前的提示词suffix="基于上面的示例,请告诉我当我的心情是{now_feel}时,我应该听beyond的什么歌?",# 示例之后的提示词input_variables=['now_feel']# 声明在前缀或后缀中所需要注入的变量名)prompt_text=few_shot_template.invoke(input={"now_feel":"开心"}).to_string()

3. format和invoke的区别关系

PromptTemplate、FewShotPromptTemplate和ChatPromptTemplate这些类对象都有format和invoke这两个方法

Ⅰ 继承关系

Ⅱ 区别
区别formatinvoke
功能纯字符串替换,解析占位符生成提示词Runnable接口标准方法,解析占位符生成提示词
返回值字符串PromptValue类对象,通过.to_string()转换为字符串
传参.format(k1=v1, k2=v2, ...).invoke({"k1":v1, "k2":v2, ...})
解析支持解析{}占位符支持解析{}占位符和MessagesPlaceholder结构化占位符
Ⅲ 代码验证
①format方法

三个类的继承关系,最终都是继承BasePromptTemplate

PromptTemplate->StringPromptTemplate->BasePromptTemplate FewShotPromptTemplate->StringPromptTemplate->BasePromptTemplate ChatPromptTemplate->BaseChatPromptTemplate->BasePromptTemplate

BasePromptTemplate的format是个抽象方法,故子类必须去实现

②invoke方法
...->BasePromptTemplate->RunnableSerializable->Runnable

BasePromptTemplate类下有个RunnableSerializable

这个RunnableSerializable继承了Runnable

Runnab类下有一个抽象的invoke方法

③format返回值——纯字符串

template.format的返回值是纯字符串,<class 'str'>

fromlangchain_core.promptsimportPromptTemplatefromlangchain_core.promptsimportFewShotPromptTemplatefromlangchain_core.promptsimportChatPromptTemplate template=PromptTemplate.from_template("Beyond的核心成员{name},代表作{sing}")res=template.format(name="黄家驹",sing="《海阔天空》")print(res,type(res))# Beyond的核心成员黄家驹,代表作《海阔天空》 <class 'str'>
④invoke返回值——类对象

template.invoke的返回值是PromptTemplate类对象,<class 'langchain_core.prompt_values.StringPromptValue'>

fromlangchain_core.promptsimportPromptTemplatefromlangchain_core.promptsimportFewShotPromptTemplatefromlangchain_core.promptsimportChatPromptTemplate template=PromptTemplate.from_template("Beyond的核心成员{name},代表作{sing}")res2=template.invoke({"name":"黄家强","sing":"《冷雨夜》"})print(res2,type(res2))# text='Beyond的核心成员黄家强,代表作《冷雨夜》' <class 'langchain_core.prompt_values.StringPromptValue'>

四、ChatPromptTemplate(聊天提示词模板)

1. 介绍

PromptTemplate:通用提示词模板,支持动态注入信息
FewShotPromptTemplate:支持基于模板注入任意数量的示例信息
ChatPromptTemplate:支持注入任意数量的历史会话信息

通过from_messages方法,从列表中获取多轮次会话作为聊天的基础模板

  • PromptTemplate类用的from_template仅能接入一条消息
  • ChatPromptTemplate类用的from_messages可以接入一个list的消息

2. 静态注入版本

导包:from langchain_core.prompts import ChatPromptTemplate

fromlangchain_core.promptsimportChatPromptTemplate ChatPromptTemplate.from_messages([("system","你是一个民谣歌手"),("ai","ok,我已经明白我的身份"),("human","来一首民谣")]

历史会话信息并不是静态的(固定的),而是随着对话的进行不停地积攒,即动态的,所以,历史会话信息需要支持动态注入

3. 动态注入版本

导包:from langchain_core.prompts import MessagesPlaceholder, ChatPromptTemplate,注意,多了MessagesPlaceholder

MessagesPlaceholder提供history作为占位的key
基于invoke动态注入历史会话记录,必须是invoke,format返回值是纯字符串,故无法注入

fromlangchain_core.promptsimportMessagesPlaceholder,ChatPromptTemplate chat_prompt_template=ChatPromptTemplate.from_messages([("system","你是一个民谣歌手"),MessagesPlaceholder("history"),("human","再来一首民谣")])history_data=[("human","来首伤感民谣"),("ai","我知道,那些夏天,就像青春一样回不来,我也不会再对谁满怀期待"),("human","很好听,再来一首"),("ai","青春又醉倒在,岌岌无名的坏,靠嬉笑来度过,这破碎的年代")]prompt_text=chat_prompt_template.invoke({"history":history_data}).to_string()

4. 完整动态注入版本

Ⅰ 提示词文本占位测试

fromlangchain_core.promptsimportMessagesPlaceholder,ChatPromptTemplate chat_prompt_template=ChatPromptTemplate.from_messages([("system","你是一个民谣歌手"),MessagesPlaceholder("history"),("human","再来一首民谣")])history_data=[("human","来首伤感民谣"),("ai","我知道,那些夏天,就像青春一样回不来,我也不会再对谁满怀期待"),("human","很好听,再来一首"),("ai","青春又醉倒在,岌岌无名的坏,靠嬉笑来度过,这破碎的年代")]prompt_text=chat_prompt_template.invoke({"history":history_data}).to_string()print(prompt_text,type(prompt_text))

运行内容:

提示词没问题后,丢给模型就行

Ⅱ 完整代码

fromlangchain_core.promptsimportMessagesPlaceholder,ChatPromptTemplatefromlangchain_ollamaimportChatOllama chat_prompt_template=ChatPromptTemplate.from_messages([("system","你是一个民谣歌手"),MessagesPlaceholder("history"),("human","再来一首民谣")])history_data=[("human","来首伤感民谣"),("ai","我知道,那些夏天,就像青春一样回不来,我也不会再对谁满怀期待"),("human","很好听,再来一首"),("ai","青春又醉倒在,岌岌无名的坏,靠嬉笑来度过,这破碎的年代")]prompt_text=chat_prompt_template.invoke({"history":history_data}).to_string()model=ChatOllama(model="gemma4:12b")res=model.invoke(prompt_text)print(res.content,type(res))# 因为model.invoke返回的是一个对象,里面内容很多,其中content为模型的输出内容,故这里只拿有用的信息输出""" # 也可以用stream流式输出 res = model.stream(prompt_text) print(res, type(res)) for chunk in res: print(chunk, end="", flush=True) """

运行结果:

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询