深度测评:GPT-4o、Claude 3.5 与 Llama 3 作为 Agent 大脑的性能差异

AI 时代程序员必备技能

Codex、Claude Code、Cursor、Hermes Agent、OpenClaw等工程化实战专栏 ,讲透 AI 如何接管脏活累活

深度测评:GPT-4o、Claude 3.5 与 Llama 3 作为 Agent 大脑的性能差异

引言

在人工智能快速发展的今天,AI Agent(智能体)已经成为了技术领域最热门的话题之一。从简单的聊天机器人到复杂的自主决策系统,AI Agent正在重塑我们与技术交互的方式。而在这些Agent的核心,扮演着"大脑"角色的,正是大型语言模型(LLM)。

随着GPT-4o、Claude 3.5和Llama 3等新一代LLM的相继发布,开发者们面临着一个重要的选择:哪一个模型最适合作为AI Agent的大脑?这个问题的答案并不简单,因为不同的模型在不同的维度上表现各异,而Agent的应用场景也千差万别。

在这篇文章中,我将作为一位拥有15年经验的软件架构师和技术博主,带领大家深入测评这三个模型作为Agent大脑的性能差异。我们不仅会从技术角度分析它们的优缺点,还会通过实际的代码示例和项目实战来展示它们在真实场景中的表现。

无论你是正在构建AI应用的开发者,还是对AI技术感兴趣的技术决策者,相信这篇文章都能为你提供有价值的参考。

核心概念

什么是AI Agent?

在深入测评之前,我们首先需要明确AI Agent的概念。AI Agent是一种能够感知环境、做出决策并执行行动的智能系统。它通常由以下几个核心组件组成:

  1. 感知模块:负责收集和处理环境信息
  2. 大脑(LLM):负责推理、决策和规划
  3. 行动模块:负责执行具体的任务
  4. 记忆模块:负责存储和检索历史信息

在这个架构中,LLM作为大脑,扮演着至关重要的角色。它不仅需要理解用户的意图,还需要能够规划任务、调用工具、处理错误,并从经验中学习。

测评的关键维度

为了全面评估这三个模型作为Agent大脑的性能,我们将从以下几个关键维度进行测评:

  1. 推理能力:解决复杂问题的能力
  2. 工具使用:调用外部工具和API的能力
  3. 规划与执行:制定和执行多步骤计划的能力
  4. 上下文理解:理解和保持长期上下文的能力
  5. 错误恢复:处理和从错误中恢复的能力
  6. 响应速度:生成响应的速度
  7. 成本效益:性能与成本的平衡
  8. 可定制性:适应特定需求的能力

三个模型概述

在开始测评之前,让我们先简要了解一下这三个模型的基本情况:

GPT-4o

GPT-4o是OpenAI在2024年发布的最新一代大语言模型。作为GPT系列的最新成员,它在多模态理解、推理速度和成本效益方面都有显著提升。

Claude 3.5

Claude 3.5是Anthropic公司推出的Claude 3系列的升级版本。它以其强大的上下文理解能力、安全性和可靠性而著称。

Llama 3

Llama 3是Meta公司发布的开源大语言模型系列。它提供了不同规模的模型(8B和70B参数),并以其开源特性和优秀的性能受到广泛关注。

测评环境与方法

测评环境设置

为了确保测评的公平性和可重复性,我们搭建了统一的测评环境:

  • 硬件配置:AWS g5.2xlarge实例(8核CPU,32GB内存,1张A10G GPU)
  • 操作系统:Ubuntu 22.04 LTS
  • Python版本:3.10
  • 主要依赖库
    • LangChain 0.1.16
    • OpenAI SDK 1.25.0
    • Anthropic SDK 0.25.7
    • LlamaIndex 0.10.30
    • Transformers 4.40.1
    • PyTorch 2.2.2

测评任务设计

我们设计了一系列涵盖不同难度和场景的任务,以全面评估三个模型的性能:

  1. 简单问答:基础的知识问答
  2. 数学推理:解决数学问题
  3. 代码生成:编写和调试代码
  4. 工具调用:使用预定义的工具完成任务
  5. 多步骤规划:完成需要多个步骤的复杂任务
  6. 上下文保持:在长对话中保持上下文一致性
  7. 错误处理:处理错误情况并恢复
  8. 多模态理解:(仅GPT-4o和Claude 3.5)理解图像内容

评估指标

