Delphi で gRPC を使う Google Cloud Natural Language

· コンポーネント

Google Cloud Natural Language は、構造化されていないテキストを読み取り、そこに何が含まれているかを教えてくれます。ドキュメント全体の感情を測定し、言及されている人物、場所、組織をエンティティとして抽出し、テキストをコンテンツ分類体系に分類します。sgcWebSockets Enterprise エディションには TsgcGRPCClient の上に構築された型付き Natural Language gRPC クライアントが付属しているため、外部の gRPC ランタイムなしで、Delphi や C++Builder から直接 language.googleapis.com サービスにアクセスできます。

仕組み

Natural Language API は gRPC サービスとして公開されており、gRPC は HTTP/2 上でフレーミングされた Protocol Buffers メッセージです。sgcWebSockets には完全な HTTP/2 スタックがすでに付属しているため、gRPC クライアントは TLS 経由で language.googleapis.com:443 に向けた TsgcHTTP2Client トランスポート上に配置されます。TsgcGRPCClient がフレーミング、コンテンツタイプ、ステータストレーラーを処理し、型付きユニット sgcGRPC_Google_Language がリクエストとレスポンスのメッセージを処理します。

各リクエストはドキュメントをラップします。分析するテキストに加えて、その種類(プレーンテキストまたは HTML)と省略可能な言語ヒントです。型付きクラスは、そのドキュメントを API が期待する正確な Protocol Buffers のワイヤレイアウトにシリアライズし、レスポンスをすぐに読み取れるプロパティに解析します。protobuf を手作業で組み立てたり、フィールド番号を追ったりすることは一切ありません。

認証には Google Cloud サービスアカウントを使用します。自己署名のサービスアカウント JWT がベアラートークンと交換され、すべての呼び出しで gRPC メタデータとして送信されます。そのトークンはオーディエンスにバインドされるため、language.googleapis.com に受け入れられるよう、JWT は Natural Language エンドポイントに対して発行されます。

クライアントのセットアップ

Natural Language ホスト用の HTTP/2 トランスポートを作成し、それに TsgcGRPCClient をアタッチして、バイナリ protobuf コンテンツタイプを選択します。サービスアカウントから取得したベアラートークンは DefaultMetadata に標準的な authorization ヘッダーとして追加され、すべてのリクエストに付随します。

uses
  sgcHTTP2_Client, sgcGRPC_Client, sgcGRPC_Types, sgcGRPC_Google_Language;

var
  HTTP2: TsgcHTTP2Client;
  GRPC: TsgcGRPCClient;
begin
  HTTP2 := TsgcHTTP2Client.Create(nil);
  HTTP2.Host := 'language.googleapis.com';
  HTTP2.Port := 443;
  HTTP2.TLS  := True;

  GRPC := TsgcGRPCClient.Create(nil);
  GRPC.Client := HTTP2;
  GRPC.ChannelOptions.ContentType := grpcProto;
  GRPC.ChannelOptions.Compression := grpcNoCompression;

  // bearer token from the service-account JWT exchange
  GRPC.DefaultMetadata.Add('authorization', 'Bearer ' + Token);

  HTTP2.Active := True;
end;

感情の分析

感情分析は、-1.0(ネガティブ)から +1.0(ポジティブ)までの感情スコアと、ドキュメントがどれだけ感情的な内容を持つかを反映する大きさを報告します。TsgcGRPCLanguageAnalyzeSentimentRequest を構築し、ドキュメントの内容を設定し、LanguageServiceAnalyzeSentiment メソッドを呼び出してから、レスポンスのバイト列を型付きレスポンスに読み込みます。

var
  oRequest: TsgcGRPCLanguageAnalyzeSentimentRequest;
  oResponse: TsgcGRPCResponse;
  oResult: TsgcGRPCLanguageAnalyzeSentimentResponse;
begin
  oRequest := TsgcGRPCLanguageAnalyzeSentimentRequest.Create;
  try
    oRequest.Document.DocType := 1; // PLAIN_TEXT
    oRequest.Document.Content := 'sgcWebSockets makes gRPC in Delphi easy.';

    oResponse := GRPC.Call('google.cloud.language.v1.LanguageService',
      'AnalyzeSentiment', oRequest.ToBytes);

    if oResponse.StatusCode = grpcOK then
    begin
      oResult := TsgcGRPCLanguageAnalyzeSentimentResponse.Create;
      try
        oResult.LoadFromBytes(oResponse.Data);
        ShowMessage('Score: ' + FloatToStr(oResult.DocumentSentiment.Score) +
          '  Magnitude: ' + FloatToStr(oResult.DocumentSentiment.Magnitude));
      finally
        oResult.Free;
      end;
    end;
  finally
    oRequest.Free;
  end;
end;

エンティティの抽出

エンティティ分析は、ドキュメントが語っている重要なものを返します。レスポンスはエンティティのリストで、各エンティティには NameEntityType(人物、場所、組織など)、そしてそのエンティティがテキストの中心にどれだけ近いかをランク付けする Salience スコアが含まれます。型付きレスポンスは、順に処理できるインデックス付きリストを提供します。

var
  oRequest: TsgcGRPCLanguageAnalyzeEntitiesRequest;
  oResponse: TsgcGRPCResponse;
  oResult: TsgcGRPCLanguageAnalyzeEntitiesResponse;
  i: Integer;
begin
  oRequest := TsgcGRPCLanguageAnalyzeEntitiesRequest.Create;
  try
    oRequest.Document.DocType := 1; // PLAIN_TEXT
    oRequest.Document.Content := Memo1.Text;

    oResponse := GRPC.Call('google.cloud.language.v1.LanguageService',
      'AnalyzeEntities', oRequest.ToBytes);

    oResult := TsgcGRPCLanguageAnalyzeEntitiesResponse.Create;
    try
      oResult.LoadFromBytes(oResponse.Data);
      for i := 0 to oResult.EntityCount - 1 do
        Memo2.Lines.Add(oResult.Entity(i).Name + ' (type ' +
          IntToStr(oResult.Entity(i).EntityType) + ', salience ' +
          FloatToStr(oResult.Entity(i).Salience) + ')');
    finally
      oResult.Free;
    end;
  finally
    oRequest.Free;
  end;
end;

テキストの分類

コンテンツ分類は、ドキュメントを Google のカテゴリ分類体系に振り分け、それぞれ /Computers & Electronics/Software のような NameConfidence 値を持つカテゴリのリストを返します。パターンは同じです。TsgcGRPCLanguageClassifyTextRequest を構築し、ClassifyText を呼び出してから、CategoryCountCategory(i)TsgcGRPCLanguageClassifyTextResponse からカテゴリを読み取ります。分類がうまく機能するにはそれなりの量のテキストが必要なので、1 文だけではなくもっと多くを与えてください。

提供状況

Natural Language gRPC クライアントは sgcWebSockets Enterprise エディションの一部で、Delphi と C++Builder にわたり Windows、macOS、Linux、iOS、Android で動作します。すぐに実行できる完全なサンプルは Demos\21.GRPC\14.Natural_Language にあり、基盤となるクライアントは gRPC Client 製品ページに記載されています。

ご質問やご意見はありますか? お問い合わせください。コードを書いた本人から返信いたします。