Hybridge · internal platform demo

Hybridge Enterprise Search

An internal, permission aware search assistant. Employees sign in with their Hybridge Google account, ask questions in plain language, and get streamed answers grounded in company documents, with citations that open the exact source passage. Authorized users grow the knowledge base by dropping documents into a governed ingestion pipeline. Built entirely on Google Cloud with open source components. No third party SaaS.

Live at hybridge-search.web.app GCP native 122 automated tests RAG with hard guardrails

01What a user sees

Two tabs, mirroring the quality bar of modern AI chat apps:

Ask Hybridge

A chat home with a serif greeting and a rounded composer. Answers stream in live. Every factual claim carries a small numbered citation. Clicking a citation opens the source document in a right pane, scrolled to the exact cited passage with a highlight. A model chip switches between Flash (fast) and Pro (deeper reasoning). Conversations persist in a left rail with pin, rename, and delete.

Dropoff

The governed way in for new knowledge. Uploaders see a reactive particle vortex as the drop target. Dropping a file or pasting a link opens a scope popup: who can find it (everyone or specific groups), tags, document class, and effective date. A status list tracks each document from Processing to Ready. Everyone else sees a lock. The tab itself is hidden for people without upload rights.

02Architecture at a glance

A single page app on Firebase Hosting talks to a FastAPI service on Cloud Run. Postgres (Cloud SQL) holds everything relational plus the vectors. Google Cloud Storage keeps the original files. Vertex AI provides embeddings, reranking, and Gemini generation. All infrastructure is defined in Terraform, and every deploy is versioned and tagged.