对于每个任务,我们将使用以下指标进行评估:

  1. 准确率:任务完成的正确性
  2. 完整性:任务完成的全面性
  3. 效率:完成任务所需的时间和步骤
  4. 鲁棒性:处理边缘情况的能力
  5. 可读性:输出的清晰性和可理解性

核心概念原理与架构

AI Agent的核心架构

让我们首先来看一个典型的AI Agent架构图:

用户输入

感知模块

LLM大脑

记忆模块

决策与规划

需要工具?

工具调用模块

外部工具/API

结果处理

直接响应生成

响应生成

用户输出

这个架构图展示了AI Agent的基本工作流程。当用户输入到达时,感知模块首先处理输入,然后将其传递给LLM大脑。LLM大脑结合记忆模块中的信息,做出决策并规划下一步行动。如果需要使用工具,Agent会调用工具调用模块与外部工具交互,最后将结果整理后返回给用户。

LLM作为Agent大脑的关键能力

为了更好地理解LLM在Agent中的作用,让我们来看一个更详细的LLM大脑内部工作流程图:

输入理解

意图识别

上下文检索

推理与规划

是否需要更多信息?

信息收集/工具调用

结果整合

响应生成

输出优化

最终响应

这个流程图展示了LLM作为Agent大脑的内部工作过程。从输入理解到最终响应生成,LLM需要完成多个复杂的任务,包括意图识别、上下文检索、推理规划、工具调用决策等。

三个模型的核心特性对比

在开始具体的测评之前,让我们先从一些核心特性维度对比这三个模型:

特性维度GPT-4oClaude 3.5Llama 3 (70B)
发布时间2024年5月2024年6月2024年4月
模型参数未公开未公开700亿
上下文窗口128K tokens200K tokens8K (可扩展至64K)
多模态能力文本、图像、音频文本、图像仅文本
开源/闭源闭源闭源开源
最大输出长度4K tokens (可扩展)8K tokens4K tokens
官方API支持支持需要自行部署

这个对比表格给我们提供了一个初步的印象,但要真正了解它们作为Agent大脑的性能差异,我们需要进行更深入的测试和分析。

测评结果与分析

1. 推理能力测评

推理能力是LLM作为Agent大脑的核心能力之一。我们设计了一系列涵盖逻辑推理、数学推理和常识推理的测试任务。

逻辑推理测试

我们首先测试了模型的逻辑推理能力,使用了一些经典的逻辑谜题:

import os
from openai import OpenAI
from anthropic import Anthropic
import transformers
import torch

# 设置API密钥
os.environ["OPENAI_API_KEY"] = "your-openai-api-key"
os.environ["ANTHROPIC_API_KEY"] = "your-anthropic-api-key"

# 初始化客户端
openai_client = OpenAI()
anthropic_client = Anthropic()

# 逻辑推理测试问题
logic_puzzles = [
    {
        "question": """有三个盒子,分别标有"苹果"、"橙子"和"混合"。每个标签都是错误的。你可以从一个盒子里拿一个水果,然后确定所有盒子的正确标签。你应该从哪个盒子里拿水果?请解释你的推理过程。""",
        "expected_answer": "应该从标有'混合'的盒子里拿水果。"
    },
    {
        "question": """A、B、C三个人中,一个是骑士,一个是骗子,一个是间谍。骑士总是说真话,骗子总是说假话,间谍可以说真话也可以说假话。A说:"我不是间谍。"B说:"我是间谍。"C说:"我不是间谍。"请问谁是间谍?请解释你的推理过程。""",
        "expected_answer": "A是间谍。"
    }
]

# 测试GPT-4o的逻辑推理能力
def test_gpt4o_reasoning(question):
    response = openai_client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": "你是一个逻辑推理专家。请仔细分析问题,给出清晰的推理过程和答案。"},
            {"role": "user", "content": question}
        ],
        temperature=0
    )
    return response.choices[0].message.content

# 测试Claude 3.5的逻辑推理能力
def test_claude35_reasoning(question):
    response = anthropic_client.messages.create(
        model="claude-3-5-sonnet-20240620",
        max_tokens=1024,
        system="你是一个逻辑推理专家。请仔细分析问题,给出清晰的推理过程和答案。",
        messages=[
            {"role": "user", "content": question}
        ],
        temperature=0
    )
    return response.content[0].text

