fix: improve incremental wiki compilation (#18130)

### What problem does this PR solve?

Incremental Wiki compilation could lose provenance for claim-light
entities, produce unstable page groups across embedding models, route
entities to unrelated pages, and assign topics without sufficient
page-level context. Document removals and page membership changes could
also leave stale Wiki state.

This PR:

- preserves source document and chunk provenance throughout entity
matching, reduction, page generation, and deletion;
- uses embeddings to retrieve candidates and the LLM to make final page
grouping and incremental routing decisions;
- batches embedding and LLM operations with bounded concurrency and
deterministic fallbacks;
- selects source-scoped topic candidates with embeddings before the page
LLM chooses the final topic;
- rebuilds Wiki state when the compilation mode or embedding model
changes;
- normalizes Wiki array fields returned by the API and retains entities
without relations in graph responses.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
buua436
2026-08-11 20:13:04 +08:00
committed by GitHub
parent 4386ff71b0
commit 0cfd8f41e4
5 changed files with 1382 additions and 447 deletions

View File

@@ -79,6 +79,9 @@ def _load_list_datasets_module(monkeypatch, *, kbs, parsing_status_by_kb):
get_list_mock = MagicMock(return_value=(list(kbs), len(kbs)))
get_accessible_ids_mock = MagicMock(return_value={kb["id"] for kb in kbs})
_stub(monkeypatch, "api.apps", __path__=[])
_stub(monkeypatch, "api.apps.services", __path__=[])
_stub(monkeypatch, "api.apps.services.structure_graph_common")
_stub(
monkeypatch,
"api.db.joint_services.tenant_model_service",
@@ -366,3 +369,15 @@ def test_list_datasets_with_include_parsing_status_missing_kb_gets_empty_dict(mo
assert by_id["kb-a"]["parsing_status"]["unstart_count"] == 1
assert by_id["kb-b"]["parsing_status"] == {}
parsing_status_mock.assert_called_once()
def test_string_list_decodes_legacy_json_and_native_arrays(monkeypatch):
module, _, _ = _load_list_datasets_module(
monkeypatch,
kbs=[],
parsing_status_by_kb={},
)
assert module._string_list('["doc_1", "doc_2"]') == ["doc_1", "doc_2"]
assert module._string_list(["doc_1", "doc_2", "doc_1"]) == ["doc_1", "doc_2"]
assert module._string_list("doc_1###doc_2") == ["doc_1", "doc_2"]