← Back to 文字

PromptTemplate、Runnable 与 LCEL

本文来自《AI 应用开发课程》月份 1 课程文档,已整理为网站文章版本。

学习目标

学完本节后,你应当能够:

  • 理解 LangChain 中最值得先学的三个核心概念。
  • 用组合方式组织 Prompt、模型和解析器。
  • 把一段纯 API 调用逻辑映射到 LangChain 思路。

前置知识

  • 已理解普通 LLM 调用链

1. PromptTemplate

它的作用是把原本手工拼接的 Prompt 变成模板。

示例思路:

from langchain_core.prompts import PromptTemplate

prompt = PromptTemplate.from_template(
    "你是研发助手。请总结以下需求:\n\n{task_text}"
)

价值:

  • 模板更清晰
  • 输入变量更明确
  • 更容易复用和测试

2. Runnable

你可以把它理解为“可执行、可组合的处理单元”。

它让你可以把:

  • Prompt
  • Model
  • Parser

按流水线方式串起来。

3. LCEL

LCEL 是 LangChain 的组合表达方式。你可以把它理解为:

  • 一种声明式链路写法
  • 让不同组件通过统一协议串联

典型思路:

chain = prompt | model | parser

这比手工一步一步调用更容易看出链路结构。

4. 为什么这三个抽象值得先学

因为它们最接近你已经理解的纯 API 调用流程:

  • Prompt 如何构造
  • Model 如何调用
  • Output 如何解析

LangChain 在月份 1 的价值主要在这里,而不是在“帮你一键做完所有事情”。

5. LangChain 组合链路图

flowchart LR
    A["PromptTemplate"] --> B["Chat Model"]
    B --> C["OutputParser"]
    C --> D["结构化结果"]

6. 你应当如何使用 LangChain

  • 先用它替换一小段纯 API 逻辑
  • 再比较代码可读性和可替换性
  • 不要一开始就让整个项目都依赖它

7. 实操任务

  1. 选择一个已完成的纯 API 任务
  2. PromptTemplate 重写 prompt 构造
  3. 用 LCEL 连接模型与解析器
  4. 对比前后代码结构

8. 自测题

  1. PromptTemplate 相比手写字符串最大的好处是什么?
  2. Runnable 为组合带来了什么统一性?
  3. 为什么月份 1 不鼓励把全项目立刻“LangChain 化”?

9. 作业与验收

验收标准:

  • 至少有一段链路被改写成 prompt | model | parser
  • 你能解释每个部分承担什么职责
  • 你能说明与纯 API 实现相比的得失

10. 本章与前文关系

上一章让你从概念层理解了 LangChain 的定位,这一章开始真正动手,把你前面写过的纯 API 逻辑映射成 LangChain 的组件链。

它的目标不是让你背 API,而是让你能回答:

  • 这个组件在我之前的手写版本里对应什么
  • 它帮我节省了什么
  • 它隐藏了什么

11. 本章在研发助手项目中的位置

对于研发助手项目,最适合先用 LangChain 改写的往往不是整套系统,而是一条相对稳定的链路,例如:

  • 需求总结
  • 待办项抽取
  • 结构化分析

因为这些链路天然符合:

  • Prompt
  • Model
  • Parser

的组合结构。

12. 纯 API 与 LangChain 的一一映射

纯 API 版本里你通常这样写

  1. 拼 Prompt 字符串
  2. 调用模型
  3. 拿到文本
  4. 解析文本

LangChain 版本里你通常这样写

  1. PromptTemplate
  2. Chat Model
  3. OutputParser
  4. 用 LCEL 串起来

所以本质不是“新逻辑”,而是“把原本隐式存在的几步显式表达出来”。

13. 一个完整的对照示例

纯 API 版本

prompt = f"请总结下面的任务:\n\n{task_text}"
raw_output = await llm_client.generate(
    messages=[{"role": "user", "content": prompt}]
)
result = parse_task_analysis(raw_output)

LangChain 版本

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate


prompt = PromptTemplate.from_template(
    "请总结下面的任务:\n\n{task_text}"
)
parser = StrOutputParser()

chain = prompt | model | parser
result = chain.invoke({"task_text": task_text})

14. 为什么 LCEL 值得学

因为它让你看到一条链的真正组成,而不是把所有步骤揉在一段脚本里。

prompt | model | parser 的价值在于:

  • 可读
  • 可替换
  • 可组合

这比“几段函数随意串起来”更利于后续扩展。

15. 错误示例 vs 正确示例

错误示例:为了用 LangChain 而用 LangChain

比如把一个本来只有两步的简单逻辑,强行包得非常复杂。

正确示例:只在链路清晰受益时引入组件化表达

月份 1 的重点是理解抽象,而不是框架覆盖率。

16. 一个更接近工程的增强版理解

你可以把 Runnable 看成:

  • 可以执行
  • 可以串联
  • 可以在链路中替换

这对后面做:

  • 不同 Prompt 对照
  • 不同解析器替换
  • 不同模型封装

都很有价值。

17. 调试与排错:本章最常见问题

问题一:不知道链路里到底哪一步出错

这反而说明你还没真的把 promptmodelparser 视为不同组件。要重新把职责拆开理解。

问题二:一上来就全项目改成 LangChain

这会让你失去和纯 API 的对照能力。

问题三:只记语法,不做对照实验

那样你学到的只是表面写法,而不是框架思维。

18. 本章完成后你应该具备的能力

完成本章后,你应当做到:

  1. 能把一条纯 API 链路翻译成 LCEL。
  2. 能说清 PromptTemplateRunnableOutputParser 各自位置。
  3. 能判断什么时候值得引入组件化。

19. 如果你卡在这里,先回看哪几章

20. 从本章过渡到下一章的桥接说明

接下来进入 03-OutputParser与Tool封装.md

因为你现在已经把“Prompt + Model + Parser”链路串起来了,下一步自然就是去看:

  • Parser 在结构化输出中到底解决什么问题
  • Tool 在 LangChain 里如何映射你已经手写过的工具系统

这会让你把 LangChain 和月份 1 前面的原生实现真正对齐。

Fin