v0.5.0
·
24 commits
to main
since this release
Put the chat boilerplate behind ui.conversation and ai.talk
Writing chat.ipynb made it obvious that the interesting part of a chat
lesson is about four lines, and the other forty-five are the same every
time. That boilerplate was already copied into five places — three in the
README, one in each notebook — so fixing it meant fixing it five times.
Two pieces, split by what they need. ui.conversation() holds a
conversation and renders it; say/reply/note replace hand-built
{"role": ..., "content": ...} dicts, and it can be displayed while still
empty, which ui.chat cannot. Display stays in Chat — Conversation
delegates to it rather than growing a second copy of the markup.
ai.talk() sits on top and adds what only matters when the other side is a
model: folding recent turns back into the prompt, since ai.ask() keeps
nothing between calls; cutting the answer where a small model starts
writing your next line for you; and rebuilding the bubbles as tokens
arrive, without letting the half-written text into the history where it
would poison the next prompt. It lives in _ai.py and reaches for ui only
when rendering, the same way Recommendation does, so ui still knows
nothing about ai.
talk.form() owns both the field and the handler, so the field name and
the argument name can no longer drift apart — a mismatch there breaks
only the form, and only in a notebook. Since forms still do nothing in
PyHiroba, it says so there instead of rendering a dead input.
The README's AI chat examples were the ones with no memory at all: their
history fed the display while ai.ask() saw only the latest question.
Rewriting them closes that quietly along the way.