Replace repository with DuckLM runtime

This commit is contained in:
2026-05-20 01:00:28 +08:00
parent ddc285b8f4
commit 4a84ada770
190 changed files with 7060 additions and 13602 deletions
+5
View File
@@ -0,0 +1,5 @@
# Architecture
DuckLM is organized as WebChat and FastAPI over Duck Core. Duck Core owns task state, context building, model calls, events, tools, approvals, skills, experience, and memory adapters.
The first vertical slice is WebChat -> FastAPI -> RuntimeLoop -> ModelClient -> llama-server -> SQLite event timeline.
+9
View File
@@ -0,0 +1,9 @@
# Experience Learning
Experience records are stored in SQLite. Suggested skill updates are written to `skills/_proposals/` and are not applied automatically.
Use:
```bash
curl http://127.0.0.1:8000/v1/experience
```
+71
View File
@@ -0,0 +1,71 @@
# How To Run
1. Install dependencies:
```bash
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -e ".[dev]"
```
2. Configure:
```bash
cp .env.example .env
```
The default `DUCK_MAIN_MODEL_PATH` points to `./models/Qwen3.6/nonMTP/Qwen3.6-35B-A3B-UD-Q4_K_M.gguf`.
3. Start `llama-server`:
```bash
bash scripts/llama/start_main.sh start
```
Useful process commands:
```bash
bash scripts/llama/start_main.sh status
bash scripts/llama/start_main.sh logs --follow
bash scripts/llama/start_main.sh restart
bash scripts/llama/start_main.sh stop
```
4. Start DuckLM API:
```bash
python -m duck_core.api
```
5. Open WebChat:
```text
http://127.0.0.1:8000/
```
6. Send a task:
```bash
curl -X POST http://127.0.0.1:8000/v1/chat \
-H "Content-Type: application/json" \
-d '{"message":"Скажи коротко, что ты DuckLM","workspace":"./workspace","debug":true}'
```
7. Inspect events:
```bash
curl http://127.0.0.1:8000/v1/tasks/<task_id>/events
```
8. Approvals:
```bash
curl http://127.0.0.1:8000/v1/approvals/pending
```
9. Stop services:
```bash
bash scripts/llama/start_main.sh stop
docker compose -f docker-compose.memory.yml down
```
+15
View File
@@ -0,0 +1,15 @@
# How To Test
Run smoke tests:
```bash
python -m pytest tests/smoke -v
```
Run verification scripts against a running API:
```bash
bash scripts/verify/verify_basic_chat.sh
bash scripts/verify/verify_models_roles.sh
bash scripts/verify/verify_tool_blocking.sh
```
+44
View File
@@ -0,0 +1,44 @@
# Local Llama Server
DuckLM expects an OpenAI-compatible `llama-server` at `http://127.0.0.1:8081/v1` by default.
On the current Radeon RX580 system, `llama.cpp` is built locally with Vulkan:
```bash
bash scripts/llama/build_vulkan.sh
```
The main model is Qwen3.6 35B A3B nonMTP:
```text
models/Qwen3.6/nonMTP/Qwen3.6-35B-A3B-UD-Q4_K_M.gguf
```
Start it in the background with:
```bash
bash scripts/llama/start_main.sh start
```
Manage the process:
```bash
bash scripts/llama/start_main.sh status
bash scripts/llama/start_main.sh logs
bash scripts/llama/start_main.sh logs --follow
bash scripts/llama/start_main.sh restart
bash scripts/llama/start_main.sh stop
```
The local `.env` uses:
```env
DUCK_LLAMA_SERVER_BIN=./vendor/llama.cpp/build/bin/llama-server
DUCK_CTX_SIZE=4096
DUCK_N_GPU_LAYERS=20
DUCK_PARALLEL=1
DUCK_LLAMA_DEVICE=Vulkan0
DUCK_LLAMA_EXTRA_ARGS="--reasoning off --cache-ram 0"
```
MTP is available only through `scripts/llama/start_thinker_mtp_experimental.sh` and is not used by the action JSON endpoint by default.
+5
View File
@@ -0,0 +1,5 @@
# Memory Architecture
Semantic memory uses Qdrant as the vector store. Embeddings come from `/v1/embeddings` when the model backend supports it.
If embeddings are unavailable, `VectorMemory` fails explicitly with `EmbeddingsUnavailableError`; it does not invent a local embedding algorithm.
+7
View File
@@ -0,0 +1,7 @@
# Model Roles
Roles are logical, not physical. `thinker`, `critic`, `coder`, `action`, and `summary` may all point to the same model.
Each role can differ by prompt, temperature, output limit, response format, schema, memory scope, and endpoint. Request-level parameters can change per call. Backend-level parameters such as GGUF path, context size, GPU offload, MTP, and server port require the backend to be started with the desired settings.
See `config/models.yaml` for one model mapped to all roles.
+5
View File
@@ -0,0 +1,5 @@
# Performance And MTP
MTP/speculative decoding is an inference backend concern. DuckLM keeps action JSON on the normal endpoint by default.
Use `scripts/llama/start_thinker_mtp_experimental.sh` only for experiments. Benchmark scaffolding is in `scripts/bench/bench_runtime.py`.
-24
View File
@@ -1,24 +0,0 @@
# UI Bootstrap And Review Flow Plan
## Goal
Move the web chat UI to Bootstrap 5.3 with Bootswatch themes and improve review/password/terminal-output ergonomics.
## Required Changes
- Replace the current hand-written visual system in `app/api/static/index.html` with Bootstrap 5.3 layout/components.
- Add Bootswatch theme support with a visible theme selector and persistent localStorage choice.
- Password/secret input must submit on Enter as well as the "Отправить" button.
- Console/tool output must render inside a collapsed Bootstrap accordion item.
- The accordion body must contain terminal-style output inside `<pre></pre>`.
- The terminal accordion must expand only when the user clicks it.
- Review UI must show critic/system assessment and user voting buttons:
- `Ошибочное действие`
- `Всё верно`
- optional correction/comment text.
## Notes
- Keep runtime event handling WebSocket-driven.
- Do not mix console output with assistant prose.
- Keep raw tool output available for debugging, but collapsed by default.
+9
View File
@@ -0,0 +1,9 @@
# Skills
Skills are procedural memory, not hardcoded routing. The first skill is `analyze_project`, loaded from `skills/analyze_project/skill.yaml`.
Use:
```bash
curl http://127.0.0.1:8000/v1/skills
```
@@ -0,0 +1,83 @@
# DuckLM Runtime Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Build the first runnable DuckLM local cognitive runtime from `Ducklm.md`.
**Architecture:** FastAPI exposes WebChat and HTTP endpoints, RuntimeLoop coordinates tasks, ModelClient calls an OpenAI-compatible `llama-server`, and SQLite persists tasks/events/approvals/experience. Tools, skills, and memory are small adapters with clear boundaries so later stages can grow without turning the runtime into hardcoded workflow rules.
**Tech Stack:** Python 3.11+, FastAPI, httpx, aiosqlite, Pydantic, Jinja2, PyYAML, jsonschema, Qdrant client.
---
### Task 1: Tests First
**Files:**
- Create: `tests/smoke/test_models_config.py`
- Create: `tests/smoke/test_model_client.py`
- Create: `tests/smoke/test_api_health.py`
- Create: `tests/smoke/test_event_log.py`
- Create: `tests/smoke/test_action_directive_schema.py`
- Create: `tests/smoke/test_tool_gateway.py`
- Create: `tests/smoke/test_approvals.py`
- Create: `tests/smoke/test_skill_registry.py`
- Create: `tests/smoke/test_experience_recorder.py`
- Create: `tests/smoke/test_vector_memory.py`
- [ ] Write smoke tests for config, model role mapping, stores, tools, approvals, skills, experience, memory, and API health.
- [ ] Run `python -m pytest tests/smoke -v` and verify tests fail because implementation modules do not exist.
### Task 2: Runtime Core
**Files:**
- Create: `pyproject.toml`
- Create: `.env.example`
- Create: `config/models.yaml`
- Create: `duck_core/config.py`
- Create: `duck_core/model_client.py`
- Create: `duck_core/events/store.py`
- Create: `duck_core/tasks/store.py`
- Create: `duck_core/tasks/state.py`
- Create: `duck_core/context_builder.py`
- Create: `duck_core/runtime_loop.py`
- Create: `duck_core/api.py`
- [ ] Implement settings and model config loading.
- [ ] Implement ModelClient role-based chat calls with latency and usage capture.
- [ ] Implement SQLite task and event stores.
- [ ] Implement RuntimeLoop for `POST /v1/chat`.
- [ ] Implement FastAPI endpoints and WebChat rendering.
### Task 3: Stage Adapters
**Files:**
- Create: `duck_core/tools/*`
- Create: `duck_core/approvals/service.py`
- Create: `duck_core/skills/registry.py`
- Create: `duck_core/experience/recorder.py`
- Create: `duck_core/reflection.py`
- Create: `duck_core/memory/*`
- Create: `duck_core/schemas/action_directive.schema.json`
- [ ] Implement safe file read/write and allowlisted shell execution.
- [ ] Implement exact-action approval records.
- [ ] Implement filesystem SkillRegistry.
- [ ] Implement experience recording and skill proposal writing.
- [ ] Implement Qdrant memory adapter with explicit embedding-disabled errors.
### Task 4: Project Surface
**Files:**
- Create: `scripts/llama/*`
- Create: `scripts/verify/*`
- Create: `scripts/bench/bench_runtime.py`
- Create: `duck_core/web/templates/*`
- Create: `duck_core/web/static/*`
- Create: `skills/analyze_project/*`
- Create: `docker-compose.memory.yml`
- Create: `Makefile`
- Create: `README.md`
- Create: `docs/*.md`
- [ ] Add llama-server scripts, verification scripts, benchmark, WebChat pages, starter skill, compose file, make targets, and docs.
- [ ] Run smoke tests and syntax checks.
+9
View File
@@ -0,0 +1,9 @@
# Tool Gateway
The model does not execute tools directly. It emits an action directive and `ToolGateway` validates the tool name and arguments before execution.
Implemented tools:
- `file_read`: reads inside workspace only.
- `file_write`: writes inside workspace only and refuses overwrites unless `overwrite=true`.
- `shell_exec_safe`: runs only allowlisted commands and blocks dangerous commands.
+25
View File
@@ -0,0 +1,25 @@
# Web API
Endpoints:
```text
GET /health
GET /v1/status
GET /v1/models/roles
GET /v1/models/ping
POST /v1/chat
POST /v1/tasks
GET /v1/tasks
GET /v1/tasks/{task_id}
GET /v1/tasks/{task_id}/events
GET /v1/tasks/{task_id}/stream
GET /v1/approvals/pending
POST /v1/approvals/{approval_id}/allow_once
POST /v1/approvals/{approval_id}/allow_forever
POST /v1/approvals/{approval_id}/deny
GET /v1/skills
GET /v1/skills/{skill_id}
GET /v1/experience
GET /v1/experience/{id}
GET /v1/memory/search?q=...
```