Reference Omeka Classic plugin

Developer Reference

The chat and search endpoints

Both take a JSON body (or form fields) by POST, answer JSON, and are rate limited per IP address.

POST /chatbot/api/chat

{ "question": "Who painted the field at dusk?", "collection_ids": [3] }
Field Required
question yes Up to 1000 characters.
collection_ids no Only evidence from these collections.
{
  "answer_html": "<p>Mara Lind painted it <sup><a href=\"#chatbot-source-1\" class=\"chatbot-citation\">[1]</a></sup>.</p>",
  "sources": [
    { "citation_num": 1, "title": "Field at Dusk", "url": "https://example.org/items/show/12",
      "resource_type": "item", "resource_id": 12, "snippet": "Lind painted the field behind her studio…" }
  ]
}

answer_html is escaped text in paragraphs, with the citations as links; sources lists the cited sources only.

POST /chatbot/api/search

{ "query": "evening light over fields", "page": 1, "per_page": 10, "collection_ids": [3] }
{
  "results": [
    { "resource_type": "item", "resource_id": 12, "title": "Field at Dusk",
      "url": "https://example.org/items/show/12", "distance": 0.31, "snippet": "Lind painted the field…" }
  ],
  "total": 47, "page": 1, "per_page": 10
}

distance is the cosine distance of the closest chunk: 0 is identical, 1 unrelated.

Errors

Status Body error
400 The question or query is missing or too long.
403 Chat or search is turned off, or the chat is for signed-in users only.
405 Not a POST.
429 Over the rate limit.
503 OpenAI or Turso failed, or the plugin is not set up (the detail is in the log, never in the answer).

The system prompt cannot be sent: it is the one set in the admin.

The scripts

The plugin's views load chatbot.js and semantic-search.js. A theme can use them too:

<div id="ask"></div>
<script src="/plugins/Chatbot/views/shared/javascripts/chatbot.js"></script>
<script>
ChatbotWidget.init({ apiUrl: '/chatbot/api/chat', mode: 'inline', collectionIds: [3] }, document.getElementById('ask'));
</script>

ChatbotWidget.init({apiUrl, mode: 'widget' | 'inline', heading, collectionIds}, element) and SemanticSearch.init({apiUrl, perPage, placeholder, collectionIds}, element). The styles are in css/chatbot.css and css/semantic-search.css; they use --color-primary when the theme defines it.

Storage

In Omeka's database:

Table Holds
chatbot_log The log: level, event, message, context (JSON), time (UTC).
chatbot_rate_limit Requests per IP address per minute, kept an hour.
chatbot_queue Records waiting to be indexed.

In Turso, one table, chunks: resource_type (item, file, collection, simple_page, exhibit_page), resource_id, chunk_id, chunk_text, metadata (JSON: title, collection_ids), url (relative to the site), created_at and embedding (F32_BLOB(n)), with the DISKANN index chunks_vec_idx. The same table as the Omeka S Chatbot module's, with Classic's kinds of records.

Indexing without background jobs

When background jobs cannot run, chatbot.sync_jobs = 1 in config.ini indexes during the request that saves a record (saving is slower: one OpenAI call per chunk), and re-indexing runs during the request that starts it (keep it to small sites, or the request may time out).

Log in for Support