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.
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
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.
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.
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.
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 ).
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
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) |
SERVICE | NAT_LANG_UNDRSTND_V1 | |
INSTANCE_UID | NLU_DEMO | |
PARAM | HOST | |
VALUE | https://api.eu-de.natural-language-understanding.watson.cloud.ibm.com/instances/cf89a… | (IBM Watson service instance URL) |
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 ).
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.