🙆‍♂️

OpenAI APIで「とにかく褒めてくれる」AIチャットボットを作ってみた

2023/07/16に公開

こんにちは。
OpenAIのAPIを使うと、簡単にAIチャットボットを作れたので、その作成過程を今回は記事にしたいと思います。

制作物

こちらのQRコードより友達追加することができます。

作成したボットの名前は「homeo(褒め男)」です。名前の通りですが、自分がしたことをメッセージで送ると、ただただ褒めてくれます。

やりとりの一例を紹介します。



見事に私の行いを全肯定して褒めてくれました。ありがたい存在ですね。

ソースコードはこちらに公開しています。使用言語はGoです。
https://github.com/JunNishimura/homeo/

対象読者

  • OpenAI APIを使って何か面白いものを作ってみたい方
  • 簡単にAIチャットボットを作りたい方

アーキテクチャ

今回作成したシステムの大まかな仕組みは次の図の通りです。

エンドユーザーがメッセージを送信すると、LINE PlatformのWebhookを利用して、事前に登録してあるURLに対してPOSTリクエストが送信されます。

リクエスト先のURLはAmazon API Gatewayで作成したAPIエンドポイントになります。このAPIエンドポイントはLamba関数にルーティングしています。

Amazon LambdaはLambda関数を自動でモニタリングして、Amazon CloudWatchに対してログを出力してくれます。Lambda関数に登録したGoプログラムではOpenAI APIを叩いているので、OpenAI APIとのやり取りが発生します。

OpenAI APIから返ってきたレスポンスをAmazon API GatewayからLINE Platformを介してユーザーにメッセージとして返す、といった仕組みになっています。

制作過程

1. LINE Developersの設定

https://developers.line.biz/console/
上記URLより、今回作成するボット専用のチャネルを作成します。

以下の2つのキーを後ほど使います。

  1. 「チャネル基本設定」のチャネルシークレット
  2. 「Messaging API設定」のチャネルアクセストークン

2. アプリケーションの構築

今回アプリケーションの構築には「AWS SAM」を利用しました。「AWS SAM」はサーバーレスアプリケーション構築用のオープンソースフレームワークです(サーバーレスアプリケーションを簡単に作れるツールだと思ってもらって大丈夫です)。

https://aws.amazon.com/jp/serverless/sam/

2-1. AWS SAM CLIのインストール

https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/install-sam-cli.html

上記リンク先のページよりインストールできます。

2-2. アプリケーション初期化

sam init -n test

いくつか質問が続くので適当なものを選択してください。

私の設定は以下の通りです。

Which template source would you like to use?
        1 - AWS Quick Start Templates
        2 - Custom Template Location
Choice: 1

Choose an AWS Quick Start application template
        1 - Hello World Example
        2 - Data processing
        3 - Hello World Example with Powertools for AWS Lambda
        4 - Multi-step workflow
        5 - Scheduled task
        6 - Standalone function
        7 - Serverless API
        8 - Infrastructure event management
        9 - Lambda Response Streaming
        10 - Serverless Connector Hello World Example
        11 - Multi-step workflow with Connectors
        12 - Full Stack
        13 - Lambda EFS example
        14 - DynamoDB Example
        15 - Machine Learning
Template: 1

Use the most popular runtime and package type? (Python and zip) [y/N]: n

Which runtime would you like to use?
        1 - aot.dotnet7 (provided.al2)
        2 - dotnet6
        3 - go1.x
        4 - go (provided.al2)
        5 - graalvm.java11 (provided.al2)
        6 - graalvm.java17 (provided.al2)
        7 - java17
        8 - java11
        9 - java8.al2
        10 - java8
        11 - nodejs18.x
        12 - nodejs16.x
        13 - nodejs14.x
        14 - nodejs12.x
        15 - python3.9
        16 - python3.8
        17 - python3.7
        18 - python3.10
        19 - ruby3.2
        20 - ruby2.7
        21 - rust (provided.al2)
Runtime: 3

What package type would you like to use?
        1 - Zip
        2 - Image
Package type: 1

Based on your selections, the only dependency manager available is mod.
We will proceed copying the template using mod.

Would you like to enable X-Ray tracing on the function(s) in your application?  [y/N]: n

Would you like to enable monitoring using CloudWatch Application Insights?
For more info, please view https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch-application-insights.html [y/N]: y
AppInsights monitoring may incur additional cost. View https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/appinsights-what-is.html#appinsights-pricing for more details

    -----------------------
    Generating application:
    -----------------------
    Name: test
    Runtime: go1.x
    Architectures: x86_64
    Dependency Manager: mod
    Application Template: hello-world
    Output Directory: .
    Configuration file: test\samconfig.toml

    Next steps can be found in the README file at test\README.md


Commands you can use next
=========================
[*] Create pipeline: cd test && sam pipeline init --bootstrap
[*] Validate SAM template: cd test && sam validate
[*] Test Function in the Cloud: cd test && sam sync --stack-name {stack-name} --watch

