Qwen2.5-Coder-1.5B与GPT-4o代码生成能力对比测试
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类常见的编程任务,覆盖不同难度和场景:
- 基础算法实现(排序、查找等)
- 数据处理脚本(文件操作、数据清洗)
- Web开发相关(API接口、前端组件)
- 代码调试与修复
- 复杂逻辑实现
所有测试都使用相同的提示词模板,确保对比的公平性。
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])}")
对比分析:
- 代码正确性:两者都正确实现了快速排序算法,都能正常工作
- 实现方式:Qwen2.5使用了列表推导式,代码更简洁;GPT-4o使用了传统的for循环,更易理解
- 注释质量:两者注释都很详细,但GPT-4o的注释更贴近实际教学场景
- 测试用例: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()
对比分析:
- 功能完整性:两者都实现了核心功能,但GPT-4o的版本更全面,包含了数据类型的检查、更详细的错误处理、以及额外的统计指标(最小值、最大值)
- 缺失值处理:Qwen2.5使用平均值填充,GPT-4o使用中位数填充(对异常值更鲁棒)
- 代码结构:GPT-4o的代码结构更清晰,函数职责更明确,错误处理更完善
- 用户体验: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]
对比分析:
- 算法复杂度:GPT-4o实现的版本明显更复杂、更完整,包含了评分标准化、缓存优化、详细解释等高级特性
- 代码质量:GPT-4o的代码有完整的类型提示、文档字符串,结构更清晰
- 性能考虑:GPT-4o考虑了缓存优化(相似度缓存、用户平均评分缓存),使用了堆数据结构高效查找Top-K相似用户
- 实用性: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 部分测试用例失败,请检查代码逻辑。")
对比分析:
- 问题分析深度:GPT-4o提供了更详细的问题分析,解释了为什么会出现重复的重复项
- 解决方案多样性:GPT-4o提供了4种不同的解决方案,每种都有优缺点分析
- 测试完整性:GPT-4o包含了完整的测试框架,能验证所有解法的正确性
- 教学价值: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的场景:
- 快速原型开发:当你需要快速生成一些基础代码框架时
- 学习与教学:学生和初学者用来学习编程基础
- 私有化部署:对数据隐私有严格要求的企业环境
- 资源受限环境:只有消费级硬件或边缘设备
- 简单代码补全:IDE中的基础代码补全和提示
适合使用GPT-4o的场景:
- 复杂系统开发:需要高质量、生产级别的代码
- 代码审查与优化:深度代码分析和性能优化建议
- 架构设计:系统架构和设计模式咨询
- 技术方案选型:需要多方案对比和优缺点分析
- 紧急问题排查:复杂的bug调试和问题诊断
4.3 如何最大化利用Qwen2.5-Coder-1.5B
虽然Qwen2.5-Coder-1.5B在某些方面不如GPT-4o,但通过一些技巧,你仍然可以充分发挥它的价值:
-
分步提示:将复杂任务分解为多个简单步骤
# 不好的提示:实现一个完整的Web应用 # 好的提示:1. 先设计数据库模型 2. 实现API接口 3. 编写前端组件 -
提供上下文:在提示中提供更多背景信息
# 不好的提示:写一个排序函数 # 好的提示:我需要一个快速排序函数来处理用户订单数据,数据量在1000条左右 -
迭代优化:先生成基础代码,然后要求优化
# 第一轮:生成基本功能 # 第二轮:添加错误处理 # 第三轮:优化性能 -
结合人工审核:将模型生成的代码作为初稿,由开发者进行审查和优化
5. 总结
经过全面的对比测试,我对开源代码大模型的现状有了更清晰的认识:
Qwen2.5-Coder-1.5B的优势在于轻量、快速、隐私安全。它能够在消费级硬件上运行,响应速度快,适合对数据隐私有要求的场景。对于简单的编码任务和学习用途,它完全够用。
GPT-4o的优势在于深度、广度和质量。它生成的代码更接近生产级别,考虑更周全,提供的解决方案更多样。对于复杂的开发任务和关键业务代码,它仍然是更好的选择。
重要发现:虽然Qwen2.5-Coder-1.5B在参数规模上只有GPT-4o的零头,但在基础编码任务上表现出了令人惊讶的能力。这说明专门化的代码训练确实能大幅提升小模型在特定领域的表现。
未来展望:随着开源模型的不断进步,我们有望看到更多在特定领域媲美甚至超越大模型的小型专用模型。对于大多数开发者和企业来说,结合使用大模型进行复杂任务和小模型进行日常开发,可能是最经济高效的选择。
最后,无论选择哪个模型,记住它们都是辅助工具。真正的编程能力、系统思维和问题解决能力,仍然需要开发者自己不断学习和积累。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
更多推荐

所有评论(0)