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
1import os 2from dotenv import load_dotenv 3from langchain_openai import ChatOpenAI 4from langchain_core.prompts import ChatPromptTemplate, PromptTemplate 5from langchain_core.tools import Tool 6import datetime 7 8# 加载环境变量 9load_dotenv() 10api_key = os.getenv('OPENAI_API_KEY') 11base_url = os.getenv('OPENAI_API_BASE') 12 13# ========== 1. 初始化 LLM(大语言模型) ========== 14# LangChain 特点:统一的 LLM 接口,支持多种模型提供商 15llm = ChatOpenAI( 16 base_url=base_url, 17 api_key=api_key, 18 model="deepseek-ai/DeepSeek-V3.2", 19 temperature=0.7 # LangChain 特点:统一的参数配置 20) 21 22# 也可以使用 init_chat_model 由于我使用的是硅基流动的,所以需要提供model_provider为openai 23# 如果你直接使用的是deepseek,model_provider可以不用填,但需要安装langchain-deepseek包 24model = init_chat_model( 25 model="deepseek-ai/DeepSeek-V3.2", 26 model_provider="openai", 27 temperature=0.7 28) 29 30 31# ========== 2. LLMChain:Prompt → LLM → 输出链的基本流程封装 ========== 32def demo_llm_chain(): 33 """ 34 演示 LLMChain:支持变量注入与模板复用的核心组件 35 LangChain 特点:模板化提示词管理,支持变量替换 36 """ 37 print("=" * 50) 38 print("🔗 LLMChain 演示:Prompt → LLM → 输出链") 39 print("=" * 50) 40 41 # 创建提示词模板 - LangChain 特点:模板复用 42 prompt_template = PromptTemplate( 43 input_variables=["topic", "style"], 44 template=""" 45 请以{style}的风格,写一段关于{topic}的介绍。 46 要求:简洁明了,不超过100字。 47 """ 48 ) 49 50 # LCEL (LangChain Expression Language),还是0.x的版本用的比较多 51 # 1.x开始采用Message 52 # 下面两种方式都行 53 chain = prompt_template | llm 54 chain = prompt_template | model 55 # 执行链 - 变量注入 56 57 result = chain.invoke({"topic": "人工智能", "style": "科普"}) 58 print(f"📝 LLMChain 输出:\n{result.content}\n") 59 60 # 流式输出 61 for chunk in chain.stream({"topic": "人工智能", "style": "科普"}): 62 print(chunk.text, end="|", flush=True) 63 64 # batch 65 messages = [ 66 {"topic": "人工智能", "style": "科普"}, 67 {"topic": "大模型", "style": "科普"}, 68 {"topic": "langchain", "style": "科普"} 69 ] 70 responses = chain.batch(messages) 71 for response in responses: 72 print(response) 73 74 75 return result.content 76
核心的方法
- invoke
1result = chain.invoke({"topic": "人工智能", "style": "科普"}) 2print(f"📝 LLMChain 输出:\n{result.content}\n") 3
- stream
1# 流式输出 2for chunk in chain.stream({"topic": "人工智能", "style": "科普"}): 3 print(chunk.text, end="|", flush=True) 4
- batch
1# batch 2messages = [ 3 {"topic": "人工智能", "style": "科普"}, 4 {"topic": "大模型", "style": "科普"}, 5 {"topic": "langchain", "style": "科普"} 6] 7responses = chain.batch(messages) 8for response in responses: 9 print(response) 10
核心参数:
- model: 大模型名称
- model_provider: 模型供应商,我用的是硅基流动,langchain没有提供硅基流动的包,但硅基流动兼容了OpenAi协议,模型供应商选择OpenAi,也能连接硅基流动。
- api_key:
- temperature:
- max_token:
- max_retries:
- timeout:
比较常用的Model 功能
思考模式打开
1reasoning = { 2 "effort": "medium" 3} 4 5reasoning_model = ChatOpenAI( 6 model="gpt-5.2", 7 temperature=0.7, 8 reasoning=reasoning 9) 10 11for chunk in reasoning_model.stream("大模型的原理"): 12 reasoning_steps = [r for r in chunk.content_blocks if r["type"] == "reasoning"] 13 print(reasoning_steps if reasoning_steps else chunk.text) 14
结构化输出
Message
Message按照OpenAi的规范需要区分角色:
- developer: developer message的主要职责是
-
- 系统的核心规则
- 系统的业务逻辑
- 工具的定义
- user:用户的输入和配置,用于
- Assistant:大模型的输出
developer以前是system,现在变成了developer,但是langchain或者其他智能体框架,都还沿用着system作为系统角色,OpenAi两者都兼容。
Langchain还新增了一个角色,Tool,工具消息用于将单个工具执行的结果传递回模型。工具可以直接生成 ToolMessage 对象。
1messages = [ 2 SystemMessage(content="你是一名资深的Python后端工程师面试官,负责考察候选人的技术能力。"), 3 HumanMessage(content="请问什么是装饰器?"), 4 AIMessage(content="装饰器是Python中用于修改函数或类行为的语法糖..."), 5 HumanMessage(content="能举个实际应用的例子吗?") 6] 7 8# 9# messages = [ 10# {"role": "system", "content": "你是一名资深的Python后端工程师面试官,负责考察候选人的技术能力。"}, # 对应SystemMessage 11# {"role": "user", "content": "请问什么是装饰器?"}, # 对应HumanMessage 12# {"role": "assistant", "content": "装饰器是Python中用于修改函数或类行为的语法糖..."}, # 对应AIMessage 13# {"role": "user", "content": "能举个实际应用的例子吗?"} 14# ] 15 16 17response = llm.invoke(messages) 18 19print(f"📝 LLMChain 输出:\n{response.content}\n") 20
ToolMessage的使用方式
1def get_weather(location: str) -> str: 2 """Get the weather at a location.""" 3 # 先获取城市ID 4 location_url = f"https://n53h2qt5jy.re.qweatherapi.com/geo/v2/city/lookup?location={location}" 5 location_response = (requests.get(url=location_url,headers={"Content-Type": "application/json","X-QW-Api-Key": q_weather_api_key}).json()) 6 7 if location_response['code'] != '200': 8 return f"未找到城市:{location}" 9 10 location_id = location_response['location'][0]['id'] 11 12 # 查询天气 13 weather_url = f"https://n53h2qt5jy.re.qweatherapi.com/v7/weather/now?location={location_id}" 14 weather_response = requests.get(url=weather_url, headers={"Content-Type": "application/json", "X-QW-Api-Key": q_weather_api_key}).json() 15 16 if weather_response['code'] == '200': 17 now = weather_response['now'] 18 return f"{location}当前天气:{now['text']},温度{now['temp']}°C,体感温度{now['feelsLike']}°C" 19 20 return "天气查询失败" 21 22model_with_tools = llm.bind_tools([get_weather]) 23response = model_with_tools.invoke("What's the weather in 上海?") 24 25for tool_call in response.tool_calls: 26 print(f"Tool: {tool_call['name']}") 27 print(f"Args: {tool_call['args']}") 28 print(f"ID: {tool_call['id']}") 29 30# After a model makes a tool call 31# (Here, we demonstrate manually creating the messages for brevity) 32ai_message = AIMessage( 33 content=[], 34 tool_calls=[{ 35 "name": "get_weather", 36 "args": {"location": "上海"}, 37 "id": "call_123" 38 }] 39) 40 41# Execute tool and create result message 42tool_message = ToolMessage( 43 content=get_weather("上海"), 44 tool_call_id="call_123" # Must match the call ID 45) 46 47# Continue conversation 48messages = [ 49 HumanMessage("上海天气如何?"), 50 ai_message, # Model's tool call 51 tool_message, # Tool execution result 52] 53response = llm.invoke(messages) # Model processes the result 54print("==================") 55print(f"📝 LLMChain 输出:\n{response.content}\n") 56 57print(f"llm 元数据:{response.usage_metadata}") 58