Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Charlie πŸ€–

An offline-first AI assistant built on BitNet β€” runs on a R2,500 Raspberry Pi with no internet, no API costs, and no load shedding excuses.

Named after my daughter, born March 2026. Built so that wherever she grows up, the people around her have access to the same quality of information as anyone else.


What is Charlie?

Charlie is a fine-tuned BitNet-compatible model and inference framework designed to run completely offline on consumer hardware. It uses Microsoft's 1-bit ternary weight architecture via bitnet.cpp to achieve useful AI capability on hardware that costs a fraction of what cloud AI requires.

Model size:      ~400MB
RAM required:    ~1.1GB  
Hardware:        Core i5, Raspberry Pi 4/5 (8GB), any x86/ARM CPU
Internet:        Not required
API costs:       Zero
GPU:             Not required

Charlie runs at ~16 tokens/second on a Core i5 and ~8-11 tokens/second on a Raspberry Pi 5. That is fast enough for natural conversation.


Why does this exist?

Most AI assistants assume you have:

  • Fast, reliable internet
  • A credit card for API billing in USD
  • Hardware powerful enough to run large models

In South Africa β€” and most of the world β€” none of those assumptions hold reliably. Load shedding cuts power for 4-12 hours a day. Rural connectivity is unreliable or nonexistent. Cloud AI costs are denominated in dollars that most people don't have.

Charlie assumes none of those things. She runs on a device that costs R2,500, works during Stage 6 load shedding on a battery bank, and can be distributed on a USB stick.


Current Status

Component Status
Base model (Falcon-Edge 1B, tool calling fine-tune) βœ… v1 training complete
bitnet.cpp inference βœ… Working on Core i5 WSL2
Tool router (pre-LLM token optimisation) βœ… Designed, testing
Markdown knowledge base (zero dependencies) βœ… Built
Web learner (SearXNG + Crawl4AI β†’ offline KB) βœ… Built
Bootstrap primitives (safe self-improvement) βœ… Designed
FastAPI OpenAI-compatible server πŸ”§ In progress
Raspberry Pi deployment πŸ”§ In progress
isiZulu language support πŸ“‹ Planned v2

Architecture

Charlie is built around four separating concerns:

SOUL.md      β†’ personality and tone (runtime, no retraining)
MODE.md      β†’ online/offline/community mode (runtime)
skills/      β†’ capabilities (training time)
tools/       β†’ what Charlie can do (runtime, MCP)

Tool routing β€” the key innovation

Instead of injecting all tool schemas into every prompt (OpenClaw-style token bloat), Charlie uses a pre-LLM router that selects only the 2-3 tools relevant to the current prompt:

User prompt
    ↓
Tool Router (keyword + semantic, <5ms)
    ↓
Inject only relevant tool schemas (~160 tokens vs ~800 tokens)
    ↓
Charlie LLM (3,800+ tokens available for conversation)

On a 4096 token context window this saves ~640 tokens per request β€” the difference between Charlie losing context after 5 exchanges and maintaining a full conversation.

Skills architecture

Skills are composable training ingredients, not runtime plugins:

charlie/
β”œβ”€β”€ skills/
β”‚   β”œβ”€β”€ tool_calling/     ← when and how to call tools
β”‚   β”œβ”€β”€ restraint/        ← when NOT to call tools
β”‚   └── bootstrap/        ← how to propose new skills
β”œβ”€β”€ tools/
β”‚   β”œβ”€β”€ offline/          ← always available
β”‚   β”‚   β”œβ”€β”€ rag_search    ← local markdown knowledge base
β”‚   β”‚   β”œβ”€β”€ calculator    ← safe maths
β”‚   β”‚   β”œβ”€β”€ load_shedding ← Eskom schedule lookup
β”‚   β”‚   └── local_calendar
β”‚   └── online/           ← available when connected
β”‚       β”œβ”€β”€ searxng_search
β”‚       β”œβ”€β”€ gmail (MCP)
β”‚       β”œβ”€β”€ google_calendar (MCP)
β”‚       └── web_learn     ← SearXNG + Crawl4AI β†’ saves to KB
β”œβ”€β”€ serve/
β”‚   β”œβ”€β”€ tool_router.py
β”‚   β”œβ”€β”€ knowledge_base.py
β”‚   β”œβ”€β”€ web_learner.py
β”‚   └── bootstrap_primitives.py
β”œβ”€β”€ SOUL.md
└── MODE.md

Offline knowledge base

Charlie's knowledge base is plain markdown files. No vector database. No indexing pipeline. No dependencies.

# A community health worker adds local knowledge:
nano knowledge/local/local_clinic.md
# Charlie picks it up on next restart

BM25 search with title and tag boosting. Runs on a Pi Zero. Anyone who can type can contribute.

Bootstrap skill

When Charlie cannot accomplish a task she uses four MCP-wrapped primitive tools to research and propose new skills:

mcp_searxng    β†’ research topics
mcp_requests   β†’ fetch documentation
mcp_bash       β†’ read files, run scripts (allowlisted commands only)
write_file     β†’ save proposals to skills/proposed/ only

The safety model: Charlie proposes. Humans approve. Nothing auto-deploys. All proposals go to skills/proposed/ and require explicit human review before moving to skills/active/.


Model

Charlie v1 is fine-tuned from tiiuae/Falcon-E-1B-Base (bfloat16 revision) using LoRA on tool-calling datasets.