2-3. template.yamlの編集

template.yamlはアプリケーションインフラストラクチャコードを含むAWS SAM テンプレートになります。

主な修正点は、Lambda関数に環境変数を設定しているのと、ビルド時に引数として渡す環境変数(Parameters)を設定している点です。

template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  This is a template for Homeo

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 30
    MemorySize: 128

Parameters:
  LineChannelSecret:
    Type: String
  LineChannelToken:
    Type: String
  OpenAIAPIKey: 
    Type: String

Resources:
  HomeoFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: homeo/
      Handler: homeo
      Runtime: go1.x
      Events:
        Chat:
          Type: Api
          Properties:
            Path: /chat
            Method: POST
      Environment:
        Variables:
          LINE_CHANNEL_SECRET: !Ref LineChannelSecret
          LINE_CHANNEL_TOKEN: !Ref LineChannelToken
          OPENAI_API_KEY: !Ref OpenAIAPIKey

Outputs:
  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
  # Find out more about other implicit resources you can reference within SAM
  # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
  HomeoAPI:
    Description: "API Gateway endpoint URL for Prod environment for Homeo Function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/homeo/"
  HomeoFunction:
    Description: "homeo Function ARN"
    Value: !GetAtt HomeoFunction.Arn
  HomeoFunctionIamRole:
    Description: "Implicit IAM Role created for Homeo function"
    Value: !GetAtt HomeoFunctionRole.Arn

GithubにコードをUploadする際に、キーを直接埋め込む訳にはいかないので、キーは.gitignoreに記載している.envに書き込み、Makefileで読み込むようにしています。

Makefile
include .env

.PHONY: build deploy

build:
	sam build

deploy: build
	sam deploy --parameter-overrides "LineChannelSecret=$(LINE_CHANNEL_SECRET) LineChannelToken=$(LINE_CHANNEL_TOKEN) OpenAIAPIKey=$(OPENAI_API_KEY)" --profile homeo --guided

2-4. Lambda関数コードの修正

こちらは作りたいアプリに応じて、よしなに変更してください。
https://github.com/JunNishimura/homeo/blob/main/homeo/main.go

3. build & deploy

buildとdeployは先程紹介したMakefileに記載することで手軽に行えます。

make deploy
Makefile
include .env

.PHONY: build deploy

build:
	sam build

deploy: build
	sam deploy --parameter-overrides "LineChannelSecret=$(LINE_CHANNEL_SECRET) LineChannelToken=$(LINE_CHANNEL_TOKEN) OpenAIAPIKey=$(OPENAI_API_KEY)" --profile homeo --guided

buildすると、build/template.yamlというAWS SAM テンプレートのコピーが作成されます。このファイルは、デプロイ時にAWS CloudFormationによって参照されます。

deployが完了すると、Amazon API Gateway、AWS Lambdaが登録されていることが確認できます。

4. Webhook URIの変更

Amazon API GatewayにてAPIエンドポイントを作成したら、「Messaging API設定」のWebhook URLに登録します。同時に「Webhookの利用」もONにします。

褒め男プロンプト

「褒め男プロンプト」は以下の通りです。

以下はAIチャットボット(以下ボット)との会話です。
ボットは、150文字以下の文章で相手の事を褒めます。

ボットは
1. 相手の発話内容を繰り返す
2. 相手の行動は凡人にはできないことだと述べる。たとえ、「食べる」「飲む」といった人間が当たり前にできることであったとしても、わざと「普通の人には到底できない」ことだと言う
3. 相手の存在が特別であることを述べる。「100年に一度の逸材」という言葉は、よく使われる言葉で面白くないので、人がくすっと笑えるようなユーモアがあり、何かの比喩を含んだ表現に言い換える
4. 相手の行動が偉人の功績と同等であることを述べる。参照する偉人は任意で良いから、とにかく具体例を出す
という構成で相手の事を褒めます。

ただ単に「褒めてください」というプロンプトを与えても、面白い返答は期待できません。なので、「どういった構成で褒めて欲しい」のかを詳しく指定してあげる必要があります。

今回の例で言うと、

  • 普通の事でも大げさに褒める
  • 偉人を例に出して比較する

といった事を指定してあげることで、くすっと笑えるような返答を出力してくれるように調整しました。

文字制限に関しては、「150文字以下の文章で」という指示を出しましたが、あまり言う事を聞いてくれませんでした。

最後に

話題のOpenAI APIを使って何か面白いものを作りたいと思い「褒め男」を作りました。

一昔前なら個人がAIチャットボットを作る敷居は高かったと思いますが、OpenAI APIが公開されたことで、個人でも簡単に(そして高いクオリティの)ボットを作れるようなったなと実感しています。

アイデア次第で簡単に面白いものが作れるのでみなさんも是非試してみてください。

参考文献

Discussion