MOBILUS TECH BLOG

モビルスのプロダクト開発を支えるメンバーが 日々の開発現場の情報を発信します。

MOBI AGENTで使用している技術紹介

自己紹介
初めまして。Messaging-Tech Productの松本です。
MOBI AGENTのバックエンドの開発を約一年半ほど担当しています。
今回は、MOBI AGENTで使っている技術を紹介します。

 

MOBI AGENTとは                             
始めに、MOBI AGENTの紹介です。
MOBI AGENTは、コンタクトセンターに対応する顧客サポート向けの有人チャットシステムです。
WebやLINEなどのSNSアプリで顧客チャネルからチャットでの問い合わせ対応ができます。
また、チャットボット「MOBI BOT」と連携をして、シナリオを用いた自動応答に対応することもできます。
他の機能として、問い合わせメッセージの感情をオペレーター画面に表示したり、問い合わせ数や問い合わせが完了するまでの対応時間等の統計情報を表示するなど、コンタクトセンター向けの機能を有しています。

 

技術紹介
ここから、MOBI AGENTで使用している、技術やアーキテクチャを紹介します。
本題に入る前ですが、Go言語や、Hazelcastなどのミドルウェアを使っていたりしていますが、機能の一部であるため、今回は省略させていただきます。

 

Scala                                     
MOBI AGENTのバックエンドは、Scalaで記述されていて、全てAPIとして実装されています。Scalaは、オブジェクト指向関数型プログラミングの両方を備えた特徴があります。JVM上で動作するため、Java言語で書かれたライブラリを使用することが可能です。

MOBI AGENTに携わってからScalaを触りましたが、Javaの仕様より書き方が複数あり、最初のうちはIDEの補助なしだと難しい印象ですが、慣れるとエラーの制御がしやすいのと、「null」が含まれないので、安全で制御しやすい言語だと思っています。

 

MongoDB                                 

データベースは、MongoDBを使用しています。
MongoDBはドキュメント指向データベースで、データ構造を柔軟に変更できるため、仕様変更が頻繁に起こるシステムには最適です。

データの中身はJSONなので、Web開発者であれば、馴染みやすいです。リリース時に構造の変更が伴う場合、データのマイグレーションを行なっていますが、データ操作をJavaScriptで書けるので非常に便利です。
まだ、触ったことがない方は、試してみてはいかがでしょうか。

 

フロントエンド                                    

フロントエンドは、主にReactとTypeScriptを使用しています。               機能は、大まかに言うと3つの要素で構成されています。それぞれバックエンドAPIサーバーと通信をしながら、機能を提供しています。

フロントエンドの機能
1. 顧客の問い合わせが可能なWeb小窓
2. オペレータが顧客と対話するチャット画面
3. ダッシュボードや設定などの管理画面

問い合わせ時にフロントエンドのソースコードを見る時があるのですが、TypeScriptは型がはっきりしているのでわかりやすくていいと思います。

 

ンフラ                                           

インフラは、AWSで構築されています。
バックエンドは、主にAmazon EC2上で動作しており、一部、AWS FargateやLambdaで構成されています。他には、検索でAmazon OpenSearch Serviceを使っていたり、ログはCloudWatchで確認ができます。

一番使用しているのは、問い合わせ時のログ検索で、CloudWatchを使用しています。
検索で使用するクエリーは取っ付きにくいですが、速度は早くて助かっています。

 

まとめ
特徴や使用感などを交えて説明させていただきましたが、いかがでしたでしょうか。
大枠ですが、製品のシステムを理解できたかと思います。
この記事により、知らない技術に興味を持っていただけたら幸いです。

プロダクト・エンジニアリングLT会 第9回

ビルスでは、開発部門合同で毎月「プロダクト・エンジニアリングLT会」という全員で自由討論をする会を開催しています。9月22日に開催した第9回の様子をお届けします!今回、LT会に参加された方々の発表タイトルは以下の通りです。

1.ちょっとだけ業務効率が上がるかも知れないマメ知識の共有 (第2回)
 いつも使っているBacklogの、見過ごしがちな便利機能を紹介してもらいました。「知らなかった」の声が漏れ聞こえていました。

2.モビエージェントの基礎知識
 最近モビルスに入社したエンジニアや今までモビエージェントに関わっていないエンジニアのために、モビエージェントの歴史・特徴・基本構成やシステムアーキテクチャなどの基礎的な内容を解説しました。

3.各ソーシャルスタイルに響く判定会資料の作り方
 QAは日々の業務の中でさまざまな開発者や開発部門とのコミュニケーションが発生して製品の痛いところを突っついていかないといけなく、その中で開発プロセスを含む製品全般の品質向上を目指していく必要があります。
 その改善への取り組みを開発者にも響くようにコミュニケーションを取っていくことに参考にできるソーシャルスタイルを利用したコミュニケーションについての話がありました。
 30個程度の質問に答えるだけで下記の4つのどのタイプの傾向があるかが分かって、そのタイプごとに好むコミュニケーションの仕方があるので、そのコミュニケーションの仕方を資料などにうまく取り入れていくことでQAだけではなく開発側としても品質向上の意識をより強めていく好循環が回せるのではないかということです。
 面白そうなのでみんなで試してみたいですね。

4.MOBI VOICE過去障害を振り返り、コード視点での横展開活動の共有  
 障害の振り返りと共に、コード視点でどのように改善ができるのかをディスカッションしたチーム活動内容を共有しました。発表後の質疑応答が盛んに行われていました。

LT会の様子

会場からは「へー」「ほー」といった感嘆の声が聞こえてきました

うなずきながら聞いている方も

半数程度の方が自身のソーシャルスタイルを把握されていました

発表後の質問タイムでは、部門を超えた議論につながりました

ビルスでは、一緒に働く仲間を募集中です!
興味のある方は、ぜひ採用情報のページをご覧ください!

電話サービスのデプロイについて

MOBI VOICE担当の三谷智信です。
 
今回はMOBI VOICEという電話自動応答サービスで課題になるデプロイの話です。
MOBI VOICEはSIPを使用した電話自動応答サービスであり、通常のWEBサービスとは異なる考え方が必要になります。
 
SIPは通話セッションの確立や制御を可能にするプロトコルであり、その柔軟性と拡張性が電話自動応答サービスにおいて重要な役割を果たしていますが、大きくセッションの確立、変更、終了などの制御情報をやり取りする通信と音声データのやり取りをする通信に分けられます。
SIPメッセージをやり取りするポートは固定で決まっているのですが、音声データのやり取りをするポートは広いレンジでの通信が求められます。
 
サービス運用をするにあたっては、複数サーバを使用して可用性を担保した状態で行いたいのですが、どのように通信を制御したりサービスのデプロイを行うかということが課題になってきます。
特に電話サービスは急な呼量の増加も発生する可能性があるため、サーバのスケーリングは柔軟にできるようにしておきたいところです。
 
MOBI VOICEではAmazon ECS(Elastic Container Service)を採用しオートスケーリングを実現し、需要の変動に柔軟に対応しています。
単一のポートだけ考えればよいだけならロードバランサーを使用し、オートスケーリング設定と合わせてリクエストを制御するという構成がよくあるのですが、広範なポートレンジの場合ロードバランサーだけで制御はできません。

一般のWEBサーバ
そこで動的なIPアドレス変更に対応するため、MOBI VOICEはAWSのCloudWatchEventとLambdaとRoute 53を組み合わせて利用しています。この組み合わせにより、起動中のサーバのIPアドレスを動的に制御することが可能です。
CloudWatchEventでECSのタスクの状態がSTOPPED or RUNNINGになったらLambdaを実行するよう設定し、LambdaのロジックでECSのタスク情報から新たに立ち上がったサーバのIPを取得し、Route53の該当FQDNにIPを追加登録する処理を行っています(途中色々端折って書いています)。

SIP通信環境でのデプロイ
 
デプロイで次に問題になってくるのが、電話中のお客様をどうするかというものです。
電話自動応答サービスという都合上、通話中のお客様のセッションをぶつ切りにすることはできず、一通りの通話を終えるまでセッションを維持する必要があります。
そのため、MOBI VOICEではBlue/Greenデプロイを採用しています。
Blue/Greenデプロイとは、新旧など2系統のサーバ群が同時に混在する環境を構築した後、ロードバランサー等によるルーティング制御によってトラフィックを切り替え、ダウンタイム無しで環境を切り替えることですが、このルーティング切り替えを上記Lambdaの機構で行っています。
デプロイ前のバージョンのサーバは一定期間稼働させたままにするため、通話中の電話はつながったままにし、新しいセッションは新しくデプロイしたサーバに送ることができます。
これにより、MOBI VOICEで無停止でのデプロイが可能になりました。

Blue/Greenでのデプロイ
 
今後はPBX連携なども進めているため、より電話の通信環境パターンが増え、複雑になっていくことが予想されます。特に通信環境要件によってはIPレンジの固定化が必要だったり、特定IPに固定する必要が出てきたりすると思います。今のデプロイ方法だけでは対処できない可能性も出てくるため、環境ごとにより可用性が高く運用に支障のないデプロイ方法が必要になってきます。
今後も環境ごとに最善なデプロイ方法を模索していきたいと思います。
 
ビルスでは、一緒に働く仲間を募集中です!
興味のある方は、ぜひ採用情報のページをご覧ください!
 
 
 
 
 
 

プロダクト・エンジニアリングLT会 第8回

ビルスでは、開発部門合同で毎月「プロダクト・エンジニアリングLT会」という全員で自由討論をする会を開催しています。8月18日に開催した第8回の様子をお届けします!今回、LT会に参加された方々の発表タイトルは以下の通りです。

1.コンポーネント分割の進め方

ソフトウェアアーキテクチャ・ハードパーツという書籍で学んだ知見をもとに、コンポーネントの分割アプローチと現場で導入する際の注意点などを紹介しました。実際にありそうなサービスを元に、分割前後を図でわかりやすく説明しました。

2.相手を知ってミスコミュニケーションを防ごう〜QAの生態編〜

開発とQA間、また各製品間、もっと広くは社内全体で情報共有の認識相違を防ぐためのコミュニケーションのあり方について考えてみました。

3.Le Trompe-l’œil, l’Illusion, et la Proposition~ だまし絵と錯覚と命題~

業務遂行上の思い込みが発生し得る理由を「だまし絵と錯覚と命題」の例を使って実体験しながら、業務でのミスを防げる方法について参加者全員で考えました。

4.バグってた!検出バグ全部集合~

4月〜8月に実施したQAの検証レポートをもとに、QAにて新たに取り組んでいる様々な観点での分析を行い、その分析結果を関係者に共有する時間を持ちました。

LT会の様子

ビルスでは、一緒に働く仲間を募集中です!
興味のある方は、ぜひ採用情報のページをご覧ください!

プロダクト・エンジニアリングLT会 第7回

ビルスでは、開発部門合同で毎月「プロダクト・エンジニアリングLT会」という全員で自由討論をする会を開催しています。先月7月24日に開催した第7回の様子をお届けします!今回、LT会に参加された方々の発表タイトルは以下の通りです。

1.QAチームをゆる~くQAする

QA業務の理解(復習)を深めるとともに普段関わらないメンバーに向けて親近感を感じてもらい意思疎通をより深めていくためのQAチームを紹介しました。

2.You Don’t Know MBA Yet

モビエージェントをもっと知るためにエンジニア全員でクイズ大会をしました!
モビエージェントをより深く知ることができ、かつクイズ形式で楽しく学ぶことができました。

3.SecureMFAの今までの開発について

