お問い合わせ

技術コラム

GitHub Actionsでラクラク! ChatGPTによる自動原稿チェック

投稿日:2024年12月12日|最終更新日:2025年1月8日

ChatGPT APIで原稿を校正したい。できれば自動で

昨年から世間の注目を集めつづけるChatGPT。 「大規模言語モデルによる生成AIチャットbot」というありきたりな説明はさておき、実際にさわってみると、たまにトンデモ回答もあるものの、なかなか使えるやつであります。 何聞いても、何度聞いても怒らないし。

今回は、そんなChatGPTと、GitHub ActionsというGitHubの機能を使用して、テキスト原稿を自動で校正してもらいます。

まず大前提として、ChatGPTによる校正は、現状、すごく精度が高いわけでもありません
私としても、プロンプトなど試行錯誤しながら、自筆のレポートなど機密上問題にならない場面では毎回、試しに校正をお願いしていますが、「どうでもいいし、間違ってないし、それ」みたいな、重箱の隅をつつく知ったかぶり回答がでて、うんざりすることも少なくありません。 ですが、時々、重要な見落としを指摘してくれるんですよね。
なので、原稿が整ったら、できれば一応ChatGPTにもチェックさせたい。 でも精度が悪いので、無駄解答がつづくとモチベーションが保たず、ついつい忘れがちになる。 今回は、そんな状況を改善するためのプロジェクト「良きタイミングで勝手にChatGPTが原稿チェックしてくれるラクチン環境を手に入れたい!」を紹介します。

コストの話

最初に残念なお知らせです。 GitHub ActionsからChatGPTを使うには、ChatGPTのWeb APIを呼び出す必要があります。 が、そのためには通常のChatGPTの利用プランとは別に、API用にOpenAIに課金する必要があります

でも、お待ちください。 ChatGPTのAPI、mini版(廉価版)ならそんなに高くないです! サービスを一般公開してみんなでAPI呼び放題にすれば恐ろしい金額になる可能性もありますが、自分一人で使っている分にはそれほどでもありません。

Web APIの正確な価格は最新情報( https://openai.com/api/pricing/ )を確認していただきたいのですが、一般的なGPT-4o、コスト重視のGPT-4o miniの価格は2024年12月現在、次のとおりです。

モデル 入出力 価格
gpt-4o 入力 1Mトークンにつき2.50ドル
gpt-4o 出力 1Mトークンにつき10.00ドル
gpt-4o mini 入力 1Mトークンにつき0.15ドル
gpt-4o mini 出力 1Mトークンにつき0.6ドル

通常版とmini版で、かなり値段違います。 もちろん、GPT-4oのほうが賢いのは事実ですが、文章校正くらいなら、その能力には大差ない気がしています。 というわけなので、今回はmini版を使っていくことにしましょう。

トークンとは

ここでトークンとはなんぞや、という問題になります。 簡単にいうとChatGPTがテキストを処理するときの最小単位のことです。

      

ChatGPTに出力してもらったトークンを分解するGPT少年のイラスト。

ChatGPT本人に聞いてみたところ、平均的に「日本語文章のトークン数=文字数×1.5」が目安となる、と言っていましたが、日本語版Wikipediaデータセットで実測された方の結果では、gpt-4o miniが使用する方式で、1文字あたり平均約0.8トークンとなったそうです( https://zenn.dev/microsoft/articles/dcf32f3516f013 )。

10,000文字の原稿(フォーマットにもよるが、A5版で10ページ弱くらい?)を入力対象にして、1,500字くらいの出力を得た場合、文字数×1.5のかなり高めな数値を使用しても

入力価格

10,000文字 × 1.5 = 15,000トークン
15,000トークン ÷ 1,000,000トークン×0.15ドル = 0.00225ドル

出力価格

1,500文字 × 1.5 = 2,250トークン
2,250トークン ÷ 1,000,000トークン×0.6ドル = 0.00135ドル

合計

0.00225ドル + 0.00135ドル = 0.0036ドル約0.54円)※1ドル150円換算

全体200ページ弱の本ならば、1冊全部見てもらっても、1回10.8円。 まあ、多少役立たずな回答があっても、許容できる範囲なのではないでしょうか。

それでは、安心して校正システム構築していくことにしましょう。

用意するもの

このプロジェクトでは次のものが必要になります。

  • GitHubリポジトリ
  • OpenAIアカウントを取得し以下2点用意
    • API利用のためのクレジット支払い(先に入金して、使用のたびに残金が減っていくデポジット方式です)
    • APIシークレットキー(Project単位で管理できるので、先にProject登録してから取得するのがおすすめ)

OpenAI APIを利用するためのアカウント作成方法や、課金、シークレットキー取得手順については「OpenAI API key 課金」などで検索してください。 注意点としては、短期間で仕様が変わるので、Google検索時に「ツール」→「期間を指定」で「1年以内」を選ぶなど、比較的新しい情報を探すとよいかと思われます。

ちなみにデポジットのデフォルトは10ドル。 4o-miniを使用するのであれば、これで当面は問題なさそうです(私は3ヶ月くらい使っても余ってます)。

はじめてのGitHub Actions

では、ここで話をGitHub Actionsに移しましょう。

GitHub Actionsとは、GitHub上で特定のタイミングで何らかの自動処理を行う仕組みです。 リポジトリに「ワークフロー」と呼ばれる処理内容を設定したファイルを置くことで、特定のタイミング(例えばpushやプルリクエスト)に応じた処理を実行できるようになります。

今回の場合は、下図のように動作します。 GitHubにプルリクエストを出すと指定したワークフローが実行され、変更があったテキストの校正をChatGPTに依頼します。 校正結果はGitHub上のプルリクエスト画面に表示されます。

 

なお、プログラム開発であれば、プログラムの動作テストや、コードの書き方が適切かどうかのチェックなどを行うケースが多く、「テストが通らないかぎりmainリポジトリにマージさせない」という運用も少なくないですが、今回は処理内容がChatGPTの校正であり、ポンコツ回答がくることも多いため、ダメ出しされようがなんだろうが、mainリポジトリにマージできるようにしています。

 

ワークフローファイルの配置

そういうわけで、まずは適当なGitHubリポジトリを用意して、GitHubActionsのワークフローファイルを作成します。

ワークフローファイルは置き場所が決まっており、リポジトリのルート/.github/workflows/です。 ここにワークフローの内容をYAMLファイルで配置します。

今回使用したワークフローファイルは下記のとおり。 ubuntu-latestを指定していることからわかるように、GitHub Actionsが毎回、仮想マシンを立てて、指定された内容を処理する仕組みであることがわかります。

  • /.github/workflows/onPullReq_proofread.yml
name: Spell Check and Proofread
on:
  pull_request:
    branches:
      - main

permissions:
  pull-requests: write
  contents: read

jobs:
  check_spelling:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Get changed files # 更新のあったファイルを調べるのに公開Actionを利用
        id: changed-files
        uses: tj-actions/changed-files@v45

      - name: Process each modified file
        id: check_spelling
        run: |
          extensions="*.txt *.md *.re"
          output=""

          files="${{ steps.changed-files.outputs.modified_files }} ${{ steps.changed-files.outputs.added_files }}"

          for file in $files; do
            for ext in $extensions; do
              if [[ "$file" == $ext ]]; then
                echo "Processing $file"
                content=$(cat "$file")

                
                request_data=$(jq -n --arg content "$content" '{
                  model: "gpt-4o-mini",
                  # 以下、ChatGPTへのプロンプト
                  messages: [
                    {role: "system", content: "You are a professional proofreader. Your task is to carefully proofread the text provided by the user. Instead of directly correcting the text, please provide a list of suggested corrections. These suggestions should include details on the following: spelling mistakes, grammatical errors, consistency in style, appropriate use of formal and informal language, and overall readability. Additionally, point out any deviations from standard Japanese writing conventions, such as punctuation and spacing errors. Present each suggestion as a bullet point and in Japanese.\nFurthermore, add the following instructions:\nInclude the line number from the original file being proofread at the beginning of each bullet point.(e.g., ●1:, ●24:,)\nAfter the line number, specify the type of issue being pointed out (e.g., 【誤字】【漢字かなのつかいわけ】)."},
                    {role: "user", content: $content}
                  ],
                  # gpt-4o-miniのmaxトークン数を指定
                  max_tokens: 16384
                }')

                response=$(curl -s -X POST "https://api.openai.com/v1/chat/completions" \
                  -H "Authorization: Bearer ${{ secrets.OPENAI_API_KEY }}" \
                  -H "Content-Type: application/json" \
                  -d "$request_data" | jq -r '.choices[0].message.content // .error.message')

                if [ "$response" == "null" ] || [ -z "$response" ]; then
                  echo "Error: Received null or empty response from the API"
                  exit 1
                fi

                output+="**$file**:\n$response\n\n"
              fi
            done
          done
          # responseでは改行コードが\\nになっているので\nに
          echo "$output" | sed ':a;N;$!ba;s/\\n/\n/g' > output.txt

      # プルリク画面に結果を表示
      - name: Comment on the pull request
        if: steps.changed-files.outputs.modified_files != ''
        uses: marocchino/sticky-pull-request-comment@v2
        with:
          header: Spell Check and Proofreading Results
          path: output.txt

シークレットキーの指定

まず、注目していただきたいのが下記の行です。

                  -H "Authorization: Bearer ${{ secrets.OPENAI_API_KEY }}"

ここで「ChatGPTのAPIシークレットキー(secrets.OPENAI_API_KEY)」を使うことで自分のデポジットから料金を払い情報を取得する仕組みなんですが、シークレットキーを直接ファイルに書き入れるのは絶対やめてください。 ちょっとしたミスや事故によって、簡単に漏洩して悪用される可能性があります。

今回は、後ほど設定するGitHubの環境変数としてシークレットキーを参照します。

ChatGPTへのプロンプト

肝心のChatGPTへのプロンプトがこの部分です。 ChatGPT APIへのリクエストにはroleというパラメータがあり、"system"で全体的な指示を、"user"で個別の質問を渡すことになっています(もう1つasistantというロールもあります)。

今回のように1つの質問に1つの回答を得るだけで終わるケースでは、あまり使い分けに意味がない気もしますが、複数回のやりとりを繰り返す場合に、systemを利用すると返答の一貫性などが保ちやすくなるようです。

                  messages: [
                    {role: "system", content: "You are a professional proofreader. Your task is to carefully proofread the text provided by the user. Instead of directly correcting the text, please provide a list of suggested corrections. These suggestions should include details on the following: spelling mistakes, grammatical errors, consistency in style, appropriate use of formal and informal language, and overall readability. Additionally, point out any deviations from standard Japanese writing conventions, such as punctuation and spacing errors. Present each suggestion as a bullet point and in Japanese.\nFurthermore, add the following instructions:\nInclude the line number from the original file being proofread at the beginning of each bullet point.(e.g., ●1:, ●24:,)\nAfter the line number, specify the type of issue being pointed out (e.g., 【誤字】【漢字かなのつかいわけ】)."},
                    {role: "user", content: $content}
                  ],

{role: "system", content: "以下を書き換えることで、好きなプロンプトに変更できます。 ここでは、結果を箇条書きで報告すること、文法ミス、スタイルの一貫性、スペリングチェック、読みやすさなどをチェックしてくれるようお願いしています(プロンプトは英語にしたほうが精度が良い、という噂があるので英語にしていますが、最近は日本語でもそんなに変わらない気もしています)。
前述のように、校正対象ファイルの中身は{role: "user", content: $content}$contentで渡されます。

チェック対象の絞り込み

tj-actions/changed-files@v45というツールで、何らかの変更があったファイル or 新規に追加されたファイルのみを取り出し、さらにそのなかで拡張子がtxtmdre(Re:View)のものを校正対象としています。

files="${{ steps.changed-files.outputs.modified_files }} ${{ steps.changed-files.outputs.added_files }}"
extensions="*.txt *.md *.re"

プルリクエスト画面への出力

最後に校正結果をGitHub上に出力します。 前のステップでChatGPTのすべての返答をoutput.txtに書き出しておいたので、これをそのまま使います。

marocchino/sticky-pull-request-comment@v2を使うと、指定した内容をもとのプルリクエスト画面のコメントとして書き込めるので、これを利用しています。

      # プルリク画面に結果を表示
      - name: Comment on the pull request
        if: steps.changed-files.outputs.modified_files != ''
        uses: marocchino/sticky-pull-request-comment@v2
        with:
          header: Spell Check and Proofreading Results
          path: output.txt

GitHubActionsへのシークレットキーの登録

前述のように、OpenAIのページで取得したシークレットキーは、GitHub Actionsの環境変数経由でワークフローに渡すため、GitHub Actionsにシークレットキーを登録する必要があります。

具体的には、次の手順となります。

  1. リポジトリトップの右上の[Settings]→左側のメニュー[Security]配下の[Secrets and variables]→[Actions]をクリックして、「Actions secrets and variables」画面を開きます。

     

  1. New repository secret]をクリックして、環境変数名(Name)とシークレットキー(Secret)を入力し、[Add secret]ボタンを押します。

先ほどのワークフローファイル(onPullReq_proofread.yml)では、-H "Authorization: Bearer ${{ secrets.OPENAI_API_KEY }}"でシークレットキーを参照していたので、環境変数名はOPENAI_API_KEYです。

ワークフローを実行する

校正対象サンプルの作成

それではChatGPTによる自動校正を試してみましょう。 リポジトリに適当なテキストを突っ込んでプルリクエストを発行します。

ここでは、日本語文章であればなんでも良いので、次の手順でChatGPTに丸投げしました。

  1. ChatGPTに生成を依頼

    「量子コンピューターについて10,000字で概説してください」

  2. ChatGPTに間違いを入れてもらう

    この文章に、校正チェック用の間違いをいれてください。漢字のミス(同音異義語の間違い。ありがちな変換ミスなど)、誤字脱字(私たちの生活→私たち生活 など)、漢字かなの使い分けの不統一(例えば、たとえば、など)を意図的に全体で30箇所いれてください。

  3. できあがった文章をsample2.mdとして保存

こんな感じになりました。

## 量子コンピュータの世界:原理から未来まで
### 1.はじめに
量子コンピュータは、従来のコンピューター技術とは全く異なる原理に基づく新しい計算装置で。クラシカルコンピュータは0と1のビットで情報を処理するのに対し、量子コンピュータは「量子ビット(qubit)」と呼ばれる単位を用いて計算を行います。量子ビットは、0と1の状態を同時に持つことができる「重ね合わせ」という性質を持つため、膨大な計算を一度に実行する可能性を秘めています。この技術は、素因数分解や複雑なシミュレーション、機械学習などの分野において、従来のコンピューターが到達できない領域での活用が期待されてます。本稿では、量子コンピュータの原理、現在の応用例、そして将来の可能性について詳しく解説します

### 2.量子コンピュータの基礎
量子コンピュータは、量子力学の基本的な原理に基づいています。特に、以下の3つの重要な概念が有りんす。
(以下、略)

プルリクエストの作成とActions

では、Gitで別ブランチをつくり、このファイルをコミットしてmainリポジトリへのプルリクエストを発行してみましょう。

$ git branch testpq
$ git switch testpq
$ git add sample2.md
$ git commit -m '校正対象サンプルの追加'
$ git push origin testpq

GitHubにアクセスします。

適当に入力してプルリクエストを発行します。

最初、何事も起こらないのであれ?と思いますが、

しばらく待つと(10秒くらい)、Actionsが動作している旨表示されます。

さらに待つこと1、2分。 無事にChatGPTによる校正結果が返ってきます。

それなりに誤脱字を拾ってくれています。 ちょっと何言っているのかわからない指摘もありますが。

まとめ

以上で、GitHub Actionsを利用したChatGPT校正が可能になりました。 「入力トークン数に限度があるので、とんでもなく長いテキストでは、テキストを分割する」など改善点はいろいろ考えられますが、とりあえず当初の目標は達成できたと思います。

まだまだ完璧とは言い難いChatGPTによる校正ですが、今後、どんどん精度があがっていくことも考えられます。 ぜひ、みなさまも手元でも試してみてください。

ちなみに、この記事執筆のために10,000字前後の文章を30回程度APIを利用して校正してもらいましたが、私のデポジットは0.04ドルしか減ってませんでした。 以前GPT4で10ドル分を比較的短期間で使い切った経験があるのですが、感覚的にもgpt-4o-mini、本当に安いなと思います。 ぜひAPIも積極的に活用してみてください。

(R&D かつの)