diff --git a/.env.example b/.env.example index b091ede..84e8c4f 100644 --- a/.env.example +++ b/.env.example @@ -2,12 +2,41 @@ # Advanced tuning knobs (decay rates, graph depth, agent turn limits) have # reasonable defaults — see braindb/config.py for the full list. -# PostgreSQL connection string (psycopg2 format) -DATABASE_URL=postgresql://user:password@host:5432/braindb +# ============================================================ +# DATABASE — pick ONE of the two modes +# ============================================================ + +# --- Mode 1: Internal DB (recommended / default) ------------ +# BrainDB runs its own Postgres container — nothing to install. +# This single line is the switch; remove it for Mode 2: +COMPOSE_PROFILES=internal-db + +# Optional knobs for the internal DB. They are IGNORED in Mode 2 +# (external connections are configured entirely via DATABASE_URL). +# NOTE: user/password/db-name are baked into the data volume on its +# FIRST boot. To reset the internal DB later (wipes its data!): +# docker rm -f braindb_db && docker volume rm braindb_pgdata +# POSTGRES_PORT=5435 # host port, only for inspecting the DB with +# # psql/adminer; the stack itself doesn't need +# # it. Change if 5435 is taken on your machine. +# POSTGRES_DB=braindb +# POSTGRES_USER=braindb +# POSTGRES_PASSWORD=braindb # change for anything beyond local use + +# --- Mode 2: External DB (bring your own Postgres) ---------- +# Your Postgres needs the pgvector and pg_trgm extensions. +# 1. Remove (or comment out) the COMPOSE_PROFILES line above. +# 2. Put EVERYTHING — host, port, db name, credentials — in this +# one URL. The POSTGRES_* knobs above have no effect here. +# DATABASE_URL=postgresql://user:password@your-host:5432/braindb # API port (default 8000) API_PORT=8000 +# Frontend (read-only browser UI) host port — served automatically by +# docker compose at http://localhost:8642. Change if 8642 is taken. +FRONTEND_PORT=8642 + # HuggingFace token — for faster model downloads (optional but recommended) # Get yours at https://huggingface.co/settings/tokens HF_TOKEN= diff --git a/.gitignore b/.gitignore index b10de4a..350887f 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,6 @@ benchmarks/*/answers/ # Bench compose: separate host data dir for the bench watcher, separate env file data_bench/ .env.bench + +# Test stack (docker-compose.test.yml): separate host data dir for test ingests +data_test/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 03c0d46..baecc68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,42 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.6.0] — 2026-06-12 + +### Added + +- **Bundled internal Postgres (opt-in by one `.env` line).** A `braindb_db` + service (pgvector/pg17) guarded by the `internal-db` compose profile. + `.env.example` now ships `COMPOSE_PROFILES=internal-db`, so a fresh clone + gets a working database with plain `docker compose up -d` — nothing to + install. Existing setups are untouched: without that line the service does + not exist and `DATABASE_URL` keeps pointing at your own Postgres exactly as + before. Optional knobs: `POSTGRES_PORT` (host inspection port, default + 5435, loopback-only), `POSTGRES_DB`, `POSTGRES_USER`, `POSTGRES_PASSWORD`. + Requires Docker Compose >= 2.20. Closes the request in issue #12. +- **Frontend served by the stack.** A `frontend` service (nginx:alpine over + the static `frontend/` directory) joins `docker compose up -d` — the + read-only browser UI is now at `http://localhost:8642` with zero manual + steps (`FRONTEND_PORT` to change it; loopback-only). The manual + static-server route still works as before. +- **Logo + architecture diagrams.** The BrainDB logo tops the README and the + frontend header (plus favicon), and five SVG diagrams — the keyword-graph + mechanism, retrieval pipeline, save/ingest lanes, wiki maintainer loop, and + wiki writer pipeline — illustrate their README sections. Assets live in + `docs/assets/`. + +### Fixed + +- **Test suite no longer touches your database — at all.** The suite now + runs against an isolated test stack (`docker-compose.test.yml`: its own + API on port 8002 + its own throwaway Postgres), and the session-end + cleanup that deleted pattern-matched rows from the configured database + has been removed entirely. Previously the tests ran against the live + personal stack and their cleanup silently failed from the host, leaking + `_pytest_*` keyword entities into real data (where the wiki maintainer + wasted LLM calls triaging them). Now: `docker compose -f + docker-compose.test.yml up -d && pytest`, and `down -v` wipes everything. + ## [0.5.0] — 2026-06-09 ### Changed diff --git a/CLAUDE.md b/CLAUDE.md index 3b873e6..0e780fb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -87,8 +87,8 @@ braindb/ ├── skills/ # Shipped Claude Code skills │ ├── braindb/SKILL.md # Direct curl-based skill │ └── braindb-agent/SKILL.md # Thin wrapper around the agent endpoint -├── frontend/ # Read-only browser UI — vanilla JS, no build -├── docker-compose.yml # api + watcher services (external PostgreSQL) +├── frontend/ # Read-only browser UI — vanilla JS, no build (served at :8642) +├── docker-compose.yml # api + watcher + wiki_scheduler + frontend (+ optional bundled Postgres) ├── .env # Real credentials — DO NOT COMMIT └── BRAINDB_GUIDE.md # Full API reference with curl examples ``` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 01efdca..0a37e15 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,13 +4,13 @@ Thanks for your interest. BrainDB is a small, opinionated project — the bar is ## Dev setup -Prerequisites: Docker Desktop (or any Docker Engine), Python 3.12, a Postgres 16 instance reachable from the container. +Prerequisites: Docker Desktop (or Docker Engine) with Compose v2.20+, Python 3.12. The database is bundled by default (`COMPOSE_PROFILES=internal-db` in `.env.example`); to use your own Postgres instead, remove that line and set `DATABASE_URL` — see the README's Setup section. ```bash git clone braindb cd braindb cp .env.example .env -# edit .env — set DATABASE_URL; recommended LLM_PROFILE=deepinfra + DEEPINFRA_API_KEY (or any other profile) +# edit .env — recommended LLM_PROFILE=deepinfra + DEEPINFRA_API_KEY (or any other profile) docker network create local-network # one-time; docker-compose expects this docker compose up -d --build @@ -26,10 +26,14 @@ pip install -e ".[dev]" ## Running tests +The suite runs against an **isolated test stack** (its own API on port 8002 + its own throwaway Postgres) — never against your personal BrainDB database: + ```bash -pytest # full suite (needs the stack up) +docker compose -f docker-compose.test.yml up -d # start the test stack +pytest # full suite pytest -k "not agent" # skip the live-LLM smoke tests pytest tests/test_split_chunks.py # a single file +docker compose -f docker-compose.test.yml down -v # stop + wipe test data ``` See [`tests/README.md`](tests/README.md) for what is and isn't covered. diff --git a/README.md b/README.md index d664d42..f91c6d5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -# BrainDB +

