LIFULL Creators Blog

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

LLMを利用したPlatform Engineering

KEELチーム の相原です。

これまでKEELチームではKubernetesベースの内製PaaSであるKEELを開発・運用しながら、合間で社内で汎用AI(仮)と呼ぶAutoGPT実装 keelai を開発してきました。

www.lifull.blog

我々はあくまでプラットフォーマーであり、目指すところはLLMを利用したPlatform Engineeringです。

いくつかの取り組みが実を結んできたのでここで紹介したいと思います。

APIの提供

何はともあれまずはAPIの提供でしょう。 ここでは我々が開発するAutoGPT実装である keelai をAPIとして提供しています。

移植性のためにOpenAI互換のインタフェースになっていて、当然Server Sent Eventsにも対応しています。

KEELチームで開発しているSAMLベースの認証基盤の下で社内に公開しており、Kubernetesクラスタ内通信も含めてIstioのAuthorizationPolicyで認可しています。

FastAPIを使っていてちょうどよくWebインタフェースが用意されていることもあり、開発者はAPI Keyなどを発行することなくすぐにAPIを利用することができます。

IstioのRequestAuthenticationで任意のJSON Web Tokenを検証することもでき、あらゆる場所から安全に呼び出すことが可能です。

また、セグメントごとのトークンベースのRate Limitを実装してあり、SAML認証済みのユーザやJSON Web Tokenの任意のペイロード・呼び出し元ワークロードに応じてヘッダを付与し、それをもとにSliding Windowで流量制限しています。 呼び出し元ワークロードの判定をヘッダから行うためには、まずIstioのPeerAuthenticationでmTLSを強制して呼び出し元のEnvoyを保証し、Envoyが付与する x-envoy-peer-metadata をProxy-Wasmでパースしてワークロードを取得するなどちょっとハックしているので、この辺はまた別のエントリで書くとしましょう。

当然サイト信頼性に責任を負う立場として、各種メトリクスやOpenTelemetryによるトレースの収集、適切なリトライやエラーハンドリングによってProduction Readyな品質となっており、コンシューマ向けのプロダクトからもこのAPIが呼ばれています。

各種ベクトルデータベースの提供Semantic Search用のコンポーネントの提供もしていますが、嬉しい誤算で汎用AI(仮)ということもあり基本的に現在はこのAPIを介してあらゆる機能を実現しています。 (OpenAIへの課金を懸念してllama.cppベースのオープンソースLLMのAPIサーバも提供していますが、これも嬉しい誤算でLLMの価格競争による低コスト化が進んでいるので今のところ出番はなさそうです)

今後はKubernetesクラスタであるKEEL自身のLLMを使ったAIOps(?)を強化していく予定で、Alertmanagerから発火する運用自動化用のKnative Serviceが存在しているため、そこから同様に keelai のAPIを呼ぶことで更なる自動化を進めていきます。 keelai はSelf-hostingされた汎用AI(仮)として社内の監視基盤とも連携できるのでここは色々と遊べそうです。

GitHub ActionsからのLLM利用

APIには前述した通りIstioのレイヤでJSON Web Tokenの検証と認可が実装されているため、同じく我々が提供するGitHub Actions Self-hosted runnersを利用することでGitHub Actionsから以下のように呼び出すことができます。

www.lifull.blog

$ ID_TOKEN=$(curl -sSL -H "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=${GITHUB_ACTION_PATH}" | jq -r .value)
$ curl -sSL -X POST -H "Authorization: Bearer $ID_TOKEN" -H "Content-Type: application/json" https://keelai-api.keelai.svc.cluster.local:8080/v1/chat/completions -d "$(echo $@ | jq -sc --arg model "$MODEL" '. as $messages | {"model": $model, "messages": $messages}')"

これにはGitHubのOpenID Connectを利用していて、サーバ側はこのようにGitHubから送られてきたJSON Web Tokenのclaimsをもとに認可することが可能です。

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: keelai-api
spec:
  action: ALLOW
  rules:
  - when:
    - key: request.auth.claims[iss]
      values:
      - https://token.actions.githubusercontent.com
    - key: request.auth.claims[repository_owner]
      values:
      - lifull
  selector:
    matchLabels:
      app.kubernetes.io/name: keelai-api

これにより各リポジトリにAPI Keyを配布することなく、気軽にLLMを利用した自動化を始めることができています。

