Skip to content

arusso-aboutcloud/aboutcloud-search

Repository files navigation

AboutCloud AI Chatbot

A Cloudflare Workers RAG (Retrieval Augmented Generation) chatbot for technical blogs, with a transparent safety framework you can read, audit, and reuse.

The interesting part isn't the chatbot. It's the guardrail framework around it — six runtime defenses and four operational practices, documented and tested, that apply to any LLM-backed product behind a public input.

Runs entirely on Cloudflare's free tier. No external APIs. No npm dependencies in the Worker.

Why This Repo Exists

Most "AI safety" claims in production are vibes. "We use guardrails." "Built-in safety." Without specifics, that's the AI equivalent of "bank-grade encryption" — true of nothing in particular.

This repo takes the opposite approach: every defense is named, located in the source, paired with what it does not protect against, and backed by an automated eval suite. If the safety story isn't worth that level of openness, it isn't worth claiming.

The Safety Framework

Safety Framework

Six runtime defenses execute in the Worker, deterministically, before and after the model:

  1. Prompt Injection Shield. NFKC Unicode normalization (so homoglyph attacks like ignore collapse to ASCII), then 20+ pattern matches against known injection styles. Runs before the prompt ever reaches the LLM.
  2. Topic Boundary. Seven category regexes block politics, religion, medical, legal, financial, NSFW, and violent content. The bot refuses politely with a short redirect rather than improvising answers outside its competence.
  3. Destructive Behavior Blocker. 15+ patterns cover SQL injection, XSS, hacking instructions, malware, credential theft. Refuses to roleplay these even with research-framing pretexts.
  4. Input Length Cap. Hard limit at 2,000 characters. Reduces prompt-stuffing surface and blocks the most common context-flooding attempts.
  5. Anti-Hallucination Threshold. Vector similarity score must clear 0.50 for a response to ground in retrieved sources. Below the threshold, the bot says it doesn't know rather than inventing an answer. Temperature locked at 0.2.
  6. Output Sanitizer. Widget renders LLM text via DOM construction and createElement, never innerHTML. Auto-detected URLs become real <a> elements through DOM APIs, so model output cannot inject markup into the page.

Four operational practices sit alongside the runtime defenses:

  • Stateless. No chat history persisted, no cookies set by the widget.
  • AI Disclaimer. Rendered on every answer, not just the first one.
  • De-escalation Tone. Refusals stay friendly; redirect rather than scold.
  • Versioned Releases. x-bot-version response header on every API call, git-tagged release commits, change log discipline.

The split between defenses and practices is the credibility move. A regex on every request is a defense — an attacker has to defeat it. A monthly review cadence is governance — useful, but not the same thing. Calling both "layers" inflates the count and obscures which controls actually do the blocking.

For the full specification, including what each defense does not catch, see docs/GUARDRAILS.md and docs/RESIDUAL_RISK.md.

Architecture

Architecture

Browser Widget
    ↓
Cloudflare Worker  ← guardrails execute here
    ↓
Workers AI (embed)  →  Vectorize (search)  →  D1 (fetch content)
                                                     ↓
                                          Workers AI (generate)
                                                     ↓
                              Answer + numbered citations + disclaimer

A single Worker handles every request. Pre-LLM filters run first; if any reject, the request never reaches the model. After generation, the output sanitizer runs and the response is shaped with citations and disclaimer before return.

See docs/ARCHITECTURE.md for the full request flow, data shapes, and component contracts.

Tech Stack

Layer Technology
Runtime Cloudflare Workers
Embeddings BGE-Base v1.5 (768d) — Workers AI
Generation Llama 3.1 8B Instruct — Workers AI
Vector store Vectorize (cosine similarity)
Metadata + content D1 (SQLite-compatible)
Widget Vanilla HTML/CSS/JS, ~6KB

Zero external APIs. Zero npm dependencies in the Worker. Compatible with any blog platform that supports footer code injection (Ghost, WordPress, Hugo, custom HTML).

Cost

Resource Free tier limit Typical usage
Worker requests 100,000 / day < 100 / day
Workers AI neurons 10,000 / day ~ 500 / day
Vectorize vectors 200,000 20–50
D1 storage 5 GB < 1 MB
D1 reads/writes 5M / month < 1,000

€0 / month at typical blog-traffic scale. Structurally free — not a free trial, not a credit-card-required tier. Small Cloudflare account is the only requirement.

Quick Start

# Clone
git clone https://github.com/arusso-aboutcloud/aboutcloud-search.git
cd aboutcloud-search

# Authenticate
wrangler login

# Create resources (replace names with your own)
wrangler d1 create your-blog-db
wrangler vectorize create your-blog-index --dimensions=768 --metric=cosine

# Update wrangler.toml with the resource IDs that wrangler prints,
# then set your INDEX_SECRET (generate with: openssl rand -hex 32)
wrangler secret put INDEX_SECRET

# Deploy
wrangler deploy

# Index your content (see docs/HOWTO.md for the JSON schema)
curl -X POST https://your-worker.your-subdomain.workers.dev/index \
  -H "X-Index-Secret: $YOUR_INDEX_SECRET" \
  -H "Content-Type: application/json" \
  -d @posts.json

# Test
curl -X POST https://your-worker.your-subdomain.workers.dev/chat \
  -H "Content-Type: application/json" \
  -d '{"message":"what does your blog say about topic X?"}'

Full step-by-step in docs/HOWTO.md, including custom-domain setup, security headers, blog integration, and optional Cloudflare Access for admin endpoints.

Eval Suite

The repository ships with a 47-case automated eval suite covering prompt injection, off-topic deflection, destructive-request blocking, hallucination prevention, and product-knowledge accuracy. An additional 10 adversarial cases — Unicode homoglyph attacks, multi-step jailbreaks, embedded payloads — are held out as a private set so improvements aren't fitted to the public benchmark.

Run against your own deployment:

cd evals
EVAL_TARGET_URL=https://your-worker.your-subdomain.workers.dev node run.mjs

A pass-rate regression gates pull requests. Current public-set pass rate is documented in CHANGELOG.md per release.

Documentation

Document Purpose
ARCHITECTURE.md Request flow, data shapes, component contracts
COMPONENTS.md Resource inventory and binding map
GUARDRAILS.md Safety framework specification
RESIDUAL_RISK.md What the system does not defend against
HOWTO.md Step-by-step deployment guide
PUBLIC_PREP_SCRUB.md Pre-release security review
CHANGELOG.md Version history
SECURITY.md Vulnerability reporting
CONTRIBUTING.md PR process

License

MIT. See LICENSE.

Credits

Built on Cloudflare Workers, Workers AI, Vectorize, and D1. Embedding model BGE-Base v1.5 by BAAI. Generation model Llama 3.1 8B Instruct by Meta.

Issues and PRs welcome. If you build something on top of this framework, a note would be appreciated.

About

AI-powered semantic search & RAG chatbot for aboutcloud.io — Cloudflare Workers AI + Vectorize + D1, €0/month

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors