mirror of
https://github.com/n8n-io/n8n.git
synced 2026-09-24 23:22:38 +08:00
fix(OpenAI Node): Use new model for text classification (#22130)
This commit is contained in:
@@ -15,7 +15,7 @@ export class OpenAi extends VersionedNodeType {
|
||||
name: 'openAi',
|
||||
icon: { light: 'file:openAi.svg', dark: 'file:openAi.dark.svg' },
|
||||
group: ['transform'],
|
||||
defaultVersion: 2,
|
||||
defaultVersion: 2.1,
|
||||
subtitle: `={{(${prettifyOperation})($parameter.resource, $parameter.operation)}}`,
|
||||
description: 'Message an assistant or GPT, analyze images, generate audio, etc.',
|
||||
codex: {
|
||||
@@ -55,6 +55,7 @@ export class OpenAi extends VersionedNodeType {
|
||||
1.7: new OpenAiV1(baseDescription),
|
||||
1.8: new OpenAiV1(baseDescription),
|
||||
2: new OpenAiV2(baseDescription),
|
||||
2.1: new OpenAiV2(baseDescription),
|
||||
};
|
||||
|
||||
super(nodeVersions, baseDescription);
|
||||
|
||||
Vendored
+102
@@ -0,0 +1,102 @@
|
||||
import { mockDeep } from 'jest-mock-extended';
|
||||
import type { IExecuteFunctions, INode } from 'n8n-workflow';
|
||||
|
||||
import * as transport from '../../../../transport';
|
||||
import * as classify from '../../../../v2/actions/text/classify.operation';
|
||||
|
||||
describe('OpenAI Classify Operation', () => {
|
||||
const executeFunctions = mockDeep<IExecuteFunctions>();
|
||||
const node = {
|
||||
id: '123',
|
||||
name: 'OpenAI Node',
|
||||
type: '@n8n/n8n-nodes-langchain.openAi',
|
||||
typeVersion: 2.1,
|
||||
position: [0, 0],
|
||||
parameters: {},
|
||||
} as INode;
|
||||
const apiRequestSpy = jest.spyOn(transport, 'apiRequest');
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('should use omni-moderation-latest model when version is 2.1', async () => {
|
||||
executeFunctions.getNode.mockReturnValue(node);
|
||||
executeFunctions.getNodeParameter.mockImplementation((param: string) => {
|
||||
const params = {
|
||||
input: 'Lorem ipsum',
|
||||
simplify: false,
|
||||
};
|
||||
return params[param as keyof typeof params];
|
||||
});
|
||||
apiRequestSpy.mockResolvedValueOnce({ results: [{ flagged: true }] });
|
||||
|
||||
const result = await classify.execute.call(executeFunctions, 0);
|
||||
|
||||
expect(apiRequestSpy).toHaveBeenCalledWith('POST', '/moderations', {
|
||||
body: { input: 'Lorem ipsum', model: 'omni-moderation-latest' },
|
||||
});
|
||||
expect(result).toEqual([
|
||||
{
|
||||
json: { flagged: true },
|
||||
pairedItem: { item: 0 },
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should use text-moderation-stable model when version is less than 2.1 and useStableModel is true', async () => {
|
||||
executeFunctions.getNode.mockReturnValue({
|
||||
...node,
|
||||
typeVersion: 2,
|
||||
});
|
||||
executeFunctions.getNodeParameter.mockImplementation((param: string) => {
|
||||
const params = {
|
||||
input: 'Lorem ipsum',
|
||||
simplify: false,
|
||||
options: { useStableModel: true },
|
||||
};
|
||||
return params[param as keyof typeof params];
|
||||
});
|
||||
apiRequestSpy.mockResolvedValueOnce({ results: [{ flagged: true }] });
|
||||
|
||||
const result = await classify.execute.call(executeFunctions, 0);
|
||||
|
||||
expect(apiRequestSpy).toHaveBeenCalledWith('POST', '/moderations', {
|
||||
body: { input: 'Lorem ipsum', model: 'text-moderation-stable' },
|
||||
});
|
||||
expect(result).toEqual([
|
||||
{
|
||||
json: { flagged: true },
|
||||
pairedItem: { item: 0 },
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should use text-moderation-latest model when version is less than 2.1 and useStableModel is false', async () => {
|
||||
executeFunctions.getNode.mockReturnValue({
|
||||
...node,
|
||||
typeVersion: 2,
|
||||
});
|
||||
executeFunctions.getNodeParameter.mockImplementation((param: string) => {
|
||||
const params = {
|
||||
input: 'Lorem ipsum',
|
||||
simplify: false,
|
||||
options: { useStableModel: false },
|
||||
};
|
||||
return params[param as keyof typeof params];
|
||||
});
|
||||
apiRequestSpy.mockResolvedValueOnce({ results: [{ flagged: true }] });
|
||||
|
||||
const result = await classify.execute.call(executeFunctions, 0);
|
||||
|
||||
expect(apiRequestSpy).toHaveBeenCalledWith('POST', '/moderations', {
|
||||
body: { input: 'Lorem ipsum', model: 'text-moderation-latest' },
|
||||
});
|
||||
expect(result).toEqual([
|
||||
{
|
||||
json: { flagged: true },
|
||||
pairedItem: { item: 0 },
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -23,7 +23,7 @@ export class OpenAiV2 implements INodeType {
|
||||
constructor(baseDescription: INodeTypeBaseDescription) {
|
||||
this.description = {
|
||||
...baseDescription,
|
||||
version: [2],
|
||||
version: [2, 2.1],
|
||||
defaults: {
|
||||
name: 'OpenAI',
|
||||
},
|
||||
|
||||
+11
-2
@@ -38,6 +38,11 @@ const properties: INodeProperties[] = [
|
||||
'Whether to use the stable version of the model instead of the latest version, accuracy may be slightly lower',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
'@version': [{ _cnd: { lt: 2.1 } }],
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -52,8 +57,12 @@ export const description = updateDisplayOptions(displayOptions, properties);
|
||||
|
||||
export async function execute(this: IExecuteFunctions, i: number): Promise<INodeExecutionData[]> {
|
||||
const input = this.getNodeParameter('input', i) as string;
|
||||
const options = this.getNodeParameter('options', i);
|
||||
const model = options.useStableModel ? 'text-moderation-stable' : 'text-moderation-latest';
|
||||
const version = this.getNode().typeVersion;
|
||||
let model = 'omni-moderation-latest';
|
||||
if (version < 2.1) {
|
||||
const options = this.getNodeParameter('options', i);
|
||||
model = options.useStableModel ? 'text-moderation-stable' : 'text-moderation-latest';
|
||||
}
|
||||
|
||||
const body = {
|
||||
input,
|
||||
|
||||
Reference in New Issue
Block a user