IBM Watson provides a set of industry leading AI services for conversation, natural language processing, speech recognition / synthesis and other purposes.
ABAP SDK for IBM Watson Release 2.0.0 is available now, which is an open source community project for integrating IBM Watson services in SAP applications using pure ABAP language.
This blog post is a step-by-step tutorial for implementing an ABAP program for entity detection. IBM Watson Natural Language Understanding (NLU) is used to extract entities such as
person and
location from a document.
Although this tutorial focuses on NLU, other IBM Watson services can be utilized similarly. Thus, the description here can be used as a blueprint for integrating any IBM Watson service into an ABAP application.
Instantiate the IBM Watson Service
IBM Cloud is a Software-as-a-Service platform that offers a high amount of services, including AI and Machine Learning services. It is located at
cloud.ibm.com
If you do not yet have an IBM Cloud account, create one. A free account is sufficient to complete this tutorial.
Login to IBM Cloud. On the dashboard, click button
Create Resource, search the catalog for "nlu" and click the
Natural Language Understanding tile.
The IBM Watson services offer multiple plans including a free plan that can be used for testing. Select the
Lite plan here. You may also want to adjust the
Service Location and the Service name. Afterwards agree to the licenses agreements by checking the corresponding box and click button
Create.
The service is instantiated immediately.
To use the NLU service within an ABAP application, you must know the service credentials. They consist of an
API Key and a
URL and can be displayed on the
Manage view. You will need them later in your ABAP program to access the service instance.
Installing the ABAP SDK for IBM Watson
The ABAP SDK for IBM Watson is available as public Github repository
Throughout this blog we will work on the BTP ABAP environment. If you are working with an on-prem system, follow instructions on
https://docs.abapgit.org.
If not already done, install the abapGit plugin, see
https://developers.sap.com/tutorials/abap-install-abapgit-plugin.html.
Open the abapGit Repository view and click on the
plus sign (new abapGit Repository). Enter URI from above and click
Next. Choose master branch, enter ZIBMC for
Package name, check
Pull after link and click
Next. Choose
Folder Logic PREFIX and click
Next. Select an existing transport request or
Create a new request and click
Finish. Select all objects for pull and click
Finish. Wait until status turns
Pulled successfully. (Refresh the view to see the current status.)
After the pull has completed, package ZIBMC contains all objects of the ABAP SDK for IBM Watson. Activate all these objects.
Using the ABAP SDK for IBM Watson with a custom ABAP program
Now you are ready to exploit the ABAP SDK with your own ABAP programs.
As an example you will implement a console application that extract entities from a given text input.
First create a new ABAP package ZWATSON under structure package
ZLOCAL.
Create a new ABAP class ZWATSON_NLU in package ZWATSON and add interface IF_OO_ADT_CLASSRUN to it.
All ABAP code that is referred to in the following must be added to method
main of class ZWATSON_NLU.
Instantiate ABAP class for IBM Watson Service
You must instantiate an ABAP class that provides an interface to your individual IBM Watson service instance. Since you are using the NLU service, the corresponding ABAP class is
zcl_ibmc_nat_lang_undrstnd_v1. You find the ABAP class name for each IBM Watson service and detailed descriptions in the online reference at
https://watson-developer-cloud.github.io/abap-sdk-nwas
Add an appropriate data declaration to your program.
DATA: lo_nlu TYPE REF TO zcl_ibmc_nat_lang_undrstnd_v1.
Call factory method
zcl_ibmc_service_ext=>get_instance to instantiate the ABAP class. This method requires as parameter the IBM Watson service credentials (host and API key) for your individual IBM Watson service that you have instantiate at IBM Cloud before. Also, you must specify the service API version as parameter.
The factory method returns a reference to the instantiated ABAP class. Be aware that the class type is determined by the type of the importing parameter which has been specified by the explicit data declaration before. Therefore, you must not use implicit data declaration here.
zcl_ibmc_service_ext=>get_instance(
EXPORTING
i_host = 'https://api.eu-de.natural-language-understanding.watson.cloud.ibm.com/instances/cf89a...'
i_apikey = 'SZiPLlV...'
i_version = '2022-04-07'
IMPORTING
eo_instance = lo_nlu ).
Invoke IBM Watson service API endpoint
You want to call IBM Watson service API endpoint
analyze to run the entity detection on the input. The IBM Watson service requires the input as a JSON object. For details, see the IBM Watson service reference
https://cloud.ibm.com/apidocs/natural-language-understanding#analyze.
{ "text": "...",
"features": {
"entities": { }
}
The ABAP SDK for IBM Watson provides the ABAP class method
analyze that represents an ABAP interface to the IBM Watson service API endpoint and transparently converts JSON data to ABAP structures and vice versa. Suitable ABAP types for data exchange are provided as well. Here ABAP structure type
zcl_ibmc_nat_lang_undrstand_v1=>t_parameters represents the data structure that is required by IBM Watson service API endpoint
analyze and is therefore the type of the input parameter of ABAP class method
analyze. Thus, declare a variable of that type and assign the input to the corresponding ABAP structure component.
As a specialty to this API, key
entities must not be omitted, even though its value is empty. This cannot be mapped to an ABAP value since ABAP cannot distinguish between
null and
empty. As a workaround, set key value
limit of substructure
entities.
DATA: ls_parameters TYPE zcl_ibmc_nat_lang_undrstnd_v1=>t_parameters.
ls_parameters-text =
`The Thomas J. Watson Research Center includes facilities in Yorktown` &&
` Heights and Albany, New York as well as Cambridge, Massachusetts. It serves` &&
` as the headquarters of IBM Research – one of the largest industrial` &&
` research organizations in the world – with 12 labs on six continents.`.
ls_parameters-features-entities-limit = 99999.
Now you are ready to perform IBM Watson entity detection by invoking the corresponding ABAP method
analyze. You should implement a try-catch block to catch exception
zcx_ibmc_service_exception in case of an error.
TRY.
lo_nlu->analyze(
EXPORTING
i_parameters = ls_parameters
IMPORTING
e_response = DATA(ls_results) ).
CATCH zcx_ibmc_service_exception INTO DATA(lo_service_exception).
" handle error
return.
ENDTRY.
ABAP class method
analyze converts the IBM Watson service response in JSON format to an ABAP structure. Objects in JSON are mapped to ABAP structures and arrays in JSON are mapped to internal tables. The filled ABAP structure is returned by the ABAP class method.
Assign the importing parameter to ABAP variable
ls_result using implicit data declaration as indicated in the ABAP code snippet above. The variable is used to access the response of the IBM Waston NLU service by regular ABAP means.
For example, loop at internal table
ls_result-entities to write all detected entities and the corresponding entity types to the console. Since there is also a data type defined for the records of that internal table, direct access to the components of a record is supported. Subsequently assign each record to variable
ls_entity using implicit data declaration.
LOOP AT ls_results-entities INTO DATA(ls_entity).
out->write( `"` && ls_entity-text && `"` && ` -> ` && ls_entity-type ).
ENDLOOP.
That’s it!
You can now run your program as console application. Your program should return all entities that have been detected in the given text document like shown below.
"Thomas J. Watson Research Center" -> Facility
"Albany, New York" -> Location
"Cambridge, Massachusetts" -> Location
"Yorktown Heights" -> Location
"IBM Research" -> Organization
"one" -> Number
"12" -> Number
"six" -> Number
Storing IBM Watson service credentials in a table.
You must provide IBM Watson service credentials to ABAP method
zcl_ibmc_service_ext=>get_instance in order to instantiate an ABAP class. By reason of better security and easier maintenance it is recommended to
not hard code the credentials in your ABAP program. Instead, you can store the credentials in table
ZIBMC_CONFIG.
Add the following two records to table
ZIBMC_CONFIG.
SERVICE |
NAT_LANG_UNDRSTND_V1 |
(ABAP class name without prefix ZCL_IBMC_) |
INSTANCE_UID |
NLU_DEMO |
(an individual ID) |
PARAM |
APIKEY |
|
VALUE |
SZiPLlV... |
(IBM Watson service instance API Key) |
Now you can provide service credentials to ABAP method
zcl_ibmc_service_ext=>get_instance by specifying parameter
i_instance_id. The parameter value is
INSTANCE_UID as it appears in table
ZIBMC_CONFIG.
zcl_ibmc_service_ext=>get_instance(
EXPORTING
i_instance_id = 'NLU_DEMO'
i_version = '2022-04-07'
IMPORTING
eo_instance = lo_nlu ).
Complete ABAP Program
Finally, here is the complete source code of your ABAP program.
CLASS zwatson_nlu DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun .
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zwatson_nlu IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
" Data declaration using data types provides by the ABAP SDK for Watson Services
DATA:
lo_nlu TYPE REF TO zcl_ibmc_nat_lang_undrstnd_v1,
ls_parameters TYPE zcl_ibmc_nat_lang_undrstnd_v1=>t_parameters.
" Instantiate ABAP wrapper for IBM NLU service API endpoints
zcl_ibmc_service_ext=>get_instance(
EXPORTING
i_host = 'https://api.eu-de.natural-language-understanding.watson.cloud.ibm.com/instances/cf89a503-a140-4943-b4ca-71f112378454' " adjust
i_apikey = 'SZiPLlVU3ICDzBVmeO0IyoMUlVT3GqyzvGXYFIyg7kfJ' " adjust
i_version = '2022-04-07'
IMPORTING
eo_instance = lo_nlu ).
" Set parameters for NLU entity detection
ls_parameters-text =
`The Thomas J. Watson Research Center includes facilities in Yorktown` &&
` Heights and Albany, New York as well as Cambridge, Massachusetts. It serves` &&
` as the headquarters of IBM Research – one of the largest industrial` &&
` research organizations in the world – with 12 labs on six continents.`.
" Optional parameters with default values are left out when transferred to json.
" Therefore, we must set at least one component of parameters-features-entities
" to make it appear in json.
ls_parameters-features-entities-limit = 99999.
" Call IBM NLU service
TRY.
lo_nlu->analyze(
EXPORTING
i_parameters = ls_parameters
IMPORTING
e_response = DATA(ls_results) ).
CATCH zcx_ibmc_service_exception INTO DATA(lo_service_exception).
out->write( `ERROR: ` && lo_service_exception->get_text( ) ).
RETURN.
ENDTRY.
" Process service response
LOOP AT ls_results-entities INTO DATA(ls_entity).
out->write( `"` && ls_entity-text && `"` && ` -> ` && ls_entity-type ).
ENDLOOP.
ENDMETHOD.
ENDCLASS.