OBLETHdocs

Enable Knowledge

Give Chat an S3-compatible bucket and an embedding model so people can build document collections. The bucket also holds people's attachments and generated images.

5 min readUpdated for Chat 0.5.2Edit on GitHub

You needAn S3 bucket, pgvector, an embedding model
Turn it onOBLETH_CHAT_S3_ENDPOINT
Per person2 GiB, 2,000 documents

Document files go to an S3-compatible bucket. Passages and vectors stay in Chat's Postgres database, so pgvector must be installed there (see Install Chat). From v0.4.2, the same bucket also holds the files people attach to chats and the images models generate; see Where files are kept.

Set it up

  1. 1

    Create a bucket

    Any S3-compatible store works: AWS S3, Cloudflare R2, MinIO, Garage. Create an access key that can read, write and delete objects in that bucket only.

  2. 2

    Serve an embedding model

    Register an embedding model in the gateway and make sure Chat's tenant may use it. The default is qwen3-embedding-8b; any embedding model works. Chat stores 1,024 dimensions: it keeps the first 1,024 of a longer vector and renormalizes them, which suits models trained to be truncated, such as Qwen3-Embedding, and pads a shorter one with zeros, which doesn't change its distances.

    Most embedding models expect a prefix before searches and before passages. From v0.4.4, Chat knows the prefixes for common models and uses them on its own; for any other model, set them (see Choose the embedding model).

  3. 3

    Configure Chat

    OBLETH_CHAT_S3_ENDPOINT=https://<account>.r2.cloudflarestorage.com
    OBLETH_CHAT_S3_BUCKET=obleth-chat
    OBLETH_CHAT_S3_ACCESS_KEY_ID=…
    OBLETH_CHAT_S3_SECRET_ACCESS_KEY=…
    OBLETH_CHAT_EMBEDDING_MODEL=qwen3-embedding-8b
    

    Restart Chat. Library appears in the sidebar for everyone, with Saved, Collections and Generated, and answers get a Save button. Without these settings Library is hidden.

Opening a document's original file, for example from a citation, sends the person's browser straight to the bucket on a 5-minute signed link. People's browsers must therefore reach OBLETH_CHAT_S3_ENDPOINT and trust its certificate. With a bucket on a private network, uploads, indexing and citations still work everywhere, but only people on that network can open the original files.

Where files are kept

With a bucket configured (v0.4.2 and later), Chat stores these files there:

FilesStored under
Knowledge documentsknowledge/<user>/<document>
Chat attachmentsattachments/<user>/<file>
Generated imagesimages/<user>/<image>

Without a bucket, attachments and generated images are kept in Postgres. Turning the bucket on later needs no other step: a background worker moves existing files into it one at a time, and files stay readable throughout. Each replica logs moving files kept in Postgres into object storage when it starts moving them.

Attachments and generated images are served through Chat, never through a link to the bucket, so people's browsers don't need to reach the bucket to open them. Deleting a file, a chat or an account deletes the stored files shortly afterwards. An upload whose chat or file was never saved is deleted after 15 minutes.

Reclaim the database space after the move

Moving files out of Postgres frees their space for new rows, but the database files don't shrink. To give the space back to the disk, run this once the move is done, in a quiet period:

VACUUM FULL attachments, generated_images;

VACUUM FULL rewrites both tables and blocks reads and writes on them while it runs.

Settings

VariableDefaultMeaning
OBLETH_CHAT_S3_ENDPOINTunsetTurns Knowledge on. Chat uses path-style addresses
OBLETH_CHAT_S3_BUCKETunsetThe bucket
OBLETH_CHAT_S3_ACCESS_KEY_ID, OBLETH_CHAT_S3_SECRET_ACCESS_KEYunsetThe bucket's credentials
OBLETH_CHAT_S3_REGIONautoSigning region. auto suits R2; set the real region for S3
OBLETH_CHAT_EMBEDDING_MODELqwen3-embedding-8bDefault gateway embedding model. An administrator can choose another in Settings
OBLETH_CHAT_EMBEDDING_QUERY_PREFIXQwen3-Embedding's instructionDefault text put before each search. Empty for none
OBLETH_CHAT_EMBEDDING_DOCUMENT_PREFIXemptyDefault text put before each passage and saved item
OBLETH_CHAT_KNOWLEDGE_USER_MB2048Storage per person, in MiB
OBLETH_CHAT_PDFTOTEXT, OBLETH_CHAT_UNZIPon PATHPaths to the extraction tools, if they're elsewhere

Choose the embedding model

From v0.4.3, an administrator chooses the embedding model and its prefixes in Settings › Administration › System › Knowledge search. The list shows the embedding models the gateway offers. OBLETH_CHAT_EMBEDDING_MODEL sets the default model.

Each prefix comes from the first of these that is set (v0.4.4 and later):

  1. The administrator's choice in Settings.
  2. OBLETH_CHAT_EMBEDDING_QUERY_PREFIX or OBLETH_CHAT_EMBEDDING_DOCUMENT_PREFIX, while the default model is in use. They never carry over to another model.
  3. The model's own prefixes, for the models in the table below.

Any other model gets no prefix. Choosing a model in Settings fills in its prefixes, so check them against the model's documentation only when it isn't in the table.

The same happens when the defaults change in the environment and no administrator has chosen otherwise. In v0.4.2, which has no setting in the app, change the environment variables and upload the documents again.

Models whose prefixes Chat knows

Chat recognises these by a part of the model's name in the gateway:

ModelName containsSearch prefixPassage prefix
Qwen3-Embeddingqwen3-embeddingInstruct: Given a question, retrieve passages from the person's documents that answer it\nQuery: none
EmbeddingGemmaembeddinggemmatask: search result | query: title: none | text:
Nomic Embed Textnomic-embed-textsearch_query: search_document:
E5multilingual-e5, e5-large, e5-base, e5-smallquery: passage:
BGE English, mxbaibge-large-en, bge-base-en, bge-small-en, mxbai-embed-largeRepresent this sentence for searching relevant passages: none

In an environment variable, the trailing space is part of the prefix, so quote the value.

How indexing runs

A background worker on each replica claims queued documents with FOR UPDATE SKIP LOCKED, so replicas share the work. A claim is reclaimed after 10 minutes, and a document gets 3 attempts. Files are stored under knowledge/<user>/<document>, and downloads are 5-minute presigned links.

Deleting a document or collection removes its passages at once. Its files go on a trash list that the worker empties shortly after, so a bucket error never leaves passages behind.

pdftotext (from poppler-utils) and unzip must be on the image; the Chat image includes both.