+ BrainDB +

[![BrainDB walkthrough](https://img.youtube.com/vi/AJ7iMOj4vvA/maxresdefault.jpg)](https://youtu.be/AJ7iMOj4vvA "Watch the BrainDB walkthrough on YouTube") @@ -18,6 +20,10 @@ Inspired by Karpathy's [LLM wiki idea](https://gist.github.com/karpathy/442a6bf5 - **vs. classic graph DBs** (Neo4j, Memgraph). Those are general-purpose graph stores with their own query languages and ops cost. BrainDB is purpose-built for LLM agents: a plain HTTP API designed for tool-calling, semantically meaningful fields (`certainty`, `importance`, `emotional_valence`), built-in text + pgvector search with geometric-mean scoring, always-on rule injection, automatic provenance, and runs on plain PostgreSQL + `pg_trgm` + `pgvector` — no new infrastructure to operate. - **vs. markdown files as memory.** Markdown wikis are flat and unstructured: the LLM has to grep, read whole files into context, and manage linking by hand. BrainDB's entities are atomic, queryable, ranked, and self-connecting. Facts extracted from a document automatically link back to the source via `derived_from`; recall returns relevant nodes plus their graph neighbourhood; nothing needs to be read in full unless the agent asks for it. +

+ One keyword, one graph — facts, a wiki article, and a derived thought all connect through a central keyword entity that carries the embedding +

+ --- ## Entity Types @@ -37,13 +43,12 @@ Relations connect any two entities with `relation_type`, `relevance_score`, `imp ## Setup -BrainDB runs as three Docker services — `api`, `watcher` (auto-ingests files), and `wiki_scheduler` (auto-maintains wikis) — against an **external** PostgreSQL you provide. The two sidecars are hands-off: you never call the pipeline by hand. The whole setup is six steps. +BrainDB runs as Docker services — `api`, `watcher` (auto-ingests files), `wiki_scheduler` (auto-maintains wikis), and a read-only browser `frontend` — plus a database that is either **bundled** (default, zero install) or **your own PostgreSQL**. The two sidecars are hands-off: you never call the pipeline by hand. ### 1. Prerequisites -- Docker Desktop (or any Docker Engine) -- A PostgreSQL 16 instance reachable from Docker (see step 3 for three common options) -- The PostgreSQL extensions `pg_trgm` and `pgvector` must exist on the target database, and the connecting user must have permission to create them on first connection (migrations will `CREATE EXTENSION IF NOT EXISTS` on startup). If you don't have DB admin rights, ask an admin to pre-install both extensions. +- Docker Desktop (or Docker Engine) with Compose v2.20+ +- That's it for the default setup — the database ships with the stack. ### 2. Clone and configure @@ -53,9 +58,19 @@ cd braindb cp .env.example .env ``` -### 3. Point `.env` at your PostgreSQL +### 3. Choose your database mode + +`.env.example` ships with the **internal DB** enabled — a bundled Postgres (with pgvector) that starts as part of the stack. For most users there is nothing to do in this step. + +The switch is one line in `.env`: + +``` +COMPOSE_PROFILES=internal-db # present = bundled DB starts automatically +``` + +Optional internal-DB knobs (defaults are fine): `POSTGRES_PORT` (host port for inspecting the DB with psql/adminer, default 5435), `POSTGRES_DB`, `POSTGRES_USER`, `POSTGRES_PASSWORD`. Note: these are baked into the data volume on first boot — to reset later: `docker rm -f braindb_db && docker volume rm braindb_pgdata` (wipes its data). -Edit `.env` and set `DATABASE_URL`. The value depends on **where your Postgres runs**: +**Bring your own Postgres instead?** Remove the `COMPOSE_PROFILES` line and set `DATABASE_URL` — everything (host, port, db name, credentials) lives in that one URL: **Option A — Postgres running as another Docker container on the same network** (e.g. a `postgres_container`): ``` @@ -72,7 +87,8 @@ DATABASE_URL=postgresql://postgres:password@host.docker.internal:5432/braindb ``` DATABASE_URL=postgresql://user:password@db.example.com:5432/braindb ``` -Any reachable hostname/IP works — the connecting user just needs network access, auth, and the extensions mentioned in step 1. + +External databases need the `pg_trgm` and `pgvector` extensions; the connecting user must be able to create them on first connection (migrations run `CREATE EXTENSION IF NOT EXISTS` on startup), or an admin pre-installs both. ### 4. Pick an LLM provider (for the internal agent) @@ -91,14 +107,16 @@ Adding a third provider (Together, OpenAI, local vLLM, whatever) is a two-line e ### 5. Create the Docker network, then bring the stack up -`docker-compose.yml` expects an external network called `local-network` so the `api` and `watcher` containers can reach your Postgres (and each other) by DNS name: +`docker-compose.yml` expects an external network called `local-network` so the containers can reach each other (and an external Postgres, if you use one) by DNS name: ```bash docker network create local-network # one-time, ignore error if it already exists docker compose up -d --build ``` -If your Postgres is a container (Option A in step 3), attach it to this network too: +With the internal DB (default), this also starts the bundled Postgres and waits for it to be healthy before the API boots. + +If you brought your own Postgres as a container (Option A in step 3), attach it to this network too: ```bash docker network connect local-network postgres_container ``` @@ -110,7 +128,7 @@ curl http://localhost:8000/health # {"status":"ok","embeddings":true} ``` -API at `http://localhost:8000`. Swagger UI at `http://localhost:8000/docs`. Database migrations run automatically on startup. +API at `http://localhost:8000`. Swagger UI at `http://localhost:8000/docs`. Browser UI (read-only frontend) at `http://localhost:8642`. Database migrations run automatically on startup. Drop a markdown file into `data/sources/` and the watcher sidecar picks it up within ~7 seconds — see [File Ingestion](#file-ingestion) below. @@ -150,6 +168,8 @@ See [BRAINDB_GUIDE.md](BRAINDB_GUIDE.md) for full API reference with curl exampl `POST /api/v1/memory/context` is the main endpoint. **Keywords are the indexing layer** — both the fuzzy and the embedding pathways match the query against keyword-entity content / embeddings, then entities surface via `tagged_with` edges. A keyword tagged on many entities is the hub; you don't need explicit `elaborates` / `refers_to` edges for an entity to be findable, as long as it has the right keywords. +![Retrieval pipeline — queries fan out to parallel fuzzy and semantic keyword matching, merge, graph-expand, and rank; always-on rules join the ranked context](docs/assets/braindb-retrieval.svg) + 1. **Multi-query search** — pass `queries: ["topic1", "topic2"]` to search multiple angles at once. Each query is matched against keyword entities by both pg_trgm trigram similarity AND query-embedding-vs-keyword-embedding cosine similarity; results are merged with the geometric mean (configurable `missing_signal_penalty` when only one signal fires). 2. **Per-search-term reservation (L1 diversity quota)** — each query you pass gets a guaranteed share of the result slots filled from THAT query's own top-ranked entities. Bare-keyword queries (`"Petros"`) reliably surface specific facts even when paired with broader semantic angles. 3. **Per-keyword reservation (L2 diversity quota)** — each dominant matched keyword gets a halving slot allowance (50% / 25% / 12.5% ..., floor 1). Stops one popular hub keyword (e.g. `user-profile` tagging 100 facts) from monopolising top-N. @@ -269,6 +289,8 @@ Replace `/ABSOLUTE/PATH/TO/braindb` with your repo path. The hook is async (non- Drop a file in `data/sources/` — the always-on watcher sidecar picks it up within 7s, ingests it, and runs a chunked fact-extraction pipeline that saves atomic facts into the knowledge graph linked back to the source via `derived_from` relations. Processed files move to `data/sources/ingested/`, failures to `data/sources/failed/` with an `.error.txt` sidecar. +![Save and ingest — the direct API lane, the agent lane, and the file-ingest watcher pipeline all converge into the knowledge graph](docs/assets/braindb-ingestion.svg) + ```bash cp ~/some-article.md data/sources/ docker logs braindb_watcher -f # watch the pipeline @@ -300,6 +322,10 @@ docker logs braindb_wiki_scheduler -f # the autonomous loop docker logs braindb_api -f # the agent doing the work ``` +![Wiki scheduler and maintainer loop — cron scans for entities not yet covered, the maintainer decides attach / create / consolidate / skip, suggestion jobs hand off to the writer, and the loop repeats](docs/assets/braindb-upkeep-loop.svg) + +![Wiki writer pipeline — lock and snapshot, gather context, draft with citations, reconcile relations, validate with retry, then commit a reversible living wiki page](docs/assets/braindb-writer.svg) + You do **not** drive this by hand. The `POST /api/v1/wiki/{cron,maintain,write}` endpoints exist for **debugging / inspection only** — normal operation is the sidecar. (Optional read-only review: `docker compose exec api python -m @@ -311,15 +337,11 @@ automatically. To run without it, bring the stack up excluding the service or scale it to 0 (`docker compose up -d --scale wiki_scheduler=0`), exactly as you would for the watcher; or point `LLM_PROFILE` at a local model. -## Frontend (optional, read-only) - -A small vanilla-JS frontend ships under `frontend/` — no build step. Three views (Reader for browsing wikis, Graph for visual exploration, Ops for watching the maintainer/writer pipeline) plus an Ask drawer that talks to the agent endpoint. Talks to the BrainDB API at `http://localhost:8000`. Serve it from the repo root: +## Frontend (read-only browser UI) -```bash -cd frontend && python -m http.server 8090 -``` +A small vanilla-JS frontend ships under `frontend/` — no build step — and is served by the stack itself: after `docker compose up -d`, open **`http://localhost:8642`** (change the port with `FRONTEND_PORT` in `.env`). Three views (Reader for browsing wikis, Graph for visual exploration, Ops for watching the maintainer/writer pipeline) plus an Ask drawer that talks to the agent endpoint. The UI calls the BrainDB API at `http://localhost:8000` from your browser. -Then open `http://localhost:8090`. See [frontend/README.md](frontend/README.md) for the design notes. +Prefer no extra container? Any static file server over `frontend/` works too, e.g. `cd frontend && python -m http.server 8642`. See [frontend/README.md](frontend/README.md) for the design notes. ## Stack @@ -328,4 +350,4 @@ Then open `http://localhost:8090`. See [frontend/README.md](frontend/README.md) - Alembic migrations - `sentence-transformers` + `Qwen/Qwen3-Embedding-0.6B` for keyword embeddings - `openai-agents[litellm]` + LiteLLM for the internal agent (DeepInfra / NIM / others pluggable via `LLM_PROFILE`) -- Docker Compose — `api` + `watcher` + `wiki_scheduler` services, external PostgreSQL +- Docker Compose — `api` + `watcher` + `wiki_scheduler` + `frontend` services, with a bundled Postgres (default) or your own diff --git a/docker-compose.test.yml b/docker-compose.test.yml new file mode 100644 index 0000000..d095836 --- /dev/null +++ b/docker-compose.test.yml @@ -0,0 +1,65 @@ +# Isolated test stack — what `pytest` runs against. NEVER your real data. +# +# docker compose -f docker-compose.test.yml up -d # start +# pytest # run the suite +# docker compose -f docker-compose.test.yml down -v # stop + wipe test data +# +# Own project namespace, own Postgres + volume, own network, own ports +# (api 8002, db 5436 — the personal stack uses 8000, the bench 8001/5434). +# No watcher and no wiki scheduler: tests exercise the API directly, and +# with no background extraction the suite is deterministic. +# +# LLM credentials pass through from the repo .env so the live-agent smoke +# test works; everything else is fully isolated from the personal stack. + +name: braindb_test + +services: + braindb_test_db: + image: pgvector/pgvector:pg17 + container_name: braindb_test_db + environment: + POSTGRES_USER: braindb + POSTGRES_PASSWORD: braindb + POSTGRES_DB: braindb_test + ports: + # Loopback-only. Published so the handful of direct-DB tests + # (e.g. graph_expand) can connect from the host. + - "127.0.0.1:5436:5432" + volumes: + - braindb_test_pgdata:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U braindb -d braindb_test"] + interval: 5s + timeout: 3s + retries: 10 + + braindb_test_api: + build: . + container_name: braindb_test_api + depends_on: + braindb_test_db: + condition: service_healthy + environment: + DATABASE_URL: postgresql://braindb:braindb@braindb_test_db:5432/braindb_test + API_PORT: 8002 + HF_TOKEN: ${HF_TOKEN:-} + LLM_PROFILE: ${LLM_PROFILE:-deepinfra} + AGENT_MODEL: ${AGENT_MODEL:-} + NVIDIA_NIM_API_KEY: ${NVIDIA_NIM_API_KEY:-} + DEEPINFRA_API_KEY: ${DEEPINFRA_API_KEY:-} + VLLM_API_KEY: ${VLLM_API_KEY:-} + AGENT_VERBOSE: "false" + extra_hosts: + - "host.docker.internal:host-gateway" + ports: + - "8002:8002" + volumes: + - .:/app + - ./data_test:/app/data + command: > + sh -c "alembic upgrade head && uvicorn braindb.main:app --host 0.0.0.0 --port 8002" + +volumes: + braindb_test_pgdata: + name: braindb_test_pgdata diff --git a/docker-compose.yml b/docker-compose.yml index 04e2f43..4e62aab 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,8 +5,19 @@ services: restart: unless-stopped networks: - local-network + # Starts the bundled DB first when the internal-db profile is active + # (COMPOSE_PROFILES=internal-db in .env). With the profile inactive the + # dependency is skipped entirely — external-DB setups are unaffected. + # `required: false` needs Docker Compose >= 2.20. + depends_on: + braindb_db: + condition: service_healthy + required: false environment: - DATABASE_URL: ${DATABASE_URL} + # Set DATABASE_URL in .env to use your own Postgres (external mode). + # Leave it unset with COMPOSE_PROFILES=internal-db and the api connects + # to the bundled braindb_db service below. + DATABASE_URL: ${DATABASE_URL:-postgresql://${POSTGRES_USER:-braindb}:${POSTGRES_PASSWORD:-braindb}@braindb_db:5432/${POSTGRES_DB:-braindb}} API_PORT: ${API_PORT:-8000} HF_TOKEN: ${HF_TOKEN:-} LLM_PROFILE: ${LLM_PROFILE:-deepinfra} @@ -54,6 +65,37 @@ services: - .:/app command: python -m braindb.ingest_watcher + # Bundled Postgres (pgvector) — exists ONLY when the internal-db profile is + # active, i.e. when .env contains COMPOSE_PROFILES=internal-db. Without that + # line this service is invisible to every compose command and external-DB + # setups behave exactly as before. Named braindb_db (not "postgres") so its + # DNS name can't collide with a user's own Postgres on local-network. + # POSTGRES_* values are baked into the volume on FIRST boot; to reset: + # docker rm -f braindb_db && docker volume rm braindb_pgdata + braindb_db: + image: pgvector/pgvector:pg17 + container_name: braindb_db + profiles: ["internal-db"] + restart: unless-stopped + environment: + POSTGRES_USER: ${POSTGRES_USER:-braindb} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-braindb} + POSTGRES_DB: ${POSTGRES_DB:-braindb} + ports: + # Loopback only — for inspecting the DB from the host (psql/adminer). + # The stack itself talks to braindb_db over the docker network and does + # not need this mapping. Change POSTGRES_PORT in .env if 5435 is taken. + - "127.0.0.1:${POSTGRES_PORT:-5435}:5432" + volumes: + - braindb_pgdata:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-braindb} -d ${POSTGRES_DB:-braindb}"] + interval: 5s + timeout: 3s + retries: 10 + networks: + - local-network + # Always-on wiki maintenance sidecar — same posture as `watcher`. It loops # cron -> maintain -> write so wikis self-organise from entities with zero # manual steps. To run without it (e.g. cost control), start the stack @@ -74,6 +116,26 @@ services: - .:/app command: python -m braindb.wiki_scheduler + # Read-only browser UI (frontend/ — plain static files, no build step). + # Loopback-only on purpose: the UI's API calls go to http://localhost:8000 + # from the BROWSER, so publishing this port beyond loopback wouldn't make + # the app usable remotely anyway. Change FRONTEND_PORT in .env if taken. + frontend: + image: nginx:alpine + container_name: braindb_frontend + restart: unless-stopped + ports: + - "127.0.0.1:${FRONTEND_PORT:-8642}:80" + volumes: + - ./frontend:/usr/share/nginx/html:ro + networks: + - local-network + +volumes: + # Data volume for the bundled internal DB (internal-db profile only). + braindb_pgdata: + name: braindb_pgdata + networks: local-network: external: true diff --git a/docs/assets/braindb-ingestion.svg b/docs/assets/braindb-ingestion.svg new file mode 100644 index 0000000..87245b2 --- /dev/null +++ b/docs/assets/braindb-ingestion.svg @@ -0,0 +1,57 @@ +BrainDB — save and ingest pipeline + + + + + + + DIRECT / AGENT + + FILE INGEST + + + + + DIRECT API + POST /entities/* + + AGENT + /agent/query · NL + + STORE + validate + persist + + + + + + DROP + data/sources/ + + WATCHER + poll 7s · dedup + + new? + + skip · dup + + CHUNK + 1200w · offsets + + EXTRACT + per chunk → facts + + + yes + + no + + + + + KNOWLEDGE GRAPH + typed entities + relations + keyword index · pgvector + + + diff --git a/docs/assets/braindb-logo.svg b/docs/assets/braindb-logo.svg new file mode 100644 index 0000000..62d3517 --- /dev/null +++ b/docs/assets/braindb-logo.svg @@ -0,0 +1 @@ +BrainDB diff --git a/docs/assets/braindb-mark.svg b/docs/assets/braindb-mark.svg new file mode 100644 index 0000000..c31fcdc --- /dev/null +++ b/docs/assets/braindb-mark.svg @@ -0,0 +1 @@ +BrainDB diff --git a/docs/assets/braindb-mechanism.svg b/docs/assets/braindb-mechanism.svg new file mode 100644 index 0000000..63ddaf2 --- /dev/null +++ b/docs/assets/braindb-mechanism.svg @@ -0,0 +1,54 @@ +BrainDB — one keyword, one graph + + + + + + + + + + + + + + FACT + A wide moat protects + long-term earnings. + + + + + WIKI + Intrinsic Value + + + + + + + + + + + + + + + + FACT + Owner earnings reveal + real cash flow. + + + + ∴ THOUGHT · DERIVED + A moated, cash-rich + company is a compounder. + + + + KEYWORD + intrinsic + value + diff --git a/docs/assets/braindb-retrieval.svg b/docs/assets/braindb-retrieval.svg new file mode 100644 index 0000000..fe642c0 --- /dev/null +++ b/docs/assets/braindb-retrieval.svg @@ -0,0 +1,56 @@ +BrainDB - retrieval pipeline + + + + + + + + QUERIES + queries[] + depth + + + + FUZZY MATCH + keywords · pg_trgm + + SEMANTIC MATCH + keywords · pgvector + per query · in parallel + + + + + + MERGE + geom-mean · penalty + + + + + + GRAPH EXPAND + ≤3 hops · 1·0.8·0.6 + + hops + + + + + RANK + decay × imp · L1/L2 + + + + + ALWAYS-ON RULES + injected every call + + + + RANKED CONTEXT + graph neighbourhood + ranked + capped + + + diff --git a/docs/assets/braindb-upkeep-loop.svg b/docs/assets/braindb-upkeep-loop.svg new file mode 100644 index 0000000..44987b9 --- /dev/null +++ b/docs/assets/braindb-upkeep-loop.svg @@ -0,0 +1,72 @@ +BrainDB — wiki scheduler and maintainer loop + + + + + + + + SCHEDULER + loops ~60s + + + CRON · SQL + scan orphans → triage + + + pending? + + + MAINTAIN · 1 LLM + agent researches + recall + view_tree + + + MAINTAINER + DECISION + + + + + yes + + LLM pluggable · DeepInfra / NIM / vLLM + + + + no + + idle · 0 LLM + + + + attach → #n + + create new + + consolidate + + skip · ambig. + + + + + + + + SUGGESTION JOB + queued for the writer + + + + + + → WRITER + phase 3 · 2 of 2 + + + + + + loop · next tick + diff --git a/docs/assets/braindb-writer.svg b/docs/assets/braindb-writer.svg new file mode 100644 index 0000000..c2c5b13 --- /dev/null +++ b/docs/assets/braindb-writer.svg @@ -0,0 +1,56 @@ +BrainDB - wiki writer pipeline + + + + + + + + SUGGESTION + attach·create·consol + + + LOCK + SNAPSHOT + prior revision saved + + + GATHER + members + contradictions + + + WRITER · LLM + skeleton + [[ref]] cites + + + + + + + + + RECONCILE + summarises · additive + + + validate + + + COMMIT + new revision + + + LIVING WIKI PAGE + grounded · cited + self-correcting + + + + pass + + + + + fail · retry + + every change logged → auditable & restorable + diff --git a/docs/assets/social-preview.png b/docs/assets/social-preview.png new file mode 100644 index 0000000..ad1525b Binary files /dev/null and b/docs/assets/social-preview.png differ diff --git a/frontend/README.md b/frontend/README.md index 8ef436a..799efc4 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -4,17 +4,15 @@ A thin, read-mostly browser UI for BrainDB. Vanilla HTML / CSS / JS — no build ## Run -The BrainDB backend must be running first (default: `http://localhost:8000`). From the repo root: +Served by the stack itself — `docker compose up -d` includes an nginx container for this directory. Open (change the port with `FRONTEND_PORT` in `.env`). The backend must be running too (default: `http://localhost:8000`). + +No container? Any static file server works. From the repo root: ```bash -python -m http.server 8090 -d frontend +python -m http.server 8642 -d frontend ``` -Then open . - -That's it. The frontend is a static page that talks to the API directly via `fetch`. CORS is already open on the backend. - -> If `8090` is in use on your machine, pick any free port: `python -m http.server -d frontend`. (Avoid `8080` on Windows with Docker Desktop installed — it's commonly held by the WSL backend.) +That's it. The frontend is a static page that talks to the API directly via `fetch`. CORS is already open on the backend. (If you pick your own port, avoid `8080` on Windows with Docker Desktop installed — it's commonly held by the WSL backend.) ## Pointing at a non-local backend diff --git a/frontend/braindb-logo.svg b/frontend/braindb-logo.svg new file mode 100644 index 0000000..62d3517 --- /dev/null +++ b/frontend/braindb-logo.svg @@ -0,0 +1 @@ +BrainDB diff --git a/frontend/braindb-mark.svg b/frontend/braindb-mark.svg new file mode 100644 index 0000000..c31fcdc --- /dev/null +++ b/frontend/braindb-mark.svg @@ -0,0 +1 @@ +BrainDB diff --git a/frontend/index.html b/frontend/index.html index 722e2ef..e764693 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -4,13 +4,14 @@ BrainDB +
-
BrainDB
+
BrainDB