第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

这表示:

  1. 输入首先传递给 component_A
  2. component_A 的输出作为输入传递给 component_B
  3. component_B 的输出作为输入传递给 component_C
  4. 整个 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方法中传入参数。