Files
alighasami 3d5eaf9445
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
first commit
2026-03-17 16:22:57 +03:30

155 lines
4.3 KiB
TypeScript

import { AzureChatOpenAI } from '@langchain/openai';
import { getProxyAgent, makeN8nLlmFailedAttemptHandler, N8nLlmTracing } from '@n8n/ai-utilities';
import {
NodeOperationError,
NodeConnectionTypes,
type INodeType,
type INodeTypeDescription,
type ISupplyDataFunctions,
type SupplyData,
} from 'n8n-workflow';
import { setupApiKeyAuthentication } from './credentials/api-key';
import { setupOAuth2Authentication } from './credentials/oauth2';
import { properties } from './properties';
import { AuthenticationType } from './types';
import type {
AzureOpenAIApiKeyModelConfig,
AzureOpenAIOAuth2ModelConfig,
AzureOpenAIOptions,
} from './types';
export class LmChatAzureOpenAi implements INodeType {
description: INodeTypeDescription = {
displayName: 'Azure OpenAI Chat Model',
name: 'lmChatAzureOpenAi',
icon: 'file:azure.svg',
group: ['transform'],
version: 1,
description: 'For advanced usage with an AI chain',
defaults: {
name: 'Azure OpenAI Chat Model',
},
codex: {
categories: ['AI'],
subcategories: {
AI: ['Language Models', 'Root Nodes'],
'Language Models': ['Chat Models (Recommended)'],
},
resources: {
primaryDocumentation: [
{
url: 'https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.lmchatazureopenai/',
},
],
},
},
inputs: [],
outputs: [NodeConnectionTypes.AiLanguageModel],
outputNames: ['Model'],
credentials: [
{
name: 'azureOpenAiApi',
required: true,
displayOptions: {
show: {
authentication: [AuthenticationType.ApiKey],
},
},
},
{
name: 'azureEntraCognitiveServicesOAuth2Api',
required: true,
displayOptions: {
show: {
authentication: [AuthenticationType.EntraOAuth2],
},
},
},
],
properties,
};
async supplyData(this: ISupplyDataFunctions, itemIndex: number): Promise<SupplyData> {
try {
const authenticationMethod = this.getNodeParameter(
'authentication',
itemIndex,
) as AuthenticationType;
const modelName = this.getNodeParameter('model', itemIndex) as string;
const options = this.getNodeParameter('options', itemIndex, {}) as AzureOpenAIOptions;
// Set up Authentication based on selection and get configuration
let modelConfig: AzureOpenAIApiKeyModelConfig | AzureOpenAIOAuth2ModelConfig;
switch (authenticationMethod) {
case AuthenticationType.ApiKey:
modelConfig = await setupApiKeyAuthentication.call(this, 'azureOpenAiApi');
break;
case AuthenticationType.EntraOAuth2:
modelConfig = await setupOAuth2Authentication.call(
this,
'azureEntraCognitiveServicesOAuth2Api',
);
break;
default:
throw new NodeOperationError(this.getNode(), 'Invalid authentication method');
}
this.logger.info(`Instantiating AzureChatOpenAI model with deployment: ${modelName}`);
const timeout = options.timeout;
const model = new AzureChatOpenAI({
// Force completions API — Azure's SDK doesn't rewrite the /responses path,
// so the Responses API hits an invalid endpoint and causes a connection error.
// See: https://github.com/langchain-ai/langchainjs/issues/9038
useResponsesApi: false,
// Model name is required so logs are correct
// Also ensures internal logic (like mapping "maxTokens" to "maxCompletionTokens") is correct
model: modelName,
azureOpenAIApiDeploymentName: modelName,
...modelConfig,
...options,
timeout,
maxRetries: options.maxRetries ?? 2,
callbacks: [new N8nLlmTracing(this)],
configuration: {
fetchOptions: {
dispatcher: getProxyAgent(undefined, {
headersTimeout: timeout,
bodyTimeout: timeout,
}),
},
},
modelKwargs: options.responseFormat
? {
response_format: { type: options.responseFormat },
}
: undefined,
onFailedAttempt: makeN8nLlmFailedAttemptHandler(this),
});
this.logger.info(`Azure OpenAI client initialized for deployment: ${modelName}`);
return {
response: model,
};
} catch (error) {
this.logger.error(`Error in LmChatAzureOpenAi.supplyData: ${error.message}`, error);
// Re-throw NodeOperationError directly, wrap others
if (error instanceof NodeOperationError) {
throw error;
}
throw new NodeOperationError(
this.getNode(),
`Failed to initialize Azure OpenAI client: ${error.message}`,
error,
);
}
}
}