AI can fly !!

AI がやりたい Web エンジニアのアウトプット (AI の知識は無い)

【最近のお仕事】direct チャットボット開発 (アーキテクチャと技術スタックの紹介)

Architecture

はじめに

今回取り上げるプロジェクトは、先日リリースした国産ビジネスチャット「direct / ダイレクト」のチャットボット開発第二弾です (第一弾は過去にリリース済み) 。

前回に引続き、アーキテクチャと技術スタックについて紹介します。

プロジェクトメンバは実務担当のマネージャーとエンジニア (私) 、あとは顔役の偉い人と今後の運用・保守を担当するエンジニアの合計 4 名です。

チャットボット開発第一弾での私の役割はプロトタイプ開発 & アドバイザー的な立ち位置でしたが、今回はメインの開発エンジニアとして参画しました。

開発期間は設計からリリースまで片手間で二か月程度、実質一か月半程になります。

詳細な仕様については守秘義務があるので記載しませんが、ざっくり言えば、 direct 上でユーザから問合せを受け付け、条件に合致する情報をデータベースから取得して表示するチャットボットを作りました。

アーキテクチャ

Web サービスとして提供されている direct 上で動作するチャットボットとして、サーバ仮想化プラットフォーム (VMware vSphere) 上に構成された仮想マシン (Alma Linux) の Docker 環境に、コンテナとして daab (direct agent assist bot) を構築しています。

ベースコンテナには Node.js の v16 を採用し、 daab の開発ツールとして提供されている daab SDK を使用して開発を行いました。

サーバ仮想化プラットフォーム外の同一ネットワークに存在する DB2 へは、 daab SDK にインストールした npm の IBM DB 用のドライバパッケージを介して接続しています。

仮想マシン内のコンテナ化されたチャットボット (daab) からオンプレのデータベース (DB2) と外部 Web サービス (direct) へ接続するので、ネットワーク関連にやや気を遣う必要はありますが、アーキテクチャ全体としてはシンプルな構成です。

技術スタック

チャットボット

daab (direct agent assist bot)

direct 上で動作するチャットボットの構築にあたっては、 direct の提供・開発元である L is B 社より、 direct とクラウドサービスや企業のシステムをつなぐための bot として daab (direct agent assist bot) が提供されています。

daab のベースになっているのは、 GitHub 社が開発し MIT ライセンスで公開している Hubot というチャットボット開発・実行フレームワークです。

この Hubot に direct 用の拡張が加えられたものが daab で、 Hubot の基本的な機能・スクリプトに加え、 direct 用の Adapter や様々な処理・イベントが追加されています。

direct4b.com

Hubot

Hubot は GitHub 社が開発した Node.js 上で bot を動かすためのフレームワークで、 MIT ライセンスで OSS として公開されています。

Hubot 自体は CoffeeScript で書かれており、 npm パッケージとして提供されていることから、 Node.js が動作する環境であれば手軽に導入することができます。

また、 Hubot は様々な Adapter と組み合わせることで、多くのサードパーティ製チャットツールに接続が可能という特徴があり、 daab には前述の通り direct 用の Adapter がバンドルされています。

bot としての動作は JavaScriptスクリプトを記述しますが、 npm で公開されている様々なパッケージを使用できることに加え、最終的に JavaScriptスクリプトが出力されていれば問題無いので、 TypeScript や CoffeeScript でコードを書くことも可能です。

hubot.github.com

hubot-redis-brain (Redis)

daab のベースである Hubot には、データ永続化の仕組みとして hubot-redis-brain が用意されており、 daab でも使用することができます。

hubot-redis-brain は内部的に Redis が使用されているシンプルな KVS です。

daab (Hubot) は基本的にステートレスなので、チャットのやり取りによる処理の分岐やユーザ毎のデータ保持などを目的として hubot-redis-brain を使用し、ステートフルな会話を実現しました。

github.com

daab SDK

direct 開発元の L is B 社からは、 daab 本体だけでなく daab を開発するための開発ツールとして daab SDK が提供されており、 daab の開発はこの SDK を使用して行います。