さて、LLMによるソフトウェアエンジニアリングの生産性向上でやはり最初に思いつくものはコードレビューでしょう。 既にOpenAIのAPIを叩いてコードレビューするようなものはありふれていますが、目指すべき先は社内のコーディングガイドラインや過去の障害実績をもとにしたコードレビューだと思います。

そのためには社内情報にアクセスできる必要があり、そこで汎用AI(仮)を目指す keelai が役に立ちます。 keelai はAutoGPT実装として、目的達成のため自律的に複数の関数を使い分けながら回答を作成できるため、(今はまだ精度に改善点はあるものの)必要に応じて過去の障害情報を参照しながらコードレビューすることが可能です。

我々はプラットフォーム戦略としてKubernetes Manifestからドキュメントまでを一手に生成するコードジェネレータも開発しており、これによって多くのGitHub Actionsを配布しています。

その中でコードレビューの機能も実験的に提供しており、プロンプトに以下のような指示を加えて、git diff の出力をもとにコードレビューの結果をreviewdogの形式で出力させています。

The output MUST be `%f:%l: %m` format.
<snip>
%f: File name
%l: Line number
%m: Message
</snip>

Line number MUST be the line number of the file that calculated from the diff.

こうしておくことでreviewdogを使って雑にPullRequestへのインラインコメントが可能です。

echo "$body" | reviewdog -efm='%f:%l: %m' -reporter=github-pr-review -filter-mode=nofilter

このメソッドは手軽な割に意外と汎用的で、セキュリティに特化したコードレビュー機能が社内で配布され始めたりと好感触です。 他にも、利用しているOSSのバグチケットをGitHub Actionsのスケジュール実行で監視して翻訳・要約してIssueとして起票するチームがあったりとGitHub ActionsからのLLM利用が進んでいます。

Slack AutomationsによるLLMノーコードツールの提供

次はSlack Automationsを利用した疑似的なLLMノーコードツールを提供している話です。

Slack AutomationsとはSlackの有料プランで利用できるワークフロービルダーです。 リアクション時やスケジュール実行でチャンネルへの発言からスプレッドシートへの追記まで割となんでもできます。

api.slack.com

Deno Slack SDKを使ってステップと呼ばれる任意の処理も自作可能で、組み込みのステップは多くないものの自分で作ってしまえば問題ありません。

LIFULLではこのSlack AutomationsからLLMを呼び出せるようにして、LLMノーコードツールとして職種問わず広く社員が業務を自動化できる環境を整えています。

とは言うものの、Slack Automationsは2024年8月現在でステップのSelf-hostingに対応していません。 つまりプライベートネットワーク上で公開されているAPIにアクセスすることができません。

幸い我々のAutoGPT実装である keelai はSlack Botとしても実装されており、Slack AutomationsからメンションすることでLLMを発火させることができました。

www.lifull.blog

実際の利用例は以下のようなイメージです。

基本的にはリアクションなどを起点に組み込みの Reply to a message in thread を使いながらメンションしてLLMを発火させているだけです。 リアクション時にペイロードとして渡ってくるメッセージのURLからメッセージ本文を取得するステップを実装していますが、これはFew-shot promptingをしやすくするためのものであり必須ではありません。

そして設定したリアクションをすると以下のようにLLMが呼び出されます。

これもなかなか好評で、プログラミングなしでLLMによる業務の自動化が可能であることから職種問わず広く利用されています。

ちなみに、回答結果へのリアクションは keelai 自身が行っており、Slackの chat.update を通してServer Sent Eventsを表現しているためそれの完了通知という意味もありつつ、ここから更にリアクション起点のSlack Automationsを発火させるためという意味もあります。

Slack Automationsには簡易的なフォームを作成する機能もあり、総務部門など各部署が自分達で相談の一次受けのフォームを用意するといったことが行われています。 汎用AI(仮)である keelai は当然社内でのこれまでの相談内容や社内ドキュメントをSemantic Searchできるようになっているため、そこそこの精度で回答することが可能です。

そして、Submit すると事前に定義されたプロンプトにフォームの入力を埋め込んでLLMが呼び出されます。

Slack Automationsにはスプレッドシート連携の機能もあるため、完了通知のリアクションを起点に質問と回答結果のペアをスプレッドシートに追記しておいて、それをもとにプロンプトの改善に繋げるといった運用になっています。

他にも経理部門が為替の日次確認の自動化を実現していたり、RSSによって通知されるニュースをリアクションで要約するワークフローが普及していたりと、こういったことをエンジニアでなくてもすぐに実現できる点が汎用AI(仮) + Slack Automationsの強みです。

元々Slack Botとして keelai を開発し始めた狙いでもありますが、コミュニケーションツール内でLLMを利用することにより社員が日頃からLLMの活用を目にしやすく、利用者の拡大にも一役買っていると思います。

我々はプラットフォーマーとして多くのステップをDeno Slack SDKで開発しており、ループ機構を実現するステップやSlack Automations側でOAuthのサポートがあるためそれを使ったGitHubやGoogle Apps Scriptへアクセスするステップなどが既に実装されています。

(Self-hostingのサポートを待ちつつ)今後もLLMノーコードツールとして機能開発を続けていきます。

Chrome Extensionで実現するシームレスなLLM体験

LIFULLのプラットフォームを広く開発する我々KEELチームは、プラットフォーム戦略の一環としてChrome Extensionも開発しています。 KEELチームが開発する汎用AI(仮)が keelai なので、このChrome Extensionの名前は keelext です。

当初はGrafanaのユーザ体験を補完するなどプラットフォームの利用補助が主なスコープでしたが、汎用AI(仮)の開発に伴いそのスコープが拡大してきています。

LLM周りでの主な機能としては、対応している社内サービスなどのページを開くと keelai のアイコンが表示され、それをクリックするとモーダルが開いて例えばConfluenceの場合はそのページの要約が生成されます。

他にはGrafana上のエラーメッセージの解決方法を過去のエラー対応のやり取りをもとに提案してくれる機能や、右クリックのメニューからは選択範囲の文字列の翻訳・要約するなどありがちな機能も実装してあります。 生成結果の言語はブラウザの設定言語に従いますが、モーダル内でそのまま翻訳することも可能です。

このシームレスなユーザ体験により、利用者は keelai のアイコンを見かけたら とりあえずクリックするだけで何かがいい感じに生成される ということが実現されています。

他にもフォームの自動入力など社内の各種プラットフォームのLLM連携が実現されており、LLMを利用したPlatform Engineeringを支える重要なコンポーネントとなっています。

当然これも keelai のAPIを利用することで実現されていて、APIの提供で紹介した社内の認証基盤の認証フローを chrome.identity.launchWebAuthFlow で踏んでいます。 そのため利用者が手元にAPI Keyを用意することなく安全に呼び出すことができています。

あとは愚直にひたすら実装していくだけです。あえて言うとすれば生成結果をServer Sent Eventsでそのままモーダルにストリーミングしていて、性質上複数回クリックするなどしてリクエストが重複する可能性が高いので丁寧にAbortControllerで重複を防いでることくらいでしょうか。

Gmailで利用できるメール返信文の自動生成を実装しているなど本家と衝突して危ういものもありますが、メールは職種によっては評判がよかったりするのでとりあえず短期の生産性向上を目指してあらゆるページにLLM連携を実装していっています。

とはいえChrome Extensionだと権限の問題で実現できる範囲に制約があり、現在は鋭意デスクトップアプリケーションを開発中です。 (プラットフォーマーとして、Kubernetesベースの内製PaaS・GitHub ActionsからKubernetes Manifest, ドキュメントまでを握るコードジェネレータを中心としたコマンドラインツール・Chrome Extensionとやってきたので次はデスクトップアプリケーションかなというところです)

コマンドラインツールでのLLM活用

我々は keelctl と呼ばれるコマンドラインツールも開発しており、先に紹介したコードジェネレータもこの keelctl に実装された機能の一つです。

www.lifull.blog

実はコマンドラインツールでのLLM活用は以前に似た内容のエントリを書いていて、社内の認証基盤の認証フローをコマンドラインから踏んでAPIを利用するという大枠は変わっていません。

www.lifull.blog

こちらも順調に機能拡充が進んでいて、Conventional Commits形式のコミットメッセージの自動生成の他にも色々なタスクをコマンドラインツールからLLMを活用することで実現しています。

中でも、CSVのカラムを入力として他のカラムを埋める keelctl llm fillcsv という機能が好評です。

