Langchain是一款开源框架,用于构建Agent,集成了众多大模型供应商和工具。
- langchain主要负责与LLM交互,Tool,Rag,Memory,Agent等功能。
- LangGraph负责实现Agent编排,专用于构建、管理和部署长时间运行(long-running)且具备状态管理(stateful的智能体。
- LangSmith则负责提升Agent的可观测性,提供了用于开发、调试和部署 LLM 应用程序的工具。 它能够帮助您在一个统一的平台上追踪请求、评估输出、测试提示词(Prompts)以及管理部署。
Langchain核心功能
LCEL语法
早期的Langchain,将提示词,模型,工具调用,Rag,Memory等模块组织成链式结构,让开发者能够清晰的组合这些组件,构建出复杂的Agent。但是缺点也很明显:
- 流程不透明、调试困难:链条中间没有明确的状态表达,出错时难以定位是哪一步出了问题。
- 缺乏并发与分支控制能力:只能“从左到右”执行,面对多轮对话、并行任务,力不从心。
- Agent 系统复杂难控:LangChain Agent 的“反复推理 + 工具调用”机制,虽然看似智能,但在实际工程中不稳定、不易测试。
为了解决这些问题,Langchain团队研发出了LCEL。LCEL (LangChain Expression Language) 是 LangChain 提供的一种声明式语言,用于轻松构建和组合复杂的链(Chains)。使得代码更加简洁、清晰,并且原生支持流式/非流式输出。
在LCEL中,所有组件都实现了 langchain_core.runnables.base.Runnable接口,都实现了
- invoke() - 单个输入
- batch() - 批量输入
- stream() - 流式输出
- ainvoke() - 异步单个输入
| 组件名称 | 作用 |
|---|---|
| RunnableSequence | 顺序执行 |
| RunnableParallel | 并行执行多个任务 |
| RunnablePassthrough | 透传数据,不做处理 |
| RunnableLambda | 将自定义 Python 函数转为 Runnable |
| RunnableConfig | 配置项 |
| RunnableBranch | 条件分支 |
但是,现在的Agent是越来越复杂,需要更加精细化的状态管控,任务调度,失败处理,事件监听,整个Agent的生命周期到每一个事件的生命周期,都需要更加细粒度的管理,还需要一套更为清晰完整的,适合工作流程编排的框架。那就是LangGraph的诞生。
- LCEL:描述单个“图节点”的调用逻辑(比如一个子任务、一个 API 调用)。
- LangGraph:编排多个节点,负责整个工作流的调度、状态跳转与生命周期控制。
Model
安装 openai依赖 pip install langchain-openai
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, PromptTemplate
from langchain_core.tools import Tool
import datetime
# 加载环境变量
load_dotenv()
api_key = os.getenv('OPENAI_API_KEY')
base_url = os.getenv('OPENAI_API_BASE')
# ========== 1. 初始化 LLM(大语言模型) ==========
# LangChain 特点:统一的 LLM 接口,支持多种模型提供商
llm = ChatOpenAI(
base_url=base_url,
api_key=api_key,
model="deepseek-ai/DeepSeek-V3.2",
temperature=0.7 # LangChain 特点:统一的参数配置
)
# 也可以使用 init_chat_model 由于我使用的是硅基流动的,所以需要提供model_provider为openai
# 如果你直接使用的是deepseek,model_provider可以不用填,但需要安装langchain-deepseek包
model = init_chat_model(
model="deepseek-ai/DeepSeek-V3.2",
model_provider="openai",
temperature=0.7
)
# ========== 2. LLMChain:Prompt → LLM → 输出链的基本流程封装 ==========
def demo_llm_chain():
"""
演示 LLMChain:支持变量注入与模板复用的核心组件
LangChain 特点:模板化提示词管理,支持变量替换
"""
print("=" * 50)
print("🔗 LLMChain 演示:Prompt → LLM → 输出链")
print("=" * 50)
# 创建提示词模板 - LangChain 特点:模板复用
prompt_template = PromptTemplate(
input_variables=["topic", "style"],
template="""
请以{style}的风格,写一段关于{topic}的介绍。
要求:简洁明了,不超过100字。
"""
)
# LCEL (LangChain Expression Language),还是0.x的版本用的比较多
# 1.x开始采用Message
# 下面两种方式都行
chain = prompt_template | llm
chain = prompt_template | model
# 执行链 - 变量注入
result = chain.invoke({"topic": "人工智能", "style": "科普"})
print(f"📝 LLMChain 输出:\n{result.content}\n")
# 流式输出
for chunk in chain.stream({"topic": "人工智能", "style": "科普"}):
print(chunk.text, end="|", flush=True)
# batch
messages = [
{"topic": "人工智能", "style": "科普"},
{"topic": "大模型", "style": "科普"},
{"topic": "langchain", "style": "科普"}
]
responses = chain.batch(messages)
for response in responses:
print(response)
return result.content
核心的方法
- invoke
result = chain.invoke({"topic": "人工智能", "style": "科普"})
print(f"📝 LLMChain 输出:\n{result.content}\n")
- stream
# 流式输出
for chunk in chain.stream({"topic": "人工智能", "style": "科普"}):
print(chunk.text, end="|", flush=True)
- batch
# batch
messages = [
{"topic": "人工智能", "style": "科普"},
{"topic": "大模型", "style": "科普"},
{"topic": "langchain", "style": "科普"}
]
responses = chain.batch(messages)
for response in responses:
print(response)
核心参数:
- model: 大模型名称
- model_provider: 模型供应商,我用的是硅基流动,langchain没有提供硅基流动的包,但硅基流动兼容了OpenAi协议,模型供应商选择OpenAi,也能连接硅基流动。
- api_key:
- temperature:
- max_token:
- max_retries:
- timeout:
比较常用的Model 功能
思考模式打开
reasoning = {
"effort": "medium"
}
reasoning_model = ChatOpenAI(
model="gpt-5.2",
temperature=0.7,
reasoning=reasoning
)
for chunk in reasoning_model.stream("大模型的原理"):
reasoning_steps = [r for r in chunk.content_blocks if r["type"] == "reasoning"]
print(reasoning_steps if reasoning_steps else chunk.text)
结构化输出
Message
Message按照OpenAi的规范需要区分角色:
- developer: developer message的主要职责是
-
- 系统的核心规则
- 系统的业务逻辑
- 工具的定义
- user:用户的输入和配置,用于
- Assistant:大模型的输出
developer以前是system,现在变成了developer,但是langchain或者其他智能体框架,都还沿用着system作为系统角色,OpenAi两者都兼容。
Langchain还新增了一个角色,Tool,工具消息用于将单个工具执行的结果传递回模型。工具可以直接生成 ToolMessage 对象。
messages = [
SystemMessage(content="你是一名资深的Python后端工程师面试官,负责考察候选人的技术能力。"),
HumanMessage(content="请问什么是装饰器?"),
AIMessage(content="装饰器是Python中用于修改函数或类行为的语法糖..."),
HumanMessage(content="能举个实际应用的例子吗?")
]
#
# messages = [
# {"role": "system", "content": "你是一名资深的Python后端工程师面试官,负责考察候选人的技术能力。"}, # 对应SystemMessage
# {"role": "user", "content": "请问什么是装饰器?"}, # 对应HumanMessage
# {"role": "assistant", "content": "装饰器是Python中用于修改函数或类行为的语法糖..."}, # 对应AIMessage
# {"role": "user", "content": "能举个实际应用的例子吗?"}
# ]
response = llm.invoke(messages)
print(f"📝 LLMChain 输出:\n{response.content}\n")
ToolMessage的使用方式
def get_weather(location: str) -> str:
"""Get the weather at a location."""
# 先获取城市ID
location_url = f"https://n53h2qt5jy.re.qweatherapi.com/geo/v2/city/lookup?location={location}"
location_response = (requests.get(url=location_url,headers={"Content-Type": "application/json","X-QW-Api-Key": q_weather_api_key}).json())
if location_response['code'] != '200':
return f"未找到城市:{location}"
location_id = location_response['location'][0]['id']
# 查询天气
weather_url = f"https://n53h2qt5jy.re.qweatherapi.com/v7/weather/now?location={location_id}"
weather_response = requests.get(url=weather_url, headers={"Content-Type": "application/json", "X-QW-Api-Key": q_weather_api_key}).json()
if weather_response['code'] == '200':
now = weather_response['now']
return f"{location}当前天气:{now['text']},温度{now['temp']}°C,体感温度{now['feelsLike']}°C"
return "天气查询失败"
model_with_tools = llm.bind_tools([get_weather])
response = model_with_tools.invoke("What's the weather in 上海?")
for tool_call in response.tool_calls:
print(f"Tool: {tool_call['name']}")
print(f"Args: {tool_call['args']}")
print(f"ID: {tool_call['id']}")
# After a model makes a tool call
# (Here, we demonstrate manually creating the messages for brevity)
ai_message = AIMessage(
content=[],
tool_calls=[{
"name": "get_weather",
"args": {"location": "上海"},
"id": "call_123"
}]
)
# Execute tool and create result message
tool_message = ToolMessage(
content=get_weather("上海"),
tool_call_id="call_123" # Must match the call ID
)
# Continue conversation
messages = [
HumanMessage("上海天气如何?"),
ai_message, # Model's tool call
tool_message, # Tool execution result
]
response = llm.invoke(messages) # Model processes the result
print("==================")
print(f"📝 LLMChain 输出:\n{response.content}\n")
print(f"llm 元数据:{response.usage_metadata}")