10月18日に開催されました「クラウド研究会」の活動についてお伝えします。
つい先日(10月10日)に出荷されたばかりの Notes/Domino 10.0 ですが、そこには Notes アプリの開発者が待ちに待った機能の追加がありました。
それは LotusScript の新しいクラス「NotesHTTPRequest」です。
ノーツコンソーシアムのクラウド研究会として、これを検証の対象から外すことはできません!
といった訳で今回は、IBM Cloud の"AI"カテゴリにあります翻訳サービス「Language Translator」を Node-RED 経由で利用する Notes アプリケーションの検証(という名目で NotesHTTPRequest を使い倒す)に着手いたしました。

※事前に IBM Cloud のダッシュボードから「Node-RED Starter」と「Language Translator」のリソースを追加しています。
作成しましたのは Get と Post の2種類あります。
まずは Get 要求に対応した Node-RED のフローです。

入力となる最初のノード「http」では、メソッドに "GET"、フローの入り口となるURL に "/watsonLT" と指定しています①。
次のノード「function」では、httpノードで受けた内容から Language Translator に渡すパラメータを設定するため、次のように記述しています②。
msg.srclang = msg.payload.src;
msg.destlang = msg.payload.dest;
msg.payload = msg.payload.message;
return msg; |
各行のmsg.payloadの右にある文言 "src", "dest", "message"は、NotesHTTPRequest の Get で指定するURLの一部に、次のように設定されるパラメータです。
| https://<Node-REDのURL>/<フローの入り口に付けたURL>?src=【翻訳する文字列の言語】&dest=【翻訳後の言語】&message=【翻訳する文字列】 |
例えば、「I love Notes Domino」という英語を日本語に翻訳する場合、次のようになります。
| https://xxxxxxxxxx.mybluemix.net/watsonLT?src=en&dest=ja&message=I%20love%20Notes%20Domino. |
※「xxxxxxxxxx.mybluemix.net」は Node-RED のフローエディタを開いている時にブラウザの URL に表示されている /red/ の左側の文字列です。ここでパラメータとして渡す【翻訳する文字列】をURL エンコードしていることに注意してください。
続いて「Language Translator」ノードで翻訳③した後、結果を最後の出力ノード「http response」で戻します④。
上記のフローを利用する LotusScript として、フォーム上に作成したホットスポットボタンへ次のようなコードを設定しました。
|
Dim session As New NotesSession
Dim http As NotesHTTPRequest
Dim url As String
Dim notesmacro As String
Dim textEnglish As String
Dim textURLEncoded As String
Dim returnValue As Variant
textEnglish = "I love Notes Domino."
notesmacro = |@URLEncode("Domino";"| & textEnglish & |")| '①
res = Evaluate( notesmacro ) '②
textURLEncoded = res(0) '③
url = |https://xxxxxxxxxx.mybluemix.net/watsonLT?src=en&dest=ja&message=| & textURLEncoded '④
Set http = session.CreateHTTPRequest() '⑤
returnValue = http.Get(url) '⑥
Msgbox returnValue '⑦
|
ポイントだけご説明します。
①@URLEncodeという関数を使い、翻訳する文字列をURLへ埋め込むためURLエンコードします。その関数式(マクロ)を生成して変数「notesmacro」へ代入します。
②マクロを実行します。結果は変数「res」に配列で返ります。
③URLエンコード後の文字列を変数「textURLEncoded」へ代入します。
④パラメータ付きのURLを生成します。
⑤NotesHTTPRequest のインスタンスを作成します。
⑥URLへGetを要求し、結果を変数「returnValue」へ。
⑦翻訳結果を表示します。
ホットスポットボタンをクリックすると、"私はNotesドミノが好きです。"と翻訳されました。成功です!
なお Get の場合、URLをWebブラウザのアドレス欄へ投入することでも結果が得られます。

ところでこの Get の例では翻訳サービスへ渡したいパラメータが3つありました。それらを URL へ設定するので送信するデータが丸見えです。
「パラメータのデータ量が多い」、「秘匿情報を送りたい」、「ブックマークされたくない」といったような場合、 Get でなく Post を使うようです。
では Post で作成したサンプルを見ていきます。
Post と Get ではデータを受ける方法が変わりますのでフローを新たに作成しました。
まずはフロー図から。

入力となる最初のノード「http」では、メソッドに"POST"、フローの入り口となるURLに"/LSPost"と指定しています①。
次のノード「function」では、httpノードで受けた JSON 形式のデータから 次以降のノードに渡すパラメータを設定するため、次のように記述しています②。
msg.destlang = msg.payload.destlang;
msg.payload = decodeURI(msg.payload.sourceText);
return msg; |
2行目では翻訳したい文字列がURLエンコードされていることを想定していますのでデコードしています。
実は入力された文字列の言語を自動判定することができるノード「language identify」が用意されています。Get の例では入力の言語を予め指定しましたが、Post のサンプルでは自動判定することとしました③。
最もそれらしいと判定された言語が msg.lang.language に返ります。それを入力の言語として Language Translator が認識できるよう function ノードで設定します④。
msg.srclang = msg.lang.language;
return msg; |
そして⑤で翻訳した結果を返します⑥。
なお、Language Translator には翻訳可能な言語のペアがあるようです。現状では、英語から日本語への翻訳は可能ですがイタリア語から日本語へは翻訳できませんでした。翻訳できないペアの場合、フローのノードの下に Model not found と表示され、翻訳前の文字列がそのまま返りました。
上のフローを利用する LotusScript のサンプルです。
|
Dim session As New NotesSession
Dim http As NotesHTTPRequest
Dim url As String 'Node-RED の受け口となるURLを指定する
Dim sourceText As String
Dim notesmacro$ 'この変数にエンコードする@関数を生成する
Dim postValue As Variant
Dim returnValue As Variant
Dim res As Variant 'テキストをURLエンコードした結果を保持する変数
url = "https://xxxxxxxxxx.mybluemix.net/LSPost" '①
sourceText = "I love Notes Domino."
notesmacro = |@URLEncode("Domino";"| & sourceText & |")|
res = Evaluate( notesmacro ) '②
postValue = |{"sourceText":"| + res(0) + |", "destlang":"ja"}| '③
Set http = session.CreateHTTPRequest()
Call http.Setheaderfield("Content-Type", "application/json") '④
Call http.Setheaderfield("Accept", "application/json") '⑤
returnValue = http.Post(url, postValue) '⑥
MsgBox returnValue '⑦
|
Get に比べると Post に渡す URL はパラメータが無いぶんシンプルです。フローを作成した Node-RED の URL に、そのフローへの入り口となる /LSPost を追加した文字列を設定します①
翻訳する文字列をURLエンコードして②、次の様な JSON 形式のデータを変数「postValue」にセットします③。フローへ送信するパラメータは、翻訳する文字列「sourceText」と翻訳後の言語」の2つです。
{
"sourceText":"<URLエンコードされた文字列>",
"destlang":"ja"
} |
リクエスト④とレスポンス⑤のメディアタイプを指定して、リクエストを送信します。Get との違いはパラメータに URL の他、データが増えたことです。Node-RED のフローの結果が変数「returnValue」に戻ります。
⑦翻訳結果を表示します。
これらのサンプルでは翻訳したい文字列と翻訳後の言語をハードコーディングしましたが、Notes であれば「フォーム」を使用することでそれらをユーザーにタイプ(あるいは選択)させることが可能です。それらをプログラムに読み込むことや、フォーム上に翻訳結果を反映することも簡単に実現できます。
今回利用した IBM Cloud のサービスは翻訳以外にもいろいろと興味をそそられるものがあります。研究会のリーダーの発表では、Notesの文書に添付された写真を「Visual Recognition」で認識させ、写っているものを文字で表現するといったデモアプリが披露されました。無料の「ライトプラン」で利用できるサービスも増えてきたので、気軽に試すことができそうです。
これまでのNotes/Dominoのバージョンでは、外部の Web サービスと REST API を使って連携したい場合、 Java エージェントを使ったり、Windows 環境であれば XMLHTTP を利用するなど LotusScript だけで実現できずひと手間以上の手間をかけて実装していた訳ですが、V10 では LotusScript だけで外部連携することができることが確認できました。
今回で「使い倒す」つもりだったのですが Web サービスや Proxy などの認証の処理や、写真や動画などのバイナリデータの扱いといった部分の検証までは今回できませんでしたので、今後の課題でしょうか...
Notes アプリケーションの開発者としては NotesHTTPRequest は待ちに待った機能であり、今回はその検証ということで、興奮のあまり休憩時間も惜しんで試行錯誤していたことは内緒です。