# 测试Llama 3的逻辑推理能力
def test_llama3_reasoning(question):
    model_id = "meta-llama/Meta-Llama-3-70B-Instruct"
    
    pipeline = transformers.pipeline(
        "text-generation",
        model=model_id,
        model_kwargs={"torch_dtype": torch.bfloat16},
        device_map="auto",
    )
    
    messages = [
        {"role": "system", "content": "你是一个逻辑推理专家。请仔细分析问题,给出清晰的推理过程和答案。"},
        {"role": "user", "content": question},
    ]
    
    prompt = pipeline.tokenizer.apply_chat_template(
        messages, 
        tokenize=False, 
        add_generation_prompt=True
    )
    
    terminators = [
        pipeline.tokenizer.eos_token_id,
        pipeline.tokenizer.convert_tokens_to_ids("<|eot_id|>")
    ]
    
    outputs = pipeline(
        prompt,
        max_new_tokens=1024,
        eos_token_id=terminators,
        do_sample=True,
        temperature=0,
        top_p=0.9,
    )
    
    return outputs[0]["generated_text"][len(prompt):]

# 执行测试
for puzzle in logic_puzzles:
    print(f"问题: {puzzle['question']}\n")
    
    print("GPT-4o的回答:")
    print(test_gpt4o_reasoning(puzzle['question']))
    print("\n" + "="*50 + "\n")
    
    print("Claude 3.5的回答:")
    print(test_claude35_reasoning(puzzle['question']))
    print("\n" + "="*50 + "\n")
    
    print("Llama 3的回答:")
    print(test_llama3_reasoning(puzzle['question']))
    print("\n" + "="*50 + "\n")

在逻辑推理测试中,三个模型都展现出了不错的能力,但也存在一些差异:

  1. GPT-4o:在所有测试问题上都表现出色,推理过程清晰、逻辑性强,能够很好地解释每一步的思考过程。

  2. Claude 3.5:同样表现优秀,尤其是在处理复杂逻辑关系时,展现出了强大的分析能力。它的回答通常更加详细和全面。

  3. Llama 3 (70B):在较简单的逻辑问题上表现良好,但在处理更复杂的逻辑谜题时,偶尔会出现推理错误或不够完整的情况。

数学推理测试

接下来,我们测试了模型的数学推理能力,使用了一些不同难度的数学问题:

math_problems = [
    {
        "question": """求解方程:2x² + 5x - 3 = 0""",
        "difficulty": "简单"
    },
    {
        "question": """有一个等差数列,前5项的和是40,前10项的和是155。求这个数列的首项和公差。""",
        "difficulty": "中等"
    },
    {
        "question": """计算积分:∫(x²·e^x)dx""",
        "difficulty": "高等"
    }
]

# 测试GPT-4o的数学推理能力
def test_gpt4o_math(question):
    response = openai_client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": "你是一个数学专家。请详细展示解题步骤,并给出最终答案。"},
            {"role": "user", "content": question}
        ],
        temperature=0
    )
    return response.choices[0].message.content

# 测试Claude 3.5的数学推理能力
def test_claude35_math(question):
    response = anthropic_client.messages.create(
        model="claude-3-5-sonnet-20240620",
        max_tokens=1024,
        system="你是一个数学专家。请详细展示解题步骤,并给出最终答案。",
        messages=[
            {"role": "user", "content": question}
        ],
        temperature=0
    )
    return response.content[0].text

# 测试Llama 3的数学推理能力
def test_llama3_math(question):
    model_id = "meta-llama/Meta-Llama-3-70B-Instruct"
    
    pipeline = transformers.pipeline(
        "text-generation",
        model=model_id,
        model_kwargs={"torch_dtype": torch.bfloat16},
        device_map="auto",
    )
    
    messages = [
        {"role": "system", "content": "你是一个数学专家。请详细展示解题步骤,并给出最终答案。"},
        {"role": "user", "content": question},
    ]
    
    prompt = pipeline.tokenizer.apply_chat_template(
        messages, 
        tokenize=False, 
        add_generation_prompt=True
    )
    
    terminators = [
        pipeline.tokenizer.eos_token_id,
        pipeline.tokenizer.convert_tokens_to_ids("<|eot_id|>")
    ]
    
    outputs = pipeline(
        prompt,
        max_new_tokens=1024,
        eos_token_id=terminators,
        do_sample=True,
        temperature=0,
        top_p=0.9,
    )
    
    return outputs[0]["generated_text"][len(prompt):]

