fix(Basic LLM Chain Node): Use correct mimetype for binary data (#12978)

This commit is contained in:
jeanpaul 2025-02-07 09:49:11 +01:00 committed by GitHub
parent 9e4e1ca1f4
commit 2b1eb049f2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 56 additions and 13 deletions

View file

@ -34,6 +34,7 @@ import { getOptionalOutputParsers } from '@utils/output_parsers/N8nOutputParser'
import { getTemplateNoticeField } from '@utils/sharedFields';
import { getTracingConfig } from '@utils/tracing';
import { dataUriFromImageData, UnsupportedMimeTypeError } from './utils';
import {
getCustomErrorMessage as getCustomOpenAiErrorMessage,
isOpenAiError,
@ -88,21 +89,28 @@ async function getImageMessage(
NodeConnectionType.AiLanguageModel,
0,
)) as BaseLanguageModel;
const dataURI = `data:image/jpeg;base64,${bufferData.toString('base64')}`;
const directUriModels = [ChatGoogleGenerativeAI, ChatOllama];
const imageUrl = directUriModels.some((i) => model instanceof i)
? dataURI
: { url: dataURI, detail };
try {
const dataURI = dataUriFromImageData(binaryData, bufferData);
return new HumanMessage({
content: [
{
type: 'image_url',
image_url: imageUrl,
},
],
});
const directUriModels = [ChatGoogleGenerativeAI, ChatOllama];
const imageUrl = directUriModels.some((i) => model instanceof i)
? dataURI
: { url: dataURI, detail };
return new HumanMessage({
content: [
{
type: 'image_url',
image_url: imageUrl,
},
],
});
} catch (error) {
if (error instanceof UnsupportedMimeTypeError)
throw new NodeOperationError(context.getNode(), error.message);
throw error;
}
}
async function getChainPromptTemplate(

View file

@ -0,0 +1,23 @@
import { mock } from 'jest-mock-extended';
import type { IBinaryData } from 'n8n-workflow';
import { dataUriFromImageData, UnsupportedMimeTypeError } from '../utils';
describe('dataUriFromImageData', () => {
it('should not throw an error on images', async () => {
const mockBuffer = Buffer.from('Test data');
const mockBinaryData = mock<IBinaryData>({ mimeType: 'image/jpeg' });
const dataUri = dataUriFromImageData(mockBinaryData, mockBuffer);
expect(dataUri).toBe('data:image/jpeg;base64,VGVzdCBkYXRh');
});
it('should throw an UnsupportetMimeTypeError on non-images', async () => {
const mockBuffer = Buffer.from('Test data');
const mockBinaryData = mock<IBinaryData>({ mimeType: 'text/plain' });
expect(() => {
dataUriFromImageData(mockBinaryData, mockBuffer);
}).toThrow(UnsupportedMimeTypeError);
});
});

View file

@ -0,0 +1,12 @@
import type { IBinaryData } from 'n8n-workflow';
import { ApplicationError } from 'n8n-workflow';
export class UnsupportedMimeTypeError extends ApplicationError {}
export function dataUriFromImageData(binaryData: IBinaryData, bufferData: Buffer) {
if (!binaryData.mimeType?.startsWith('image/'))
throw new UnsupportedMimeTypeError(
`${binaryData.mimeType} is not a supported type of binary data. Only images are supported.`,
);
return `data:${binaryData.mimeType};base64,${bufferData.toString('base64')}`;
}