File Attachments
Enable file uploads by passing an UploadManager, Upload, or any custom AIFileReceiver implementation to the builder via withFileReceiver(). Uploaded files are sent to the LLM as attachments with the next prompt.
Source code
Java
var uploadManager = new UploadManager(this);
var uploadButton = new UploadButton(uploadManager);
var orchestrator = AIOrchestrator
.builder(provider, systemPrompt)
.withMessageList(messageList)
.withInput(messageInput)
.withFileReceiver(uploadManager)
.build();|
Note
|
Upload Handler Conflict
When using UploadManager or Upload, the component must not already have an upload handler set, and an Upload must not have a receiver either. The orchestrator installs its own in-memory handler. If one is already set, withFileReceiver() throws an IllegalArgumentException. This restriction does not apply to custom AIFileReceiver implementations.
|
|
Note
|
Supported Attachment Types
The following MIME type categories are supported: images (image/), text (text/), PDF (application/pdf or application/x-pdf), audio (audio/), and video (video/). An attachment with any other MIME type still appears in the Message List, but the built-in providers leave its content out of the request, so the LLM never sees it. To send such a file anyway, convert it to a supported format with a request interceptor.
|
|
Note
|
Duplicate File Names
Uploading a file whose name matches one that is still pending, that is, uploaded but not yet sent with a prompt, throws an IllegalArgumentException. Removing the earlier file from the upload list frees the name, and once a prompt has consumed the pending files, the name can be used again.
|
Persisting Attachments
The orchestrator passes attachments to the LLM with each request but does not store them afterward. To save attachments to your own storage and look them up later — for example when the user clicks one in the message list — use withRequestListener() (see Request & Response Listeners) and withAttachmentClickListener():
Source code
Java
var orchestrator = AIOrchestrator
.builder(provider, systemPrompt)
.withMessageList(messageList)
.withInput(messageInput)
.withFileReceiver(uploadManager)
.withRequestListener(event -> {
// Store attachments keyed by message ID
saveAttachments(event.getMessageId(),
event.getAttachments());
})
.withAttachmentClickListener(event -> {
// Retrieve and display the attachment
showAttachment(event.getMessageId(),
event.getAttachmentIndex());
})
.build();saveAttachments and showAttachment are placeholders for application code. The former persists the AIAttachment data, while the latter loads it back and displays it.
Programmatic Attachments
Use prompt(message, attachments) to send a prompt and attachments from application code — a file the user dropped on the form, a PDF the application generated, or content fetched from a service. No chat UI is needed.
Source code
Java
var attachment = new AIAttachment("receipt.png", "image/png", receiptBytes);
orchestrator.prompt("Fill the form from this receipt",
List.of(attachment));AIAttachment is a record with name(), mimeType(), and data() (raw bytes). All three are required.
From a Vaadin Upload
UploadHandler.inMemory() is the simplest way to receive a file as a byte array. The callback runs on the UI thread, so prompt(…) can be called directly:
Source code
Java
var handler = UploadHandler.inMemory((metadata, data) -> {
var attachment = new AIAttachment(metadata.fileName(),
metadata.contentType(), data);
orchestrator.prompt("Fill the form from this receipt",
List.of(attachment));
});
var upload = new Upload(handler);The same handler can be passed to UploadManager.
|
Note
|
Mixing With Chat Attachments
prompt(message, attachments) sends only the supplied list. Anything already queued in a configured AIFileReceiver stays there for the next prompt(message) call or chat submit — the two paths do not share state.
|