几种AI Agent开发框架对比:相比手写代码是否更便捷?

在之前几篇文章中,Chaiys同学设计了一个高考信息查询智能助手AI Agent业务场景,分别使用手写代码LangChain框架QwenAgent框架AgentScope框架实现了一次,学习了几大框架如何开发智能体。

在此基础上,我们进一步对比它们在业务逻辑编排、大模型调用、工具调用、上下文记忆、多智能体协作等方面的差异,看看框架是否确实能方便我们进行智能体开发。

业务逻辑编排对比

首先回顾一下我们的业务流程:

接下来分别使用手写代码和几种框架来实现这个业务流程逻辑,看看差异所在。

1、手写代码

纯编码时,我们直接根据业务逻辑来串联工作流:

python 复制代码
# sql agent
def sql_agent(user_query):
    # 1. 语义匹配
    table = semanticService.hybrid_search(user_query, 1)
    if not table:
        print(f"未匹配到字段")
        return Result.error()
    table_struct = [t["table_info"] for t in table]
    prompt = f"""
            你是一个MySQL专家。根据以下表结构信息:
            {table_struct}

            历史问答(仅供参考):"{mm.get_messages(session_id)}"
            
            用户查询:"{user_query}"

            生成标准MYSQL查询语句。
            要求:
            1. 只输出MYSQL语句,不要额外解释
            2. 根据语义和字段类型,使用COUNT/SUM/AVG等聚合函数进行计算,非必须
            3. 给生成的字段取一个简短的中文名称
            输出格式:使用[]包含sql文本即可,不需要其他输出,便于解析,例如:[select 1 from dual]
        """
    print(f"SQL AGENT PROMPT={prompt}")
    # 2. 大模型生成SQL
    str1 = analysisService.analysis(prompt)
    sql = re.search(r'[(.*?)]', str1, re.DOTALL).group(1).strip()

    # 3. 执行查询
    if not sql:
        print("\nSQL生成失败")
        return Result.error()

    resultSet = queryService.query_with_column(sql)
    if not resultSet:
        print("\nSQL查询失败")
        return Result.error()
    return Result.success(data={ "tableStruct": table_struct, "resultSet": resultSet, "sql": sql })

# analysis agent
def analysis_agent(user_query, data):
    # 基础分析
    prompt = f"""
                根据以下表结构信息:
                {data['tableStruct']}
                
                查询SQL:
                {data['sql']}
                
                和以下数据信息:
                {data['resultSet']}

                历史问答(仅供参考):"{mm.get_messages(session_id)}"
                
                用户查询:"{user_query}"

                生成一段简要分析,加上一些预测总结的内容
            """
    print(f"ANALYSIS AGENT PROMPT={prompt}")
    return Result.success(analysisService.analysis(prompt))

def workflow(user_input):
    # 1 - SQL Agent
    result = sql_agent(user_input)
    if not result.success:
        returnNone
    # 2 - Analysis Agent
    return analysis_agent(user_input, result.data)

2、LangChain框架

使用LangChain框架的Chain模式时,可以手动串联业务流程逻辑:

ini 复制代码
# 构建顺序链
overall_chain = SequentialChain(
    chains=[
        TransformChain(
            input_variables=["user_query"],
            output_variables=["table_schema"],
            transform=get_table_schema
        ),
        TransformChain(
            input_variables=["user_query", "table_schema"],
            output_variables=["sql_result", "generated_sql"],
            transform=execute_sql
        ),
        analysis_chain
    ],
    input_variables=["user_query"],
    output_variables=["analysis_result"],
    verbose=True
)

LangChain 已经发展出丰富的 Chain 类型,用于构建复杂、模块化的 LLM 应用,这里就不一一介绍了。

LangChain框架除了提供Chain模式外,还可以使用的Agent模式来实现,通过提示词来指定业务流程逻辑,然后直接调用工具,如下:

