Files
command-center/omp-docs/pi/models.md
Frank 62a70caebb docs(okf): 53 Obsidian wikilinks become OKF links
`[[page|Label]]` is Obsidian syntax, not OKF. `kb-lint` resolves it Obsidian-style — by
filename, anywhere in the bundle — so it has never tripped the link gate, while every other
consumer of the bundle (an OKF renderer, a Gitea wiki export, `grep` for reachability) sees
bracketed text where a link should be. That is how two generated pages ended up with no
inbound link at all and nobody noticed: the my-first link census of the bundle reported them
as orphans because their only inbound edges were wikilinks.

Mechanical conversion, 52 links across 17 pages, each resolved against the same page set
`kb-lint` uses: an explicit `|Label` is kept verbatim, an unlabelled link takes the target's
frontmatter `title`. Targets are emitted bundle-absolute (`/tools/niri/tips.md`), the form
the spec recommends and the form 99 existing links in this bundle already use.

Two links were `[[index]]`, which resolves by filename to 21 pages — the ambiguity that
filename-resolution invites. Both meant their own directory's index, so both are now written
out in full: `/tools/gitea/index.md`, `/tools/niri/index.md`.

The linter still tolerates wikilinks; whether it should reject them outright is an open
question on #64, because that would replace the two tests pinning today's tolerance.

Refs #64
2026-10-21 02:11:56 -07:00

148 lines
6.3 KiB
Markdown

