Sample Python wordsets client

NLUaaS offers a fully-functional sample Python client application that you can download and use to perform wordset operations using the Wordset gRPC API. To run this client, you need:

Download the client zip file for Linux or Windows and extract its files into the same directory as the nuance directory that contains your proto files and Python stubs.

Python app file

Each sample client app package contains a common Python client application file, nlu_wordset_client.py. This file imports the generated Python stubs and contains the main application code. The client apps also include command line scripts to run the app easily on the respective platforms.

  View nlu_wordset_client.py  

Linux client

The Linux client zip file nlu-wordset-python-client.zip contains, in addition to the Python app file, two run scripts for the app:

  • wordset-nlu-client.sh: A bash shell script that passes the OAuth URL, client ID, and secret to the Python application as arguments so that it can manage the token generation itself.
  • wordset-nlu-token-client.sh: A bash shell script file that generates an access token from the client id and secret and then runs the application.
#!/bin/bash

echo "Setting CLIENT_ID and SECRET"

export CLIENT_ID="ENTER YOUR MIX CLIENT ID HERE"
export SECRET="ENTER YOUR MIX CLIENT SECRET HERE"

echo "CLIENT_ID: " $CLIENT_ID
echo ""
echo "URL encoding CLIENT_ID"
# URL encode the client id by converting ':' characters to '%3A'
CLIENT_ID=${CLIENT_ID//:/%3A}
echo ""
echo "Updated CLIENT_ID: "$CLIENT_ID
echo ""
#'?' matches any character and '//' tells bash to replace all matches to the asterisk
echo "SECRET: "${SECRET//?/*}
echo ""

python3 nlu_wordset_client.py compile --oauthURL "https://auth.crt.nuance.com/oauth2/token" \
    --clientID $CLIENT_ID --clientSecret $SECRET \
    --serverUrl "nlu.api.nuance.com" \
    --wordsetFile "$1" \
    --artifactUrn "$2" \
    --modelUrn "$3" \
    --metadata "$4"
#!/bin/bash

echo "Setting CLIENT_ID and SECRET"

export CLIENT_ID="ENTER YOUR MIX CLIENT ID HERE"
export SECRET="ENTER YOUR MIX CLIENT SECRET HERE"

echo "CLIENT_ID: " $CLIENT_ID
echo ""
echo "URL encoding CLIENT_ID"
# URL encode the client id by converting ':' characters to '%3A'
CLIENT_ID=${CLIENT_ID//:/%3A}
echo ""
echo "Updated CLIENT_ID: "$CLIENT_ID
echo ""
#'?' matches any character and '//' tells bash to replace all matches to the asterisk
echo "SECRET: "${SECRET//?/*}
echo ""

export TOKEN="`curl -s -u "$CLIENT_ID:$SECRET" "https://auth.crt.nuance.com/oauth2/token" \
-d "grant_type=client_credentials" -d "scope=nlu nlu.wordset" \
| python -c 'import sys, json; print(json.load(sys.stdin)["access_token"])'`"

python3 nlu_wordset_client.py compile --serverUrl "nlu.api.nuance.com" --token $TOKEN \
    --wordsetFile "$1" \
    --artifactUrn "$2" \
    --modelUrn "$3" \
    --metadata "$4"

Give the two shell scripts execute permission with chmod +x.

chmod +x *.sh

Windows client

The Windows client zip file nlu-wordset-python-client-win.zip contains, in addition to the Python app file, two run scripts for the app:

  • wordset-nlu-client.bat: A bash shell script that passes the OAuth URL, client ID, and secret to the Python application as arguments so that it can manage the token generation itself.
  • wordset-nlu-token-client.bat: A bash shell script file that generates an access token from the client id and secret and then runs the application.
@echo off
setlocal enabledelayedexpansion

echo Setting CLIENT_ID and SECRET

set CLIENT_ID=ENTER YOUR MIX CLIENT ID HERE
set SECRET=ENTER YOUR MIX CLIENT SECRET HERE

echo CLIENT_ID:  %CLIENT_ID%
echo.
echo URL encoding CLIENT_ID

rem URL encoding CLIENT_ID by converting colons (:) to %3A 
set CLIENT_ID=!CLIENT_ID::=%%3A!
echo.
echo Updated CLIENT_ID: %CLIENT_ID%
echo.

rem Masking secret before displaying on command line
set buildMask=
set num=0
set repl=*

:strMask_Loop
call set tmp=%%SECRET:~%num%,1%%%
set /a num+=1
if not "%tmp%" equ "" (
set buildMask=%repl%%buildMask%
goto strMask_Loop
)

echo SECRET: %buildMask%

python nlu_wordset_client.py compile --oauthURL https://auth.crt.nuance.com/oauth2/token ^
    --clientID %CLIENT_ID% --clientSecret %SECRET% ^
    --serverUrl nlu.api.nuance.com:443 ^
    --wordsetFile %1 ^
    --artifactUrn %2 ^
    --modelUrn %3 ^
    --metadata %4
@echo off
setlocal enabledelayedexpansion

echo Setting CLIENT_ID and SECRET

set CLIENT_ID=ENTER YOUR MIX CLIENT ID HERE
set SECRET=ENTER YOUR MIX CLIENT SECRET HERE

echo CLIENT_ID:  %CLIENT_ID%
echo.
echo URL encoding CLIENT_ID

rem URL encoding CLIENT_ID by converting colons (:) to %3A 
set CLIENT_ID=!CLIENT_ID::=%%3A!
echo.
echo Updated CLIENT_ID: %CLIENT_ID%
echo.

rem Masking secret before displaying on command line
set buildMask=
set num=0
set repl=*

:strMask_Loop
call set tmp=%%SECRET:~%num%,1%%%
set /a num+=1
if not "%tmp%" equ "" (
set buildMask=%repl%%buildMask%
goto strMask_Loop
)

echo SECRET: %buildMask%

set command=curl -s -u "%CLIENT_ID%:%SECRET%"  ^
-d "grant_type=client_credentials" -d "scope=nlu nlu.wordset" ^
"https://auth.crt.nuance.com/oauth2/token"

for /f "delims={}" %%a in ('%command%') do (
  for /f "tokens=1 delims=:, " %%b in ("%%a") do set key=%%b
  for /f "tokens=2 delims=:, " %%b in ("%%a") do set value=%%b
  goto done:
)

:done
rem Check if the token was found
if not !key!=="access_token" (
   echo Access token not found^^!
   pause
   exit
)

rem Remove quotes
set MY_TOKEN=!value:"=!

python nlu_wordset_client.py compile --serverUrl nlu.api.nuance.com:443 --token %MY_TOKEN% ^
    --wordsetFile %1 ^
    --artifactUrn %2 ^
    --modelUrn %3 ^
    --metadata %4

Client files

These are the resulting client files, above the nuance directory holding your Python stubs:

├── nlu_wordset_client.py
├── wordset-nlu-client.sh or wordset-nlu-client.bat
├── wordset-nlu-token-client.sh or wordset-nlu-token-client.bat
└── nuance
    ├── nlu
    │   ├── v1
    │   │   ├── runtime_pb2.py
    │   │   ├── runtime_pb2_grpc.py
    │   │   ├── runtime.proto
    │   │   ├── result_pb2.py
    │   │   ├── result.proto
    │   │   ├── interpretation-common_pb2.py
    │   │   ├── interpretation-common.proto
    │   │   ├── single-intent-interpretation_pb2.py
    │   │   ├── single-intent-interpretation.proto
    │   │   ├── multi-intent-interpretation_pb2.py
    │   │   └── multi-intent-interpretation.proto
    │   ├── wordset 
    │   │   └── v1beta1
    │   │       ├── wordset_pb2.py
    │   │       ├── wordset_grpc_pb2.py
    │   │       └── wordset.proto
    │   └── common
    │       └── v1beta1
    │           ├── job_pb2.py
    │           ├── job.proto
    │           ├── resource_pb2.py
    │           └── resource.proto
    └── rpc
        ├── error_details_pb2.py
        ├── error_details.proto
        ├── status_code_pb2.py
        ├── status_code.proto
        ├── status_pb2.py
        └── status.proto

Run Python client for help

For a quick check that the client is working, and to see the arguments it accepts, run it on Linux or Windows using the help (-h or --help) option.

See the results below and notice:

See the results below and notice:

  • -s, --serverUrl: URL for the NLU server. By default this is localhost:8080 but the sample scripts specify hosted Mix NLU at nlu.api.nuance.com.

  • Authorization: Include --oauthURL, --clientID, and --clientSecret. Alternatively, generate a token and use the (hidden) --token argument. The --oauthScope is set by default to nlu nlu.wordset and so does not need to be specified for the provided Python client, which does not require any other scopes.

  • --wordsetFile: a JSON file for the wordset.

  • --modelUrn: Mix URN for the NLU model.

  • --artifactUrn: Mix URN for compiled wordset.

  • --metadata and --clientData: wordset metadata and client data as key-value pairs.

$ python nlu_wordset_client.py -h
usage: client.py <command> [-options]

positional arguments:
  command                                   Command to execute [values: compile, get-metadata,
                                            delete] (default: compile)

options:
  -h, --help                                Show this help message and exit.
  --oauthURL [oauthUrl]                     OAuth 2.0 URL
  --clientID [clientID]                     OAuth 2.0 Client ID
  --clientSecret [clientSecret]             OAuth 2.0 Client Secret
  --oauthScope [oauthScope]                 OAuth 2.0 Scope, default=nlu nlu.wordset
  -s [serverUrl], --serverUrl [serverUrl]   NLU server URL, default=localhost:9090.
  --wordsetFile [file]                      Wordset JSON file.
  --artifactUrn [artifactUrn]               Compiled Wordset URN.
  --modelUrn [modelUrn]                     NLU Model URN.
  --metadata metadata [metadata ...]        Wordset metadata defined as one or more key:value pairs.
  --clientData clientData [clientData ...]  Client data defined as one or more key=value pairs.

Overview of the application

This sample Python wordsets app performs the following tasks:

  • Imports the the contents of the generated client stub files.
  • Collects parameters from the command line:
    • Wordset operation to perform (by default, compile)
    • NLUaaS server URL
    • A wordset JSON file name
    • URN for NLU model
    • (Optional) URN for a wordset
    • Wordset metadata and client data.
  • Sets parameters such as logging mode.
  • Obtains an OAuth token to access the service
  • Calls NLUaaS Wordset service on a secure channel (authorized by the token), sending the specified request.
  • Prints the results to JSON format.

Procedure

To run the app, perform the following steps.

Edit run script to add authorization credentials

NLUaaS is a hosted service on the Nuance Mix platform. To access this service, your client applications must be authorized with an access token generated by the OAuth 2 protocol.

In order to request a token, you need your Mix client ID and secret. With these credentials, you can request an access token in several ways.

The sample client supports two methods.

Let Python client generate token

The Python client includes token-generation code, checking first to see whether the token has expired. To use this method, pass your credentials and the location of the OAuth server in the --clientID, --clientSecret, and --oauthURL arguments. This is the preferred method.

Edit your run script to add your Mix client ID and secret.

#!/bin/bash 

echo "Setting CLIENT_ID and SECRET"

export CLIENT_ID="ENTER YOUR MIX CLIENT ID HERE"
export SECRET="ENTER YOUR MIX CLIENT SECRET HERE"
@echo off
setlocal enabledelayedexpansion

echo Setting CLIENT_ID and SECRET

set CLIENT_ID=ENTER YOUR MIX CLIENT ID HERE
set SECRET=ENTER YOUR MIX CLIENT SECRET HERE

Generate token manually

Alternatively, you may generate the token manually and pass it to the client as an environment variable in the --token argument.

This token expires after a short time (around 15 minutes) so must be regenerated frequently. Not however that the number of requests is limited for security reasons.

Similarly to the case of letting the client generate the token, edit the script to add your Mix client ID and secret.

#!/bin/bash 

echo "Setting CLIENT_ID and SECRET"

export CLIENT_ID="ENTER YOUR MIX CLIENT ID HERE"
export SECRET="ENTER YOUR MIX CLIENT SECRET HERE"
@echo off
setlocal enabledelayedexpansion

echo Setting CLIENT_ID and SECRET

set CLIENT_ID=ENTER YOUR MIX CLIENT ID HERE
set SECRET=ENTER YOUR MIX CLIENT SECRET HERE

The script takes the client ID and secret and uses them to make a curl call to the authorization service and obtain a token.

export TOKEN="`curl -s -u "$CLIENT_ID:$SECRET" "https://auth.crt.nuance.com/oauth2/token" \
-d "grant_type=client_credentials" -d "scope=nlu nlu.wordset" \
| python -c 'import sys, json; print(json.load(sys.stdin)["access_token"])'`"
set command=curl -s -u "%CLIENT_ID%:%SECRET%"  ^
-d "grant_type=client_credentials" -d "scope=nlu nlu.wordset" ^
"https://auth.crt.nuance.com/oauth2/token"

for /f "delims={}" %%a in ('%command%') do (
  for /f "tokens=1 delims=:, " %%b in ("%%a") do set key=%%b
  for /f "tokens=2 delims=:, " %%b in ("%%a") do set value=%%b
  goto done:
)

:done
rem Check if the token was found
if not !key!=="access_token" (
   echo Access token not found^^!
   pause
   exit
)

rem Remove quotes
set MY_TOKEN=!value:"=!

Note that the scope in the authorization request in the run script includes nlu.wordset as required to get a token giving access the NLUaaS API.

Run the client

Run the client from the shell script, passing it parameters.

With the run scripts edited to include valid authorization credentials, run the client from the Linux shell or Windows command line via the run-mix-client.sh shell script or run-mix-client.bat batch script. Pass in the wordsetFile, artifactUrn, NLU modelUrn, and metadata parameters as command line arguments:

wordset-nlu-client.sh wordsetFile artifactUrn modelUrn metadata
wordset-nlu-client.bat wordsetFile artifactUrn modelUrn metadata

So, for example:

wordset-nlu-client.sh "wordset.json" "urn:nuance-mix:tag:wordset:lang/bakery/item_names/eng-USA/mix.nlu" "urn:nuance-mix:tag:model/bakery/mix.nlu?=language=eng-USA"
wordset-nlu-client.bat "wordset.json" "urn:nuance-mix:tag:wordset:lang/bakery/item_names/eng-USA/mix.nlu" "urn:nuance-mix:tag:model/bakery/mix.nlu?=language=eng-USA"

Here is an example of the script output:

55 2021-03-30 14:18:18,855 DEBUG: Adding CallCredentials with token $TOKEN
59 2021-03-30 14:18:18,857 DEBUG: Creating secure gRPC channel
{
  "job_status_update": {
    "status": "JOB_STATUS_PROCESSING"
  },
  "request_status": {
    "status_code": "OK"
  }
}
{
  "job_status_update": {
    "status": "JOB_STATUS_COMPLETE"
  },
  "request_status": {
    "status_code": "OK"
  }
}

Here we show the details for the “client generates token” option using wordset-nlu-client.sh or wordset-nlu-client.bat. Details for the Linux and Windows token-generating run scripts are similar for the manual token generation option using wordset-nlu-token-client.sh or wordset-nlu-token-client.bat respectively. The scripts are structured such that the calls are identical—simply replace the name of the script file for the alternate script from the same platform client app.