跳至主要内容

DeepSeek-Coder-V2 教程:示例、安装、基准测试

DeepSeek-Coder-V2 是一个开源代码语言模型,在性能上可与 GPT-4、Gemini 1.5 Pro、Claude 3 Opus、Llama 3 70B 或 Codestral 比肩。
· 8分钟 阅读

使用 AI 探索

随着 GitHub Copilot 等 AI 编码助手在开发者中走红,开源替代方案也在不断涌现。

其中一个值得关注的例子是 DeepSeek-Coder-V2,这是一款采用先进机器学习技术的强大开源模型。它专为代码相关任务设计,在代码生成、补全与理解方面的表现可与 GPT-4相媲美。

在本文中,我将介绍 DeepSeek-Coder-V2 的功能与特性,并带您上手使用这一工具。

什么是 DeepSeek-Coder-V2?

DeepSeek-Coder-V2 是一款开源的 Mixture-of-Experts(MoE,专家混合) 代码语言模型,在代码专项任务上的表现可与 GPT-4 比肩。该模型旨在助力开发者,具备以下关键特性:

  • 多语言: 在多种编程语言与自然语言(包括英语和中文)上进行训练,适用于全球化的开发团队。
  • 通用性强: 支持 338+ 种编程语言,能够满足多样的编码环境与需求。
  • 大规模: 以万亿级别的代码与文本 token 进行预训练,强化了其在多种编程情境下的理解与生成能力。
  • 多种规模可选: 提供多种模型尺寸,便于开发者根据算力资源与项目需求选择合适的模型。

您可以在 DeepSeek 官网访问该模型,他们提供付费 API 与聊天功能。源代码可在 GitHub 获取,研究论文托管在 arXiv 上。

模型托管在 Huggingface——但由于模型体量较大,要在本地运行需要研究级硬件。

DeepSeek-Coder-V2 基准测试

让我们看看 DeepSeek-Coder-V2 在各项基准测试中的表现,并与 GPT-4 Turbo、Gemini 1.5 Pro、Claude 3 Opus、LLaMA 3-70B 与 Codestral 等模型对比。

来源:Qihao Zhu 等

HumanEval

HumanEval 基准通过检查生成代码是否通过特定单元测试来衡量代码生成能力。DeepSeek-Coder-V2 在该基准上表现出色,准确率达 90.2%。这一结果凸显了其在复杂场景下生成可用且准确代码片段的能力。

MBPP+

MBPP+ 基准聚焦代码理解,评估模型对代码结构与语义的把握。DeepSeek-Coder-V2 再次表现优异,准确率达 76.2%,显示其对代码含义与功能的扎实理解。

MATH

MATH 基准测试模型在代码语境下的数学推理能力。DeepSeek-Coder-V2 以 75.7% 的准确率保持领先,表明其在处理嵌入代码中的数学运算与逻辑方面颇为擅长,这对许多编程任务至关重要。

GSM8K

GSM8K 基准关注解决小学数学应用题,评估模型在纯代码生成之外的广义问题求解能力。DeepSeek-Coder-V2 以 94.9% 的准确率紧随 Claude 3 Opus 之后,展现了对自然语言呈现的数学问题的理解与求解能力。

Aider

Aider 基准评估模型提供代码辅助与建议的能力。DeepSeek-Coder-V2 以 73.7% 的准确率领跑,显示其作为开发者实时指导与支持工具的潜力。

LiveCodeBench

LiveCodeBench 基准衡量模型在真实场景中的代码生成表现。DeepSeek-Coder-V2 的准确率为 43.4%(位列 GPT-4-Turbo-0409 之后第二),展示了其在实际语境中生成可用代码的能力。

SWE Bench 基准

​​SWE-Bench 基准专门评估 AI 模型执行软件工程任务的能力,如代码生成、调试与理解复杂编程概念。在该基准中,DeepSeek-Coder-V2 得分 12.7,表现稳健但并非领先。其落后于 GPT-4-Turbo-0409(18.7)与 Gemini-1.5-Pro(18.3),这两者在相关任务中展现出更强能力。然而,DeepSeek-Coder-V2 仍优于 Claude-3-Opus(11.7)、Llama-3-70B(2.7)与 Codestral,说明基于此基准,它是可靠但非顶尖的软件工程应用之选。

