UNPKG

@azure/ai-text-analytics

Version:
504 lines • 20.8 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT license. import { __rest } from "tslib"; import { bearerTokenAuthenticationPolicy } from "@azure/core-rest-pipeline"; import { isTokenCredential } from "@azure/core-auth"; import { SDK_VERSION } from "./constants"; import { GeneratedClient } from "./generated/generatedClient"; import { logger } from "./logger"; import { makeDetectLanguageResultArray } from "./detectLanguageResultArray"; import { makeRecognizeCategorizedEntitiesResultArray } from "./recognizeCategorizedEntitiesResultArray"; import { makeAnalyzeSentimentResultArray } from "./analyzeSentimentResultArray"; import { makeExtractKeyPhrasesResultArray } from "./extractKeyPhrasesResultArray"; import { makeRecognizePiiEntitiesResultArray } from "./recognizePiiEntitiesResultArray"; import { makeRecognizeLinkedEntitiesResultArray } from "./recognizeLinkedEntitiesResultArray"; import { createSpan } from "./tracing"; import { SpanStatusCode } from "@azure/core-tracing"; import { textAnalyticsAzureKeyCredentialPolicy } from "./azureKeyCredentialPolicy"; import { addParamsToTask, compose, handleInvalidDocumentBatch, setCategoriesFilter, setOpinionMining, setStrEncodingParam, setStrEncodingParamValue } from "./util"; import { BeginAnalyzeHealthcarePoller } from "./lro/health/poller"; import { BeginAnalyzeActionsPoller } from "./lro/analyze/poller"; const DEFAULT_COGNITIVE_SCOPE = "https://cognitiveservices.azure.com/.default"; /** * The types of PII domains the user can choose from. */ export var PiiEntityDomain; (function (PiiEntityDomain) { /** * @see {@link https://aka.ms/tanerpii} for more information. */ PiiEntityDomain["PROTECTED_HEALTH_INFORMATION"] = "PHI"; })(PiiEntityDomain || (PiiEntityDomain = {})); /** * Client class for interacting with Azure Text Analytics. */ export class TextAnalyticsClient { /** * Creates an instance of TextAnalyticsClient. * * Example usage: * ```ts * import { TextAnalyticsClient, AzureKeyCredential } from "@azure/ai-text-analytics"; * * const client = new TextAnalyticsClient( * "<service endpoint>", * new AzureKeyCredential("<api key>") * ); * ``` * @param endpointUrl - The URL to the TextAnalytics endpoint * @param credential - Used to authenticate requests to the service. * @param options - Used to configure the TextAnalytics client. */ constructor(endpointUrl, credential, options = {}) { this.endpointUrl = endpointUrl; const { defaultCountryHint = "us", defaultLanguage = "en" } = options, pipelineOptions = __rest(options, ["defaultCountryHint", "defaultLanguage"]); this.defaultCountryHint = defaultCountryHint; this.defaultLanguage = defaultLanguage; const libInfo = `azsdk-js-ai-textanalytics/${SDK_VERSION}`; if (!pipelineOptions.userAgentOptions) { pipelineOptions.userAgentOptions = {}; } if (pipelineOptions.userAgentOptions.userAgentPrefix) { pipelineOptions.userAgentOptions.userAgentPrefix = `${pipelineOptions.userAgentOptions.userAgentPrefix} ${libInfo}`; } else { pipelineOptions.userAgentOptions.userAgentPrefix = libInfo; } const internalPipelineOptions = Object.assign(Object.assign({}, pipelineOptions), { loggingOptions: { logger: logger.info, additionalAllowedHeaderNames: ["x-ms-correlation-request-id", "x-ms-request-id"] } }); this.client = new GeneratedClient(this.endpointUrl, internalPipelineOptions); const authPolicy = isTokenCredential(credential) ? bearerTokenAuthenticationPolicy({ credential, scopes: DEFAULT_COGNITIVE_SCOPE }) : textAnalyticsAzureKeyCredentialPolicy(credential); this.client.pipeline.addPolicy(authPolicy); } async detectLanguage(documents, countryHintOrOptions, options) { let realOptions; let realInputs; if (!Array.isArray(documents) || documents.length === 0) { throw new Error("'documents' must be a non-empty array"); } if (isStringArray(documents)) { const countryHint = countryHintOrOptions || this.defaultCountryHint; realInputs = convertToDetectLanguageInput(documents, countryHint); realOptions = options || {}; } else { // Replace "none" hints with "" realInputs = documents.map((input) => (Object.assign(Object.assign({}, input), { countryHint: input.countryHint === "none" ? "" : input.countryHint }))); realOptions = countryHintOrOptions || {}; } const { span, updatedOptions: finalOptions } = createSpan("TextAnalyticsClient-detectLanguages", makeGeneratedDetectLanguageOptions(realOptions)); try { const result = await this.client.languages({ documents: realInputs }, finalOptions); return makeDetectLanguageResultArray(realInputs, result); } catch (e) { span.setStatus({ code: SpanStatusCode.ERROR, message: e.message }); throw e; } finally { span.end(); } } async recognizeEntities(documents, languageOrOptions, // eslint-disable-next-line @azure/azure-sdk/ts-naming-options options) { let realOptions; let realInputs; if (!Array.isArray(documents) || documents.length === 0) { throw new Error("'documents' must be a non-empty array"); } if (isStringArray(documents)) { const language = languageOrOptions || this.defaultLanguage; realInputs = convertToTextDocumentInput(documents, language); realOptions = options || {}; } else { realInputs = documents; realOptions = languageOrOptions || {}; } const { span, updatedOptions: finalOptions } = createSpan("TextAnalyticsClient-recognizeEntities", makeGeneratedRecognizeCategorizedEntitiesOptions(realOptions)); try { const result = await this.client.entitiesRecognitionGeneral({ documents: realInputs }, finalOptions); return makeRecognizeCategorizedEntitiesResultArray(realInputs, result); } catch (e) { /** * This special logic handles REST exception with code * InvalidDocumentBatch and is needed to maintain backward compatability * with sdk v5.0.0 and earlier. In general, REST exceptions are thrown as * is and include both outer and inner exception codes. However, the * earlier versions were throwing an exception that included the inner * code only. */ const backwardCompatibleException = handleInvalidDocumentBatch(e); span.setStatus({ code: SpanStatusCode.ERROR, message: backwardCompatibleException.message }); throw backwardCompatibleException; } finally { span.end(); } } async analyzeSentiment(documents, languageOrOptions, options) { let realOptions; let realInputs; if (!Array.isArray(documents) || documents.length === 0) { throw new Error("'documents' must be a non-empty array"); } if (isStringArray(documents)) { const language = languageOrOptions || this.defaultLanguage; realInputs = convertToTextDocumentInput(documents, language); realOptions = options || {}; } else { realInputs = documents; realOptions = languageOrOptions || {}; } const { span, updatedOptions: finalOptions } = createSpan("TextAnalyticsClient-analyzeSentiment", makeGeneratedAnalyzeSentimentOptions(realOptions)); try { const result = await this.client.sentiment({ documents: realInputs }, finalOptions); return makeAnalyzeSentimentResultArray(realInputs, result); } catch (e) { span.setStatus({ code: SpanStatusCode.ERROR, message: e.message }); throw e; } finally { span.end(); } } async extractKeyPhrases(documents, languageOrOptions, options) { let realOptions; let realInputs; if (!Array.isArray(documents) || documents.length === 0) { throw new Error("'documents' must be a non-empty array"); } if (isStringArray(documents)) { const language = languageOrOptions || this.defaultLanguage; realInputs = convertToTextDocumentInput(documents, language); realOptions = options || {}; } else { realInputs = documents; realOptions = languageOrOptions || {}; } const { span, updatedOptions: finalOptions } = createSpan("TextAnalyticsClient-extractKeyPhrases", makeGeneratedExtractKeyPhrasesOptions(realOptions)); try { const result = await this.client.keyPhrases({ documents: realInputs }, finalOptions); return makeExtractKeyPhrasesResultArray(realInputs, result); } catch (e) { span.setStatus({ code: SpanStatusCode.ERROR, message: e.message }); throw e; } finally { span.end(); } } async recognizePiiEntities(inputs, languageOrOptions, options) { let realOptions; let realInputs; if (isStringArray(inputs)) { const language = languageOrOptions || this.defaultLanguage; realInputs = convertToTextDocumentInput(inputs, language); realOptions = options || {}; } else { realInputs = inputs; realOptions = languageOrOptions || {}; } const { span, updatedOptions: finalOptions } = createSpan("TextAnalyticsClient-recognizePiiEntities", makeGeneratedRecognizePiiEntitiesOptions(realOptions)); try { const result = await this.client.entitiesRecognitionPii({ documents: realInputs }, finalOptions); return makeRecognizePiiEntitiesResultArray(realInputs, result); } catch (e) { span.setStatus({ code: SpanStatusCode.ERROR, message: e.message }); throw e; } finally { span.end(); } } async recognizeLinkedEntities(documents, languageOrOptions, options) { let realOptions; let realInputs; if (!Array.isArray(documents) || documents.length === 0) { throw new Error("'documents' must be a non-empty array"); } if (isStringArray(documents)) { const language = languageOrOptions || this.defaultLanguage; realInputs = convertToTextDocumentInput(documents, language); realOptions = options || {}; } else { realInputs = documents; realOptions = languageOrOptions || {}; } const { span, updatedOptions: finalOptions } = createSpan("TextAnalyticsClient-recognizeLinkedEntities", makeGeneratedRecognizeLinkingEntitiesOptions(realOptions)); try { const result = await this.client.entitiesLinking({ documents: realInputs }, finalOptions); return makeRecognizeLinkedEntitiesResultArray(realInputs, result); } catch (e) { span.setStatus({ code: SpanStatusCode.ERROR, message: e.message }); throw e; } finally { span.end(); } } async beginAnalyzeHealthcareEntities(documents, languageOrOptions, options) { let realOptions; let realInputs; if (isStringArray(documents)) { const language = languageOrOptions || this.defaultLanguage; realInputs = convertToTextDocumentInput(documents, language); realOptions = options || {}; } else { realInputs = documents; realOptions = languageOrOptions || {}; } const { updateIntervalInMs, resumeFrom } = realOptions, restOptions = __rest(realOptions, ["updateIntervalInMs", "resumeFrom"]); const poller = new BeginAnalyzeHealthcarePoller({ client: this.client, documents: realInputs, options: restOptions, updateIntervalInMs: updateIntervalInMs, resumeFrom: resumeFrom }); await poller.poll(); return poller; } async beginAnalyzeActions(documents, actions, languageOrOptions, options) { let realOptions; let realInputs; if (!Array.isArray(documents) || documents.length === 0) { throw new Error("'documents' must be a non-empty array"); } if (isStringArray(documents)) { const language = languageOrOptions || this.defaultLanguage; realInputs = convertToTextDocumentInput(documents, language); realOptions = options || {}; } else { realInputs = documents; realOptions = languageOrOptions || {}; } validateActions(actions); const compiledActions = compileAnalyzeInput(actions); const { updateIntervalInMs, resumeFrom } = realOptions, restOptions = __rest(realOptions, ["updateIntervalInMs", "resumeFrom"]); const poller = new BeginAnalyzeActionsPoller({ client: this.client, documents: realInputs, actions: compiledActions, options: restOptions, resumeFrom: resumeFrom, updateIntervalInMs: updateIntervalInMs }); await poller.poll(); return poller; } } function validateActions(actions) { function validateActionType(actionList, actionType) { var _a; if (((_a = actionList === null || actionList === void 0 ? void 0 : actionList.length) !== null && _a !== void 0 ? _a : 0) > 1) { throw new Error(`beginAnalyzeActions: Currently, the service can accept up to one action only for ${actionType} actions.`); } } validateActionType(actions.analyzeSentimentActions, `analyzeSentiment`); validateActionType(actions.extractKeyPhrasesActions, `extractKeyPhrases`); validateActionType(actions.recognizeEntitiesActions, `recognizeEntities`); validateActionType(actions.recognizeLinkedEntitiesActions, `recognizeLinkedEntities`); validateActionType(actions.recognizePiiEntitiesActions, `recognizePiiEntities`); } /** * @internal */ function compileAnalyzeInput(actions) { var _a, _b, _c, _d, _e; return { entityRecognitionPiiTasks: (_a = actions.recognizePiiEntitiesActions) === null || _a === void 0 ? void 0 : _a.map(compose(setStrEncodingParam, compose(setCategoriesFilter, addParamsToTask))), entityRecognitionTasks: (_b = actions.recognizeEntitiesActions) === null || _b === void 0 ? void 0 : _b.map(compose(setStrEncodingParam, addParamsToTask)), keyPhraseExtractionTasks: (_c = actions.extractKeyPhrasesActions) === null || _c === void 0 ? void 0 : _c.map(addParamsToTask), entityLinkingTasks: (_d = actions.recognizeLinkedEntitiesActions) === null || _d === void 0 ? void 0 : _d.map(compose(setStrEncodingParam, addParamsToTask)), sentimentAnalysisTasks: (_e = actions.analyzeSentimentActions) === null || _e === void 0 ? void 0 : _e.map(compose(setStrEncodingParam, compose(setOpinionMining, addParamsToTask))) }; } function isStringArray(documents) { return typeof documents[0] === "string"; } /** * @internal */ function convertToDetectLanguageInput(inputs, countryHint) { if (countryHint === "none") { countryHint = ""; } return inputs.map((text, index) => { return { id: String(index), countryHint, text }; }); } /** * @internal */ function convertToTextDocumentInput(inputs, language) { return inputs.map((text, index) => { return { id: String(index), language, text }; }); } /** * Creates the options the service expects for the analyze sentiment API from the user friendly ones. * @param params - the user friendly parameters * @internal */ function makeGeneratedAnalyzeSentimentOptions(params) { return { abortSignal: params.abortSignal, opinionMining: params.includeOpinionMining, includeStatistics: params.includeStatistics, modelVersion: params.modelVersion, requestOptions: params.requestOptions, stringIndexType: setStrEncodingParamValue(params.stringIndexType), tracingOptions: params.tracingOptions, onResponse: params.onResponse, serializerOptions: params.serializerOptions, loggingOptOut: params.disableServiceLogs }; } /** * Creates the options the service expects for the recognize pii entities API from the user friendly ones. * @param params - the user friendly parameters * @internal */ function makeGeneratedRecognizePiiEntitiesOptions(params) { return { abortSignal: params.abortSignal, domain: params.domainFilter, includeStatistics: params.includeStatistics, modelVersion: params.modelVersion, requestOptions: params.requestOptions, stringIndexType: setStrEncodingParamValue(params.stringIndexType), tracingOptions: params.tracingOptions, piiCategories: params.categoriesFilter, onResponse: params.onResponse, serializerOptions: params.serializerOptions, loggingOptOut: params.disableServiceLogs }; } /** * Creates the options the service expects for the recognize entities API from the user friendly ones. * @param params - the user friendly parameters * @internal */ function makeGeneratedRecognizeCategorizedEntitiesOptions(params) { return { abortSignal: params.abortSignal, includeStatistics: params.includeStatistics, modelVersion: params.modelVersion, requestOptions: params.requestOptions, stringIndexType: setStrEncodingParamValue(params.stringIndexType), tracingOptions: params.tracingOptions, onResponse: params.onResponse, serializerOptions: params.serializerOptions, loggingOptOut: params.disableServiceLogs }; } /** * Creates the options the service expects for the detect language API from the user friendly ones. * @param params - the user friendly parameters * @internal */ function makeGeneratedDetectLanguageOptions(params) { return { abortSignal: params.abortSignal, includeStatistics: params.includeStatistics, modelVersion: params.modelVersion, requestOptions: params.requestOptions, tracingOptions: params.tracingOptions, onResponse: params.onResponse, serializerOptions: params.serializerOptions, loggingOptOut: params.disableServiceLogs }; } /** * Creates the options the service expects for the extract key phrases API from the user friendly ones. * @param params - the user friendly parameters * @internal */ function makeGeneratedExtractKeyPhrasesOptions(params) { return { abortSignal: params.abortSignal, includeStatistics: params.includeStatistics, modelVersion: params.modelVersion, requestOptions: params.requestOptions, tracingOptions: params.tracingOptions, onResponse: params.onResponse, serializerOptions: params.serializerOptions, loggingOptOut: params.disableServiceLogs }; } /** * Creates the options the service expects for the recognize linked entities API from the user friendly ones. * @param params - the user friendly parameters * @internal */ function makeGeneratedRecognizeLinkingEntitiesOptions(params) { return { abortSignal: params.abortSignal, includeStatistics: params.includeStatistics, modelVersion: params.modelVersion, requestOptions: params.requestOptions, tracingOptions: params.tracingOptions, onResponse: params.onResponse, serializerOptions: params.serializerOptions, loggingOptOut: params.disableServiceLogs, stringIndexType: setStrEncodingParamValue(params.stringIndexType) }; } //# sourceMappingURL=textAnalyticsClient.js.map