fix(advice): stale advice must not overwrite a correction
The review found a race between the background advice thread and the
brewer correcting a reading.
`set_reading_advice` wrote unconditionally by id. The advice is
generated in the background, so if the brewer corrects a reading while
the advice for the OLD gravity is still being generated, the slow thread
lands afterwards and overwrites the fresh advice with advice about a
reading that no longer exists. The reading ends up with the final
gravity from the correction and the advice from before it.
Reproduced against the live database:
wrote advice for 1050
wrote advice for 1020
late stale write matched: 0
final sg: 1020 | final advice: 'ADVICE FOR THE CORRECTION'
The write is now conditional on the reading still holding the gravity
the advice was generated for, so a late thread matches nothing.
Also
----
`finish_reason` is now checked. A reply that stopped at the token
ceiling is incomplete - it may be advice that stops mid-sentence - and
it was being stored as if it were the whole answer. It is now marked
as cut off.
173 tests (up from 171).
This commit is contained in:
@@ -198,11 +198,24 @@ def call_ollama(prompt: str, *, url: str | None = None, model: str | None = None
|
||||
if not choices:
|
||||
raise RuntimeError("the model returned no choices")
|
||||
message = choices[0].get("message") or {}
|
||||
|
||||
# Some models put their working in a separate field. It is ignored -
|
||||
# the advice is the content.
|
||||
content = message.get("content") or ""
|
||||
content = content.strip()
|
||||
if not content:
|
||||
raise RuntimeError("the model returned an empty response")
|
||||
return _trim_advice(_strip_reasoning(content))
|
||||
|
||||
# A reply cut off at the token ceiling is INCOMPLETE. It may be
|
||||
# advice that stops mid-sentence, so it is marked as truncated rather
|
||||
# than stored as if it were the whole answer.
|
||||
finish_reason = choices[0].get("finish_reason") or body.get("done_reason")
|
||||
truncated = finish_reason == "length"
|
||||
|
||||
advice = _trim_advice(_strip_reasoning(content))
|
||||
if truncated:
|
||||
advice = _trim_advice(advice + " (the reply was cut off)")
|
||||
return advice
|
||||
|
||||
|
||||
def _trim_advice(text: str) -> str:
|
||||
|
||||
Reference in New Issue
Block a user