文章目录
- [1. 什么是 LangChain?为什么需要它?](#1. 什么是 LangChain?为什么需要它?)
-
- [1.1 大模型开发的挑战](#1.1 大模型开发的挑战)
- [1.2 LangChain 的定位](#1.2 LangChain 的定位)
- [2. 环境准备 (Prerequisites)](#2. 环境准备 (Prerequisites))
-
- [2.1 安装](#2.1 安装)
- [2.2 配置 API Key](#2.2 配置 API Key)
- [3. 模型交互:ChatModel 基础](#3. 模型交互:ChatModel 基础)
-
- [3.1 定义模型](#3.1 定义模型)
- [3.2 消息体系 (Message Types)](#3.2 消息体系 (Message Types))
- [4. 核心语法:LCEL (LangChain Expression Language)](#4. 核心语法:LCEL (LangChain Expression Language))
-
- [4.1 为什么要用 LCEL?](#4.1 为什么要用 LCEL?)
- [4.2 动手写第一条链](#4.2 动手写第一条链)
- [4.3 Runnable 协议详解](#4.3 Runnable 协议详解)
- [5. 提升体验:流式传输 (Streaming)](#5. 提升体验:流式传输 (Streaming))
-
- [5.1 同步流式 (`.stream`)](#5.1 同步流式 (
.stream)) - [5.2 异步流式 (`.astream`) - Web 开发必备](#5.2 异步流式 (
.astream) - Web 开发必备)
- [5.1 同步流式 (`.stream`)](#5.1 同步流式 (
摘要:本篇作为系列开篇,将带你从零认识 LangChain,了解它如何简化大模型应用开发。我们将重点掌握 LangChain 的"现代语法"------LCEL,并手写第一个支持流式输出的对话应用。
适合人群:LangChain 初学者、希望从旧版 Chain 迁移到新版的开发者。
1. 什么是 LangChain?为什么需要它?
1.1 大模型开发的挑战
直接调用 OpenAI 的 API 并不难,写几行 requests 或者用官方 SDK 都能做到。但在开发复杂的 LLM 应用(如 RAG、智能体)时,我们很快会遇到以下痛点:
- 模型碎片化:想把 GPT-4 换成 Claude 3 或本地的 Llama 3,API 格式完全不同,代码要重写。
- 数据连接难:如何优雅地把 PDF、数据库、网页内容塞给大模型?
- 流程编排乱:先去搜索,整理结果,再生成回答,这中间的数据流转代码很容易写成"面条代码"。
1.2 LangChain 的定位
LangChain 就是为了解决这些问题而生的编排框架。它提供了一套标准化的接口:
- 统一接口 (Model I/O):无论你是调 OpenAI 还是通义千问,代码写法完全一样。
- 数据连接 (Retrieval):内置 100+ 种加载器,轻松连接私有数据。
- 链式编排 (Chains):像搭积木一样组合不同的组件。
2. 环境准备 (Prerequisites)
在开始写代码前,让我们先搞定环境。
2.1 安装
推荐使用 Python 3.9+ 环境。LangChain 已拆分为多个包,我们主要安装核心包和 OpenAI 适配包。
bash
pip install langchain langchain-openai langchain-community
2.2 配置 API Key
LangChain 默认会从环境变量中读取 API Key。建立一个 .env 文件或直接在终端设置:
python
import os
# 替换为你的 API Key
os.environ["OPENAI_API_KEY"] = "sk-..."
# 如果你需要使用国内的中转服务,可以设置 Base URL
# os.environ["OPENAI_API_BASE"] = "https://api.your-proxy.com/v1"
3. 模型交互:ChatModel 基础
LangChain 中主要有两种模型对象:LLM (纯文本补全) 和 ChatModel (对话模型)。现在主流大模型(如 GPT-4)都是 ChatModel。
3.1 定义模型
python
from langchain_openai import ChatOpenAI
# model: 指定模型版本,如 gpt-4o-mini, gpt-3.5-turbo
# temperature: 创新性控制 (0-2)。0 表示最保守、确定;1 表示有创意。
# max_tokens: 限制回复的最大长度,防止 token 耗尽。
model = ChatOpenAI(
model="gpt-4o-mini",
temperature=0.7,
max_tokens=500
)
3.2 消息体系 (Message Types)
对话模型不接受单一字符串,而是接受一个"消息列表"。这模拟了真实的对话历史。
SystemMessage: 系统指令。设定 AI 的人设、语气或行为准则。通常放在列表第一个。HumanMessage: 用户输入。代表人类的问题。AIMessage: AI 回复。模型的输出。
python
from langchain_core.messages import SystemMessage, HumanMessage
messages = [
SystemMessage(content="你是一个像莎士比亚一样的诗人,说话都要押韵。"),
HumanMessage(content="请介绍一下什么是人工智能。")
]
# 调用模型 (.invoke 是标准同步调用方法)
response = model.invoke(messages)
# response 是一个 AIMessage 对象,包含 content, response_metadata 等
print(f"原始内容: {response}")
print(f"回复文本: {response.content}")
4. 核心语法:LCEL (LangChain Expression Language)
LangChain v0.1 后,官方强烈推荐使用 LCEL。这是一种声明式的编程方式,让代码更易读、更易调试。
4.1 为什么要用 LCEL?
在旧版 LangChain 中,我们可能需要使用 LLMChain 类,参数多且不直观。LCEL 借用了 Unix 管道符 |,让数据流向一目了然。
原理 :Python 允许重载 | 运算符 (__or__ 方法)。LangChain 利用这一点,将 A | B 解释为"把 A 的输出作为 B 的输入"。
4.2 动手写第一条链
让我们解决一个经典任务:翻译助手 。
我们将组合三个组件:Prompt (处理输入) -> Model (生成) -> Parser (处理输出)。
python
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
# 1. 定义 Prompt 模板
# 这里的 {language} 和 {text} 是挖好的坑(变量)
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个专业的翻译助手,负责将文本翻译成{language}。"),
("user", "{text}")
])
# 2. 定义输出解析器
# ChatModel 输出的是 AIMessage 对象,StrOutputParser 帮我们直接提取 .content 字符串
parser = StrOutputParser()
# 3. 组装链 (魔法发生的地方)
chain = prompt | model | parser
# 4. 调用链
# 输入是一个字典,key 必须匹配 prompt 中的变量名
result = chain.invoke({"language": "中文", "text": "LangChain is a powerful framework."})
print(result)
# 输出结果直接就是字符串: "LangChain 是一个强大的框架。"
4.3 Runnable 协议详解
LCEL 之所以能借用 |,是因为链中的每个节点(Prompt, Model, Parser)都实现了 Runnable 接口。这意味着它们都支持一套标准 API:
.invoke(input): 标准同步调用。.stream(input): 流式返回,像打字机一样一个字一个字出。.batch([inputs]): 并行处理一批输入。.astream(input): 异步流式(对于 Web 后端很重要)。
5. 提升体验:流式传输 (Streaming)
在构建 Chatbot 时,如果模型生成一个长回复需要 5 秒,用户就会盯着空白屏幕傻等。流式传输能让用户立刻看到第一个字,极大提升体验。
5.1 同步流式 (.stream)
python
# 还是复用上面的 chain
input_data = {"language": "中文", "text": "Please write a short poem about coding."}
print("开始生成...")
# chunk 是每次返回的一小块内容(对于 StrOutputParser,就是字符串片段)
for chunk in chain.stream(input_data):
# end="" 防止print自动换行
# flush=True 强制刷新缓冲区,确保内容立刻显示在终端
print(chunk, end="", flush=True)
print("\n生成结束")
5.2 异步流式 (.astream) - Web 开发必备
在 FastAPI、Django 或 Flask 异步视图中,必须使用异步方法,否则会阻塞服务器线程。
python
import asyncio
async def async_main():
print("异步流式开始...")
async for chunk in chain.astream(input_data):
print(chunk, end="", flush=True)
# 在 Jupyter 或 Python 脚本中运行
# asyncio.run(async_main())
本篇总结:
- ChatModel 是核心,记得用
SystemMessage设定人设。 - LCEL (
|) 是灵魂,它把 Prompt、Model、Parser 串成流水线。 - Streaming 是体验提升的关键,
.stream()让应用有了"生命感"。
下一篇,我们将深入提示词工程 (Prompt Engineering) ,学习如何管理复杂的提示词,以及最重要的技能------让大模型输出 JSON 格式数据。