SecureMFAというサービスの概要と今まで歩んできた開発ヒストリーの紹介をしてから、システムのアーキテクチャに基づいたデータフローを説明しました。
 そして、今後やりたいことと共に課題を問いかけして他開発者からのアイデアを募りました。

4.本の紹介『運動脳』 

人類が誕生した頃と現代の人間の違いから、我々モビルスエンジニアがどうしたらより良いエンジニアリングができるか?を面白おかしく… そして本題がフットサル部への勧誘へ(笑)

 

LT会の様子

QAの目指す姿がよく分かりました!

クイズ形式での発表。全問正解の強者もいました。

今までの軌跡を振り返りました!

サバンナにタイムスリップする楽しい仕掛けの発表

ビルスでは、一緒に働く仲間を募集中です!
興味のある方は、ぜひ採用情報のページをご覧ください!




 

CSSのline-heightの話

UIデザインを担当している三谷(佑)です。
ビルスでは月に一度、社内LT会があり、先日line-heightに関する話をしました(プロダクト・エンジニアリングLT会 第5回)。line-heightは文字の歴史的経緯から複雑で、どういった振る舞いをするプロパティなのか理解するのが大変です。

www.figma.com

こちらは2019年にfigmaが公開したline-heightについての素晴らしい記事で、活字組版からデジタルに至るまでが紹介されています。このタイミングでfigma内でのline-heightの仕様も変更されたそうです。
ビルスでは画面制作にfigmaを使用していますので、line-heightの解説とfigmaのツール内でのline-heightの扱いについて理解をしておくと、デザイナー・エンジニア双方での認識合わせがスムーズになります。
下記に要点と制作時に注意する点をまとめました。

line-heightとは

  • CSS のプロパティで、行ボックスの高さを設定します。(行ボックスの中に複数のインラインボックスを含む場合、インラインボックスの高さはline-heightによって決まります。)
  • line-height:100%;、またはline-height:1;の行ボックスの高さは、フォントサイズの100%、つまりフォントサイズ20pxの行ボックスの高さは20pxになります。
  • フォントサイズと「line-height」の差を「レディング」と呼び、レディングの半分をハーフ・レディングと呼び、文字の上下に分散されます。

参考:「MDN Web Docsの行ボックス(※)とは」                

※行ボックスは、テキストの各行を包むボックスのことです

developer.mozilla.org

コーディング時の注意点

  • line-height の値は単位をつけない(親要素の値が継承され意図しない結果になるため)
  • アクセシビリティを考慮して値は1.5 以上を推奨

参考:MDN Web Docsのline-height   

主要な段落コンテンツでは、 line-height の値が 1.5 以上になるようにしてください。これは弱視の人や、認知障碍を負った人に有用です。ページがテキストの寸法が大きくなるように拡大した場合、単位なしの値を使用すれば行の高さも同じ割合で拡大します。developer.mozilla.org

figma制作時の注意点

  • ツール内で指定できるのは、%とpxとautoになります。
  • autoを指定するとDev Modeで見た時に、line-height: normal;になります。
  • Dev Modeで見たときの単位を変更できないので、単位をつけない値を入れられないことに注意してください。

参考:MDN Web Docsのline-height(再掲)  

  • normal                                   ユーザーエージェントに依存します。デスクトップブラウザ (Firefox を含む) は 要素のfont-family によって決まる、おおよそ 1.2 という既定値を使いますdeveloper.mozilla.org

おわりに

今回はline-heightを中心にまとめました。レイアウトへの影響が大きいプロパティですので気をつけて扱いたいですね。

 

ビルスでは、一緒に働く仲間を募集中です!

興味のある方は、ぜひ採用情報のページをご覧ください!

LLMの精度を向上するためのセマンティック検索

今回のテックブログを担当するMooA(※)開発室の李と申します。​

※MooA(ムーア)とは、モビルスが独自開発するオペレーション支援AIで、コンタクトセンターのオペレータやスーパーバイザーの業務をサポートするAIシステムです。

 

