AI智能体设计模式系列(三)—— 并行化模式

并行化模式概述

许多复杂的 Agent 任务涉及多个可同时执行而非顺序执行的子任务。这正是并行化模式变 得至关重要的场景。

并行化涉及并发执行多个组件,包括 LLM 调用、工具使用乃至整个子 Agent。不同于顺序等待每 个步骤完成,并行执行允许独立任务同时运行,从而显著缩短可分解为独立部分的任务的总执行时间。

图1 并行化设计模式

  • 并行化是一种通过并发执行独立任务来提高效率的模式

  • ・ 在涉及等待外部资源(如API调用)的任务中特别有效

  • ・ 采用并发或并行架构会引入显著复杂性和成本,影响设计、调试和系统日志等关键开发环节

  • ・ 像LangChain和GoogleADK这样的框架提供定义和管理并行执行的内置支持

  • ・ 在LangChain表达式语言(LCEL)中,RunnableParallel是并行运行多个可运行对象的关键构造

  • ・ GoogleADK可通过LLM驱动的委托实现并行执行,协调器Agent的LLM识别独立子任务并触发专门

    子 Agent 的并发处理

  • ・ 并行化有助于减少整体延迟,使Agent系统在处理复杂任务时更具响应性

在LangChain表达式语言(LCEL)中,RunnableParallel 是一个用于并行执行多个可运行对象的工具。它允许我们将一个输入同时传递给多个可运行对象(如链、工具、函数等),然后将它们的结果合并到一个字典中。这样,我们可以并行地执行多个任务,从而提高效率。

基本用法:

我们可以通过传递一个字典给 RunnableParallel 来创建它,字典的键是输出结果中的键,值是可运行对象(可以是任何实现了 Runnable 接口的对象,如链、提示模板、模型等)。

示例:

假设我们有两个链,一个用于生成笑话,另一个用于生成总结。我们可以使用 RunnableParallel 同时运行它们。

步骤:

  1. 定义两个可运行对象(这里假设是两个简单的链,但可以是任何可运行对象)。

  2. 使用 RunnableParallel 将这两个链组合起来,并指定输出字典中的键。

  3. 调用组合后的可运行对象。

注意:RunnableParallel 不会保证执行顺序,但会并行执行所有可运行对象。

另外,RunnableParallel 也支持与 RunnableMap 类似的用法,但 RunnableMap 更侧重于将一个输入映射到多个输出,而 RunnableParallel 更强调并行执行。

基本概念

RunnableParallel 允许你将一个输入同时传递给多个可运行对象(链、函数、模型等),并将它们的结果合并成一个字典。

基本用法

python 复制代码
from langchain_core.runnables import RunnableParallel

# 创建并行执行的runnable
parallel_runnable = RunnableParallel({
    "joke": joke_chain,        # 第一个可运行对象
    "summary": summary_chain,   # 第二个可运行对象
    "length": length_func       # 第三个可运行对象(函数)
})

# 执行 - 所有组件并行运行
result = parallel_runnable.invoke("关于AI的笑话")
# 返回: {"joke": "...", "summary": "...", "length": 42}

常见使用场景

1. 并行处理多个任务

python 复制代码
from langchain_core.runnables import RunnableParallel, RunnableLambda

# 定义不同的处理函数
def extract_names(text):
    return extract_name_chain.invoke(text)

def extract_dates(text):
    return extract_date_chain.invoke(text)

def analyze_sentiment(text):
    return sentiment_chain.invoke(text)

# 并行执行
analyzer = RunnableParallel({
    "names": RunnableLambda(extract_names),
    "dates": RunnableLambda(extract_dates),
    "sentiment": RunnableLambda(analyze_sentiment)
})

2. 结合管道使用

python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

# 创建多个处理链
joke_chain = ChatPromptTemplate.from_template("讲一个关于{topic}的笑话") | model
poem_chain = ChatPromptTemplate.from_template("写一首关于{topic}的诗") | model
summary_chain = ChatPromptTemplate.from_template("总结{topic}") | model

# 并行执行然后合并
parallel = RunnableParallel({
    "joke": joke_chain,
    "poem": poem_chain,
    "summary": summary_chain
})

# 在管道中使用
full_chain = (
    {"topic": lambda x: x} 
    | parallel
    | combine_results_chain
)

3. 收集多个来源的信息

