Repository navigation
Ask: general answers from the local model, offline - #547
Draft
raiseCatError wants to merge 1 commit into
Draft
raiseCatError wants to merge 1 commit into
raiseCatError wants to merge 1 commit into
Conversation
/btw and /ask keep every deterministic path (NMSh actions and their
confirmations, refusals, Copy/Insert-only command suggestions). A question
Ask cannot place, or a follow-up to a model answer, now becomes a new
`answer` task in the existing user-global model service:
- the question, a bounded recent history kept per Ask in this window only
(never persisted or shared), the shell and OS family, and terminal output
only when asked for ("explain the last error", "summarise the last
output"): one block's redacted, bounded excerpt, with NMSh's own diagnosis
shown first as a separate turn
- Qwen3 non-thinking by default with the model card's sampling; "Think it
through" runs a bounded thinking pass on request
- streaming partial text for llama.cpp, Ollama and LM Studio; cancel for one
request (Esc keeps Ask open; closing Ask or a window stops it); service
generation limit; older services are never sent the task
- model text is sanitized untrusted data rendered by NMSh (code, lists,
narrow widths, NO_COLOR); nothing in it becomes an action, and shell code
blocks only get NMSh's own risk label and Copy
- fail closed: requests that look like they contain a secret, or ask for
credentials or the environment, never reach a model
- clarifying questions for vague requests ("fix it"), and in Auto the intent
model's reading of an unclear request is offered as a choice instead of
being acted on
Adds an evaluation set and a maintainer evaluator that drives the real
TerminalApp against a private model service and measures latency, tokens
per second, memory, history, cancellation and unloading.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
/btw(alias/ask) can now answer general and terminal questions with the local model, offline. Every existing path stays as it was: NMSh actions and their confirmations, refusals, and Copy/Insert-only command suggestions. No existing issue covers this; related to #432 (command suggestions), which this does not change.Design: docs/design/ask-conversation.md.
Before and after
Before: Ask mapped requests onto NMSh capabilities. The model only chose a capability (intent), hinted folds, or suggested one command. A question it could not place got "I'm not sure what you mean yet", and in Auto the 0.6B intent model often read it into the wrong capability. Recorded with the real model:
After:
Ask · local model · <model>.Routing (deterministic; the model never routes)
The
answertaskOne more task in the existing user-global model service; no second model or backend.
/askstarts empty. The service is stateless, with the prompt cache off.{text, truncated};Local model (…).Thinking and non-thinking
Both modes were tested on the real model; results are in the examples below.
Prompt tuning (measured, real model)
A/B on 10 weak cases × 3 runs: adding "rewrite: reply with only the new text" and "say you cannot see the user's files" took loose checks from 18/30 to 22/30. It stopped answers like "No, there is no typo on line 12 of your zshrc" and invented dates.
Quoting the text apart from the instruction: this turned "Rewrite this more politely: send me the report now" from "Sure! Let me know when you're ready…" into "Please send me the report." (5/5). Corrections measured 5/5 unquoted against 4/5 quoted, so only rewrite/shorten/translate requests are quoted.
Real Qwen3 0.6B examples (final run, verbatim)
Good:
sorted()example →sorted(my_list, reverse=True)with codegit stash pop"Wrong or weak (the loose checks miss some of these; I read every answer):
"Go to school yesterday."(5/5 correct in a separate run)Routing in the final run: 48 of 49 as expected. The one miss is a known gap kept in the set: "In a shell, what is the difference between > and >>?" is claimed by NMSh's shell guide.
Performance (Apple M2, 8 GB, llama.cpp b11146 Metal, Qwen3-0.6B-Q8_0)
No larger model was evaluated: none is installed, and NMSh never downloads one.
Tests
tests/askConversation.test.ts(fake runtime): validation and sanitizing, request bounds, history trimming, prompt, ChatML and soft switch, stream parsing, service streaming, thinking budget, cancel (queued, running, other window untouched), closing window, timeouts, older service, eligibility, signals, context excerpt, shell checks, rendering at 24/40/80 columns, NO_COLOR.tests/askConversationApp.test.ts(real TerminalApp, stub model): every route in the evaluation set; questions never reach the intent model; actions and refusals kept; streaming labelled turn with nothing actionable; follow-up history, bounds and a new Ask starting empty; Esc stops without closing; typing during generation; close stops it; context only when asked, redacted; fail-closed cases; recording off/on; Think it through; copy; intent guess becomes a choice; follow-up and other-language routing.tests/ask*.test.ts,tests/understanding.test.tsand the two new files — 174 passed, 0 failed.scripts/local-model/askEval.tswithaskEvalSet.ts(49 cases across general knowledge, programming, shell and git, reasoning, rewriting, follow-ups, ambiguous, current events, can't-know, command-like and security).npm run verify: see the comment below; the first local run was under load averages up to 32.Needs human terminal testing (not done)
Ghostty / Terminal.app with a real model:
Unsuitable for 0.6B
Factual recall is unreliable (it said "Sydney"). Arithmetic and reasoning need the thinking pass and still fail sometimes. Its git explanations are often wrong. It is fine for short rewrites, translations of simple phrases, common programming idioms, and saying what it cannot know. The labels and the design say so; a larger, user-chosen model was not measured.