1、同步链路:
同步链(Synchronous Chain)是 LangChain 中最基础、最简单的执行模式。它代表了“一步接一步”的链式处理方式,就像排队买奶茶:前一个任务没做完,下一个任务只能等
一、同步链的本质:
同步链本质上是:
可组合的可调用对象(Runnable),按顺序执行,前一步的输出就是下一步的输入
它是一条严格的流水线:
Prompt → Model → Parser → Output
每一个环节都必须等待上一环节完成
二、同步链的结构(最常见三件套)
构建同步链常见三个组件:
-
提示模板 PromptTemplate
用来构造文本输入,负责把用户输入塞进模板 -
LLM / ChatModel(Language Model)
如 OpenAI、Azure、Ollama、本地模型等 -
输出解析器 StrOutputParser
用来把模型的输出转换为 Python String -
穿起来就是:
chain = prompt | model | StrOutputParser()
三、同步执行:invoke
同步链通过 invoke() 执行:
result = chain.invoke({"question": "同步链是如何工作的?"})
答:同步链按顺序依次执行任务,每个任务必须等待前一个任务完成后才能开始,确保执行顺序和状态一致性。
特点:
- 阻塞(blocking):没有执行完不会继续别的任务
- 单步式:必须等模型返回
- 执行顺序稳定:一步一步推进
同步链确保“有序、确定性、安全”,但速度可能慢
四、同步链的应用场景
同步链适合:
-
单次问答(ChatGPT 式交互)
-
顺序严格的流程,如:
加载 → 清洗 → 分析 → 输出 -
模型调用间有依赖关系(前一步必须完成才有下一步)
举例:
你问模型一个问题,它回答后你解析,然后你再做计算, 一环扣一环,就适合同步
五、同步链的完整代码样例:
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
# 构建同步链
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个专业问答助手"),
("user", "{question}")
])
model = ChatOpenAI(model="gpt-4o-mini")
parser = StrOutputParser()
chain = prompt | model | parser # 使用 | 操作符
# 同步执行
result = chain.invoke({"question": "什么是同步链?"})
print(result)
2、异步链路:
异步链在 LangChain 中最关键的点只有一件事:
所有可运行体(Runnable)都支持
.ainvoke()、.astream()等异步方法
一、异步链的核心概念:
通俗的讲,同步链是 “一步一个脚印”,异步链是 “谁先跑完谁先回来”
-
同步链:
result = chain.invoke({"question":"Who are you?"}) -
异步链:
result = await chain.ainvoke({"question":"Who are you?"})
异步链的优点:
- 可以并发地处理多个任务
- 不必等待 CPU/IO 空档
- 大幅提升吞吐量,尤其适合“并行问答、批量处理、多路输出”场景
二、构造异步问答链:
-
构造 “PromptTemplatePromptTemplatePromptTemplate”负责生成提示、“ChatOpenAIChatOpenAIChatOpenAI”负责调用模型 和 “StrOutputParserStrOutputParserStrOutputParser”负责把模型的输出转换为字符串
-
import asyncio from langchain_core.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI from langchain_core.output_parsers import StrOutputParser # ------------------------- # 1. Prompt # ------------------------- prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个专业问答机器人,回答要清晰简洁。"), ("user", "{question}") ]) # ------------------------- # 2. Model # ------------------------- model = ChatOpenAI( model="gpt-4o-mini", temperature=0.2 ) # ------------------------- # 3. Parser # ------------------------- parser = StrOutputParser() # ------------------------- # 4. 异步链 # ------------------------- # 把 prompt → model → parser 串成一条流水线 chain = prompt | model | parser # 运行异步链 async def run_async(): result = await chain.ainvoke({"question": "什么是异步模型链?"}) print(result) asyncio.run(run_async())
3、同步 vs 异步的并发性能测试:
# 导入必要的模块
import time # 用于记录执行时间
import asyncio
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
from dotenv import load_dotenv
import os
load_dotenv(override=True)
api_key = os.getenv("你的API密钥")
base_url = os.getenv("对应的URL地址")
prompt = ChatPromptTemplate.from_template(
"你是一个问答助手。请简洁回答:{question}"
)
model = ChatOpenAI(
model="qwen3-max",
api_key=api_key,
base_url=base_url,
)
parser = StrOutputParser()
chain = prompt | model | parser
# 准备10个测试问题,每个问题都要求一句哲学思考
questions = [
f"第{i}个问题:给我一句哲学思考?"
for i in range(1, 11) # 生成问题列表:第1个问题...第10个问题
]
# -------------------
# 同步执行函数
# -------------------
def test_sync():
"""
同步方式依次调用 chain.invoke 处理每个问题。
特点:一个接一个执行,前一个完成后再执行下一个。
优点:逻辑简单;缺点:总耗时长(串行)。
"""
start = time.time() # 记录开始时间
results = [] # 存储所有结果
# 遍历每个问题,同步调用链
for q in questions:
r = chain.invoke({"question": q}) # 调用链并传入参数
results.append(r) # 将结果加入列表
# 打印同步执行总耗时
print("同步执行耗时:", time.time() - start)
return results
# -------------------
# 异步执行函数
# -------------------
async def test_async():
"""
异步方式并发调用 chain.ainvoke 处理所有问题。
特点:同时发起多个请求(非阻塞),利用 asyncio 并发处理 I/O 等待。
优点:大幅减少总耗时(尤其在网络请求密集场景);缺点:需理解异步编程。
"""
start = time.time() # 记录开始时间
# chain.ainvoke(...) 是一个 异步方法,返回一个“协程对象”,可以理解为待办任务
# 执行 chain.ainvoke(...) 后,不会立刻发请求,而是生成一个“任务蓝图”,这个蓝图被放在 task 列表里
# 形式:task = [chain.ainvoke({"question":q}), chain.ainvoke({"question":q}), ···]
tasks = [
chain.ainvoke({"question": q}) # 使用异步方法 ainvoke
for q in questions
]
# 使用 asyncio.gather 把一堆协程(任务)同时“启动”,然后等它们全部完成
# 并发执行所有任务,并等待全部完成
# 返回结果顺序与 tasks 列表一致
results = await asyncio.gather(*tasks)
# 打印异步执行总耗时
print("异步执行耗时:", time.time() - start)
return results
# -------------------
# 主程序入口
# -------------------
if __name__ == "__main__":
"""
程序启动时依次运行同步测试和异步测试,
并对比两者耗时差异。
注意:由于 OpenAI API 调用是网络 I/O 操作,异步版本通常显著更快。
"""
print("\n开始同步测试……")
sync_results = test_sync() # 执行同步测试
print("\n开始异步测试……")
async_results = asyncio.run(test_async()) # 启动异步事件循环并执行异步测试
4、完善异步链的“异常处理”
异步请求难免有失败的时候,比如:
- 网络卡住
- API 限流
- 某个问题模型无法回答
我们要写一个更强壮的异步链封装
-
捕获所有异常(
Exception)并返回结构化错误信息async def safe_ainvoke(question): try: result = await chain.ainvoke({"question": question}) return {"question": question, "answer": result, "error": None} except requests.exceptions.RequestException as e: if e.response and e.response.status_code == 429: # 限流错误 return {"question": question, "answer": None, "error": "RATE_LIMIT"} return {"question": question, "answer": None, "error": str(e)} -
批量执行逻辑
async def test_async_safe(): # 构建任务蓝图列表 tasks = [safe_ainvoke(q) for q in questions] results = await asyncio.gather(*tasks) for item in results: if item["error"]: print("错误:", item["error"]) else: print("回答:", item["answer"])
2478

被折叠的 条评论
为什么被折叠?



