yggdrasil.loki.engines.ollama_engine¶
ollama_engine ¶
Local Ollama -backed :class:TokenEngine.
Talks to a local Ollama <https://ollama.com>_ server (default
http://localhost:11434, override with OLLAMA_HOST) over its native
chat API — so any open model you've ollama pull-ed runs on this machine,
free and private. Available only when the server answers.
Every call rides the project's :class:~yggdrasil.http_.HTTPSession (its
connection pooling, retry budget, and response parsing) — no bespoke HTTP — so
probes get a quick single-shot waiting profile and the real calls reuse the
shared pool.
OllamaEngine ¶
OllamaEngine(
*,
model: Optional[str] = None,
tier: Optional[str] = None,
host: Optional[str] = None
)
Bases: LocalEngine
Reason with a local model served by Ollama, sized to the workstation.
bootstrap_model
property
¶
The default model for this box — the resource-sized row, or the
engine's :attr:default_model fallback.
installed_models ¶
Models already pulled onto this Ollama server (empty if unreachable).
has_model ¶
True when model (with or without a :tag) is already pulled.
pull ¶
pull(
model: Optional[str] = None,
*,
timeout: float = 1800.0,
on_progress: "Optional[Callable[[dict[str, Any]], None]]" = None
) -> str
Download model onto the Ollama server (lazy — the heavy bit).
Defaults to :attr:bootstrap_model, the lightweight brain. Without
on_progress this does the non-streaming pull (one final status object).
With on_progress it streams Ollama's NDJSON progress events —
{"status", "completed", "total"} per chunk — so a caller can render a
live download bar; the final status string is returned either way.
ensure ¶
ensure(
model: Optional[str] = None,
on_progress: "Optional[Callable[[dict[str, Any]], None]]" = None,
) -> dict[str, Any]
Make sure model is available, pulling it only if missing.
Returns {"model", "was_present", "status"} — the lazy-install
receipt so a caller (the setup skill) can report what it did. An
on_progress callback streams the pull's download progress.
choose_tier ¶
choose_tier(
messages: Optional[list[dict[str, Any]]] = None,
system: Optional[str] = None,
) -> str
Adaptive tier for this request: "deep" or "fast".
Sizes on the message content (the actual work, not the fixed system boilerplate) and scans both message and system text for reasoning signals. Long or signalled requests get the deep tier; the rest stay fast. Override for a smarter policy.
resolve_model ¶
resolve_model(
*,
messages: Optional[list[dict[str, Any]]] = None,
system: Optional[str] = None,
tier: Optional[str] = None
) -> Optional[str]
An explicit pin wins; otherwise the model sized to this workstation.
Local models are resource-bound, so the remote fast/deep cost
tier doesn't apply — the box, not the prompt, picks the size.
generate ¶
generate(
prompt: str,
*,
system: Optional[str] = None,
tier: Optional[str] = None,
**options: Any
) -> str
Convenience: complete a single user prompt → reply text.
stream ¶
stream(
messages: list[dict[str, Any]],
*,
system: Optional[str] = None,
max_tokens: int = DEFAULT_MAX_TOKENS,
tier: Optional[str] = None,
**options: Any
) -> "Iterator[str]"
Yield reply text incrementally as it is produced.
The default has no real streaming — it runs :meth:complete and
yields the whole reply once. Engines whose SDK streams override this
to yield token deltas live (and still record usage on completion).
generate_stream ¶
generate_stream(
prompt: str,
*,
system: Optional[str] = None,
tier: Optional[str] = None,
**options: Any
) -> "Iterator[str]"
Convenience: stream a single user prompt → text chunks.