上篇我们跑通了第一个Agent,但如果你只停留在"能用"的层面,后面遇到复杂场景一定会卡壳。LangChain 1.0的设计哲学和0.x完全不同,理解三个核心概念就够了:LCEL、Runnable、content_blocks。
这三个东西不是孤立的,它们是一条线串下来的:Runnable是组件的统一抽象,LCEL是组件之间的组合语法,content_blocks是组件之间的数据格式。搞懂这条线,你就掌握了1.0的设计骨架。
Runnable:一切皆可执行
1.0里几乎所有东西都是Runnable:模型是Runnable,提示词模板是Runnable,输出解析器是Runnable,检索器也是Runnable。
为什么这么设计?0.x的问题在于,每种组件都有自己的接口和调用方式——模型用llm(prompt),链用chain.run(),Agent用agent.run(),你没法把它们自由组合。
Runnable统一了接口,所有组件都只有三个核心方法:
# 同步调用result = runnable.invoke(input)# 流式调用for chunk in runnable.stream(input): print(chunk)# 异步调用result = await runnable.ainvoke(input)这意味着什么?你可以把模型、提示词模板、解析器像搭积木一样自由拼装,因为它们的输入输出接口是统一的。
from langchain_core.prompts import ChatPromptTemplatefrom langchain_openai import ChatOpenAIfrom langchain_core.output_parsers import StrOutputParser# 每个组件都是Runnableprompt = ChatPromptTemplate.from_template("用一句话解释{concept}")model = ChatOpenAI(model="gpt-4o-mini")parser = StrOutputParser()# 用LCEL管道组合chain = prompt | model | parser# 统一调用result = chain.invoke({"concept": "量子纠缠"})print(result) # 量子纠缠是两个粒子无论相隔多远,测量其中一个会瞬间影响另一个的状态。prompt | model | parser,这个管道语法就是LCEL,下一节详细说。
LCEL:LangChain表达式语言
LCEL全称LangChain Expression Language,就是上面那个|管道操作符。它的设计灵感来自Unix管道——把一个命令的输出直接传给下一个命令。
基本用法
# 等价于 bash 里的 cat file | grep keyword | sort# LCEL 里就是 prompt | model | parserchain = prompt | model | parser看起来简单,但它解决的其实是0.x里一个很烦人的问题:链式调用太死板。
0.x里你要创建一条链,得这样写:
# 0.x写法from langchain.chains import LLMChainchain = LLMChain(llm=model, prompt=prompt)result = chain.run(concept="量子纠缠")问题在于LLMChain是个固定结构,你想在中间加个步骤(比如加个输出格式化),就得写个自定义Chain类,继承BaseChain,实现一堆方法。
LCEL的做法是:不需要固定结构,你自己拼。
# 1.0写法:在模型和解析器之间加一步格式化from langchain_core.runnables import RunnableLambdadef format_output(text): return text.strip().replace("。", "。\n")chain = prompt | model | RunnableLambda(format_output) | parser想加步骤就|一个Runnable进去,想删就删,灵活度完全不在一个量级。
LCEL的高级用法
1. 并行执行
from langchain_core.runnables import RunnableParallel# 两条链同时跑,结果合并parallel = RunnableParallel({ "summary": summary_chain, "keywords": keyword_chain,})result = parallel.invoke({"text": "一段长文本..."})# result = {"summary": "摘要内容", "keywords": "关键词列表"}2. 条件路由
from langchain_core.runnables import RunnableBranch# 根据输入选择不同的处理链branch = RunnableBranch( (lambda x: len(x["text"]) > 1000, long_text_chain), (lambda x: "code" in x["text"], code_chain), default_chain, # 默认走这条)3. 配置化
运行时动态切换组件,不用改代码:
from langchain_core.runnables import ConfigurableFieldmodel = ChatOpenAI(model="gpt-4o-mini").configurable_fields( model_name=ConfigurableField(id="model"))# 运行时选模型result = model.invoke( "你好", config={"configurable": {"model": "deepseek-chat"}})这些在0.x里要么做不到,要么得写大量模板代码。LCEL用几行就搞定了。
content_blocks:统一的消息内容格式
这个概念我在第一篇里提过,这里展开讲讲为什么它重要、怎么用。
它解决什么问题?
不同大模型返回消息的格式各不相同:
- OpenAI返回
content字符串 +function_call对象 - Anthropic返回多个
content_block,文本和工具调用分开 - DeepSeek返回
content+tool_calls列表
0.x时代,你要处理不同模型的输出,就得写适配代码。比如判断response.additional_kwargs.get("function_call")、response.tool_calls等,每个模型还不一样。
1.0用content_blocks统一了这一切:
response = model.invoke("帮我查一下北京天气")# 不管底层是什么模型,都用同一套方式访问for block in response.content_blocks: match block["type"]: case "text": print(f"文本: {block['text']}") case "tool_call": print(f"调用工具: {block['name']}, 参数: {block['args']}") case "reasoning": print(f"推理过程: {block['text']}") # DeepSeek的思考链 case "image": print(f"图片: {block.get('url', '')}")实际开发中怎么用?
场景1:你想从模型回复中提取工具调用
tool_calls = [ block for block in response.content_blocks if block["type"] == "tool_call"]场景2:你想拿到DeepSeek的思考过程
reasoning = ""answer = ""for block in response.content_blocks: if block["type"] == "reasoning": reasoning = block["text"] elif block["type"] == "text": answer = block["text"]print(f"思考过程: {reasoning}")print(f"最终回答: {answer}")场景3:多模态输出处理
for block in response.content_blocks: if block["type"] == "image": # 懒加载,图片不会在content_blocks里直接加载 image_data = block.load() # 需要时才下载 image_data.save(f"output_{block['id']}.png")content_blocks和旧版content属性的关系
1.0里AIMessage同时保留了content(字符串)和content_blocks(列表)两个属性,向下兼容:
# content还是能用的,返回纯文本print(response.content) # "北京今天晴,气温28℃"# content_blocks是结构化视图print(response.content_blocks) # [{"type": "text", "text": "北京今天晴..."}]日常简单场景用content就行,需要细粒度处理再用content_blocks。
三者的关系:一张图搞定
用户输入 ↓[Prompt Template (Runnable)] ← LCEL定义 ↓[Chat Model (Runnable)] ← content_blocks统一输出格式 ↓[Output Parser (Runnable)] ↓最终输出- Runnable让每个组件都有统一的调用接口(invoke/stream/ainvoke)
- LCEL让组件之间可以用
|自由组合 - content_blocks让组件之间的数据传递有了统一的格式
三件事,一个目标:让AI应用的开发像搭积木一样灵活。
学AI大模型的正确顺序,千万不要搞错了
🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!
有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!
就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋
📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇
学习路线:
✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经
以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!
我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~