DeepSeek-Coder-V2 的工作原理

DeepSeek-Coder-V2 构建在 DeepSeek-V2 模型之上,采用复杂的专家混合(MoE)架构,以在代码专项任务中实现高性能。该模型利用多个专家模型,每个专家专长于不同编码任务,并根据输入代码动态选择最相关的专家,从而提升推理效率与准确性。

DeepSeek-Coder-V2 的训练过程包含若干关键环节。其在由 60% 源代码、10% 数学语料与 30% 自然语言语料组成的综合数据集上进行预训练,总计 10.2 万亿个 token。多样化的数据集使模型能够高效理解与生成代码。源代码数据集包含 1,1700 亿个 token,来源于 GitHub 与 CommonCrawl,覆盖 338 种编程语言,较以往模型有显著扩展。

DeepSeek-Coder-V2 features

在预训练之后,模型会使用包含编码、数学与通用语言指令的专用指令数据集进行微调。此过程提升了模型对自然语言提示的响应能力,使其成为实用的助手。

对底层架构感兴趣的读者可参考 DeepSeek-Coder-V2 的基础模型 DeepSeek-V2,其引入了多头潜在注意力(MLA)与 DeepSeekMoE 框架等创新。这些创新有助于高效推理与经济训练,详情可见发表在 arXiv 的 DeepSeek-V2 论文。

DeepSeek-Coder-V2 上手指南

开始使用 DeepSeek-Coder-V2 有多种方式。您可以通过 Hugging Face 的 transformers 库在本地运行模型。但请注意,模型体量较大,需要相当可观的计算资源。

或者,DeepSeek 提供了付费 API 与类似 ChatGPT 的在线聊天界面。DeepSeek 的在线聊天还能在对话窗口中直接运行 HTML 与 JavaScript 代码!这一功能相当创新——我只在 Artifacts(Claude 3.5 Sonnet 模型)中见过类似功能。本文的示例将使用聊天功能。

DeepSeek-Coder-V2:示例用法

第一个示例中,我让模型用 HTML 与 JavaScript 编写康威生命游戏。我给出的提示是:“您能用 HTML 编写康威生命游戏吗?”以下是回应:

Certainly! Below is a simple implementation of Conway's Game of Life using HTML, CSS, and JavaScript. This version will display the grid in an HTML table and update it every second.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Conway's Game of Life</title>
    <style>
        table {
            border-collapse: collapse;
        }
        td {
            width: 10px;
            height: 10px;
            border: 1px solid #ccc;
        }
        .alive {
            background-color: black;
        }
        .dead {
            background-color: white;
        }
    </style>
</head>
<body>
    <h1>Conway's Game of Life</h1>
    <table id="grid"></table>
    <script>
        const N = 50; // Grid size
        let grid = createGrid(N);
        let intervalId;
        function createGrid(N) {
            let grid = new Array(N);
            for (let i = 0; i < N; i++) {
                grid[i] = new Array(N);
                for (let j = 0; j < N; j++) {
                    grid[i][j] = Math.random() > 0.7 ? 1 : 0;
                }
            }
            return grid;
        }
        function renderGrid(grid) {
            const table = document.getElementById('grid');
            table.innerHTML = '';
            for (let i = 0; i < N; i++) {
                const row = table.insertRow();
                for (let j = 0; j < N; j++) {
                    const cell = row.insertCell();
                    cell.classList.add(grid[i][j] ? 'alive' : 'dead');
                }
            }
        }
        function updateGrid(grid) {
            const newGrid = grid.map(row => row.slice());
            for (let i = 0; i < N; i++) {
                for (let j = 0; j < N; j++) {
                    const aliveNeighbors = countAliveNeighbors(grid, i, j);
                    if (grid[i][j] === 1) {
                        newGrid[i][j] = aliveNeighbors === 2 || aliveNeighbors === 3 ? 1 : 0;
                    } else {
                        newGrid[i][j] = aliveNeighbors === 3 ? 1 : 0;
                    }
                }
            }
            return newGrid;
        }
        function countAliveNeighbors(grid, x, y) {
            let count = 0;
            for (let i = -1; i <= 1; i++) {
                for (let j = -1; j <= 1; j++) {
                    if (i === 0 && j === 0) continue;
                    const newX = (x + i + N) % N;
                    const newY = (y + j + N) % N;
                    count += grid[newX][newY];
                }
            }
            return count;
        }
        function startGame() {
            intervalId = setInterval(() => {
                grid = updateGrid(grid);
                renderGrid(grid);
            }, 1000);
        }
        renderGrid(grid);
        startGame();
    </script>
