1. 异步编程基础与LangChain流式传输
在当今大模型应用开发领域,实时交互体验已成为衡量产品优劣的关键指标。想象一下,当你向ChatGPT提问时,如果必须等待10秒才能看到完整回答,那种体验会有多糟糕?这正是流式传输技术要解决的核心问题。
1.1 同步与异步的本质区别
同步编程就像在快餐店点单时遇到的新手收银员:你必须等他完整记录你的整个订单(包括所有定制要求)后,才能开始制作餐点。而异步编程则像经验丰富的收银员 - 他刚听到"汉堡"这个词,就立即向后厨喊出这个指令,同时继续记录你接下来的需求。
让我们用代码直观展示这个差异:
python复制import time
# 同步版本
def make_coffee():
print("磨咖啡豆...")
time.sleep(3) # 模拟耗时操作
print("冲泡咖啡...")
time.sleep(2)
return "拿铁"
def toast_bread():
print("烤面包...")
time.sleep(4)
return "烤吐司"
def sync_breakfast():
coffee = make_coffee() # 必须等待咖啡完成
toast = toast_bread() # 才能开始烤面包
print(f"早餐准备好了:{coffee} 和 {toast}")
# 总耗时约7秒
而异步版本则能显著提升效率:
python复制import asyncio
async def make_coffee_async():
print("磨咖啡豆...")
await asyncio.sleep(3)
print("冲泡咖啡...")
await asyncio.sleep(2)
return "拿铁"
async def toast_bread_async():
print("烤面包...")
await asyncio.sleep(4)
return "烤吐司"
async def async_breakfast():
coffee_task = asyncio.create_task(make_coffee_async())
toast_task = asyncio.create_task(toast_bread_async())
# 两个任务并行执行
coffee = await coffee_task
toast = await toast_task
print(f"早餐准备好了:{coffee} 和 {toast}")
# 总耗时约4秒
关键理解:
await不是简单的等待,而是"当这个任务需要等待时,把CPU让给其他就绪任务"的声明。这就像经验丰富的厨师在等水烧开时,会先去切蔬菜而不是干站着。
1.2 协程的轻量级优势
与传统线程相比,协程的轻量级特性在大模型交互中尤为重要:
- 内存占用:一个线程通常需要MB级内存,而一个协程只需KB级
- 切换成本:线程切换涉及内核态操作,协程切换完全在用户空间完成
- 并发数量:单机轻松支持数万协程,而线程通常不超过数千
python复制import asyncio
import threading
def thread_memory():
"""演示线程内存开销"""
threads = []
for i in range(5000): # 尝试创建5000个线程
try:
t = threading.Thread(target=lambda: time.sleep(100))
t.start()
threads.append(t)
except RuntimeError: # 大多数机器会在创建几百个线程时崩溃
print(f"崩溃于 {len(threads)} 个线程")
break
async def coroutine_memory():
"""演示协程内存开销"""
tasks = []
for i in range(100000): # 轻松创建10万个协程
task = asyncio.create_task(asyncio.sleep(100))
tasks.append(task)
print(f"成功创建 {len(tasks)} 个协程")
# 测试对比
thread_memory() # 通常会在300-500个线程崩溃
asyncio.run(coroutine_memory()) # 轻松创建10万协程
1.3 事件循环的调度艺术
事件循环就像一位高效的餐厅经理,它的工作流程可以概括为:
- 任务队列管理:维护所有待执行的协程任务
- 就绪检测:持续检查哪些任务可以继续执行
- I/O操作完成(如网络响应到达)
- 定时器到期(如
asyncio.sleep结束)
- 公平调度:按照预定策略分配CPU时间片
LangChain正是基于这种机制实现了高效的流式处理。当模型生成第一个token时,事件循环会立即将其推送给客户端,而不是等待完整响应。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
