Message Attachments
Overview
This functionality allows users to upload and attach files to chat to get more accurate answers based on the content of the file. The AI can analyze text documents, images, tables, and other formats supported by the platform.
To enable message attachments, pass the enableFileAttachments
through the props.
<ChatPage
enableFileAttachments={true}
// ...other props
/>
Structure
User message content with attachments are of type: MessageUserContent.
For any attachment types, you can pass data in two ways, via url: string
or file: File
.
file
and url
, file
will take priority.const messages = [{
id: '1',
role: 'user',
content: [{
type: 'text',
text: "Describe the files I sent you"
},
{
id: '1',
type: 'image',
url: 'your_image_link', // image source
},
{
id: '2',
type: 'video',
url: 'your_video_link', // video source
},
{
id: '3',
type: 'file',
file: new File(["sample text"], "example.txt", { type: "text/plain" }), // file
}],
}];
Capabilities
Attach Files
You can pre-load a file on your server to improve the performance of sending a message by passing the onFileAttached
method through the props. This feature allows you to retrieve and process the file as you see fit for future use. Please refer to the FileAttachedParams page for more details about parameters.
onFileAttached
- Callback function that is triggered when a user attaches a file in the chat interface. This function receives an object with parameters describing the file and a method to update the upload progress. You can use this callback to handle file uploads, simulate progress, handling errors in interface, or perform validation.
const onFileAttached = async ({ actions }: FileAttachedParams) => {
const { setProgress } = actions;
await fileUploadMock(setProgress);
};
import * as React from "react";
import {
ChatPage,
useAssistantAnswerMock,
Thread,
FileAttachedParams,
} from "@plteam/chat-ui";
import Box from "@mui/material/Box";
const App: React.FC = () => {
const [threads] = React.useState<Thread[]>(
[
{
id: "1",
title: "Attachment Progress",
messages: [
{
id: '1',
content: 'Hello! May I send files in this chat?',
role: "user",
},
{
id: '2',
content: "Hello, yes, you can send files in this chat, and you can also monitor the process of uploading them to the server.",
role: "assistant",
},
],
"date": "2024-11-16 08:07:54"
}
]
);
const { onUserMessageSent, handleStopMessageStreaming } =
useAssistantAnswerMock();
const fileUploadMock = async (callback: (num: number) => void) => {
for (let i = 0; i < 100; i += 10) {
await new Promise(resolve => setTimeout(resolve, 500));
callback(i);
}
};
const onFileAttached = async ({ actions }: FileAttachedParams) => {
const { setProgress } = actions;
await fileUploadMock(setProgress);
};
return (
<Box height="100dvh" width="100dvw">
<ChatPage
enableFileAttachments
initialThread={threads[0]}
threads={threads}
handleStopMessageStreaming={handleStopMessageStreaming}
onUserMessageSent={onUserMessageSent}
onFileAttached={onFileAttached}
/>
</Box>
);
}
export default App;
If you want to send a message regardless of whether the file has been uploaded to the server or not, you can use onFinish
from FileAttachedParams
to prematurely end or skip the upload process in the chat interface.
const onFileAttached = async ({ file, actions }: FileAttachedParams) => {
const { onFinish } = actions;
// finishes loading in the interface
onFinish();
// file upload on server
await fileUploadMock(file);
}
If you encounter an error while uploading a file and want to display it in the interface, you need to use setError
from FileAttachedParams
.
const onFileAttached = ({ actions }: FileAttachedParams) => {
const { setError } = actions;
try {
await fileUploadMock();
} catch {
setError('Server error');
}
};
import * as React from "react";
import {
ChatPage,
useAssistantAnswerMock,
Thread,
} from "@plteam/chat-ui";
import Box from "@mui/material/Box";
import { FileAttachedParams } from "../../../packages/chat-ui/src/models/FileAttachedParams";
const App: React.FC = () => {
const [threads] = React.useState<Thread[]>(
[
{
id: "1",
title: "Attachment Error",
messages: [
{
id: '1',
content: 'Hello! May I send files in this chat?',
role: 'user',
},
{
id: '2',
content: "Hello, you can try, but you will get an error now.",
role: "assistant",
},
],
"date": "2024-11-16 08:07:54"
}
]
);
const { onUserMessageSent, handleStopMessageStreaming } =
useAssistantAnswerMock();
const fileUploadMock = async () => {
await new Promise((_resolve, reject) => setTimeout(reject, 500));
};
const onFileAttached = ({ actions }: FileAttachedParams) => {
const { setError } = actions;
try {
// file upload on server
await fileUploadMock();
} catch {
// set error text in interface
setError('Server error');
}
};
return (
<Box height="100dvh" width="100dvw">
<ChatPage
enableFileAttachments
initialThread={threads[0]}
threads={threads}
handleStopMessageStreaming={handleStopMessageStreaming}
onUserMessageSent={onUserMessageSent}
onFileAttached={onFileAttached}
/>
</Box>
);
}
export default App;
Remove Files
If you need to keep track of files that are deleted before a chat message is sent, you can use the onFileDetached
method. This feature can be used to clean up resources. It allows you to clean up any temporary storage, server database, UI references, or metadata associated with the deleted file.
onFileDetached
- Callback function that is triggered when a user removes (detaches) a file from the chat input before sending the message.
const onFileDetached = async (fileId: string | number) => {
// delete file from server
await fileDeleteMock(fileId);
};
Restrictions
You can further control and filter which files can be uploaded to the interface. Various options are presented below.
<ChatPage
enableFileAttachments
initialThread={threads[0]}
threads={threads}
handleStopMessageStreaming={handleStopMessageStreaming}
acceptableFileFormat={['.png', '.jpg']}
maxFileCount={3}
maxFileSize={10 * 1024 * 1024}
onUserMessageSent={onUserMessageSent}
/>
import * as React from "react";
import {
ChatPage,
useAssistantAnswerMock,
Thread,
} from "@plteam/chat-ui";
import Box from "@mui/material/Box";
const App: React.FC = () => {
const [threads] = React.useState<Thread[]>(
[
{
id: "1",
title: "Attachment Restriction",
messages: [
{
id: '1',
content: 'What are the restrictions on sending files to this chat?',
role: "user",
},
{
id: '2',
content: `The following restrictions apply in this chat:
- Maximum number of files in one message: 3
- The size of a single file cannot exceed 10 MB
- Allowed file types: \`.png\`, \`.jpg\``,
role: "assistant",
},
],
"date": "2024-11-16 08:07:54"
}
]
);
const { onUserMessageSent, handleStopMessageStreaming } =
useAssistantAnswerMock();
return (
<Box height="100dvh" width="100dvw">
<ChatPage
enableFileAttachments
initialThread={threads[0]}
threads={threads}
handleStopMessageStreaming={handleStopMessageStreaming}
acceptableFileFormat={['.png', '.jpg']}
maxFileCount={3}
maxFileSize={10 * 1024 * 1024}
onUserMessageSent={onUserMessageSent}
/>
</Box>
);
}
export default App;
Format
You can control the file formats that can be attached to a message using the acceptableFileFormat
variable in chat props.
acceptableFileFormat
- Specifies the acceptable file types that users are allowed to attach. This can be a single MIME type, an array of MIME types, or file extensions.
By default, there are no restrictions ('*'
).
<ChatPage
enableFileAttachments={true}
acceptableFileFormat='*'
// ...other props
/>
Size
You can limit the maximum file size that can be transferred via the interface using the maxFileSize
variable in chat props.
maxFileSize
- Maximum file size in bytes.
The default limit is 20 MB.
<ChatPage
enableFileAttachments={true}
maxFileSize={20 * 1024 * 1024} // 20 MB
// ...other props
/>
Count
You can limit the number of files that can be attached to a single message using the maxFileCount
variable in chat props.
maxFileCount
- Specifies the maximum number of files.
By default, you can send a maximum of 10 files in a single message.
<ChatPage
enableFileAttachments={true}
maxFileCount={10}
// ...other props
/>
Branching
If the Branching fiche is active you can also delete files in the message editor.
Example
<ChatPage
enableFileAttachments
enableBranches
initialThread={threads[0]}
threads={threads}
handleStopMessageStreaming={handleStopMessageStreaming}
onUserMessageSent={onUserMessageSent}
/>
import * as React from "react";
import {
ChatPage,
useAssistantAnswerMock,
Thread,
} from "@plteam/chat-ui";
import Box from "@mui/material/Box";
const text = `
Both images feature anthropomorphic cats.
The first image shows a fluffy white cat with light blue eyes sitting amidst a bed of roses and other flowers, some in shades of purple and pink. To the right of the cat, there's a glass of what appears to be champagne or a similar sparkling beverage, and behind it, a bottle. The background is a vibrant pink and purple, with what looks like floating bubbles or orbs. The cat has a somewhat serious or inquisitive expression.
The second image depicts a fluffy gray cat dressed in a dark green jacket and a brown bow tie, holding a violin as if playing it. The cat has yellow eyes. It is seated at a wooden table next to a lit candle in a glass pitcher, a silver chalice-like object, and an open book. There's also a slice of lime on the table. The background is dark and moody, with a hint of smoke or mist rising from behind the candle.
`;
const App: React.FC = () => {
const [threads] = React.useState<Thread[]>(
[
{
id: "1",
title: "Attachment",
messages: [
{
id: '1',
content: [
{
type: 'text',
text: "Describe what you see in the images",
},
{
id: '1',
type: 'image',
url: 'https://examples.cuikit.com/files/exampleImage1.jpg',
},
{
id: '2',
type: 'image',
url: 'https://examples.cuikit.com/files/exampleImage2.jpg',
},
],
role: "user",
},
{
id: '2',
parentId: '1',
content: text,
role: "assistant",
},
{
id: '3',
parentId: '2',
content: [
{
type: 'text',
text: "What does this file contain?",
},
{
id: '1',
type: 'file',
url: 'https://examples.cuikit.com/files/exampleText.txt',
},
],
role: "user",
},
{
id: '4',
parentId: '3',
content: `The file contains the text "Hello world".`,
role: "assistant",
},
],
"date": "2024-11-16 08:07:54"
}
]
);
const { onUserMessageSent, handleStopMessageStreaming } =
useAssistantAnswerMock();
return (
<Box height="100dvh" width="100dvw">
<ChatPage
enableFileAttachments
enableBranches
initialThread={threads[0]}
threads={threads}
handleStopMessageStreaming={handleStopMessageStreaming}
onUserMessageSent={onUserMessageSent}
/>
</Box>
);
}
export default App;