2025/01/09

作ってみよう:#22)スマート名刺管理 - 名刺情報の取得

GPT4o API 連携の最後の仕上げです。前回の API からのレスポンスから名刺情報を抽出する部分を開発します。スクリプトライブラリに作成したメイン関数 ReadNameCard の以下の部分ですね。

Public Function ReadNameCard(vnd As NotesDocument) As Boolean
         ・・・
   '3. 結果の JSON 内から名刺情報部分だけの JSON を取得
   Set jnavNameCard = xGetNameCard(jnavResponce)
   Call xSetRT(vnd, "JSON_NameCard", jnavNameCard.Stringify)

   '4. 名刺情報を文書に保存
   Call xSaveNameCard(jnavNameCard, vnd)

End Function


名刺情報の JSON 取得

まず、レスポンスの JSON の構造を確認します。

赤線の部分が AI が認識した名刺情報です。choices(配列) > message > content の順でノードを取得すればよいということですね。

以下の xGetNameCard 関数の戻り値は、名刺情報の JSON を NotesJSONNavigator のオブジェクトで返します。関数内では choices 配列の 1 つ目の要素を取得し、その先を処理を別のサブ関数で行っています。

Private Function xGetNameCard(vnav As NotesJSONNavigator) As NotesJSONNavigator
   Dim je As NotesJSONElement
   Dim ja As NotesJSONArray
   Dim jeChoice As NotesJSONElement
   Dim sResponce As String

   Set je = xGetElementByName_Nav(vnav, "choices")

   If Not (je Is Nothing) Then
      'choices は配列
      Set ja = je.Value

      If ja.Size > 0 Then
         '1件目を利用
         Set jeChoice = ja.GetFirstElement()
         sResponce = xGetResponce_Content(jeChoice)

         'JSON(テキスト)を NotesJSONNavigator のオブジェクトに変換
         Set xGetNameCard = xns.CreateJsonNavigator(sResponce)
      End If
   End If
End Function


xGetResponce_Content 関数は choices の 1 配列要素から message > content を取得して、その値を文字列で返す処理を担当しています。

Private Function xGetResponce_Content(vjeChoice As NotesJSONElement) As String
   Dim jobj As NotesJSONObject
   Dim jeMsg As NotesJSONElement
   Dim je As NotesJSONElement

   Dim sRole As String
   Dim sContent As String

   'message を取得
   Set jobj = vjeChoice.Value
   Set je = xGetElementByName_Obj(jobj, "message")

   'role を取得(今回は未使用)
   Set jobj = je.Value
   Set je = xGetElementByName_Obj(jobj, "role")
   sRole = je.Value

   'content を取得
    Set je = xGetElementByName_Obj(jobj, "content")
   sContent = je.Value

   xGetResponce_Content = sContent
End Function


名刺情報を文書にセット

上記関数で取得した JSON の構造を確認します。当たり前ですが、StructuredOutputs で指定した構造通りとなっていますね。


この JSON を文書にセットするのが xSaveNameCard 関数です。

Private Sub xSaveNameCard(vjnav As NotesJSONNavigator, vnd As NotesDocument)
   If Not(vjnav Is Nothing) Then
      Call xSetFld(vnd, "CompanyName_Full", vjnav)
      Call xSetFld(vnd, "CompanyName", vjnav)
      Call xSetFld(vnd, "CompanyName_Kn", vjnav)
      Call xSetFld(vnd, "Name", vjnav)
      Call xSetFld(vnd, "Name_Kn", vjnav)
      Call xSetFld(vnd, "Name_En", vjnav)
      Call xSetFld(vnd, "Dept", vjnav)
      Call xSetFld(vnd, "Role", vjnav)
      Call xSetFld(vnd, "Zip", vjnav)
      Call xSetFld(vnd, "Address", vjnav)
      Call xSetFld(vnd, "Tel", vjnav)
      Call xSetFld(vnd, "Mobile", vjnav)
      Call xSetFld(vnd, "Fax", vjnav)
      Call xSetFld(vnd, "eMail", vjnav)
      Call xSetFld(vnd, "URL", vjnav)
   End If