ini 复制代码
# 初始化Agent
agent = initialize_agent(
    tools=[semantic_tool, sql_tool],
    llm=llm,
    agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
    verbose=True,
    handle_parsing_errors=True,
    max_iterations=10,  # 增加最大迭代次数以支持多步查询
    early_stopping_method="generate"
)

def chat(user_query):
    print("执行方法chat")

    # 更明确的指令
    enhanced_query = f"""
    问题:{user_query}

    请特别注意:这个问题可能需要从多个表中查询数据。
    1. 首先确定需要查询哪些数据
    2. 使用match_metadata工具分别匹配包含这些数据的表结构
    3. 对每个表生成相应的SQL查询语句
    4. 执行查询并汇总结果
    5. 最后计算并给出答案

    请确保逐步执行,不要跳过任何步骤。
    """

    try:
        result = agent.run(enhanced_query)
        print(f"\n最终结果: {result}")
    except Exception as e:
        print(f"执行过程中出错: {str(e)}")
        # 这里可以添加重试或更详细的错误处理逻辑

3、QwenAgent框架

QwenAgent框架则只能通过提示词方式指定业务流程逻辑,然后直接调用Assistant等待用户输入:

ini 复制代码
# 创建Agent实例
agent = Assistant(
    name='ai_agent_assistant',
    llm={
        'model': 'qwen3:32b',
        'model_server': 'http://localhost:11434/v1',
    },
    system_message="""
        你是一个数据分析助手,负责帮助用户查询数据库信息。
        请特别注意:用户的问题可能需要从多个表中查询数据。
        1. 首先确定需要查询哪些数据
        2. 使用match_metadata工具分别匹配包含这些数据的表结构
        3. 对每个表生成相应的SQL查询语句
        4. 执行查询并汇总结果
        5. 最后计算并给出答案

        请确保逐步执行,不要跳过任何步骤。
    """,
    function_list=[MatchMetadataTool(), ExecuteSQLTool()],
)

4、AgentScope框架

AgentScope框架中支持单体Agent模式,将工具提供给框架,再通过提示词来指定业务流程逻辑:

ini 复制代码
async def interactive_react_agent() -> None:
    """创建一个支持多轮对话的ReAct智能体。"""
    # 准备工具
    toolkit = Toolkit()
    toolkit.register_tool_function(match_metadata)
    toolkit.register_tool_function(execute_sql)

    jarvis = ReActAgent(
        name="Jarvis",
        sys_prompt="""
            你是一个数据分析助手,负责帮助用户查询数据库信息。
            请特别注意:用户的问题可能需要从多个表中查询数据。
            1. 首先确定需要查询哪些数据
            2. 使用match_metadata工具分别匹配包含这些数据的表结构
            3. 对每个表生成相应的SQL查询语句
            4. 执行查询并汇总结果
            5. 最后计算并给出答案

            请确保逐步执行,不要跳过任何步骤。
        """,
        model=OllamaChatModel(
            model_name="qwen3:32b",  # 指定模型名称
            stream=True,  # 根据需要设置是否流式输出
            enable_thinking=True,  # 为Qwen3启用思考功能(可选)
            # host="http://localhost:11434" # 如果Ollama不在默认地址,需指定
        ),
        formatter=OllamaChatFormatter(),
        toolkit=toolkit,
        memory=InMemoryMemory(),
    )

小结

手写代码需人工串联各个步骤,灵活但开发成本高,维护复杂。各框架则提供了丰富的链(Chain)或Agent模式,支持流程模块化、工具调用自动化,极大提升开发效率和可维护性。

模型调用对比

接下来看看手写代码和使用开发框架,都是如何调用大模型的,如何处理大模型的流式输出的。

1、手写代码

通过HTTP方式调用外部大模型示例:

