学习启动
Q:我想要学习 langchain 开发
LangChain 是一个非常强大的框架,它的核心作用是将大语言模型(LLM)与其他计算或知识来源结合起来。
如果把大语言模型(如 GPT-4)比作一个博学的"大脑" 🧠,那么 LangChain 就是让这个大脑能够由想法转变为实际行动的"骨架"和"双手" 👐。它允许你通过**链(Chains)**将多个组件连接起来,从而构建复杂的应用。
为了让你更有效地掌握 LangChain 开发,我们可以从以下几个不同的切入点开始。请告诉我你最感兴趣的一个方向:
核心基础 (Core Basics): 从最基本的 Prompt Templates(提示词模板)、Models(模型接口)和 Output Parsers(输出解析器)开始,理解 LangChain 的"Hello World"是如何运行的。
与数据对话 (RAG - 检索增强生成): 学习如何加载 PDF 或文本文档,将其存入向量数据库,并让 AI 基于你的私有数据回答问题。这是目前最流行的应用场景。
智能体 (Agents): 探索如何让 AI 自主决定使用什么工具(比如搜索网络、运行代码或查询 API)来解决复杂问题。
你想从哪个方向开始我们的学习之旅?
Q:我们先从核心基础开始吧
没问题,我们先打好地基!🏗️
LangChain 最基础的部分通常被称为 "Model I/O" (模型输入/输出)。你可以把它想象成是一个处理信息的流水线。
这个流水线主要由三个核心组件像乐高积木一样拼在一起:
提示词模板 (Prompt Templates): 负责把用户的输入(比如"苹果")包装成 AI 能听懂的完整指令。
大语言模型 (Language Models): 负责思考和生成回答的"大脑"。
输出解析器 (Output Parsers): 负责把 AI 啰嗦的回答整理成我们要的格式(比如只要结果,不要"好的,这是你的翻译..."这种废话)。
我们就从第一个组件 提示词模板 (Prompt Template) 开始。
想象一下,你正在开发一个 "中法翻译器" 🇫🇷。 用户在你的 App 里只需要输入单词,比如 "苹果"。 但是,如果你直接把 "苹果" 这两个字发给 GPT-4,它可能会不知道你想干什么(它可能会解释什么是苹果,而不是翻译它)。
为了让 AI 稳定地执行翻译任务,我们需要把用户的输入 "苹果" 嵌入到一个固定的指令中。
如果让你给 AI 写一段通用的指令,把 "苹果" 替换成一个变量(比如 {user_input}),你会怎么写这段话,才能让 AI 无论收到什么词,都知道是要做"翻译成法语"这件事?
Q:我会写:你是一个中文到法语的翻译器。会将我的输入{user_input}翻译为准确的法语,作为你的唯一输出。
这是一个非常标准且有效的提示词!通过明确 角色(翻译器)、任务(翻译为法语)以及 约束条件(唯一输出),你已经建立了一个高质量的指令。
在 LangChain 中,我们使用 PromptTemplate 类来管理这种模板。它的好处是你可以预先定义好逻辑,然后在程序运行时动态地填充变量。
下面是这段逻辑在 LangChain 代码中的样子:
python
from langchain_core.prompts import PromptTemplate
# 定义模板
template = "你是一个中文到法语的翻译器。会将我的输入{user_input}翻译为准确的法语,作为你的唯一输出。"
# 创建 PromptTemplate 对象
prompt_template = PromptTemplate.from_template(template)
# 填充变量
final_prompt = prompt_template.format(user_input="苹果")
print(final_prompt)
有了提示词后,下一步就是把它发给 模型 (Model)。LangChain 提供了统一的接口来调用不同的模型(如 OpenAI、Anthropic 或国产的通义千问等)。
现在,假设我们已经把这个 final_prompt 发送给了模型,模型返回了:
"Voici la traduction : Pomme"
你会发现模型并没有完全遵守你"唯一输出"的指令,它多说了一句"这是翻译:"。
为了让程序能够直接拿到 Pomme 这个单词而不受干扰,你觉得我们应该在代码中加入什么机制来处理这种"多余"的信息?
修改提示词 (Prompt Engineering): 继续尝试用文字命令模型闭嘴。
输出解析器 (Output Parser): 编写一段逻辑,自动提取出模型回答中的法语部分。
模型参数调整: 调低模型的热度(Temperature),让它不那么"话多"。
你认为哪种方式在构建稳健的开发系统时最可靠?
Q:输出解析器。
选择输出解析器 (Output Parser) 是非常明智的!在实际开发中,这是保证程序稳定性最关键的一环。
如果只靠提示词,AI 就像一个不听指挥的翻译官,偶尔会多嘴说些"这是你要的翻译:"。而输出解析器就像是一个过滤器,它能确保你的程序拿到的数据是干净、结构化的(比如纯文本、JSON 格式或 Python 列表)。
LangChain 提供了多种解析器。对于我们这个翻译器的例子,最适合的是 StrOutputParser,它的工作很简单:把模型返回的复杂对象直接转换成纯字符串,去掉多余的元数据。
现在我们把这三者串联起来,形成一个真正的 "链" (Chain)。在 LangChain 中,我们使用一种类似 Unix 管道的语法 | 来连接组件:
python
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI # 假设使用 OpenAI
# 1. 准备组件
prompt = prompt_template
model = ChatOpenAI(model="gpt-4")
output_parser = StrOutputParser()
# 2. 构建链 (Chain)
# 逻辑:提示词 -> 发给模型 -> 解析输出
chain = prompt | model | output_parser
# 3. 运行
result = chain.invoke({"user_input": "苹果"})
print(result) # 此时输出的就是干净的 "Pomme"
这种 A | B | C 的结构就是 LangChain 最核心的设计哲学,叫做 LCEL (LangChain Expression Language)。
既然我们已经跑通了一个简单的流程,我想考考你:
如果我们现在不只是想要一个单词,而是希望 AI 返回一个结构化的数据(例如:同时返回法语单词及其对应的词性,像 {"word": "Pomme", "type": "noun"}),你觉得我们是应该:
继续在提示词里求 AI "请给我 JSON 格式"。
更换一个更强大的输出解析器,专门用来处理 JSON 数据。
你直觉上觉得哪种做法更能让你的后端代码(比如 Python)轻松地读取这些数据?
Q:我选 2
这是一个非常专业的选择!🎯 在实际的生产环境中,依靠提示词(Prompt Engineering)让模型输出 JSON 往往不够稳定,模型偶尔会多写一个逗号或加一段开场白,导致你的 Python 程序崩溃。
使用 输出解析器 (Output Parser) 可以让你定义预期的结构,它甚至能在模型输出格式错误时尝试进行修复或提供清晰的报错。
为了实现输出 { "word": "...", "type": "..." } 这样的结构,LangChain 提供了几种强大的解析器。其中最常用的是 PydanticOutputParser 或更简单的 JsonOutputParser。
我们可以这样定义我们的解析需求:
定义结构: 告诉 LangChain 我们想要一个包含 word (string) 和 type (string) 的对象。
获取格式指令: 解析器会自动生成一段复杂的提示词指令(例如:"输出必须是一个 JSON,包含以下字段..."),我们只需把这段指令塞进我们的 Prompt 里。
动手试试看
我们要把之前的链升级一下。在 LangChain 中,解析器不仅负责"处理结果",它还能"生成指令"。
如果你现在要定义这个解析器,你觉得除了告诉它字段名(word 和 type),是否还需要告诉它:
A: 每一个字段代表的具体含义(比如 type 是指"词性")。
B: 这个单词在字典里的页码。
你认为哪个信息对 AI 生成准确的结构化数据更关键?
Q:当然是 A
完全正确!选择 A 是构建健壮系统的核心。
给 AI 提供字段的语义描述(Description)至关重要。这就像给厨师一张订单,如果你只写"肉",他可能不知道要做成什么;但如果你写"肉:请使用新鲜牛肉并切成薄片",结果就会准确得多。
在 LangChain 中,我们通常使用 Pydantic 来定义这种结构。这不仅能告诉 AI 每个字段的意思,还能让 Python 自动验证 AI 返回的数据是否符合要求。
结构化输出的代码实现
看看这段代码是如何把你的想法转变为现实的:
python
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_core.output_parsers import JsonOutputParser
# 1. 定义数据结构
class Translation(BaseModel):
word: str = Field(description="翻译后的法语单词")
type: str = Field(description="该单词的词性,例如:名词、动词、形容词")
# 2. 初始化解析器
parser = JsonOutputParser(pydantic_object=Translation)
# 3. 将解析指令注入提示词
# parser.get_format_instructions() 会生成一段告诉 AI 如何输出 JSON 的文字
prompt = PromptTemplate(
template="你是一个翻译器。\n{format_instructions}\n用户输入:{user_input}",
input_variables=["user_input"],
partial_variables={"format_instructions": parser.get_format_instructions()}
)
chain = prompt | model | parser
核心基础小结
我们刚刚走过了 LangChain 开发最经典的 Model I/O 流程:
Prompt: 包装输入,并嵌入格式指令。
Model: 处理逻辑。
Output Parser: 确保结果是你想要的 Python 对象(字典/模型)。
掌握了这个流程,你就已经能开发简单的 AI 工具了!
现在,你准备好进入下一个阶段了吗?我们可以:
实战练习: 尝试把这个链增加一点复杂度,比如让它同时返回"例句"。
进入 RAG (检索增强生成): 学习如何让 AI 读完你的文档后再回答问题。
你想继续打磨这个翻译器,还是开启全新的"对话文档"之旅?