End Sub


1 要素分の処理はサブ関数 xSetFld で行っています。関数では、引数の指示に従って JSON から値を取得して、フィールドにセットしています。

なお、フィールド名と JSON ノード名は一致する前提としています。

Private Function xSetFld(vnd As NotesDocument, ByVal vsFld As String, vjnav As NotesJSONNavigator)
   Dim s As String

   s = xGetValueByName_Nav(vjnav, LCase(vsFld))
   Call vnd.ReplaceItemValue(vsFld, s)
End Function


汎用関数

今回紹介した関数内には、JSON の処理に関する汎用的な関数を利用しています。これまでの他の記事で紹介した関数が多いのですが、このアプリ内で利用しているものをまとめておきます。

スクリプトライブラリ lsReadNameCard に追加してください。

◇ NotesJSONNavigator から指定した名前のノードを返す

Private Function xGetElementByName_Nav(vjnav As NotesJSONNavigator, ByVal vsName As String) As NotesJSONElement
   Dim je As NotesJSONElement

   Set je = Nothing

   On Error GoTo ErrProc
   Set je = vjnav.GetElementByName(vsName)

ExitProc:
   Set xGetElementByName_Nav = je
   Exit Function

ErrProc:
   Resume ExitProc
End Function

◇ NotesJSONObject から指定した名前のノードを返す

Private Function xGetElementByName_Obj(vjobj As NotesJSONObject, ByVal vsName As String) As NotesJSONElement
   Dim je As NotesJSONElement

   Set je = Nothing

   On Error GoTo ErrProc
   Set je = vjobj.GetElementByName(vsName)

ExitProc:
   Set xGetElementByName_Obj = je
   Exit Function

ErrProc:
   Resume ExitProc
End Function

◇ NotesJSONNavigator から指定した名前のノードの値を返す

Private Function xGetValueByName_Nav(vjnav As NotesJSONNavigator, ByVal vsName As String) As String
   Dim je As NotesJSONElement

   On Error GoTo Proc_Err

   Set je = xGetElementByName_Nav(vjnav, vsName)

   If Not (je Is Nothing) Then
      xGetValueByName_Nav = je.Value
   End If

Proc_Exit:
   Exit Function

Proc_Err:
   Resume Proc_Exit
End Function


動作検証

それでは GPT4o API 連携機能の最終テストを行います。ReadNameCard 関数で、今回開発した部分のコメントを外し、有効化します。

Public Function ReadNameCard(vnd As NotesDocument) As Boolean
   Dim jnavRequest As NotesJSONNavigator
   Dim jnavResponce As NotesJSONNavigator
   Dim jnavNameCard As NotesJSONNavigator

   '1. API リクエスト時に送信する JSON を作成
   Set jnavRequest = xMakeRequest(vnd)
   'Call xSetRT(vnd, "JSON_Request", jnavRequest.Stringify)

   '2. API をコールし、結果の JSON を取得
   Set jnavResponce = xCallWebAPI(jnavRequest)
   Call xSetRT(vnd, "JSON_Responce", jnavResponce.Stringify)


   '3. 結果の JSON 内から名刺情報部分だけの JSON を取得
   Set jnavNameCard = xGetNameCard(jnavResponce)
   Call xSetRT(vnd, "JSON_NameCard", jnavNameCard.Stringify)


   '4. 名刺情報を文書に保存
   Call xSaveNameCard(jnavNameCard , vnd)

End Function

ノーツから新規で文書を作成、名刺の画像を貼り付けて、[名刺読込] ボタンをクリックしてテストします。今回はレスポンスと取得した名刺情報に JSON が出力されていれば成功です。あわせて登録情報タブの各項目が正しく表示されています。


次回の予定

これで GPT4o API 連携機能部分は完成です。次回は、ノーツアプリとしての仕上げ作業を行います。


前回 作ってみよう 次回


0 件のコメント:

コメントを投稿