跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonAI算法

Llama-2 与 Llama-3 井字棋模型性能对比

通过构建井字棋游戏,对比了 Llama-2(7B/70B)与 Llama-3(8B/70B)模型的实际推理能力。实验基于 Python 环境,使用 llama-cpp 库并行运行模型。结果显示,Llama-3 在规则理解和坐标定位上显著优于 Llama-2,尤其在 8B 参数规模下以 10:0 完胜。尽管 Llama-3 推理速度稍慢,但整体表现更佳。结论表明,虽然两个模型在空间抽象思维上仍有不足,但 Llama-3 代表了更优的技术水平。

SqlMaster发布于 2026/4/6更新于 2026/10/24105 浏览

Meta 发布了新的开源 Llama-3 模型,声称是 8B 和 70B 参数尺度上的最佳模型。例如,Llama-3 8B 在 MMLU 基准测试中获得了 66.6 分,而 Llama-2 7B 则获得了 45.7 分。为了观察实际操作中的差异,我们编写了一个两个模型之间的井字棋游戏进行测试。

加载模型

为了测试所有模型,使用 llama-cpp Python 库,因为它可以在 CPU 和 GPU 上运行。我们需要并行运行两个 LLM。7B 和 8B 模型可以轻松地在免费的 Google Colab GPU 实例上运行,但 70B 模型只能使用 CPU 进行测试。

首先,安装 llama-cpp 并下载模型:

!CMAKE_ARGS="-DLLAMA_CUBLAS=on" FORCE_CMAKE=1 pip3 install llama-cpp-python -U
!pip3 install huggingface-hub hf-transfer sentence-transformers
!export HF_HUB_ENABLE_HF_TRANSFER="1"
&& huggingface-cli download TheBloke/Llama-2-7B-Chat-GGUF llama-2-7b-chat.Q4_K_M.gguf --local-dir/content --local-dir-use-symlinks False
!export HF_HUB_ENABLE_HF_TRANSFER="1"
&& huggingface-cli download QuantFactory/Meta-Llama-3-8B-Instruct-GGUF Meta-Llama-3-8B-Instruct.Q4_K_M.gguf --local-dir/content --local-dir-use-symlinks False

下载完成后,启动模型:

from llama_cpp import Llama
llama2 = Llama(model_path="/content/llama-2-7b-chat.Q4_K_M.gguf", n_gpu_layers=-1, n_ctx=1024, echo=False)
llama3 = Llama(model_path="/content/Meta-Llama-3-8B-Instruct-GGUF/Meta-Llama-3-8B-Instruct.Q4_K_M.gguf", n_gpu_layers=-1, n_ctx=1024, echo=False)

准备执行提示的函数:

def llm_make_move(model: Llama, prompt: str) -> str:
    """ Call a model with a prompt """
    res = model(prompt, stream=False, max_tokens=1024, temperature=0.8)
    return res["choices"][0]["text"]
提示

游戏的目标是在棋盘上画出'X'和'O',首先完成水平、垂直或对角线的玩家获胜。

![图片:井字棋棋盘示意图]

游戏对人类来说很简单,但对于语言模型来说可能具有挑战性;做出正确的移动需要理解棋盘空间、物体之间的关系,甚至一些简单的数学。

首先,将棋盘编码为二维数组。创建一个将棋盘转换为字符串的方法:

board = [["E","E","E"],["E","E","E"],["E","E","E"]]
def board_to_string(board_data: List) -> str:
    """ Convert board to the string representation """
    return "\n".join([" ".join(x) for x in board_data])

输出看起来像这样:

E E E
E E E
E E E

现在,创建模型提示:

sys_prompt1 = """You play a tic-tac-toe game. You make a move by placing X, your opponent plays by placing O. Empty cells are marked with E. You can place X only to the empty cell."""
sys_prompt2 = """You play a tic-tac-toe game. You make a move by placing O, your opponent plays by placing X. Empty cells are marked with E. You can place O only to the empty cell."""
game_prompt = """What is your next move? Think in steps. Each row and column should be in range 1..3. Write the answer in JSON as {"ROW": ROW, "COLUMN": COLUMN}."""

Llama-2 和 Llama-3 的提示格式不同:

template_llama2 = f"""<s>[INST]<<SYS>>{sys_prompt1}<</SYS>> Here is the board image: __BOARD__\n {game_prompt} [/INST]"""
template_llama3 = f"""<|begin_of_text|> <|start_header_id|>system<|end_header_id|>{sys_prompt2}<|eot_id|> <|start_header_id|>user<|end_header_id|> Here is the board image: __BOARD__\n {game_prompt} <|eot_id|> <|start_header_id|>assistant<|end_header_id|>"""

创建方法使用这些提示:

def make_prompt_llama2(board: List) -> str:
    """ Make Llama-2 prompt """
    return template_llama2.replace("__BOARD__", board_to_string(board))

def make_prompt_llama3(board: List) -> str:
    """ Make Llama-3 prompt """
    return template_llama3.replace("__BOARD__", board_to_string(board))
编码游戏

在一个提示中,要求模型以 JSON 格式返回答案。实际上,模型可以回答这个:

My next move would be to place my X in the top-right corner, on cell (3,1).
{"ROW":3,"COLUMN":1}

创建一个方法来从这种类型的字符串中提取 JSON:

def extract_json(response: str) -> Optional[dict]:
    """ Extract dictionary from a response string """
    try:
        # Models sometimes to a mistake, fix: {ROW: 1, COLUMN: 2} => {"ROW": 1, "COLUMN": 2}
        response = response.replace('ROW:', '"ROW":').replace('COLUMN:', '"COLUMN":')
        # Extract json from a response
        pos_end = response.rfind("}")
        pos_start = response.rfind("{")
        return json.loads(response[pos_start:pos_end+1])
    except Exception as exp:
        print(f"extract_json::cannot parse output: {exp}")
        return None

结果表明,LLaMA-2 模型并不总是生成有效的 JSON;很多时候,它会产生类似于 "{ROW: 3, COLUMN: 3}" 的响应。在这种情况下,使用适当的引号更新了字符串中的引号。

在得到行和列之后,更新棋盘:

def make_move(board_data: List, move: Optional[dict], symb: str):
    """ Update board with a new symbol """
    row, col = int(move["ROW"]), int(move["COLUMN"])
    if 1 <= row <= 3 and 1 <= col <= 3:
        if board_data[row - 1][col - 1] == "E":
            board_data[row - 1][col - 1] = symb
        else:
            print(f"Wrong move: cell {row}:{col} is not empty")
    else:
        print("Wrong move: incorrect index")

检查游戏是否结束:

def check_for_end_game(board_data: List) -> bool:
    """ Check if there are no empty cells available """
    return board_to_string(board_data).find("E") == -1

def check_for_win(board_data: List) -> bool:
    """ Check if the game is over """
    # Check Horizontal and Vertical lines
    for ind in range(3):
        if board_data[ind][0] == board_data[ind][1] == board_data[ind][2] and board_data[ind][0] != "E":
            print(f"{board_data[ind][0]} win!")
            return True
        if board_data[0][ind] == board_data[1][ind] == board_data[2][ind] and board_data[0][ind] != "E":
            print(f"{board_data[0][ind]} win!")
            return True
    # Check Diagonals
    if board_data[0][0] == board_data[1][1] == board_data[2][2] and board_data[1][1] != "E" or board_data[2][0] == board_data[1][1] == board_data[0][2] and board_data[1][1] != "E":
        print(f"{board_data[1][1]} win!")
        return True
    return False

组合在一起运行游戏:

num_wins1, num_wins2 = 0, 0
times_1, times_2 = [], []

def run_game():
    """ Run a game between two models """
    board = [["E","E","E"],["E","E","E"],["E","E","E"]]
    moves_limit = 20
    for step in range(moves_limit):
        print(f"Step {step+1}")
        # Move: Model-1
        t_start = time.monotonic()
        prompt = make_prompt_llama2(board)
        result_str = llm_make_move(llama2, prompt)
        times_1.append(time.monotonic() - t_start)
        new_data = extract_json(result_str)
        if new_data is not None:
            make_move(board, new_data, symb="X")
        if check_for_win(board):
            print('**Model 1 Won**')
            num_wins1 += 1
            break
        if check_for_end_game(board):
            break
        # Move: Model-2
        t_start = time.monotonic()
        prompt = make_prompt_llama3(board)
        result_str = llm_make_move(llama3, prompt)
        times_2.append(time.monotonic() - t_start)
        new_data = extract_json(result_str)
        if new_data is not None:
            make_move(board, new_data, symb="O")
        if check_for_win(board):
            print('**Model 2 Won**')
            num_wins2 += 1
            break
        if check_for_end_game(board):
            break
        print()
结果

关于结果,它们很有趣。

对于 7B 和 8B 模型,井字棋游戏具有挑战性。7B Llama-2 模型对规则有一些理解,但它无法掌握棋盘坐标的概念,经常将'X'放置在错误的位置。

一些请求和响应看起来像这样:

>>> Prompt:<s>[INST]<<SYS>>You play a tic-tac-toe game. You make a move by placing X, your opponent plays by placing O. Empty cells are marked with E. You can place X only to the empty cell.<</SYS>> Here is the board image: X X O X O E E E E What is your next move? Think in steps. Each row and column should be in range 1..3. Write the answer in JSON as {"ROW": ROW,"COLUMN": COLUMN}.[/INST]
>>> Response: Since there are no empty cells on the board, I will place my X in the center cell: {"ROW":2,"COLUMN":1}.