python 复制代码
import requests
# Analysis API
class AnalysisService:
    def __init__(self):
        self.ollama_host = "http://localhost:11434/api/chat"

    def analysis(self, prompt, model="deepseek-r1:32b", messages=None):
        # 发送POST请求
        if messages isNone:
            messages = []
        str = ""
        newMessages = messages[:]
        newMessages.append({"role": "user", "content": prompt})
        # 请求数据
        data = {
            "model": model,
            "messages": newMessages,
            "stream": True
        }
        isThinking = False
        with requests.post(self.ollama_host, json=data, stream=True) as response:
            # 处理流式响应
            for line in response.iter_lines():
                if line:
                    decoded_line = line.decode('utf-8')
                    try:
                        # 解析JSON数据
                        chunk = json.loads(decoded_line)
                        content = chunk['message']['content']
                        if "<think>"in content:
                            isThinking = True
                        if "</think>"in content:
                            isThinking = False
                        if not isThinking and"</think>"notin content:
                            str += chunk['message']['content']
                        # 打印消息内容
                        print(chunk['message']['content'], end='', flush=True)
                    except json.JSONDecodeError:
                        print(f"无法解析JSON: {decoded_line}")
        return str

使用官方或社区封装的 Python 包(如 ollama 包)调用示例:

ini 复制代码
import ollama

# 调用模型生成回复,流式输出
for chunk in ollama.chat(
    model='deepseek-r1:32b',
    messages=[{'role': 'user', 'content': '讲一个笑话'}],
    stream=True
):
    print(chunk['message']['content'], end='', flush=True)

2、LangChain框架

LangChain内部集成支持多种类型的模型调用,以下列举部分:

模型类型 支持模型示例 示例代码
GGUF 格式(Llama.cpp) Llama 3, Mistral, Phi-3, Gemma 等 python from langchain_community.llms import LlamaCpp llm = LlamaCpp(model_path="/path/to/model.gguf", n_ctx=2048)
Transformers (PyTorch) Llama 3, Qwen, GLM, Mistral, Falcon 等 python from langchain_community.llms import HuggingFacePipeline pipe = pipeline("text-generation", model="Qwen/Qwen2-7B-Instruct") llm = HuggingFacePipeline(pipeline=pipe)
vLLM (高性能推理) 支持所有 Transformers 模型 python from langchain_community.llms import VLLM llm = VLLM(model="Qwen/Qwen2-7B-Instruct", tensor_parallel_size=1)
Ollama llama3, mistral, phi3, qwen2, gemma 等 python from langchain_ollama import OllamaLLM llm = OllamaLLM(model="llama3")
Local LLM via API 任意本地模型 python from langchain_openai import ChatOpenAI llm = ChatOpenAI( base_url="<http://localhost:1234/v1>", api_key="not-needed", model="local-model" )

3、QwenAgent框架

QwenAgent内部集成支持通用HTTP方式调用大模型:

