第3节:链与提示词模板
1. 链
上一节我们接入大模型之后,是通过下面的方式给AI输入提示词的
prompt = "你是谁"
response = llm.invoke(prompt);
print(response.content)
在实际开发中,为了让提示词更加灵活,我们会把提示词下载一个提示词模板组件中,示例代码如下
# 引入提示词模板
from langchain.prompts import ChatPromptTemplate
# 创建一个提示词模板组件
prompt = ChatPromptTemplate("你是谁?")
那么如何给大模型发送这段提示词呢,可以使用langchian的“链”功能,代码如下:
chain = prompt | llm
response = chain.invoke({})
print(response.content)
代码中的chain = prompt | model
是链的概念
在 LangChain 中,链可以将多个组件(如模型、提示模板、解析器、检索器、工具、智能体等)组合起来,按特定顺序执行,以完成更复杂任务的逻辑单元。
这是LangChain的表达式语言 ,简称LCEL
LCEL 的核心是 |
(管道) 操作符,类似于 Unix/Linux 中的管道命令。它允许你将一个组件的输出"流"向下传递给下一个组件作为输入。
基本语法:
chain = component_A | component_B | component_C
这表示:
- 输入首先传递给
component_A
。 component_A
的输出作为输入传递给component_B
。component_B
的输出作为输入传递给component_C
。- 整个
chain
的最终输出是component_C
的输出。
因此示例代码chain = prompt | model
的作用是当执行chain.invoke()
的时候,从左到右依次调用组件,第一个组件的参数是invoke传递的参数,后续每一个组件的输入都是前一个组件的输出,一直到最后一组件返回结果。
Runnable 接口:
LangChain 中几乎所有的核心组件(PromptTemplates, Models, OutputParsers, Retrievers 等)都实现了Runnable接口,这样组件就有了公用的属性和方法,可以无缝地用 |
连接起来。
常用的 Runnable 方法:
invoke(input)
: 对单个输入调用链。batch(list_of_inputs)
: 对输入列表进行批量调用(通常更高效)。stream(input)
: 流式处理输入,逐步返回输出块(对于生成长文本很有用)。astream(input)
: 异步版本的stream
。ainvoke(input)
: 异步版本的invoke
。abatch(list_of_inputs)
: 异步版本的batch
。
LCEL 的优势:
- 简洁直观: 使用
|
操作符使得链的结构清晰易懂。 - 类型安全: LangChain 会尝试进行类型检查,减少运行时错误。
- 灵活性: 可以轻松组合各种组件,包括自定义函数(使用
RunnableLambda
)。 - 可组合性: 一个 LCEL 链本身也是一个 Runnable,可以嵌套在其他链中。
- 内置优化: 支持并行执行、批处理、流式输出和异步操作。
- 可观测性: 与 LangSmith 等工具集成良好,方便调试和追踪。
2. 提示词模板
了解了链的概念之后,我们接着看提示词模板,可以在ChatPromptTemplate
方法中进一步划分系统提示词和用户提示词。系统提示词用来设置提问的背景,用户提示词用来描述具体问题。示例代码如下:
prompt = ChatPromptTemplate([
("system", "你是一个擅长心理学的学习助手,帮我用心理学的理论知识解决我学习过程中的困惑"),
("user", "{input}")
])
chain = prompt | llm
response = chain.invoke({"input": "我为什么学习不好"})
print(response.content)
可以看到,提示中可以通过{parms}
的形式定义参数。在invoke
方法中传入参数。