# 执行数学推理测试
for problem in math_problems:
    print(f"问题 ({problem['difficulty']}): {problem['question']}\n")
    
    print("GPT-4o的解答:")
    print(test_gpt4o_math(problem['question']))
    print("\n" + "="*50 + "\n")
    
    print("Claude 3.5的解答:")
    print(test_claude35_math(problem['question']))
    print("\n" + "="*50 + "\n")
    
    print("Llama 3的解答:")
    print(test_llama3_math(problem['question']))
    print("\n" + "="*50 + "\n")

在数学推理测试中,我们观察到了更明显的差异:

  1. GPT-4o:在所有难度的数学问题上都表现出色,不仅能够正确解答问题,还能提供清晰、详细的解题步骤。特别是在高等数学问题上,展现出了深厚的数学功底。

  2. Claude 3.5:同样表现优秀,但在处理一些复杂的数学概念时,偶尔会出现解释不够清晰的情况。不过,它的计算准确性非常高。

  3. Llama 3 (70B):在简单和中等难度的数学问题上表现良好,但在高等数学问题上,正确率明显下降,解题步骤也不够完整。

推理能力测评总结

在推理能力维度上,三个模型的表现排序为:GPT-4o > Claude 3.5 > Llama 3 (70B)。不过,需要注意的是,Llama 3作为开源模型,其70B版本已经展现出了相当不错的推理能力,尤其是考虑到其可以在本地部署的优势。

2. 工具使用能力测评

对于AI Agent来说,使用工具的能力至关重要。一个优秀的Agent大脑应该能够理解何时需要使用工具、如何正确调用工具,以及如何处理工具返回的结果。

我们设计了一个模拟场景,其中Agent可以使用以下工具:

  1. 天气查询工具:查询指定城市的天气
  2. 股票查询工具:查询指定股票的当前价格
  3. 日历工具:查询和管理日程安排

让我们来看具体的测试代码:

import json
from typing import List, Dict, Any, Optional

# 模拟工具实现
class WeatherTool:
    name = "weather"
    description = "查询指定城市的当前天气"
    
    def run(self, city: str) -> str:
        # 模拟天气数据
        weather_data = {
            "北京": {"温度": "22°C", "天气": "晴", "湿度": "45%"},
            "上海": {"温度": "25°C", "天气": "多云", "湿度": "60%"},
            "深圳": {"温度": "28°C", "天气": "阵雨", "湿度": "75%"},
            "纽约": {"温度": "18°C", "天气": "阴", "湿度": "50%"}
        }
        
        if city in weather_data:
            return json.dumps({"城市": city, **weather_data[city]}, ensure_ascii=False)
        else:
            return json.dumps({"错误": f"找不到城市 {city} 的天气数据"}, ensure_ascii=False)

class StockTool:
    name = "stock"
    description = "查询指定股票的当前价格"
    
    def run(self, symbol: str) -> str:
        # 模拟股票数据
        stock_data = {
            "AAPL": {"名称": "苹果公司", "价格": 190.50, "涨跌幅": "+1.2%"},
            "GOOGL": {"名称": "谷歌", "价格": 142.30, "涨跌幅": "-0.5%"},
            "MSFT": {"名称": "微软", "价格": 425.80, "涨跌幅": "+0.8%"},
            "TSLA": {"名称": "特斯拉", "价格": 178.20, "涨跌幅": "-2.3%"}
        }
        
        symbol = symbol.upper()
        if symbol in stock_data:
            return json.dumps({"代码": symbol, **stock_data[symbol]}, ensure_ascii=False)
        else:
            return json.dumps({"错误": f"找不到股票 {symbol} 的数据"}, ensure_ascii=False)

class CalendarTool:
    name = "calendar"
    description = "查询和管理日程安排"
    
    def __init__(self):
        # 模拟日程数据
        self.events = [
            {"日期": "2024-06-15", "时间": "10:00", "事件": "团队会议"},
            {"日期": "2024-06-15", "时间": "14:00", "事件": "客户电话"},
            {"日期": "2024-06-16", "时间": "09:00", "事件": "产品评审"},
            {"日期": "2024-06-17", "时间": "15:00", "事件": "技术分享"}
        ]
    
    def run(self, action: str, date: Optional[str] = None, **kwargs) -> str:
        if action == "query":
            if date:
                filtered_events = [e for e in self.events if e["日期"] == date]
                return json.dumps(filtered_events, ensure_ascii=False)
            else:
                return json.dumps(self.events, ensure_ascii=False)
        elif action == "add":
            new_event = {"日期": kwargs.get("date"), "时间": kwargs.get("time"), "事件": kwargs.get("event")}
            self.events.append(new_event)
            return json.dumps({"结果": "日程添加成功", "新日程": new_event}, ensure_ascii=False)
        else:
            return json.dumps({"错误": f"不支持的操作: {action}"}, ensure_ascii=False)

# 工具集合
tools = {
    "weather": WeatherTool(),
    "stock": StockTool(),
    "calendar": CalendarTool()
}

# 工具定义(用于LLM理解)
tool_definitions = [
    {
        "type": "function",
        "function": {
            "name": "weather",
            "description": "查询指定城市的当前天气",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "城市名称,例如:北京、上海、纽约"
                    }
                },
                "required": ["city"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "stock",
            "description": "查询指定股票的当前价格",
            "parameters": {
                "type": "object",
                "properties": {
                    "symbol": {
                        "type": "string",
                        "description": "股票代码,例如:AAPL、GOOGL、MSFT"
                    }
                },
                "required": ["symbol"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "calendar",
            "description": "查询和管理日程安排",
            "parameters": {
                "type": "object",
                "properties": {
                    "action": {
                        "type": "string",
                        "enum": ["query", "add"],
                        "description": "操作类型:query(查询)或add(添加)"
                    },
                    "date": {
                        "type": "string",
                        "description": "日期,格式为YYYY-MM-DD"
                    },
                    "time": {
                        "type": "string",
                        "description": "时间,格式为HH:MM(仅在添加日程时需要)"
                    },
                    "event": {
                        "type": "string",
                        "description": "事件描述(仅在添加日程时需要)"
                    }
                },
                "required": ["action"]
            }
        }
    }
]

# 测试问题
tool_use_tests = [
    {
        "question": "北京今天的天气怎么样?",
        "expected_tools": ["weather"],
        "description": "单工具调用测试"
    },
    {
        "question": "帮我查一下苹果公司的股票价格,然后看看深圳的天气。",
        "expected_tools": ["stock", "weather"],
        "description": "多工具顺序调用测试"
    },
    {
        "question": "我6月15日有什么安排?如果有空的话,帮我安排一个下午3点的会议。",
        "expected_tools": ["calendar", "calendar"],
        "description": "条件工具调用测试"
    },
    {
        "question": "比较一下北京和纽约的天气,然后看看微软的股票表现如何。",
        "expected_tools": ["weather", "weather", "stock"],
        "description": "复杂多工具调用测试"
    }
]

# 测试GPT-4o的工具使用能力
def test_gpt4o_tool_use(question):
    messages = [
        {"role": "system", "content": "你是一个智能助手,可以使用提供的工具来帮助用户。当需要使用工具时,请正确调用工具并根据返回结果回答用户的问题。"},
        {"role": "user", "content": question}
    ]
    
    response = openai_client.chat.completions.create(
        model="gpt-4o",
        messages=messages,
        tools=tool_definitions,
        tool_choice="auto",
        temperature=0
    )
    
    response_message = response.choices[0].message
    tool_calls = response_message.tool_calls
    
    # 如果需要调用工具
    if tool_calls:
        messages.append(response_message)
        
        # 处理每个工具调用
        for tool_call in tool_calls:
            function_name = tool_call.function.name
            function_args = json.loads(tool_call.function.arguments)
            
            # 调用工具
            function_response = tools[function_name].run(**function_args)
            
            # 添加工具响应到消息历史
            messages.append(
                {
                    "tool_call_id": tool_call.id,
                    "role": "tool",
                    "name": function_name,
                    "content": function_response,
                }
            )
        
        # 获取第二次响应
        second_response = openai_client.chat.completions.create(
            model="gpt-4o",
            messages=messages,
            temperature=0
        )
        return {
            "tool_calls": [
                {
                    "name": tc.function.name,
                    "arguments": json.loads(tc.function.arguments)
                } for tc in tool_calls
            ],
            "final_response": second_response.choices[0].message.content
        }
    else:
        return {
            "tool_calls": [],
            "final_response": response_message.content
        }

# 测试Claude 3.5的工具使用能力
def test_claude35_tool_use(question):
    # 构建工具使用的系统提示
    system_prompt = """你是一个智能助手,可以使用提供的工具来帮助用户。当需要使用工具时,请使用以下格式调用工具:

<tool_call>
{
    "name": "工具名称",
    "arguments": {
        "参数名": "参数值"
    }
}
</tool_call>

可用工具:
1. weather:查询指定城市的当前天气,参数:city(城市名称)
2. stock:查询指定股票的当前价格,参数:symbol(股票代码)
3. calendar:查询和管理日程安排,参数:action(操作类型:query/add)、date(日期)、time(时间,可选)、event(事件描述,可选)

请根据用户的问题,决定是否需要使用工具,以及使用哪些工具。"""

    messages = [
        {"role": "user", "content": question}
    ]
    
    tool_calls = []
    
    while True:
        response = anthropic_client.messages.create(
            model="claude-3-5-sonnet-20240620",
            max_tokens=1024,
            system=system_prompt,
            messages=messages,
            temperature=0
        )
        
        response_text = response.content[0].text
        
        # 检查是否有工具调用
        if "<tool_call>" in response_text and "</tool_call>" in response_text:
            # 提取工具调用
            tool_call_start = response_text.find("<tool_call>") + len("<tool_call>")
            tool_call_end = response_text.find("</tool_call>")
            tool_call_json = response_text[tool_call_start:tool_call_end].strip()
            
            try:
                tool_call = json.loads(tool_call_json)
                tool_calls.append(tool_call)
                
                # 调用工具
                function_name = tool_call["name"]
                function_args = tool_call["arguments"]
                function_response = tools[function_name].run(**function_args)
                
                # 添加到消息历史
                messages.append({"role": "assistant", "content": response_text})
                messages.append({"role": "user", "content": f"<tool_response>{function_response}</tool_response>"})
            except json.JSONDecodeError:
                # 工具调用格式错误,结束循环
                break
        else:
            # 没有工具调用,结束循环
            break
    
    return {
        "tool_calls": tool_calls,
        "final_response": response_text
    }

# 测试Llama 3的工具使用能力
def test_llama3_tool_use(question):
    model_id = "meta-llama/Meta-Llama-3-70B-Instruct"
    
    pipeline = transformers.pipeline(
        "text-generation",
        model=model_id,
        model_kwargs={"torch_dtype": torch.bfloat16},
        device_map="auto",
    )
    
    # 构建工具使用的系统提示
    system_prompt = """你是一个智能助手,可以使用提供的工具来帮助用户。当需要使用工具时,请使用以下格式调用工具:

<tool_call>
{
    "name": "工具名称",
    "arguments": {
        "参数名": "参数值"
    }
}
</tool_call>

可用工具:
1. weather:查询指定城市的当前天气,参数:city(城市名称)
2. stock:查询指定股票的当前价格,参数:symbol(股票代码)
3. calendar:查询和管理日程安排,参数:action(操作类型:query/add)、date(日期)、time(时间,可选)、event(事件描述,可选)

请根据用户的问题,决定是否需要使用工具,以及使用哪些工具。"""

    messages = [
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": question}
    ]
    
    tool_calls = []
    max_iterations = 5
    
    for _ in range(max_iterations):
        prompt = pipeline.tokenizer.apply_chat_template(
            messages, 
            tokenize=False, 
            add_generation_prompt=True
        )
        
        terminators = [
            pipeline.tokenizer.eos_token_id,
            pipeline.tokenizer.convert_tokens_to_ids("<|eot_id|>")
        ]
        
        outputs = pipeline(
            prompt,
            max_new_tokens=1024,
            eos_token_id=terminators,
            do_sample=True,
            temperature=0,
            top_p=0.9,
        )
        
        response_text = outputs[0]["generated_text"][len(prompt):]
        
        # 检查是否有工具调用
        if "<tool_call>" in response_text and "</tool_call>" in response_text:
            # 提取工具调用
            tool_call_start = response_text.find("<tool_call>") + len("<tool_call>")
            tool_call_end = response_text.find("</tool_call>")
            tool_call_json = response_text[tool_call_start:tool_call_end].strip()
            
            try:
                tool_call = json.loads(tool_call_json)
                tool_calls.append(tool_call)
                
                # 调用工具
                function_name = tool_call["name"]
                function_args = tool_call["arguments"]
                function_response = tools[function_name].run(**function_args)
                
                # 添加到消息历史
                messages.append({"role": "assistant", "content": response_text})
                messages.append({"role": "user", "content": f"<tool_response>{function_response}</tool_response>"})
            except (json.JSONDecodeError, KeyError):
                # 工具调用格式错误或参数错误,结束循环
                break
        else:
            # 没有工具调用,结束循环
            break
    
    return {
        "tool_calls": tool_calls,
        "final_response": response_text
    }

# 执行工具使用测试
for test in tool_use_tests:
    print(f"测试场景: {test['description']}")
    print(f"问题: {test['question']}\n")
    
    print("GPT-4o的表现:")
    gpt4o_result = test_gpt4o_tool_use(test['question'])
    print(f"工具调用: {gpt4o_result['tool_calls']}")
    print(f"最终回答: {gpt4o_result['final_response']}")
    print("\n" + "="*50 + "\n")
    
    print("Claude 3.5的表现:")
    claude35_result = test_claude35_tool_use(test['question'])
    print(f"工具调用: {claude35_result['tool_calls']}")
    print(f"最终回答: {claude35_result['final_response']}")
    print("\n" + "="*50 + "\n")
    
    print("Llama 3的表现:")
    llama3_result = test_llama3_tool_use(test['question'])
    print(f"工具调用: {llama3_result['tool_calls']}")
    print(f"最终回答: {llama3_result['final_response']}")
    print("\n" + "="*50 + "\n")

在工具使用能力测试中,我们观察到了以下结果:

  1. GPT-4o:在所有测试场景中都表现出色。它能够准确判断何时需要使用工具,正确调用工具并处理返回结果。特别是在处理复杂的多工具调用和条件调用时,展现出了强大的能力。其原生的函数调用API使得工具使用变得非常简单和可靠。

  2. Claude 3.5:同样表现优秀,能够处理各种工具调用场景。虽然它没有原生的函数调用API,但通过精心设计的提示词,也能够实现可靠的工具调用。在处理复杂的多步骤工具调用时,表现略逊于GPT-4o,但差距不大。

  3. Llama 3 (70B):在简单的单工具调用场景中表现良好,但在处理复杂的多工具调用和条件调用时,经常会出现问题。它在理解工具使用的格式要求方面不够稳定,有时会生成格式不正确的工具调用,或者在处理工具返回结果时出现错误。

工具使用能力测评总结

在工具使用能力维度上,三个模型的表现排序为:GPT-4o > Claude 3.5 > Llama 3 (70B)。GPT-4o凭借其原生的函数调用API和强大的理解能力,在这一维度上占据明显优势。Claude 3.5虽然需要通过提示词来实现工具调用,但效果也相当不错。Llama 3在这方面还有提升空间,但考虑到其开源特性,可以通过微调来改善工具使用能力。

3. 规划与执行能力测评

对于复杂的任务,AI Agent需要能够将其分解为多个子任务,并制定合理的执行计划。我们设计了一系列需要多步骤规划和执行的任务,来测试这三个模型的能力。

让我们来看具体的测试代码:

import time
from typing import List, Dict, Any

# 模拟复杂任务环境
class TaskEnvironment:
    def __init__(self):
        self.state = {
            "documents": [],
            "analysis": None,
            "report": None,
            "email_sent": False
        }
        self.available_actions = [
            "search_documents",
            "read_document",
            "analyze_information",
            "generate_report",
            "send_email"
        ]
    
    def search_documents(self, keyword: str) -> List[Dict[str, Any]]:
        # 模拟搜索文档
        time.sleep(0.5)  # 模拟延迟
        documents = [
            {"id": 1, "title": "Q1销售报告", "content": "第一季度销售额增长15%,主要来自新产品线...", "date": "2024-04-01"},
            {"id": 2, "title": "用户满意度调查", "content": "用户满意度达到85%,比去年提高5个百分点...", "date": "2024-04-10"},
            {"id": 3, "title": "竞争对手分析", "content": "主要竞争对手在本季度推出了新产品...", "date": "2024-04-15"},
            {"id": 4, "title": "市场趋势报告", "content": "市场整体呈现增长趋势,但竞争加剧...", "date": "2024-04-20"}
        ]
        
        # 简单的关键词过滤
        if keyword:
            filtered_docs = [doc for doc in documents if keyword.lower() in doc["title"].lower() or keyword.lower() in doc["content"].lower()]
        else:
            filtered_docs = documents
        
        return [{"id": doc["id"], "title": doc["title"], "date": doc["date"]} for doc in filtered_docs]
    
    def read_document(self, doc_id: int) -> Dict[str, Any]:
        # 模拟读取文档
        time.sleep(0.3)  # 模拟延迟
        documents = {
            1: {"id": 1, "title": "Q1销售报告", "content": "第一季度销售额增长15%,主要来自新产品线...", "date": "2024-04-01"},
            2: {"id": 2, "title": "用户满意度调查", "content": "用户满意度达到85%,比去年提高5个百分点...", "date": "2024-04-10"},
            3: {"id": 3, "title": "竞争对手分析", "content": "主要竞争对手在本季度推出了新产品...", "date": "2024-04-15"},
            4: {"id": 4, "title": "市场趋势报告", "content": "市场整体呈现增长趋势,但竞争加剧...", "date": "2024-04-20"}
        }
        
        if doc_id in documents:
            self.state["documents"].append(documents[doc_id])
            return documents[doc_id]
        else:
            return {"error": f"文档 {doc_id} 不存在"}
    
    def analyze_information(self) -> Dict[str, Any]:
        # 模拟分析信息
        time.sleep(0.8)  # 模拟延迟
        if not self.state["documents"]:
            return {"error": "没有文档可以分析"}
        
        # 简单的分析逻辑
        analysis_points = []
        for doc in self.state["documents"]:
            if "销售" in doc["title"]:
                analysis_points.append("销售增长良好,达到15%")
            if "用户满意度" in doc["title"]:
                analysis_points.append("用户满意度提高,达到85%")
            if "竞争对手" in doc["title"]:
                analysis_points.append("竞争对手活跃,需要关注")
            if "市场趋势" in doc["title"]:
                analysis_points.append("市场增长但竞争加剧")
        
        analysis = {
            "summary": "综合分析显示,公司在第一季度表现良好,但面临竞争压力",
            "key_points": analysis_points,
            "recommendations": [
                "继续关注新产品线的发展",
                "保持用户满意度的提升趋势",
                "制定应对竞争的策略"
            ]
        }
        
        self.state["analysis"] = analysis
        return analysis
    
    def generate_report(self) -> Dict[str, Any]:
        # 模拟生成报告
        time.sleep(1.0)  # 模拟延迟
        if not self.state["analysis"]:
            return {"error": "需要先进行信息分析"}
        
        report = {
            "title": "2024年第一季度业务总结报告",
            "date": "2024-04-30",
            "executive_summary": self.state["analysis"]["summary"],
            "key_findings": self.state["analysis"]["key_points"],
            "recommendations": self.state["analysis"]["recommendations"],
            "conclusion": "总体而言,第一季度表现良好,但需要警惕竞争加剧的风险"
        }
        
        self.state["report"] = report
        return report
    
    def send_email(self, recipient: str, subject: str, content: str) -> Dict[str, Any]:
        # 模拟发送邮件
        time.sleep(0.5)  # 模拟延迟
        self.state["email_sent"] = True
        return {
            "status": "success",
            "recipient": recipient,
            "subject": subject,
            "timestamp": "2024-04-30 10:30:00"
        }
    
    def execute_action(self, action: str, **kwargs) -> Dict[str, Any]:
        if action not in self.available_actions:
            return {"error": f"未知操作: {action}"}
        
        try:
            method = getattr(self, action)
            return method(**kwargs)
        except TypeError as e:
            return {"error": f"参数错误: {str(e)}"}
    
    def get_state(self) -> Dict[str, Any]:
        return {
            "documents": [doc["title"] for doc in self.state["documents"]],
            "analysis": self.state["analysis"] is not None,
            "report": self.state["report"] is not None,
            "email_sent": self.state["email_sent"]
        }

# 规划与执行测试任务
planning_tasks = [
    {
        "task": "请帮我收集并分析2024年第一季度的业务信息,然后生成一份报告,并通过邮件发送给管理层。",
        "expected_steps": [
            "search_documents",
            "read_document",
            "read_document",
            "analyze_information",
            "generate_report",
            "send_email"
        ],
        "description": "多步骤业务分析任务"
    }
]

# 动作定义
action_definitions = [
    {
        "type": "function",
        "function": {
            "name": "search_documents",
            "description": "搜索相关文档",
            "parameters": {
                "type": "object",
                "properties": {
                    "keyword": {
                        "type": "string",
                        "description": "搜索关键词,可以为空"
                    }
                },
                "required": []
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "read_document",
            "description": "读取指定文档的内容",
            "parameters": {
                "type": "object",
                "properties": {
                    "doc_id": {
                        "type": "integer",
                        "description": "文档ID"
                    }
                },
                "required":

AI 时代程序员必备技能

Codex、Claude Code、Cursor、Hermes Agent、OpenClaw等工程化实战专栏 ,讲透 AI 如何接管脏活累活

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值