Repository navigation
Hybrid RAG over docs, pages, blog, changelog and API reference (#194) - #196
Conversation
…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>
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
frontlit/apps/api/src/documentation/index-status.ts
Lines 45 to 49 in f9538eb
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>
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>
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) replacesdocument_chunks,document_index_jobsand the docs-onlydocumentation_embeddings/documentation_embedding_configs.tsvector, GIN index, stemming, prefix match).Indexing is a per-team reconcile worker (
search/indexer.ts):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 › sectionline 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):
POST /public/:teamId/chat/feedback, stored onticket_messages.feedback.negative_feedback).Dashboard:
Also:
#sluganchors.bun run search:eval <team> <questions.json> [--rerank]reports recall@1 and recall@5.getChatAnswer/streamChatAnswer.docs/architecture.md§6–7 rewritten.Migration
0015_search_indexcreates the new tables, addsticket_messages.feedback, drops the old tables, and queues every existing team for indexing.Testing
tscis clean for api, web and sites. Tests pass: api 771, web 97, sites 82./pricingand/docs/refunds#refund-policy. Thumbs down was stored, shown in the inbox and listed under "Review gaps".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.Follow-up fixes from that test:
[n]marker, so the answer was replaced with "couldn't verify". The model is now asked once more to cite the passages or replyNO_ANSWER. A question is recorded as a documentation gap only when search found nothing or the model says the passages don't answer it.[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
TimeoutErrorthat crashes the API process.now()with JS UTC dates on timezone-less columns, so it fails on non-UTC databases. The new index queue avoids this.sitesOriginhardcodes port 3002 for localhost URLs.Closes #194
🤖 Generated with Claude Code