見出し画像

メールするとGoogleカレンダーにスケジュール登録してくれる秘書を作成する

久しぶりにmakeを使ってライフハックをしたので紹介していきます。
今回紹介するのは、Googleカレンダーにいい感じに予定を登録してくれるAI秘書です。

レベルとしてはpythonを書いたり、Google cloud functionsを使ったりと簡単ではない面があるかもしれません。

そしてGoogle cloud functionsの手順やOpenAPIのAPIキーの取得手順などすっとばして書いていますのでご容赦ください。。。


モチベーション

Googleカレンダーの登録ポチポチするのが面倒 

モチベーションとしては以下のような作業を面倒と感じていたことでした。

  • Gmailの文面から自動でカレンダーに反映してほしいのに反映されない

  • GmailとGoogleカレンダーのアプリを行ったり来たりでカレンダー登録をポチポチするのが面倒

生成AIのある世界なら、きっと次のような機能が作れるだろ〜とmakeを使って作ってみることにしました。

  • 自分の秘書にメールを転送したらいい感じにカレンダーに登録してくれる!

  • 自分用のカレンダーと家族との共有カレンダーに分けて登録してくれる!

作り方

ステップは2つです。

  1. google cloud functions でOpenAI APIのfunction callingを利用してカレンダーに登録するかどうかを判断してもらって必要なカレンダー情報をもらう

  2. makeでメールトリガーとOpenAIAPIとGoogleカレンダーをつなぐ

1. google cloud functions でOpenAI APIのfunction callingを利用する

 ここで秘書にやってもらいたいことは、転送したメールと指示を読み取ってカレンダーに登録する情報を組み立てる、です。

Function Calling

OpenAIのAPIではfunction callingという機能があります。これはGPTに情報を渡すと指定したfunctionをcallするかどうかを判断し、callする場合は必要な情報を返してくれる、という機能です。

具体的には、メールの情報 -> カレンダーに登録する情報か(function callingで判断) -> カレンダーに登録する情報ならカレンダーのタイトル、開始時間、終了時間を返すといったものとなります。

以下のmain.pyとrequirement.txtをcloud functions上で作成して、https://で始まるエンドポイントを取得しておきます。

main.py

  • API_KEYはご自身のOpenAI APIキーに置き換えてください。ただし、本来直書きは推奨されませんのでご認識ください。(こういうところ改めたい…)

  • gpt-3.5-turbo-16kのモデルは金額もやすいのでこちらを利用しています。

  • いつかこのあたりの手順はちゃんと書かないととは思っている

import functions_framework
from openai import OpenAI
from flask import make_response
import json

@functions_framework.http
def hello_http(request):
    """HTTP Cloud Function.
    Args:
        request (flask.Request): The request object.
        <https://flask.palletsprojects.com/en/1.1.x/api/#incoming-request-data>
    Returns:
        The response text, or any set of values that can be turned into a
        Response object using `make_response`
        <https://flask.palletsprojects.com/en/1.1.x/api/#flask.make_response>.
    """
    request_json = request.get_json(silent=True)
    request_args = request.args

    if request_json and 'text' in request_json:
        article = request_json['text']
        # Initialize OpenAI client with your API key
        client = OpenAI(
        api_key=API_KEY,
        )

        # Define the function to be available for calling
        functions = [
            {
                "type": "function",
                "function": {
                    "name": "add_event_to_google_calendar",
                    "description": "Add an event to Google Calendar",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "calendar_type": {"type": "string", "description": "The calendar type, e.g. private or family. default is private",},
                            "summary": {"type": "string"},
                            "location": {"type": "string"},
                            "description": {"type": "string"},
                            "start_time": {"type": "string", "description": "The calendar start time, e.g. 2023-01-30T00:00:00+09:00"},
                            "end_time": {"type": "string", "description": "The calendar end time , e.g. 2023-01-30T00:00:00+09:00"}
                        },
                        "required": ["calendar_type", "summary", "start_time", "end_time"]
                    }
                }
            }
        ]

        # Example conversation with function calling
        conversation = [
            {
                "role": "system",
                "content": "You are an excellent secretary. Your job is to register your appointments in Google Calendar and Google's To-Do application."
            },
            {
                "role": "user",
                "content": article
            }
        ]
        # Make the API call
        response = client.chat.completions.create(
            model="gpt-3.5-turbo-16k",
            messages=conversation,
            tools=functions,
            tool_choice="auto"
        )
        response_message = response.choices[0].message
        tool_calls = response_message.tool_calls
        if tool_calls:
            #TODO 複数のfunctionがcallされることを想定する
            for tool_call in tool_calls:
                function_name = tool_call.function.name
                secretary_message = tool_call.function.arguments
                response= make_response(json.dumps(secretary_message, ensure_ascii=False))
                response.headers['content-type'] = 'application/json'
            return response

        else:
            secretary_message = response_message

    else:
        secretary_message = ''
    return secretary_message

requirement.txt

functions-framework==3.*
cohere==4.45
tiktoken==0.5.2
openai==1.11.1

2. makeでメールトリガーとOpenAIAPIとGoogleカレンダーをつなぐ

makeはAPIを提供しているSaaS製品などをいい感じにつなげてくれるサービスです。もちろん自分で作ったAPIをつなぐこともできます。

makeではメールアドレスを発行し、メールアドレスの着信をトリガーとするCustom Webhookがあるのでそちらを利用します。

makeはこちらから登録可能

https://www.make.com/en/register?pc=birdy53


全体像

データの組み立て

最初のCreateJsonではメール文面からAPIに渡すデータを組み立てます。
APIは日付がわかってないので渡してあげます。

Create JSON

HTTPコネクション

次にHTTPのコネクションを利用します。URL部分にCloud functionsで作成したエンドポイントのURLを貼り付けます。他は画像を参照してください。

Make a request

JSONをパースする

次にレスポンスのJSONをParseします。

Parse JSON

カレンダータイプで分岐させる

カレンダーはファミリーで共有しているカレンダーと、個人のみで管理するためのカレンダーを使っているので、レスポンスの内容で分岐させるためにRouterを利用します。

Routerの設定

CalendarIDのところでカレンダーを指定します。Googleアカウントを接続できていればプルダウンで選択できると思います。

最後はそれぞれのGoogleCalendarのコネクションを接続して完成です!


実際にメールを送ってみる

こんな感じのメールを送ってみます。

そうするとこんな感じでGoogleカレンダーに登録されました(見にくい…


おまけ

以前書いたこちらの記事と組み合わせれば、カレンダーに登録されるとiPhoneなどに通知してくれます。

通知の内容をみて、秘書がちゃんとカレンダー登録してくれたかの確認ができますので、こちらの設定はおすすめです。

今後の改善ポイントとしては、次のようなことを考えていきたいと思っています。

  • カレンダーをどのように登録したかをAI秘書から返信してもらう

  • カレンダーだけではなく、TODOリストへの登録など秘書業務としての横の拡がり

気が向けばもうちょっとStep by Stepでリライトするかもです。

ではまたお会いしましょう!

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