# DeepSeek-V3-0324: ローカル実行方法

{% hint style="info" %}
こちらをご覧ください <https://docs.unsloth.ai/basics/deepseek-r1-0528-how-to-run-locally> (2025年5月28日更新) DeepSeekをより高速かつ効率的に実行する方法を学ぶために！
{% endhint %}

DeepSeekがまたやってくれました！2024年12月と2025年1月にV3、R1 Zero、R1を公開した後、DeepSeekはV3のチェックポイント／モデルを更新し、3月のアップデートをリリースしました！

DeepSeekによると、MMLU-Proは+5.3%上昇して81.2%になりました。 **GPQA +9.3ポイント**. AIME +19.8% と LiveCodeBench +10.0%！彼らは、以前のV3チェックポイントや GPT 4.5、Claude Sonnet 3.7 などの他モデルと比較した図を提供しました。 <mark style="background-color:blue;">**でも、6710億パラメータのモデルをローカルでどう実行するのでしょうか？**</mark>

<table data-full-width="true"><thead><tr><th>MoE ビット数</th><th>タイプ</th><th>ディスクサイズ</th><th>精度</th><th>リンク</th><th>詳細</th></tr></thead><tbody><tr><td>1.78bit</td><td>IQ1_S</td><td><strong>173GB</strong></td><td>OK</td><td><a href="https://huggingface.co/unsloth/DeepSeek-V3-0324-GGUF/tree/main/UD-IQ1_S">リンク</a></td><td>2.06/1.56bit</td></tr><tr><td>1.93bit</td><td>IQ1_M</td><td><strong>183GB</strong></td><td>まずまず</td><td><a href="https://huggingface.co/unsloth/DeepSeek-V3-0324-GGUF/tree/main/UD-IQ1_M">リンク</a></td><td>2.5/2.06/1.56</td></tr><tr><td>2.42bit</td><td>IQ2_XXS</td><td><strong>203GB</strong></td><td><mark style="background-color:blue;"><strong>推奨</strong></mark></td><td><a href="https://huggingface.co/unsloth/DeepSeek-V3-0324-GGUF/tree/main/UD-IQ2_XXS">リンク</a></td><td>2.5/2.06bit</td></tr><tr><td>2.71bit</td><td>Q2_K_XL</td><td><strong>231GB</strong></td><td><mark style="background-color:purple;"><strong>推奨</strong></mark></td><td><a href="https://huggingface.co/unsloth/DeepSeek-V3-0324-GGUF/tree/main/UD-Q2_K_XL">リンク</a></td><td>3.5/2.5bit</td></tr><tr><td>3.5bit</td><td>Q3_K_XL</td><td><strong>320GB</strong></td><td>素晴らしい</td><td><a href="https://huggingface.co/unsloth/DeepSeek-V3-0324-GGUF/tree/main/UD-Q3_K_XL">リンク</a></td><td>4.5/3.5bit</td></tr><tr><td>4.5bit</td><td>Q4_K_XL</td><td><strong>406GB</strong></td><td>最高</td><td><a href="https://huggingface.co/unsloth/DeepSeek-V3-0324-GGUF/tree/main/UD-Q4_K_XL">リンク</a></td><td>5.5/4.5bit</td></tr></tbody></table>

{% hint style="success" %}
DeepSeek V3 の元のアップロードは float8 で、715GB を必要とします。Q4\_K\_M を使うとファイルサイズはおよそ 404GB まで半減し、私たちの動的 1.78bit 量子化は約 151GB に収まります。 **サイズと精度のバランスを取るために、私たちの 2.7bit 量子化の使用を推奨します！2.4bit 版もよく動作します！**
{% endhint %}

## :gear: 公式推奨設定

によると [DeepSeek](https://huggingface.co/deepseek-ai/DeepSeek-V3-0324)、推論に推奨される設定は以下のとおりです：

* <mark style="background-color:blue;">**温度 0.3**</mark> （コード用途では 0.0 でもよいかもしれません [こちらで見られるように](https://api-docs.deepseek.com/quick_start/parameter_settings))
* Min\_P 0.00（任意ですが、0.01 でもうまく動作します。llama.cpp のデフォルトは 0.1 です）
* チャットテンプレート： `<｜User｜>Pythonで、簡単に遊べるFlappy Birdゲームを作成してください。完成したゲームはMarkdownセクション内に配置してください。<｜Assistant｜>`
* BOSトークンの `<｜begin▁of▁sentence｜>` はトークン化の際に自動で追加されます（手動で追加しないでください！）
* DeepSeekは、 <mark style="background-color:green;">**システムプロンプト**</mark> も使用していると述べています（任意）—中国語では次のとおりです： `该助手为DeepSeek Chat，由深度求索公司创造。\n今天是3月24日，星期一。` これは次のように翻訳されます： `このアシスタントは DeepSeek Chat であり、DeepSeek によって作成されました。\n今日は3月24日、月曜日です。`
* <mark style="background-color:orange;">**KVキャッシュの量子化には、4bitではなく8bitを使用してください。明らかに性能が悪くなることがわかりました。**</mark>

## 📖 チュートリアル：llama.cpp で DeepSeek-V3 を実行する方法

1. 最新の `llama.cpp` を [GitHub こちら](https://github.com/ggml-org/llama.cpp)から取得してください。以下のビルド手順に従うこともできます。 `-DGGML_CUDA=ON` を `-DGGML_CUDA=OFF` に変更してください。GPU がない場合、または CPU 推論だけを使いたい場合です。 **Apple Mac / Metal デバイスの場合**、次を設定して `-DGGML_CUDA=OFF` その後は通常どおり続けてください - Metal サポートは既定で有効です。

{% hint style="warning" %}
使用する際の注意 `-DGGML_CUDA=ON` GPU向けではコンパイルに5分かかる場合があります。CPUのみなら1分でコンパイルできます。llama.cpp の事前コンパイル済みバイナリに興味があるかもしれません。
{% endhint %}

```bash
apt-get update
apt-get install pciutils build-essential cmake curl libcurl4-openssl-dev -y
git clone https://github.com/ggml-org/llama.cpp
cmake llama.cpp -B llama.cpp/build \\
    -DBUILD_SHARED_LIBS=OFF -DGGML_CUDA=ON -DLLAMA_CURL=ON
cmake --build llama.cpp/build --config Release -j --clean-first --target llama-quantize llama-cli llama-gguf-split
cp llama.cpp/build/bin/llama-* llama.cpp
```

2. モデルのダウンロード（ `pip install huggingface_hub hf_transfer` のインストール後）。 `UD-IQ1_S`（動的 1.78bit 量子化）または次のような他の量子化版 `Q4_K_M` . <mark style="background-color:green;">**私たちの 2.7bit 動的量子化を使うことを推奨します**</mark><mark style="background-color:green;">**&#x20;**</mark><mark style="background-color:green;">**`UD-Q2_K_XL`**</mark><mark style="background-color:green;">**&#x20;**</mark><mark style="background-color:green;">**サイズと精度のバランスを取るためです**</mark>。その他のバージョンはこちら： <https://huggingface.co/unsloth/DeepSeek-V3-0324-GGUF>

{% code overflow="wrap" %}

```python
# !pip install huggingface_hub hf_transfer
import os
os.environ["HF_HUB_ENABLE_HF_TRANSFER"] = "1"
from huggingface_hub import snapshot_download
snapshot_download(
    repo_id = "unsloth/DeepSeek-V3-0324-GGUF-UD",
    local_dir = "unsloth/DeepSeek-V3-0324-GGUF-UD",
    allow_patterns = ["*UD-Q2_K_XL*"], # 動的 2.7bit（230GB） 「*UD-IQ_S*」は動的 1.78bit（151GB）で使用
)
```

{% endcode %}

3. DeepSeek R1 向けの 1.58bit 動的量子化で説明したとおりに、Unsloth の Flappy Bird テストを実行してください。
4. 編集 `--threads 32` CPU スレッド数を `--ctx-size 16384` コンテキスト長を `--n-gpu-layers 2` GPU オフロードする層数を指定します。GPU のメモリ不足になる場合は調整してみてください。CPU のみで推論する場合は、これも削除してください。

<pre class="language-bash" data-overflow="wrap"><code class="lang-bash">./llama.cpp/llama-cli \\
    --model unsloth/DeepSeek-V3-0324-GGUF-UD/blob/main/UD-Q2_K_XL/DeepSeek-V3-0324-UD-Q2_K_XL-00001-of-00006.gguf \
    <a data-footnote-ref href="#user-content-fn-1">--cache-type-k q8_0 </a>\
    <a data-footnote-ref href="#user-content-fn-2">--threads 20</a> \
    <a data-footnote-ref href="#user-content-fn-3">--n-gpu-layers 2</a> \
    -no-cnv \\
    --prio 3 \\
    --temp 0.3 \
    --min-p 0.01 \\
    <a data-footnote-ref href="#user-content-fn-4">--ctx-size 4096</a> \
    --seed 3407 \\
    --prompt "&#x3C;｜User｜>PythonでFlappy Birdゲームを作成してください。次の要素を必ず含めてください:\n1. pygame を使うこと。\n2. 背景色はランダムに選び、明るい色にすること。最初は薄い青にしてください。\n3. SPACE を何度も押すと鳥が加速すること。\n4. 鳥の形は四角、円、三角形のいずれかからランダムに選ぶこと。色は暗い色からランダムに選ぶこと。\n5. 画面下部に、濃い茶色または黄色からランダムに選んだ色の地面を配置すること。\n6. 右上にスコアを表示すること。パイプを通過して当たらなければ加点すること。\n7. 十分な間隔を空けてランダムな位置にパイプを配置すること。色は濃い緑、薄い茶色、または濃い灰色からランダムにすること。\n8. 失敗したらベストスコアを表示すること。テキストは画面内に収めること。q または Esc を押すとゲームを終了し、SPACE をもう一度押すと再開すること。\n最終的なゲームコードは Python の markdown セクション内に入れてください。最終的な markdown セクションの前にコードをエラー確認して修正してください。&#x3C;｜Assistant｜>"
</code></pre>

<details>

<summary>上記を実行すると、非常に異なる2つの結果が得られます。<br><br><strong>標準の2-bit版：</strong> クリックして結果を表示 <em><mark style="color:赤;"><strong>（発作注意！）</strong></mark></em><br><strong>動的2-bit版：</strong> 以下の結果を見てください：</summary>

<img src="/files/e160b225d22c32752f9754af9d41898373817aca" alt="" data-size="original">

標準の2-bit。背景で失敗し、衝突でも失敗

</details>

<div align="center"><figure><img src="/files/50afc4992845c868e9056e97adcf9ad3dd4baebe" alt="" width="240"><figcaption><p>動的2-bit。プレイ可能なゲームの作成に成功。</p></figcaption></figure></div>

5. DeepSeek-R1 と同様に、V3 は61層あります。たとえば24GB GPUまたは80GB GPUでは、切り捨て後に次の層数をオフロードできると予想できます（メモリ不足になる場合は1減らしてください）：

| 量子化     | ファイルサイズ | 24GB GPU | 80GB GPU | 2x80GB GPU |
| ------- | ------- | -------- | -------- | ---------- |
| 1.73bit | 173GB   | 5        | 25       | 56         |
| 2.22bit | 183GB   | 4        | 22       | 49         |
| 2.51bit | 212GB   | 2        | 19       | 32         |

### Mac / Apple デバイスでの実行

Apple Metal デバイスでは、 `--n-gpu-layers`に注意してください。マシンがメモリ不足になる場合は、これを減らしてください。128GBのユニファイドメモリ搭載マシンなら、59層程度をオフロードできるはずです。

```bash
./llama.cpp/llama-cli \\
    --model DeepSeek-R1-GGUF/DeepSeek-V3-0324-UD-IQ1_S/DeepSeek-V3-0324-UD-IQ1_S-00001-of-00003.gguf \
    --cache-type-k q4_0 \\
    --threads 16 \
    --prio 2 \\
    --temp 0.6 \\
    --ctx-size 8192 \\
    --seed 3407 \\
    --n-gpu-layers 59 \\
    -no-cnv \\
    --prompt "<｜User｜>PythonでFlappy Birdゲームを作成してください。<｜Assistant｜>"
```

## :8ball: 七角形テスト

また、私たちは動的量子化を以下でもテストします [r/Localllama](https://www.reddit.com/r/LocalLLaMA/comments/1j7r47l/i_just_made_an_animation_of_a_ball_bouncing/) これは、動く閉じた六角形ではなく七角形の形の中で回転するボールをシミュレートする基本的な物理エンジンを作るテストです。

<figure><img src="/files/f05be6a8c0f9d69f5cf4e1acc075c328cb73babc" alt="" width="563"><figcaption><p>目標は七角形を回転させることであり、七角形の中のボールは動く必要があります。</p></figcaption></figure>

{% code overflow="wrap" %}

```bash
./llama.cpp/llama-cli \\
    --model unsloth/DeepSeek-V3-0324-GGUF-UD/blob/main/UD-Q2_K_XL/DeepSeek-V3-0324-UD-Q2_K_XL-00001-of-00006.gguf \
    --cache-type-k q8_0 \
    --threads 20 \
    --n-gpu-layers 2 \
    -no-cnv \\
    --prio 3 \\
    --temp 0.3 \
    --min-p 0.01 \\
    --ctx-size 4096 \
    --seed 3407 \\
    --prompt "<｜User｜>回転する七角形の中で20個のボールが跳ね回る様子を表示するPythonプログラムを書いてください：\n- すべてのボールは同じ半径を持つ。\n- すべてのボールには1から20までの番号が付いている。\n- すべてのボールは開始時に七角形の中心から落下する。\n- 色は次のとおり：#f8b862, #f6ad49, #f39800, #f08300, #ec6d51, #ee7948, #ed6d3d, #ec6800, #ec6800, #ee7800, #eb6238, #ea5506, #ea5506, #eb6101, #e49e61, #e45e32, #e17b34, #dd7a56, #db8449, #d66a35\n- ボールは重力と摩擦の影響を受け、回転する壁に現実的に跳ね返らなければならない。ボール同士の衝突も必要。\n- すべてのボールの材質は、衝突時の跳ね返りの高さが七角形の半径を超えないが、ボールの半径よりは高くなることを意味する。\n- すべてのボールは摩擦で回転し、ボール上の数字はボールのスピンを示すために使える。\n- 七角形は中心の周りで回転し、回転速度は5秒あたり360度とする。\n- 七角形のサイズは、すべてのボールを収められる十分な大きさでなければならない。\n- pygameライブラリは使用しないでください。衝突検出アルゴリズムや衝突応答などは自分で実装してください。次のPythonライブラリは使用可能です：tkinter, math, numpy, dataclasses, typing, sys。\n- すべてのコードは1つのPythonファイルにまとめてください。<｜Assistant｜>"
```

{% endcode %}

<table data-view="cards"><thead><tr><th></th><th data-type="files"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td>動的ではない2-bit。失敗 - <mark style="background-color:red;">発作注意</mark> 再び！</td><td><a href="/files/583589aa97dd7200a4342651d1002ffa474d3260">/files/583589aa97dd7200a4342651d1002ffa474d3260</a></td><td><a href="/files/61268463453026422d0c4e458a8807dad3d4bdf0">/files/61268463453026422d0c4e458a8807dad3d4bdf0</a></td></tr><tr><td>動的2-bit。実際に七角形パズルを正しく解決!!</td><td><a href="/files/024b156d9fd9fb703975c63094d7847a023978d4">/files/024b156d9fd9fb703975c63094d7847a023978d4</a></td><td><a href="/files/af5fea87532a18c68bb1d11cc04750b7004acb29">/files/af5fea87532a18c68bb1d11cc04750b7004acb29</a></td></tr><tr><td>元の float8</td><td><a href="/files/3731b22a03437572da94d9ab22f65bfe2a106963">/files/3731b22a03437572da94d9ab22f65bfe2a106963</a></td><td><a href="/files/61b9326f403c1746bf890748c2c125def37ac11f">/files/61b9326f403c1746bf890748c2c125def37ac11f</a></td></tr></tbody></table>

サイズがたった230GBの動的2.7bit量子化が、実際に七角形パズルの解決に成功しました！3つのバージョンすべて（完全なfp8を含む）の完全な出力は以下です：

<details>

<summary>動的2-bit 七角形コード</summary>

```python
import tkinter as tk
import math
import numpy as np
from dataclasses import dataclass
from typing import List, Tuple, Optional

# 定数
HEPTAGON_RADIUS = 300
BALL_RADIUS = 20
GRAVITY = 0.2
FRICTION = 0.99
BOUNCE_FACTOR = 0.8
ROTATION_SPEED = 360 / 5  # 1秒あたりの度数
SPIN_FRICTION = 0.98
BALL_COLORS = [
    "#f8b862", "#f6ad49", "#f39800", "#f08300", "#ec6d51",
    "#ee7948", "#ed6d3d", "#ec6800", "#ec6800", "#ee7800",
    "#eb6238", "#ea5506", "#ea5506", "#eb6101", "#e49e61",
    "#e45e32", "#e17b34", "#dd7a56", "#db8449", "#d66a35"
]

@dataclass
class Ball:
    x: float
    y: float
    vx: float
    vy: float
    number: int
    spin: float = 0.0
    color: str = "#000000"

@dataclass
class Wall:
    x1: float
    y1: float
    x2: float
    y2: float

class BouncingBalls:
    def __init__(self, root):
        self.root = root
        self.canvas = tk.Canvas(root, width=800, height=800, bg="white")
        self.canvas.pack()
        self.balls: List[Ball] = []
        self.walls: List[Wall] = []
        self.heptagon_angle = 0
        self.last_time = 0
        
        self.setup_balls()
        self.setup_heptagon()
        
        self.root.after(16, self.update)
        self.root.bind("<space>", self.reset_balls)
    
    def setup_balls(self):
        for i in range(20):
            ball = Ball(
                x=400,
                y=400,
                vx=np.random.uniform(-5, 5),
                vy=np.random.uniform(-5, 5),
                number=i+1,
                color=BALL_COLORS[i]
            )
            self.balls.append(ball)
    
    def setup_heptagon(self):
        # 初期の七角形の壁を作成
        self.update_heptagon_walls(0)
    
    def update_heptagon_walls(self, angle):
        self.walls = []
        center_x, center_y = 400, 400
        angle_rad = math.radians(angle)
        
        for i in range(7):
            angle1 = angle_rad + 2 * math.pi * i / 7
            angle2 = angle_rad + 2 * math.pi * (i + 1) / 7
            
            x1 = center_x + HEPTAGON_RADIUS * math.cos(angle1)
            y1 = center_y + HEPTAGON_RADIUS * math.sin(angle1)
            x2 = center_x + HEPTAGON_RADIUS * math.cos(angle2)
            y2 = center_y + HEPTAGON_RADIUS * math.sin(angle2)
            
            self.walls.append(Wall(x1, y1, x2, y2))
    
    def reset_balls(self, event=None):
        for ball in self.balls:
            ball.x = 400
            ball.y = 400
            ball.vx = np.random.uniform(-5, 5)
            ball.vy = np.random.uniform(-5, 5)
            ball.spin = np.random.uniform(-5, 5)
    
    def update(self):
        current_time = self.root.after_idle(self.root.after, 16, self.update)
        if self.last_time == 0:
            self.last_time = current_time
            return
        
        # 経過時間を計算（概算）
        dt = 0.016  # 約60FPSと仮定
        
        # 七角形の回転を更新
        self.heptagon_angle += ROTATION_SPEED * dt
        self.update_heptagon_walls(self.heptagon_angle)
        
        # ボールを更新
        for ball in self.balls:
            # 重力を適用
            ball.vy += GRAVITY
            
            # 摩擦を適用
            ball.vx *= FRICTION
            ball.vy *= FRICTION
            ball.spin *= SPIN_FRICTION
            
            # ボールを移動
            ball.x += ball.vx
            ball.y += ball.vy
            
            # 壁との衝突を確認
            self.check_wall_collisions(ball)
            
            # 他のボールとの衝突を確認
            for other in self.balls:
                if other.number != ball.number:
                    self.check_ball_collision(ball, other)
        
        # すべて描画
        self.draw()
    
    def check_wall_collisions(self, ball):
        for wall in self.walls:
            # 壁セグメント上のボールに最も近い点を求める
            closest = self.closest_point_on_segment(
                wall.x1, wall.y1, wall.x2, wall.y2, ball.x, ball.y
            )
            
            # 壁までの距離を計算
            dx = ball.x - closest[0]
            dy = ball.y - closest[1]
            distance = math.sqrt(dx*dx + dy*dy)
            
            if distance < BALL_RADIUS:
                # 衝突を検出
                # 法線ベクトルを計算
                nx = dx / distance
                ny = dy / distance
                
                # 法線方向の相対速度を計算
                v_rel = ball.vx * nx + ball.vy * ny
                
                if v_rel < 0:  # 壁に向かって移動中
                    # 反力を計算
                    j = -(1 + BOUNCE_FACTOR) * v_rel
                    
                    # 反力を適用
                    ball.vx += j * nx
                    ball.vy += j * ny
                    
                    # 衝突に基づいてスピンを少し加える
                    ball.spin += (ball.vx * ny - ball.vy * nx) * 0.1
                    
                    # ボールを衝突から押し戻す
                    penetration = BALL_RADIUS - distance
                    ball.x += penetration * nx
                    ball.y += penetration * ny
    
    def check_ball_collision(self, ball1, ball2):
        dx = ball2.x - ball1.x
        dy = ball2.y - ball1.y
        distance = math.sqrt(dx*dx + dy*dy)
        
        if distance < 2 * BALL_RADIUS:
            # 衝突を検出
            nx = dx / distance
            ny = dy / distance
            
            # 相対速度を計算
            v_rel_x = ball2.vx - ball1.vx
            v_rel_y = ball2.vy - ball1.vy
            v_rel = v_rel_x * nx + v_rel_y * ny
            
            if v_rel < 0:  # 互いに向かって移動中
                # 反力を計算
                j = -(1 + BOUNCE_FACTOR) * v_rel / 2
                
                # 反力を適用
                ball1.vx -= j * nx
                ball1.vy -= j * ny
                ball2.vx += j * nx
                ball2.vy += j * ny
                
                # 衝突に基づいてスピンを加える
                ball1.spin += (ball1.vx * ny - ball1.vy * nx) * 0.05
                ball2.spin += (ball2.vx * ny - ball2.vy * nx) * 0.05
                
                # ボール同士を引き離す
                penetration = 2 * BALL_RADIUS - distance
                ball1.x -= penetration * nx * 0.5
                ball1.y -= penetration * ny * 0.5
                ball2.x += penetration * nx * 0.5
                ball2.y += penetration * ny * 0.5
    
    @staticmethod
    def closest_point_on_segment(x1, y1, x2, y2, x, y):
        # 点から線分の始点へのベクトル
        dx = x - x1
        dy = y - y1
        
        # 線分ベクトル
        sx = x2 - x1
        sy = y2 - y1
        
        # 点の線分への射影
        dot = dx * sx + dy * sy
        len_sq = sx * sx + sy * sy
        param = dot / len_sq if len_sq != 0 else -1
        
        if param < 0:
            return x1, y1
        elif param > 1:
            return x2, y2
        else:
            return x1 + param * sx, y1 + param * sy
    
    def draw(self):
        self.canvas.delete("all")
        
        # 七角形を描画
        points = []
        for wall in self.walls:
            points.extend([wall.x1, wall.y1])
        self.canvas.create_polygon(points, fill="", outline="black", width=2)
        
        # ボールを描画
        for ball in self.balls:
            # ボールを描画
            self.canvas.create_oval(
                ball.x - BALL_RADIUS, ball.y - BALL_RADIUS,
                ball.x + BALL_RADIUS, ball.y + BALL_RADIUS,
                fill=ball.color, outline="black"
            )
            
            # スピンに基づいて数字を描画
            angle = ball.spin * 10  # 視覚効果のためにスピンを拡大
            self.canvas.create_text(
                ball.x, ball.y,
                text=str(ball.number),
                font=("Arial", 12, "bold"),
                angle=angle
            )

if __name__ == "__main__":
    root = tk.Tk()
    root.title("回転する七角形の中の跳ねるボール")
    app = BouncingBalls(root)
    root.mainloop()
```

</details>

<details>

<summary>動的でない2-bit 七角形コード</summary>

```python
import tkinter as tk
import math
import random
from dataclasses import dataclass
from typing import List, Tuple, Optional
import sys

# 定数
WIDTH, HEIGHT = 800, 800
HEPTAGON_RADIUS = 300
BALL_RADIUS = 15
GRAVITY = 0.5
FRICTION = 0.999
ELASTICITY = 0.8
ROTATION_SPEED = 2 * math.pi / 5  # 5秒あたり360度
SPIN_DECAY = 0.99

# ボールの色
BALL_COLORS = [
    "#f8b862", "#f6ad49", "#f39800", "#f08300", "#ec6d51",
    "#ee7948", "#ed6d3d", "#ec6800", "#ec6800", "#ee7800",
    "#eb6238", "#ea5506", "#ea5506", "#eb6101", "#e49e61",
    "#e45e32", "#e17b34", "#dd7a56", "#db8449", "#d66a35"
]

@dataclass
class Ball:
    x: float
    y: float
    vx: float
    vy: float
    radius: float
    color: str
    number: int
    spin: float = 0.0

@dataclass
class Heptagon:
    center_x: float
    center_y: float
    radius: float
    angle: float = 0.0

class BouncingBalls:
    def __init__(self, root):
        self.root = root
        self.canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT, bg="white")
        self.canvas.pack()
        
        self.heptagon = Heptagon(WIDTH//2, HEIGHT//2, HEPTAGON_RADIUS)
        self.balls = []
        self.setup_balls()
        
        self.root.after(0, self.update)
        self.root.mainloop()
    
    def setup_balls(self):
        center_x, center_y = WIDTH//2, HEIGHT//2
        for i in range(20):
            self.balls.append(Ball(
                x=center_x,
                y=center_y,
                vx=0,
                vy=0,
                radius=BALL_RADIUS,
                color=BALL_COLORS[i],
                number=i+1,
                spin=0
            ))
    
    def update(self):
        self.canvas.delete("all")
        
        # 七角形の角度を更新
        self.heptagon.angle += ROTATION_SPEED / 60  # 60FPSを想定
        
        # 七角形を描画
        self.draw_heptagon()
        
        # ボールを更新して描画
        for ball in self.balls:
            # 重力を適用
            ball.vy += GRAVITY
            
            # 位置を更新
            ball.x += ball.vx
            ball.y += ball.vy
            
            # 摩擦を適用
            ball.vx *= FRICTION
            ball.vy *= FRICTION
            
            # スピンの減衰を適用
            ball.spin *= SPIN_DECAY
            
            # 七角形の壁との衝突を確認
            self.check_heptagon_collision(ball)
            
            # 他のボールとの衝突を確認
            for other in self.balls:
                if other != ball:
                    if self.check_ball_collision(ball, other):
                        self.resolve_ball_collision(ball, other)
            
            # ボールを描画
            self.draw_ball(ball)
        
        self.root.after(16, self.update)  # 約60FPS
    
    def draw_heptagon(self):
        center_x, center_y = self.heptagon.center_x, self.heptagon.center_y
        points = []
        for i in range(7):
            angle = self.heptagon.angle + i * 2 * math.pi / 7
            x = center_x + self.heptagon.radius * math.cos(angle)
            y = center_y + self.heptagon.radius * math.sin(angle)
            points.append((x, y))
        
        # 七角形を描画
        self.canvas.create_polygon(
            [points[0], points[1], points[2], points[3], 
             points[4], points[5], points[6]],
            outline="black", fill="", width=2
        )
    
    def draw_ball(self, ball):
        self.canvas.create_oval(
            ball.x - ball.radius,
            ball.y - ball.radius,
            ball.x + ball.radius,
            ball.y + ball.radius,
            fill=ball.color,
            outline="black"
        )
        
        # 数字を描画
        self.canvas.create_text(
            ball.x, ball.y,
            text=str(ball.number),
            fill="black"
        )
    
    def check_heptagon_collision(self, ball):
        center_x, center_y = WIDTH//2, HEIGHT//2
        
        # 中心からの距離を確認
        dx = ball.x - center_x
        dy = ball.y - center_y
        dist = math.sqrt(dx**2 + dy**2)
        
        if dist + ball.radius > self.heptagon.radius:
            # 中心からボールへの法線ベクトルを求める
            angle = math.atan2(dy, dx)
            normal_x = math.cos(angle)
            normal_y = math.sin(angle)
            
            # ボールを七角形の内側に戻す
            overlap = (dist + ball.radius) - self.heptagon.radius
            ball.x -= overlap * normal_x
            ball.y -= overlap * normal_y
            
            # 速度を反射する
            dot_product = ball.vx * normal_x + ball.vy * normal_y
            ball.vx -= 2 * dot_product * normal_x * ELASTICITY
            ball.vy -= 2 * dot_product * normal_y * ELASTICITY
    
    def check_ball_collision(self, ball1, ball2):
        dx = ball2.x - ball1.x
        dy = ball2.y - ball1.y
        distance = math.sqrt(dx**2 + dy**2)
        return distance < (ball1.radius + ball2.radius)
    
    def resolve_ball_collision(self, ball1, ball2):
        dx = ball2.x - ball1.x
        dy = ball2.y - ball1.y
        distance = math.sqrt(dx**2 + dy**2)
        
        # 法線ベクトル
        nx = dx / distance
        ny = dy / distance
        
        # 相対速度
        dvx = ball2.vx - ball1.vx
        dvy = ball2.vy - ball1.vy
        
        # 反力を計算
        impulse = 2 * (dvx * nx + dvy * ny) / 2
        impulse *= ELASTICITY
        
        # 反力を適用
        ball1.vx -= impulse * nx
        ball1.vy -= impulse * ny
        ball2.vx += impulse * nx
        ball2.vy += impulse * ny
        
        # ボールがくっつくのを防ぐために分離する
        overlap = (ball1.radius + ball2.radius) - distance
        ball1.x -= overlap * nx / 2
        ball1.y -= overlap * ny / 2
        ball2.x += overlap * nx / 2
        ball2.y += overlap * ny / 2
    
    def run(self):
        self.root.mainloop()

if __name__ == "__main__":
    root = tk.Tk()
    root.title("回転する七角形の中の跳ねるボール")
    app = BouncingBalls(root)
    app.run()
```

</details>

<details>

<summary>Float8 七角形コード</summary>

```python
import tkinter as tk
import math
import numpy as np
from dataclasses import dataclass
from typing import List, Tuple, Optional

# 定数
WIDTH, HEIGHT = 800, 800
CENTER_X, CENTER_Y = WIDTH // 2, HEIGHT // 2
GRAVITY = 0.2
FRICTION = 0.99
BALL_RADIUS = 15
HEPTAGON_RADIUS = 300
ROTATION_SPEED = 360 / 5  # 1秒あたりの度数
ELASTICITY = 0.8
SPIN_FRICTION = 0.98

# ボールの色
BALL_COLORS = [
    '#f8b862', '#f6ad49', '#f39800', '#f08300', '#ec6d51',
    '#ee7948', '#ed6d3d', '#ec6800', '#ec6800', '#ee7800',
    '#eb6238', '#ea5506', '#ea5506', '#eb6101', '#e49e61',
    '#e45e32', '#e17b34', '#dd7a56', '#db8449', '#d66a35'
]

@dataclass
class Ball:
    x: float
    y: float
    vx: float
    vy: float
    radius: float
    color: str
    number: int
    spin: float = 0.0

    def move(self):
        self.x += self.vx
        self.y += self.vy
        self.vy += GRAVITY
        self.vx *= FRICTION
        self.vy *= FRICTION
        self.spin *= SPIN_FRICTION

    def collide_with_ball(self, other: 'Ball'):
        dx = other.x - self.x
        dy = other.y - self.y
        distance = math.hypot(dx, dy)
        
        if distance < self.radius + other.radius:
            # 衝突法線を計算
            nx = dx / distance
            ny = dy / distance
            
            # 相対速度を計算
            dvx = other.vx - self.vx
            dvy = other.vy - self.vy
            
            # 反力を計算
            impulse = 2 * (dvx * nx + dvy * ny) / (1/self.radius + 1/other.radius)
            
            # 反力を適用
            self.vx += impulse * nx / self.radius
            self.vy += impulse * ny / self.radius
            other.vx -= impulse * nx / other.radius
            other.vy -= impulse * ny / other.radius
            
            # ボール同士がくっつかないように分離する
            overlap = (self.radius + other.radius - distance) / 2
            self.x -= overlap * nx
            self.y -= overlap * ny
            other.x += overlap * nx
            other.y += overlap * ny
            
            # いくつかのスピンを移す
            transfer = impulse * 0.01
            self.spin -= transfer
            other.spin += transfer

class HeptagonBounceSimulator:
    def __init__(self, root):
        self.root = root
        self.canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT, bg='white')
        self.canvas.pack()
        
        self.balls = self.create_balls()
        self.heptagon_angle = 0
        self.last_time = 0
        self.running = True
        
        self.root.bind('<space>', self.toggle_pause)
        self.root.bind('<Escape>', lambda e: root.destroy())
        
        self.last_time = self.root.after(0, self.update)
    
    def create_balls(self) -> List[Ball]:
        balls = []
        for i in range(20):
            # すべてのボールを中心から、少しランダムな速度で開始する
            angle = np.random.uniform(0, 2 * math.pi)
            speed = np.random.uniform(0.5, 2)
            vx = math.cos(angle) * speed
            vy = math.sin(angle) * speed
            
            balls.append(Ball(
                x=CENTER_X,
                y=CENTER_Y,
                vx=vx,
                vy=vy,
                radius=BALL_RADIUS,
                color=BALL_COLORS[i],
                number=i+1,
                spin=np.random.uniform(-2, 2)
            ))
        return balls
    
    def toggle_pause(self, event):
        self.running = not self.running
        if self.running:
            self.last_time = self.root.after(0, self.update)
    
    def get_heptagon_vertices(self) -> List[Tuple[float, float]]:
        vertices = []
        for i in range(7):
            angle = math.radians(self.heptagon_angle + i * 360 / 7)
            x = CENTER_X + HEPTAGON_RADIUS * math.cos(angle)
            y = CENTER_Y + HEPTAGON_RADIUS * math.sin(angle)
            vertices.append((x, y))
        return vertices
    
    def check_ball_heptagon_collision(self, ball: Ball):
        vertices = self.get_heptagon_vertices()
        closest_dist = float('inf')
        closest_normal = (0, 0)
        closest_edge = None
        
        # 七角形の各辺との衝突を確認する
        for i in range(len(vertices)):
            p1 = vertices[i]
            p2 = vertices[(i + 1) % len(vertices)]
            
            # p1 から p2 へのベクトル
            edge_x = p2[0] - p1[0]
            edge_y = p2[1] - p1[1]
            edge_length = math.hypot(edge_x, edge_y)
            
            # 辺のベクトルを正規化する
            edge_x /= edge_length
            edge_y /= edge_length
            
            # 法線ベクトル（辺に垂直で、内側を向く）
            nx = -edge_y
            ny = edge_x
            
            # p1 からボールへのベクトル
            ball_to_p1_x = ball.x - p1[0]
            ball_to_p1_y = ball.y - p1[1]
            
            # ボールを辺の法線に投影する
            projection = ball_to_p1_x * nx + ball_to_p1_y * ny
            
            # 投影が負なら、ボールは七角形の外側にある
            if projection < ball.radius:
                # 辺上でボールに最も近い点を見つける
                edge_proj = ball_to_p1_x * edge_x + ball_to_p1_y * edge_y
                edge_proj = max(0, min(edge_length, edge_proj))
                closest_x = p1[0] + edge_proj * edge_x
                closest_y = p1[1] + edge_proj * edge_y
                
                # ボールから辺上の最も近い点までの距離
                dist = math.hypot(ball.x - closest_x, ball.y - closest_y)
                
                if dist < closest_dist:
                    closest_dist = dist
                    closest_normal = (nx, ny)
                    closest_edge = (p1, p2)
        
        if closest_dist < ball.radius:
            # バウンドの応答を計算する
            dot_product = ball.vx * closest_normal[0] + ball.vy * closest_normal[1]
            
            # 弾性を適用して跳ね返す
            ball.vx -= (1 + ELASTICITY) * dot_product * closest_normal[0]
            ball.vy -= (1 + ELASTICITY) * dot_product * closest_normal[1]
            
            # 衝撃に基づいて少しスピンを加える
            edge_vec = (closest_edge[1][0] - closest_edge[0][0], 
                        closest_edge[1][1] - closest_edge[0][1])
            edge_length = math.hypot(edge_vec[0], edge_vec[1])
            if edge_length > 0:
                edge_vec = (edge_vec[0]/edge_length, edge_vec[1]/edge_length)
                # 速度と辺の方向の外積
                spin_effect = (ball.vx * edge_vec[1] - ball.vy * edge_vec[0]) * 0.1
                ball.spin += spin_effect
            
            # ボールを七角形の外に移動して、めり込みを防ぐ
            penetration = ball.radius - closest_dist
            ball.x += penetration * closest_normal[0]
            ball.y += penetration * closest_normal[1]
    
    def update(self):
        if not self.running:
            return
        
        # キャンバスをクリア
        self.canvas.delete('all')
        
        # 七角形の回転を更新
        self.heptagon_angle += ROTATION_SPEED / 60  # 約60FPSを想定
        
        # 七角形を描画
        vertices = self.get_heptagon_vertices()
        self.canvas.create_polygon(vertices, outline='black', fill='', width=2)
        
        # ボールを更新して描画
        for i, ball in enumerate(self.balls):
            # ボールを移動
            ball.move()
            
            # 七角形との衝突を確認する
            self.check_ball_heptagon_collision(ball)
            
            # ボールを描画
            self.canvas.create_oval(
                ball.x - ball.radius, ball.y - ball.radius,
                ball.x + ball.radius, ball.y + ball.radius,
                fill=ball.color, outline='black'
            )
            
            # スピンに基づいて数字を描画
            angle = ball.spin * 10  # 見える回転になるようスピンを拡大
            self.canvas.create_text(
                ball.x, ball.y,
                text=str(ball.number),
                font=('Arial', 10, 'bold'),
                angle=angle
            )
        
        # ボール同士の衝突を確認する
        for i in range(len(self.balls)):
            for j in range(i + 1, len(self.balls)):
                self.balls[i].collide_with_ball(self.balls[j])
        
        # 次の更新を予約
        self.last_time = self.root.after(16, self.update)  # 約60FPS

if __name__ == '__main__':
    root = tk.Tk()
    root.title('回転する七角形の中で跳ねるボール')
    simulator = HeptagonBounceSimulator(root)
    root.mainloop()
```

</details>

## :detective: 追加の発見とヒント

1. 経験的なテストでは、低いKVキャッシュ量子化（4bit）を使うと生成品質が低下するようです。さらにテストが必要ですが、 `q8_0` キャッシュ量子化の使用を提案します。量子化の目的は、KVキャッシュがかなり多くのメモリを使うため、より長いコンテキスト長をサポートすることです。
2. 私たちは `down_proj` がこのモデルにおいて非常に量子化に敏感であることを確認しました。私たちはいくつかの動的量子化をやり直す必要がありましたが、そこで2bitsを使っていました `down_proj` が、現在はこれらの行列すべてに対して最小でも3bitsを使っています。
3. を使うと `llama.cpp` のFlash Attentionバックエンドは、ある程度高速なデコード速度になります。コンパイル時には `-DGGML_CUDA_FA_ALL_QUANTS=ON` を使ってください。なお、CUDAアーキテクチャは次のサイトで確認して設定するのが最善です <https://developer.nvidia.com/cuda-gpus> コンパイル時間を短縮するために、次のように設定してください `-DCMAKE_CUDA_ARCHITECTURES="80"`
4. を使うと `min_p=0.01`でおそらく十分です。 `llama.cpp`のデフォルトは0.1ですが、おそらく必要ありません。いずれにせよ温度が0.3なので、低確率トークンをサンプルする可能性は非常に低く、したがって可能性の低いトークンを除外するのは良い考えです。DeepSeek はコーディングタスクに対して温度0.0を推奨しています。

[^1]: 必ず8bitを使用してください - 4bitではありません

[^2]: お使いのマシンのCPUスレッド数

[^3]: 24GB GPU なら約2。80GB GPU なら約18。

[^4]: : SigLIP2 NaFlex 形状最適化 400M


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://unsloth.ai/docs/jp/moderu/tutorials/deepseek-v3-0324-how-to-run-locally.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
