Qwen2.5-Coder-1.5B与GPT-4o代码生成能力对比测试

最近,开源代码大模型Qwen2.5-Coder系列发布,官方宣称其32B版本在编码能力上已与GPT-4o相当。这让我很好奇:作为开发者,我们真的能用上媲美GPT-4o的开源代码模型吗?

今天,我就带大家实际测试一下Qwen2.5-Coder系列中最小巧的1.5B版本。虽然它只有15亿参数,但官方文档明确表示,整个系列在代码生成、推理和修复方面都有显著提升。那么,这个“小个子”在实际编码任务中表现如何?能否在某些场景下接近GPT-4o的水平?

我将通过多个维度的实际测试,带你直观感受两者的差异。无论你是想了解开源代码模型的当前水平,还是考虑在实际项目中部署轻量级代码助手,这篇文章都会给你清晰的答案。

1. 测试环境与准备

1.1 测试模型介绍

在开始对比之前,我们先简单了解一下今天的主角们。

Qwen2.5-Coder-1.5B是通义千问团队推出的专门针对代码任务的轻量级模型。它只有15亿参数,但基于Qwen2.5架构,在5.5万亿token的代码相关数据上进行了训练。这个模型最大的特点是轻量——这意味着它可以在消费级硬件上运行,部署成本低,响应速度快。

GPT-4o是OpenAI目前最先进的多模态模型之一,虽然不是专门的代码模型,但在代码生成和理解方面表现出了强大的能力。它拥有数千亿参数,训练数据覆盖了海量的代码和文本信息。

从参数规模上看,两者相差数百倍,但这并不意味着小模型就一定弱。很多时候,专门化训练的小模型在特定任务上可能比通用大模型表现更好。

1.2 测试环境搭建

为了公平对比,我搭建了以下测试环境:

Qwen2.5-Coder-1.5B部署环境:

  • 硬件:NVIDIA RTX 3060 12GB(消费级显卡)
  • 内存:16GB
  • 部署方式:通过CSDN星图镜像广场的预置镜像一键部署
  • 推理框架:Ollama

GPT-4o测试环境:

  • 通过OpenAI官方API访问
  • 使用默认参数设置

测试代码准备: 我准备了5类常见的编程任务,覆盖不同难度和场景:

  1. 基础算法实现(排序、查找等)
  2. 数据处理脚本(文件操作、数据清洗)
  3. Web开发相关(API接口、前端组件)
  4. 代码调试与修复
  5. 复杂逻辑实现

所有测试都使用相同的提示词模板,确保对比的公平性。

2. 基础代码生成能力对比

2.1 简单算法实现

我们先从最简单的开始——实现一个快速排序算法。

测试提示词:

用Python实现一个快速排序算法,要求:
1. 函数名为quick_sort
2. 能够处理整数列表
3. 包含详细的注释说明
4. 提供使用示例

Qwen2.5-Coder-1.5B生成结果:

