LoCAL2 — Loosely Coupled Agent Language model, second generation
Project description
LoCAL2
Loosely Coupled Agent Language model — Second Generation.
LLM-native tool calling with Gemma 4 as the orchestrator. Web search, memory recall, and feedback loops augment Gemma's native reasoning — the model decides when to use them.
Reference hardware: Mac Mini M4 Pro, 64GB memory. Performance on lower-spec hardware will vary — tool calling and thinking tokens work best with sufficient VRAM/unified memory.
Prerequisites
- Python 3.11+
- Ollama
- Docker Desktop (for SearXNG web search)
Setup
1. Install Ollama
Download from ollama.com and install. Verify it's running:
curl http://127.0.0.1:11434/api/tags
2. Pull the models
ollama pull gemma4:e4b
ollama pull nomic-embed-text
gemma4:e4b is the default model for the generator and critic. gemma4:26b is also supported for stronger tool calling reliability; configure in config/generator.yaml. A dedicated grading model can be used for the critic by setting model in config/critic.yaml — the default is prometheus-7b:latest (Prometheus-7B-v2.0).
nomic-embed-text is required for episodic memory and the RAG library. Both use it to embed and retrieve passages.
After pulling, do a quick sanity check:
ollama run gemma4:e4b
>>> hello
Type /bye to exit.
3. Install Docker Desktop
Download from docker.com/products/docker-desktop. Check your chip first:
uname -m # arm64 = Apple Silicon, x86_64 = Intel
After installing, launch Docker Desktop and verify:
docker --version
4. Set up Python environment
Create and activate a virtual environment:
python3 -m venv .venv
source .venv/bin/activate
You should see (.venv) on the left of your prompt. Upgrade pip first:
python3 -m pip install --upgrade pip
Then install dependencies:
pip install -r requirements.txt
5. Configure secrets
cp .env.example .env
Open .env and fill in MY_SEARX_SECRET. SearXNG requires this to start — it's an internal signing key, not a user-facing password. Generate one with:
openssl rand -hex 32
Paste the output as MY_SEARX_SECRET=<value> in .env. You only need to do this once.
BRAVE_API_KEY and TAVILY_API_KEY are only needed if you switch the search provider in config/web_search.yaml away from the default SearXNG.
SEMANTIC_SCHOLAR_API_KEY is optional but recommended — the free tier rate-limits to 1 req/sec without a key. Add it to your shell environment (not .env):
echo 'export SEMANTIC_SCHOLAR_API_KEY=<your-key>' >> ~/.zshrc
source ~/.zshrc
Get a free key at semanticscholar.org/product/api.
6. Start SearXNG
docker compose up -d
SearXNG will be available at http://localhost:8080. Verify it's running:
curl "http://localhost:8080/search?q=test&format=json" | head -c 200
Once started, SearXNG runs in the background and restarts automatically with Docker Desktop on login.
7. Run LoCAL2
# UI only
python run_local.py
# UI + REST API
python run_local.py --api
# Headless (API only)
python run_local.py --headless --api
# Use a different model
python run_local.py --model gemma4:26b
Configuration
All tunable parameters live in config/:
| File | Controls |
|---|---|
config/generator.yaml |
Model, context size, temperature, tool schemas, tool timeout |
config/web_search.yaml |
Search provider, max results, request timeout |
config/web_fetch.yaml |
Max chars extracted, fetch timeout |
config/critic.yaml |
Critic model, grading rubric, grade timeout |
config/memory.yaml |
ChromaDB path, episodic memory collection name |
config/search_memory.yaml |
Max results returned by search_memory tool |
config/semantic_scholar.yaml |
Max results, timeout, API fields returned |
config/documents.yaml |
Chunk size/overlap, topic, ChromaDB collection for RAG library |
config/location.yaml |
Optional static location override (skips live IP geolocation) |
config/bus.yaml |
ZMQ proxy ports |
config/system.yaml |
Debug flags |
Document library (RAG)
LoCAL2 maintains a persistent local knowledge base you can query with search_library. Use the library window (📚 button in the sidebar) to ingest files.
Ingest from the UI
- Click 📚 in the sidebar to open the library window.
- Set a Topic (e.g. "MBA textbooks covering strategy, finance, and marketing") and click Save — Gemma uses this to decide when to search the library instead of the web.
- Click + Files to pick individual files, or + Folder to ingest an entire folder recursively. Supported formats: PDF, TXT, MD, PY, YAML, JSON, CSV.
A progress bar shows embedding progress per file. Files are chunked into 1500-character segments and embedded with nomic-embed-text. Re-ingesting the same file is safe — chunks are upserted by deterministic ID.
Ingest from the CLI
# Ingest one or more files
PYTHONPATH=src python scripts/ingest.py path/to/file.pdf path/to/file.txt
# List all ingested sources
PYTHONPATH=src python scripts/ingest.py --list
# Delete a source by filename
PYTHONPATH=src python scripts/ingest.py --delete "file.pdf"
Running stories
PYTHONPATH=src python tests/run_story.py tests/stories/s1_basic_qa.yaml
PYTHONPATH=src python tests/run_story.py tests/stories/s2_multi_turn.yaml
After a reboot
Two services don't start automatically and need to be launched before running LoCAL2:
1. Docker Desktop — SearXNG won't be running. Open Docker Desktop, wait for it to be ready, then verify:
docker compose ps # searxng should show "Up"
docker compose up -d # if it's not running
2. Ollama — On macOS, a stale ollama serve process from before the reboot can persist alongside the freshly launched Ollama.app, splitting IPv4 and IPv6 across two processes. The Python ollama library may connect to the wrong one, causing ollama.chat() to hang silently with no error.
Check before starting:
pgrep -fl ollama # should show exactly one "ollama serve" process
If two appear (one from /usr/local/bin/ollama, one from /Applications/Ollama.app), kill the older one:
kill <old-pid>
The Ollama.app process will then own port 11434 on both IPv4 and IPv6.
Architecture
See .claude/plan_local2.html for the full architecture plan.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file local2-0.1.0.tar.gz.
File metadata
- Download URL: local2-0.1.0.tar.gz
- Upload date:
- Size: 15.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0c4c4898c9ea23905ab28286115da8029a9812ed1b2d4a4dbcb2aced2b930e8c
|
|
| MD5 |
aeabf2a7816071c18444d242555d5767
|
|
| BLAKE2b-256 |
84270c889182fa9b081de16947e3272e148c248b726335d94ac7496d50ecb85d
|
File details
Details for the file local2-0.1.0-py3-none-any.whl.
File metadata
- Download URL: local2-0.1.0-py3-none-any.whl
- Upload date:
- Size: 236.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
daee307e1f776b0ec7c74abe43d403017d05846c8d0ca9b1abb5965fb9a63218
|
|
| MD5 |
264b3d90ffbacce77b522861f6f34a57
|
|
| BLAKE2b-256 |
773e27b8481e517e191b93e325db911ecd90041680a35026b06476d3c68783e9
|