Source code for ibm_watson.natural_language_classifier_v1

# coding: utf-8

# (C) Copyright IBM Corp. 2019.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
IBM Watson™ Natural Language Classifier uses machine learning algorithms to return
the top matching predefined classes for short text input. You create and train a
classifier to connect predefined classes to example texts so that the service can apply
those classes to new inputs.
"""

import json
from .common import get_sdk_headers
from enum import Enum
from ibm_cloud_sdk_core import BaseService
from ibm_cloud_sdk_core import datetime_to_string, string_to_datetime
from ibm_cloud_sdk_core import get_authenticator_from_environment
from ibm_cloud_sdk_core import read_external_sources

##############################################################################
# Service
##############################################################################


[docs]class NaturalLanguageClassifierV1(BaseService): """The Natural Language Classifier V1 service.""" default_service_url = 'https://gateway.watsonplatform.net/natural-language-classifier/api' def __init__( self, authenticator=None, ): """ Construct a new client for the Natural Language Classifier service. :param Authenticator authenticator: The authenticator specifies the authentication mechanism. Get up to date information from https://github.com/IBM/python-sdk-core/blob/master/README.md about initializing the authenticator of your choice. """ service_url = self.default_service_url disable_ssl_verification = False config = read_external_sources('natural_language_classifier') if config.get('URL'): service_url = config.get('URL') if config.get('DISABLE_SSL'): disable_ssl_verification = config.get('DISABLE_SSL') if not authenticator: authenticator = get_authenticator_from_environment( 'natural_language_classifier') BaseService.__init__(self, service_url=service_url, authenticator=authenticator, disable_ssl_verification=disable_ssl_verification) ######################### # Classify text #########################
[docs] def classify(self, classifier_id, text, **kwargs): """ Classify a phrase. Returns label information for the input. The status must be `Available` before you can use the classifier to classify text. :param str classifier_id: Classifier ID to use. :param str text: The submitted phrase. The maximum length is 2048 characters. :param dict headers: A `dict` containing the request headers :return: A `DetailedResponse` containing the result, headers and HTTP status code. :rtype: DetailedResponse """ if classifier_id is None: raise ValueError('classifier_id must be provided') if text is None: raise ValueError('text must be provided') headers = {} if 'headers' in kwargs: headers.update(kwargs.get('headers')) sdk_headers = get_sdk_headers('natural_language_classifier', 'V1', 'classify') headers.update(sdk_headers) data = {'text': text} url = '/v1/classifiers/{0}/classify'.format( *self._encode_path_vars(classifier_id)) request = self.prepare_request(method='POST', url=url, headers=headers, data=data, accept_json=True) response = self.send(request) return response
[docs] def classify_collection(self, classifier_id, collection, **kwargs): """ Classify multiple phrases. Returns label information for multiple phrases. The status must be `Available` before you can use the classifier to classify text. Note that classifying Japanese texts is a beta feature. :param str classifier_id: Classifier ID to use. :param list[ClassifyInput] collection: The submitted phrases. :param dict headers: A `dict` containing the request headers :return: A `DetailedResponse` containing the result, headers and HTTP status code. :rtype: DetailedResponse """ if classifier_id is None: raise ValueError('classifier_id must be provided') if collection is None: raise ValueError('collection must be provided') collection = [self._convert_model(x) for x in collection] headers = {} if 'headers' in kwargs: headers.update(kwargs.get('headers')) sdk_headers = get_sdk_headers('natural_language_classifier', 'V1', 'classify_collection') headers.update(sdk_headers) data = {'collection': collection} url = '/v1/classifiers/{0}/classify_collection'.format( *self._encode_path_vars(classifier_id)) request = self.prepare_request(method='POST', url=url, headers=headers, data=data, accept_json=True) response = self.send(request) return response
######################### # Manage classifiers #########################
[docs] def create_classifier(self, training_metadata, training_data, **kwargs): """ Create classifier. Sends data to create and train a classifier and returns information about the new classifier. :param file training_metadata: Metadata in JSON format. The metadata identifies the language of the data, and an optional name to identify the classifier. Specify the language with the 2-letter primary language code as assigned in ISO standard 639. Supported languages are English (`en`), Arabic (`ar`), French (`fr`), German, (`de`), Italian (`it`), Japanese (`ja`), Korean (`ko`), Brazilian Portuguese (`pt`), and Spanish (`es`). :param file training_data: Training data in CSV format. Each text value must have at least one class. The data can include up to 3,000 classes and 20,000 records. For details, see [Data preparation](https://cloud.ibm.com/docs/services/natural-language-classifier?topic=natural-language-classifier-using-your-data). :param dict headers: A `dict` containing the request headers :return: A `DetailedResponse` containing the result, headers and HTTP status code. :rtype: DetailedResponse """ if training_metadata is None: raise ValueError('training_metadata must be provided') if training_data is None: raise ValueError('training_data must be provided') headers = {} if 'headers' in kwargs: headers.update(kwargs.get('headers')) sdk_headers = get_sdk_headers('natural_language_classifier', 'V1', 'create_classifier') headers.update(sdk_headers) form_data = [] form_data.append(('training_metadata', (None, training_metadata, 'application/json'))) form_data.append(('training_data', (None, training_data, 'text/csv'))) url = '/v1/classifiers' request = self.prepare_request(method='POST', url=url, headers=headers, files=form_data, accept_json=True) response = self.send(request) return response
[docs] def list_classifiers(self, **kwargs): """ List classifiers. Returns an empty array if no classifiers are available. :param dict headers: A `dict` containing the request headers :return: A `DetailedResponse` containing the result, headers and HTTP status code. :rtype: DetailedResponse """ headers = {} if 'headers' in kwargs: headers.update(kwargs.get('headers')) sdk_headers = get_sdk_headers('natural_language_classifier', 'V1', 'list_classifiers') headers.update(sdk_headers) url = '/v1/classifiers' request = self.prepare_request(method='GET', url=url, headers=headers, accept_json=True) response = self.send(request) return response
[docs] def get_classifier(self, classifier_id, **kwargs): """ Get information about a classifier. Returns status and other information about a classifier. :param str classifier_id: Classifier ID to query. :param dict headers: A `dict` containing the request headers :return: A `DetailedResponse` containing the result, headers and HTTP status code. :rtype: DetailedResponse """ if classifier_id is None: raise ValueError('classifier_id must be provided') headers = {} if 'headers' in kwargs: headers.update(kwargs.get('headers')) sdk_headers = get_sdk_headers('natural_language_classifier', 'V1', 'get_classifier') headers.update(sdk_headers) url = '/v1/classifiers/{0}'.format( *self._encode_path_vars(classifier_id)) request = self.prepare_request(method='GET', url=url, headers=headers, accept_json=True) response = self.send(request) return response
[docs] def delete_classifier(self, classifier_id, **kwargs): """ Delete classifier. :param str classifier_id: Classifier ID to delete. :param dict headers: A `dict` containing the request headers :return: A `DetailedResponse` containing the result, headers and HTTP status code. :rtype: DetailedResponse """ if classifier_id is None: raise ValueError('classifier_id must be provided') headers = {} if 'headers' in kwargs: headers.update(kwargs.get('headers')) sdk_headers = get_sdk_headers('natural_language_classifier', 'V1', 'delete_classifier') headers.update(sdk_headers) url = '/v1/classifiers/{0}'.format( *self._encode_path_vars(classifier_id)) request = self.prepare_request(method='DELETE', url=url, headers=headers, accept_json=True) response = self.send(request) return response
############################################################################## # Models ##############################################################################
[docs]class Classification(): """ Response from the classifier for a phrase. :attr str classifier_id: (optional) Unique identifier for this classifier. :attr str url: (optional) Link to the classifier. :attr str text: (optional) The submitted phrase. :attr str top_class: (optional) The class with the highest confidence. :attr list[ClassifiedClass] classes: (optional) An array of up to ten class-confidence pairs sorted in descending order of confidence. """ def __init__(self, *, classifier_id=None, url=None, text=None, top_class=None, classes=None): """ Initialize a Classification object. :param str classifier_id: (optional) Unique identifier for this classifier. :param str url: (optional) Link to the classifier. :param str text: (optional) The submitted phrase. :param str top_class: (optional) The class with the highest confidence. :param list[ClassifiedClass] classes: (optional) An array of up to ten class-confidence pairs sorted in descending order of confidence. """ self.classifier_id = classifier_id self.url = url self.text = text self.top_class = top_class self.classes = classes @classmethod def _from_dict(cls, _dict): """Initialize a Classification object from a json dictionary.""" args = {} valid_keys = ['classifier_id', 'url', 'text', 'top_class', 'classes'] bad_keys = set(_dict.keys()) - set(valid_keys) if bad_keys: raise ValueError( 'Unrecognized keys detected in dictionary for class Classification: ' + ', '.join(bad_keys)) if 'classifier_id' in _dict: args['classifier_id'] = _dict.get('classifier_id') if 'url' in _dict: args['url'] = _dict.get('url') if 'text' in _dict: args['text'] = _dict.get('text') if 'top_class' in _dict: args['top_class'] = _dict.get('top_class') if 'classes' in _dict: args['classes'] = [ ClassifiedClass._from_dict(x) for x in (_dict.get('classes')) ] return cls(**args) def _to_dict(self): """Return a json dictionary representing this model.""" _dict = {} if hasattr(self, 'classifier_id') and self.classifier_id is not None: _dict['classifier_id'] = self.classifier_id if hasattr(self, 'url') and self.url is not None: _dict['url'] = self.url if hasattr(self, 'text') and self.text is not None: _dict['text'] = self.text if hasattr(self, 'top_class') and self.top_class is not None: _dict['top_class'] = self.top_class if hasattr(self, 'classes') and self.classes is not None: _dict['classes'] = [x._to_dict() for x in self.classes] return _dict def __str__(self): """Return a `str` version of this Classification object.""" return json.dumps(self._to_dict(), indent=2) def __eq__(self, other): """Return `true` when self and other are equal, false otherwise.""" if not isinstance(other, self.__class__): return False return self.__dict__ == other.__dict__ def __ne__(self, other): """Return `true` when self and other are not equal, false otherwise.""" return not self == other
[docs]class ClassificationCollection(): """ Response from the classifier for multiple phrases. :attr str classifier_id: (optional) Unique identifier for this classifier. :attr str url: (optional) Link to the classifier. :attr list[CollectionItem] collection: (optional) An array of classifier responses for each submitted phrase. """ def __init__(self, *, classifier_id=None, url=None, collection=None): """ Initialize a ClassificationCollection object. :param str classifier_id: (optional) Unique identifier for this classifier. :param str url: (optional) Link to the classifier. :param list[CollectionItem] collection: (optional) An array of classifier responses for each submitted phrase. """ self.classifier_id = classifier_id self.url = url self.collection = collection @classmethod def _from_dict(cls, _dict): """Initialize a ClassificationCollection object from a json dictionary.""" args = {} valid_keys = ['classifier_id', 'url', 'collection'] bad_keys = set(_dict.keys()) - set(valid_keys) if bad_keys: raise ValueError( 'Unrecognized keys detected in dictionary for class ClassificationCollection: ' + ', '.join(bad_keys)) if 'classifier_id' in _dict: args['classifier_id'] = _dict.get('classifier_id') if 'url' in _dict: args['url'] = _dict.get('url') if 'collection' in _dict: args['collection'] = [ CollectionItem._from_dict(x) for x in (_dict.get('collection')) ] return cls(**args) def _to_dict(self): """Return a json dictionary representing this model.""" _dict = {} if hasattr(self, 'classifier_id') and self.classifier_id is not None: _dict['classifier_id'] = self.classifier_id if hasattr(self, 'url') and self.url is not None: _dict['url'] = self.url if hasattr(self, 'collection') and self.collection is not None: _dict['collection'] = [x._to_dict() for x in self.collection] return _dict def __str__(self): """Return a `str` version of this ClassificationCollection object.""" return json.dumps(self._to_dict(), indent=2) def __eq__(self, other): """Return `true` when self and other are equal, false otherwise.""" if not isinstance(other, self.__class__): return False return self.__dict__ == other.__dict__ def __ne__(self, other): """Return `true` when self and other are not equal, false otherwise.""" return not self == other
[docs]class ClassifiedClass(): """ Class and confidence. :attr float confidence: (optional) A decimal percentage that represents the confidence that Watson has in this class. Higher values represent higher confidences. :attr str class_name: (optional) Class label. """ def __init__(self, *, confidence=None, class_name=None): """ Initialize a ClassifiedClass object. :param float confidence: (optional) A decimal percentage that represents the confidence that Watson has in this class. Higher values represent higher confidences. :param str class_name: (optional) Class label. """ self.confidence = confidence self.class_name = class_name @classmethod def _from_dict(cls, _dict): """Initialize a ClassifiedClass object from a json dictionary.""" args = {} valid_keys = ['confidence', 'class_name'] bad_keys = set(_dict.keys()) - set(valid_keys) if bad_keys: raise ValueError( 'Unrecognized keys detected in dictionary for class ClassifiedClass: ' + ', '.join(bad_keys)) if 'confidence' in _dict: args['confidence'] = _dict.get('confidence') if 'class_name' in _dict: args['class_name'] = _dict.get('class_name') return cls(**args) def _to_dict(self): """Return a json dictionary representing this model.""" _dict = {} if hasattr(self, 'confidence') and self.confidence is not None: _dict['confidence'] = self.confidence if hasattr(self, 'class_name') and self.class_name is not None: _dict['class_name'] = self.class_name return _dict def __str__(self): """Return a `str` version of this ClassifiedClass object.""" return json.dumps(self._to_dict(), indent=2) def __eq__(self, other): """Return `true` when self and other are equal, false otherwise.""" if not isinstance(other, self.__class__): return False return self.__dict__ == other.__dict__ def __ne__(self, other): """Return `true` when self and other are not equal, false otherwise.""" return not self == other
[docs]class Classifier(): """ A classifier for natural language phrases. :attr str name: (optional) User-supplied name for the classifier. :attr str url: Link to the classifier. :attr str status: (optional) The state of the classifier. :attr str classifier_id: Unique identifier for this classifier. :attr datetime created: (optional) Date and time (UTC) the classifier was created. :attr str status_description: (optional) Additional detail about the status. :attr str language: (optional) The language used for the classifier. """ def __init__(self, url, classifier_id, *, name=None, status=None, created=None, status_description=None, language=None): """ Initialize a Classifier object. :param str url: Link to the classifier. :param str classifier_id: Unique identifier for this classifier. :param str name: (optional) User-supplied name for the classifier. :param str status: (optional) The state of the classifier. :param datetime created: (optional) Date and time (UTC) the classifier was created. :param str status_description: (optional) Additional detail about the status. :param str language: (optional) The language used for the classifier. """ self.name = name self.url = url self.status = status self.classifier_id = classifier_id self.created = created self.status_description = status_description self.language = language @classmethod def _from_dict(cls, _dict): """Initialize a Classifier object from a json dictionary.""" args = {} valid_keys = [ 'name', 'url', 'status', 'classifier_id', 'created', 'status_description', 'language' ] bad_keys = set(_dict.keys()) - set(valid_keys) if bad_keys: raise ValueError( 'Unrecognized keys detected in dictionary for class Classifier: ' + ', '.join(bad_keys)) if 'name' in _dict: args['name'] = _dict.get('name') if 'url' in _dict: args['url'] = _dict.get('url') else: raise ValueError( 'Required property \'url\' not present in Classifier JSON') if 'status' in _dict: args['status'] = _dict.get('status') if 'classifier_id' in _dict: args['classifier_id'] = _dict.get('classifier_id') else: raise ValueError( 'Required property \'classifier_id\' not present in Classifier JSON' ) if 'created' in _dict: args['created'] = string_to_datetime(_dict.get('created')) if 'status_description' in _dict: args['status_description'] = _dict.get('status_description') if 'language' in _dict: args['language'] = _dict.get('language') return cls(**args) def _to_dict(self): """Return a json dictionary representing this model.""" _dict = {} if hasattr(self, 'name') and self.name is not None: _dict['name'] = self.name if hasattr(self, 'url') and self.url is not None: _dict['url'] = self.url if hasattr(self, 'status') and self.status is not None: _dict['status'] = self.status if hasattr(self, 'classifier_id') and self.classifier_id is not None: _dict['classifier_id'] = self.classifier_id if hasattr(self, 'created') and self.created is not None: _dict['created'] = datetime_to_string(self.created) if hasattr( self, 'status_description') and self.status_description is not None: _dict['status_description'] = self.status_description if hasattr(self, 'language') and self.language is not None: _dict['language'] = self.language return _dict def __str__(self): """Return a `str` version of this Classifier object.""" return json.dumps(self._to_dict(), indent=2) def __eq__(self, other): """Return `true` when self and other are equal, false otherwise.""" if not isinstance(other, self.__class__): return False return self.__dict__ == other.__dict__ def __ne__(self, other): """Return `true` when self and other are not equal, false otherwise.""" return not self == other
[docs] class StatusEnum(Enum): """ The state of the classifier. """ NON_EXISTENT = "Non Existent" TRAINING = "Training" FAILED = "Failed" AVAILABLE = "Available" UNAVAILABLE = "Unavailable"
[docs]class ClassifierList(): """ List of available classifiers. :attr list[Classifier] classifiers: The classifiers available to the user. Returns an empty array if no classifiers are available. """ def __init__(self, classifiers): """ Initialize a ClassifierList object. :param list[Classifier] classifiers: The classifiers available to the user. Returns an empty array if no classifiers are available. """ self.classifiers = classifiers @classmethod def _from_dict(cls, _dict): """Initialize a ClassifierList object from a json dictionary.""" args = {} valid_keys = ['classifiers'] bad_keys = set(_dict.keys()) - set(valid_keys) if bad_keys: raise ValueError( 'Unrecognized keys detected in dictionary for class ClassifierList: ' + ', '.join(bad_keys)) if 'classifiers' in _dict: args['classifiers'] = [ Classifier._from_dict(x) for x in (_dict.get('classifiers')) ] else: raise ValueError( 'Required property \'classifiers\' not present in ClassifierList JSON' ) return cls(**args) def _to_dict(self): """Return a json dictionary representing this model.""" _dict = {} if hasattr(self, 'classifiers') and self.classifiers is not None: _dict['classifiers'] = [x._to_dict() for x in self.classifiers] return _dict def __str__(self): """Return a `str` version of this ClassifierList object.""" return json.dumps(self._to_dict(), indent=2) def __eq__(self, other): """Return `true` when self and other are equal, false otherwise.""" if not isinstance(other, self.__class__): return False return self.__dict__ == other.__dict__ def __ne__(self, other): """Return `true` when self and other are not equal, false otherwise.""" return not self == other
[docs]class ClassifyInput(): """ Request payload to classify. :attr str text: The submitted phrase. The maximum length is 2048 characters. """ def __init__(self, text): """ Initialize a ClassifyInput object. :param str text: The submitted phrase. The maximum length is 2048 characters. """ self.text = text @classmethod def _from_dict(cls, _dict): """Initialize a ClassifyInput object from a json dictionary.""" args = {} valid_keys = ['text'] bad_keys = set(_dict.keys()) - set(valid_keys) if bad_keys: raise ValueError( 'Unrecognized keys detected in dictionary for class ClassifyInput: ' + ', '.join(bad_keys)) if 'text' in _dict: args['text'] = _dict.get('text') else: raise ValueError( 'Required property \'text\' not present in ClassifyInput JSON') return cls(**args) def _to_dict(self): """Return a json dictionary representing this model.""" _dict = {} if hasattr(self, 'text') and self.text is not None: _dict['text'] = self.text return _dict def __str__(self): """Return a `str` version of this ClassifyInput object.""" return json.dumps(self._to_dict(), indent=2) def __eq__(self, other): """Return `true` when self and other are equal, false otherwise.""" if not isinstance(other, self.__class__): return False return self.__dict__ == other.__dict__ def __ne__(self, other): """Return `true` when self and other are not equal, false otherwise.""" return not self == other
[docs]class CollectionItem(): """ Response from the classifier for a phrase in a collection. :attr str text: (optional) The submitted phrase. The maximum length is 2048 characters. :attr str top_class: (optional) The class with the highest confidence. :attr list[ClassifiedClass] classes: (optional) An array of up to ten class-confidence pairs sorted in descending order of confidence. """ def __init__(self, *, text=None, top_class=None, classes=None): """ Initialize a CollectionItem object. :param str text: (optional) The submitted phrase. The maximum length is 2048 characters. :param str top_class: (optional) The class with the highest confidence. :param list[ClassifiedClass] classes: (optional) An array of up to ten class-confidence pairs sorted in descending order of confidence. """ self.text = text self.top_class = top_class self.classes = classes @classmethod def _from_dict(cls, _dict): """Initialize a CollectionItem object from a json dictionary.""" args = {} valid_keys = ['text', 'top_class', 'classes'] bad_keys = set(_dict.keys()) - set(valid_keys) if bad_keys: raise ValueError( 'Unrecognized keys detected in dictionary for class CollectionItem: ' + ', '.join(bad_keys)) if 'text' in _dict: args['text'] = _dict.get('text') if 'top_class' in _dict: args['top_class'] = _dict.get('top_class') if 'classes' in _dict: args['classes'] = [ ClassifiedClass._from_dict(x) for x in (_dict.get('classes')) ] return cls(**args) def _to_dict(self): """Return a json dictionary representing this model.""" _dict = {} if hasattr(self, 'text') and self.text is not None: _dict['text'] = self.text if hasattr(self, 'top_class') and self.top_class is not None: _dict['top_class'] = self.top_class if hasattr(self, 'classes') and self.classes is not None: _dict['classes'] = [x._to_dict() for x in self.classes] return _dict def __str__(self): """Return a `str` version of this CollectionItem object.""" return json.dumps(self._to_dict(), indent=2) def __eq__(self, other): """Return `true` when self and other are equal, false otherwise.""" if not isinstance(other, self.__class__): return False return self.__dict__ == other.__dict__ def __ne__(self, other): """Return `true` when self and other are not equal, false otherwise.""" return not self == other