System:
You are an AI assistant. Given a question and its answer, your task is to generate alternative expressions (paraphrasing) for that question to provide more options.

User:
Paraphrasing provides a new perspective on the question and aids users in obtaining the answer. Please generate at least 10 paraphrasings.

Paraphrasing MUST be joined semicolons.

question: keelaiの利用方法
answer: keelaiを利用する際には対象のSlackチャンネルにkeelaiを招待してメンションするか、keelaiのSlack Appsに対してDirect Messageで話しかけてください
paraphrasing: keelaiを利用するには;keelaiの使い方;keelaiのドキュメント;LLMを使いたい

question: %s
answer: %s
paraphrasing:

例えば上記のようなプロンプトテンプレートを与えると、以下のCSVを行ごとに処理して paraphrasing カラムを questionanswer から生成した想定される質問の別バリエーションで埋めることができます。

question,answer,paraphrasing
LIFULLに興味がある場合の次のアクション,お気軽に[カジュアル面談](https://hrmos.co/pages/lifull/jobs/010-9998)をお申込みください,
...

利用イメージは以下です。 コマンドを実行するだけでLLMを使ったタスクを並行で一括実行することができます。 中身は汎用AI(仮)なので、社内情報へのアクセスはもちろんのこと検索や画像生成まであらゆるタスクをこなすことができます。

$ keelctl llm fillcsv input.csv question,answer paraphrasing --prompt-template /path/to/paraphrasing.tmpl --concurrency 10

先のプロンプトテンプレートは社内知識をEmbeddingに変換する時に検索精度向上のために利用しているもので、他にも社内のよくある質問集の多言語対応をする際にも似た要領で一括実行しています。

最近では膨大な業務データのLLMを利用したタグ付けにも使用されたりと、簡単に使える一括処理として広く使われるようになってきました。

Jupyter Notebookでの高度なLLM活用

一方で、CSVの行ごとの一括処理ではまとまった単位で処理をしたい時や複雑な前処理が必要な時に対応することができません。

KEELチームはプラットフォームの機械学習サポートとしてJupyterHubを運用しており、そこでそういった高度なユースケースに対応しています。

JupyterHubは社内の認証基盤と統合されており、社員であればURLにアクセスするだけでJupyter Notebookを利用可能です。

そして認証基盤との統合により keelai のAPIをNotebook上から認証なしに実行することができ、すぐにプログラムからLLMを使い始めることができます。

余談ですが、Jupyter Notebookは比較的リッチなUIを実現できるため、このような簡易的な画像生成用のNotebookも提供しています。 これとは別にStable Diffusion WebUIのホスティングもしていて、利用者は用途に応じて画像生成AIを使い分けることが可能です。

このJupyter Notebookの表現力を活かし、Slack上の keelai でCode Interpreter相当の機能を実現するためのインタフェースとしても利用されます。

また、コマンドラインツールの実行者はソフトウェアエンジニアに限られてしまいますが、Jupyter Notebookであれば誰もが簡単に実行できます。

共有ストレージをNotebookにマウントして、作成したJupyter Notebookの配布機構も備えたことで、作成したLLMの高度なユースケースを配布するプラットフォームとしても機能するようになりました。

まとめ

今回はLIFULLでのLLMを利用したPlatform Engineeringを紹介しました。

LIFULLのプラットフォームを開発する我々KEELチームは、Kubernetesベースの内製PaaSであるKEELを開発・運用しながら、社内で汎用AI(仮)と呼ぶAutoGPT実装 keelai も開発しています。

そして、コードジェネレータを備えた keelctl、プラットフォームのユーザ体験を補完するChrome Extensionである keelext といった複数のチャネルを活かして、LLMを利用したPlatform Engineeringを進めてきました。

Slack Automationsを利用した疑似的なLLMノーコードツールやJupyter Notebookの提供では、利用者が自律的にLLMを用いた業務改善を行い更にそれを配布する仕組みも作ることで、社内のLLM活用にレバレッジを効かせることにも成功しています。

今後は根幹を担う汎用AI(仮)を中心に機能を増やしつつ、KubernetesクラスタであるKEEL自身のAIOps(?)を強化し、あらゆる面からLLMを使ってLIFULLの生産性向上に貢献していきたいと考えています。

もし興味を持っていただけた場合は、是非カジュアル面談をさせてください!

hrmos.co

hrmos.co