Open7

【挑戦】Laravel 11 でGeminiAIを利用した日報作成アプリを作ってみた

DaiNakaDaiNaka

はじめに

今回の作ってみるシリーズは、流行りに乗ってAIを活用したアプリを作ることに挑戦してみたいと思います。実は、一つ前の作ってみたシリーズが途中であることはお許しください🙂

参考サイト

Laravel公式サイトに掲載されている2024/2/22のNews記事を参考にしています。
ただ、ほとんどはこのページから遷移できるgoogle-gemini-php/laravelの説明を読んで進めています。
https://laravel-news.com/google-gemini-laravel

アーカイブ

No 記事 デモサイト
1 【挑戦】Laravel 8 でLINEの様なチャットサービスを作ってみた https://chat-app.dev-labo.net/
2 【挑戦】Laravel 8 で簡易的な掲示板を作ってみた https://bbs-app.dev-labo.net/
3 【挑戦】Laravel 8 でEvernoteの様なメモアプリを作ってみる 😢完成に至らず
4 【挑戦】Laravel 9 でポートフォリオを作ってみた https://portfolio.dev-labo.net/
5 【挑戦】Laravel 9 でとてもシンプルなブログシステムを作ってみた https://blog-app.dev-labo.net/
6 【挑戦】Laravel 10 でチームで使えるタスク管理システムを作ってみた https://task-app.dev-labo.net/
7 【挑戦】Zennで書いた記事をLaravel 10で作ったページに連携してみた https://article-app.dev-labo.net/
8 【挑戦】Laravel 11 がリリースされたのでメモアプリを作ってみる ※途中 https://memo-app.dev-labo.net/

開発環境

  • Docker 4.27.1
  • VS Code

利用言語

  • PHP 8.3.3
  • Laravel 11.0.0

公開コード[GitHub]

https://github.com/DaiNaka1207/ai-app

注意事項

ここで説明しているコマンドプロンプトで扱うコマンドですが、エイリアスを設定しておりXAMPPの時と同じようなコマンドで実行できるようにしています。
エラーが吐かれる場合には、phpvendor/laravel/sail/bin/sailに置き換えて実行してみてください。
例:php artisan route:list → vendor/laravel/sail/bin/sail artisan route:list

今回からは、Laravelの初期画面が表示されたところから開始したいと思います。

DaiNakaDaiNaka

機能説明

  • 実行したタスクを入力することができる
  • 入力したタスクを基にして自動で日報が作成される

作っていく手順

  • APIのインストール
  • 日報自動作成処理の作成
  • トップ画面の作成
DaiNakaDaiNaka

APIのインストール

👇こちらのページのREADMEを参考にインストールしていきます。
https://github.com/google-gemini-php/laravel

コマンドプロンプトにて👇こちらのコマンドを実行します。
実行するとプロジェクトにAPIを実行するために必要な設定やファイルが追加されます。
composer require google-gemini-php/laravel
php artisan gemini:install

コマンドを実行し終えると、下記の画面のようなメッセージがでてきたら、Enterキーを押下します。
翻訳すると分かりますが、👍しますか的なことを聞いており、デフォルトで[no]が選択されています。

参考にしているサイトに記載はされていますが、Gemini API を使用するにはキーが必要です。
Google AI Studio でキーを作成してください。

https://makersuite.google.com/app/apikey

取得したAPIキーを.envファイルへ追記していきます。
一番最下部にGEMINI_API_KEY=という項目が追加されているので、そちらへキーをコピーします。

DaiNakaDaiNaka

日報自動作成処理の作成

先にコントローラーの部分を作成していきます。
コマンドプロンプトにて👇こちらのコマンドを実行します。
php artisan make:controller GeminiController

App\Http\Controllers\GeminiController.phpが作成されて、下記の内容が入っています。

App\Http\Controllers\GeminiController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class GeminiController extends Controller
{
    //
}

早速、日報自動作成処理の部分を追記していきます。
参考サイトに記載のUsage(使用法)を参考にします。
ちょっとプロンプトが長くなってしまうため、toGeminiCommand変数に処理内容を書いています。

App\Http\Controllers\GeminiController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Gemini\Laravel\Facades\Gemini;

use Illuminate\Support\Str;

class GeminiController extends Controller
{
    public function index()
    {
        return view('index');
    }
    
    public function entry(Request $request)
    {
        $toGeminiCommand = "# やって欲しいこと\n次のテキストを基に日報を作成してください。\n# 日報には、次の内容を含めてください。\n- 実施したことを箇条書き\n- やったことに対する所感をポジティブな内容で文章にして書いてください。改行も入れてください。\n- やったことに対して次にとるべき行動を文章で書いてください\n```\n" . $request->toGeminiText . "\n```";

        $result = [
            'task' => $request->toGeminiText,
            'content' => Str::markdown(Gemini::geminiPro()->generateContent($toGeminiCommand)->text()),
        ];
        return view('index', compact('result'));
    }
}

GeminiAIに対して、👇このようなプロンプトを送信しています。

そうすると、👇このような結果が返ってきます。

DaiNakaDaiNaka

トップ画面の作成

最後に入力画面と送信した後に出力される画面を作って完了です😄カンタン!
まずは、web.phpにトップ画面と送信後の出力のルーティングを行います。

web.php
 <?php
 use Illuminate\Support\Facades\Route;
+use App\Http\Controllers\GeminiController;

-Route::get('/', function () {
-    return view('welcome');
-});
+Route::get('/', [GeminiController::class, 'index'])->name('index');
+Route::post('/', [GeminiController::class, 'entry'])->name('entry');

次にindex.blade.phpを作成します。

\resources\views\index.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>{{config('app.name')}}</title>

    <style>
        body {background: #bae6fd;}
        h1 {margin: 30px 10px;}
        h2 {margin: 30px 10px;}
        form {display: flex; align-items: flex-end; margin: 0 0 20px 10px}
        textarea {margin-right: 10px; padding: 5px 10px; width: 200px; height: 100px;}
        button {padding: 5px 10px;height: 30px;}
        p {margin: 5px 0 0 10px;}
    </style>
</head>
<body>
    <h1>{{config('app.name')}}</h1>
    
    <form action="{{route('entry')}}" method="post">
        @csrf
        <textarea name="toGeminiText" autofocus>@isset($result['task']){{$result['task']}}@endisset </textarea>
        <button type="submit">send</button>
    </form>
    
    <hr>

    @isset($result)
    <p>{!!$result['content']!!}</p>
    @endisset
</body>
</html>

👇送信前はこんな感じの画面になります

👇実施したことを入力して送信するとこんな感じで出力されます