6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

GPT-4でSES営業メール(Gmail)を自動分類してみる

Posted at

概要

こんにちは!
GPT君は文脈を読み取る力みたいなのが非常に優れているので、「React歴2年以上の案件メールだけ確認したい」みたいなことができるのは。と思ったのでSpringBootで試してみました。

前提

  • Googleアカウント開設済み
  • OpenAIのAPI keysを取得済み

Gmail APIの設定

GmailのAPIを利用するため、以下の手順が必要になります。

  • Google Cloudでプロジェクトの作成
  • Gmail APIの有効化
  • OAuth 2.0 クライアントの設定

Google Cloudでプロジェクトを作成する

https://console.cloud.google.com/cloud-resource-manager にログインし、プロジェクトを作成します。
キャプチャ.PNG
プロジェクト名は適当にgmail-aiとかにしました。

Gmail APIの有効化

https://console.developers.google.com/apis/library にアクセスし、「Gmail API」で検索→Gmail-apiを有効化する。
キャプチャ2.PNG

OAuth 2.0 クライアントの作成

https://console.cloud.google.com/apis/credentials にアクセスし、認証情報を作成→OAuthクライアントIDを選択する。
キャプチャ3.PNG
ウェブアプリケーションを選択し、名前は適当に「gmailai」、承認済みのリダイレクトURIに「http://localhost:5555/Callback 」を入力→保存する。
キャプチャ4.PNG
秘密鍵をJSONでダウンロード。後に実装で使います。
キャプチャ5.PNG

実装

構成はこんな感じ
先ほど取得した秘密鍵JSONは/resourcesに配置。OpenAiのAPI_Keyはopen-api-secret.propatiesに書いています。
キャプチャ6.PNG

まずはbuild.gradleにTheoKanning/openai-javaを追加

implementation group: 'com.theokanning.openai-gpt3-java', name: 'service', version: '0.12.0'

ちなみに

implementation group: 'com.theokanning.openai-gpt3-java', name: 'client', version: '0.12.0'

もありますが、後にOpenAiServiceクラスを使うためにはサービスモジュールの必要があるため前者の方にして下さい。

今回はGMailのAPIを使うので以下も追加します。

implementation 'com.google.apis:google-api-services-gmail:v1-rev20220404-1.32.1'
implementation group: 'com.google.api-client', name: 'google-api-client', version: '1.32.1'
implementation group: 'com.google.oauth-client', name: 'google-oauth-client-jetty', version: '1.32.1'

認証

認証のためのコーディングをしていきます。大体のコードは以下記事を参考にしています。

/service/GmailAiService.java
// Json処理
    JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
    // スコープ
    List<String> SCOPES = Collections.singletonList(GmailScopes.GMAIL_READONLY);
    // 認証周りの設定ファイルの格納フォルダ
    String CREDENTIALS_FOLDER = "credentials";
    
    String path = "/client-secret.json";
    try (InputStream is = getClass().getResourceAsStream(path);
    InputStreamReader streamReader = new InputStreamReader(is, StandardCharsets.UTF_8);
    BufferedReader br = new BufferedReader(streamReader);
    ) {
      // HTTP通信
      NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
      System.out.println(HTTP_TRANSPORT.toString());
      GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, streamReader);
      GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY,
        clientSecrets, SCOPES)
                .setDataStoreFactory(new FileDataStoreFactory(new java.io.File(CREDENTIALS_FOLDER)))
                .setAccessType("offline").build();
      // 認証を行う
      LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(5555).build();
      Credential credential = new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
      // Gmailのサービスを作成
      // アプリケーション名
      String APPLICATION_NAME = "gmailai";
      // Gmailにアクセス
      Gmail service = new Gmail.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).setApplicationName(APPLICATION_NAME)
              .build();
    }