Validation run (v0) Full run (v1)
Dataset 6,500 examples 22,500 examples
Epochs 1 2
Max sequence length 256 tokens 384 tokens
Final loss 0.856 ~0.40 (estimated)
Smoke test 1/3 TBD

HuggingFace:


What I learned building this

Eight walls have been hit and documented:

  1. Microsoft BitNet is not directly fine-tunable β€” quantized weights cannot store gradients. Use Falcon-Edge bfloat16 revision instead.
  2. Falcon-Edge revision confusion β€” prequantized = inference only, bfloat16 = training. This is not documented clearly anywhere.
  3. Tokenizer mismatch causes loss of 9.8 β€” base model revisions ship bare tokenizers with no special tokens. Use the instruct tokenizer.
  4. <tool_call> must be a single token β€” multi-token tool call tags are unreliable at 1B scale. Confirmed: token ID 21 for Falcon-Edge instruct tokenizer.
  5. BitnetLinear + PEFT incompatible β€” LoRA cannot attach to custom quantized layers. Apply LoRA before replace_linear_with_bitnet_linear().
  6. fp16 + BitnetLinear = grad scaler crash β€” BitnetLinear produces fp16 gradients that PyTorch's AMP scaler refuses to unscale.
  7. 256 token sequences truncate tool call closing tags β€” minimum 384 tokens needed to capture complete tool call format.
  8. Kaggle draft sessions don't run unattended β€” use "Save & Run All (Commit)" for overnight training runs.

Full findings: docs/findings.md


Getting started

Run inference locally (WSL2 or Linux)

# Install bitnet.cpp
git clone --recursive https://github.com/microsoft/BitNet.git
cd BitNet

# Fix known build issue
sed -i 's/int8_t \* y_col = y + col \* by;/const int8_t * y_col = y + col * by;/' \
    src/ggml-bitnet-mad.cpp

# Install clang and build
sudo apt install -y clang cmake build-essential
python setup_env.py -md models/BitNet-b1.58-2B-4T -q i2_s

# Download Charlie v1
huggingface-cli download jeff3c/charlie-falcon-edge-tool-calling-v1 \
    --local-dir ~/models/charlie-v1/

# Convert to GGUF
python convert-hf-to-gguf-bitnet.py \
    ~/models/charlie-v1/ \
    --outtype i2_s \
    --outfile ~/models/charlie-v1.gguf

# Run
python run_inference.py \
    -m ~/models/charlie-v1.gguf \
    -p "What meetings do I have tomorrow?" \
    -cnv -t 2

Fine-tune your own Charlie

# Requires Kaggle account (free) or any GPU with 16GB VRAM
# Training script: finetune/kaggle_charlie_v1_full.py

# Key config:
BASE_MODEL       = "tiiuae/Falcon-E-1B-Base"
MODEL_REVISION   = "bfloat16"          # NOT prequantized
TOKENIZER_MODEL  = "tiiuae/Falcon-E-1B-Instruct"  # NOT base
TOKENIZER_REVISION = "main"

See finetune/README.md for the complete guide.


Personalising Charlie

Edit SOUL.md to change personality without retraining:

# SOUL.md
name: Charlie
tone:
  style: friendly      # friendly | professional | clinical | encouraging
  verbosity: concise
  warmth: high
communication:
  use_local_references: true   # knows what load shedding is
  use_humour: occasionally

Edit MODE.md to switch between online and offline modes:

# MODE.md
active_mode: offline_personal   # offline_community | offline_personal | connected_personal

Adding knowledge

Drop a markdown file in knowledge/:

nano knowledge/health/local_clinic.md
# Manguzi Community Clinic

Open Monday to Friday, 7:30am to 4:30pm.
Services: antenatal care, TB treatment, immunisations.
Emergency: 035 592 0021

#health #clinic #local

Charlie finds it on next restart. No indexing. No pipeline. Just a file.


Roadmap

v1 (current)

  • Tool calling fine-tune on Falcon-Edge 1B
  • bitnet.cpp inference on CPU
  • Markdown knowledge base
  • Tool router

v2

  • FastAPI OpenAI-compatible server
  • Raspberry Pi deployment guide
  • Bootstrap skill (propose new capabilities)
  • Restraint fine-tune (when NOT to call tools)
  • Web learner (learn from internet, store offline)

v3

  • isiZulu language support
  • SMS interface (R200 USB GSM modem)
  • Community kiosk deployment guide
  • Request advice skill (consult frontier models, cache forever)

Contributing

Charlie is built for a context most AI projects ignore. If you want to help:

  • Add knowledge β€” drop a markdown file in knowledge/ for your domain
  • Add a language β€” isiZulu, Afrikaans, Sesotho data contributions welcome
  • Test on hardware β€” results on Raspberry Pi, old laptops, ARM devices
  • Add a skill β€” see skills/tool_calling/SKILL.md for the format
  • Report findings β€” undocumented walls you hit are valuable contributions

All contributions go through skills/proposed/ β€” the same process Charlie uses for bootstrap. Humans review before anything merges.


Built with


Acknowledgements

Built with Claude (Anthropic) as a collaborative pair programmer over an extended development session. The architecture decisions, mission, and persistence through 8 consecutive build failures were human. The code generation and research assistance were AI. Both mattered.


License

MIT β€” do whatever you want with it, just keep it accessible.


Charlie is named after my daughter, who will be born in April 2026. Built so that the communities around her have access to the same information as anyone else.

About

An offline AI assistant based for the bitnetcpp inference engine

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors