見出し画像

GoogleChatでGoogleのLLM(PaLM2)が動くように作ってみた~VertexAI APIを利用~

 ChatGPTが一気に広まり、生成系AIの話題がニュースにならない日がありませんね。私も生成系AIの凄さに魅了され、ChatGPTやそのプラグインを使ったり、TalkToGPTで英会話の練習をしたり、GPTのAPIを使って開発したりしていましたが、GoogleのLLMってどうなんだろう、、と周囲でちょっと話題にあがったので、GoogleのPaLM2をGoogleChatで動かせるように作ってみたくなり、超素人開発をしてみました。

 以下は、GCP初めて触る&Pythonも簡単なものしか書いたことのない素人の私が、上記開発の為にお盆休みの数日で取り組んだことを順に記載した、超素人備忘録です。また、自分でとりあえず動くものを作りたい、ということで作ったもので、セキュリティ・精度・正確性は考慮しておりませんのでご容赦ください。

 尚、コーディングやエラー解決、Pythonの構文やテクニカルドキュメントの理解に当たっては、ChatGPTに全面的にサポート頂きました(笑)


1.全体の流れ

 GoogleChatを使った開発を行うにはGoogleWorkSpace(GWS)のアカウントが必要で、GWSアカウント取得には、ドメイン保有が必要になる。
また、GoogleLLMのPaLM2を動かす方法の一つにGoogleCloudPlatform(GCP)のCluod Functionsを利用する方法がある。
 そこで事前の環境準備として、①ドメイン取得②GWS無料トライアル契約と設定③GCPの無料トライアル契約と設定を行ったうえ、プログラム開発として①CloudFunctionsでのGoogleChatAPIの使い方の練習 した後、②VertexAI APIを利用 してGoogleChat内でPaLM2を利用できるようにした。

2.事前準備

①ドメインの取得

 格安・無料でドメインが取得できる「お名前.com」に会員登録して、無料の「.com」ドメイン(+付属でもらえる「.site」ドメイン)を契約。
 尚、後述②のGWSのでドメイン関連のDNS設定が必要となるが、これは、「お名前.com」の中(ネームサーバーの設定⇒DNS設定/転送設定)で実施。(以下ご参考)

②GoogleWorkSpace(GWS)の無料トライアル契約と設定

 GWSは14日間の無料トライアルがあるので、トライアル契約を実施。

Admin画面でチュートリアルに従い

  • 各種ドメインの設定(これは①のDNS設定画面で基本行い、それによりGWSでドメインが確認・承認される)

  • ユーザーの追加(当該ドメインのメールアドレス作成、10個まで可能)

  • G-Mailアドレスの有効化

を実施。①のお名前.comでのDNS設定が結構複雑だった。そして、最後のG-Mailのアドレス有効化で何度も失敗、セカンダリードメインでもうまくいかず、GoogleWorkSpaceのヘルプに問い合わせたが、実際にはうまくいっているのでそのままで問題なしとのこと。それならそのままでいっか、ということで次に進む。

③GoogleCloudPlatform(GCP)の無料トライアル契約と設定

GCPも以下無料トライアルと無料枠があるので、これを利用。尚、契約は上記②で取得したドメインのメールアドレスで実施。

3.プログラム開発

①Cloud FunctionsでのGoogleChatAPIの使い方の練習

 以下のドキュメントに従って、Chatアプリの作り方を練習。

  • 「Prerequisites」のところは、上記2の事前準備の通り。

  • 「Cloud 関数を作成してデプロイする」のところは、最初Node.jsで行っていたが(タブに分かれているのに気づかず)うまくいかず、Pythonに変更して実施(HTTPで、未認証の呼出を許可とか、セキュリティ的には甘いのかな、、、と思いつつそのまま実施)。尚、ここに記載がなかったが、7の「main.py」以外に、gitHubサンプル通り「requirement.txt」の修正も必要(同僚に教えてもらった)。

  • 「Google Chat にアプリを公開する」のところは、手順5の「管理」や手順6の「設定」というのはなかったが、「構成」タブにある内容だったでそのまま進める。手順6のfのメールアドレスには、②で作成したドメイン内の管理メールアドレスを追加。

  • これで、この「Quickstart App」は完成。GoogleChatの「チャット」や「スペース」でアプリを検索とすると、このアプリが見つかるのでそれを組み込むと、ちゃんとその中で応答が返ってきた。

②VertexAI APIの利用

 次に、VertexAIのPaLM APIを用いてPaLM2をGoogleChatで利用できるようにする。以下がVertex AI APIのクイックスタートのサイト。

 気持ち的には、上記①のGoogleChatで応答するサンプルコードと、上記クイックスタートのTry chat promptsのシェルスクリプトコードをあわせた感じのコードをPythonで書けばいいはず。
 そこで、以下のステップで試行錯誤しながらプログラムを完成させた。

  • まずは上記をマージしたPythonコードの作成をそのままChatGPTにお願い。⇒2つのコードをそのままコピーしてお願いしただけにもかかわらず、さすがGPT、大体それっぽいコードを返してくれた。

  • 上記マージコードにPROJECT_IDとACCESS_TOKENの記述があったが、PROJECT_IDはGCPの画面の中ですぐに見つけられたので、自分のPROJECT_ID変更。

  • 次にACCESS_TOKEN。こちらは、どう取得していいかわからないので、ChatGPTに聞いてみると、1つの方法として「IAMと管理」 > 「サービスアカウント」からサービスアカウントのJSONキーファイルを取得し、それを使ってACCESS_TOKENを取得するプログラムを書いてくれたので、そのプログラムを実行して一旦はACCESS_TOKEN取得。

  • だが、ACCESS_TOKENは有効期限が過ぎると変わってしまい、この方法では実用できない。それを回避する方法をまたGPTに聞いたところ、ランタイム環境変数を作成しそこにJSONキーファイルの中身をセットする方法(環境変数はGOOGLE_APPLICATION_CREDENTIALSとした)、セットした環境変数を利用してTOKENを取得する方法を教えてくれたので、その方法に変更し、必要なモジュール(os、google.oauth2、json)をインポート。

  • また、トリガーURLをクリックしてもアクセス拒否になってしまっていたので、権限を上記①と同じになるようにAllUserを追加(セキュリティ的な懸念はあるも)

  • その後、デプロイ・GoogleChatでトライ&エラー試行を繰り返す中で、ログエクスプローラーの見方、Curlコマンドでのコンソール実行など、エラーを突き止める方法もGPTに教えてもらいつつ、都度出るエラーと実行元ソースコードをChatGPTに渡し、コードの返信&解説で内容を理解しながらコードを再修正。(例えば、Curlコマンドで色々試しす中で、examplesの中のoutputの文字列が空白の場合や「!」が入るとエラーなることが判明。また、response_dataのJSONのリスト構造を確認して適切に値が取れるように修正を行った)

  • そしてGoogleChatに組み込みこんだチャットアプリ(Vertex AI Test)で、英語の質問に英語で返ってくるところまで完成。(現状Vertex AI APIはパブリックには日本語対応していないので)

最終的に動いたコードはこちら(デバッグの為のPrintとか、使っていない変数とか色々残っているが一旦そのまま)

<main.py> ※PROJECT_IDのところは、自分自身のものに置き換え

from typing import Any, Mapping
import flask
import functions_framework
import requests
import os
from google.oauth2 import service_account
import json
from google.auth.transport.requests import Request

@functions_framework.http
def vertex_chat(req: flask.Request) -> Mapping[str, Any]:

    # Get service account credentials from environment variable
    credentials_json_str = os.environ.get('GOOGLE_APPLICATION_CREDENTIALS')

    if not credentials_json_str:
        raise Exception("Service account credentials not found in environment variable.")

    # Parse the JSON string to get the actual credentials dictionary
    credentials_json = json.loads(credentials_json_str)

    # Specify the desired scopes for the credentials
    scopes = [
        'https://www.googleapis.com/auth/cloud-platform',
        'https://www.googleapis.com/auth/dialogflow',
        # Add any other necessary scopes here
    ]

    # Create credentials object with the specified scopes
    credentials = service_account.Credentials.from_service_account_info(
        credentials_json, scopes=scopes)

    # Make a request to set up the credentials
    credentials.refresh(Request())

    # Now you can use the credentials to get the access token
    access_token = credentials.token
    print("ACCESS_TOKEN:",access_token)

    if req.method == "GET":
        return "Hello! This function must be called from Google Chat."

    request_json = req.get_json(silent=True)
    print(request_json["message"]["text"])

    # Extract sender's display name and avatar URL
    display_name = request_json["message"]["sender"]["displayName"]
    avatar = request_json["message"]["sender"]["avatarUrl"]

   # Create the input data for AI model prediction
    input_data = {
        "instances": {
            "context": "My name is Ned. You are my personal assistant. My favorite movies are Lord of the Rings and Hobbit.",
            "examples": [
                {
                    "input": {"content": request_json["message"]["text"]},
                    "output": {"content": "welcome"}
                }
            ],
            "messages": [
                {
                    "author": "user",
                    "content": request_json["message"]["text"]
                }
            ]

        },
        "parameters": {
            "temperature": 0.3,
            "maxOutputTokens": 200,
            "topP": 0.8,
            "topK": 40
        }
    }
    
    print("INPUT_DATA:",input_data)
    
    # Make a POST request to AI model prediction API
    response = requests.post(
        "https://us-central1-aiplatform.googleapis.com/v1/pbrojects/PROJECT_ID/locations/us-central1/publishers/google/models/chat-bison:predict",
        json=input_data,
        headers={
             "Authorization": f"Bearer {access_token}",  # Replace with actual access token
            "Content-Type": "application/json"
        }
    )
    print("RESPONSE:",response.json())

    # Process the response from the AI model and generate a message
    if response.status_code == 200:
        response_data = response.json()
        generated_output = response_data["predictions"][0]["candidates"][0]["content"]
        response_message = {
            "text": generated_output  # Use the generated output as the reply
        }
    else:
        response_message = {
            "text": "An error occurred while processing your request."  # Handle error case
        }
        print("API error response:", response.content)


    # Return the generated response message
    return response_message

<requirement.txt>

Flask>=2.3.2
functions-framework>=3.*
requests>=2.31.0
google-auth

4.今後

 以上で、目標であった、PaLM2をGoogleChatで動かせるように自分で作ってみたい、というところは一旦は実現したが、本格的に利用しようと思った場合には、以下のようなことを検討していく必要がある。(職場の同僚情報含む)

  • セキュリティ・認証の考慮⇒とりあえず動くことだけを考えたので、ほぼ考慮できていないが本格的な利用の場合は必須。

  • 応答の精度向上⇒現在ソースコード中のinstancesの中のexamples等の記載や、parametersも適当なのでその修正要。

  • 日本語対応⇒以下の通り、現在Vertex IAI APIの日本語対応は公にはサポートされていないが(以下リンクの通り)、個別サポートの確認や、ない場合には内部に言語変換を組み込む等が必要。

  • ベクターデータベースの対応⇒以下はChatGPTでの記事ではあるが、どのLLMでも共通な仕組みのようなので、勉強してみたい。

この記事が気に入ったらサポートをしてみませんか?