{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "12c67844-4b4e-4c1f-b7f4-9c2c6f2189c7",
      "metadata": {
        "id": "12c67844-4b4e-4c1f-b7f4-9c2c6f2189c7"
      },
      "source": [
        "## LLMを利用したGoogleフォーム（小テスト）の作成\n",
        "\n",
        "Googleフォーム作成用 GAS (Google Apps Script)コードを生成します。\n",
        "\n",
        "以下のセルのコードを上から順番に実行します。なにかエラーが生じたら、対処し、そのセルを再実行してから、進んでください。\n",
        "\n",
        "注：AIが生成したテスト問題の内容が間違っていないか、最終確認は必ず行ってください。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "583d459d-8cbb-41ed-b6b5-d8566309c1fe",
      "metadata": {
        "id": "583d459d-8cbb-41ed-b6b5-d8566309c1fe"
      },
      "outputs": [],
      "source": [
        "# openai python ライブラリーのインストール\n",
        "! pip install openai"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Google Colab のシークレットを読み込みます\n",
        "# これを実行する前に、左端の鍵アイコンをクリックし、「新しいシークレットを追加」で、\n",
        "# apikey という名前でAPIキーの値を保存しておいてください。\n",
        "from google.colab import userdata\n",
        "apikey = userdata.get('apikey')"
      ],
      "metadata": {
        "id": "L8vi7vAqdOtx"
      },
      "id": "L8vi7vAqdOtx",
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "f3833624-7e3f-4d8d-8131-065a9835c0a2",
      "metadata": {
        "id": "f3833624-7e3f-4d8d-8131-065a9835c0a2"
      },
      "outputs": [],
      "source": [
        "from openai import OpenAI\n",
        "client = OpenAI(\n",
        "    api_key = apikey\n",
        ")\n",
        "\n",
        "model=\"gpt-4o-mini\"\n",
        "#model=\"gpt-4o\"\n",
        "# https://openai.com/pricing"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0adc9793-7217-4ec4-8c61-bde13068941b",
      "metadata": {
        "id": "0adc9793-7217-4ec4-8c61-bde13068941b"
      },
      "source": [
        "### 生成する教材における学習目標を指定する"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "6ba7f222-3712-488e-b5e8-a19c5db1fde8",
      "metadata": {
        "id": "6ba7f222-3712-488e-b5e8-a19c5db1fde8",
        "tags": []
      },
      "outputs": [],
      "source": [
        "data1 = input(\"学習目標は何ですか？（最後にエンターキーを）\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d562daf0-3166-40ab-a564-e6e6b008ea98",
      "metadata": {
        "id": "d562daf0-3166-40ab-a564-e6e6b008ea98"
      },
      "source": [
        "### プレーンテキスト形式で小テスト質問を生成"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "40861cbc-f468-4c26-b55d-8c465a3146e7",
      "metadata": {
        "id": "40861cbc-f468-4c26-b55d-8c465a3146e7",
        "tags": []
      },
      "outputs": [],
      "source": [
        "prompt1 = f'''\n",
        "あなたはオンラインテストの開発者です。\n",
        "「{data1}」という学習目標に到達しているかどうかを測定できる４択問題を８問作成してください。\n",
        "正解の選択肢も示してください。\n",
        "各問題は、下の＜問題フォーマットの例＞のようなフォーマットで書いてください。\n",
        "\n",
        "＜問題フォーマットの例＞\n",
        "1. AI技術の基礎に対する理解とは別に、「教育・リテラシーの原則」で強調されるべきはどれですか。\n",
        "A) ステークホルダーとともに国際コンセンサスを遵守すること\n",
        "B) 格差と分断の防止を、関係者の利益も考慮しつつ行うこと\n",
        "C) 自動化だけでなく安全性も重視した行動を心がけること\n",
        "D) データの有効利用を最大限図ること\n",
        "正解: B) 格差と分断の防止を、関係者の利益も考慮しつつ行うこと\n",
        "解説: 教育・リテラシーの原則では、AIに関する知識と理解の平等な提供やリテラシー向上を通じて、格差と分断の予防が重要視される。\n",
        "'''\n",
        "\n",
        "response = client.chat.completions.create(\n",
        "    model = model,\n",
        "    messages=[\n",
        "        {\"role\": \"user\", \"content\": prompt1},\n",
        "    ],\n",
        ")\n",
        "res1 = response.choices[0].message.content.strip()\n",
        "print(res1)\n",
        "\n",
        "#with open('quiz1.txt', 'w') as f:\n",
        "    #print(res1, file=f)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "40e68b2b-cbee-4d4a-8e93-74ede7c37024",
      "metadata": {
        "id": "40e68b2b-cbee-4d4a-8e93-74ede7c37024"
      },
      "source": [
        "### 小テスト問題のテキストに基づきGASのコードを生成"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "30294bf4-80fe-4f59-9660-ae7c6bddb68a",
      "metadata": {
        "id": "30294bf4-80fe-4f59-9660-ae7c6bddb68a"
      },
      "outputs": [],
      "source": [
        "prompt2 = '''\n",
        "さきほどの問題データを用いて、Googleフォーム上の小テストを作成する、以下のようなGASのコードを出力してください。\n",
        "選択肢番号は削除してください。選択肢文字（a, b, c など）は削除してください。\n",
        "GASコードだけを出力し、それ以外は出力しないでください。\n",
        "\n",
        "function createForm() {\n",
        "  // フォームの作成\n",
        "  var form = FormApp.create('自動作成小テスト');\n",
        "  form.setIsQuiz(true); // クイズ設定を有効にする\n",
        "\n",
        "  // 問題1の追加（記述式）\n",
        "  var item1 = form.addTextItem();\n",
        "  item1.setTitle('日本の首都は？');\n",
        "  // setCorrectAnswerは利用できない?\n",
        "\n",
        "  // 問題2の追加（複数選択式）\n",
        "  var item2 = form.addMultipleChoiceItem();\n",
        "  item2.setTitle('プログラミング言語の種類として、正しいものはどれですか。')\n",
        "      .setPoints(10)\n",
        "      .setRequired(true)\n",
        "      .setChoices([\n",
        "        item2.createChoice('Python', true),\n",
        "        item2.createChoice('JavaScript', true),\n",
        "        item2.createChoice('Excel', false),\n",
        "        item2.createChoice('Word', false)\n",
        "      ]);\n",
        "\n",
        "  const editUrl = form.getEditUrl();\n",
        "  const formUrl = form.getPublishedUrl();\n",
        "  Logger.log('編集URLは ' + editUrl + ' です。設定タブを開き、「成績の発表」を「送信直後」に、また、「点数」を有効にしておくと良いでしょう。');\n",
        "  Logger.log('公開URLは ' + formUrl + ' です。');\n",
        "}\n",
        "'''\n",
        "\n",
        "response = client.chat.completions.create(\n",
        "    model = model,\n",
        "    messages=[\n",
        "        {\"role\": \"user\", \"content\": prompt1},\n",
        "        {\"role\": \"assistant\", \"content\": res1},\n",
        "        {\"role\": \"user\", \"content\": prompt2},\n",
        "    ],\n",
        ")\n",
        "res2 = response.choices[0].message.content.strip()\n",
        "\n",
        "gas_file = 'gform1.gs'\n",
        "res2 = res2.replace(\"```javascript\", '').replace(\"```\", '')\n",
        "with open(gas_file, 'w') as f:\n",
        "    print(res2, file=f)\n",
        "\n",
        "print(\"Googleフォームを自動作成するGASコードが生成されました。\")\n",
        "print(f\"左端のフォルダアイコンをクリックし、生成された {gas_file} というファイルを見つけて開いてください。\")\n",
        "print(\"その内容をコピーし、別途開いた Apps Script の画面で新しいファイルに貼り付けて実行してください。\")"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "display_name": "Python 3 (ipykernel)",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.9.13"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}