🤖

基本情報技術者試験 科目B対策システムの開発 - Gemini 2.0 Flash × ベクトルDB × React

に公開

はじめに

基本情報技術者試験の科目B(アルゴリズムとプログラミング)対策に特化した学習システムを開発しました。Gemini 2.0 Flash APIがリアルタイムで問題を生成し、ベクトルDBで類似問題を推薦する革新的な学習アプリです。

🔗 デモサイト: https://fe.foreverisland.jp/
🔗 X (Twitter): @kewa8579

システムの特徴

🤖 AIリアルタイム生成

Gemini 2.0 Flash APIが1問ずつリアルタイムで問題を生成します。事前に問題を用意する必要がなく、毎回新鮮な問題に取り組めます。

🔍 ベクトルDB蓄積と類似問題推薦

生成された問題は自動的にベクトルDBに保存され、間違えた問題から類似問題をAIが選択・推薦します。弱点を効率的に克服できます。

✅ 実試験に近い選択肢形式

IPA公式サンプル問題に基づき、実際の試験に近い選択問題(セレクトボックス形式)で出題されます。

📝 即座の詳しい解説

回答後すぐに詳しい解説が表示されるため、理解を深めながら学習を進められます。

💾 ログイン不要

ブラウザのローカルストレージで学習記録を管理するため、アカウント登録や個人情報の入力は一切不要です。

技術スタック

フロントエンド

  • React 18 + TypeScript
  • Vite (ビルドツール)
  • React Router (ルーティング)
  • Chart.js (学習記録の可視化)

バックエンド

  • FastAPI (Python)
  • Gemini 2.0 Flash API (問題生成)
  • PostgreSQL (問題データベース)
  • pgvector (ベクトル検索)

インフラ

  • Docker + Docker Compose
  • Nginx (リバースプロキシ)

システムアーキテクチャ

┌─────────────┐     ┌──────────────┐     ┌────────────────┐
│   Browser   │────▶│   Nginx      │────▶│   Frontend     │
│  (React)    │◀────│ (Reverse     │◀────│   (Vite)       │
└─────────────┘     │  Proxy)      │     └────────────────┘
                    └──────────────┘
                           │
                           ▼
                    ┌──────────────┐     ┌────────────────┐
                    │   Backend    │────▶│   PostgreSQL   │
                    │   (FastAPI)  │◀────│   + pgvector   │
                    └──────────────┘     └────────────────┘
                           │
                           ▼
                    ┌──────────────┐
                    │  Gemini API  │
                    │ 2.0 Flash    │
                    └──────────────┘

主要機能の実装詳細

1. Gemini 2.0 Flash APIによる問題生成

# backend/app/services/question_generator.py
import google.generativeai as genai

async def generate_question():
    model = genai.GenerativeModel("gemini-2.0-flash-exp")
    
    prompt = """
基本情報技術者試験 科目Bのサンプル問題を1問生成してください。
形式: JSON
{
  "question": "問題文(コード含む)",
  "options": ["選択肢1", "選択肢2", "選択肢3", "選択肢4"],
  "correct_answer": 0,
  "explanation": "詳しい解説"
}
"""
    
    response = await model.generate_content_async(prompt)
    question_data = json.loads(response.text)
    
    # ベクトルDB保存用の埋め込み生成
    embedding = await generate_embedding(question_data["question"])
    
    return question_data, embedding

2. pgvectorによる類似問題検索

# backend/app/services/similarity_search.py
from pgvector.sqlalchemy import Vector

async def find_similar_questions(question_embedding, limit=5):
    query = """
        SELECT id, question, explanation
        FROM questions
        ORDER BY embedding <-> %s
        LIMIT %s
    """
    
    results = await db.execute(query, (question_embedding, limit))
    return results.fetchall()

3. Reactフロントエンドの状態管理

// frontend/src/App.tsx
const [currentQuestion, setCurrentQuestion] = useState<Question | null>(null);
const [userAnswers, setUserAnswers] = useState<number[]>([]);
const [results, setResults] = useState<Result[]>([]);

const fetchQuestion = async () => {
  const response = await fetch('/api/questions/generate');
  const data = await response.json();
  setCurrentQuestion(data);
};

const submitAnswer = async (answer: number) => {
  setUserAnswers([...userAnswers, answer]);
  
  if (userAnswers.length >= 4) {
    // 5問完了後、結果を表示
    const resultsData = await submitQuiz(userAnswers);
    setResults(resultsData);
  } else {
    // 次の問題を生成
    await fetchQuestion();
  }
};

4. 学習記録のローカルストレージ管理

// frontend/src/utils/storage.ts
interface StudyRecord {
  date: string;
  correct: number;
  total: number;
  weakTopics: string[];
}

export const saveStudyRecord = (record: StudyRecord) => {
  const records = getStudyRecords();
  records.push(record);
  localStorage.setItem('study_records', JSON.stringify(records));
};

export const getStudyRecords = (): StudyRecord[] => {
  const data = localStorage.getItem('study_records');
  return data ? JSON.parse(data) : [];
};

Docker Composeによるデプロイ

# docker-compose.yml
version: '3.8'

services:
  database:
    image: pgvector/pgvector:pg16
    environment:
      POSTGRES_DB: kihonjoho_db
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

  backend:
    build: ./backend
    environment:
      GEMINI_API_KEY: ${GEMINI_API_KEY}
      DATABASE_URL: postgresql://postgres:${DB_PASSWORD}@database:5432/kihonjoho_db
    depends_on:
      database:
        condition: service_healthy
    ports:
      - "8000:8000"

  frontend:
    build: ./frontend
    ports:
      - "5173:80"
    depends_on:
      - backend

volumes:
  pgdata:

セキュリティとプライバシー

個人情報の非収集

  • ユーザー登録不要
  • ローカルストレージのみで学習記録を管理
  • サーバー側に個人データを保存しない

API Key管理

  • 環境変数でAPI Keyを管理
  • 複数のAPI Keyをカンマ区切りで設定可能(ラウンドロビン負荷分散)
# .env
GEMINI_API_KEY=key1,key2,key3

パフォーマンス最適化

1. 問題生成の高速化

  • Gemini 2.0 Flash(最速モデル)を使用
  • ストリーミングレスポンスで体感速度を向上

2. ベクトル検索の効率化

  • pgvectorのインデックス作成
CREATE INDEX ON questions USING ivfflat (embedding vector_cosine_ops);

3. フロントエンドの最適化

  • Viteによる高速ビルド
  • コード分割とLazy Loading
  • React.memoによる不要な再レンダリング防止

今後の展開

  • 📊 学習分析機能の強化
  • 🎯 難易度別出題モード
  • 📱 モバイルアプリ化
  • 🔊 音声読み上げ機能
  • 🌐 多言語対応

まとめ

Gemini 2.0 Flash APIとベクトルDBを活用することで、従来の固定問題集とは異なる、AIが問題を生成し類似問題を推薦する革新的な学習システムを実現しました。ログイン不要でプライバシーにも配慮した設計となっています。

基本情報技術者試験の科目B対策にぜひご活用ください!


開発者: @kewa8579
デモサイト: https://fe.foreverisland.jp/

Discussion