flowchart LR
  subgraph Browser
    SPA["React SPA
Firebase Hosting"] end subgraph GCP["Google Cloud · project hybridge-search"] IDP["Identity Platform
Google SSO, domain locked"] API["FastAPI on Cloud Run
token verify · ACL · RAG"] DB[("Cloud SQL Postgres
pgvector · FTS · chat")] GCS[("Cloud Storage
original files")] VAI["Vertex AI
embeddings · rerank · Gemini"] JOB["Ingestion job
Cloud Run + Pub/Sub"] end SPA -->|Google sign in| IDP SPA -->|Bearer token, HTTPS| API API --> DB API --> VAI API -->|signed URLs| GCS JOB --> DB JOB --> VAI GCS --> JOB
Stack
Python 3.12, FastAPI, SQLAlchemy async, Alembic migrations · React 19, TypeScript, Vite, Tailwind
GCP services
Cloud Run, Cloud SQL, Identity Platform, Firebase Hosting, Cloud Storage, Pub/Sub, Vertex AI, Artifact Registry, Secret Manager, Cloud Build
Infra as code
Terraform modules for every service, so the whole environment is reproducible
Deploy versioning
every release is an immutable image tagged with the git commit, and the running version is visible on the health endpoint

03Why this retrieval design

Before writing code we researched four ways to back a retrieval system. The decision was driven by our real workload: a corpus that starts near zero and grows document by document, strict permission filtering on every query, and chat grade latency.

ApproachHow it worksStrengthsWhy not (for us)
Vector DB (chosen)Embed chunks, nearest neighbor search, plus keyword search, fused and rerankedFast (tens of ms), scales incrementally, filters combine naturally with SQL, matureChosen. Weakness (exact terms, part numbers) is covered by the BM25 side of the hybrid
Vectorless / PageIndexLLM navigates a table of contents tree, reasoning its way to the right sectionExcellent on long structured docs, no index to rebuildEach query costs multiple LLM calls and seconds of latency; per query cost grows with corpus
Graph DB / GraphRAGExtract entities and relations, answer by walking the graphMulti hop questions across documentsExpensive extraction on every ingest, brittle as the corpus shifts, heavy maintenance
Keyword only (BM25)Classic full text searchCheap, exact match, explainableMisses paraphrase and synonyms; no semantic recall

We landed on hybrid retrieval with reranking on Postgres pgvector: dense vectors for meaning, BM25 for exact words, reciprocal rank fusion to merge, and a cross encoder reranker for final precision. Postgres also gives us one database for chunks, metadata, permissions, chat history, and users, which keeps ACL filtering inside the same query planner. When scale demands it, the same schema moves to AlloyDB with minimal change.

04The write path: ingestion

Every document enters through one governed pipeline, whether it arrives as a file drop or a pasted link.

👆 Click any stage to see how it works:

Failures are first class: a document that cannot be parsed lands in a Failed state with the reason stored, visible in the Dropoff status list.

05Metadata: the document card

Better answers come from better metadata, so at ingestion we build a small document card for every document, and it stays small no matter how long the document is. Gemini reads the document and proposes a title, a summary capped at 200 characters, key entities, tags from a fixed taxonomy, and an effective date. The uploader confirms or edits the governance fields in the scope popup. (Click Document card in the pipeline above for the visual.)

FieldSet byUsed for
title, summary, entitiesGemini proposesfast document level filtering and display
tagsGemini proposes, uploader confirmsdepartment style filtering, source pills in answers
group_acluploaderwho can ever see this content (empty means everyone)
document classuploaderauthority: Official Policy 8 · Approved SOP 6 · Draft 3 · Note 1
authority scorecomputed server sideclass base, plus 2 if an admin uploaded, plus 1 for uploader role, minus 1 for link sources, clamped 1 to 10. Never client supplied.
effective dateuploader confirmsrecency tiebreaks and conflict handling
version, supersedes, statuspipelineversion chain and current flag

Every chunk inherits the tenant id, document id, permissions, version, and character offsets, so a citation can always be traced to an exact byte range of an exact version of an exact document.

06Chunking and embeddings

Chunking is layout aware, not a blind character count: the chunker walks the parsed blocks, keeps headings attached to their sections, respects paragraph boundaries, and packs blocks into token bounded chunks with a controlled overlap between neighbors. Each chunk records its exact character start and end. Encoding uses Vertex AI gemini-embedding-001 at 768 dimensions, batched for throughput, with queries embedded by the same model into the same space. 768 is the deliberate middle ground: strong recall at a quarter of the storage and index cost of 3072. (Click Chunk and Embed in the pipeline above for the visuals.)

07Storage and indexing

Everything lands in one Postgres instance (Cloud SQL) with the pgvector extension. Three indexes make retrieval fast, and all three accept inserts incrementally, which matters for a corpus that grows daily. (Click Index in the pipeline above for the visual.)

Original files live in Cloud Storage; Postgres stores the pointer. Chat history, users, groups, and audit logs share the same database, which is why one SQL query can combine "semantically similar" with "this user is allowed to see it" with "only current versions".

08The read path: retrieval

flowchart LR
  Q["Question"] --> ACL["Permission prefilter
from identity, in SQL"] ACL --> D["Dense search
pgvector cosine, top 50"] ACL --> S["Keyword search
BM25 full text, top 50"] D --> F["Reciprocal rank fusion"] S --> F F --> R["Rerank to top 8
Vertex AI ranker"] R --> C["Conflict resolution
authority, recency"] C --> G["Gemini generates
grounded, cited, streamed"]
👆 Click any stage to see how it works:

09Groups and access control

Access is organized around groups, created by uploaders on the fly (clinical, regulatory, leadership, and so on). Users belong to groups; documents are scoped to groups at Dropoff time. An empty scope means everyone at Hybridge. (Click Permission filter in the pipeline above for the visual.)

10Trust: versions, conflicts, citations

Document versioning

Re uploading a changed document creates a new version and supersedes the old one. Retrieval only sees current versions, so stale guidance cannot resurface, while the full chain remains stored for audit. (Click Version resolve in the write path for the visual.)

Conflict resolution, never a coin flip

When two retrieved documents disagree, the system resolves by governance instead of chance: drop superseded documents, prefer higher authority, tiebreak by effective date, and if the top two remain comparable, say so explicitly in the answer. (Click Resolve conflicts in the read path for the visual.)

Example from the demo corpus
Two documents give different torque minimums. The answer uses the current Official Policy, and a visible callout says sources disagree, naming the newer higher authority document it followed and the older SOP it set aside.

Citations, always

Every claim carries a numbered citation. Each citation stores the document id, chunk id, and character offsets, so clicking it opens the document scrolled to the highlighted passage. Sources under an answer show title, tags, document class, effective date, and authority. If the knowledge base cannot support an answer, the assistant abstains rather than guesses.

11Chat, history, and memory

12Security and compliance

Identity

Google sign in via Identity Platform, restricted to the hybridgeimplants.com domain with verified email required. Users are provisioned on first login. Every API call verifies the Firebase token server side.

Authorization

Deny by default group permissions enforced in SQL before retrieval, on the source viewer, and on file downloads. Roles gate upload and admin surfaces in both API and UI.

Data protection

Originals in Cloud Storage behind short lived signed URLs, issued only after a permission check. Secrets live in Secret Manager. Nothing sensitive is committed to the repository.

Safe failure

Stream errors are logged in full on the server but the client only ever sees a generic message, so internal details cannot leak. Ingestion of links has a guard against requests to internal or metadata addresses.

Audit

Logins, group changes, and membership changes write an audit log with actor, action, target, and time.

Compliance posture

Google Cloud BAA is in place for the organization. Access is scoped, audited, and revocable per group; encryption at rest and in transit is on by default across the stack, with customer managed keys staged as a hardening step.

Also in the discipline column: 122 automated tests across backend and frontend, adversarial code review on every pull request (which caught real permission and correctness bugs before merge), and an automated security review pass that hardened the error path.

13The frontend

React 19 with TypeScript and Tailwind, built with Vite, served from Firebase Hosting. The visual identity is a warm beige and brown system designed for this product, in both tabs and this document.

14Built to grow, not preloaded

This system assumes the corpus is always growing rather than imported once:

15Quality and evaluation

16What is next

17Suggested demo script

  1. Sign in with a Hybridge account; note the domain lock and that a personal Gmail cannot enter.
  2. Dropoff first. Show the vortex, drop a policy PDF, walk the scope popup (pick a group, a class, a date), and watch Processing turn to Ready.
  3. Ask the question that document answers. Watch it stream, then click citation 1 and let the source pane land on the highlighted passage. This moment sells the whole system.
  4. Show the conflict callout with two disagreeing documents, and how the answer names which source won and why.
  5. Show access control: the same question from an account outside the group returns the abstention, because the restricted document never even entered retrieval.
  6. Ask something the corpus cannot answer to show honest abstention instead of a confident guess.
  7. Close on the rail: history persisted, pin and delete, Flash versus Pro, and the roadmap above.