最近、大規模言語モデル(Large Language Models、以下LLM)の活用例が増えています。セマンティック検索(意味検索)を組み合わせることで、LLMはより高度で精度の高い応答や情報提供が可能となります。今回のブログでは、セマンティック検索とRedisを使って、LLMがより高度で精度の高い応答を実現する方法を紹介します。​

セマンティック検索とは

セマンティック検索(意味検索)は、情報検索の方法の一つであり、単純なキーワードの一致だけでなく、意味や関連性に基づいて情報を検索・取得する技術です。従来のキーワードベースの検索エンジンでは、単語やフレーズの一致を重視して結果を返すため、検索クエリの意図を完全に理解することができませんでした。しかし、セマンティック検索では、ユーザーの意図をより深く理解し、関連性の高い情報を提供することができます。

​ セマンティック検索は、自然言語処理(Natural Language Processing)や機械学習(Machine Learning)の技術を活用しています。文脈や意味に基づいた検索クエリの解釈を行い、関連するドキュメントや情報源を特定します。これにより、キーワードの一致だけでなく、文章の意味や関連性を考慮した検索結果が得られます。

​ドキュメントの検索を利用する際、例えばユーザーが「apple」というキーワードで検索する場合、従来のキーワードベースの検索エンジンではApple社やリンゴに関連する情報を返しますが、セマンティック検索では文脈や意味を解釈し、キーワード「apple」と一致する情報だけでなく、オレンジやパイナップルなどの「果物」に関連する情報も提供することができます。

また、セマンティック検索はサジェストシステムにおいても活用されます。例えば、ユーザーが入力している途中のキーワードに基づいて、セマンティックサーチは文脈や意味を理解し、次に入力される可能性の高い単語やフレーズを予測します。たとえば、ユーザーが「スマート」と入力した場合、セマンティックサーチは「スマートフォン」、「スマートウォッチ」、「スマートホーム」といった関連キーワードを提案します。​

LLMとの組み合わせ

セマンティック検索を使って検索結果を絞り込み、関連性の高い文書や情報を抽出します。そして、抽出された情報をLLMに与えることで、LLMがより適切な文や回答を生成できます。セマンティック検索が文脈や意味を考慮して情報を絞り込んでいるため、それを基にしたLLMの応答や生成結果は、より意味的に優れたものとなる可能性があります。​

Redisとは

RedisはC言語で開発された、Open Source Key-Value in-memory databaseです。ちょっと修飾語が多いと感じませんか?(笑)それでは、一つずつ紹介していきましょう。

‐ Open Source                      

Open Sourceとは、無償で一般公開される「ソースコード」のことです。つまり、Redisは無料のソフトウェアとなります。RedisのライセンスはBSD 3-Clauseなので、商用利用も可能となります。

‐ Key-Value database                   

MySQLなどのリレーショナルデータベースでは、データは構造化されたテーブルやカラムに格納されていますが、RedisなどのKey-Valueデータベースは、KeyとValueのペアのコレクションとしてデータを格納します。また、Keyは一意の識別子として機能し、KeyとValueのどちらも、単純なオブジェクトから複雑な複合オブジェクトまで、何であっても構いません。

‐ In-memory database                  

Redisは、メモリ上にデータを保存することで、非常に高速な書き込みと読み込みが可能となります。また、ディスク上にデータを永続化し、リストアも容易に行うことができます。

Redisは、データストレージエンジンである、上記の問題(大量の複雑なハッシュテーブルを保存・共有など)を非常に簡単に解決し、実装することができます。​

Redisのデータタイプ

Redisには、いくつのデータタイプがあり、以下はでよく使われているデータタイプを紹介します。

  • stringは、Redisの基本のデータタイプであり、1つのkeyに1つのvalueが対応します。Valueは文字列だけでなく、数値でも可能です。Redisのstringはバイナリセーフであり、jpg画像やシリアライズされたオブジェクトなど、あらゆるデータを格納することができます。Redisのstringは最大512Mのvalueを格納できます。
  • hashは、Redisのkeyとvalueマッピングで、特にオブジェクトの保存に適しています。
  •  listは、文字列を挿入順に並べたものです。要素はリストの先頭(左)または末尾(右)に追加できます。Twitterのフォローリストやファンリストなど、さまざまなシナリオで使用されます。Redisは、listに対してpushとpopの操作を提供し、セグメントを操作するためのAPIも提供しているので、セグメントの要素を直接検索したり削除したりすることができます。​
  • setは、文字列型の順序のないコレクションであり、listとは異なるのは、setには重複要素がないことです。​
  • sorted setは、与えられたランキングスコアによって、自動的にソートされます。sorted setにも重複要素がありません。​

※上記以外にも、Streams, Geospatial indexes, Bitmaps, Bitfields, HyperLogLogデータタイプもあります。

Vector Similarity Search(ベクトル類似度検索)を紹介する前に、まずVector Similarity(ベクトル類似度)を紹介しましょう。簡単に言えば、ベクトルは数字のリストだと考えてください。Vector Similarityは2つ以上のベクトルがどれだけ違うか(似ているか)を表す尺度です。

Vector Similarity Searchはセマンティック検索(Semantic Search)の一つの手法として使用することができます。ベクトル類似度検索は、ベクトル表現を使用して文書やクエリの類似性を計算し、関連性の高い情報を検索する手法です。この手法では、文書やクエリをベクトル空間に埋め込み、ベクトル間の距離や類似性を計算することで、意味的な関連性を捉えます。

Redisでは、Euclidean、Inner Product、そしてCosine Similarityなどのベクトル類似度の計算をサポートしています。​

ベクトル類似度で一番理解しやすいCosine Similarityを紹介しましょう。例えば、上記の図の中にVector 1とVector 3のなす角が Vector 1 とVector 2のなす角より大きいので、Vector 1 とVector 2のなす角のcosine値はVector 1 とVector 2のなす角のcosine値より大きい、それは「Vector 1とVector 2の類似度はVector 1とVector 3の類似度より大きい」ということを意味します。

Embeddings

Embeddingsは、テキスト、画像、音声などのデータを数値ベクトルの形式に変換する手法やモデルです。これにより、テキストデータを機械学習アルゴリズムに入力できるようになります。

具体的には、単語や文章を低次元のベクトル空間にマッピングします。これにより、単語や文章の意味や関係性を数値表現として捉えることができます。例えば、同義語間の距離が近くなるようなベクトル表現を学習することができます。

そのため、上記のデータをベクトル表現に変換するためのモデルは「Embeddings Model」と呼ばれています。テキスト専用のEmbeddings Modelを例として説明すると、一般的には、Embeddings Modelは大量のデータ(コーパスなど)を用いて訓練されます。有名なテキストEmbeddings Modelには、Word2Vec、GloVe、BERTなどがあります。

下記の図のように、Embedding Modelを使えれば、テキスト、画像、音声などのデータを埋め込み空間に変換することはできます。変換したベクトルとデータ両方もRedisでの保存ができます。

下記の図はユーザーがある情報を検索する際の流れを表わしています。もしユーザーが「○○の使い方を教えてください。」と検索すると、この検索内容はまずEmbedding Modelでベクトルを変換して、Redisを使って検索内容のベクトルと保存したデータのベクトルの類似度を算出することで、関連するデータを取得できます。取得されたデータを検索内容と一緒にLLMに入力すれば、期待する答えの生成ができます。

こんなワークフローにより、Redisでデータのベクトルを保存して、検索の結果をLLMに提供することで、精度と質の高い応答や情報提供が可能となります。

おわりに

今回は、LLMの精度を向上するために、セマンティック検索との組み合わせを紹介しました。また、Redisというデータベースをセマンティック検索がサポートし、その検索結果をLLMで合わせて使うことができる可能性も紹介しました。

(参考)

 

ビルスでは、一緒に働く仲間を募集中です!

興味のある方は、ぜひ採用情報のページをご覧ください!