def quick_sort(arr):
    """
    快速排序算法的实现
    
    参数:
    arr (list): 需要排序的整数列表
    
    返回:
    list: 排序后的列表
    """
    # 如果列表长度小于等于1,直接返回
    if len(arr) <= 1:
        return arr
    
    # 选择基准元素(这里选择中间元素)
    pivot = arr[len(arr) // 2]
    
    # 将列表分为三部分:小于基准、等于基准、大于基准
    left = [x for x in arr if x < pivot]
    middle = [x for x in arr if x == pivot]
    right = [x for x in arr if x > pivot]
    
    # 递归排序左右两部分,然后合并
    return quick_sort(left) + middle + quick_sort(right)


# 使用示例
if __name__ == "__main__":
    # 测试数据
    test_list = [64, 34, 25, 12, 22, 11, 90]
    print("原始列表:", test_list)
    
    # 调用快速排序
    sorted_list = quick_sort(test_list)
    print("排序后列表:", sorted_list)
    
    # 更多测试
    test_list2 = [3, 6, 8, 10, 1, 2, 1]
    print("\n原始列表:", test_list2)
    print("排序后列表:", quick_sort(test_list2))

GPT-4o生成结果:

def quick_sort(arr):
    """
    实现快速排序算法
    
    参数:
    arr (list): 待排序的整数列表
    
    返回:
    list: 排序后的列表
    """
    # 基本情况:如果列表为空或只有一个元素,已经有序
    if len(arr) <= 1:
        return arr
    
    # 选择基准元素(这里选择最后一个元素)
    pivot = arr[-1]
    
    # 分区操作
    left = []
    right = []
    
    for element in arr[:-1]:  # 遍历除基准外的所有元素
        if element <= pivot:
            left.append(element)
        else:
            right.append(element)
    
    # 递归排序并合并
    return quick_sort(left) + [pivot] + quick_sort(right)


# 使用示例
if __name__ == "__main__":
    # 示例1
    numbers = [64, 34, 25, 12, 22, 11, 90]
    print(f"原始数组: {numbers}")
    sorted_numbers = quick_sort(numbers)
    print(f"排序后数组: {sorted_numbers}")
    
    # 示例2:包含重复元素
    numbers2 = [3, 6, 8, 10, 1, 2, 1, 5]
    print(f"\n原始数组: {numbers2}")
    sorted_numbers2 = quick_sort(numbers2)
    print(f"排序后数组: {sorted_numbers2}")
    
    # 示例3:空列表和单元素列表
    print(f"\n空列表排序: {quick_sort([])}")
    print(f"单元素列表排序: {quick_sort([42])}")

对比分析:

  1. 代码正确性:两者都正确实现了快速排序算法,都能正常工作
  2. 实现方式:Qwen2.5使用了列表推导式,代码更简洁;GPT-4o使用了传统的for循环,更易理解
  3. 注释质量:两者注释都很详细,但GPT-4o的注释更贴近实际教学场景
  4. 测试用例:GPT-4o提供了更全面的测试用例,包括边界情况

小结:在简单算法实现上,Qwen2.5-Coder-1.5B表现相当不错,代码简洁有效。虽然测试用例不如GPT-4o全面,但核心功能完全正确。

2.2 数据处理脚本生成

接下来测试一个更实用的场景——生成一个数据处理脚本。

测试提示词:

编写一个Python脚本,读取CSV文件,计算每列的平均值和标准差,并将结果保存到新的CSV文件中。
要求处理可能存在的缺失值,并提供错误处理机制。

Qwen2.5-Coder-1.5B生成结果:

import pandas as pd
import numpy as np
import os


def process_csv_file(input_file, output_file):
    """
    处理CSV文件,计算每列的平均值和标准差
    
    参数:
    input_file (str): 输入CSV文件路径
    output_file (str): 输出CSV文件路径
    
    返回:
    bool: 处理是否成功
    """
    try:
        # 检查输入文件是否存在
        if not os.path.exists(input_file):
            print(f"错误:文件 {input_file} 不存在")
            return False
        
        # 读取CSV文件
        print(f"正在读取文件: {input_file}")
        df = pd.read_csv(input_file)
        
        # 检查数据框是否为空
        if df.empty:
            print("警告:CSV文件为空")
            return False
        
        print(f"成功读取数据,共 {len(df)} 行,{len(df.columns)} 列")
        
        # 处理缺失值:用列的平均值填充
        numeric_cols = df.select_dtypes(include=[np.number]).columns
        for col in numeric_cols:
            if df[col].isnull().any():
                mean_value = df[col].mean()
                df[col].fillna(mean_value, inplace=True)
                print(f"列 '{col}' 中的缺失值已用平均值 {mean_value:.2f} 填充")
        
        # 计算每列的平均值和标准差
        results = []
        for col in numeric_cols:
            mean_val = df[col].mean()
            std_val = df[col].std()
            results.append({
                '列名': col,
                '平均值': mean_val,
                '标准差': std_val,
                '数据数量': len(df[col])
            })
        
        # 创建结果DataFrame
        results_df = pd.DataFrame(results)
        
        # 保存结果到CSV文件
        results_df.to_csv(output_file, index=False, encoding='utf-8')
        print(f"结果已保存到: {output_file}")
        
        # 打印摘要信息
        print("\n处理摘要:")
        print(f"处理文件: {input_file}")
        print(f"数值列数量: {len(numeric_cols)}")
        print(f"输出文件: {output_file}")
        
        return True
        
    except Exception as e:
        print(f"处理过程中发生错误: {str(e)}")
        return False


if __name__ == "__main__":
    # 示例用法
    input_csv = "data.csv"  # 替换为你的输入文件路径
    output_csv = "statistics_results.csv"  # 输出文件路径
    
    # 调用处理函数
    success = process_csv_file(input_csv, output_csv)
    
    if success:
        print("数据处理完成!")
    else:
        print("数据处理失败!")

GPT-4o生成结果:

import pandas as pd
import numpy as np
import sys
import traceback
from pathlib import Path


def calculate_csv_statistics(input_path, output_path):
    """
    计算CSV文件中数值列的平均值和标准差
    
    参数:
    input_path (str): 输入CSV文件路径
    output_path (str): 输出CSV文件路径
    
    返回:
    tuple: (成功标志, 错误信息)
    """
    try:
        # 验证输入文件
        input_file = Path(input_path)
        if not input_file.exists():
            return False, f"输入文件不存在: {input_path}"
        
        if input_file.suffix.lower() != '.csv':
            return False, "输入文件必须是CSV格式"
        
        # 读取CSV文件
        print(f"正在读取: {input_path}")
        try:
            df = pd.read_csv(input_path)
        except Exception as e:
            return False, f"读取CSV文件失败: {str(e)}"
        
        # 检查数据
        if df.empty:
            return False, "CSV文件为空"
        
        print(f"数据形状: {df.shape[0]} 行 × {df.shape[1]} 列")
        
        # 识别数值列
        numeric_columns = df.select_dtypes(include=[np.number]).columns.tolist()
        if not numeric_columns:
            return False, "CSV文件中没有数值列"
        
        print(f"找到 {len(numeric_columns)} 个数值列")
        
        # 处理缺失值
        df_processed = df.copy()
        missing_info = {}
        
        for col in numeric_columns:
            missing_count = df[col].isnull().sum()
            if missing_count > 0:
                # 用中位数填充(对异常值更鲁棒)
                median_val = df[col].median()
                df_processed[col].fillna(median_val, inplace=True)
                missing_info[col] = {
                    'missing_count': missing_count,
                    'fill_value': median_val
                }
        
        # 计算统计量
        statistics_data = []
        for col in numeric_columns:
            col_data = df_processed[col]
            stats = {
                'column_name': col,
                'mean': float(col_data.mean()),
                'std': float(col_data.std()),
                'min': float(col_data.min()),
                'max': float(col_data.max()),
                'count': int(len(col_data)),
                'missing_original': int(df[col].isnull().sum()),
                'data_type': str(df[col].dtype)
            }
            statistics_data.append(stats)
        
        # 创建结果DataFrame
        results_df = pd.DataFrame(statistics_data)
        
        # 保存结果
        output_file = Path(output_path)
        results_df.to_csv(output_file, index=False)
        
        # 生成报告
        print(f"\n处理完成!结果已保存到: {output_path}")
        print("\n统计摘要:")
        print(results_df[['column_name', 'mean', 'std', 'count']].to_string())
        
        if missing_info:
            print("\n缺失值处理情况:")
            for col, info in missing_info.items():
                print(f"  {col}: {info['missing_count']} 个缺失值,用中位数 {info['fill_value']:.4f} 填充")
        
        return True, "处理成功"
        
    except Exception as e:
        error_details = traceback.format_exc()
        return False, f"未预期的错误: {str(e)}\n详细信息:\n{error_details}"


def main():
    """主函数"""
    # 配置输入输出文件
    input_file = "input_data.csv"  # 修改为你的输入文件
    output_file = "statistics_output.csv"  # 修改为期望的输出文件
    
    print("CSV文件统计计算工具")
    print("=" * 50)
    
    # 执行计算
    success, message = calculate_csv_statistics(input_file, output_file)
    
    if success:
        print(f"\n {message}")
        sys.exit(0)
    else:
        print(f"\n 处理失败: {message}")
        sys.exit(1)


if __name__ == "__main__":
    main()

对比分析:

  1. 功能完整性:两者都实现了核心功能,但GPT-4o的版本更全面,包含了数据类型的检查、更详细的错误处理、以及额外的统计指标(最小值、最大值)
  2. 缺失值处理:Qwen2.5使用平均值填充,GPT-4o使用中位数填充(对异常值更鲁棒)
  3. 代码结构:GPT-4o的代码结构更清晰,函数职责更明确,错误处理更完善
  4. 用户体验:GPT-4o提供了更详细的处理报告和进度提示

小结:在实用脚本生成方面,GPT-4o明显更胜一筹。它生成的代码不仅功能完整,还考虑到了更多的边缘情况和用户体验。Qwen2.5-Coder-1.5B虽然能生成可工作的代码,但在代码质量和完整性上还有差距。

3. 复杂逻辑与代码调试能力

3.1 复杂算法挑战

现在我们来测试一个更有挑战性的任务——实现一个简单的推荐系统算法。

测试提示词:

实现一个基于用户的协同过滤推荐算法。
要求:
1. 计算用户之间的相似度(使用余弦相似度)
2. 根据相似用户评分预测目标用户对未评分项目的评分
3. 为指定用户生成Top-N推荐
4. 使用Python编写,包含完整的测试用例

由于这个任务比较复杂,我们看看两个模型的表现差异。

Qwen2.5-Coder-1.5B生成结果(节选关键部分):

import numpy as np
from collections import defaultdict


class UserBasedCF:
    def __init__(self):
        self.user_ratings = defaultdict(dict)
        self.item_users = defaultdict(set)
    
    def add_rating(self, user_id, item_id, rating):
        """添加用户评分"""
        self.user_ratings[user_id][item_id] = rating
        self.item_users[item_id].add(user_id)
    
    def cosine_similarity(self, user1, user2):
        """计算两个用户之间的余弦相似度"""
        # 获取两个用户都评分过的项目
        common_items = set(self.user_ratings[user1].keys()) & set(self.user_ratings[user2].keys())
        
        if not common_items:
            return 0
        
        # 提取评分向量
        vec1 = [self.user_ratings[user1][item] for item in common_items]
        vec2 = [self.user_ratings[user2][item] for item in common_items]
        
        # 计算余弦相似度
        dot_product = sum(v1 * v2 for v1, v2 in zip(vec1, vec2))
        norm1 = sum(v * v for v in vec1) ** 0.5
        norm2 = sum(v * v for v in vec2) ** 0.5
        
        if norm1 == 0 or norm2 == 0:
            return 0
        
        return dot_product / (norm1 * norm2)
    
    def predict_rating(self, user_id, item_id, k=5):
        """预测用户对项目的评分"""
        if item_id in self.user_ratings[user_id]:
            return self.user_ratings[user_id][item_id]
        
        # 找到评分过该项目的用户
        users_rated = self.item_users[item_id]
        if not users_rated:
            return 0
        
        # 计算与目标用户的相似度
        similarities = []
        for other_user in users_rated:
            if other_user != user_id:
                sim = self.cosine_similarity(user_id, other_user)
                if sim > 0:
                    similarities.append((sim, self.user_ratings[other_user][item_id]))
        
        # 如果没有相似用户,返回0
        if not similarities:
            return 0
        
        # 按相似度排序,取前k个
        similarities.sort(reverse=True)
        top_k = similarities[:k]
        
        # 计算加权平均评分
        weighted_sum = sum(sim * rating for sim, rating in top_k)
        sim_sum = sum(sim for sim, _ in top_k)
        
        if sim_sum == 0:
            return 0
        
        return weighted_sum / sim_sum
    
    def recommend(self, user_id, n=5):
        """为用户生成Top-N推荐"""
        # 获取用户未评分的项目
        all_items = set()
        for items in self.user_ratings.values():
            all_items.update(items.keys())
        
        user_items = set(self.user_ratings[user_id].keys())
        unrated_items = all_items - user_items
        
        # 预测评分
        predictions = []
        for item in unrated_items:
            pred_rating = self.predict_rating(user_id, item)
            predictions.append((item, pred_rating))
        
        # 按预测评分排序
        predictions.sort(key=lambda x: x[1], reverse=True)
        
        return predictions[:n]

GPT-4o生成结果(节选关键改进部分):

import numpy as np
from typing import Dict, List, Tuple, Set
from collections import defaultdict
import heapq


class UserBasedCollaborativeFiltering:
    """
    基于用户的协同过滤推荐系统
    
    特点:
    1. 使用余弦相似度计算用户相似度
    2. 支持Top-K相似用户选择
    3. 包含评分标准化处理
    4. 提供详细的推荐解释
    """
    
    def __init__(self, k_neighbors: int = 5, min_common_items: int = 2):
        self.k_neighbors = k_neighbors  # 考虑的最近邻数量
        self.min_common_items = min_common_items  # 最小共同评分项目数
        self.user_ratings: Dict[int, Dict[int, float]] = defaultdict(dict)
        self.item_ratings: Dict[int, Dict[int, float]] = defaultdict(dict)
        self.user_means: Dict[int, float] = {}  # 用户平均评分缓存
        self.similarity_cache: Dict[Tuple[int, int], float] = {}  # 相似度缓存
        
    def add_rating(self, user_id: int, item_id: int, rating: float) -> None:
        """添加评分数据"""
        self.user_ratings[user_id][item_id] = rating
        self.item_ratings[item_id][user_id] = rating
        # 清除相关缓存
        self.user_means.pop(user_id, None)
        self._clear_similarity_cache(user_id)
    
    def get_user_mean_rating(self, user_id: int) -> float:
        """获取用户平均评分(带缓存)"""
        if user_id not in self.user_means:
            ratings = list(self.user_ratings[user_id].values())
            self.user_means[user_id] = np.mean(ratings) if ratings else 0.0
        return self.user_means[user_id]
    
    def compute_similarity(self, user1: int, user2: int) -> float:
        """计算两个用户的余弦相似度(带缓存和优化)"""
        # 检查缓存
        cache_key = tuple(sorted([user1, user2]))
        if cache_key in self.similarity_cache:
            return self.similarity_cache[cache_key]
        
        # 获取共同评分项目
        items1 = set(self.user_ratings[user1].keys())
        items2 = set(self.user_ratings[user2].keys())
        common_items = items1.intersection(items2)
        
        # 检查最小共同项目数要求
        if len(common_items) < self.min_common_items:
            similarity = 0.0
        else:
            # 提取评分向量
            vec1 = np.array([self.user_ratings[user1][item] for item in common_items])
            vec2 = np.array([self.user_ratings[user2][item] for item in common_items])
            
            # 计算余弦相似度
            dot_product = np.dot(vec1, vec2)
            norm1 = np.linalg.norm(vec1)
            norm2 = np.linalg.norm(vec2)
            
            if norm1 == 0 or norm2 == 0:
                similarity = 0.0
            else:
                similarity = dot_product / (norm1 * norm2)
        
        # 缓存结果
        self.similarity_cache[cache_key] = similarity
        return similarity
    
    def find_similar_users(self, target_user: int, k: int = None) -> List[Tuple[float, int]]:
        """找到与目标用户最相似的K个用户"""
        if k is None:
            k = self.k_neighbors
        
        similarities = []
        for other_user in self.user_ratings:
            if other_user == target_user:
                continue
            
            similarity = self.compute_similarity(target_user, other_user)
            if similarity > 0:  # 只考虑正相似度
                heapq.heappush(similarities, (similarity, other_user))
                # 保持堆的大小为k
                if len(similarities) > k:
                    heapq.heappop(similarities)
        
        # 返回排序后的结果(相似度从高到低)
        return sorted(similarities, reverse=True)
    
    def predict_rating(self, user_id: int, item_id: int, 
                      use_mean_adjustment: bool = True) -> Tuple[float, Dict]:
        """
        预测用户对项目的评分
        
        返回:
        - 预测评分
        - 包含预测详情的字典
        """
        # 如果用户已经评分过该项目,直接返回
        if item_id in self.user_ratings[user_id]:
            return self.user_ratings[user_id][item_id], {"reason": "already_rated"}
        
        # 获取评分过该项目的用户
        users_rated = self.item_ratings.get(item_id, {})
        if not users_rated:
            user_mean = self.get_user_mean_rating(user_id)
            return user_mean, {"reason": "no_ratings", "fallback": "user_mean"}
        
        # 找到相似用户
        similar_users = self.find_similar_users(user_id)
        
        # 收集相似用户对该项目的评分
        weighted_sum = 0.0
        similarity_sum = 0.0
        contributing_users = []
        
        for similarity, other_user in similar_users:
            if other_user in users_rated:
                other_rating = users_rated[other_user]
                
                if use_mean_adjustment:
                    # 评分标准化:减去用户平均评分
                    other_mean = self.get_user_mean_rating(other_user)
                    user_mean = self.get_user_mean_rating(user_id)
                    adjusted_rating = other_rating - other_mean + user_mean
                else:
                    adjusted_rating = other_rating
                
                weighted_sum += similarity * adjusted_rating
                similarity_sum += similarity
                contributing_users.append({
                    'user': other_user,
                    'similarity': similarity,
                    'rating': other_rating,
                    'adjusted_rating': adjusted_rating if use_mean_adjustment else other_rating
                })
        
        # 计算预测评分
        if similarity_sum > 0:
            prediction = weighted_sum / similarity_sum
            details = {
                "reason": "collaborative_filtering",
                "contributing_users": contributing_users,
                "similarity_sum": similarity_sum,
                "weighted_sum": weighted_sum
            }
        else:
            # 回退到用户平均评分
            prediction = self.get_user_mean_rating(user_id)
            details = {
                "reason": "no_similar_users",
                "fallback": "user_mean",
                "user_mean": prediction
            }
        
        return max(0.0, min(5.0, prediction)), details  # 限制评分范围
    
    def recommend(self, user_id: int, n_recommendations: int = 5,
                 exclude_rated: bool = True) -> List[Tuple[int, float, Dict]]:
        """
        为用户生成推荐
        
        返回:
        - 列表,每个元素为(项目ID, 预测评分, 预测详情)
        """
        # 获取用户未评分的项目
        if exclude_rated:
            user_items = set(self.user_ratings[user_id].keys())
            all_items = set(self.item_ratings.keys())
            candidate_items = all_items - user_items
        else:
            candidate_items = set(self.item_ratings.keys())
        
        # 为每个候选项目预测评分
        predictions = []
        for item_id in candidate_items:
            pred_rating, details = self.predict_rating(user_id, item_id)
            predictions.append((item_id, pred_rating, details))
        
        # 按预测评分排序
        predictions.sort(key=lambda x: x[1], reverse=True)
        
        return predictions[:n_recommendations]

对比分析:

  1. 算法复杂度:GPT-4o实现的版本明显更复杂、更完整,包含了评分标准化、缓存优化、详细解释等高级特性
  2. 代码质量:GPT-4o的代码有完整的类型提示、文档字符串,结构更清晰
  3. 性能考虑:GPT-4o考虑了缓存优化(相似度缓存、用户平均评分缓存),使用了堆数据结构高效查找Top-K相似用户
  4. 实用性:GPT-4o版本提供了更详细的返回信息,便于调试和理解推荐原因

小结:在复杂算法实现上,GPT-4o展现出明显优势。它不仅能实现基本功能,还能考虑性能优化、代码可维护性、用户体验等多个维度。Qwen2.5-Coder-1.5B虽然能生成可工作的代码,但在算法优化和代码质量上还有很大提升空间。

3.2 代码调试与修复

现在测试一下代码调试能力。我准备了一段有bug的Python代码,看看两个模型能否发现并修复问题。

有bug的代码:

def find_duplicates(numbers):
    """找出列表中的重复元素"""
    duplicates = []
    for i in range(len(numbers)):
        for j in range(i + 1, len(numbers)):
            if numbers[i] == numbers[j]:
                duplicates.append(numbers[i])
    return duplicates

# 测试用例
test_cases = [
    [1, 2, 3, 4, 5],  # 无重复
    [1, 2, 3, 2, 4, 5, 3],  # 有重复
    [],  # 空列表
    [1, 1, 1, 1],  # 全部重复
    [1, 2, 3, 4, 2, 3, 2]  # 多个重复
]

for test in test_cases:
    result = find_duplicates(test)
    print(f"列表: {test}, 重复元素: {result}")

测试提示词:

上面的代码有一个问题:当有多个重复元素时,结果中会出现重复的重复项。
例如对于列表 [1, 2, 3, 4, 2, 3, 2],期望输出应该是 [2, 3],但实际输出是 [2, 2, 3]。
请分析问题原因并提供修复方案。

Qwen2.5-Coder-1.5B的分析与修复:

def find_duplicates(numbers):
    """找出列表中的重复元素(修复版本)"""
    duplicates = []
    seen = set()  # 记录已经找到的重复元素
    
    for i in range(len(numbers)):
        for j in range(i + 1, len(numbers)):
            if numbers[i] == numbers[j]:
                # 检查是否已经记录过这个重复元素
                if numbers[i] not in seen:
                    duplicates.append(numbers[i])
                    seen.add(numbers[i])
                break  # 找到重复后跳出内层循环
    
    return duplicates

# 优化版本:使用字典计数
def find_duplicates_optimized(numbers):
    """使用字典计数找出重复元素"""
    from collections import Counter
    
    if not numbers:
        return []
    
    # 统计每个元素的出现次数
    count = Counter(numbers)
    
    # 找出出现次数大于1的元素
    duplicates = [num for num, cnt in count.items() if cnt > 1]
    
    return duplicates

GPT-4o的分析与修复:

"""
问题分析:
原始代码的问题在于,当同一个元素出现多次时,内层循环会多次发现相同的重复对。
例如对于元素2,它在索引1、4、6位置出现:
- 当i=1时,会发现(1,4)和(1,6)两个重复对,导致2被添加两次
- 当i=4时,会发现(4,6)重复对,2又被添加一次

根本原因:算法没有去重机制,且没有在找到第一个重复后就停止检查同一个元素。
"""

def find_duplicates_original_fixed(numbers):
    """
    修复原始算法:添加去重和提前跳出
    
    优点:保持原始双循环逻辑,易于理解
    缺点:时间复杂度O(n²),不适合大数据集
    """
    duplicates = []
    seen_elements = set()
    seen_duplicates = set()
    
    for i in range(len(numbers)):
        current_num = numbers[i]
        
        # 如果当前元素已经在重复集合中,跳过
        if current_num in seen_duplicates:
            continue
        
        # 如果当前元素已经检查过且不是重复,跳过
        if current_num in seen_elements:
            continue
            
        found_duplicate = False
        for j in range(i + 1, len(numbers)):
            if current_num == numbers[j]:
                if not found_duplicate:
                    duplicates.append(current_num)
                    seen_duplicates.add(current_num)
                    found_duplicate = True
                # 可以继续检查其他重复,但已经记录过就不重复添加
        
        if not found_duplicate:
            seen_elements.add(current_num)
    
    return duplicates


def find_duplicates_hashmap(numbers):
    """
    使用哈希表的高效解法
    
    时间复杂度:O(n)
    空间复杂度:O(n)
    """
    if not numbers:
        return []
    
    seen = set()
    duplicates = set()
    
    for num in numbers:
        if num in seen:
            duplicates.add(num)
        else:
            seen.add(num)
    
    return list(duplicates)


def find_duplicates_counter(numbers):
    """
    使用Counter的简洁解法
    
    优点:代码简洁,功能明确
    缺点:需要导入额外模块
    """
    from collections import Counter
    
    counter = Counter(numbers)
    return [num for num, count in counter.items() if count > 1]


def find_duplicates_sorting(numbers):
    """
    使用排序的解法
    
    优点:空间复杂度O(1)(如果不考虑排序需要的空间)
    缺点:修改了原始列表,时间复杂度O(n log n)
    """
    if len(numbers) < 2:
        return []
    
    sorted_nums = sorted(numbers)
    duplicates = []
    
    for i in range(1, len(sorted_nums)):
        if sorted_nums[i] == sorted_nums[i - 1]:
            if not duplicates or duplicates[-1] != sorted_nums[i]:
                duplicates.append(sorted_nums[i])
    
    return duplicates


# 测试所有解法
def test_all_solutions():
    test_cases = [
        ([1, 2, 3, 4, 5], []),  # 无重复
        ([1, 2, 3, 2, 4, 5, 3], [2, 3]),  # 有重复
        ([], []),  # 空列表
        ([1, 1, 1, 1], [1]),  # 全部重复
        ([1, 2, 3, 4, 2, 3, 2], [2, 3]),  # 多个重复
        ([1, 2, 2, 3, 3, 3, 4, 4, 4, 4], [2, 3, 4]),  # 递增重复
    ]
    
    solutions = [
        ("原始修复版", find_duplicates_original_fixed),
        ("哈希表版", find_duplicates_hashmap),
        ("Counter版", find_duplicates_counter),
        ("排序版", find_duplicates_sorting),
    ]
    
    all_passed = True
    
    for test_name, solution_func in solutions:
        print(f"\n测试解法: {test_name}")
        print("-" * 40)
        
        for i, (input_list, expected) in enumerate(test_cases):
            result = solution_func(input_list.copy())  # 使用副本避免修改
            result_sorted = sorted(result)
            expected_sorted = sorted(expected)
            
            passed = result_sorted == expected_sorted
            status = "" if passed else ""
            
            print(f"测试用例 {i+1}: {status}")
            print(f"  输入: {input_list}")
            print(f"  期望: {expected_sorted}")
            print(f"  实际: {result_sorted}")
            
            if not passed:
                all_passed = False
    
    return all_passed


if __name__ == "__main__":
    print("代码调试与修复测试")
    print("=" * 50)
    
    success = test_all_solutions()
    
    if success:
        print("\n 所有测试用例通过!")
    else:
        print("\n  部分测试用例失败,请检查代码逻辑。")

对比分析:

  1. 问题分析深度:GPT-4o提供了更详细的问题分析,解释了为什么会出现重复的重复项
  2. 解决方案多样性:GPT-4o提供了4种不同的解决方案,每种都有优缺点分析
  3. 测试完整性:GPT-4o包含了完整的测试框架,能验证所有解法的正确性
  4. 教学价值:GPT-4o的回复不仅修复了bug,还教给了读者多种解决问题的方法

小结:在代码调试方面,GPT-4o再次展现优势。它不仅能修复bug,还能提供多种解决方案、详细的分析和完整的测试。Qwen2.5-Coder-1.5B虽然能提供正确的修复,但在深度和广度上还有差距。

4. 综合评估与使用建议

4.1 性能对比总结

经过多个维度的测试,我对两个模型的代码生成能力有了更清晰的认识。下面用表格总结一下关键对比点:

对比维度 Qwen2.5-Coder-1.5B GPT-4o 优势方
简单算法实现 代码简洁,功能正确 代码规范,测试全面 平手
实用脚本生成 基础功能完整 考虑周全,错误处理完善 GPT-4o
复杂逻辑实现 能实现基本功能 优化完善,考虑性能 GPT-4o
代码调试能力 能发现并修复问题 深度分析,多种方案 GPT-4o
代码注释质量 基础注释完整 详细规范,包含类型提示 GPT-4o
测试用例提供 基础测试用例 全面测试,边界情况覆盖 GPT-4o
响应速度 极快(本地部署) 中等(依赖API) Qwen2.5
部署成本 极低(消费级硬件) 高(API调用费用) Qwen2.5
数据隐私 完全本地,隐私安全 数据需上传云端 Qwen2.5

4.2 实际使用场景建议

基于测试结果,我建议在不同场景下选择不同的模型:

适合使用Qwen2.5-Coder-1.5B的场景:

  1. 快速原型开发:当你需要快速生成一些基础代码框架时
  2. 学习与教学:学生和初学者用来学习编程基础
  3. 私有化部署:对数据隐私有严格要求的企业环境
  4. 资源受限环境:只有消费级硬件或边缘设备
  5. 简单代码补全:IDE中的基础代码补全和提示

适合使用GPT-4o的场景:

  1. 复杂系统开发:需要高质量、生产级别的代码
  2. 代码审查与优化:深度代码分析和性能优化建议
  3. 架构设计:系统架构和设计模式咨询
  4. 技术方案选型:需要多方案对比和优缺点分析
  5. 紧急问题排查:复杂的bug调试和问题诊断

4.3 如何最大化利用Qwen2.5-Coder-1.5B

虽然Qwen2.5-Coder-1.5B在某些方面不如GPT-4o,但通过一些技巧,你仍然可以充分发挥它的价值:

  1. 分步提示:将复杂任务分解为多个简单步骤

    # 不好的提示:实现一个完整的Web应用
    # 好的提示:1. 先设计数据库模型 2. 实现API接口 3. 编写前端组件
    
  2. 提供上下文:在提示中提供更多背景信息

    # 不好的提示:写一个排序函数
    # 好的提示:我需要一个快速排序函数来处理用户订单数据,数据量在1000条左右
    
  3. 迭代优化:先生成基础代码,然后要求优化

    # 第一轮:生成基本功能
    # 第二轮:添加错误处理
    # 第三轮:优化性能
    
  4. 结合人工审核:将模型生成的代码作为初稿,由开发者进行审查和优化

5. 总结

经过全面的对比测试,我对开源代码大模型的现状有了更清晰的认识:

Qwen2.5-Coder-1.5B的优势在于轻量、快速、隐私安全。它能够在消费级硬件上运行,响应速度快,适合对数据隐私有要求的场景。对于简单的编码任务和学习用途,它完全够用。

GPT-4o的优势在于深度、广度和质量。它生成的代码更接近生产级别,考虑更周全,提供的解决方案更多样。对于复杂的开发任务和关键业务代码,它仍然是更好的选择。

重要发现:虽然Qwen2.5-Coder-1.5B在参数规模上只有GPT-4o的零头,但在基础编码任务上表现出了令人惊讶的能力。这说明专门化的代码训练确实能大幅提升小模型在特定领域的表现。

未来展望:随着开源模型的不断进步,我们有望看到更多在特定领域媲美甚至超越大模型的小型专用模型。对于大多数开发者和企业来说,结合使用大模型进行复杂任务和小模型进行日常开发,可能是最经济高效的选择。

最后,无论选择哪个模型,记住它们都是辅助工具。真正的编程能力、系统思维和问题解决能力,仍然需要开发者自己不断学习和积累。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

更多推荐