mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 08:50:15 +01:00
🗃️ feat: General File Support for OpenAI, Azure, Custom, Anthropic and Google (RAG) (#2143)
* refactor: re-purpose `resendImages` as `resendFiles` * refactor: re-purpose `resendImages` as `resendFiles` * feat: upload general files * feat: embed file during upload * feat: delete file embeddings on file deletion * chore(fileConfig): add epub+zip type * feat(encodeAndFormat): handle non-image files * feat(createContextHandlers): build context prompt from file attachments and successful RAG * fix: prevent non-temp files as well as embedded files to be deleted on new conversation * fix: remove temp_file_id on usage, prevent non-temp files as well as embedded files to be deleted on new conversation * fix: prevent non-temp files as well as embedded files to be deleted on new conversation * feat(OpenAI/Anthropic/Google): basic RAG support * fix: delete `resendFiles` only when true (Default) * refactor(RAG): update endpoints and pass JWT * fix(resendFiles): default values * fix(context/processFile): query unique ids only * feat: rag-api.yaml * feat: file upload improved ux for longer uploads * chore: await embed call and catch embedding errors * refactor: store augmentedPrompt in Client * refactor(processFileUpload): throw error if not assistant file upload * fix(useFileHandling): handle markdown empty mimetype issue * chore: necessary compose file changes
This commit is contained in:
parent
af347cccde
commit
f7761df52c
38 changed files with 683 additions and 261 deletions
|
|
@ -9,6 +9,7 @@ import {
|
|||
} from 'librechat-data-provider';
|
||||
import type { ExtendedFile, FileSetter } from '~/common';
|
||||
import { useUploadFileMutation, useGetFileConfig } from '~/data-provider';
|
||||
import { useDelayedUploadToast } from './useDelayedUploadToast';
|
||||
import { useToastContext } from '~/Providers/ToastContext';
|
||||
import { useChatContext } from '~/Providers/ChatContext';
|
||||
import useUpdateFiles from './useUpdateFiles';
|
||||
|
|
@ -24,6 +25,7 @@ type UseFileHandling = {
|
|||
const useFileHandling = (params?: UseFileHandling) => {
|
||||
const { showToast } = useToastContext();
|
||||
const [errors, setErrors] = useState<string[]>([]);
|
||||
const { startUploadTimer, clearUploadTimer } = useDelayedUploadToast();
|
||||
const { files, setFiles, setFilesLoading, conversation } = useChatContext();
|
||||
const setError = (error: string) => setErrors((prevErrors) => [...prevErrors, error]);
|
||||
const { addFile, replaceFile, updateFileById, deleteFileById } = useUpdateFiles(
|
||||
|
|
@ -72,6 +74,7 @@ const useFileHandling = (params?: UseFileHandling) => {
|
|||
|
||||
const uploadFile = useUploadFileMutation({
|
||||
onSuccess: (data) => {
|
||||
clearUploadTimer(data.temp_file_id);
|
||||
console.log('upload success', data);
|
||||
updateFileById(
|
||||
data.temp_file_id,
|
||||
|
|
@ -95,6 +98,7 @@ const useFileHandling = (params?: UseFileHandling) => {
|
|||
width: data.width,
|
||||
filename: data.filename,
|
||||
source: data.source,
|
||||
embedded: data.embedded,
|
||||
},
|
||||
params?.additionalMetadata?.assistant_id ? true : false,
|
||||
);
|
||||
|
|
@ -103,6 +107,7 @@ const useFileHandling = (params?: UseFileHandling) => {
|
|||
onError: (error, body) => {
|
||||
console.log('upload error', error);
|
||||
const file_id = body.get('file_id');
|
||||
clearUploadTimer(file_id as string);
|
||||
deleteFileById(file_id as string);
|
||||
setError(
|
||||
(error as { response: { data: { message?: string } } })?.response?.data?.message ??
|
||||
|
|
@ -117,6 +122,8 @@ const useFileHandling = (params?: UseFileHandling) => {
|
|||
return;
|
||||
}
|
||||
|
||||
startUploadTimer(extendedFile.file_id, extendedFile.file?.name || 'File');
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('file', extendedFile.file as File);
|
||||
formData.append('file_id', extendedFile.file_id);
|
||||
|
|
@ -159,7 +166,27 @@ const useFileHandling = (params?: UseFileHandling) => {
|
|||
}
|
||||
|
||||
for (let i = 0; i < fileList.length; i++) {
|
||||
const originalFile = fileList[i];
|
||||
let originalFile = fileList[i];
|
||||
let fileType = originalFile.type;
|
||||
|
||||
// Infer MIME type for Markdown files when the type is empty
|
||||
if (!fileType && originalFile.name.endsWith('.md')) {
|
||||
fileType = 'text/markdown';
|
||||
}
|
||||
|
||||
// Check if the file type is still empty after the extension check
|
||||
if (!fileType) {
|
||||
setError('Unable to determine file type for: ' + originalFile.name);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Replace empty type with inferred type
|
||||
if (originalFile.type !== fileType) {
|
||||
const newFile = new File([originalFile], originalFile.name, { type: fileType });
|
||||
originalFile = newFile;
|
||||
fileList[i] = newFile;
|
||||
}
|
||||
|
||||
if (!checkType(originalFile.type, supportedMimeTypes)) {
|
||||
console.log(originalFile);
|
||||
setError('Currently, unsupported file type: ' + originalFile.type);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue