LangChain 架构演进与功能扩展:流式事件处理、事件过滤及回调策略
介绍 LangChain v0.2 版本的核心演进,包括架构调整、依赖拆分及迁移指南。重点阐述基于 Runnable 的流式事件支持(astream_events),展示如何在 Chain 和 ChatModel 中获取中间状态。内容涵盖事件过滤机制、回调传播策略以及@tool 装饰器的变化,并提供完整的代码示例与最佳实践建议,帮助开发者构建可观测性强的 LLM 应用。

介绍 LangChain v0.2 版本的核心演进,包括架构调整、依赖拆分及迁移指南。重点阐述基于 Runnable 的流式事件支持(astream_events),展示如何在 Chain 和 ChatModel 中获取中间状态。内容涵盖事件过滤机制、回调传播策略以及@tool 装饰器的变化,并提供完整的代码示例与最佳实践建议,帮助开发者构建可观测性强的 LLM 应用。

v0.1 是初始版本,包含基本功能。从 0.1 到 0.2 完成的关键特性包括:
注意:自 0.2.0 版本起,langchain 不再依赖 langchain-community。langchain-community 将依赖于 langchain-core 和 langchain。
从 0.2.0 版开始,langchain 必须与集成无关。这意味着,langchain 中的代码默认情况下不应实例化任何特定的聊天模型、LLMs、嵌入模型、vectorstores 等;相反,用户需要明确指定这些模型。
以下这些 API 从 0.2 版本起要显式的传递 LLM:
langchain.natbot.NatBotChain.from_default 已被移除,推荐使用 from_llm 类方法。0.2 前运行结果会显示工具签名:my_tool: (x: str) -> str - Some description.
0.2 后的运行结果简化为:Some description.
LangChain 简化了 LLM 应用程序生命周期的每个阶段:
该框架目前将自身定位为覆盖 LLM 应用开发全生命周期的框架。包含开发、部署、工程化三个大方向:
0.2 版本对依赖包做了较大调整,详细参照官方文档表格。主要变化是解耦了核心功能与社区集成。
安装该工具:
pip install langchain-cli
注意:该工具并不完美,在迁移前你应该备份好你的代码。使用的时候您需要运行两次迁移脚本,因为每次运行只能应用一次导入替换。
命令示例:
langchain migrate import --all
大模型在推理时由于要对下一个字的概率进行计算,所以无论多么牛逼的 LLM,在推理的时候或多或少都有一些延迟。而这种延迟在类似 Chat 的场景里,体验非常不好。除了在 LLM 上下功夫外,提升最明显的就是从用户体验着手,采用类似流式输出的方式,加快反馈提升用户体验,让用户感觉快乐很多,这也是为什么 ChatGPT 会采用这种类似打字机效果的原因。
流式在 LangChain 前面版本已经支持不少,在 0.2 版本里,主要是增加了事件支持,方便开发者对流可以有更细致的操作颗粒度。
我们知道从 0.1 大版本开始,LangChain 就支持所谓的 Runnable 协议,为大部分组件都添加了一些交互接口,其中流的接口有:
from langchain_core.messages import HumanMessage, AIMessageChunk
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-3.5-turbo")
for chunk in llm.stream("你好,世界!"):
print(chunk.content, end="", flush=True)
在使用 Chain 时,同样可以获取流式输出。这允许我们在处理过程中逐步消费数据。
很多时候的实际场景是,我们希望接口输出的是一个 JSON 结构,这样在前端应用层面会比较灵活。但是如果是流式输出,很可能因为字符结构没有输出结束会导致 JSON 报错。这种情况可以这样处理:
我们可以利用 output_parser 结合流式生成,确保每一步都是合法的 JSON 片段,或者等待完整结构后再解析。以下是处理国家信息的示例逻辑:
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.runnables import RunnableLambda
# 定义输出解析器
parser = JsonOutputParser()
# 构建 Chain
chain = (
{"countries": RunnableLambda(lambda x: [])}
# ... 后续逻辑根据实际需求填充
)
在实际应用中,我们期望在这种结构下,可以以流式来取到国家名称。这里需要在 JSON 输出后,继续处理流事件,提取特定字段。
并不是所有的组件都支持流式输出,比如检索器就不支持。在原生的 LangChain 中,当你给不支持 stream 的组件调用流接口时,一般不会有打字机效果,而是和使用 invoke 效果差不多。而当你使用 LCEL 去调用类似检索器组件的时候,它依然可以搞出来打字机效果,这也是为什么要尽量使用 LCEL 的原因。
原生检索器在这种情况下只会返回最终结果,并没有流的效果。而使用 LCEL 调用后,则可以输出中间的过程。例如使用 FAISS 作为向量存储:
import faiss
from langchain_community.vectorstores import FAISS
from langchain_core.embeddings import Embeddings
# 假设已初始化 embeddings 和 index
# retriever = FAISS(...).as_retriever()
如要使用该特性,你首先要确认自己的 langchain_core 版本等于 0.2。
import langchain_core
print(langchain_core.__version__)
# '0.2.18'
官方给到了一些注意事项:
LangChain 将流的过程细化,并在每个阶段给了开发者一个事件钩子,每个阶段都可以获取输出结果。
from langchain_core.callbacks import CallbackManagerForLLMRun
from langchain_core.language_models.chat_models import BaseChatModel
# 配置 version=v2 参数表明 events 事件流依然是一个 beta API,后面肯定还有更改,所以商业应用要慎重!
# 该参数只在 langchain-core>=0.2.0 作用!
事件流输出示例:
[
{
"event": "on_chat_model_start",
"data": {"input": "hello"},
"name": "ChatZhipuAI",
"run_id": "c87b9c20-6dbf-41d3-989a-0b609c0b3fb4"
},
{
"event": "on_chat_model_stream",
"data": {"chunk": {"content": "Hello"}},
"run_id": "c87b9c20-6dbf-41d3-989a-0b609c0b3fb4"
}
]
在 Chain 内部,事件会按照执行顺序触发,包括 start、end、stream 等。这使得我们可以追踪整个 Chain 的执行路径。
结合事件以及配置参数,可以很方便的找出你想要的阶段数据。通过定义名字实现事件的筛选,后续想要使用的块。
可以使用 tags 参数来标记特定的运行步骤,然后在监听事件时过滤出带有特定 tags 的事件。
config = {"tags": ["retrieval"]}
result = chain.invoke(input, config=config)
在工具中使用调用可运行项,则需要将回调传播到可运行项;否则,不会生成任何流事件。
当工具内部调用了 Chain 或其他 Runnable 时,必须确保配置正确传递,以保证事件链路不断裂。
{'event': 'on_tool_start', 'data': {'input': 'hello'}, 'name': 'correct_tool'}
{'event': 'on_chain_start', 'data': {'input': 'hello'}, 'parent_ids': ['...']}
{'event': 'on_chain_end', 'data': {'output': 'olleh'}}
{'event': 'on_tool_end', 'data': {'output': 'olleh'}}
astream 和 astream_events 以避免阻塞主线程。on_chain_start/end 和 on_chat_model_stream 构建详细的日志系统,便于调试和成本分析。eventsource-parser 配合后端流式输出)来处理不完整的 JSON 片段。通过上述优化,开发者可以更高效地构建可观测、高性能且易于维护的 LLM 应用。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online