Commit graph

16 commits

Author SHA1 Message Date
Yiorgis Gozadinos
b374d5eb83
Replace ask_question and analyze with execute_code
In Claude Code the client is the model, so the server no longer runs one.
execute_code runs a Python program per call in the analysis sandbox over
the selected documents and returns what it printed; the sandbox is created
and closed per call so Monty's cumulative budget and a frozen mount never
outlive a program. --no-agents goes with the two tools, and format_citations
in haiku.rag.utils goes with its only caller.

The sandbox exposes chunk metadata to code: chunk_meta on search results,
metadata on list_documents rows and in metadata.json, and chunks.jsonl per
document. A host-side failure inside a program, a document read or an
in-code search raising, reaches the program by exception type only and is
logged with its traceback. recovery_hint moves to haiku.rag.sandbox.

Closes #604.
2026-09-07 10:02:42 +03:00
Yiorgis Gozadinos
7f7223e0ac
Default to ollama:qwen3.8
Replaces gpt-oss on ModelConfig, qa.model and processing.title_model, and
ministral-3 on the picture-description model. qa.model.vision follows the
model and is now true.

enable_thinking was gated on the gpt-oss name, so it did nothing for
qwen3.8. With title_model's max_tokens of 100 the reasoning consumed the
whole budget and title generation returned an empty string. The mapping
now applies to any ollama model via reasoning_effort(): false sends
"none", true sends "high". Measured on qwen3.8:27b-mlx, "low" does not
disable thinking and "none" does; gpt-oss is the inverse, its template
has no "none" level, so it keeps "low".

Picture description bypasses get_model -- docling posts the request
itself from a params dict -- so the flag was inert on that path too.
vlm_api_params() carries reasoning_effort into both converters' request
bodies. At max_tokens 200 the description survived either way, but the
switch cut completion tokens from 141 to 45.

test_search_tool_skips_binary_content_when_qa_model_is_text_only asserted
the vision default rather than setting it; it now configures vision=False
itself.

docs/benchmarks.md keeps ministral-3: those are recorded measurements.
2026-09-04 12:36:36 +03:00
Yiorgis Gozadinos
31fc8aba29
Guard dedup against compaction and document search units
A picture deduplicated within a burst must still reach the model once in
its own question and, when cited, again via the capsule re-fetch after
compaction; uncited it is dropped. Two wire tests pin both paths. The
harness builds the rag capability with defer_loading=False: a deferred
evidence capability the model has not loaded presents an empty record,
so compaction computes boundary 0 and rewrites nothing.

qa.md describes max_searches in units.
2026-09-02 12:29:12 +03:00
Yiorgis Gozadinos
ed5519b38d
Make the documented configuration match the code
search.limit was documented as 10 in three places while the default is 5.
The documented way to disable reranking, provider: "", is a valid
ModelConfig, so it raised "Unknown reranking provider" — disabling means
omitting reranking.model or setting it to null. The inline provider list
named four of the six rerankers. prompts.picture_description: null fails
validation, since the field is a non-optional str.

storage.data_dir: "" coerced to Path("") — the working directory — while two
doc pages promise the platform default and soliplex's example config relies
on it. Empty or whitespace now resolves to the platform directory; an
explicit "." is still honoured, so a config that wants the working directory
says so.

Three tests keep this from drifting again: every fenced yaml block in the
docs validates against AppConfig, every value in the complete example either
equals its default or is listed as a deliberate deviation, and empty
data_dir resolves to the platform default.

init-config's test reimplemented the command body instead of invoking it,
which is why the command carried a coverage pragma. It now goes through
CliRunner, with the refuse-to-overwrite guard covered too.
2026-08-19 15:52:50 +03:00
Yiorgis Gozadinos
485a8f901e
Document the real max_searches default
Both configuration pages said 3; the default has been 5.
2026-07-30 14:56:17 +03:00
Yiorgis Gozadinos
221c90af72
Bound a compute-only call at code_timeout
The pool watchdog counts only the time a worker spends running code, so a read
that blocks the worker never trips it. The margin above code_timeout therefore
guarded a race that cannot happen, and only bought a runaway call 90s where 60s
was configured. Pass code_timeout straight through. The two limits are disjoint:
the watchdog bounds a call that computes, and the read deadline bounds a call
that reads.

Drop the ordering test, which was true for any positive margin. The containment
test no longer sets code_timeout to zero, because that value now also disables
the watchdog and kills the worker before the read guard can refuse. It patches
the guard instead.

Monty 0.0.19 runs a plain class and a class with __enter__ and __exit__. Only
inheritance and metaclasses raise. Say that in the instructions.

MemoryFile is no longer constructed, so drop the import, the annotation, and the
stale references in the sandbox docstring and CLAUDE.md. That CLAUDE.md line
also still claimed a ThreadPoolExecutor, _run_async, and a fresh interpreter per
call.
2026-07-28 19:11:19 +03:00
Yiorgis Gozadinos
522959d9b4
Check the code timeout before each document read
The VFS bridge suspends the Monty worker for the length of a read. Monty checks
its duration budget between interpreter steps, so it cannot check while a read
is in flight. Code that reads in a loop overran a 60s budget by minutes. A read
takes about 20ms on a 2789-document corpus, so a full scan spends about 55s in
reads alone.

Check the deadline before each read. Raising from inside the callback answers the
worker's suspension, which keeps the session usable.

Monty also spends max_duration_secs across the session rather than per call, and
the sandbox reuses the session so that variables persist. Budget it for
code_timeout * max_executions. At the old per-call value the first slow call
starved every later one.

Do not wrap feed_run in asyncio.wait_for. Cancelling during pure compute is
clean, but cancelling while a read waits for an answer wedges the session with a
protocol RuntimeError that escapes execute(). A call that computes without
reading stays bounded by the session budget alone.
2026-07-28 19:11:19 +03:00
Yiorgis Gozadinos
43c17a6777
fix capability execution limits and chat loading 2026-07-24 15:26:17 +03:00
Yiorgis Gozadinos
9deb1f2bd4
replace haiku.skills with native Pydantic AI capabilities 2026-07-24 15:26:17 +03:00
Yiorgis Gozadinos
c1ec13f081
Lower search.max_context_chars default to 5000 2026-07-14 11:58:42 +03:00
Yiorgis Gozadinos
b14152a45b
Keep picture and table hits section-bounded during context expansion 2026-07-09 11:05:40 +03:00
Yiorgis Gozadinos
cd77bd9889
Bound analysis execute_code calls to avoid request-limit nulls 2026-06-06 14:52:05 +03:00
Yiorgis Gozadinos
e55125763f
Document setting thinking on OpenAI compat providers 2026-05-21 10:25:48 +03:00
Yiorgis Gozadinos
0ee00334c7
drop prose emdashes and semicolons; minor fixes 2026-05-20 14:27:16 +03:00
Yiorgis Gozadinos
910d178b00
docs: rebuild Skills section, drop pitch prose 2026-05-20 14:27:16 +03:00
Yiorgis Gozadinos
8c57a3ca99
Drop the multi-agent research workflow 2026-05-20 12:46:48 +03:00
Renamed from docs/configuration/qa-research.md (Browse further)