どうも!ゲーマーなら一度は「自分専用のAIアシスタントが欲しい」と思ったことありませんか?ゲーム攻略を手伝ってくれたり、チーム戦略を考えてくれたり、そんな夢のようなチャットボットが実は簡単に作れるんです!
この記事では、ChatGPT API(OpenAI API)を使った自作チャットボットの作り方を、プログラミング初心者でも理解できるよう詳しく解説します。
ChatGPT API基礎知識
GPT-4o API料金体系(2026年1月現在)
API料金は「入力トークン」と「出力トークン」の従量課金が基本です。さらに、同じプロンプト(または共通の前半部分)を繰り返す用途では、キャッシュ入力(Cached input)が適用できるモデルもあり、コストを抑えられます。
| モデル | 入力料金 | 出力料金 | 特徴 |
|---|---|---|---|
| gpt-4o | $2.50/1M tokens | $10.00/1M tokens | 高性能の主力モデル。品質重視の本番向け |
| gpt-4o-mini | $0.15/1M tokens | $0.60/1M tokens | 低コスト・高速。要約/定型QA/軽量ボットに最適 |
| gpt-4.1-mini | $0.40/1M tokens | $1.60/1M tokens | コスパと品質のバランス型。迷ったら候補に |
トークン数の目安(注意:文章により変動)
- 英語は「1トークン ≒ 4文字」程度が目安(文章によって増減)
- 日本語は英語よりトークンが増えやすい傾向があるため、実データでの確認が確実
- 正確に見積もるには、OpenAIのトークン解説やトークナイザー(tiktoken等)で事前計測する

API利用開始手順
1. OpenAIアカウント作成
1. https://platform.openai.com/ にアクセス
2. 「Sign up」でアカウント作成 → ログイン
3. ダッシュボードで Project(プロジェクト)を作成(未作成なら作成)
2. APIキーの取得
APIキーは絶対に公開しないでください(ブラウザ側に埋め込むのもNG)。サーバー側の環境変数で安全に扱います。
1. ダッシュボード → API keys(Project配下のキー管理)
2. 「Create new secret key」クリック
3. キー名を入力(例:ChatBot_Project)
4. APIキーをコピーして安全に保管(再表示できない場合があるので注意)
3. 課金設定
請求情報を登録し、Project単位の上限や制限(利用枠・レート制限・コスト上限)を設定しておくと安心です。
1. Settings → Billing(支払い情報の登録)
2. Settings → Limits(使用量・レート・コスト上限の確認/設定)
3. 用途に応じて上限を設定(例:開発中は低め、本番は監視前提で調整)
関連YouTube動画(日本語)
Python Flask チャットボット開発
開発環境構築
1. 必要なライブラリインストール
# 仮想環境作成
python -m venv chatbot_env
source chatbot_env/bin/activate # Linux/Mac
# chatbot_env\Scripts\activate # Windows
# 必要ライブラリインストール
pip install flask openai python-dotenv requests
2. プロジェクト構造
chatbot_project/
├── app.py
├── .env
├── templates/
│ └── index.html
├── static/
│ ├── style.css
│ └── script.js
└── requirements.txt
基本チャットボットの実装
1. 環境設定(.env)
APIキーは環境変数で管理し、リポジトリには絶対にコミットしないでください(.gitignore推奨)。
OPENAI_API_KEY=sk-your-api-key-here
FLASK_ENV=development
FLASK_DEBUG=True
2. メインアプリケーション(app.py)
2026年1月時点では、従来のChat Completionsも利用できますが、新規開発では最新機能を取り込みやすいResponses APIが推奨されています。以下はResponses API前提の実装例です。
from flask import Flask, request, jsonify, render_template
from dotenv import load_dotenv
from openai import OpenAI
# 環境変数読み込み(OPENAI_API_KEY を .env から読み込む)
load_dotenv()
app = Flask(__name__)
# OpenAIクライアント(環境変数 OPENAI_API_KEY を参照)
client = OpenAI()
# チャット履歴保存(本番はDB/Redis推奨)
chat_history = []
@app.route('/')
def index():
return render_template('index.html')
@app.route('/chat', methods=['POST'])
def chat():
try:
user_message = request.json.get('message', '').strip()
if not user_message:
return jsonify({'error': 'メッセージが空です'}), 400
# システム(instructions): ボットの性格・方針
instructions = "あなたはゲーマー向けのAIアシスタントです。ゲームに関する質問に詳しく、フレンドリーに答えてください。"
# 履歴に追加
chat_history.append({"role": "user", "content": user_message})
# 直近10件を送信(必要に応じて調整)
recent = chat_history[-10:]
# Responses API(input は role/content 形式の配列を渡せます)
response = client.responses.create(
model="gpt-4o-mini", # 品質重視なら "gpt-4o" に変更
instructions=instructions,
input=recent,
max_output_tokens=500,
temperature=0.7,
)
assistant_message = response.output_text
# 履歴に追加
chat_history.append({"role": "assistant", "content": assistant_message})
# 使用量(存在しない場合もあるので安全に取り出す)
usage = {}
if getattr(response, "usage", None):
usage = {
"input_tokens": getattr(response.usage, "input_tokens", None),
"output_tokens": getattr(response.usage, "output_tokens", None),
"total_tokens": getattr(response.usage, "total_tokens", None),
}
return jsonify({
"response": assistant_message,
"usage": usage
})
except Exception as e:
return jsonify({'error': str(e)}), 500
@app.route('/clear', methods=['POST'])
def clear_history():
global chat_history
chat_history = []
return jsonify({'message': 'チャット履歴をクリアしました'})
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5000)
3. HTMLテンプレート(templates/index.html)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ゲーマー向けAIチャットボット</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<div class="container">
<header>
<h1>ゲーマー向けAIアシスタント</h1>
</header>
<div class="chat-container">
<div id="chatMessages" class="chat-messages">
<div class="message bot-message">
<div class="message-content">
こんにちは!ゲームに関する質問なら何でも聞いてください!
</div>
</div>
</div>
<div class="input-container">
<input type="text" id="messageInput" placeholder="メッセージを入力..." />
<button id="sendButton">送信</button>
<button id="clearButton">履歴クリア</button>
</div>
</div>
<div class="usage-info">
<p>使用量: <span id="tokensUsed">0</span> tokens</p>
</div>
</div>
<script src="{{ url_for('static', filename='script.js') }}"></script>
</body>
</html>
4. スタイリング(static/style.css)
このCSSはFlaskアプリ側の見た目を整えるためのものです(WordPress本文の装飾ではありません)。不要なら削除しても動作します。
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
border-radius: 15px;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
overflow: hidden;
}
header {
background: linear-gradient(45deg, #FF6B6B, #4ECDC4);
color: white;
padding: 20px;
text-align: center;
}
.chat-container {
height: 500px;
display: flex;
flex-direction: column;
}
.chat-messages {
flex: 1;
padding: 20px;
overflow-y: auto;
background: #f8f9fa;
}
.message {
margin-bottom: 15px;
display: flex;
align-items: flex-start;
}
.user-message {
justify-content: flex-end;
}
.bot-message {
justify-content: flex-start;
}
.message-content {
max-width: 70%;
padding: 12px 16px;
border-radius: 18px;
word-wrap: break-word;
}
.user-message .message-content {
background: #007bff;
color: white;
}
.bot-message .message-content {
background: white;
color: #333;
border: 1px solid #e1e8ed;
}
.input-container {
display: flex;
padding: 20px;
background: white;
border-top: 1px solid #eee;
}
#messageInput {
flex: 1;
padding: 12px;
border: 1px solid #ddd;
border-radius: 25px;
margin-right: 10px;
outline: none;
}
button {
padding: 12px 20px;
border: none;
border-radius: 25px;
background: #007bff;
color: white;
cursor: pointer;
margin-left: 5px;
}
button:hover {
background: #0056b3;
}
#clearButton {
background: #dc3545;
}
#clearButton:hover {
background: #c82333;
}
.usage-info {
padding: 10px 20px;
background: #f8f9fa;
text-align: center;
font-size: 14px;
color: #666;
}
.loading {
opacity: 0.7;
}
5. JavaScript(static/script.js)
class ChatBot {
constructor() {
this.messageInput = document.getElementById('messageInput');
this.sendButton = document.getElementById('sendButton');
this.clearButton = document.getElementById('clearButton');
this.chatMessages = document.getElementById('chatMessages');
this.tokensUsed = document.getElementById('tokensUsed');
this.totalTokens = 0;
this.isLoading = false;
this.initEventListeners();
}
initEventListeners() {
this.sendButton.addEventListener('click', () => this.sendMessage());
this.clearButton.addEventListener('click', () => this.clearHistory());
this.messageInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
this.sendMessage();
}
});
}
async sendMessage() {
const message = this.messageInput.value.trim();
if (!message || this.isLoading) return;
this.isLoading = true;
this.sendButton.disabled = true;
this.sendButton.textContent = '送信中...';
// ユーザーメッセージを表示
this.addMessage(message, 'user');
this.messageInput.value = '';
try {
const response = await fetch('/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ message: message })
});
const data = await response.json();
if (response.ok) {
this.addMessage(data.response, 'bot');
this.updateTokenUsage(data.usage);
} else {
this.addMessage(`エラー: ${data.error}`, 'error');
}
} catch (error) {
this.addMessage(`通信エラー: ${error.message}`, 'error');
} finally {
this.isLoading = false;
this.sendButton.disabled = false;
this.sendButton.textContent = '送信';
}
}
addMessage(content, type) {
const messageDiv = document.createElement('div');
messageDiv.className = `message ${type}-message`;
const contentDiv = document.createElement('div');
contentDiv.className = 'message-content';
contentDiv.textContent = content;
messageDiv.appendChild(contentDiv);
this.chatMessages.appendChild(messageDiv);
// 最新メッセージまでスクロール
this.chatMessages.scrollTop = this.chatMessages.scrollHeight;
}
updateTokenUsage(usage) {
if (!usage || usage.total_tokens == null) return;
this.totalTokens += usage.total_tokens;
this.tokensUsed.textContent = this.totalTokens.toLocaleString();
}
async clearHistory() {
try {
const response = await fetch('/clear', { method: 'POST' });
if (response.ok) {
this.chatMessages.innerHTML = `
<div class="message bot-message">
<div class="message-content">
こんにちは!ゲームに関する質問なら何でも聞いてください!
</div>
</div>
`;
this.totalTokens = 0;
this.tokensUsed.textContent = '0';
}
} catch (error) {
console.error('履歴クリアエラー:', error);
}
}
}
document.addEventListener('DOMContentLoaded', () => {
new ChatBot();
});
VPS選択とデプロイ方法
推奨VPSスペック
| 用途 | CPU | メモリ | ストレージ | 月額料金目安 |
|---|---|---|---|---|
| 開発・テスト | 1-2vCPU | 1-2GB | 20GB | 500-1,000円 |
| 本番運用 | 2-4vCPU | 4-8GB | 50GB | 1,000-3,000円 |
| 大規模運用 | 4-8vCPU | 8-16GB | 100GB | 3,000-10,000円 |
デプロイ手順(Ubuntu 22.04)
Ubuntu 22.04でも手順は問題なく動きます。新規構築ならUbuntu 24.04 LTSでも基本は同様です(パッケージ名や設定場所は環境で差が出る場合があります)。
1. サーバー初期設定
# システムアップデート
sudo apt update && sudo apt upgrade -y
# 必要パッケージインストール
sudo apt install python3 python3-pip python3-venv nginx -y
# ファイアウォール設定
sudo ufw allow 22
sudo ufw allow 80
sudo ufw allow 443
sudo ufw enable
2. アプリケーションデプロイ
# プロジェクトディレクトリ作成
sudo mkdir /var/www/chatbot
sudo chown $USER:$USER /var/www/chatbot
# ソースコード配置
cd /var/www/chatbot
git clone https://github.com/your-username/chatbot-project.git .
# 仮想環境構築
python3 -m venv venv
source venv/bin/activate
# 依存関係インストール
pip install -r requirements.txt
3. Systemdサービス設定
# サービスファイル作成
sudo nano /etc/systemd/system/chatbot.service
[Unit]
Description=ChatBot Flask App
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/chatbot
Environment="PATH=/var/www/chatbot/venv/bin"
ExecStart=/var/www/chatbot/venv/bin/python app.py
Restart=always
[Install]
WantedBy=multi-user.target
# サービス有効化
sudo systemctl daemon-reload
sudo systemctl enable chatbot
sudo systemctl start chatbot
4. Nginx設定
sudo nano /etc/nginx/sites-available/chatbot
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# 設定有効化
sudo ln -s /etc/nginx/sites-available/chatbot /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
高度な機能実装
データベース連携
import sqlite3
class ChatDatabase:
def __init__(self, db_path='chat.db'):
self.db_path = db_path
self.init_db()
def init_db(self):
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS conversations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT,
message TEXT,
response TEXT,
tokens_used INTEGER,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
conn.commit()
conn.close()
def save_conversation(self, user_id, message, response, tokens_used):
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute('''
INSERT INTO conversations (user_id, message, response, tokens_used)
VALUES (?, ?, ?, ?)
''', (user_id, message, response, tokens_used))
conn.commit()
conn.close()
ユーザー認証
from functools import wraps
import jwt
def token_required(f):
@wraps(f)
def decorated(*args, **kwargs):
token = request.headers.get('Authorization')
if not token:
return jsonify({'message': '認証が必要です'}), 401
try:
data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=['HS256'])
current_user = data['user_id']
except:
return jsonify({'message': '無効なトークンです'}), 401
return f(current_user, *args, **kwargs)
return decorated
@app.route('/protected-chat', methods=['POST'])
@token_required
def protected_chat(current_user):
pass
レート制限
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(
app,
key_func=get_remote_address,
default_limits=["200 per day", "50 per hour"]
)
@app.route('/chat', methods=['POST'])
@limiter.limit("10 per minute")
def chat():
pass
API料金最適化テクニック
トークン削減戦略
def optimize_history(chat_history, client):
# 履歴が長い場合は要約して圧縮(要約は安価なモデルで)
if len(chat_history) > 20:
summary_prompt = "以下の会話を簡潔に要約してください:\n" + \
"\n".join([f"{msg['role']}: {msg['content']}" for msg in chat_history[:10]])
summary = client.responses.create(
model="gpt-4o-mini",
input=[{"role": "user", "content": summary_prompt}],
max_output_tokens=200,
temperature=0.2,
).output_text
optimized = [{"role": "system", "content": f"過去の会話要約: {summary}"}] + chat_history[-10:]
return optimized
return chat_history
モデル使い分け
def choose_model(message_type):
# 例:簡単な処理は低コスト、高度な分析は高性能モデル
if "翻訳" in message_type or "要約" in message_type:
return "gpt-4o-mini"
elif "分析" in message_type or "戦略" in message_type:
return "gpt-4o"
else:
return "gpt-4o-mini"
キャッシュ機能
import hashlib
class ResponseCache:
def __init__(self):
self.cache = {}
def get_cache_key(self, messages):
content = str(messages)
return hashlib.md5(content.encode()).hexdigest()
def get(self, messages):
return self.cache.get(self.get_cache_key(messages))
def set(self, messages, response_text):
self.cache[self.get_cache_key(messages)] = response_text
cache = ResponseCache()
def get_ai_response(client, model, instructions, messages):
cached = cache.get(messages)
if cached:
return cached
resp = client.responses.create(
model=model,
instructions=instructions,
input=messages
)
text = resp.output_text
cache.set(messages, text)
return text
セキュリティ対策
入力サニタイゼーション
import re
from html import escape
def sanitize_input(user_input):
sanitized = escape(user_input)
forbidden_patterns = [
r'<script.*?>.*?</script>',
r'javascript:',
r'on\w+\s*=',
]
for pattern in forbidden_patterns:
sanitized = re.sub(pattern, '', sanitized, flags=re.IGNORECASE)
return sanitized[:1000]
環境変数管理
import os
from dotenv import load_dotenv
load_dotenv()
class Config:
OPENAI_API_KEY = os.environ.get('OPENAI_API_KEY')
SECRET_KEY = os.environ.get('SECRET_KEY') or 'dev-secret-key'
DATABASE_URL = os.environ.get('DATABASE_URL') or 'sqlite:///chat.db'
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Lax'
ログ管理
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('chatbot.log'),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
おすすめVPS・サーバー(ChatGPT API用)
ChatGPTボットの安定運用には、信頼性の高いサーバーが必要です。用途別のおすすめをご紹介します。
開発・プロトタイプ:ConoHa VPS
特徴
- 時間単位課金で開発コスト最適化
- SSD標準でレスポンス高速
- 簡単操作のコントロールパネル
- 月額296円~
ChatGPTボット向け仕様
- CPU: 1-4vCPU
- メモリ: 1-8GB
- SSD: 100GB
- 料金: 296円/月~
本番運用:エックスサーバー VPS
特徴
- 国内最大級の安定性
- 24時間365日サポート
- 自動バックアップ標準
- 月額830円~
ChatGPTボット向け仕様
- CPU: 2-8vCPU
- メモリ: 2-32GB
- SSD: 50-100GB
- 料金: 830円/月~
コスパ重視:KAGOYA CLOUD VPS
特徴
- 業界最安級の料金設定
- 柔軟なスペック変更
- 無料お試し期間
- 月額550円~
ChatGPTボット向け仕様
- CPU: 1-16vCPU
- メモリ: 1GB-64GB
- SSD: 25GB-800GB
- 料金: 550円/月~
まとめ
ChatGPT APIを使った自作チャットボットの開発から運用まで、詳しく解説しました。
重要ポイント
- API料金最適化でコストを大幅削減可能
- Flask + Pythonで比較的簡単に実装
- 適切なVPS選択で安定運用
- セキュリティ対策は必須
ゲーマーの皆さんなら、新しいゲームを覚えるときの集中力で、きっとプログラミングも楽しく習得できるはず。まずは開発環境から始めて、段階的にスケールアップしていきましょう!