daab SDK には daab のスケルトン (開発プロジェクトのテンプレート) 作成や direct へのログインを行うための CLI がバンドルされているので、チャットボットの作成や実行を簡単に行うことができます。

ベースである Hubot と同様、チャットボット (daab) の動作は JavaScript で記述する必要がありますが、今回は daab SDK + TypeScript の組合せで開発を行いました。

daab.direct4b.com

TypeScript

今さら TypeScript の説明はしませんが、言わずと知れた AltJS のデファクトスタンダードJavaScript のスーパーセットである静的型付け言語です。

今回 daab の開発をするにあたって TypeScript 導入の決め手となったのは、 daab のベースとなっている Hubot の型情報 (@types/hubot) が存在することでした。

daab によって拡張されている部分の型宣言は存在しませんが、 Hubot の型情報に合わせてコードを書いていけば概ね問題はありません。

www.npmjs.com

データベース

IBM DB2

IBM 社が開発・販売する RDBMS で、 Oracle Database と並んで歴史あるデータベース管理システムです。

direct 上でのチャットをトリガーに daab から DB2 へ接続し、必要な情報を取得しています。

www.ibm.com

node-ibm_db

npm で公開されている IBM 社の DB へ接続するためのドライバパッケージで、 Node.js 上で動作します。

TypeScript の型情報として @types/ibm_db も公開されています。

github.com

www.npmjs.com

開発環境・開発ツール

もはやお決まりですが、 Windows10 Pro の WSL2 (Ubuntu) 上の Docker 環境に必要なコンテナを構築し、開発を行いました。

Node.js の公式イメージをベースとした daab 開発用コンテナ、 Redis 公式イメージをベースとした hubot-redis-brain 用コンテナ、 DB2 公式イメージを使用したコンテナの三つを Docker Compose で管理し、 daab 開発用コンテナからコンテナ間のネットワークを通じて各コンテナへ接続しています。

Visual Studio Code やそれに付随するパッケージ等々は省略します。

Prettier や ESLint は在って当たり前の空気みたいな存在です。

Prettier については 以前書いた記事 を参照ください。

ai-can-fly.hateblo.jp

ESLint はいつか記事にまとめると言いながら、全然その気が無いことがバレバレです。

A5:SQL Mk-2

GUI で DB のテーブルの確認や SQL 作成・実行が行える、高機能かつ軽量なフリーの SQL クライアントアプリです。

DB2 へのテストデータの登録や SQL の作成・動作確認などに使用しました。

a5m2.mmatsubara.com

IBM Data Server Driver for ODBC and CLI ソフトウェア

Windows 上で動作するアプリから DB2 へ接続するために必要な IBM 社から提供されている ODBC ドライバです。

入手するためには IBM のアカウントを作成する必要がありました…正直めんどい…

www.ibm.com

おわりに

今回のプロジェクトで作成したチャットボットは所謂ルールベース型と呼ばれるもので、ある一定の決まったシナリオ (フロー) に沿った動作のみを行うシンプルなチャットボットでした。

シンプルとはいえ、複数ユーザとのやり取りや想定外のチャットなどへの考慮も加えると、それなりに設計・実装を行う必要があります。

業務で使用するチャットボットの開発ということでなかなか勉強になりましたが、個人的にはそんなことよりも、本来 JavaScript で開発を行う想定の daab のコードを TypeScript で書くことができたというのが大きな収穫でしたw

フルスタックで開発を行っていると、フロントエンドは TypeScript でバックエンドが Python といった場合に言語が異なることによる脳内のスイッチングログが発生するのですが、バックエンドも TypeScript で書くことができればこの問題を解決できます。

ただ、 Google Cloud の Cloud Functions などの FaaS は置いておいて、弊社では Web アプリのバックエンドに Node.js を採用することがほとんど無いので、そもそも TypeScript でバックエンドコードを書くことができないという…

Deno の v1.0.0 が出て 2 年以上経ちますが、まだ Node.js に取って代わるような状況にはなっていないようなので、なんとか Deno には頑張ってもらいたいところ。

もうしばらくは Python も書かないといけないかなぁ… _(:ロ」∠)_