---
type: reference
title: Pi Models Configuration
description: Complete reference for models.json — provider definitions, model specs, and API endpoints for the Frank Program.
tags:
- pi
- models
- providers
- llamacpp
- unverified
timestamp: 2026-08-28
---
# Pi Models Configuration (`models.json`)
`models.json` defines the LLM providers pi connects to. Each provider specifies a base URL, API type, authentication, and available models.
**Location:** `/home/dank/.pi/agent/models.json`
---
## Providers
Current providers in `models.json` (verified 2026-08-27, after the
2026-08-18 service swap):
### llamacpp (dankserver)
| Property | Value |
|----------|-------|
| **Base URL** | `http://192.168.0.235:7770/v1` |
| **API** | `openai-completions` |
| **Auth** | None (EMPTY) |
| **Host** | [dankserver](/system/dankserver.md) |
#### Models
| Model ID | Context Window | maxTokens | Reasoning | Input Types |
|----------|---------------|-----------|-----------|-------------|
| `frank-default-small` | 262,144 | 262,144 | Yes | Text, image |
The server is upstream llama.cpp (b10121) serving HauhauCS
Qwen3.6-35B-A3B-Uncensored-Aggressive Q6_K_P with 36 MoE experts on CPU,
ngram-mod spec, 4 slots of ~175K context. The server serves the loaded
model regardless of the requested model ID. Requests with any `model`
value succeed.
### llamacpp (dankclaw)
| Property | Value |
|----------|-------|
| **Base URL** | `http://192.168.0.143:7770/v1` |
| **API** | `openai-completions` |
| **Auth** | None (EMPTY) |
| **Host** | [dankclaw](/system/dankclaw.md) |
> 2026-08-22: `frank-default-large` moved from `:52625` to `:7770` on
> Dankclaw (operator request: the primary inference server sits on the
> standard llama.cpp port). The OpenWebUI quadlet
> (`OPENAI_API_BASE_URL`) was re-pointed to `:7770` in the same change.
#### Models
| Model ID | Context Window | maxTokens | Reasoning | Input Types |
|----------|---------------|-----------|-----------|-------------|
| `frank-default-large` | 262,144 | 262,144 | Yes | Text, image |
The server is the ROCmFPX llama.cpp runtime serving
[kingjones777's Qwen3.8-Flash-Next Uncensored ROCmFP4 STRIX_LEAN GGUF](https://huggingface.co/kingjones777/Qwen3.8-Flash-Next-Uncensored-ROCmFP4-STRIX_LEAN-GGUF)
— a 177B-parameter, 56B-MoE model sharded into 3 Q4_0-ROCmFP4 GGUF files
(98.3 GB total) with a standalone BF16 vision embedding project (0.85 GB).
Speculative decoding uses `--spec-type ngram-mod` because the ROCmFPX quantization
drops the 4B MTP head. The model is loaded from
`/home/dank/models/kingjones-Qwen3.8-Flash-Next-Uncensored-ROCmFP4-STRIX_LEAN/`;
the original Q4_0-ROCmFP4-STRIX variant remains as a `.backup` directory.
Context is 262144 (native max), 1 slot. Concurrent requests queue on the
single slot; the server never preempts a running generation. It exposes
`reasoning_content` in deepseek reasoning format and supports
multimodal (vision) inference via the embedded mmproj.
2026-08-27: Upgraded from the original Qwen3.8-Flash-Next Q4_0-ROCmFP4-STRIX
GGUF to the Uncensored STRIX_LEAN variant with vision support and
ngram-mod speculative decoding.
### Thinking Levels
Pi's default thinking level is configured globally in `settings.json` as
`"defaultThinkingLevel": "medium"`. The model entries map Pi's `max` level to the llama.cpp-supported `xhigh`
wire value. Pi shows `max` in the thinking selector from the global settings,
but sends `reasoning_effort: "xhigh"` to both local llama.cpp endpoints.
`thinkingLevelMap` can translate a UI level without changing the global default.
Verified 2026-07-22:
`getSupportedThinkingLevels` returns `off,minimal,low,medium,high,xhigh`
and the live server accepts `reasoning_effort: "xhigh"` and returns
`reasoning_content` (verified 2026-08-21).
Mechanism (pi-ai `models.js` + `openai-completions.js`):
- `getSupportedThinkingLevels`: extended levels `xhigh`/`max` appear only
when `thinkingLevelMap` defines them (string = supported, `null` =
hidden, omitted = not supported).
- Default request path (no `compat.thinkingFormat`): sends
`reasoning_effort = thinkingLevelMap[level] ?? level` when
`supportsReasoningEffort` is true (default for this provider).
## Token Budgets (`maxTokens`)
Verified in the pi source, 2026-08-16 (`@earendil-works/pi-coding-agent` 0.84.1 + `pi-ai`):
- `maxTokens` is an optional model field in `models.json`. When omitted, pi defaults the model object to 16,384 (`provider-composer.js`).
- The value is metadata. It drives the model-picker "max out" display and length-error recovery (`isRecoverableLength`).
- Normal chat turns do not send `max_tokens`. The request builder sends the field only when a per-request option is set (`openai-completions.js buildParams`: `if (options?.maxTokens)`). The agent loop passes no such option.
- The only pi calls that send `max_tokens` are context compaction and branch summarization. They are deliberately budgeted.
## Model Selection Strategy
```mermaid
graph LR
A[User Request] --> B{Complexity?}
B -->|Large context / long docs| C[frank-default-large<br/>CIRU llama.cpp dankclaw :7770, 262K ctx]
B -->|Fast / interactive| D[frank-default-small<br/>llama.cpp dankserver :7770, 262K ctx]
The CIRU endpoint (dankclaw) serves the 177B 56B-MoE model with
262144 context, ngram-mod speculative decoding, 1 slot. Concurrent
requests queue on the single slot. The upstream
llama.cpp endpoint (dankserver) serves the 35B A3B MoE model with 36
experts on CPU and 262K context per slot.
## Live Defaults
`settings.json` picks the main session provider and model (verified 2026-08-19):
| Scope | Provider | Model |
|-------|----------|-------|
| Main session | `llamacpp (dankclaw)` | `frank-default-large` |
| Subagent default | `frank-default-small` (llamacpp dankserver) | ~262K ctx per slot, ngram-mod spec |
| Subagent overrides | scout, researcher | `frank-default-small` |
| Subagent overrides | planner, worker, reviewer, oracle, context-builder | `frank-default-large` (llamacpp dankclaw) |
The subagent model IDs (`frank-default-small`, `frank-default-large`) resolve against the new provider set in `models.json`. The current mappings are `max -> xhigh` for both local models; the global and subagent defaults remain `max`.
---
## See Also
- [settings](/core/settings.md) — Main configuration file
- [dankserver](/system/dankserver.md) — Primary llama.cpp server
- [dankclaw](/system/dankclaw.md) — Secondary llama.cpp server