pip install mellea, Ollama running locally.
Async methods
Every sync method onMelleaSession has an a-prefixed async counterpart with the
same signature and return type:
Parallel generation
ainstruct() returns a ModelOutputThunk immediately — generation starts in the
background but the value is not resolved until you call avalue(). This lets you
fire multiple generations and resolve them all at once:
wait_for_all_mots is a convenience wrapper:
Note: All thunks passed towait_for_all_motsmust belong to the same event loop, which is always the case when usingMelleaSession.
Streaming
Enable streaming by passingModelOption.STREAM: True in model_options. Consume
incremental output chunks with mot.astream():
astream() behaves:
- Each call returns only the new content since the previous call.
- When the thunk is fully computed (
is_computed()returnsTrue), the finalastream()call returns the complete value. - If the thunk is already computed,
astream()returns the full value immediately.
Warning: Do not call astream() from multiple coroutines simultaneously on
the same thunk. Each thunk should have a single reader.
Async and context
UseSimpleContext (the default) with concurrent async requests. Using ChatContext
with concurrent requests can cause stale context issues — Mellea logs a warning
when this is detected:
ChatContext with async, await each call before starting the next:
SimpleContext.
Streaming with per-chunk validation
stream_with_chunking() adds per-chunk validation to a streaming generation.
It splits the accumulated text into semantic units (sentences, words, or
paragraphs), calls stream_validate() on each chunk in parallel, and can
exit early if any requirement returns "fail" — preventing the consumer from
seeing invalid content mid-stream.
The primary way to observe a stream_with_chunking() run is via typed
StreamEvent objects from result.events():
result.astream() instead:
astream() (raw chunks) and events() are available on the same result
object. They use independent queues, so you can run them concurrently with
asyncio.gather. Both are single-consumer — a second iteration on either
will block indefinitely.
The stream_validate tri-state
Each call to stream_validate returns a PartialValidationResult with one of
three values:
After a natural stream end,
validate() is called on every non-"fail"
requirement (both "pass" and "unknown"). This means "pass" from
stream_validate does not replace the final validate() call.
See also: The Requirements System — Streaming validation
See also: Tutorial 02: Streaming and Async | act() and aact()