python 复制代码
# 从不同知识库并行检索
retrieval_chain = RunnableParallel({
    "legal_info": legal_retriever,
    "technical_info": technical_retriever,
    "general_info": general_retriever
})

# 使用检索结果生成答案
qa_chain = (
    {"question": lambda x: x, "context": retrieval_chain}
    | prompt
    | model
    | output_parser
)

高级用法

动态配置

python 复制代码
# 根据条件动态选择并行组件
def dynamic_parallel(input_dict):
    config = input_dict.pop("config")
    components = {}
    
    if config.get("extract_entities", True):
        components["entities"] = entity_extractor
    if config.get("classify", True):
        components["classification"] = classifier
        
    return RunnableParallel(components).invoke(input_dict)

错误处理

python 复制代码
from langchain_core.runnables import RunnableConfig

class SafeRunnableParallel(RunnableParallel):
    def invoke(self, input, config=None):
        try:
            return super().invoke(input, config)
        except Exception as e:
            # 处理部分失败的情况
            results = {}
            for key, runnable in self.config["runnables"].items():
                try:
                    results[key] = runnable.invoke(input, config)
                except:
                    results[key] = f"Error processing {key}"
            return results

性能优势

  1. 真正的并行执行:使用异步时,RunnableParallel可以真正并行执行

  2. 减少延迟:对于需要多个独立处理步骤的任务,并行执行可以显著减少总延迟

  3. 资源优化:当不同组件使用不同资源时(CPU/IO),并行执行可以提高利用率

异步支持

python 复制代码
import asyncio

async def process_concurrently():
    parallel = RunnableParallel({
        "chain1": chain1,
        "chain2": chain2,
        "chain3": chain3
    })
    
    # 异步调用
    result = await parallel.ainvoke(input_data)
    return result

实际应用示例

python 复制代码
# 一个完整的文档处理流水线
document_processor = RunnableParallel({
    # 并行提取不同类型的信息
    "summary": summary_extractor,
    "keywords": keyword_extractor,
    "entities": entity_extractor,
    "sentiment": sentiment_analyzer,
    
    # 并行验证不同方面
    "fact_check": fact_checker,
    "grammar_check": grammar_checker,
    "plagiarism_check": plagiarism_checker,
    
    # 并行生成不同格式的输出
    "html": html_generator,
    "markdown": markdown_generator,
    "json": json_generator
})

# 使用
processed = document_processor.invoke(document_text)

RunnableParallel是构建高效、模块化LCEL链的关键工具,特别适合需要同时执行多个独立任务的场景。

结论

并行化模式是通过并发执行独立子任务来优化计算工作流的方法。该模式有效减少整体延迟,在涉及多个模 型推理或对外部服务调用的复杂操作中尤为显著。

不同框架为此模式提供了不同的实现机制。在 LangChain 中,通过 RunnableParallel 等构造显式定义并同 时执行多个处理链。而 Google Agent Developer Kit (ADK) 等框架则通过多 Agent 委托实现并行化,由主协 调器模型将不同子任务分配给可并发操作的专门 Agent。

相关推荐
不丿二2 小时前
AI 时代下的个人工作台沉淀——一个越用越懂你的本地 AI 助手
ai编程
子兮曰3 小时前
OpenMontage 深度解剖:你的 AI 编程助手,其实是个视频工作室
前端·后端·ai编程
Hyyy4 小时前
Function Calling / Tool Use的原理和实现模式
前端·llm·ai编程
刘棕霆4 小时前
24—AI Skill 测评工作流工具箱化:为什么 regression 会自然出现
aigc·ai编程·测试
leeyi7 小时前
Callback 系统:给 Agent 管道装上“监听器“
aigc·agent·ai编程
Momo__7 小时前
MDN MCP Server——Mozilla 把 Web 文档接进 AI Agent,从此 LLM 不再瞎编 API
前端·ai编程·mcp
kyriewen8 小时前
折腾了半年 AI 编程工作流,最后发现效率瓶颈是桌上那块屏幕
前端·javascript·ai编程
猪猪拆迁队9 小时前
虚拟工厂仿真引擎的架构设计:让一条产线可编程、可观测、可干预
后端·ai编程
ZzT9 小时前
让 AI 少写一半代码:拆解爆火的 ponytail
ai编程·claude
Bigger10 小时前
从零搭建 AI 代码审查服务:一份前端也能看懂的 Python 学习笔记
前端·ci/cd·ai编程