LIFULL Creators Blog

LIFULL Creators Blogとは、株式会社LIFULLの社員が記事を共有するブログです。自分の役立つ経験や知識を広めることで世界をもっとFULLにしていきます。

数日で営業日報の作成を支援する生成AIブラウザ拡張を実装した話

プロダクトエンジニアリング部の二宮です。この記事はLIFULL Advent Calendar 2024 Part2の20日目です。

LIFULLにはkeelaiという社内向けの生成AI基盤プロジェクトがあり、私はその開発にコミットしています。今のところ特に社内用Slack botとして最もよく使われています。

www.lifull.blog

keelaiの基本的なコンセプトを私達はマルチエージェントと呼んでいて、サブタスクを解決するために自律的に動くエージェントを複数組み合わせて協調させることで無限にスケールすることを目指します。

このエコシステムを土台に、エンジニア以外のメンバーからの改善リクエストや新しいアイデアをうまく取り込んでいます。その中から、生成AIヘビーユーザーの営業職メンバーから「営業日報を簡単に作りたい」というアイデアをいただいて、内製AIを使ってうまく機能提供した様子を紹介します。

営業サイドからのニーズヒアリング

keelaiの開発チームでは、全社の活用方法の相談窓口となるサポート用のSlackチャンネルを設けています。そこで、営業職メンバーからプロンプトの相談を受けていました。

そこで何度かやり取りしていて、この2つ面白いフィードバックがありました。

  1. Chrome拡張機能(keelext)で提供しているメール返信文作成機能に対する好評
  2. 営業日報作成を自動生成して省力化したいという要望

keelextとは生成AI(keelai)以前からあった内製Chrome拡張です。ここ最近はkeelaiとの連携機能も増えていて、その中の一機能として次の画像のようなGmailの返信文の作成機能を提供していました。これは半ばkeelaiのAPI連携機能のデモとして作ったつもりのものだったのですが、私たち開発チーム側が考えていた以上に需要が大きかったようです。

※画像にあるメールの内容は架空のものです

もう一つは営業日報の作成が負担で、生成AIで自動化したいという話です。Slack AutomationsによるLLMノーコードツールの提供にあるやり方を紹介しました。

既存機能の再利用で短期間開発

そのまましばらく動けてなかったんですが、更にしばらくして開発チーム内で「やっぱり営業職への普及促進は重要なんじゃないか」と課題が挙がります。そこで日報作成の省力化として、日報作成機能のkeelext組み込みにトライしてみることにしました。

最初に作った機能を紹介します。次のようになぐり書きに近いメモ書きから、ボタン一発で必要な項目に整理します。

私はkeelextのリポジトリを…というよりChrome拡張機能を実装したことが無く、フロントエンドやJavaScriptの経験に乏しいので当初は心配でした。しかし実際にやってみると、うまく機能がテンプレート化されていて、いくつかの箇所を触るだけで実現できました。

まずはmanifest.jsonにソースの読み込み設定を書き足します

  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": [
        ...
      ],
      ...
    },
    {
      ...
    },
    {
      "matches": ["https://*.salesforce.com/*", "https://*.lightning.force.com/*"],
      "js": [
        "src/salesforce.js"
      ]
    }
  ],

次に実行ファイル( src/salesforce.js )を実装します。とはいえほとんど実装は使いまわしです。 <DOM要素のセレクタ>と、「保存」ボタンと被ってしまっていたボタンの位置を右側に移動させる設定だけは必要でした。

(() => {
    const monitor = (selector, cb) => {
        cb(document.querySelectorAll(selector));

        new MutationObserver((records) => {
            records.forEach((record) => {
                record.addedNodes.forEach((addedNode) => {
                    if (addedNode.nodeType === Node.ELEMENT_NODE) {
                        cb(addedNode.querySelectorAll(selector));
                    }
                });
            });
        }).observe(document.body, {
            childList: true,
            subtree: true,
        });
    };

    monitor(`<DOM要素のセレクタ>`, (nodes) => {
        // ボタンを表示する実装
        // ここでボタン押下時にtextboxの内容を取得してAPIを呼び出す実装をする
    });
})();

そして最後にAPIの呼び出し部分を追加します。ここでプロンプトを修正します。

        const response = await fetch("https://<keelai APIのエンドポイント>/v1/chat/completions", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "Authorization": `Bearer ${cookie.value}`,
          },
          body: JSON.stringify({
            messages: [{
              role: "system",
              content: `Your task is to create a sales report from the following text in ${chrome.i18n.getUILanguage()}.
              Output it thoroughly and carefully without omissions as a report for the supervisor. Adhere to the following terms.
              - CL = Sales Closing

              Structure and organize the report according to the following content.
              Output these contents in markdown with ### as titles, only the items for which information is available.
              - <項目A>
              - <項目B>
              ...
              - メモorトピックス
              `,
            }, {
              role: "user",
              content: message.content,
            }],
            stream: true,
          }),
          signal: abortController.signal,
        })

更に言うと、これも先程の営業チームで使われていたプロンプトを大幅に参考にしています。「CL = クロージング」というよく使われる略語や、<項目A>などの各項目タイトルはそのまま流用しています。プロンプト全体を英語にして整理し直した点と、内容によっては含まれない項目を only the items for which information is available. とした点は追加で工夫しました。

理想を言うと、文章に必要な追加情報も自動で取ってこれるようにしたいとかは思いつくのですが、すぐ提供できる範囲で実用的な機能は提供できたと思います。

開発後の効果とフィードバック

これで営業チームはワンクリックでメモを整理し、日報記入時間を大幅に短縮できるようになりました。協力してもらった方に連絡したところ、次のような嬉しいコメントいただけました。

実際に試してみました~!
商談メモがワンクリックで整理された日報になるのでは感動しております、、、!!!

その後、営業チーム内の勉強会でSlack botやChrome拡張を紹介していただけたそうです。こんな感じで機能アイデアや対応のやり取りして、各チームのアーリーアダプターといい協力関係を築けてるように思います。

また、既存の機能(Gmail生成)を転用し、個別開発コストをかけずに横展開できることも確認できました。今後は他のツールの転用も視野に入れています。

まとめ

このように、keelaiやkeelextは社内コードがオープンであるため、新機能を思いついたら素早く拡張できます。部署をまたいだニーズにも、既存コードを活かして最小限の修正で対応可能な環境が整っていると思います。

この日報支援機能等をきっかけに、他の業務ツールへの適用してみんなで楽できる流れを広げたいなあ…と思ってます。この後、社内向けの生成AIユースケースのデモ目的を半分、素直に自分が使いたい意図半分で、次のような機能も実装してみました。

  • Jira(プロジェクト管理ツール)やGitHubのPR, Issueなどを要約し、残課題や次のアクションをまとめてくれる機能
  • ブログを書くときによりわかりやすい書き方をアドバイスしてくれる機能

これをきっかけにユースケースを多くの社員に想像できるようにして、簡単に社内ツールの要約や提案機能をエンジニア全体で作っていけるようにもしたいです。また余談ですが、LIFULLには社内用Chrome拡張機能ストアがあったり、keelextに自動アップデート機能があったりして、こうした活動がスケールする仕組みが整備されていると感じます。

最後に、LIFULLでは一緒に自分たちの仕事を良くしていくエンジニアを求めています。これらの取り組みに興味を持っていただけたら、ぜひ求人情報やカジュアル面談のページもご覧ください🙇

hrmos.co

hrmos.co