Skip to content

compiler: concept update can write partial pages after finish_reason=length #148

Description

@fuyizheng3120

Problem

During openkb add, concept update calls can hit the provider/model output length limit (finish_reason == "length"). OpenKB prints a warning, but the truncated response can still be parsed via json_repair and written to wiki/concepts/*.md, leaving partially rewritten concept pages on disk.

In practice this means the command can finish with [OK] while one or more concept pages are silently corrupted/truncated and require manual repair.

Environment

  • OpenKB: v0.4.2 (c92f2e9)
  • Python: uv tool install, Python 3.12 venv
  • KB config:
language: zh
model: openai/claude-sonnet-4-6
pageindex_threshold: 20

Reproduction

Re-ingest a medium/large markdown document that updates already-large concept pages:

openkb --kb-dir /Volumes/WDSN7100-2TB/大喵OpenKB add \
  /Volumes/WDSN7100-2TB/大喵OpenKB/raw/claude-desktop-1m-context-zh-patch-guide.md

Observed output:

Adding: claude-desktop-1m-context-zh-patch-guide.md
  Compiling short doc...
    summary.......................... 34.2s (in=6428, out=1884)
    concepts-plan....... 7.2s (in=11882, out=452)
    Generating 5 concept(s) (concurrency=5)...
    concept: electron-app-bundle-patching... 37.1s (in=9693, out=1946)
    update: macos-codesign-entitlements... 46.5s (in=12118, out=3429)
    entity: claude-desktop... 24.4s (in=9719, out=1298)
openkb.agent.compiler WARNING: LLM [update: claude-model-whitelist] hit length limit — output may be truncated.
    [WARN] update: claude-model-whitelist hit length limit — output may be truncated.
    update: claude-model-whitelist... 67.3s (in=12869, out=4096)
openkb.agent.compiler WARNING: LLM [update: patch-survival-strategy] hit length limit — output may be truncated.
    [WARN] update: patch-survival-strategy hit length limit — output may be truncated.
    update: patch-survival-strategy... 70.1s (in=13566, out=4096)
openkb.agent.compiler WARNING: LLM [update: claude-desktop-3p-gateway] hit length limit — output may be truncated.
    [WARN] update: claude-desktop-3p-gateway hit length limit — output may be truncated.
    update: claude-desktop-3p-gateway... 72.6s (in=13444, out=4096)
  [OK] claude-desktop-1m-context-zh-patch-guide.md added to knowledge base.

Afterwards, at least two concept pages had visibly truncated tails and had to be manually repaired:

  • wiki/concepts/claude-model-whitelist.md
  • wiki/concepts/claude-desktop-3p-gateway.md

Example of a truncated tail:

| Code tab 仍显示 200k,3P 配置看起来正确 | 按版本确认

and another:

- **已是 ad-hoc

Root cause hypothesis

_warn_if_truncated() detects the length finish reason correctly:

if finish_reason != "length":
    return
sys.stdout.write(f"    [WARN] {step_name} hit length limit{cap} — output may be truncated.\n")

But the result is still returned as normal content. _gen_update() then calls _parse_json(raw), and json_repair may salvage a truncated JSON prefix into a parseable object. That object is then written to disk.

Relevant flow:

raw = await _llm_call_async(... f"update: {name}", response_format=_JSON_RESPONSE_FORMAT)
parsed = _parse_json(raw)
content = parsed.get("content") or ""
...
return name, content, True, brief

This is related to but not covered by:

This issue is specifically about per-concept create/update calls hitting output length limits and still writing partial pages.

Expected behavior

When an LLM response has finish_reason == "length", OpenKB should not write the parsed/repaired content to wiki/concepts/*.md as if it were complete.

Safer options:

  1. Treat finish_reason == "length" as a failed concept update and skip writing that page.
  2. Retry once with a higher configurable max_tokens for concept create/update calls.
  3. Return structured status from _llm_call(_async) such as {content, finish_reason} instead of only content, so callers can decide whether it is safe to write.
  4. Make per-step output token caps configurable, e.g. concept_update_max_tokens, while defaulting high enough for large existing concept pages.
  5. Optionally add a final validation step that rejects concept pages with clearly incomplete markdown/table/code block endings.

Why this matters

The warning currently looks non-fatal, but the side effect can be data corruption in the generated wiki. Because openkb add still reports [OK], users may not notice until later search/query results are based on incomplete concept pages.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions