PHPで Geminiを使ってテキストの要約を行う

(1/1)
Gemini は、2023年(令和5年)12月に Googleが発表した生成AIモデルだ。テキスト生成、翻訳、要約などを無料で利用することができる。今回は、PHPで Gemini API を使い、テキストを任意の長さに要約するプログラムを作ってみることにする。

目次

サンプル・プログラムの実行例

PHPで Geminiを使ってテキストの要約を行う

サンプル・プログラム

圧縮ファイルの内容
summaryGemini.phpサンプル・プログラム本体
pahooInputData.phpデータ入力に関わる関数群。
使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。
summaryGemini.php 更新履歴
バージョン 更新日 内容
1.0.0 2025/01/02 初版
pahooInputData.php 更新履歴
バージョン 更新日 内容
1.8.0 2024/11/12 validRegexPattern() 追加
1.7.0 2024/10/09 validURL() validEmail() 追加
1.6.0 2024/10/07 isButton() -- buttonタグに対応
1.5.0 2024/01/28 exitIfExceedVersion() 追加
1.4.2 2024/01/28 exitIfLessVersion() メッセージ修正

準備:各種初期値

summaryGemini.php

 158: class pahooGoogleGeminiAPI {
 159:     var $webapi;        //直前に呼び出したWebAPI URL
 160:     var $errmsg;        //エラーメッセージ
 161: 
 162:     // Gemini APIキー
 163:     // https://aistudio.google.com/app/apikey にて登録のこと.
 164:     var $GEMINI_API_KEY = '***********************************';

Gemini API」を利用するには、事前に APIキー を入手する必要がある。「Gemini - 各種クラウド連携サービス(WebAPI)の登録方法」を参考に、APIキー が入手してほしい。取得した APIキー は、$GEMINI_API_KEY に格納する。

summaryGemini.php

  51: // 初期値(START) ============================================================
  52: // 表示幅(ピクセル)
  53: define('WIDTH', 600);
  54: 
  55: // Spinner - jQuery UI を使用するかどうか
  56: define('USESPINNER', TRUE);
  57: 
  58: // 要約オプション
  59: $Options = array('ですます調', 'である調');
  60: 
  61: // 入力テキスト(初期値)
  62: define('DEF_SOUR', "Gemini は、2023年(令和5年)12月に Googleが発表した生成AIモデルだ。テキスト生成、翻訳、要約などを無料で利用することができる。今回は、PHPで Gemini APIを使い、テキストを任意の長さに要約するプログラムを作ってみることにする。");
  63: 
  64: // 要約文字数(初期値)
  65: define('DEF_SIZE', 50);
  66: 
  67: // 要約文字数(最大値)
  68: define('MAX_SIZE', 999);
  69: 
  70: // 初期値(END) ==============================================================

その他の初期値については、「変更不可」の記載がないかぎり、自由に変更してかまわない。

入力値のバリデーションやPHPのバージョンチェックに外部プログラム "pahooInputData.php" を利用している。include_path が通ったディレクトリに配置すること。

Gemini API

Gemini API」は、要求データをJSON形式でPOSTで渡し、応答データをJSONで受け取るクラウドAPIである。
URL
URL
https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=(APIキー)
要求データ構造(json) contents parts text プロンプト(テキスト;UTF-8)
応答データ構造(json) candidates content parts text 応答文(テキスト;UTF-8)

解説:Gemini APIにリクエストする

summaryGemini.php

 211: /**
 212:  * Gemini APIにリクエストする
 213:  * @param   string $text  プロンプト(テキスト;UTF-8)
 214:  * @return  string 応答テキスト/FALSE:失敗
 215: */
 216: function geminiRequest($text) {
 217:     $this->webapi = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=' . $this->GEMINI_API_KEY;
 218:     $headers = array(
 219:         'Content-Type: application/json',
 220:     );
 221:     $payload = array(
 222:         'contents' => array(
 223:             'parts' => array(
 224:                 'text' => $text
 225:             )
 226:         )
 227:     );
 228:     $ret = FALSE;
 229: 
 230:     $ch = curl_init();
 231:     curl_setopt($ch, CURLOPT_URL, $this->webapi);
 232:     curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
 233:     curl_setopt($ch, CURLOPT_POST, TRUE);
 234:     curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
 235:     curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
 236:     curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
 237:     curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
 238:     curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
 239:     curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
 240: 
 241:     $data = curl_exec($ch);
 242:     curl_close($ch);
 243: //  var_dump($data);
 244: 
 245:     //エラー処理
 246:     if ($data == FALSE) {
 247:         $this->errmsg = 'Gemini APIにアクセスできません';
 248:         $ret = FALSE;
 249:     } else {
 250:         $arr = json_decode($data, TRUE);
 251:         if ($arr == FALSE) {
 252:             $this->errmsg = 'Gemini APIの応答が不正です';
 253:             $ret = FALSE;
 254:         } else if (isset($arr['error'])) {
 255:             $this->errmsg = $arr['error']['message'];
 256:         //正常応答
 257:         } else if (isset($arr['candidates'][0]['content']['parts'][0]['text'])) {
 258:             $ret = (string)$arr['candidates'][0]['content']['parts'][0]['text'];
 259:         } else {
 260:             $this->errmsg = 'Gemini APIの応答が不正です';
 261:             $ret = FALSE;
 262:         }
 263:     }
 264: 
 265:     return $ret;
 266: }

Gemini API へ要求データを送り、応答データを受け取る処理は、cURL関数を使ってユーザー定義メソッド geminiRequest に実装した。

なお、Gemini API を利用する処理は、ユーザー定義クラス pahooGoogleGeminiAPI として分離してある。

解説:テキスト要約

summaryGemini.php

 383: // メイン・プログラム =======================================================
 384: // Gemini APIオブジェクトを用意する.
 385: $pgg = new pahooGoogleGeminiAPI();
 386: 
 387: // パラメータを取得する.
 388: $summary = $errmsg = '';
 389: $maxSize = MAX_SIZE;
 390: $sour    = getValidString('sour', $errmsg, $def=DEF_SOUR, 1, 199);
 391: if ($errmsg == '') {
 392:     $maxSize = mb_strlen($sour);
 393: }
 394: $size = getValidNumber('size', $errmsg, DEF_SIZE, TRUE, (int)($maxSize / 10+ 1, $maxSize);
 395: $opt = getValidNumber('opt', $errmsg, 0, TRUE, 0, 1);
 396: 
 397: // リセット
 398: if (isButton('reset')) {
 399:     $sour = DEF_SOUR;
 400:     $summary = $errmsg = '';
 401: }
 402: 
 403: // Gemini API を利用してテキストを要約する.
 404: if (($errmsg == ''&& isButton('exec'&& ($sour !'')) {
 405:     foreach ($Options as $val=>$label) {
 406:         if ($val == $opt)   break;
 407:     }
 408:     $sentence = '次の文書を、' . $label . 'で、' . $size . '文字以内で要約してください。' . "\n\n" . $sour;
 409:     $summary = $pgg->geminiRequest($sentence);
 410:     $summary = trim($summary);
 411: }
 412: 
 413: // 表示HTMLを作成する.
 414: $HtmlBody = makeCommonBody($sour, $summary, $size, $opt, $errmsg, $pgg);
 415: 
 416: // 画面に表示する.
 417: echo $HtmlHeader;
 418: echo $HtmlBody;
 419: echo $HtmlFooter;
 420: 
 421: // オブジェクトを解放する.
 422: $pgg = NULL;

メイン・プログラムは、パラメータの取得やユーザー定義クラス pahooGoogleGeminiAPI のインスタンス化、そして、前述のユーザー定義メソッド geminiRequest を呼び出してテキストの要約を行う。

元のテキスト(要約したいテキスト)を Gemini APIに渡す直前に、「次の文書を、[である調 or ですます調] で、$size 文字以内で要約してください。」という1文を冒頭に付け加えることで、Gemini に要約することを指示する。[である調 or ですます調] と文字数 $size は、テキスト入力時に選択できるようにしてる。文字数指定に利用している jQuery UI の Spinner については、「解説:Spinner - jQuery UI - PHPで素数かどうか判定」をご覧いただきたい。

参考サイト

(この項おわり)
header