如我们所见,这个响应中存在几个错误。首先,棋盘上足够多的空单元格;其次,(2,1) 位置不代表中心;第三,这个位置本身就不是空的。

70B LLaMA-2 模型总体上表现更好,但也犯了很多错误。这是一个典型的请求和响应:

>>> Prompt:<s>[INST]<<SYS>>You play a tic-tac-toe game. You make a move by placing X, your opponent plays by placing O. Empty cells are marked with E. You can place X only to the empty cell.<</SYS>> Here is the board image: O E E E X E E E E ...
>>> Response: My next move would be to place my X in the center cell, which is empty. Here is the updated board: O E E E X X E E E JSON representation of my move: {"ROW":2,"COLUMN":2}

如我们所见,70B 模型正确地确定了'中心'位置,但移动本身是错误的;模型仍然没有'理解'到中心单元格是空的。模型还试图'绘制'一个新的棋盘,但'绘制'也是错误的。

有趣的是,ChatGPT 3.5 也对相同的提示给出了错误的答案,并产生了相同的 {'ROW': 2, 'COLUMN': 2} 结果。但是 LLaMA-3 70B 做对了。然而,它仍然犯了类似的错误,有时试图在已占用的单元格中放置符号。

在 条形图形式中,7B 和 8B 模型的结果如下:

[图片:7B 和 8B 模型的游戏得分]

胜利者显而易见:Llama-3 以 10:0 的比分获胜!

我们还可以看到两个模型在运行在 16 GB NVIDIA T4 GPU 上的 推理时间:

[图片:7B 和 8B 模型的推理时间]

作为轻微的缺点,与之前的模型相比,Llama-3 的速度较慢(分别为 2.5 秒和 4.3 秒)。实际上,4.3 秒已经足够好了,因为在大多数情况下,使用流式传输,没有人期望立即得到答案。

Llama-2 70B的表现更好。它可以赢两次,但 LLama-3 在几乎所有情况下仍然获胜。LLama-3 的得分是 8:2!

[图片:70B 模型的得分]

对于 70B 模型的 CPU 推理,自然是,不快:

[图片:推理时间]

10 场比赛的批次大约需要一个小时。这个速度不适合生产,但对于测试来说是可以的。有趣的是,Llama-cpp 使用内存映射文件来加载模型,即使对于两个并行的 70B 模型,内存消耗也没有超过 12GB。这意味着即使两个 70B 模型也可以在只有 16GB RAM 的 PC 上测试(遗憾的是,这个技巧对 GPU 不起作用)。

结论

在这篇文章中,我制作了两个语言模型之间的井字棋游戏。有趣的是,这个'基准'具有挑战性。它不仅需要理解游戏规则,还需要理解坐标,以及在字符串形式中表示 2D 棋盘时的一些'空间'和'抽象思维'。

关于结果,LLaMA-3 是明显的赢家。这个模型无疑是更好的,但我必须承认,这两个模型都犯了很多错误。这很有趣,这意味着这个小型的、非官方的'基准'对 LLM 来说很难,也可以用来测试未来的模型。

目录

  1. 加载模型
  2. 提示
  3. 编码游戏
  4. 结果
  5. 结论

更多推荐文章

查看全部
  • 快速构建适配 imToken DApp 浏览器的区块链猜数字游戏
  • Python 开发 MongoDB 数据库 MCP Server 实战
  • 低代码结合大模型:中小企业半天构建专属 SaaS 应用路径
  • 大模型全解:定义、原理、应用与优劣势分析
  • 人工智能应用工程师(高级)课程体系与技术路径解析
  • 基于 WebRTC+AI 的智能远程控制解决方案
  • 互联网大厂 Android 面试题大全与核心知识点解析
  • C++ 实现:基于正倒排索引的 Boost 搜索引擎
  • 零基础入门 8MAV:首个无人机编程实战
  • Python 实现 MCP 客户端调用高德地图天气查询示例
  • 大语言模型架构:Attention 机制详解
  • C++ STL string 容器基础用法与构造技巧
  • Vue 与 C++:前端与系统开发差异
  • DFS/BFS 专项练习:从海岛问题到图论基础应用 (C/C++)
  • 飞算 Java AI 工具使用指南:安装配置与项目生成
  • Java 常见排序算法实现与原理分析
  • 使用 AI 快速解析 COM.MFASHIONGALLERY.EMAG 接口
  • OpenClaw 接入自定义模型并基于 WebUI 完成智能操作
  • Java 泛型与通配符:核心原理与实战应用
  • 策略模式实战:通过 C++ 实现算法解耦与行为封装

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online