ini 复制代码
...
# 创建Agent实例
agent = Assistant(
    name='ai_agent_assistant',
    llm={
        'model': 'qwen3:32b',
        'model_server': 'http://localhost:11434/v1',
    },
    ...

4、AgentScope框架

AgentScope内部集成多模型支持:

模型平台 类名 说明
Ollama OllamaChatModel 调用本地 Ollama 服务,支持 qwen3:32b 等模型,支持 enable_thinking=True
阿里云 DashScope(Qwen) DashScopeChatModel 调用 Qwen 系列 API(qwen-max/plus/turbo/vl),支持 enable_thinking(Qwen3/QwQ/DeepSeek-R1)
OpenAI OpenAIChatModel 调用 GPT 系列(gpt-4o、gpt-3.5-turbo 等),支持 reasoning_effort(o3/o4)
Anthropic AnthropicChatModel 调用 Claude 系列(opus/sonnet/haiku),支持 thinking 配置
Google Gemini GeminiChatModel 调用 Gemini 1.5/2.0 系列,支持 thinking_config(如 include_thoughts=True

小结

手写代码通常直接调用HTTP接口或使用官方SDK,需自行处理流式输出的循环响应和异常。而几种开发框架都内置对多种模型的统一封装,只要简单配置即可,简化了调用过程,提升了稳定性和扩展性。

工具调用对比

现在AI Agent中调用工具Tools已经是典型场景了,所以接下来对这块做个对比分析。

1、手写代码

需要手动调用外部工具:

python 复制代码
...
# sql agent
def sql_agent(user_query):
    # 1. 语义匹配
    table = semanticService.hybrid_search(user_query, 1)
    ...
    # 3. 执行查询
    if not sql:
        print("\nSQL生成失败")
        return Result.error()
    
    resultSet = queryService.query_with_column(sql)
    ...

2、LangChain框架

Agent模式初始化传入tools即可:

ini 复制代码
# 初始化Agent
agent = initialize_agent(
    tools=[semantic_tool, sql_tool],
    llm=llm,
    agent=AgentType.CONVERSATIONAL_REACT_DESCRIPTION,
    verbose=True,
    handle_parsing_errors=True,
    max_iterations=10,  # 增加最大迭代次数以支持多步查询
    early_stopping_method="generate",
    memory=memory
)

3、QwenAgent框架

Agent模式初始化传入tools即可:

ini 复制代码
# 创建Agent实例
agent = Assistant(
    name='ai_agent_assistant',
    llm={
        'model': 'qwen3:32b',
        'model_server': 'http://localhost:11434/v1',
    },
    system_message="""
        你是一个数据分析助手,负责帮助用户查询数据库信息。
        请特别注意:用户的问题可能需要从多个表中查询数据。
        1. 首先确定需要查询哪些数据
        2. 使用match_metadata工具分别匹配包含这些数据的表结构
        3. 对每个表生成相应的SQL查询语句
        4. 执行查询并汇总结果
        5. 最后计算并给出答案

        请确保逐步执行,不要跳过任何步骤。
    """,
    function_list=[MatchMetadataTool(), ExecuteSQLTool()],
)

需要处理一下流式输出结果,获取文本内容:

ini 复制代码
def read_steam_response(response_generator):
    # 处理生成器响应
    full_response = ''
    start = 0
    end = 0
    for response in response_generator:
        # 检查响应类型并适当处理
        if isinstance(response, list):
            # 如果是列表,提取内容
            for item in response:
                if isinstance(item, dict) and'content'in item:
                    full_response = item['content']
                    end = full_response.__len__()
                elif isinstance(item, str):
                    full_response = item
                    end = full_response.__len__()
        elif isinstance(response, dict) and'content'in response:
            full_response = response['content']
            end = full_response.__len__()
        elif isinstance(response, str):
            full_response = response
            end = full_response.__len__()
        print(f"{full_response[start:end]}", end="")
        start = end

    return full_response

4、AgentScope框架

Agent模式初始化传入tools即可:

ini 复制代码
# 准备工具
toolkit = Toolkit()
toolkit.register_tool_function(match_metadata)
toolkit.register_tool_function(execute_sql)

jarvis = ReActAgent(
    name="Jarvis",
    sys_prompt="""
        你是一个数据分析助手,负责帮助用户查询数据库信息。
        请特别注意:用户的问题可能需要从多个表中查询数据。
        1. 首先确定需要查询哪些数据
        2. 使用match_metadata工具分别匹配包含这些数据的表结构
        3. 对每个表生成相应的SQL查询语句
        4. 执行查询并汇总结果
        5. 最后计算并给出答案

        请确保逐步执行,不要跳过任何步骤。
    """,
    model=OllamaChatModel(
        model_name="qwen3:32b",  # 指定模型名称
        stream=True,  # 根据需要设置是否流式输出
        enable_thinking=True,  # 为Qwen3启用思考功能(可选)
        # host="http://localhost:11434" # 如果Ollama不在默认地址,需指定
    ),
    formatter=OllamaChatFormatter(),
    toolkit=toolkit,
    memory=InMemoryMemory(),
)

小结

手写开发中需显式调用语义检索、SQL查询等工具,几种框架都支持通过工具注册机制自动完成调用与路由,降低耦合并增强复用。

上下文记忆对比

在AI Agent实践过程中,如果需要实现多轮对话,就会碰到上下文记忆的处理,所以接下来对这块做个对比。

1、手写代码

这种模式需要手写代码来管理上下文消息:

python 复制代码
import threading
from dataclasses import dataclass
from typing importList, Dict, Any


@dataclass
class Message:
    role: str# "system", "user", "assistant"
    content: str

    def to_dict(self) -> Dict[str, str]:
        return {"role": self.role, "content": self.content}


class MessageManager:
    def __init__(self, max_history: int = 10):
        """
        初始化消息管理器

        :param max_history: 每个 session 最多保留的历史消息数量(不包括 system 消息)
        """
        self.max_history = max_history
        self._sessions: Dict[str, Dict[str, Any]] = {}
        self._lock = threading.Lock()  # 保证线程安全

    def set_system_message(self, session_id: str, content: str) -> None:
        """为指定 session 设置 system 消息(会覆盖旧的)"""
        with self._lock:
            if session_id notinself._sessions:
                self._sessions[session_id] = {
                    "system": None,
                    "history": []  # 只存 user/assistant 对话
                }
            self._sessions[session_id]["system"] = Message(role="system", content=content)

    def add_user_message(self, session_id: str, content: str) -> None:
        """添加用户消息"""
        self._add_message(session_id, "user", content)

    def add_assistant_message(self, session_id: str, content: str) -> None:
        """添加助手回复"""
        self._add_message(session_id, "assistant", content)

    def _add_message(self, session_id: str, role: str, content: str) -> None:
        with self._lock:
            if session_id notin self._sessions:
                self._sessions[session_id] = {
                    "system": None,
                    "history": []
                }
            history = self._sessions[session_id]["history"]
            history.append(Message(role=role, content=content))
            # 限制历史长度(只保留最近的 max_history 条 user/assistant 消息)
            if len(history) > self.max_history * 2:  # 每轮对话含 user + assistant
                # 保留最后 max_history * 2 条
                self._sessions[session_id]["history"] = history[-(self.max_history * 2):]

    def get_messages(self, session_id: str) -> List[Dict[str, str]]:
        """获取可用于 Ollama /api/chat 的 messages 列表"""
        with self._lock:
            session = self._sessions.get(session_id)
            if not session:
                return []

            messages = []
            # 添加 system 消息(如果有)
            if session["system"]:
                messages.append(session["system"].to_dict())
            # 添加历史对话
            for msg in session["history"]:
                messages.append(msg.to_dict())
            return messages

    def clear_session(self, session_id: str) -> None:
        """清除指定 session 的所有消息"""
        with self._lock:
            self._sessions.pop(session_id, None)

    def list_sessions(self) -> List[str]:
        """列出所有 session ID"""
        with self._lock:
            returnlist(self._sessions.keys())

    def delete_session(self, session_id: str) -> bool:
        """删除 session,返回是否删除成功"""
        with self._lock:
            if session_id inself._sessions:
                del self._sessions[session_id]
                return True
            return False

调用时手动传入:

python 复制代码
# sql agent
def sql_agent(user_query):
    # 1. 语义匹配
    table = semanticService.hybrid_search(user_query, 1)
    if not table:
        print(f"未匹配到字段")
        return Result.error()
    table_struct = [t["table_info"] for t in table]
    prompt = f"""
            你是一个MySQL专家。根据以下表结构信息:
            {table_struct}

            历史问答(仅供参考):"{mm.get_messages(session_id)}"
            
            用户查询:"{user_query}"

            生成标准MYSQL查询语句。
            要求:
            1. 只输出MYSQL语句,不要额外解释
            2. 根据语义和字段类型,使用COUNT/SUM/AVG等聚合函数进行计算,非必须
            3. 给生成的字段取一个简短的中文名称
            输出格式:使用[]包含sql文本即可,不需要其他输出,便于解析,例如:[select 1 from dual]
        """
    print(f"SQL AGENT PROMPT={prompt}")
    # 2. 大模型生成SQL
    str1 = analysisService.analysis(prompt)
    sql = re.search(r'[(.*?)]', str1, re.DOTALL).group(1).strip()

    # 3. 执行查询
    if not sql:
        print("\nSQL生成失败")
        return Result.error()

    resultSet = queryService.query_with_column(sql)
    if not resultSet:
        print("\nSQL查询失败")
        return Result.error()
    return Result.success(data={ "tableStruct": table_struct, "resultSet": resultSet, "sql": sql })

# analysis agent
def analysis_agent(user_query, data):
    # 基础分析
    prompt = f"""
                根据以下表结构信息:
                {data['tableStruct']}
                
                查询SQL:
                {data['sql']}
                
                和以下数据信息:
                {data['resultSet']}

                历史问答(仅供参考):"{mm.get_messages(session_id)}"
                
                用户查询:"{user_query}"

                生成一段简要分析,加上一些预测总结的内容
            """
    print(f"ANALYSIS AGENT PROMPT={prompt}")
    return Result.success(analysisService.analysis(prompt))

2、LangChain框架

Agent模式指定:

ini 复制代码
# 记忆
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)

# 初始化Agent
agent = initialize_agent(
    tools=[semantic_tool, sql_tool],
    llm=llm,
    agent=AgentType.CONVERSATIONAL_REACT_DESCRIPTION,
    verbose=True,
    handle_parsing_errors=True,
    max_iterations=10,  # 增加最大迭代次数以支持多步查询
    early_stopping_method="generate",
    memory=memory
)

除了上面用到的 ConversationBufferMemory,LangChain还提供了多种Memory组件,以适应不同场景的需求。可以根据具体情况选择:

Memory 类型 特点 适用场景
ConversationBufferWindowMemory 只保留最近K轮的对话内容,节省上下文空间。 对话频繁,且近期内容更为重要的场景。
ConversationSummaryMemory 对历史对话生成摘要,而非保存全部原文。 对话很长,需要压缩信息以节省Token消耗。
ConversationTokenBufferMemory 根据 Token 数量而非对话轮数来限制记忆长度。 需要精确控制输入给模型上下文的长度和成本。
  • 确认Agent类型 兼容性 :在选用Memory前,请确认你使用的 AgentType 支持Memory功能。例如,ZERO_SHOT_REACT_DESCRIPTION 默认不支持记忆,而 CONVERSATIONAL_REACT_DESCRIPTION 则专为多轮对话设计。
  • 注意上下文长度 :为Agent添加记忆会占用模型的上下文窗口。如果对话很长,考虑使用 ConversationSummaryMemoryConversationBufferWindowMemory 来避免超出限制。
  • 调试工具 :将 verbose 参数设为 True,可以在控制台看到详细的决策过程,有助于观察Memory是否正常工作。

3、QwenAgent框架

Agent模式的Assistant类不支持,需要手动管理:

ini 复制代码
def analysis(user_query):
    try:
        # 运行Agent
        messages = mm.get_messages(session_id) + [{'role': 'user', 'content': user_query}]
        response_generator = agent.run(messages=messages)
        # 处理生成器响应
        full_response = ''
        start = 0
        end = 0
        for response in response_generator:
            # 检查响应类型并适当处理
            if isinstance(response, list):
                # 如果是列表,提取内容
                for item in response:
                    ifisinstance(item, dict) and'content'in item:
                        full_response = item['content']
                        end = full_response.__len__()
                    elifisinstance(item, str):
                        full_response = item
                        end = full_response.__len__()
            elif isinstance(response, dict) and'content'in response:
                full_response = response['content']
                end = full_response.__len__()
            elif isinstance(response, str):
                full_response = response
                end = full_response.__len__()
            print(f"{full_response[start:end]}", end="")
            start = end

        print(f"最终结果: {full_response}")
        # 缓存历史对话
        if full_response:
            mm.add_user_message(session_id, user_query)
            mm.add_assistant_message(session_id, full_response)
        return full_response
    except Exception as e:
        print(f"执行过程中出错: {str(e)}")
        # 这里可以添加重试或更详细的错误处理逻辑
        return f"错误: {str(e)}"

4、AgentScope框架

Agent初始化指定对应类型即可:

ini 复制代码
jarvis = ReActAgent(
    name="Jarvis",
    sys_prompt="""
        你是一个数据分析助手,负责帮助用户查询数据库信息。
        请特别注意:用户的问题可能需要从多个表中查询数据。
        1. 首先确定需要查询哪些数据
        2. 使用match_metadata工具分别匹配包含这些数据的表结构
        3. 对每个表生成相应的SQL查询语句
        4. 执行查询并汇总结果
        5. 最后计算并给出答案

        请确保逐步执行,不要跳过任何步骤。
    """,
    model=OllamaChatModel(
        model_name="qwen3:32b",  # 指定模型名称
        stream=True,  # 根据需要设置是否流式输出
        enable_thinking=True,  # 为Qwen3启用思考功能(可选)
        # host="http://localhost:11434" # 如果Ollama不在默认地址,需指定
    ),
    formatter=OllamaChatFormatter(),
    toolkit=toolkit,
    memory=InMemoryMemory(),
)

小结

手写代码需自行实现消息管理和上下文传递,工作量大且需要手动维护。框架提供多样化记忆组件,支持对话上下文的灵活管理,适配不同对话场景,有效提升对话质量。

多智能体协作对比

自从Google提出A2A协议,多智能体协作已经成为业界实践过程的热点,为进一步对比手写代码和开发框架在多Agent协作上的区别,我们将本案例的程序设计拆分为以下两个Agent:

1、SQL Agent

  • 调用外部语义检索(RAG)API匹配元数据
  • 调用大模型根据元数据和用户提问生成查数SQL
  • 调用查数API查询数据

2、Analysis Agent

  • 调用大模型分析数据回答问题

1、手写代码

需要手动串联多个Agent调用,消息格式自定义传递:

python 复制代码
...
def workflow(user_input):
    # 1 - SQL Agent
    result = sql_agent(user_input)
    if not result.success:
        return None
    # 2 - Analysis Agent
    return analysis_agent(user_input, result.data)
    ...

2、LangChain框架

原生仅支持单体Agent,多Agent需要手动串联,实现类似手写代码。

3、QwenAgent框架

原生仅支持单体Agent,多Agent需要手动串联,实现类似同手写代码。

4、AgentScope框架

基于AgentScope框架,我们可以把 SQLAgent 和 AnalysisAgent 封装为 两个智能体(均继承 AgentBase),然后两个智能体的协作使用顺序管道sequential_pipeline来串联,实现"多智能体任务流转"。

AgentScope 中的主要管道类型包括:

管道函数 类型 作用 特点
sequential_pipeline 串行 按顺序执行多个 Agent(A → B → C) 简单、可控、常用于任务链
parallel_pipeline 并行 同时让多个 Agent 处理同一消息 高性能、适合意见汇总或对比
broadcast_pipeline 广播 将一条消息发送给多个 Agent,但每个独立回复 不等待所有返回,可异步
loop_pipeline 循环 将上一次输出作为下一轮输入,直到满足条件停止 适合多轮协作(例如思考-改进循环)
conditional_pipeline 条件分支 根据消息或 Agent 输出动态选择下一个 Agent 适合复杂决策流
MsgHub 管道 中心化消息调度 多 Agent 通过消息中心异步通信 实现发布-订阅、群聊模式

这几种管道协作模式,具体实践敬请期待下篇文章分享。

小结

手写代码多为线性调用,缺乏并行和复杂调度能力。AgentScope框架支持多Agent并行、条件分支、消息广播等复杂管道模式,适合构建复杂的多智能体协作系统。其他框架都需要手动组合实现。

对比总结

通过以上对比来看,在日常智能体开发中,尤其是需要多轮对话、实现多工具调用和多智能体协作时,几种开发框架确实提供了极大的便利和扩展能力,大幅降低开发门槛和维护成本,而手写代码则适合高度定制化需求,灵活性最高。

功能维度对比

功能模块 手写代码 LangChain Qwen-Agent AgentScope
🔗 业务流程编排 ⚪️ 需手动串联 ✅ 多种Chain串联,强支持 ⚪️ 依靠提示词指定业务流程 ⚪️ 依靠提示词指定业务流程
🌐 模型调用(LLM) ⚪️ http调用或官方包 ✅ 支持广泛 ✅ 原生优化 ✅ 可自定义适配器
🧰 工具调用(Tool) ⚪️ 需手动调用 ✅ 自由定义Tool/组合Tool ✅ 原生支持 ✅ 通过 Agent 工具化
💬 记忆(Memory) ⚪️ 需手动管理 ✅ 多种类型(Buffer/Entity) ⚪️ 需手动管理 ✅ 上下文共享MsgHub等
👥 多 Agent 协作 ⚪️ 需手动串联 ⚪️ 可通过手动组合实现 ⚪️ 可通过手动组合实现 ✅ 框架核心功能(多管道)
🔧 插件生态 ⚪️ 需自定义调用 ✅ 庞大(社区多) ⚪️ 早期阶段 ⚪️ 逐步扩展中

选型建议

使用场景 推荐框架 理由
构建通用 RAG / QA 系统 LangChain 生态成熟、插件丰富
构建 Qwen 系列专用 Agent Qwen-Agent 接口最友好、集成最简单
构建多角色协作系统(Planner + Coder + Critic) AgentScope 专为多 Agent 协作设计
做研究型实验 / 快速原型 Qwen-Agent / LangChain 开发快、文档齐全
做工业级多智能体调度系统 AgentScope 任务协调、上下文共享更强

当然,当我们全定制化开发,还是手写代码更加合适。

🔹 LangChain:适合你搭建任何单体智能体系统(RAG、SQL、工具调用)。

🔹 Qwen-Agent:适合快速构建"基于 Qwen 模型"的问答或助手。

🔹 AgentScope :适合研究或实现多智能体协作系统(Planner、Coder、Critic 等角色联动)。

🔹 手写代码: 高度定制化开发,当我们的手写代码逐步抽象完善,使用的频率多了,就成了框架!

本文总结:本文通过设计高考信息查询智能助手的业务场景,分别采用手写代码和主流智能体框架(LangChain、QwenAgent、AgentScope)进行了实现与比较。我们从业务流程编排、模型调用、工具集成、上下文记忆管理以及多智能体协作等多个维度进行深入分析,对比手写代码与框架调用的异同。

本文作者:Chaiys

本文原载:公众号"木昆子记录AI"

相关推荐
F_D_Z8 小时前
TensorFlow Playground 交互式神经网络可视化工具
人工智能·神经网络·tensorflow
xuejianxinokok8 小时前
如何在 Rust 中以惯用方式使用全局变量
后端·rust
爬山算法8 小时前
Hibernate(26)什么是Hibernate的透明持久化?
java·后端·hibernate
彭于晏Yan8 小时前
Springboot实现数据脱敏
java·spring boot·后端
杭州泽沃电子科技有限公司8 小时前
核电的“热血管”与它的智能脉搏:热转换在线监测如何守护能源生命线
人工智能·在线监测
向阳蒲公英8 小时前
Pycharm2025版本配置Anaconda步骤
python
yuzhiboyouye8 小时前
指引上调是什么意思
人工智能
Darkershadow8 小时前
蓝牙学习之uuid与mac
python·学习·ble
北海有初拥8 小时前
Python基础语法万字详解
java·开发语言·python
alonewolf_998 小时前
Spring IOC容器扩展点全景:深入探索与实践演练
java·后端·spring