Skip to content

Hybrid RAG over docs, pages, blog, changelog and API reference (#194) - #196

Merged
s3rot0n1n merged 4 commits into
mainfrom
t3/docs-pages-issues
Nov 9, 2026
Merged

s3rot0n1n merged 4 commits into
mainfrom
t3/docs-pages-issues

Conversation

@s3rot0n1n

@s3rot0n1n s3rot0n1n commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

Implements #194: industry-standard RAG for the site chatbot and help desk AI, grounded in docs, builder pages, blog, changelog and the API reference.

What changes

One search index (search_chunks) replaces document_chunks, document_index_jobs and the docs-only documentation_embeddings / documentation_embedding_configs.

  • Every team gets Postgres full-text search (generated tsvector, GIN index, stemming, prefix match).
  • With an embedding key, vector search (pgvector HNSW) runs too, and the two lists are merged with reciprocal rank fusion.
  • No key means keyword-only. The fake hash-vector fallback is gone.

Indexing is a per-team reconcile worker (search/indexer.ts):

  • Publishing anything queues the team: docs activation/purge/API reference (via the docs delivery outbox), page releases, blog/changelog publish/edit/delete, and AI setting changes.
  • The worker rebuilds only sources whose hash changed, drops unpublished ones, and embeds chunks lacking a vector for the current embedding model.
  • Search also filters to what's live at query time (active docs publication, active site release, published articles), so a lagging index never returns unpublished content.

Builder pages are indexed one chunk per block, covering titles, descriptions, FAQ questions and answers, plans and rich text. Chrome, forms, embeds and noindex pages are skipped.

Contextual chunks: each chunk is indexed and embedded with a kind › title › section line plus the page summary.

Reranking: the chatbot and help desk AI fetch 30 candidates and rerank them with the team's own chatbot model. Any failure falls back to the fused order. The agent prompt asks for standalone queries and a retry with other wording. Site search doesn't rerank.

Feedback (M7):

  • Thumbs up/down on bot answers in the widget, via POST /public/:teamId/chat/feedback, stored on ticket_messages.feedback.
  • A thumbs down files the question under the existing documentation gaps report (negative_feedback).
  • The inbox shows the visitor's rating on bot answers.

Dashboard:

  • The docs "Keyword / Smart" switch is replaced by a read-only "Search quality" summary showing what the team's keys unlock: keyword always, meaning-based with an embedding key, reranking with a chat key.
  • The same summary is added to Settings → AI.

Also:

  • Site search links pages, blog and changelog correctly.
  • Changelog entries get #slug anchors.
  • bun run search:eval <team> <questions.json> [--rerank] reports recall@1 and recall@5.
  • Removed the unused getChatAnswer / streamChatAnswer.
  • docs/architecture.md §6–7 rewritten.

Migration 0015_search_index creates the new tables, adds ticket_messages.feedback, drops the old tables, and queues every existing team for indexing.

Testing

  • tsc is clean for api, web and sites. Tests pass: api 771, web 97, sites 82.
  • New tests cover:
    • page extraction, live-scope filtering and team scoping
    • reconcile, including no rework on unchanged content
    • a paraphrase found via vectors (mocked embeddings)
    • rerank ordering and fallbacks
    • feedback
  • Browser smoke on a local stack:
    • A doc published in the editor became searchable within seconds.
    • A page and a blog post were indexed and linked correctly.
    • Settings show the right search tiers.
    • The widget showed an answer citing /pricing and /docs/refunds#refund-policy. Thumbs down was stored, shown in the inbox and listed under "Review gaps".
    • Site search returned both the doc and the page.
  • Reranking ran live against a free OpenCode model and kept the 2 relevant passages out of 3.

QA smoke with a real OpenAI key

Deployed to QA (docs-pages-issues-356d889) and tested on a seeded team: 4 docs, a pricing FAQ page, a blog post and 2 changelog entries.

  • Embeddings are built, and meaning-based search finds paraphrases ("reimbursement" finds Refunds).
  • The chatbot answers questions about pricing, refunds, QuickBooks and payouts correctly, citing the right source. The help desk auto-replies to tickets from the right doc.
  • Ratings show in the inbox, and the gaps report records negative feedback and unanswered questions.
  • Removed content stops appearing in search within 2 seconds. Tested 7 ways: unpublishing a doc, turning off indexing for one doc, turning off docs search for the team, deleting a blog post, turning off indexing for one changelog entry, turning off changelog indexing for the team, and hiding a page from search engines. The chatbot no longer retrieves or cites removed content.

Follow-up fixes from that test:

  • Uncited answers: the model sometimes answered correctly but left out the [n] marker, so the answer was replaced with "couldn't verify". The model is now asked once more to cite the passages or reply NO_ANSWER. A question is recorded as a documentation gap only when search found nothing or the model says the passages don't answer it.
  • Repeated markers: two passages from one source now produce one marker ([1], not [1][1]).

Retrieval noise and relevance scores are tracked in #199. Building a retrieval eval suite is tracked in #198.

Not verified live: the citation retry itself (the model couldn't be made to skip a citation on demand), and Azure embeddings.

Found while testing, not changed here

Closes #194

🤖 Generated with Claude Code

…ference (#194)

One search index (search_chunks) for everything the chatbot and help desk
AI can cite, kept in sync by a per-team reconcile worker:

- Postgres full-text search for every team; vector search added when the
  team has an embedding key, fused with reciprocal rank fusion.
- Builder pages are indexed (one chunk per block); chunks carry a
  title/section/summary context line.
- Search filters to what is live at query time.
- Chatbot/help desk AI rerank candidates with the team's chat model and
  write standalone, retried queries.
- Visitor thumbs up/down on bot answers; thumbs down feeds the
  documentation gaps report.
- search:eval script for recall@1/@5 per team.

Removes the hash-vector fallback, the docs-only semantic mode and
embedding tables, the document index jobs and the unused getChatAnswer path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-07T10:11:51.276291Z f9538eb PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

(item) =>
item.documentId === (doc as any).documentId &&
isDocIndexable(item.meta),
)
? ("indexed" as const)

P2 Badge Report docs as pending until indexed

When a doc has just been published or the search-index worker fails, this branch reports it as indexed solely because it appears in the active publication; it never checks whether chunks were created or whether the team's index request failed. As a result, document and MCP responses can report success while the new content is not searchable and the error is hidden. Use the worker and chunk state to distinguish indexed, pending, and failed.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

- Renumber the search index migration to 0016, after main's 0015_changelog_cleanup.
- Keep the deleted per-document index worker deleted; carry main's changelog
  release-date context into the new indexer (chunk context section) instead of
  the old changelogChunkContext helper.
- Take main's changelog feed, which already anchors entries by slug.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rajat and others added 2 commits November 9, 2026 15:41
On QA, gpt-4o-mini sometimes answered correctly from the search results
but left out the [n] markers, so the grounding check replaced a right
answer with "I couldn't verify this" and filed a "retrieval miss" gap.

When search returned passages but the answer has no valid citation, ask
the model once more (no tool calls) to cite them or reply NO_ANSWER.
Documentation gaps are now recorded only when search found nothing or
the model confirms the results don't answer the question; a model that
still can't cite is logged instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two passages from one source both became [1], so answers read "[1][1]".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@s3rot0n1n
s3rot0n1n merged commit 7078132 into main Nov 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Help desk + chatbot: industry-standard RAG over docs, pages, blog, changelog and API reference

1 participant