AI--LangChain进阶(一)

AI–LangChain进阶(一)

1.PromptTemplate

  PromptTemplate:通用提示词模版,支持动态注入信息

  提示词优化在模型应用中非常重要,LangChain提供了PromptTemplate类,用来协助优化提示词,PromptTemplate表示提示词模版,可以构建一个自定义的基础提示词模版,支持变量的注入,最终生成所需要的提示词,这里有两种写法,一种是标准写法,一种是基于chain链的写法

  • 标准写法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#标准的提示词模版
import os
from langchain_core.prompts import PromptTemplate
from langchain_community.llms.tongyi import Tongyi

os.environ["DASHSCOPE_API_KEY"] = "key"

prompt_template = PromptTemplate.from_template(
"我的邻居姓{lastname}, 刚生了{gender}, 帮忙起名字, 请简略回答。"
)

prompt_text = prompt_template.format(lastname="张", gender="女儿")
model = Tongyi(model="qwen-max") # 创建模型对象
res = model.invoke(input=prompt_text) # 调用模型获取结果
print(res)
  • 基于chain链的写法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#基于chain链的提示词模版
import os
from langchain_core.prompts import PromptTemplate
from langchain_community.llms.tongyi import Tongyi

os.environ["DASHSCOPE_API_KEY"] = "key"

prompt_template = PromptTemplate.from_template(
"我的邻居姓{lastname}, 刚生了{gender}, 帮忙起名字, 请简略回答。"
)

model = Tongyi(model="qwen-max") # 创建模型对象

chain = prompt_template | model

res = chain.invoke(input={"lastname": "曹", "gender": "女儿"})
print(res)

2.FewShotPromptTemplate

  FewShotPromptTemplate:支持基于模版注入容易数量的示例信息

  在提示词工程中我们有提到两种思想的提示词,既然有Zero-Shot则必然有对应的Few-Shot,在LangChain中使用的对应模块则是FewShotPromptTemlate

1
2
3
4
5
6
7
FewShotPromptTemplate(
examples=None, #示例数据,list,内套字典
example_prompt=None, #示例提示词模版
prefix=None, #组装提示词,示例数据前的内容
suffix=None, #组装提示词,示例数据后的内容
input_variables=None, #输入变量,list, 与示例数据的key对应
)

  这里举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import os
from langchain_community.chat_models.tongyi import ChatTongyi
from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate

os.environ["DASHSCOPE_API_KEY"] = "key"

# 初始化模型
chat = ChatTongyi(model="qwen-max")

example_template = PromptTemplate.from_template(
"单词:{word}\n反义词:{antonym}"
)

example_data = [
{"word": "热", "antonym": "冷"},
{"word": "大", "antonym": "小"},
{"word": "快", "antonym": "慢"},
]

few_shot_prompt = FewShotPromptTemplate(
examples=example_data, #示例数据,list,内套字典
example_prompt=example_template, #示例提示词模版
prefix="请给出每个单词的反义词:,有如下示例:\n", #组装提示词,示例数据前的内容
suffix="基于示例得知,{input_word}的反义词是:", #组装提示词,示例数据后的内容
input_variables=["input_word"], #输入变量,list, 与示例数据的key对应
)

# 调用模型
prompt_text = few_shot_prompt.format(input_word="左")
for chunk in chat.stream(input=prompt_text):
print(chunk.content, end="", flush=True)

print("\n-----------------")

  

3.format和invoke

  这两个玩意其实是提示词内容的填充方式,在我们所提到的三种提示词方法中都支持这两种,因为历史原因,三种提示词方法都能兼容这两种填充方式

  主要对比区别在于:

    如果我们对返回值可以接受是字符串的话使用format就没有问题,但是当后续我们需要用到chain链的时候,就需要使用invoke进行操作了,所以在正式的 LangChain 开发中,推荐优先使用invoke,因为它是框架统一的标准接口,兼容性更好

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from langchain_core.prompts import PromptTemplate
from langchain_core.prompts import FewShotPromptTemplate
from langchain_core.prompts import ChatPromptTemplate

"""
PromptTemplate -> StringPromptTemplate -> BasePromptTemplate -> RunnableSerializable -> Runnable
FewShotPromptTemplate -> StringPromptTemplate -> BasePromptTemplate -> RunnableSerializable -> Runnable
ChatPromptTemplate -> BaseChatPromptTemplate -> BasePromptTemplate -> RunnableSerializable -> Runnable
"""

template = PromptTemplate.from_template("我的邻居是,{neighbor},最喜欢,{favorite}")

res1 = template.format(neighbor="撩月", favorite="摄影")
print(res1, type(res1))

res2 = template.invoke(input={"neighbor": "撩月", "favorite": "摄影"})
print(res2, type(res2))

4.ChatPromptTemplate

  ChatPromptTemplate:支持注入任意数量的历史会话信息

  在前面学到的两种提示词模版中,只能接入少量的信息,而 ChatPromptTemplate通过from_messages方法,从列表中获取多轮次会话作为聊天的基础模版

1
2
3
4
5
6
7
8
from langchain_core.prompts import ChatPromptTemplate

ChatPromptTemplate.from_messages([
("system", "你是一个专业的翻译"),
("human", "你好"),
("ai", "Hello"),
("human", "{input}"),
])

  但是如果没有信息能够动态注入的话明显是不够的,所以这里引入MessagesPlaceholder,他作为占位符,提供history作为占位的key,最后基于invoke动态注入历史会话记录中,需要注意的是,这里必须是invoke,format是无法注入的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.prompts import MessagesPlaceholder
from langchain_community.chat_models.tongyi import ChatTongyi
import os

os.environ["DASHSCOPE_API_KEY"] = "key"

chat_template = ChatPromptTemplate.from_messages([
("system", "你是一个边塞诗人,可以作诗"),
MessagesPlaceholder("history"),
("human", "请再来一首唐诗"),
])

history_data = [
("human", "你来写一个唐诗"),
("ai", "床前明月光,疑是地上霜,举头望明月,低头思故乡。"),
("human", "好诗,再来一首"),
("ai", "锄禾日当午,汗滴禾下土,谁知盘中餐,粒粒皆辛苦。"),
]

# 需要同时传入 history 和 input
prompt = chat_template.invoke({"history": history_data}).to_string()

# 规范输出:只打印消息内容
print(prompt)

model = ChatTongyi(model="qwen-max")

res = model.invoke(prompt)
print(res.content)

5.Chain的基础使用

  将组件串联,上一个组件的输出作为下一个组件的输入,是LangChain链的核心工作原理,这也是链式调用的核心价值,实现数据的自动化流转与组件的协同工作,例如:

1
chain = promot_template | model

  这里需要注意有一个核心前提,即需要是Runnable子类对象才能入链(Callable Mapping接口子类对象也可以接入,不过目前用的不多),前面所列举的组件均是Runnable接口的子类,如下类的继承关系:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import os
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.prompts import MessagesPlaceholder
from langchain_community.chat_models.tongyi import ChatTongyi
from langchain_core.runnables.base import RunnableSerializable

os.environ["DASHSCOPE_API_KEY"] = "key"

chat_template = ChatPromptTemplate.from_messages([
("system", "你是一个边塞诗人,可以作诗"),
MessagesPlaceholder("history"),
("human", "请再来一首唐诗"),
])

history_data = [
("human", "你来写一个唐诗"),
("ai", "床前明月光,疑是地上霜,举头望明月,低头思故乡。"),
("human", "好诗,再来一首"),
("ai", "锄禾日当午,汗滴禾下土,谁知盘中餐,粒粒皆辛苦。"),
]

model = ChatTongyi(model="qwen-max")

#chain : RunnableSerializable = chat_template | model
chain = chat_template | model
print(type(chain))

res = chain.invoke(input={"history": history_data})
print(res.content)

for chunk in chain.stream(input={"history": history_data}):
print(chunk.content, end="", flush=True)

  在构造链后,我们就可以通过链调用invoke或者stream触发整个链条的执行,前面代码执行的流程如下:


AI--LangChain进阶(一)
https://one-null-pointer.github.io/2026/01/11/AI --LangChain进阶(一)/
Author
liaoyue
Posted on
January 11, 2026
传送口