Skip to content

Commit 0908b77

Browse files
committed
feat: employ strategies for vision requests
1 parent c05d3b0 commit 0908b77

File tree

4 files changed

+56
-21
lines changed

4 files changed

+56
-21
lines changed

api/server/services/Files/Firebase/images.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const path = require('path');
33
const sharp = require('sharp');
44
const { saveBufferToFirebase } = require('./crud');
55
const { resizeImage } = require('../images/resize');
6+
const { updateFile } = require('~/models');
67

78
/**
89
* Converts an image file to the WebP format. The function first resizes the image based on the specified
@@ -50,4 +51,19 @@ async function uploadImageToFirebase(req, file, resolution = 'high') {
5051
return { filepath: downloadURL, bytes, width, height };
5152
}
5253

53-
module.exports = { uploadImageToFirebase };
54+
/**
55+
* Local: Updates the file and returns the URL in expected order/format
56+
* for image payload handling: tuple order of [filepath, URL].
57+
* @param {Object} req - The request object.
58+
* @param {MongoFile} file - The file object.
59+
* @returns {Promise<[MongoFile, string]>} - A promise that resolves to an array of results from updateFile and encodeImage.
60+
*/
61+
async function prepareImageURL(req, file) {
62+
const { filepath } = file;
63+
const promises = [];
64+
promises.push(updateFile({ file_id: file.file_id }));
65+
promises.push(filepath);
66+
return await Promise.all(promises);
67+
}
68+
69+
module.exports = { uploadImageToFirebase, prepareImageURL };

api/server/services/Files/Local/images.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,13 @@ function encodeImage(imagePath) {
7474
}
7575

7676
/**
77-
* Local: Updates the file and encodes the image.
77+
* Local: Updates the file and encodes the image to base64,
78+
* for image payload handling: tuple order of [filepath, base64].
7879
* @param {Object} req - The request object.
7980
* @param {MongoFile} file - The file object.
80-
* @returns {Promise<[MongoFile, string]>} - A promise that resolves to an array of results from updateFile and encodeImage.
81+
* @returns {Promise<[MongoFile, string]>} - A promise that resolves to an array of results from updateFile and encodeImage.
8182
*/
82-
async function encodeLocal(req, file) {
83+
async function prepareImagesLocal(req, file) {
8384
const { publicPath, imageOutput } = req.app.locals.paths;
8485
const userPath = path.join(imageOutput, req.user.id);
8586

@@ -94,4 +95,4 @@ async function encodeLocal(req, file) {
9495
return await Promise.all(promises);
9596
}
9697

97-
module.exports = { uploadLocalImage, encodeImage, encodeLocal };
98+
module.exports = { uploadLocalImage, encodeImage, prepareImagesLocal };

api/server/services/Files/images/encode.js

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
const { EModelEndpoint, FileSources } = require('librechat-data-provider');
2-
const { encodeLocal } = require('../Local/images');
3-
4-
const encodeStrategies = {
5-
[FileSources.local]: encodeLocal,
6-
};
2+
const { getStrategyFunctions } = require('../strategies');
73

84
/**
95
* Encodes and formats the given files.
@@ -13,32 +9,45 @@ const encodeStrategies = {
139
* @returns {Promise<Object>} - A promise that resolves to the result object containing the encoded images and file details.
1410
*/
1511
async function encodeAndFormat(req, files, endpoint) {
16-
const { fileStrategy } = req.app.locals;
17-
/**
18-
* @type {function(Express.Request, MongoFile): Promise<[MongoFile, string]>}
19-
*/
20-
const updateAndEncode = encodeStrategies[fileStrategy];
21-
2212
const promises = [];
13+
const encodingMethods = {};
14+
2315
for (let file of files) {
24-
promises.push(updateAndEncode(req, file));
16+
const source = file.source ?? FileSources.local;
17+
18+
if (encodingMethods[source]) {
19+
promises.push(encodingMethods[source](req, file));
20+
continue;
21+
}
22+
23+
const { prepareImagePayload } = getStrategyFunctions(source);
24+
if (!prepareImagePayload) {
25+
throw new Error(`Encoding function not implemented for ${source}`);
26+
}
27+
28+
encodingMethods[source] = prepareImagePayload;
29+
promises.push(prepareImagePayload(req, file));
2530
}
2631

2732
// TODO: make detail configurable, as of now resizing is done
2833
// to prefer "high" but "low" may be used if the image is small enough
2934
const detail = req.body.detail ?? 'auto';
30-
const encodedImages = await Promise.all(promises);
35+
36+
/** @type {Array<[MongoFile, string]>} */
37+
const formattedImages = await Promise.all(promises);
3138

3239
const result = {
3340
files: [],
3441
image_urls: [],
3542
};
3643

37-
for (const [file, base64] of encodedImages) {
44+
for (const [file, imageContent] of formattedImages) {
3845
const imagePart = {
3946
type: 'image_url',
4047
image_url: {
41-
url: `data:image/webp;base64,${base64}`,
48+
url: imageContent.startsWith('http')
49+
? imageContent
50+
: `data:image/webp;base64,${imageContent}`,
4251
detail,
4352
},
4453
};

api/server/services/Files/strategies.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,24 @@ const {
33
getFirebaseURL,
44
saveURLToFirebase,
55
deleteFirebaseFile,
6+
prepareImageURL,
67
uploadImageToFirebase,
78
} = require('./Firebase');
8-
const { getLocalFileURL, saveFileFromURL, deleteLocalFile, uploadLocalImage } = require('./Local');
9+
const {
10+
getLocalFileURL,
11+
saveFileFromURL,
12+
deleteLocalFile,
13+
uploadLocalImage,
14+
prepareImagesLocal,
15+
} = require('./Local');
916

1017
// Firebase Strategy Functions
1118
const firebaseStrategy = () => ({
1219
// saveFile:
1320
saveURL: saveURLToFirebase,
1421
getFileURL: getFirebaseURL,
1522
deleteFile: deleteFirebaseFile,
23+
prepareImagePayload: prepareImageURL,
1624
handleImageUpload: uploadImageToFirebase,
1725
});
1826

@@ -23,6 +31,7 @@ const localStrategy = () => ({
2331
getFileURL: getLocalFileURL,
2432
deleteFile: deleteLocalFile,
2533
handleImageUpload: uploadLocalImage,
34+
prepareImagePayload: prepareImagesLocal,
2635
});
2736

2837
// Strategy Selector

0 commit comments

Comments
 (0)