Replace repository with DuckLM runtime
This commit is contained in:
@@ -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.
|
||||
@@ -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
|
||||
```
|
||||
@@ -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
|
||||
```
|
||||
@@ -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
|
||||
```
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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`.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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=...
|
||||
```
|
||||
Reference in New Issue
Block a user