You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
POST /api/search/ask/simple returns HTTP 200 with an answer that is cut off mid-sentence, with no error indication to the caller. Root cause appears to be that open_notebook/graphs/ask.py hardcodes max_tokens=2000 in all three LLM calls of the ask graph, with no config/env override path. This is the same pattern already fixed for transformations (#565 -> #568) and podcasts (#639 -> #982/#992/#991/#1197), but the ask/Q&A graph appears to have been missed.
Because non-English languages (e.g. Japanese) often consume substantially more tokens for the same amount of content, this cap is hit far more easily in those languages, making the bug much more visible for non-English-speaking users while being harder to notice for English-only maintainers/testers.
Environment
Docker image: lfnovo/open_notebook:v1-latest (rolling tag; exact commit could not be pinned down — Docker Hub shows the same digest as 1.14.0 for linux/amd64 as of 2026-07-25, but this was not independently verified beyond the tag page)
Chat model: Anthropic claude-sonnet-5
Embedding model: Ollama nomic-embed-text
Confirmed independently that the same hardcoding exists in the current main branch on GitHub (see "Root cause" below), so this is not specific to our image/version.
Steps to Reproduce
Set up a notebook with sources in Japanese (or any token-dense non-English language).
Call POST /api/search/ask/simple with a Japanese question.
Repeat with a few different Japanese questions against the same notebook.
Observed Behavior
HTTP status is 200 (no error surfaced).
In our testing, 2 out of 3 Japanese questions returned answers cut off mid-sentence / mid-token. One answer ended abruptly mid-sentence; another ended in the middle of what looks like a source ID reference.
This is consistent with hitting a hard output-token cap during generation, though we did not inspect finish_reason/stop_reason from the underlying provider response to confirm this directly — flagging this as something maintainers may want to check when reproducing.
There is no warning, error, or truncation indicator returned to the API caller. The user has no way to know the answer is incomplete.
Root Cause (verified against upstream main)
In open_notebook/graphs/ask.py (main branch, as of 2026-07-25), all three provision_langchain_model(...) calls pass a hardcoded max_tokens=2000, with no config or environment variable to override it:
call_model_with_messages() — the strategy-generation call (structured/JSON output)
write_final_answer() — final answer synthesis (the one most likely responsible for the user-visible truncation)
We were not able to obtain a fully reliable exact line number for these three call sites — two different retrieval methods against the same file gave inconsistent line numbers (apparently due to a rendering artifact, not a real code difference), so we're intentionally not quoting a specific line number here to avoid pointing at the wrong line. They are easy to find with:
We only confirmed the hardcoding exists — we have not confirmed that all three call sites are equally responsible for the truncation we observed. The first call (call_model_with_messages) requests structured/JSON output, so hitting the cap there would more likely surface as a JSON-parsing error rather than a silently truncated prose answer. The truncation we actually observed looks more consistent with the provide_answer / write_final_answer stages.
Why This Is More Visible in Non-English Languages
For a given amount of semantic content, tokenizers used by most LLM providers typically require more tokens to represent Japanese (and several other non-English/non-Latin-script languages) than to represent equivalent English content. A fixed 2000-token output cap that is rarely hit in English can be hit routinely in Japanese, especially for longer or more detailed answers. This means the same codebase can look "fine" in English-language testing while silently degrading for non-English users.
Precedent
This exact class of bug (hardcoded max_tokens causing silent truncation) has already been reported and fixed twice in this repo for other code paths:
The ask/Q&A graph (graphs/ask.py) appears to be the one remaining major code path with the same hardcoding.
Separately, #947 (Model & Provider Configuration design, ratified 2026-07-21) lists a universal parameter tier including max_tokens as part of its Phase 1 scope, and #830 notes that provision_langchain_model() already supports per-call max_tokens overrides via Esperanto >=2.21.0. This suggests the underlying plumbing to fix this already exists; it's a matter of wiring graphs/ask.py to use a configurable value rather than a literal 2000.
Suggested Fix (any of the following, not mutually exclusive)
At minimum, detect when the model output was cut off due to the token cap (e.g. via finish_reason/stop_reason if available from the provider) and surface a warning to the API caller / UI instead of silently returning HTTP 200 with an incomplete answer.
Open Questions for Maintainers
Can you confirm via finish_reason/stop_reason whether the observed truncation is in fact due to hitting the 2000-token cap, as opposed to some other cause?
Does this reproduce with providers other than Anthropic? We have only tested with claude-sonnet-5.
Notes on What We Could Not Verify
We could not pin down the exact commit corresponding to our lfnovo/open_notebook:v1-latest image (rolling tag).
We did not verify this against a from-source / non-Docker install.
We did not search GitHub Discussions (only Issues/PRs) for prior reports.
Summary
POST /api/search/ask/simplereturns HTTP 200 with an answer that is cut off mid-sentence, with no error indication to the caller. Root cause appears to be thatopen_notebook/graphs/ask.pyhardcodesmax_tokens=2000in all three LLM calls of the ask graph, with no config/env override path. This is the same pattern already fixed for transformations (#565 -> #568) and podcasts (#639 -> #982/#992/#991/#1197), but the ask/Q&A graph appears to have been missed.Because non-English languages (e.g. Japanese) often consume substantially more tokens for the same amount of content, this cap is hit far more easily in those languages, making the bug much more visible for non-English-speaking users while being harder to notice for English-only maintainers/testers.
Environment
lfnovo/open_notebook:v1-latest(rolling tag; exact commit could not be pinned down — Docker Hub shows the same digest as1.14.0forlinux/amd64as of 2026-07-25, but this was not independently verified beyond the tag page)claude-sonnet-5nomic-embed-textmainbranch on GitHub (see "Root cause" below), so this is not specific to our image/version.Steps to Reproduce
POST /api/search/ask/simplewith a Japanese question.Observed Behavior
finish_reason/stop_reasonfrom the underlying provider response to confirm this directly — flagging this as something maintainers may want to check when reproducing.Root Cause (verified against upstream
main)In
open_notebook/graphs/ask.py(main branch, as of 2026-07-25), all threeprovision_langchain_model(...)calls pass a hardcodedmax_tokens=2000, with no config or environment variable to override it:call_model_with_messages()— the strategy-generation call (structured/JSON output)provide_answer()— per-search-result answer generationwrite_final_answer()— final answer synthesis (the one most likely responsible for the user-visible truncation)We were not able to obtain a fully reliable exact line number for these three call sites — two different retrieval methods against the same file gave inconsistent line numbers (apparently due to a rendering artifact, not a real code difference), so we're intentionally not quoting a specific line number here to avoid pointing at the wrong line. They are easy to find with:
We only confirmed the hardcoding exists — we have not confirmed that all three call sites are equally responsible for the truncation we observed. The first call (
call_model_with_messages) requests structured/JSON output, so hitting the cap there would more likely surface as a JSON-parsing error rather than a silently truncated prose answer. The truncation we actually observed looks more consistent with theprovide_answer/write_final_answerstages.Why This Is More Visible in Non-English Languages
For a given amount of semantic content, tokenizers used by most LLM providers typically require more tokens to represent Japanese (and several other non-English/non-Latin-script languages) than to represent equivalent English content. A fixed 2000-token output cap that is rarely hit in English can be hit routinely in Japanese, especially for longer or more detailed answers. This means the same codebase can look "fine" in English-language testing while silently degrading for non-English users.
Precedent
This exact class of bug (hardcoded
max_tokenscausing silent truncation) has already been reported and fixed twice in this repo for other code paths:max_tokens(fixed in fix: update esperanto dep and increase transformation max_tokens #568)max_tokens(fixed via fix: pass max_tokens through to podcast_creator for outline/transcript generation #982/feat(frontend): expose episode profile max_tokens in the UI #992, further exposed in UI via [Feature]: expose episode profile max_tokens in the UI #991/fix(podcasts): clarify episode max_tokens field and fix empty-state error #1197)The ask/Q&A graph (
graphs/ask.py) appears to be the one remaining major code path with the same hardcoding.Separately, #947 (Model & Provider Configuration design, ratified 2026-07-21) lists a universal parameter tier including
max_tokensas part of its Phase 1 scope, and #830 notes thatprovision_langchain_model()already supports per-callmax_tokensoverrides via Esperanto >=2.21.0. This suggests the underlying plumbing to fix this already exists; it's a matter of wiringgraphs/ask.pyto use a configurable value rather than a literal2000.Suggested Fix (any of the following, not mutually exclusive)
max_tokensfor the ask graph configurable via settings/env var (consistent with how [Feature]: expose episode profile max_tokens in the UI #991/fix(podcasts): clarify episode max_tokens field and fix empty-state error #1197 exposed it for podcasts).finish_reason/stop_reasonif available from the provider) and surface a warning to the API caller / UI instead of silently returning HTTP 200 with an incomplete answer.Open Questions for Maintainers
finish_reason/stop_reasonwhether the observed truncation is in fact due to hitting the 2000-token cap, as opposed to some other cause?claude-sonnet-5.Notes on What We Could Not Verify
lfnovo/open_notebook:v1-latestimage (rolling tag).