The change feed shows which of your files changed, as it happens. A client reads it as an event stream. A change can come from anywhere: you in another tab, a chat that wrote a file with a tool, an upload, a trigger run, a connector, another API client, or another frontend of a cluster. The web UI uses it to refresh what it shows without a reload.
The files are the workspace of the chats, so the feed needs the chats feature, which is on by default. When the server has no files (no data path), the stream answers 409 with the type files_off.
Subsections of Files and documents
Files and shared folders
Note
Needs a build newer than 4.12.1. In the current development builds.
LocalAI keeps a workspace for each user. It holds your files and folders, the files that a chat reads or writes, and a Trash with a history. The Files page in the sidebar is the browser for it.
Note
Files need the chats of the server. The chats and their files must be on. See Chats. On a server with accounts, an administrator can turn the chats feature off for a user. That user then has no Files page.
Upload and organise
Open Files in the sidebar.
Choose Upload, or drop files or folders on the page, or paste with Ctrl+V.
Choose New folder to make a folder. Drag rows onto a folder to move them.
You can upload files of any type. A file can be 256 MiB at most. An administrator can set a smaller limit with --upload-limit. If a file has the name of a file that is in the folder already, the page asks you to replace it, keep both or skip it.
Each row has a menu. It offers preview, download, rename, move and Move to Trash. Nothing is erased until you empty the Trash. The Trash tab restores a file, and the History tab undoes a change.
LocalAI keeps two folders for itself. LocalAI/ holds your settings. Chats/ holds one folder for each chat. They show at the end of the list under Managed by LocalAI.
Find a file
Type in the box to filter the open folder by name. Press Enter to search the names and the text of all your files. The search reads the text of PDF, Word, Excel and PowerPoint files too. A scanned PDF has no text layer, so it is found by name only. Details are in Search inside documents.
Unpack an archive
Choose Extract here in the menu of an archive. The server unpacks it into a new folder next to the archive. One Undo removes the whole result. ZIP and TAR archives work. An administrator can allow 7z and RAR, but the readers for them have a known risk. Read Extract an archive before you allow them.
Use a file in a chat
A chat can use your files in two ways.
Attach a file to a message. The file is saved in the folder of the chat, and the model gets its path.
Ask the model to work with your files. A chat has file tools to list, read, search, write and edit files. They change your files like you do, so every change is in the history and you can undo it.
The model can read the text of PDF, Word, Excel and PowerPoint files. It can also look at images and transcribe audio when a model for that is installed. To run commands or code on the files, install the Sandbox add-on. To make Word, Excel, PowerPoint and PDF files, see Office documents.
A saved agent can work in chosen folders only, each as read or write. Without folders, an agent works on all your files. See Folders of an agent.
Share folders
Your files are private to your account until you share something. There are two kinds of sharing.
A shared folder is made by an administrator. It is a folder that several people use. The administrator chooses the members: a person, or Everyone, each with Can read or Can edit. Members see the folder in the Shared tab of Files. Their chats see it at /workspace/shared-<name>, and it is read only for a reader. A person who is not a member sees nothing.
A folder of your home can be shared by you. Choose Share… in the menu of the folder, then add a person or Everyone, with Can read or Can edit. You can share a folder inside your home. You cannot share the home itself, or the folders that LocalAI keeps. Sharing needs a server with accounts.
Sharing is a change that only a person makes in their own browser session. A model, an agent or an add-on cannot share a folder. For the rules, see Users and sharing and Shared folders.
Limits
Limit
Value
One file
256 MiB, or the --upload-limit value when it is smaller
Add-ons need a development build or a release newer than 4.12.1.
A chat can make and edit Word (.docx), Excel (.xlsx), PowerPoint (.pptx) and PDF files. There are two ways. Both are add-ons from the add-on library. Neither is built in. LocalAI has no built-in fallback when none is installed.
Simple Office
Sandbox
What it is
An add-on with document tools
An add-on that runs Python in an isolated runtime
Needs a VM or gVisor
No
Yes
Makes
.docx and .pdf from Markdown, .xlsx from CSV, .pptx, and edits files
Any document that a Python library can write
Control over layout
Basic
Full, with the libraries in the guest image
Platforms
Linux and macOS
Linux
Use Simple Office when you want a quick document and your host cannot run a sandbox. Use the Sandbox when you need charts, exact layout or a conversion. In the current development builds, both add-ons are in the development channel of the library.
The two add-ons work on their own. LocalAI does not route between them and does not change the choice for you.
Simple Office
Install office from the add-on library. Its visible name is Simple Office. Its internal ID, tool names and settings use office. It has 11 tools: read, edit and create for Word, Excel and PowerPoint, and read and create for PDF.
Files are saved in your files at the path that the model gives. If the path is taken, LocalAI saves the new file next to the old one. It does not change the old one.
Example: ask “Write a one-page summary of the notes in /Research as a Word file”. The model reads the notes with the file tools and calls create-docx. Open the file in Files. The preview pane shows the text, but not the formatting.
Make a Word or PDF file from Markdown
create-docx and create-pdf take a path and a markdown string. The optional title is metadata. It does not add a heading to the page.
Use a .pdf path with create-pdf. Both formats support:
headings and paragraphs
bullet and numbered lists
bold and italic text
simple rectangular tables
Code is literal text. LocalAI does not run it. Links show their label and are not fetched. The tools refuse raw HTML, images and other unsupported parts with an error. They use no network, no file inclusion, no macros, no shell commands and no outside converters.
Make a one-sheet workbook from CSV
create-xlsx takes a path and a csv string. The optional sheet names the sheet and defaults to Sheet1. The optional title is metadata.
CSV uses commas and standard quoting. Lines end with LF or CRLF. There is no delimiter guessing.
The tool makes exactly one sheet. The first row is ordinary data.
Every field is stored as a string. Leading zeros stay, and values that begin with =, +, - or @ are not turned into formulas.
Empty cells stay empty.
To get numeric cells, formulas or more sheets, use edit-xlsx after you create the file.
The tool refuses bad quoting, rows of different length, empty content and invalid sheet names.
Limits
Item
Limit
Blocks in a Word or PDF document
2000
Items in a list
100
Table columns
20
Table body rows
500
Rows in a created sheet
5000
Columns in a created sheet
200
Cells in a created sheet, empty ones included
100000
JSON argument of a tool call
1 MiB
The PDF tool supports Latin-1 characters only. It refuses other characters before it saves a file. A failed call saves no file.
All paths are in your own workspace. Chat folder rules and read-only access still apply. create-docx, create-pdf and create-xlsx no longer accept the old blocks and sheets arguments. Use markdown or csv. For the tool contract, see the add-on contract reference.
With the Sandbox
When the Sandbox is installed and isolated commands work, the docx, xlsx, pdf and pptx skills give the model Python procedures. You must switch the Sandbox on for the chat, and a saved agent must be granted the add-on. See Document skills. If both add-ons can serve a skill name, the choice in Settings > Tools decides. Without a choice, the one installed first serves it.
Preview
The Files page and the chat show a preview of a document: the text of a Word file, the first 200 rows and 30 columns of each sheet, and the slides of a deck. Formatting is not shown. Download the file to see it in Office.
Knowledge (collections)
Note
Needs a build newer than 4.12.1. In the current development builds.
Knowledge is the part of LocalAI that holds collections of documents that agents
can search. In the web UI it is the Knowledge item in the sidebar. Each item
in it is a collection: a named set of documents that LocalAI splits into chunks and
stores as embeddings. You can search a collection by meaning. A
saved agent can list the collections it may search,
and a chat with that agent gets the tools list_collections
and search_collection.
Collections are on by default. To turn them off, set LOCALAI_DISABLE_COLLECTIONS=true.
The name of this variable is old: it now turns off the collections only.
How it works
You create a collection and upload files to it, or you add a URL as a source.
LocalAI splits each document into chunks no larger than LOCALAI_COLLECTIONS_MAX_CHUNKING_SIZE.
It calls the embedding model to turn each chunk into a vector, and stores the vectors in the vector engine.
A search embeds the query and returns the closest chunks.
With the default chromem engine a search is semantic only: it finds chunks by
meaning and does not match exact words or codes. The postgres engine adds a
keyword search (BM25) and mixes the two results (hybrid search).
The embedding calls go to the LocalAI API of the same server, inside the
process, so they need no API key and work with user accounts. The embedding
model must be installed. The default is granite-embedding-107m-multilingual.
When it is not, the embeddings endpoint answers 404 and every upload and
search fails. The Knowledge page then says No embedding model installed
and names the model; an administrator gets a button that opens the Models
page with a search for it. GET /api/collections reports the same in
embedding_model and embedding_model_installed.
The Knowledge page also shows how a search finds passages, for example
Search: semantic. GET /api/collections reports it in search_mode: semantic
for the chromem engine, and hybrid for the postgres engine.
The same answer gives max_chunk_size and chunk_overlap, the chunking of a
text in characters.
Who sees a collection
With authentication off, there is one set of collections.
With authentication on, each user has their own collections. A user needs the collections feature. Admins always have it.
A name that is not yours answers 404. Nobody sees another user’s collections, with two exceptions for admins below, and the collections other people share with you.
Sharing a collection
With accounts, the owner of a collection can share it. Open Knowledge, open the
collection and choose Share. The Share dialog
finds people by name and can share with Everyone, every account of the server.
A person can receive it when their account may use collections.
Role
What the person may do
Can view (viewer)
Search it and read its entries and files.
Can edit (editor)
Also add and remove entries.
Sources, reset and sharing stay with the owner. A person with either role cannot
list the sources either (GET /{name}/sources answers 403): a source URL can
carry a credential. A shared collection is listed under Shared with you with the
owner’s name and the role.
The agents and the chats of the person find a shared collection by its name, like
their own. The person’s own collection wins a name. When the person has a collection
of the same name, or two people share collections under one name, the shared one is
named shared:<id>, where <id> is its ID in the sharing API. That name works in
every path below and in the collections of a saved agent. GET /api/collections
gives the name to use.
Nothing is copied: a shared collection stays in its owner’s store, and an entry that
an editor adds is in the owner’s collection. When the owner lowers or removes a
share, LocalAI cancels the person’s running searches and writes on it before it
answers, and the next call answers 404, as for a collection that does not exist. A
download of an entry file (GET /{name}/entries-raw/{entry}) runs under the share
too: a lowering or a revocation stops it, and answers only once no more bytes of the
file are sent. A call that the role does not allow answers 403.
API
All paths are under /api/collections. While the service starts, every
path answers 503 with collections are starting, please retry shortly.
When collections are off, the paths do not exist.
Method and path
Body
Result
GET /
{"collections": [...], "count": n, "shared": [...], "shares": {...}, "sharing": true}. shared are the collections shared with you, each with name (the name to use), title (its own name), owner and role. shares maps each of your collections that you made shareable to resource_id and shared_with. sharing is false when this server cannot share.
POST /
{"name": "docs"}
201 with {"status": "ok", "name": "docs"}
POST /{name}/upload
multipart form, field file
{"status": "ok", "filename": "...", "key": "..."}
GET /{name}/entries
{"entries": [...], "count": n}
GET /{name}/entries/{entry}
{"content": "...", "chunk_count": n}
GET /{name}/entries-raw/{entry}
The file as you uploaded it
POST /{name}/search
{"query": "...", "max_results": 5}
{"results": [...], "count": n}
DELETE /{name}/entry/delete
{"entry": "file.pdf"}
{"remaining_entries": [...], "count": n}
POST /{name}/reset
Deletes every entry and keeps the collection and its sources. {"status": "ok"}
GET /{name}/sources
{"sources": [...], "count": n}
POST /{name}/sources
{"url": "https://...", "update_interval": 60}
Follows the URL. {"status": "ok"}
DELETE /{name}/sources
{"url": "https://..."}
Stops following the URL
POST /{name}/share
Only the owner. {"resource_id": "...", "shared_with": n}, the ID of the collection in /api/shares/collection. 409 with type sharing_disabled when this server cannot share.
Example:
curl -X POST http://localhost:8080/api/collections \
-H "Content-Type: application/json" -d '{"name": "docs"}'curl -X POST http://localhost:8080/api/collections/docs/upload -F file=@manual.pdf
curl -X POST http://localhost:8080/api/collections/docs/search \
-H "Content-Type: application/json" -d '{"query": "how do I reset the device?", "max_results": 3}'
Notes:
update_interval is in minutes. A value below 1 means 60.
Names and entries with special characters, such as :, must be URL-encoded in the path.
A 404 means the collection or the entry does not exist for you.
A search for more passages than the collection holds returns all of them. An empty collection returns none.
/readyz answers 200 only after the collections are ready, so /api/collections does not answer 503 once the server is in rotation.
An upload can fail with 409 when the embedding model changed and the vectors have a different size. Restart LocalAI to embed the collection again, or reset the collection.
Admin options
With authentication on, an admin can add these query parameters:
?all_users=true on GET / also returns the collections of every other user, in user_groups, keyed by user ID.
?user_id=<id> on every path except GET / and POST / works on the collections of that user. Only an administrator may use it.
Other users cannot use either parameter. user_id is ignored for them and they always work on their own collections.
Settings
Set these as environment variables or flags. Most can also be set in the
runtime settings file, and a change needs a restart.
Variable
Default
Meaning
LOCALAI_DISABLE_COLLECTIONS
false
Turn the collections off.
LOCALAI_COLLECTIONS_STATE_DIR
The data path (LOCALAI_DATA_PATH), then the configuration folder
Where the collections keep their files. With authentication on, each user has a folder users/<id> inside it.
LOCALAI_COLLECTIONS_DB_PATH
collections inside the state directory
Where the vector engine keeps its data.
LOCALAI_COLLECTIONS_VECTOR_ENGINE
chromem
The vector engine: chromem (files on disk) or postgres.
LOCALAI_COLLECTIONS_DATABASE_URL
empty
The PostgreSQL URL. Used with the postgres engine.
LOCALAI_COLLECTIONS_EMBEDDING_MODEL
granite-embedding-107m-multilingual
The model that makes the embeddings.
LOCALAI_COLLECTIONS_MAX_CHUNKING_SIZE
400
The largest size of a chunk.
LOCALAI_COLLECTIONS_CHUNK_OVERLAP
0
How much neighbouring chunks overlap.
LOCALAI_COLLECTIONS_API_URL
The LocalAI API of this server
The API that the embedding calls go to. Set it only with a key: the calls then leave the process.
LOCALAI_COLLECTIONS_API_KEY
The first API key of LocalAI
The key for those calls. Without it the embedding calls run inside the process and need none.
LOCALAI_COLLECTIONS_DEFAULT_MODEL
empty
The default model of the collections service.
PostgreSQL vector engine
The default engine keeps the vectors in files on the local disk. To keep them in
PostgreSQL, use a PostgreSQL database and set:
The docker-compose.yaml of the project has a commented example with a
PostgreSQL service. With several frontends in
distributed mode, use the postgres engine, so
that all frontends share the same collections.
The shares of the collections are records in the policy store of the add-on owner,
keyed by the owner and the name of the collection. A search or a write on a shared
collection runs as admitted work of that policy, which only the owner process holds.
With several frontends, a frontend asks the owner over the add-on carrier: it lists
the shared collections, makes a collection shareable and has each search or write
admitted by the owner, then runs it itself. A revocation on any frontend stops that
work before it answers. When a frontend cannot reach the owner, it stops the work
on shared collections, lists none under shared and answers as for a collection
that does not exist; a person’s own collections are not affected.
Use a collection in an agent
Add the names of your collections to the collections list of a
saved agent. A chat with that agent can then search
only those collections. If a listed collection is deleted, the chat still starts
and the model is told that it is not available.
Let an agent propose a text for a collection
A model can ask to add a text to a collection, for example a procedure that you
pasted in the chat, with the propose_change tool and the kind knowledge. It
works like any other suggested change,
with these rules:
A grant. The agent needs the grant knowledge.write (Add to knowledge
in the Tools list, under Knowledge). It is sensitive and off by default. A
plain chat can propose to any of your collections; a saved agent only to the
collections on its own list.
Always your decision. The text is never added by the model alone, and never
at once, whatever your memory save level is: Ask, Auto and Always
confirm all wait for your Confirm. The level Never takes the kind
away. A wrong text would feed the answers of every chat that searches the
collection, and indexing costs compute, so there is no “save and tell me” for
Knowledge.
What you see. The card in Suggested changes names the collection and
shows the first 20 lines of the text and its size against the limit of 64 KiB.
It also says how many passages will be embedded and with which model, for
example “About 4 passages will be embedded with granite-embedding-107m-multilingual”.
The count is an estimate from the size of the text and the chunking settings
(max_chunk_size and chunk_overlap in GET /api/collections).
You can edit the text before you confirm. A change waits 24 hours, and you can
have 10 waiting and an agent can make 5 an hour, as for the other kinds.
A scan for secrets. Before a text is shown, LocalAI checks it with the same
patterns that keep a memory note from being saved at once (private keys, access
tokens, password: ... lines). A text that matches is not refused: it shows
with a warning in the card, and you can still confirm it in the web interface.
A messaging chat cannot confirm it. The bot writes nothing about it in the
chat, a yes there does not confirm it, and a no still drops it. The proposal
carries the code in warning (secret).
What happens.Confirm stores the text as one entry of the collection,
titled with the summary, and the server splits it into passages and embeds it.
Undo deletes that entry again. The embedding model must be installed;
without it the kind is not offered.
Messaging apps.knowledge.write is also a permission of a connection. It
is sensitive: only a sender you paired can use it, never a sender who is only
on the allowlist or in a listed channel. The bot writes the proposal in the
chat with the collection and the first lines of the text, and the paired sender
answers yes, no or undo there. The connection page explains a block with
the usual reasons, plus knowledge_none (the agent has no collection) and
knowledge_no_embedding (the embedding model is not installed).
This first version takes a text. Following a URL or adding a file of your Files
folder by proposal is not available yet; add those yourself on the Knowledge page.
See what changed in your files
Note
Needs a build newer than 4.12.1. In the current development builds.
The change feed shows which of your files changed, as it happens. A client reads it as an event stream. A
change can come from anywhere: you in another tab, a chat that wrote a file
with a tool, an upload, a trigger run, a connector, another API client, or
another frontend of a cluster. The web UI uses it to refresh what it shows
without a reload.
The files are the workspace of the chats, so the feed
needs the chats feature, which is on by default. When the server has no
files (no data path), the stream answers 409 with the type files_off.
Some changes were left out. Read again everything you show.
paths are inside your home folder, without a leading slash
(pages/tasks/index.html). A move gives the old and the new path. A
folder that a write created is a path too. You never see a path you cannot
read, and never a path of another user.
kinds are the kinds of the change sets: user (a change you made in the
UI or the API), agent (a chat), upload and undo.
revision is the revision of the newest change in the event. It is also the
event id.
Changes that arrive close together come as one event. The feed reads the
record of changes about once a second, so expect up to a second of delay.
A comment line (: ping) comes every 25 seconds, so that idle proxies keep
the connection open.
Resume after a disconnect
Without a resume point the stream starts from now. To get the changes you
missed, send the last event id back: a browser EventSource sends it by itself
as the Last-Event-ID header when it reconnects, and a client that opens a new
stream can send ?after=<revision>.
When more than 500 changes to your files have happened since that revision, the stream
starts with a resync event instead of the changes.
Limits
At most 8 open streams per user. One more answers 429. The web UI opens one
stream per browser tab, whatever the number of pages that listen.
A client that does not read fast enough does not slow anything down: when
its queue is full, the queued events are replaced by one resync event.
Several frontends
The feed keeps no state that frontends must share. Every change to a file is
written, with a revision, to the record of changes of the workspace (the
journal), and revisions are committed in order. In a cluster the journal is in
the shared database, so each frontend reads the same record, and a change that
any process made reaches the clients of every frontend. Nothing goes over the
message bus: the bus delivers a message at most once, the journal does not
lose one.
Each frontend reads the journal only while at least one client is connected to
it: one small query per second, and one query per user whose files changed.
The position in the journal of each frontend and of each client is kept in that
process only. After a restart it starts again from the newest revision, and a
client that reconnects gives its own position back.
A server without a database keeps the journal in a folder (the JSON index).
That server runs alone, so the feed is local too.
In the web UI
Pages of the React UI listen through one shared stream per tab
(useWorkspaceFeed). They also refresh when the window gets the focus again
and when a chat turn ends, in case the stream was down. The Files page
reads the open folder again when something in it changes, so a file that a
chat or another tab writes shows up without a reload.