サイバーエージェントがDeepSeek-R1に日本語で追加学習したモデルを無料で公開しました。
HuggingFaceやOllamaを使用することで、DeepSeek-R1の日本語モデルをローカル環境にダウンロードして利用できます。
この記事では、HuggingFace-Transformersで実装する方法と、Ollama-Pythonで実装する方法の2つを紹介します。
ざっくり言うと
- サイバーエージェントがDeepSeek-R1に日本語で追加学習したモデルを紹介
- HuggingFace-Transformersを使用して、日本語モデルを実装する方法を解説
- Ollama-Pythonを使用して、日本語モデルを実装する方法を解説
DeepSeek-R1の日本語モデルとは?

サイバーエージェントは「DeepSeek-R1」の蒸留モデルに、日本語の追加学習を行った「DeepSeek-R1-Distill-Qwen-14B/32B-Japanese」を公開しました。
HuggingFaceやOllamaを使用することで、DeepSeek-R1の日本語モデルをローカル環境にダウンロードして利用できます。
この記事では、HuggingFace-Transformersで実装する方法と、Ollama-Pythonで実装する方法の2つを紹介します。
HuggingFace-Transformers
HuggingFaceからモデルをダウンロードでき、モデルのファインチューニングや量子化など自由度が高い利用が可能です。
Ollama-Python
Ollamaでは簡単に高速な推論を実行可能です。また、OllamaはLangChainにも対応しており、RAG環境での LLM 利用にも適しています。Ollama-Pythonは、OllamaをPythonから操作するためのライブラリです。
DeepSeek-R1の日本語モデルをChatGPT風に構築するには?

DeepSeek-R1を活用したRAGの構築方法は?

DeepSeek-R1のアプリの使い方は?

日本語モデルの種類と必要なGPUメモリ(VRAM)

サイバーエージェントは140億と320億パラメータの2種類のモデルをHuggingFaceに公開しています。
また、これらのモデルをGGUF形式に変換し、量子化を施したモデルも公開されています。
いずれのモデルもMITライセンスのもとで提供されており、無料で商用利用が可能です。
モデルID | パラメータ数 | GPUメモリ(VRAM) | 参考GPUスペック |
---|---|---|---|
cyberagent/DeepSeek-R1-Distill-Qwen-14B-Japanese | 14B(140億) | 36GB(量子化なし) | NVIDIA A100 80GB x1枚 |
cyberagent/DeepSeek-R1-Distill-Qwen-32B-Japanese | 32B(320億) | 82GB(量子化なし) 21GB(量子化あり) | NVIDIA H200 141GB x1枚 NVIDIA A100 80GB x1枚 |
mmnga/cyberagent-DeepSeek-R1-Distill-Qwen-32B-Japanese-gguf | 32B(320億) | 17GB(量子化 Q4_K_M) | NVIDIA A100 40GB x1枚 |
量子化モデルとは
精度が落とす代わりにGPUメモリの消費を抑えることができるモデルです。
GGUFとは
モデルをGGUF形式に変換することで、Ollamaでの利用が可能になります。
DeepSeek-R1の他のモデルは?

DeepSeek-R1の日本語モデルの環境構築

この記事で用意した実行環境は以下のとおりです。
- GPU:NVIDIA A100 80GB
- GPUメモリ(VRAM):80GB
- OS :Ubuntu 22.04
- Docker
Dockerで環境構築
Dockerを使用してDeepSeek-R1の日本語モデルの環境構築をします
Dockerの使い方を詳しく解説!

Ubuntuのコマンドラインで、Dockerfileを作成します。
mkdir deepseekr1-cyber
cd deepseekr1-cyber
nano Dockerfile
Dockerfileに以下の記述を貼り付けます。
# ベースイメージ(CUDA)の指定
FROM nvidia/cuda:12.1.0-cudnn8-devel-ubuntu22.04
# 必要なパッケージをインストール
RUN apt-get update && apt-get install -y python3-pip python3-venv git nano curl
# Ollamaをインストール
RUN curl -fsSL https://ollama.com/install.sh | sh
# 作業ディレクトリを設定
WORKDIR /app
# アプリケーションコードをコピー
COPY . /app
# Python仮想環境の作成
RUN python3 -m venv /app/.venv
# 仮想環境をアクティベートするコマンドを.bashrcに追加
RUN echo "source /app/.venv/bin/activate" >> /root/.bashrc
# JupyterLabのインストール
RUN /app/.venv/bin/pip install Jupyter jupyterlab
# PyTorchのインストール
RUN /app/.venv/bin/pip install torch==2.4.0 torchvision==0.19.0 torchaudio==2.4.0 --index-url https://download.pytorch.org/whl/cu121
# Transformers関連のインストール
RUN /app/.venv/bin/pip install transformers==4.47.0 accelerate bitsandbytes
# Ollama関連のインストール
RUN /app/.venv/bin/pip install ollama==0.4.4
# コンテナの起動時にbashを実行
CMD ["/bin/bash"]
FROM nvidia/cuda:12.1.0-cudnn8-devel-ubuntu22.04
CUDA12.1のベースイメージを指定しています。
RUN apt-get update && apt-get install -y python3-pip python3-venv git nano curl
Python関連のパッケージをインストールしています。
RUN curl -fsSL https://ollama.com/install.sh | sh
Linux用のOllamaをインストールします。
RUN /app/.venv/bin/pip install torch==2.4.0 torchvision==0.19.0 torchaudio==2.4.0 --index-url https://download.pytorch.org/whl/cu121
PyTorch関連のパッケージをインストールしています。
RUN /app/.venv/bin/pip install transformers==4.47.0 accelerate bitsandbytes
Transformers関連のパッケージをインストールしています。
RUN /app/.venv/bin/pip install ollama==0.4.4
Python用のOllamaをインストールしています。
docker-compose.ymlでDockerコンテナの設定をします。
docker-compose.ymlのYAMLファイルを作成して開きます。
nano docker-compose.yml
以下のコードをコピーして、YAMLファイルに貼り付けます。
services:
deepseekr1-cyber:
build:
context: .
dockerfile: Dockerfile
image: deepseekr1-cyber
runtime: nvidia
container_name: deepseekr1-cyber
ports:
- "8888:8888"
volumes:
- .:/app/deepseekr1-cyber
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
command: >
bash -c '/usr/local/bin/ollama serve & /app/.venv/bin/jupyter lab --ip="*" --port=8888 --NotebookApp.token="" --NotebookApp.password="" --no-browser --allow-root'
bash -c '/usr/local/bin/ollama serve
Ollama Serverを起動しています。
PythonのOllamaを使用する際に、Ollama Serverを起動しておく必要がありますので、ご注意ください。
& /app/.venv/bin/jupyter lab --ip="*" --port=8888 --NotebookApp.token="" --NotebookApp.password="" --no-browser --allow-root'
Jupyter Labを8888番ポートで起動しています。
Dockerfileからビルドしてコンテナを起動します。
docker compose up
Dockerの起動後にブラウザの検索窓に”localhost:8888″を入力すると、Jupyter Labをブラウザで表示できます。
localhost:8888
DeepSeek-R1の日本語モデルを実装(HuggingFace-Transformers編)

ここでは、HuggingFace-Transformersを使った日本語モデルの実装方法を紹介します。
その次のセクションでOllamaを使用した実装方法について解説します。
Dockerコンテナで起動した JupyterLab上で、モデルを実装していきます。
DeepSeek-R1の日本語モデル「cyberagent/DeepSeek-R1-Distill-Qwen-32B-Japanese」をダウンロードします。
import torch
import transformers
from transformers import AutoModelForCausalLM, AutoTokenizer,BitsAndBytesConfig
model_id = "cyberagent/DeepSeek-R1-Distill-Qwen-32B-Japanese"
quantization_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
)
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
model_id,
torch_dtype=torch.bfloat16,
device_map="cuda",
quantization_config=quantization_config,
)
DeepSeek-R1の他のモデルは?

model_id = "cyberagent/DeepSeek-R1-Distill-Qwen-32B-Japanese"
HuggingFaceからダウンロードするモデルIDを指定します。
quantization_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
)
量子化のパラメータを指定しています。量子化より精度を落とす代わりにGPUメモリを節約できます。
load_in_4bit=True
:4-bit 量子化を有効化しています。
bnb_4bit_quant_type="nf4"
:4-bit 量子化の方式をNormalFloat4に指定しています。
bnb_4bit_compute_dtype=torch.float16
:量子化モデルの計算時のデータ型をbfloat16に指定しています。
tokenizer = AutoTokenizer.from_pretrained(model_id)
指定したモデルに対応するトークナイザーをダウンロードして読み込みます。
model = AutoModelForCausalLM.from_pretrained(
model_id,
torch_dtype=torch.bfloat16,
device_map="cuda",
quantization_config=quantization_config,
)
モデルをダウンロードして読み込みます。
torch_dtype=torch.bfloat16
:モデルのデータ型をbfloat16に指定します。
device_map="cuda"
:GPUにモデルに割り当てます。
quantization_config=quantization_config
:量子化のパラメータを渡しています。
DeepSeek-R1の日本語モデルを使用して、実際にテキストを生成してみます。
DEFAULT_SYSTEM_PROMPT = "あなたは日本語で回答するアシスタントです。"
text = """
PQRSの4人チームで毎年恒例のサッカーの総当たり戦が行われた。
順位に関して次のことが分かっている。なお、同じ順位のチームはない。
Ⅰ Pは昨年より順位が3つ下だった。
Ⅱ Qは今年と昨年で順位が変わらなかった。
Ⅲ Rは今年2位であった。
今年の順位を左が上位として並べたとき、ただしいものを選べ。
<選択肢>
A.SRPQ
B.SRQP
C.PRSQ
D.RPQS
"""
messages = [
{"role": "system", "content": DEFAULT_SYSTEM_PROMPT},
{"role": "user", "content": text},
]
prompt = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
token_ids = tokenizer.encode(
prompt, add_special_tokens=False,
return_tensors="pt"
)
with torch.no_grad():
output_ids = model.generate(
token_ids.to(model.device),
max_new_tokens=4096,
do_sample=True,
temperature=0.7,
)
output = tokenizer.decode(
output_ids.tolist()[0][token_ids.size(1):],
skip_special_tokens=True
)
print(output)
messages = [
{"role": "system", "content": DEFAULT_SYSTEM_PROMPT},
{"role": "user", "content": text},
]
DEFAULT_SYSTEM_PROMPT
にシステムプロンプトが入ります。
text
にユーザープロンプトが入ります。
prompt = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
apply_chat_template()
: 会話履歴をモデルが理解しやすいプロンプトの形式に整形します。tokenize=False
: ここでは文字列としてプロンプトを返すため、内部でのトークン化は行いません。add_generation_prompt=True
: モデルが回答を開始する位置を明示するための指示がプロンプトに自動的に追加されます。
token_ids = tokenizer.encode(
prompt, add_special_tokens=False,
return_tensors="pt"
)
生成された文字列を、モデルが処理できるトークンIDに変換します。
add_special_tokens=False
: 特殊トークンを追加しない設定をします。return_tensors="pt"
: 結果を PyTorch のテンソル形式で返します。
with torch.no_grad():
output_ids = model.generate(
token_ids.to(model.device),
max_new_tokens=4096,
do_sample=True,
temperature=0.7,
)
モデルの回答をトークンIDの形式で生成します。
torch.no_grad()
: 推論時は勾配計算を行わず、メモリや計算リソースの消費を抑えます。
token_ids.to(model.device)
: トークンIDをモデルが動作しているデバイス(CPUまたはGPU)に転送します。
max_new_tokens=4096
: 生成する新規トークンの最大数を指定しています。ここでは最大4096トークンまで生成可能です。
do_sample=True
: サンプリングを使って文章を生成する設定です。生成結果に確率的なバリエーションが生まれます。
temperature=0.7
: 値を上げると生成によりランダム性が加わり、値を下げるとより保守的で確定的なテキストが生成されます。
output = tokenizer.decode(
output_ids.tolist()[0][token_ids.size(1):],
skip_special_tokens=True
)
モデルが生成したトークンIDを、人間が読める文字列に変換します。
output_ids
はトークンIDのテンソル形式になっていますので、.tolist()
でPyTorchのテンソルをPythonのリスト形式に変換します。
[token_ids.size(1):]
により、入力プロンプト部分をスライスで除外 し、モデルが新たに生成した部分のみを取得します。
モデルの回答
<think>
まず、問題を整理します。4人チームP、Q、R、Sが総当たり戦で順位を決め、今年の順位を左が上位で並べたものを選ぶ問題です。選択肢はAからDまであります。
条件を一つずつ確認します。
Ⅰ:Pは昨年より順位が3つ下になった。つまり、昨年のPの順位から今年が3つ下。例えば、昨年が1位なら今年は4位、昨年が2位なら今年は5位(不可能)、よって昨年が1位の場合、今年は4位になる。ただし、総当たり戦なので4チームなので、昨年が1位なら今年は4位、昨年が2位なら今年は5位(不可能)なので、Pの昨年の順位は1位しかあり得ない。つまり、Pは昨年1位で、今年は4位。
Ⅱ:Qは今年と昨年で順位が変わらなかった。つまり、Qの順位は昨年と同じ。
Ⅲ:Rは今年2位であった。つまり、今年の順位はRが2位。
選択肢を見ると、今年の順位がRが2位である必要がある。選択肢AはSRPQ→Rが3位、BはSRQP→Rが2位、CはPRSQ→Rが2位、DはRPQS→Rが1位。つまり、BとCとDの一部がRが2位の可能性。
しかし、ⅢよりRは今年2位なので、選択肢B(SRQP)はRが2位、C(PRSQ)はRが2位、D(RPQS)はRが1位なのでDはRが2位でない。したがって、Dは除外される。
次に、Pの今年の順位は4位(昨年1位→今年4位)。選択肢Bの順位はS(1位)、R(2位)、Q(3位)、P(4位)→Pは4位で条件Ⅰを満たす。Qは今年3位、昨年も3位(条件Ⅱ)。Rは今年2位(条件Ⅲ)。Sは今年1位。
選択肢C(PRSQ)は順位がP(1位)、R(2位)、S(3位)、Q(4位)。すると、Pは今年1位で、昨年は1位→今年も1位だが、条件ⅠではPは昨年より3つ下(昨年1位→今年4位)なので矛盾。したがってCは不適切。
選択肢BのS(1位)、R(2位)、Q(3位)、P(4位)→Qは今年3位、昨年も3位(条件Ⅱ)。Rは今年2位(条件Ⅲ)。Pは昨年1位→今年4位(条件Ⅰ)。Sは今年1位。これで全ての条件を満たす。
選択肢A(SRPQ)は順位S、R、P、Q。Rは2位(条件ⅢOK)、Pは3位。Pは昨年1位→今年3位→3つ下になるのは昨年1位→今年4位なので、矛盾。よってAは不適切。
したがって、正解は選択肢B(SRQP)。
</think>
**解答:**
選択肢 **B. SRQP** が正しいです。
---
### **解説ステップ**
1. **条件Ⅰ(Pの順位)**
- 昨年1位 → 今年4位(「3つ下」の解釈)。
- 例: 昨年1位 → 今年4位(4チームのため、3つ下がる)。
2. **条件Ⅱ(Qの順位)**
- 今年と昨年で順位が同じ。
- 例: 今年3位 → 昨年も3位。
3. **条件Ⅲ(Rの順位)**
- 今年2位。
4. **選択肢の検証**
- **選択肢B(SRQP)**:
- 今年の順位: S(1位), R(2位), Q(3位), P(4位)。
- - Pは昨年1位 → 今年4位(条件ⅠOK)。
- - Qは今年3位 → 昨年も3位(条件ⅡOK)。
- - Rは今年2位(条件ⅢOK)。
- - Sは今年1位(未記載条件だが矛盾なし)。
- 他の選択肢は条件と矛盾します(例: 選択肢CのPが今年1位→昨年1位と矛盾)。
---
### **結論**
今年の順位は **S(1位)→ R(2位)→ Q(3位)→ P(4位)** となり、選択肢 **B. SRQP** が正解です。
DeepSeek-R1の日本語モデルを実装(Ollama-Python編)

ここからOllama-Python使ったDeepSeek-R1の日本語モデルの実装方法を解説します。
Dockerコンテナで起動した JupyterLab上で、モデルを実装していきます。
HuggingFaceから「mmnga/cyberagent-DeepSeek-R1-Distill-Qwen-32B-Japanese-gguf」をダウンロードします。
!curl -L -o cyberagent-DeepSeek-R1-Distill-Qwen-32B-Japanese-Q4_K_M.gguf "https://huggingface.co/mmnga/cyberagent-DeepSeek-R1-Distill-Qwen-32B-Japanese-gguf/resolve/main/cyberagent-DeepSeek-R1-Distill-Qwen-32B-Japanese-Q4_K_M.gguf?download=true"
DeepSeek-R1の他のモデルは?

ダウンロードしたモデルをOllamaで使用できるように設定します。
import ollama
modelfile='''
FROM ./cyberagent-DeepSeek-R1-Distill-Qwen-32B-Japanese-Q4_K_M.gguf
TEMPLATE """{{- if .System }}{{ .System }}{{ end }}
{{- range $i, $_ := .Messages }}
{{- $last := eq (len (slice $.Messages $i)) 1}}
{{- if eq .Role "user" }}<|User|>{{ .Content }}
{{- else if eq .Role "assistant" }}<|Assistant|>{{ .Content }}{{- if not $last }}<|end▁of▁sentence|>{{- end }}
{{- end }}
{{- if and $last (ne .Role "assistant") }}<|Assistant|>{{- end }}
{{- end }}"""
PARAMETER stop <|begin▁of▁sentence|>
PARAMETER stop <|end▁of▁sentence|>
PARAMETER stop <|User|>
PARAMETER stop <|Assistant|>
'''
ollama.create(model='deepseekr1-32b-jpn', modelfile=modelfile)
modelfile='''
モデルファイルを定義します。
モデルファイルは、Ollamaでカスタムモデルを設定するためのスクリプトです。
FROM ./cyberagent-DeepSeek-R1-Distill-Qwen-32B-Japanese-Q4_K_M.gguf
ダウンロードしたモデルのパスが入ります。
TEMPLATE """{{- if .System }}{{ .System }}{{ end }}...
モデルで使用するプロンプトテンプレートが入ります。
プロンプトテンプレートはモデルによって異なりますので、ご注意ください。
ollama.create(model='deepseekr1-32b-jpn', modelfile=modelfile)
モデルとプロンプトテンプレートを使ってOllama用のモデルを作成します。
model
にはOllamaで呼び出す際に使用する名前をつけられます。
DeepSeek-R1の日本語モデルを使用して、実際にテキストを生成してみます。
DEFAULT_SYSTEM_PROMPT = "あなたは日本語で回答するアシスタントです。"
text ="""
X、Y、Zが同じ絵を見てて、次のように発言した。
X この絵には虎が描かれている。
Y この絵には少なくとも虎か龍が描かれている。
Z この絵には龍が描かれている。
全員が本当のことを言っているとは限らない。そこで、以下の推論がなされた。次のうち正しいものを一つ選びなさい。
A. Yが正しければXは必ず正しい
B. Zが正しければYは必ず正しい
C. Xが正しければZは必ず正しい
"""
response = ollama.chat(model='deepseekr1-32b-jpn', messages=[
{
'role': 'system',
'content': DEFAULT_SYSTEM_PROMPT,
},
{
'role': 'user',
'content': text,
},
])
print(response['message']['content'])
response = ollama.chat(...)
:モデルを使用して回答を生成します。
DEFAULT_SYSTEM_PROMPT
にシステムプロンプトが入ります。
text
にユーザープロンプトが入ります。
モデルの回答
<think>
まず問題を整理しましょう。X、Y、Zの3人が同じ絵を見ていて、それぞれ異なる発言をしています。彼らは必ずしも真実を話しているとは限りません。ここから、各選択肢(A、B、C)が正しいかどうかを論理的に検証する必要があります。
まず、Xの発言は「絵には虎が描かれている」です。Yは「少なくとも虎か龍が描かれている」と言い、Zは「龍が描かれている」と言っています。
各選択肢について順番に考えてみます。
A. Yが正しければXは必ず正しい。
この場合、Yの発言が真であれば、絵には虎か龍の少なくとも1つがあることになります。ここで、もしYが正しい(即ち絵に虎か龍が存在する)とき、Xが正しいかどうかはどうなるでしょうか? Xは「虎が描かれている」と主張しています。しかし、例えば絵に龍だけがあれば、Yは正しいがXは誤りとなります。したがって、Aの選択肢は成り立たない(反例があるため)と言えます。
B. Zが正しければYは必ず正しい。
Zが正しいということは、絵には龍が描かれているということです。その場合、Yの発言「少なくとも虎か龍がある」を満たすのは明らかです。なぜなら、龍が存在するので条件を満たすからです。したがって、Bは正しいと言えます。
C. Xが正しければZは必ず正しい。
Xが正しいということは、絵に虎が描かれていることになります。しかし、その場合でもZの発言(龍が描かれている)が真かどうかは分かりません。例えば、虎だけが描かれていてもXは正しいがZは誤りです。したがって、Cは成り立ちません。
以上より、正解はBとなります。
</think>
**答え:B. Zが正しければYは必ず正しい**
### 論理的根拠
1. **選択肢Aの検証**
- Yが「少なくとも虎か龍がある」と正しい場合でも、絵に「龍だけ」があればX(「虎がある」)は誤りになります。
- → **反例あり(不成立)**
2. **選択肢Bの検証**
- Zが「龍がある」と正しい場合、Yの条件「少なくとも虎か龍がある」は自動的に満たされます。
- → **必ず成り立つ**
3. **選択肢Cの検証**
- Xが「虎がある」ことが正しい場合でも、絵に「虎だけ」があればZ(「龍がある」)は誤りになります。
- → **反例あり(不成立)**
### 結論
- **Bのみが論理的に必然的**であり、他の選択肢には反例が存在します。
DeepSeek-R1の日本語モデルをChatGPT風に構築するには?

DeepSeek-R1を活用したRAGの構築方法は?

生成AI・LLMのコストでお困りなら
GPUのスペック不足で生成AIの開発が思うように進まないことはありませんか?
そんなときには、高性能なGPUをリーズナブルな価格で使えるGPUクラウドサービスがおすすめです!

GPUSOROBANは、生成AI・LLM向けの高速GPUを業界最安級の料金で使用することができます。
インターネット環境さえあれば、クラウド環境のGPUサーバーをすぐに利用可能です。
大規模な設備投資の必要がなく、煩雑なサーバー管理からも解放されます。