FEATURED · 精选文章

LangChain设计模式03:装饰器模式

发布时间 / 2026/9/4 5:15:10
来源 / 创域科博编辑部
栏目 / 资讯中心
LangChain设计模式03:装饰器模式 LangChain设计模式之装饰器模式LangChain 的 Middleware本质上是装饰器。它把 Runnable 包装成新的 Runnable在不修改原代码的前提下把日志、重试、缓存这些横切能力叠加到执行链上。一、一句话结论装饰器模式在 LangChain 中解决的核心问题是如何在不侵入核心组件的前提下为它动态增加能力并让增强逻辑具备可组合、可回溯的特性。在 LangChain 中所有 Middleware 都是 Runnable 装饰器。它们接受一个 Runnable返回一个新的 Runnable在原invoke前后插入自己的逻辑。二、为什么还需要“洋葱”这个词LangChain Middleware 的架构通常被描述成“洋葱责任链”。它包含两个层次架构层洋葱责任链定义请求正向穿透、响应反向回溯的双向数据流。实现层装饰器模式通过动态包装 Runnable落地层层嵌套和功能增强。一句话洋葱责任链定“形”装饰器模式落“实”。外层 Middleware └── 中层 Middleware └── 内层 Middleware └── 核心 Runnable请求从最外层进入逐层向内响应和异常从最内层返回逐层向外。这个结构正是装饰器多层包装的结果。三、装饰器模式的本质装饰器是结构型设计模式动态地给一个对象添加额外的职责而不改变它原有的类定义和接口。在 LangChain 的语境下Middleware Callable[[Runnable], Runnable]装饰器的输入是 Runnable输出还是 Runnable。接口没有变因此可以无限嵌套但行为增强了因此可以在原执行流前后加入逻辑。四、核心实现日志与重试4.1 定义中间件类型fromlangchain_core.runnablesimportRunnable,RunnableLambdafromtypingimportCallable,Optional MiddlewareCallable[[Runnable],Runnable]4.2 日志中间件deflog_middleware(name:str)-Middleware:defwrap(runnable:Runnable)-Runnable:defnew_invoke(input,config:Optional[dict]None):print(f【{name}】开始执行输入{input})try:resultrunnable.invoke(input,config)print(f【{name}】执行完成输出{result})returnresultexceptExceptionasexc:print(f【{name}】执行失败异常{str(exc)})raisereturnRunnableLambda(new_invoke)returnwrap这里有三个关键点wrap接收原 Runnable返回新 Runnable。new_invoke在调用内层 Runnable 前后插入日志。异常会被记录后继续向上抛保证外层装饰器还能感知到错误。4.3 重试中间件defretry_middleware(retries:int3)-Middleware:defwrap(runnable:Runnable)-Runnable:defnew_invoke(input,config:Optional[dict]None):foriinrange(retries):try:ifi0:print(f【重试】第{i}次重试执行)returnrunnable.invoke(input,config)exceptExceptionasexc:ifiretries-1:print(f【重试】所有重试失败异常{str(exc)})raisereturnRunnableLambda(new_invoke)returnwrap4.4 缓存中间件缓存也是同一套包装思路。核心 Runnable 不变只在调用前查缓存、调用后写缓存defcache_middleware()-Middleware:cache:dict{}defwrap(runnable:Runnable)-Runnable:defnew_invoke(input,config:Optional[dict]None):keystr(input)ifkeyincache:print(【缓存】命中缓存)returncache[key]resultrunnable.invoke(input,config)cache[key]resultreturnresultreturnRunnableLambda(new_invoke)returnwrap五、把装饰器组装成洋葱有了多个装饰器就可以像套娃一样包装同一个核心 Runnabledefcore_process(text:str)-str:iflen(text)10:raiseException(输入过短)returntext.upper()coreRunnableLambda(core_process)chainlog_middleware(外层日志)(retry_middleware(2)(cache_middleware()(core)))resultchain.invoke(hello langchain)构建出的结构是外层日志 └── 重试 └── 缓存 └── core_process5.1 正向穿透外层日志 before → 重试 before → 缓存 before → core_process5.2 反向回溯core_process 返回结果或抛出异常 → 缓存 after → 重试 after → 外层日志 after这里体现出装饰器在 LangChain 中的独特价值它不只是“加日志”而是通过after钩子和异常向上抛出支撑了“请求正向、响应反向”的双向执行。六、它和传统装饰器有什么不同传统装饰器往往关心“对象不变能力增加”。LangChain 中的装饰器在此基础上多承担了一个职责维度传统装饰器LangChain 装饰器目标动态增强对象动态包装 Runnable组合方式类或函数包裹Middleware函数嵌套数据流单向调用正向穿透 反向回溯异常处理可以吞掉或包装记录后继续上抛形成异常回溯换句话说LangChain 的装饰器不只是在做功能扩展它同时是洋葱责任链的实现机制。七、实践建议在实际项目里不要把日志、重试、缓存、鉴权、限流写进核心业务组件。应该把它们做成 Middleware在链路外层按需组合。好处是核心 Runnable 保持纯净可独立测试。中间件可复用组合顺序可配置。出问题时日志装饰器能帮助你快速还原正向调用和反向异常路径。八、总结LangChain 的装饰器模式怎么落地LangChain Middleware 本质是Callable[[Runnable], Runnable]。装饰器包装原 Runnable返回新 Runnable接口保持不变。在新invoke中通过 before 和 after 钩子实现正向与反向逻辑。多层装饰器嵌套形成洋葱结构。日志、重试、缓存、鉴权等横切能力都用这种非侵入方式叠加。
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