</body>
</html>

我们还可以点击回复末尾的“Run HTML”按钮,直接在聊天窗口中运行生命游戏。

Deepseek chat interface allows running HTML and JavaScript

作者截图。

接着,我让模型制作一个可交互的网站版本,以便我可以选择初始棋盘配置。结果如下,而且运行非常流畅。

Dynamic game of life website.

作者截图。

最后一个示例中,我用一道较难的 Project Euler 题目——“jumping frog” 问题来测试模型。以下是模型生成的代码:

import numpy as np

MOD = 10**9


def matrix_power(matrix, n):
    result = np.identity(len(matrix), dtype=int)

    while n > 0:
        if n % 2 == 1:
            result = np.dot(result, matrix) % MOD

        matrix = np.dot(matrix, matrix) % MOD
        n //= 2

    return result


def fib_matrix(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1

    A = np.array([[1, 1, 1], [1, 0, 0], [0, 1, 0]], dtype=int)
    A_power = matrix_power(A, n - 3)
    initial_vector = np.array([2, 1, 1])

    return np.dot(A_power, initial_vector)[0] % MOD


def S(L):
    result = 0

    for n in range(1, L + 1):
        f_n = fib_matrix(n)
        result = (result + f_n**3) % MOD

    return result


# Compute S(10**14) % 10**9
print(S(10**14))

这个脚本需要很长时间才能跑完,于是我让模型进行优化,并得到了以下输出:

import numpy as np

MOD = 10**9


def matrix_power(matrix, n):
    result = np.identity(len(matrix), dtype=int)

    while n > 0:
        if n % 2 == 1:
            result = np.dot(result, matrix) % MOD
        matrix = np.dot(matrix, matrix) % MOD
        n //= 2

    return result


def fib_matrix(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1

    A = np.array([[1, 1, 1], [1, 0, 0], [0, 1, 0]], dtype=int)
    A_power = matrix_power(A, n - 3)
    initial_vector = np.array([2, 1, 1])

    return np.dot(A_power, initial_vector)[0] % MOD


def find_pisano_period(m):
    previous, current = 0, 1
    for i in range(m * m):
        previous, current = current, (previous + current) % m
        if previous == 0 and current == 1:
            return i + 1


def S(L):
    pisano_period = find_pisano_period(MOD)
    period_sum = 0

    for n in range(1, pisano_period + 1):
        f_n = fib_matrix(n)
        period_sum = (period_sum + f_n**3) % MOD

    full_periods, remainder = divmod(L, pisano_period)
    result = (full_periods * period_sum) % MOD

    for n in range(1, remainder + 1):
        f_n = fib_matrix(n)
        result = (result + f_n**3) % MOD

    return result


# Compute S(10**14) % 10**9
print(S(10**14))

我让优化后的代码运行了半小时,仍未得到结果。虽然我认为思路是正确的,但难点在于进一步优化。鉴于目前只有 328 人解出该题,模型未能解决也并不意外。

结语

DeepSeek-Coder-V2 是开源编码助手领域的重要补充,在性能上可与多款成熟的专有模型竞争。

要充分发挥 DeepSeek-Coder-V2 的价值,请遵循最佳实践,给出清晰、具体的提示。我也鼓励您在遇到 Bug 时向开发者反馈。

如果您想进一步了解 AI 编码助手,建议收听这期 DataFramed 播客:The Future of Programming with Kyle Daigle, COO at GitHub。

Dimitri Didmanidze

作者

Dimitri Didmanidze

我叫 Dimitri Didmanidze,是一名数据科学家,目前正在攻读数学硕士学位,研究方向为机器学习。我的学术历程还包括对基于 Transformer 的模型能力进行研究,并在大学层面授课,这些经历加深了我对复杂理论概念的理解。我也曾在银行业工作,将这些原理应用于解决真实世界中的数据难题。

主题