まずは定数の説明
JSON_FACTORY : JSONを処理するためのオブジェクト。APIの返ってくるデータはJSON形式なので。
SCOPES : APIをつかってGmailにどこまでのアクセスを許可するか。GmailScopesクラスに定数で全部あるはずなのでそれから適切なものを選んでつかいましょう。今回やるようなことはGMAIL_READONLYを選んでおけば全部できるはずなので、それを選んでおきましょう。
CLIENT_SECRET_DIR : 秘密鍵のファイルのパス。今回は直下に「client_secret.json」という名前でいれたので、"client_secret.json"でOKです。
CREDENTIALS_FOLDER : 秘密鍵を使って取得した認証まわりのファイルを保存するフォルダのパス。上で作ったフォルダを設定。
HTTP_TRANSPORT : HTTP通信をするためのオブジェクト。

メール本文の取得

先程取得したGmailのサービスのオブジェクトをもとに、以下の雑な処理でメール本文を取得し、String型に変換していきます。

sharedService/GetGmail.java
public String getGMail(Gmail service) {
    // ユーザ
    String USER = "me";
    // メールIDを全て取得
    ListMessagesResponse messagesResponse = getMessagesResponse(service, USER);
    List<Message> messageList = messagesResponse.getMessages();

    // 今回は最新のメールだけ取得
    Message targetMessage = getFullMessage(service, USER, messageList.get(0));

    // 本文の取得(Base64)
    String bodyBase64 = targetMessage.getPayload().getParts().get(0).getBody().get("data").toString();
    // Base64からデコード(byte列)
    byte[] bodyBytes = BaseEncoding.base64Url().decode(bodyBase64);
    // byte列からStringに変換
    try {
      String body = new String(bodyBytes, "UTF-8");
      // 本文を返却
      return body;
    } catch (Exception e) {
      e.printStackTrace();
      return "";
    }
}

ちなみに取得した本文サンプルはこんな感じ。かなり適当です。

突然のメール失礼いたします。
株式会社ホゲホゲ営業担当の斎藤と申します。

貴社の公式サイトを拝見し、SESの人員を募集しているとのことでしたので、ご紹介したいエンジニアがございます。
【名前】
田中 太郎
【経歴】
2018年 株式会社banに入社 プログラマーとして勤務
2022年 Boo株式会社に転職  プロジェクトマネージャーとして従事

【スキル】
Java歴 3年
React歴 1年
Vue歴 2年
Rust歴 1年

いずれも実務での経験年数になります

ご興味がありましたら、こちらのメールアドレス(abc@mail .com)にご返信ください。

GPT君の出番

やっとGPT君の出番が回ってきました。
今回はメール本文から、田中太郎さんのスキルを抽出してもらいましょう。

GptSharedService.java
public void summaryForGpt(String mailBody) { // 先程取得したメール本文
    ResourceBundle config = ResourceBundle.getBundle("open-api-secret"); // resources/open-api-secret.properties
    String token = config.getString("token");
    String prompt = "次の文章は営業メールです。文章の内容を読み取って、紹介されている人物の持っているスキルを全て抽出して下さい。\n" + mailBody;
    OpenAiService service = new OpenAiService(token);
    ChatCompletionRequest completionRequest = ChatCompletionRequest.builder()
    .messages(Arrays.asList(new ChatMessage("system", prompt)))
    .model("gpt-4")
    .maxTokens(256)
    .stream(false)
    .build();
    List<ChatCompletionChoice> completionResult = service.createChatCompletion(completionRequest).getChoices();
    for (ChatCompletionChoice choice : completionResult) {
      System.out.println(choice.getMessage().getContent());
    }
  }
出力結果
Java、React、Vue、Rust

ちなみにメール本文の【スキル】【技術】とかにしてもちゃんと取得してくれました。

できそうなこと

メールの受信時にメール本文のGPTに読み込ませる→任意の項目を抽出(スキルや職種など)→DBに保存。みたいなことすれば、高度なメールフィルター機能をもつサービスとか作れそうだな~と思いました。
あとは、メールの内容的にスパムっぽいやつは全自動でゴミ箱へシュートする機能とかもできそうな気がします。

他にもこんなことできそう!みたいな案がありましたら、コメント頂けると嬉しいです!!

参考文献

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?