Skip to main content
Pro can call an OpenAI-compatible embeddings and chat API that you configure. There is no hosted Commentify model, no token meter, and no COMMENTIFY_AI_KEY in our cloud. If the provider errors, both features fail open (no matches, no draft) rather than blocking the post. Perspective toxicity is a separate spam checker. See AI toxicity.

Enable it

Run migrations so commentify_embeddings exists. Approved comments are embedded when they are approved. Backfill older rows:
--sync runs inline. Otherwise jobs go on your default queue. Process the queue or embeddings stay empty and duplicate checks return no matches.

Duplicate detection

Before a top-level post, Livewire and the SDKs ask: POST /commentify/api/v1/{type}/{id}/duplicates with { "body": "…" }. A candidate matches only when all of these hold:
  1. COMMENTIFY_AI is on, a key is set, and commentify_embeddings exists
  2. After collapsing whitespace, the draft is at least duplicate_min_chars (default 12)
  3. The stored comment is approved, top-level, and on the same commentable
  4. Cosine similarity of the two vectors is ≥ duplicate_threshold (default 0.82)
Up to five hits, highest score first. Replies are not compared as questions. Short scraps (ok, thanks) are skipped. The UI is an info callout (not a red validation error) with permalinks and Post anyway. That button submits the held draft and skips the check once. Embeddings are stored as JSON. Matching is PHP cosine similarity. No pgvector.

Reply drafts

On the Filament Moderation queue, Draft reply (when reply drafts are on) queues a job. The model may supply page context:
The draft is a pending reply (is_approved = false) with metadata.drafted_by = ai. It stays off the public thread until the author or a moderator approves it.

Frontends

GET ui reports features.duplicate_detection and features.reply_drafts. List payloads include thread.duplicate_detection. React and Vue intercept in the thread store (post() returns null when matches exist; store.postAnyway() posts the draft). Livewire uses postAnyway on the comments component.
Never commit COMMENTIFY_AI_KEY. Keep it in .env. Commentify does not log the key.
Last modified on November 1, 2026