dsh-data-domain-knowledge 0.1.0-alpha.9 → 0.1.1-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +118 -567
- package/cordis.patch.yml +5 -418
- package/eval/README.md +19 -8
- package/eval/benchmark-extraction-format.mjs +20 -0
- package/eval/evaluate-retrieval.mjs +17 -8
- package/eval/queries.example.jsonl +1 -0
- package/lib/client.js +4181 -3239
- package/lib/contract-envelope.d.ts +91 -0
- package/lib/contract-envelope.js +106 -0
- package/lib/contract-layout.d.ts +130 -0
- package/lib/contract-layout.js +138 -0
- package/lib/contract-refs.d.ts +39 -0
- package/lib/contract-refs.js +9 -0
- package/lib/contract-version.d.ts +311 -0
- package/lib/contract-version.js +270 -0
- package/lib/contract-wire.d.ts +147 -0
- package/lib/contract-wire.js +99 -0
- package/lib/contracts.d.ts +12 -0
- package/lib/contracts.js +12 -0
- package/lib/doc-page.js +2 -2
- package/lib/pages.js +3329 -1296
- package/lib/types/agent-behavior-rules.d.ts +10 -0
- package/lib/types/agent-behavior-rules.d.ts.map +1 -0
- package/lib/types/agent-behavior-rules.js +28 -0
- package/lib/types/agent-behavior-rules.js.map +1 -0
- package/lib/types/axis-registry.d.ts +37 -5
- package/lib/types/axis-registry.d.ts.map +1 -1
- package/lib/types/axis-registry.js +234 -26
- package/lib/types/axis-registry.js.map +1 -1
- package/lib/types/card-organize.d.ts +27 -12
- package/lib/types/card-organize.d.ts.map +1 -1
- package/lib/types/card-organize.js +58 -73
- package/lib/types/card-organize.js.map +1 -1
- package/lib/types/compiler/embedding-identity.d.ts +3 -0
- package/lib/types/compiler/embedding-identity.d.ts.map +1 -0
- package/lib/types/compiler/embedding-identity.js +24 -0
- package/lib/types/compiler/embedding-identity.js.map +1 -0
- package/lib/types/compiler/snapshot.d.ts +16 -0
- package/lib/types/compiler/snapshot.d.ts.map +1 -0
- package/lib/types/compiler/snapshot.js +2 -0
- package/lib/types/compiler/snapshot.js.map +1 -0
- package/lib/types/config-schema.d.ts +6 -3
- package/lib/types/config-schema.d.ts.map +1 -1
- package/lib/types/config-schema.js +6 -2
- package/lib/types/config-schema.js.map +1 -1
- package/lib/types/convert/host.d.ts +6 -5
- package/lib/types/convert/host.d.ts.map +1 -1
- package/lib/types/convert/host.js +58 -18
- package/lib/types/convert/host.js.map +1 -1
- package/lib/types/convert/ingest.d.ts +10 -1
- package/lib/types/convert/ingest.d.ts.map +1 -1
- package/lib/types/convert/ingest.js +68 -9
- package/lib/types/convert/ingest.js.map +1 -1
- package/lib/types/derive-contract.d.ts +3 -0
- package/lib/types/derive-contract.d.ts.map +1 -0
- package/lib/types/derive-contract.js +15 -0
- package/lib/types/derive-contract.js.map +1 -0
- package/lib/types/diagnosis/cards.d.ts +7 -3
- package/lib/types/diagnosis/cards.d.ts.map +1 -1
- package/lib/types/diagnosis/cards.js +13 -8
- package/lib/types/diagnosis/cards.js.map +1 -1
- package/lib/types/diagnosis/run.d.ts +4 -13
- package/lib/types/diagnosis/run.d.ts.map +1 -1
- package/lib/types/diagnosis/run.js +26 -16
- package/lib/types/diagnosis/run.js.map +1 -1
- package/lib/types/diagnosis/schema.js +2 -2
- package/lib/types/diagnosis/schema.js.map +1 -1
- package/lib/types/diagnosis/seed-source.d.ts +1 -1
- package/lib/types/diagnosis/seed-source.d.ts.map +1 -1
- package/lib/types/diagnosis/seed-source.js +5 -4
- package/lib/types/diagnosis/seed-source.js.map +1 -1
- package/lib/types/diagnosis/seed.d.ts +4 -4
- package/lib/types/diagnosis/seed.d.ts.map +1 -1
- package/lib/types/diagnosis/seed.js +6 -8
- package/lib/types/diagnosis/seed.js.map +1 -1
- package/lib/types/diagnosis/store.d.ts +24 -18
- package/lib/types/diagnosis/store.d.ts.map +1 -1
- package/lib/types/diagnosis/store.js +130 -65
- package/lib/types/diagnosis/store.js.map +1 -1
- package/lib/types/diagnosis/types.d.ts +47 -15
- package/lib/types/diagnosis/types.d.ts.map +1 -1
- package/lib/types/diagnosis/types.js.map +1 -1
- package/lib/types/environment/dsh-python.d.ts +77 -0
- package/lib/types/environment/dsh-python.d.ts.map +1 -0
- package/lib/types/environment/dsh-python.js +139 -0
- package/lib/types/environment/dsh-python.js.map +1 -0
- package/lib/types/environment/install.d.ts +15 -0
- package/lib/types/environment/install.d.ts.map +1 -0
- package/lib/types/environment/install.js +297 -0
- package/lib/types/environment/install.js.map +1 -0
- package/lib/types/environment/manifest.d.ts +208 -0
- package/lib/types/environment/manifest.d.ts.map +1 -0
- package/lib/types/environment/manifest.js +26 -0
- package/lib/types/environment/manifest.js.map +1 -0
- package/lib/types/environment/model-catalog.d.ts +223 -0
- package/lib/types/environment/model-catalog.d.ts.map +1 -0
- package/lib/types/environment/model-catalog.js +129 -0
- package/lib/types/environment/model-catalog.js.map +1 -0
- package/lib/types/environment/process.d.ts +10 -0
- package/lib/types/environment/process.d.ts.map +1 -0
- package/lib/types/environment/process.js +54 -0
- package/lib/types/environment/process.js.map +1 -0
- package/lib/types/environment/selection.d.ts +9 -0
- package/lib/types/environment/selection.d.ts.map +1 -0
- package/lib/types/environment/selection.js +29 -0
- package/lib/types/environment/selection.js.map +1 -0
- package/lib/types/environment/service.d.ts +64 -0
- package/lib/types/environment/service.d.ts.map +1 -0
- package/lib/types/environment/service.js +424 -0
- package/lib/types/environment/service.js.map +1 -0
- package/lib/types/environment/types.d.ts +56 -0
- package/lib/types/environment/types.d.ts.map +1 -0
- package/lib/types/environment/types.js +2 -0
- package/lib/types/environment/types.js.map +1 -0
- package/lib/types/events.d.ts +76 -0
- package/lib/types/events.d.ts.map +1 -0
- package/lib/types/events.js +52 -0
- package/lib/types/events.js.map +1 -0
- package/lib/types/extract-contract.d.ts +3 -0
- package/lib/types/extract-contract.d.ts.map +1 -0
- package/lib/types/extract-contract.js +41 -0
- package/lib/types/extract-contract.js.map +1 -0
- package/lib/types/extract-model.d.ts +5 -0
- package/lib/types/extract-model.d.ts.map +1 -1
- package/lib/types/extract-model.js.map +1 -1
- package/lib/types/extract-table-contract.d.ts +3 -0
- package/lib/types/extract-table-contract.d.ts.map +1 -0
- package/lib/types/extract-table-contract.js +27 -0
- package/lib/types/extract-table-contract.js.map +1 -0
- package/lib/types/extract-table.d.ts +8 -0
- package/lib/types/extract-table.d.ts.map +1 -0
- package/lib/types/extract-table.js +158 -0
- package/lib/types/extract-table.js.map +1 -0
- package/lib/types/extraction-runs.d.ts +30 -6
- package/lib/types/extraction-runs.d.ts.map +1 -1
- package/lib/types/extraction-runs.js +69 -8
- package/lib/types/extraction-runs.js.map +1 -1
- package/lib/types/fs-atomic.d.ts +0 -7
- package/lib/types/fs-atomic.d.ts.map +1 -1
- package/lib/types/fs-atomic.js +17 -2
- package/lib/types/fs-atomic.js.map +1 -1
- package/lib/types/images.d.ts +26 -0
- package/lib/types/images.d.ts.map +1 -0
- package/lib/types/images.js +196 -0
- package/lib/types/images.js.map +1 -0
- package/lib/types/index.d.ts +2 -2
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +598 -209
- package/lib/types/index.js.map +1 -1
- package/lib/types/intent/engine.d.ts +12 -4
- package/lib/types/intent/engine.d.ts.map +1 -1
- package/lib/types/intent/engine.js +43 -5
- package/lib/types/intent/engine.js.map +1 -1
- package/lib/types/intent/host.d.ts +5 -8
- package/lib/types/intent/host.d.ts.map +1 -1
- package/lib/types/intent/host.js +56 -11
- package/lib/types/intent/host.js.map +1 -1
- package/lib/types/intent/scope.d.ts +25 -0
- package/lib/types/intent/scope.d.ts.map +1 -0
- package/lib/types/intent/scope.js +116 -0
- package/lib/types/intent/scope.js.map +1 -0
- package/lib/types/intent/tools.d.ts +24 -20
- package/lib/types/intent/tools.d.ts.map +1 -1
- package/lib/types/intent/tools.js +65 -23
- package/lib/types/intent/tools.js.map +1 -1
- package/lib/types/intent/types.d.ts +11 -4
- package/lib/types/intent/types.d.ts.map +1 -1
- package/lib/types/knowledge-bases.d.ts +11 -5
- package/lib/types/knowledge-bases.d.ts.map +1 -1
- package/lib/types/knowledge-bases.js +52 -20
- package/lib/types/knowledge-bases.js.map +1 -1
- package/lib/types/knowledge-contract.d.ts +32 -0
- package/lib/types/knowledge-contract.d.ts.map +1 -0
- package/lib/types/knowledge-contract.js +116 -0
- package/lib/types/knowledge-contract.js.map +1 -0
- package/lib/types/knowledge.d.ts +31 -9
- package/lib/types/knowledge.d.ts.map +1 -1
- package/lib/types/knowledge.js +137 -60
- package/lib/types/knowledge.js.map +1 -1
- package/lib/types/layout.d.ts +10 -29
- package/lib/types/layout.d.ts.map +1 -1
- package/lib/types/layout.js +17 -36
- package/lib/types/layout.js.map +1 -1
- package/lib/types/materialize-snapshot.d.ts +49 -0
- package/lib/types/materialize-snapshot.d.ts.map +1 -0
- package/lib/types/materialize-snapshot.js +2 -0
- package/lib/types/materialize-snapshot.js.map +1 -0
- package/lib/types/migrate.d.ts +11 -0
- package/lib/types/migrate.d.ts.map +1 -1
- package/lib/types/migrate.js +83 -2
- package/lib/types/migrate.js.map +1 -1
- package/lib/types/model-text.d.ts +58 -1
- package/lib/types/model-text.d.ts.map +1 -1
- package/lib/types/model-text.js +85 -30
- package/lib/types/model-text.js.map +1 -1
- package/lib/types/oplog.d.ts.map +1 -1
- package/lib/types/oplog.js +7 -0
- package/lib/types/oplog.js.map +1 -1
- package/lib/types/organize-contract.d.ts +18 -0
- package/lib/types/organize-contract.d.ts.map +1 -0
- package/lib/types/organize-contract.js +82 -0
- package/lib/types/organize-contract.js.map +1 -0
- package/lib/types/pipeline/engine.d.ts +66 -0
- package/lib/types/pipeline/engine.d.ts.map +1 -0
- package/lib/types/pipeline/engine.js +352 -0
- package/lib/types/pipeline/engine.js.map +1 -0
- package/lib/types/pipeline/store.d.ts +73 -0
- package/lib/types/pipeline/store.d.ts.map +1 -0
- package/lib/types/pipeline/store.js +143 -0
- package/lib/types/pipeline/store.js.map +1 -0
- package/lib/types/pipeline/types.d.ts +102 -0
- package/lib/types/pipeline/types.d.ts.map +1 -0
- package/lib/types/pipeline/types.js +5 -0
- package/lib/types/pipeline/types.js.map +1 -0
- package/lib/types/present.d.ts +2 -0
- package/lib/types/present.d.ts.map +1 -1
- package/lib/types/present.js +9 -4
- package/lib/types/present.js.map +1 -1
- package/lib/types/preset-ids.d.ts +4 -0
- package/lib/types/preset-ids.d.ts.map +1 -0
- package/lib/types/preset-ids.js +6 -0
- package/lib/types/preset-ids.js.map +1 -0
- package/lib/types/query-analysis.d.ts +13 -1
- package/lib/types/query-analysis.d.ts.map +1 -1
- package/lib/types/query-analysis.js +62 -6
- package/lib/types/query-analysis.js.map +1 -1
- package/lib/types/recall-rank.d.ts +3 -3
- package/lib/types/recall-rank.d.ts.map +1 -1
- package/lib/types/recall-rank.js +4 -4
- package/lib/types/recall-rank.js.map +1 -1
- package/lib/types/retention.d.ts +39 -0
- package/lib/types/retention.d.ts.map +1 -0
- package/lib/types/retention.js +42 -0
- package/lib/types/retention.js.map +1 -0
- package/lib/types/retrieval/vector-index.d.ts +32 -0
- package/lib/types/retrieval/vector-index.d.ts.map +1 -0
- package/lib/types/retrieval/vector-index.js +15 -0
- package/lib/types/retrieval/vector-index.js.map +1 -0
- package/lib/types/retrieval/visibility.d.ts +6 -0
- package/lib/types/retrieval/visibility.d.ts.map +1 -0
- package/lib/types/retrieval/visibility.js +11 -0
- package/lib/types/retrieval/visibility.js.map +1 -0
- package/lib/types/runtime.d.ts +272 -27
- package/lib/types/runtime.d.ts.map +1 -1
- package/lib/types/runtime.js +2751 -537
- package/lib/types/runtime.js.map +1 -1
- package/lib/types/settings-schema.d.ts +17 -15
- package/lib/types/settings-schema.d.ts.map +1 -1
- package/lib/types/settings-schema.js +50 -47
- package/lib/types/settings-schema.js.map +1 -1
- package/lib/types/settings-volatile.d.ts +4 -4
- package/lib/types/settings-volatile.js +4 -4
- package/lib/types/source-evidence.d.ts +14 -0
- package/lib/types/source-evidence.d.ts.map +1 -0
- package/lib/types/source-evidence.js +36 -0
- package/lib/types/source-evidence.js.map +1 -0
- package/lib/types/store/axis-references.d.ts +5 -0
- package/lib/types/store/axis-references.d.ts.map +1 -0
- package/lib/types/store/axis-references.js +106 -0
- package/lib/types/store/axis-references.js.map +1 -0
- package/lib/types/store/derived.d.ts +12 -1
- package/lib/types/store/derived.d.ts.map +1 -1
- package/lib/types/store/derived.js +71 -12
- package/lib/types/store/derived.js.map +1 -1
- package/lib/types/store/knowledge-db.d.ts +31 -1
- package/lib/types/store/knowledge-db.d.ts.map +1 -1
- package/lib/types/store/knowledge-db.js +252 -18
- package/lib/types/store/knowledge-db.js.map +1 -1
- package/lib/types/store/migrate.d.ts.map +1 -1
- package/lib/types/store/migrate.js +17 -6
- package/lib/types/store/migrate.js.map +1 -1
- package/lib/types/trajectory-types.d.ts +172 -0
- package/lib/types/trajectory-types.d.ts.map +1 -0
- package/lib/types/trajectory-types.js +36 -0
- package/lib/types/trajectory-types.js.map +1 -0
- package/lib/types/types.d.ts +59 -27
- package/lib/types/types.d.ts.map +1 -1
- package/lib/types/types.js +6 -15
- package/lib/types/types.js.map +1 -1
- package/lib/types/wiki-finalize.d.ts +16 -0
- package/lib/types/wiki-finalize.d.ts.map +1 -1
- package/lib/types/wiki-finalize.js +26 -0
- package/lib/types/wiki-finalize.js.map +1 -1
- package/lib/types/wiki-materialize.d.ts +4 -0
- package/lib/types/wiki-materialize.d.ts.map +1 -1
- package/lib/types/wiki-materialize.js +21 -7
- package/lib/types/wiki-materialize.js.map +1 -1
- package/lib/types/wiki-trial-types.d.ts +87 -0
- package/lib/types/wiki-trial-types.d.ts.map +1 -1
- package/lib/types/wiki-trial-types.js +0 -16
- package/lib/types/wiki-trial-types.js.map +1 -1
- package/lib/types/wiki-trial.d.ts +40 -16
- package/lib/types/wiki-trial.d.ts.map +1 -1
- package/lib/types/wiki-trial.js +337 -224
- package/lib/types/wiki-trial.js.map +1 -1
- package/package.json +29 -20
- package/python/prepare-models.py +19 -0
- package/python/requirements.txt +8 -6
- package/scripts/doctor.mjs +13 -19
- package/scripts/environment.mjs +29 -0
- package/scripts/setup-embedding.sh +15 -5
- package/src/agent-behavior-rules.ts +37 -0
- package/src/axis-registry.ts +234 -27
- package/src/card-organize.ts +69 -75
- package/src/client/AgentBehaviorRulesCard.tsx +65 -0
- package/src/client/AttributionEventGuide.tsx +41 -39
- package/src/client/AxisRegistrySection.tsx +204 -164
- package/src/client/CompileDialogs.tsx +44 -29
- package/src/client/DeleteDocumentDialog.tsx +36 -5
- package/src/client/DirectoryPicker.tsx +0 -10
- package/src/client/EnvironmentSetup.tsx +243 -0
- package/src/client/ExpansionGraph.tsx +13 -7
- package/src/client/ExtractionTasksPage.tsx +578 -0
- package/src/client/GuideArchitectureCanvas.tsx +470 -0
- package/src/client/ImportFilesDialog.tsx +2 -13
- package/src/client/IntentLogic.tsx +2 -2
- package/src/client/IntentTab.tsx +118 -47
- package/src/client/KnowledgeBaseTab.tsx +277 -197
- package/src/client/KnowledgeLayerSection.tsx +24 -6
- package/src/client/KnowledgePanel.tsx +58 -93
- package/src/client/KnowledgeSettingsDrawer.tsx +90 -0
- package/src/client/ListPager.tsx +15 -5
- package/src/client/MaterializeTrajectoryView.tsx +124 -0
- package/src/client/NodeSettings.tsx +210 -89
- package/src/client/NormalizeTrajectoryView.tsx +136 -0
- package/src/client/PipelineNotice.tsx +26 -0
- package/src/client/PreviewSections.tsx +118 -51
- package/src/client/RecallPanel.tsx +89 -85
- package/src/client/TabGuide.tsx +159 -184
- package/src/client/TrialReportView.tsx +391 -214
- package/src/client/TypeDefinitionDrawer.tsx +150 -23
- package/src/client/WikiCardPreview.tsx +62 -16
- package/src/client/WikiFlowPanel.tsx +4 -4
- package/src/client/arch/NodeLogicPanel.tsx +3 -4
- package/src/client/arch/model.ts +6 -9
- package/src/client/architecture.tsx +23 -33
- package/src/client/attribution/AttributionGraph.tsx +10 -6
- package/src/client/attribution/AttributionTab.tsx +136 -84
- package/src/client/attribution/CaseView.tsx +3 -1
- package/src/client/attribution/EventView.tsx +108 -0
- package/src/client/attribution/RunView.tsx +2 -2
- package/src/client/attribution/StageChrome.tsx +34 -3
- package/src/client/attribution/ViewSwitch.tsx +20 -5
- package/src/client/attribution/graph-options.ts +47 -39
- package/src/client/attribution/model.ts +17 -10
- package/src/client/config-scope.ts +3 -3
- package/src/client/graph/palette.ts +165 -0
- package/src/client/index.ts +49 -42
- package/src/client/pages.css +459 -135
- package/src/client/pages.tsx +37 -9
- package/src/client/problem-domains.ts +1 -1
- package/src/client/session-remote.ts +9 -0
- package/src/client/styles.css +205 -62
- package/src/client/wiki-trial.ts +44 -3
- package/src/compiler/embedding-identity.ts +21 -0
- package/src/compiler/snapshot.ts +17 -0
- package/src/config-schema.ts +8 -3
- package/src/convert/host.ts +56 -21
- package/src/convert/ingest.ts +74 -10
- package/src/derive-contract.ts +14 -0
- package/src/diagnosis/cards.ts +13 -8
- package/src/diagnosis/run.ts +27 -17
- package/src/diagnosis/schema.ts +2 -2
- package/src/diagnosis/seed-source.ts +5 -4
- package/src/diagnosis/seed.ts +6 -8
- package/src/diagnosis/store.ts +138 -69
- package/src/diagnosis/types.ts +34 -15
- package/src/environment/dsh-python.ts +156 -0
- package/src/environment/install.ts +244 -0
- package/src/environment/manifest.ts +28 -0
- package/src/environment/model-catalog.ts +147 -0
- package/src/environment/process.ts +54 -0
- package/src/environment/selection.ts +29 -0
- package/src/environment/service.ts +348 -0
- package/src/environment/types.ts +45 -0
- package/src/events.ts +108 -0
- package/src/extract-contract.ts +42 -0
- package/src/extract-model.ts +10 -1
- package/src/extract-table-contract.ts +26 -0
- package/src/extract-table.ts +132 -0
- package/src/extraction-runs.ts +70 -11
- package/src/fs-atomic.ts +19 -2
- package/src/images.ts +203 -0
- package/src/index.ts +553 -205
- package/src/intent/README.md +8 -6
- package/src/intent/engine.ts +44 -6
- package/src/intent/host.ts +59 -18
- package/src/intent/scope.ts +125 -0
- package/src/intent/tools.ts +70 -28
- package/src/intent/types.ts +11 -4
- package/src/knowledge-bases.ts +56 -20
- package/src/knowledge-contract.ts +114 -0
- package/src/knowledge.ts +138 -69
- package/src/layout.ts +17 -37
- package/src/materialize-snapshot.ts +46 -0
- package/src/migrate.ts +75 -2
- package/src/model-text.ts +109 -4
- package/src/oplog.ts +7 -0
- package/src/organize-contract.ts +83 -0
- package/src/pipeline/engine.ts +323 -0
- package/src/pipeline/store.ts +147 -0
- package/src/pipeline/types.ts +93 -0
- package/src/present.ts +10 -4
- package/src/preset-ids.ts +6 -0
- package/src/python/embedding_worker.py +66 -2
- package/src/query-analysis.ts +68 -8
- package/src/recall-rank.ts +5 -5
- package/src/retention.ts +76 -0
- package/src/retrieval/vector-index.ts +45 -0
- package/src/retrieval/visibility.ts +14 -0
- package/src/runtime.ts +2708 -567
- package/src/settings-schema.ts +11 -8
- package/src/settings-volatile.ts +4 -4
- package/src/source-evidence.ts +37 -0
- package/src/store/axis-references.ts +96 -0
- package/src/store/derived.ts +70 -12
- package/src/store/knowledge-db.ts +248 -17
- package/src/store/migrate.ts +16 -6
- package/src/trajectory-types.ts +142 -0
- package/src/types.ts +61 -35
- package/src/wiki-finalize.ts +28 -0
- package/src/wiki-materialize.ts +25 -6
- package/src/wiki-trial-types.ts +83 -1
- package/src/wiki-trial.ts +357 -185
- package/lib/types/intent/preset-tools.d.ts +0 -37
- package/lib/types/intent/preset-tools.d.ts.map +0 -1
- package/lib/types/intent/preset-tools.js +0 -45
- package/lib/types/intent/preset-tools.js.map +0 -1
- package/preset/tita-data-agent/agent.cordis.yml +0 -394
- package/preset/tita-data-agent/preset.yml +0 -3
- package/scripts/install-agent-preset.mjs +0 -92
- package/scripts/sync-agent-preset.mjs +0 -188
- package/src/client/AgentPresetCard.tsx +0 -247
- package/src/client/agent-preset.ts +0 -121
- package/src/client/convert/ConvertPanel.tsx +0 -583
- package/src/client/convert/styles.css +0 -138
- package/src/client/convert/styles.ts +0 -49
- package/src/intent/preset-tools.ts +0 -48
|
@@ -42,8 +42,8 @@ import { styles } from './styles.ts'
|
|
|
42
42
|
* Markdown 原子的界面文案。必须是**模块级常量**:平台明确要求这个对象引用稳定
|
|
43
43
|
* (换一个身份会让流式渲染的缓存整体作废),在渲染里现造一个对象正好踩中那条。
|
|
44
44
|
*
|
|
45
|
-
*
|
|
46
|
-
* 是刻意的:`MarkdownLabels`
|
|
45
|
+
* 这三个词是预览区的显示文案。没有抽回 `packages/ui`
|
|
46
|
+
* 是刻意的:`MarkdownLabels` 的类型来自**宿主提供的**平台包,而各预览消费者的
|
|
47
47
|
* 独立整页入口必须能把平台包整块排除在 bundle 之外 —— 共享层一旦引它,那条「独立
|
|
48
48
|
* 页面不拉平台依赖」的约束就断了。三行文案不值得拿那条约束换。
|
|
49
49
|
*/
|
|
@@ -524,78 +524,128 @@ export interface VersionContentDiffData {
|
|
|
524
524
|
}
|
|
525
525
|
|
|
526
526
|
type ContentDiffLine = { kind: 'add' | 'remove' | 'same'; text: string }
|
|
527
|
-
type ContentDiffDisplayLine =
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
const
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
527
|
+
type ContentDiffDisplayLine =
|
|
528
|
+
| { kind: 'pair'; before?: string; after?: string }
|
|
529
|
+
| { kind: 'skip'; count: number }
|
|
530
|
+
|
|
531
|
+
/** Line diff for Markdown/plain-text version bodies. Full mode keeps every line. */
|
|
532
|
+
function contentDiffOf(before: string, after: string, fullText = false): ContentDiffLine[] {
|
|
533
|
+
const oldLines = before.replace(/\r\n/g, '\n').split('\n')
|
|
534
|
+
const newLines = after.replace(/\r\n/g, '\n').split('\n')
|
|
535
|
+
if (!fullText) {
|
|
536
|
+
oldLines.length = Math.min(oldLines.length, 600)
|
|
537
|
+
newLines.length = Math.min(newLines.length, 600)
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// Trim shared edges before LCS. Wiki cards often have a small edit in a long body.
|
|
541
|
+
let prefix = 0
|
|
542
|
+
let oldEnd = oldLines.length
|
|
543
|
+
let newEnd = newLines.length
|
|
544
|
+
if (fullText) {
|
|
545
|
+
while (prefix < oldEnd && prefix < newEnd && oldLines[prefix] === newLines[prefix]) prefix += 1
|
|
546
|
+
while (oldEnd > prefix && newEnd > prefix && oldLines[oldEnd - 1] === newLines[newEnd - 1]) {
|
|
547
|
+
oldEnd -= 1
|
|
548
|
+
newEnd -= 1
|
|
539
549
|
}
|
|
550
|
+
} else {
|
|
551
|
+
prefix = 0
|
|
552
|
+
oldEnd = oldLines.length
|
|
553
|
+
newEnd = newLines.length
|
|
540
554
|
}
|
|
555
|
+
|
|
556
|
+
const oldMiddle = oldLines.slice(prefix, oldEnd)
|
|
557
|
+
const newMiddle = newLines.slice(prefix, newEnd)
|
|
541
558
|
const lines: ContentDiffLine[] = []
|
|
542
|
-
let
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
559
|
+
for (let index = 0; index < prefix; index += 1) lines.push({ kind: 'same', text: oldLines[index]! })
|
|
560
|
+
|
|
561
|
+
// Bound the quadratic LCS allocation for unusually large, completely rewritten hunks.
|
|
562
|
+
// The full text remains visible; only that hunk is marked as remove/add when it exceeds the budget.
|
|
563
|
+
if (fullText && (oldMiddle.length + newMiddle.length > 20_000 || oldMiddle.length * newMiddle.length > 1_000_000)) {
|
|
564
|
+
for (const text of oldMiddle) lines.push({ kind: 'remove', text })
|
|
565
|
+
for (const text of newMiddle) lines.push({ kind: 'add', text })
|
|
566
|
+
} else {
|
|
567
|
+
const matrix = Array.from({ length: oldMiddle.length + 1 }, () => new Uint16Array(newMiddle.length + 1))
|
|
568
|
+
for (let oldIndex = oldMiddle.length - 1; oldIndex >= 0; oldIndex -= 1) {
|
|
569
|
+
for (let newIndex = newMiddle.length - 1; newIndex >= 0; newIndex -= 1) {
|
|
570
|
+
matrix[oldIndex]![newIndex] = oldMiddle[oldIndex] === newMiddle[newIndex]
|
|
571
|
+
? (matrix[oldIndex + 1]![newIndex + 1] ?? 0) + 1
|
|
572
|
+
: Math.max(matrix[oldIndex + 1]![newIndex] ?? 0, matrix[oldIndex]![newIndex + 1] ?? 0)
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
let oldIndex = 0
|
|
576
|
+
let newIndex = 0
|
|
577
|
+
while (oldIndex < oldMiddle.length || newIndex < newMiddle.length) {
|
|
578
|
+
if (oldIndex < oldMiddle.length && newIndex < newMiddle.length && oldMiddle[oldIndex] === newMiddle[newIndex]) {
|
|
579
|
+
lines.push({ kind: 'same', text: oldMiddle[oldIndex]! })
|
|
580
|
+
oldIndex += 1
|
|
581
|
+
newIndex += 1
|
|
582
|
+
} else if (oldIndex < oldMiddle.length && (newIndex >= newMiddle.length || (matrix[oldIndex + 1]![newIndex] ?? 0) >= (matrix[oldIndex]![newIndex + 1] ?? 0))) {
|
|
583
|
+
lines.push({ kind: 'remove', text: oldMiddle[oldIndex]! })
|
|
584
|
+
oldIndex += 1
|
|
585
|
+
} else {
|
|
586
|
+
lines.push({ kind: 'add', text: newMiddle[newIndex]! })
|
|
587
|
+
newIndex += 1
|
|
588
|
+
}
|
|
555
589
|
}
|
|
556
590
|
}
|
|
591
|
+
|
|
592
|
+
for (let index = 0; index < oldLines.length - oldEnd; index += 1) {
|
|
593
|
+
lines.push({ kind: 'same', text: oldLines[oldEnd + index]! })
|
|
594
|
+
}
|
|
557
595
|
return lines
|
|
558
596
|
}
|
|
559
597
|
|
|
560
|
-
function compactContentDiff(lines: ContentDiffLine[]): ContentDiffDisplayLine[] {
|
|
598
|
+
function compactContentDiff(lines: ContentDiffLine[], fullText = false): ContentDiffDisplayLine[] {
|
|
561
599
|
const out: ContentDiffDisplayLine[] = []
|
|
562
600
|
let index = 0
|
|
563
601
|
while (index < lines.length) {
|
|
564
|
-
if (lines[index]?.kind
|
|
565
|
-
|
|
566
|
-
index += 1
|
|
602
|
+
if (lines[index]?.kind === 'same') {
|
|
603
|
+
const start = index
|
|
604
|
+
while (index < lines.length && lines[index]?.kind === 'same') index += 1
|
|
605
|
+
const count = index - start
|
|
606
|
+
const visible = fullText || count <= 6
|
|
607
|
+
? lines.slice(start, index)
|
|
608
|
+
: [...lines.slice(start, start + 2), { kind: 'skip' as const, count: count - 4 }, ...lines.slice(index - 2, index)]
|
|
609
|
+
for (const line of visible) {
|
|
610
|
+
if (line.kind === 'skip') out.push(line)
|
|
611
|
+
else out.push({ kind: 'pair', before: line.text, after: line.text })
|
|
612
|
+
}
|
|
567
613
|
continue
|
|
568
614
|
}
|
|
569
|
-
const
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
615
|
+
const removed: string[] = []
|
|
616
|
+
const added: string[] = []
|
|
617
|
+
while (index < lines.length && lines[index]?.kind !== 'same') {
|
|
618
|
+
const line = lines[index]!
|
|
619
|
+
if (line.kind === 'remove') removed.push(line.text)
|
|
620
|
+
if (line.kind === 'add') added.push(line.text)
|
|
621
|
+
index += 1
|
|
622
|
+
}
|
|
623
|
+
const count = Math.max(removed.length, added.length)
|
|
624
|
+
for (let pair = 0; pair < count; pair += 1) {
|
|
625
|
+
out.push({ before: removed[pair], after: added[pair], kind: 'pair' })
|
|
577
626
|
}
|
|
578
627
|
}
|
|
579
628
|
return out
|
|
580
629
|
}
|
|
581
630
|
|
|
582
631
|
/** Read-only Markdown/plain-text comparison for SourceRaw and WikiCard. */
|
|
583
|
-
export function VersionContentDiff({ data, loading = false, error }: {
|
|
632
|
+
export function VersionContentDiff({ data, loading = false, error, fullText = false }: {
|
|
584
633
|
data?: VersionContentDiffData
|
|
585
634
|
loading?: boolean
|
|
586
635
|
error?: string
|
|
636
|
+
fullText?: boolean
|
|
587
637
|
}): ReactNode {
|
|
588
638
|
if (loading) return <div className="tita-versionDiff"><div className="tita-versionStepHint">正在读取历史正文…</div></div>
|
|
589
639
|
if (error !== undefined) return <div className="tita-versionDiff"><div className="tita-kbHint">读取版本差异失败:{error}</div></div>
|
|
590
640
|
if (data === undefined) return null
|
|
591
|
-
const lines = contentDiffOf(data.before, data.after)
|
|
592
|
-
const displayed = compactContentDiff(lines)
|
|
641
|
+
const lines = contentDiffOf(data.before, data.after, fullText)
|
|
642
|
+
const displayed = compactContentDiff(lines, fullText)
|
|
593
643
|
const added = lines.filter(line => line.kind === 'add').length
|
|
594
644
|
const removed = lines.filter(line => line.kind === 'remove').length
|
|
595
645
|
const changed = Math.min(added, removed)
|
|
596
646
|
const truncated = data.beforeTruncated === true || data.afterTruncated === true
|
|
597
647
|
return (
|
|
598
|
-
<div className=
|
|
648
|
+
<div className={fullText ? 'tita-versionDiff tita-versionDiff-fullText' : 'tita-versionDiff'} aria-label="版本差异">
|
|
599
649
|
<div className="tita-versionDiffBar">
|
|
600
650
|
<p className="tita-versionDiffHead">
|
|
601
651
|
{added === 0 && removed === 0 ? '正文没有差异' : '正文差异'}
|
|
@@ -605,14 +655,31 @@ export function VersionContentDiff({ data, loading = false, error }: {
|
|
|
605
655
|
</p>
|
|
606
656
|
</div>
|
|
607
657
|
{truncated && <p className="tita-kbHint">只比较当前读取范围;正文过长,末尾内容未参与比较。</p>}
|
|
608
|
-
{lines.length > 0 && (added > 0 || removed > 0) && (
|
|
609
|
-
<div className="tita-
|
|
610
|
-
<div className="tita-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
658
|
+
{lines.length > 0 && (fullText || added > 0 || removed > 0) && (
|
|
659
|
+
<div className="tita-versionDiffTextSplit">
|
|
660
|
+
<div className="tita-versionDiffTextSplitHead">
|
|
661
|
+
<span>历史版本 · {data.beforeLabel}</span>
|
|
662
|
+
<span>当前版本 · {data.afterLabel}</span>
|
|
663
|
+
</div>
|
|
664
|
+
{displayed.map((line, index) => line.kind === 'skip'
|
|
665
|
+
? <div className="tita-versionDiffTextSkip" key={`skip-${index}`}>⋯ {line.count} 行未变化</div>
|
|
666
|
+
: (() => {
|
|
667
|
+
const same = line.before !== undefined && line.after !== undefined && line.before === line.after
|
|
668
|
+
const beforeClass = line.before === undefined
|
|
669
|
+
? 'tita-versionDiffTextCell tita-versionDiffTextCell-empty'
|
|
670
|
+
: same
|
|
671
|
+
? 'tita-versionDiffTextCell tita-versionDiffTextCell-same'
|
|
672
|
+
: 'tita-versionDiffTextCell tita-versionDiffTextCell-before'
|
|
673
|
+
const afterClass = line.after === undefined
|
|
674
|
+
? 'tita-versionDiffTextCell tita-versionDiffTextCell-empty'
|
|
675
|
+
: same
|
|
676
|
+
? 'tita-versionDiffTextCell tita-versionDiffTextCell-same'
|
|
677
|
+
: 'tita-versionDiffTextCell tita-versionDiffTextCell-after'
|
|
678
|
+
return <div className="tita-versionDiffTextSplitRow" key={`pair-${index}`}>
|
|
679
|
+
<span className={beforeClass}>{line.before === undefined ? '' : `${same ? ' ' : '-'} ${line.before}`}</span>
|
|
680
|
+
<span className={afterClass}>{line.after === undefined ? '' : `${same ? ' ' : '+'} ${line.after}`}</span>
|
|
681
|
+
</div>
|
|
682
|
+
})())}
|
|
616
683
|
</div>
|
|
617
684
|
)}
|
|
618
685
|
</div>
|
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
* `chunk_index` / `score` 一起给出 —— 只报「命中 N 条」看不出召回质量。
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import { Fragment, useEffect, useState, type ReactNode } from 'react'
|
|
12
|
+
import { Fragment, useEffect, useRef, useState, type ReactNode } from 'react'
|
|
13
13
|
import { ArrowRight, ArrowUpDown, BrainCircuit, CircleHelp, GitBranch, Layers3, Play, Search, Shapes } from '@tita-agent/ui/icons'
|
|
14
|
-
import { Button, Card, Input,
|
|
14
|
+
import { Button, Card, Input, cn } from '@tita-agent/ui/components'
|
|
15
15
|
import { ExpansionGraph } from './ExpansionGraph.tsx'
|
|
16
|
+
import { requestJson } from './request.ts'
|
|
16
17
|
import { styles } from './styles.ts'
|
|
17
18
|
|
|
18
19
|
/** 一条命中的 wikiNote。`match` 是**真正贡献了这次命中**的路线。 */
|
|
@@ -96,7 +97,7 @@ export interface QueryAnalysisView {
|
|
|
96
97
|
unresolved: QueryAxisKind[]
|
|
97
98
|
}
|
|
98
99
|
|
|
99
|
-
/**
|
|
100
|
+
/** 召回链路的三个步骤:四路候选 → Section 重排 → 完整 WikiCard 交付。 */
|
|
100
101
|
export type RecallStep = 'recall' | 'rerank' | 'deliver'
|
|
101
102
|
|
|
102
103
|
export interface RecallResultView {
|
|
@@ -108,7 +109,7 @@ export interface RecallResultView {
|
|
|
108
109
|
/** 融合与重排作用的候选池深度(0031)。它与 `recallTopK` 是两个数。 */
|
|
109
110
|
candidatePool?: number
|
|
110
111
|
/**
|
|
111
|
-
*
|
|
112
|
+
* 四路候选**去重后**的候选条数。
|
|
112
113
|
*
|
|
113
114
|
* 面板上这三个数必须各归各位:`candidatePool` 是每一路的超采深度(50),
|
|
114
115
|
* `fusedCount` 是融合后的池子(实测「投资」那次是 17),`hits.length` 是重排之后
|
|
@@ -140,6 +141,7 @@ export interface RecallResultView {
|
|
|
140
141
|
/** 面板账本(0050):每一路的全部候选 + 重排的全部候选(含被丢弃的)。 */
|
|
141
142
|
ledger?: {
|
|
142
143
|
coordinate: LedgerRowView[]
|
|
144
|
+
relation?: LedgerRowView[]
|
|
143
145
|
fts: LedgerRowView[]
|
|
144
146
|
vector: LedgerRowView[]
|
|
145
147
|
rerank: Array<LedgerRowView & { fused: number; logit?: number; rerankScore?: number; dropped: boolean }>
|
|
@@ -155,7 +157,7 @@ export interface RecallResultView {
|
|
|
155
157
|
* 只给「这次测试很慢」的感受,人没法判断该不该管它。
|
|
156
158
|
*/
|
|
157
159
|
timings?: {
|
|
158
|
-
ftsMs: number; coordinateMs: number; vectorMs: number; embedMs?: number; scanMs?: number
|
|
160
|
+
ftsMs: number; coordinateMs: number; relationMs?: number; vectorMs: number; embedMs?: number; scanMs?: number
|
|
159
161
|
graphMs: number; fuseMs: number; rerankMs?: number; assembleMs: number; totalMs: number
|
|
160
162
|
}
|
|
161
163
|
/** 命中几张卡 + 1 跳扩展几张(0050)。 */
|
|
@@ -167,22 +169,6 @@ export interface RecallResultView {
|
|
|
167
169
|
indexVersion?: number
|
|
168
170
|
}
|
|
169
171
|
|
|
170
|
-
interface Envelope<T> { ok?: boolean; data?: T; error?: { code?: string; message?: string; suggestion?: string } | null }
|
|
171
|
-
|
|
172
|
-
async function requestJson<T>(url: string): Promise<Envelope<T>> {
|
|
173
|
-
const response = await fetch(url)
|
|
174
|
-
const text = await response.text()
|
|
175
|
-
if (!text.trim()) throw new Error(`服务端返回空响应(HTTP ${response.status})`)
|
|
176
|
-
let payload: Envelope<T>
|
|
177
|
-
try { payload = JSON.parse(text) as Envelope<T> } catch { throw new Error(`服务端返回了无效响应(HTTP ${response.status})`) }
|
|
178
|
-
const error = payload.error
|
|
179
|
-
if (!response.ok || payload.ok === false) {
|
|
180
|
-
const detail = [error?.code, error?.message].filter(Boolean).join(' · ') || `请求失败(${response.status})`
|
|
181
|
-
throw new Error(error?.suggestion ? `${detail} — ${error.suggestion}` : detail)
|
|
182
|
-
}
|
|
183
|
-
return payload
|
|
184
|
-
}
|
|
185
|
-
|
|
186
172
|
/**
|
|
187
173
|
* 账本列表(0050):**每一路的全部候选**,没过阈值的也在(虚线 + 淡色 + 一句原因)。
|
|
188
174
|
*
|
|
@@ -316,43 +302,22 @@ export function DeliveryView({ wiki, onOpenWiki }: { wiki: WikiCardView[]; onOpe
|
|
|
316
302
|
}
|
|
317
303
|
|
|
318
304
|
/**
|
|
319
|
-
*
|
|
305
|
+
* 召回是四路(Coordinate + 对象关系 + 关键词 BM25 + 向量)加一个后置图谱 boost。
|
|
320
306
|
*
|
|
321
307
|
* 图谱不再是独立一路:它不能制造候选,只给已经在候选池里的条目加权。所以这一行显示的是
|
|
322
308
|
* 「加权了几条」,而不是「跑没跑」—— 后者对它已经没有意义。
|
|
323
309
|
*/
|
|
324
310
|
export const RECALL_ROUTES: Array<{ id: string; label: string; hint: string }> = [
|
|
325
311
|
{ id: 'coordinate', label: 'Coordinate', hint: 'Object × Action × Scene 坐标命中后展开为 Section' },
|
|
312
|
+
{ id: 'relation', label: '关系', hint: '从命中的对象沿一跳 related_to 关系召回相关对象卡片' },
|
|
326
313
|
{ id: 'fts', label: '关键词', hint: 'FTS5 + BM25(中文按双字词切分)' },
|
|
327
314
|
{ id: 'vector', label: '向量', hint: 'WeMM 向量近邻(binary 预筛 + int8 精算余弦)' },
|
|
328
315
|
]
|
|
329
316
|
|
|
330
|
-
/**
|
|
331
|
-
* 路线选项保留 FTS / Vector 两个调试开关;默认 Hybrid 会额外启用 Coordinate 路。
|
|
332
|
-
*
|
|
333
|
-
* 图谱 boost 不是一条路(它不能制造候选,只给已在池里的条目加权),所以它不该出现在
|
|
334
|
-
* 「选哪一路」的下拉里 —— 上一版那两条「融合 + 图谱 boost」「同融合」正是这个错:
|
|
335
|
-
* 把加权当成了路线。融合是候选路的**组合方式**,写在选项文字里,不是一个独立选项。
|
|
336
|
-
*/
|
|
337
|
-
export const RECALL_MODES: Array<{ id: string; label: string }> = [
|
|
338
|
-
{ id: 'hybrid', label: 'Coordinate + 关键词 + 向量(融合,默认)' },
|
|
339
|
-
{ id: 'fts', label: '仅关键词' },
|
|
340
|
-
{ id: 'vector', label: '仅向量' },
|
|
341
|
-
]
|
|
342
|
-
|
|
343
|
-
/**
|
|
344
|
-
* 参数摘要里用的短名字。
|
|
345
|
-
*
|
|
346
|
-
* `RECALL_MODES` 的 label 是给下拉用的**整句**(「Coordinate + 关键词 + 向量(融合,默认)」),
|
|
347
|
-
* 直接塞进那行摘要会把行撑爆 —— 摘要是拿来扫的,不是拿来读的。两处各留一份是对的:
|
|
348
|
-
* 下拉里要能说清「哪个是默认」,摘要里要短。
|
|
349
|
-
*/
|
|
350
|
-
const MODE_SHORT: Record<string, string> = { hybrid: 'Coordinate + 关键词 + 向量', fts: '仅关键词', vector: '仅向量' }
|
|
351
|
-
|
|
352
317
|
const HIT_ROUTES: Record<string, string> = {
|
|
353
|
-
coordinate: styles.hitRouteHybrid, fts: styles.hitRouteFts, vector: styles.hitRouteVector, graph: styles.hitRouteGraph, hybrid: styles.hitRouteHybrid,
|
|
318
|
+
coordinate: styles.hitRouteHybrid, relation: styles.hitRouteGraph, fts: styles.hitRouteFts, vector: styles.hitRouteVector, graph: styles.hitRouteGraph, hybrid: styles.hitRouteHybrid,
|
|
354
319
|
}
|
|
355
|
-
const HIT_ROUTE_LABEL: Record<string, string> = { coordinate: 'Coordinate', fts: '关键词', vector: '向量', hybrid: '多路', graph: '图谱加权' }
|
|
320
|
+
const HIT_ROUTE_LABEL: Record<string, string> = { coordinate: 'Coordinate', relation: '关系扩展', fts: '关键词', vector: '向量', hybrid: '多路', graph: '图谱加权' }
|
|
356
321
|
|
|
357
322
|
/** 去掉 markdown 脚手架,让命中读起来是一段正文而不是源码。 */
|
|
358
323
|
export function snippetOf(content: string, limit = 200): string {
|
|
@@ -436,17 +401,16 @@ export interface RecallPanelProps {
|
|
|
436
401
|
/** `recall` 看命中切片,`rerank` 看进入上下文的 topN,`runner` 是评测里的紧凑版。 */
|
|
437
402
|
/**
|
|
438
403
|
* `recall` = 知识库 → **召回重排**那一栏(0033 起召回与重排合成一栏,一次运行
|
|
439
|
-
*
|
|
404
|
+
* 从上到下给出四路命中 → 融合排序 → 精排丢了多少 → 进上下文的 topN)。
|
|
440
405
|
* `runner` = 评测里的紧凑版单问题检查。
|
|
441
406
|
*/
|
|
442
407
|
variant?: 'recall' | 'runner'
|
|
443
|
-
defaults?: {
|
|
408
|
+
defaults?: { topK?: number; topN?: number }
|
|
444
409
|
/** 设置写完或知识库切换时,用它把面板重置回初始值。 */
|
|
445
410
|
resetKey?: string
|
|
446
411
|
/**
|
|
447
|
-
*
|
|
448
|
-
*
|
|
449
|
-
* 参数住在设置抽屉里,这里只是那扇离现场更近的门。
|
|
412
|
+
* 卡头上的设置入口。面板**不认识设置**,只留一个位置让调用方挂最近的入口;
|
|
413
|
+
* 召回、重排与上下文共用同一组设置,评测栏不挂入口。
|
|
450
414
|
*/
|
|
451
415
|
settingsChip?: ReactNode
|
|
452
416
|
/** 点某张卡片时打开它的预览抽屉。不给就是纯文本(面板不自己造一个抽屉出来)。 */
|
|
@@ -462,18 +426,32 @@ export function RecallPanel({ kbId, kbName, visible, variant = 'recall', default
|
|
|
462
426
|
* 提示语改成直说这一栏要什么:**要测试的内容**。
|
|
463
427
|
*/
|
|
464
428
|
const [query, setQuery] = useState('')
|
|
465
|
-
const [mode, setMode] = useState(defaults?.mode ?? 'hybrid')
|
|
466
429
|
const [topK, setTopK] = useState(defaults?.topK ?? 10)
|
|
467
430
|
const [topN, setTopN] = useState(defaults?.topN ?? 5)
|
|
431
|
+
/**
|
|
432
|
+
* 两个参数框里**正在被敲的那串字**。
|
|
433
|
+
*
|
|
434
|
+
* 输入框原来直接吃数字、每次按键都夹一次(`Math.max(1, …)`),于是「全选删掉重打」
|
|
435
|
+
* 这一步永远做不到:清空的一瞬间就被改写回 1,人只能先选中再输入。**空串是一种
|
|
436
|
+
* 合法的中间态**,所以草稿留成字符串,只在失焦时夹一次。
|
|
437
|
+
*/
|
|
438
|
+
const [topKDraft, setTopKDraft] = useState(String(defaults?.topK ?? 10))
|
|
439
|
+
const [topNDraft, setTopNDraft] = useState(String(defaults?.topN ?? 5))
|
|
468
440
|
const [busy, setBusy] = useState(false)
|
|
469
441
|
const [error, setError] = useState<string | null>(null)
|
|
470
442
|
const [result, setResult] = useState<RecallResultView | null>(null)
|
|
443
|
+
/**
|
|
444
|
+
* 本次运行的票号。连按两次「测试」或连敲两次回车会发两个请求,先发的可能后回 ——
|
|
445
|
+
* 那一次的结果会把新一次盖掉,而屏幕上的参数是新一次的。每个 `setState` 前比票号,
|
|
446
|
+
* 过期的整段丢掉(与卡片列表 `eventsRequestRef` 同一条纪律)。
|
|
447
|
+
*/
|
|
448
|
+
const runRef = useRef(0)
|
|
471
449
|
/** 三个 tab:召回 / 重排 / 交付 —— 一条链路的三段,各自回答一个问题。 */
|
|
472
450
|
const [tab, setTab] = useState<RecallStep>('recall')
|
|
473
451
|
/** 召回 tab 里正在看哪一路(`all` = 看融合后的命中)。 */
|
|
474
|
-
const [routeView, setRouteView] = useState<'all' | 'coordinate' | 'fts' | 'vector'>('all')
|
|
452
|
+
const [routeView, setRouteView] = useState<'all' | 'coordinate' | 'relation' | 'fts' | 'vector'>('all')
|
|
475
453
|
/**
|
|
476
|
-
*
|
|
454
|
+
* 两个片段数量参数默认**收起来**。
|
|
477
455
|
*
|
|
478
456
|
* 它们此前常驻一整条横带,而那条横带压在步骤轨与命中列表上面 —— 列表之前一共五条
|
|
479
457
|
* 横带,一屏里真正要读的东西被推下去。参数和命中列表不是同一件事,不该有同等高度:
|
|
@@ -491,20 +469,36 @@ export function RecallPanel({ kbId, kbName, visible, variant = 'recall', default
|
|
|
491
469
|
|
|
492
470
|
// 知识库换了或设置存了:面板上的默认值跟着走,否则显示的还是上一个库的参数。
|
|
493
471
|
// 用 effect 而不是渲染期 setState:这条同步是「外部输入变了」而不是渲染推导。
|
|
494
|
-
const modeDefault = defaults?.mode
|
|
495
472
|
const topKDefault = defaults?.topK
|
|
496
473
|
const topNDefault = defaults?.topN
|
|
497
474
|
useEffect(() => {
|
|
498
475
|
if (!visible) return
|
|
499
|
-
if (
|
|
500
|
-
if (
|
|
501
|
-
if (topNDefault) setTopN(topNDefault)
|
|
476
|
+
if (topKDefault) { setTopK(topKDefault); setTopKDraft(String(topKDefault)) }
|
|
477
|
+
if (topNDefault) { setTopN(topNDefault); setTopNDraft(String(topNDefault)) }
|
|
502
478
|
setResult(null)
|
|
503
|
-
}, [visible, resetKey,
|
|
479
|
+
}, [visible, resetKey, topKDefault, topNDefault])
|
|
480
|
+
|
|
481
|
+
/** 夹一次并写回草稿。数字为空或非数就退回当前值 —— 不合法的一律不落地。 */
|
|
482
|
+
const commitTopK = (): void => {
|
|
483
|
+
const next = Math.max(1, Math.min(50, Number(topKDraft) || topK))
|
|
484
|
+
setTopK(next); setTopKDraft(String(next))
|
|
485
|
+
// topN 的上限跟着 topK:改小 topK 之后原来那个 topN 可能已经越界。
|
|
486
|
+
setTopN(current => {
|
|
487
|
+
const capped = Math.min(current, next)
|
|
488
|
+
setTopNDraft(String(capped))
|
|
489
|
+
return capped
|
|
490
|
+
})
|
|
491
|
+
}
|
|
492
|
+
const commitTopN = (): void => {
|
|
493
|
+
const next = Math.max(1, Math.min(topK, Number(topNDraft) || topN))
|
|
494
|
+
setTopN(next); setTopNDraft(String(next))
|
|
495
|
+
}
|
|
504
496
|
|
|
505
497
|
const run = async (): Promise<void> => {
|
|
506
498
|
const trimmed = query.trim()
|
|
507
499
|
if (!trimmed) { setError('请输入要测试的召回问题。'); return }
|
|
500
|
+
const ticket = runRef.current + 1
|
|
501
|
+
runRef.current = ticket
|
|
508
502
|
setBusy(true); setError(null); setDroppedOpen(null)
|
|
509
503
|
try {
|
|
510
504
|
const boundedTopN = Math.min(topN, topK)
|
|
@@ -516,7 +510,7 @@ export function RecallPanel({ kbId, kbName, visible, variant = 'recall', default
|
|
|
516
510
|
* 点下去却是「这一路没有候选」—— 计数来自 `diagnostics`,明细来自 `ledger`,
|
|
517
511
|
* 两者来源不同,缺一半就自相矛盾。
|
|
518
512
|
*/
|
|
519
|
-
const params = new URLSearchParams({ query: trimmed, top_k: String(topK), top_n: String(boundedTopN),
|
|
513
|
+
const params = new URLSearchParams({ query: trimmed, top_k: String(topK), top_n: String(boundedTopN), detail: 'true' })
|
|
520
514
|
if (kbId) params.set('kb', kbId)
|
|
521
515
|
const payload = await requestJson<{
|
|
522
516
|
hits?: Array<Partial<RecallHitView> & { content?: string }>
|
|
@@ -551,6 +545,7 @@ export function RecallPanel({ kbId, kbName, visible, variant = 'recall', default
|
|
|
551
545
|
indexVersion?: number
|
|
552
546
|
ledger?: {
|
|
553
547
|
coordinate?: LedgerRowView[]
|
|
548
|
+
relation?: LedgerRowView[]
|
|
554
549
|
fts?: LedgerRowView[]
|
|
555
550
|
vector?: LedgerRowView[]
|
|
556
551
|
rerank?: Array<LedgerRowView & { fused?: number; logit?: number; rerankScore?: number; dropped?: boolean }>
|
|
@@ -611,6 +606,8 @@ export function RecallPanel({ kbId, kbName, visible, variant = 'recall', default
|
|
|
611
606
|
...(expansion && item.via ? { via: `${item.via.title}(${item.via.relation})` } : {}),
|
|
612
607
|
}
|
|
613
608
|
})
|
|
609
|
+
// 票号过期就整段丢掉:这份响应属于上一次点击,落地只会把新一次的结果盖掉。
|
|
610
|
+
if (runRef.current !== ticket) return
|
|
614
611
|
setResult({
|
|
615
612
|
count: hits.length,
|
|
616
613
|
backend: data.backend ?? 'fts',
|
|
@@ -644,6 +641,7 @@ export function RecallPanel({ kbId, kbName, visible, variant = 'recall', default
|
|
|
644
641
|
// 而后者只可能出现在老服务端上。
|
|
645
642
|
ledger: {
|
|
646
643
|
coordinate: data.ledger?.coordinate ?? [],
|
|
644
|
+
relation: data.ledger?.relation ?? [],
|
|
647
645
|
fts: data.ledger?.fts ?? [],
|
|
648
646
|
vector: data.ledger?.vector ?? [],
|
|
649
647
|
rerank: (data.ledger?.rerank ?? []).map(row => ({ ...row, fused: Number(row.fused ?? row.score ?? 0), dropped: row.dropped === true })),
|
|
@@ -673,15 +671,18 @@ export function RecallPanel({ kbId, kbName, visible, variant = 'recall', default
|
|
|
673
671
|
...(data.indexVersion === undefined ? {} : { indexVersion: data.indexVersion }),
|
|
674
672
|
})
|
|
675
673
|
} catch (cause) {
|
|
674
|
+
if (runRef.current !== ticket) return
|
|
676
675
|
setError(cause instanceof Error ? cause.message : String(cause))
|
|
677
676
|
} finally {
|
|
678
|
-
|
|
677
|
+
// 只有还是当前这一次才关掉「测试中」:过期的那次把 busy 关掉,会让正在跑的那次
|
|
678
|
+
// 看起来已经结束(按钮重新可点,于是又多开一次请求)。
|
|
679
|
+
if (runRef.current === ticket) setBusy(false)
|
|
679
680
|
}
|
|
680
681
|
}
|
|
681
682
|
|
|
682
683
|
const title = variant === 'runner' ? '单问题召回检查' : '召回 · 重排'
|
|
683
684
|
// 这一栏没有「一句话说明」:那条步骤轨就是说明。每一步带自己的计数,
|
|
684
|
-
//
|
|
685
|
+
// 「四路各自命中了什么 → Section 重排 → 返回哪些完整 WikiCard」
|
|
685
686
|
// 这句话由轨上的真实数字说,比一句固定文案准,也不会随实现变化而过期。
|
|
686
687
|
|
|
687
688
|
/**
|
|
@@ -704,9 +705,9 @@ export function RecallPanel({ kbId, kbName, visible, variant = 'recall', default
|
|
|
704
705
|
const steps: Array<{ id: RecallStep; icon: typeof Search; label: string; verb: string; value: string; note: string; cost: string; costTitle: string }> = [
|
|
705
706
|
{
|
|
706
707
|
id: 'recall', icon: Search, label: '召回', verb: '找',
|
|
707
|
-
value: result ? `坐标 ${keptOf('coordinate') ?? 0} · 关键词 ${keptOf('fts') ?? 0} · 向量 ${keptOf('vector') ?? 0}` : '未运行',
|
|
708
|
-
note: '
|
|
709
|
-
cost: timings ? ms(timings.coordinateMs + timings.ftsMs + timings.vectorMs) : '',
|
|
708
|
+
value: result ? `坐标 ${keptOf('coordinate') ?? 0} · 关系 ${keptOf('relation') ?? 0} · 关键词 ${keptOf('fts') ?? 0} · 向量 ${keptOf('vector') ?? 0}` : '未运行',
|
|
709
|
+
note: '四路各自进入候选池的条数',
|
|
710
|
+
cost: timings ? ms(timings.coordinateMs + (timings.relationMs ?? 0) + timings.ftsMs + timings.vectorMs) : '',
|
|
710
711
|
costTitle: timings
|
|
711
712
|
? `关键词 ${ms(timings.ftsMs)}${timings.embedMs === undefined ? '' : ` · 查询编码 ${ms(timings.embedMs)}${timings.scanMs === undefined ? '' : ` · 索引扫描 ${ms(timings.scanMs)}`}`}`
|
|
712
713
|
: '',
|
|
@@ -753,10 +754,9 @@ export function RecallPanel({ kbId, kbName, visible, variant = 'recall', default
|
|
|
753
754
|
* 但界面上不写出来,人就只能靠记忆判断哪个数真的生效了。所以不一致时明说,
|
|
754
755
|
* 并在 `title` 里给出设置里的那一组值。
|
|
755
756
|
*/
|
|
756
|
-
const overridden = (defaults?.
|
|
757
|
-
|| (defaults?.topK !== undefined && topK !== defaults.topK)
|
|
757
|
+
const overridden = (defaults?.topK !== undefined && topK !== defaults.topK)
|
|
758
758
|
|| (defaults?.topN !== undefined && topN !== defaults.topN)
|
|
759
|
-
const defaultHint =
|
|
759
|
+
const defaultHint = `设置里的默认:召回 topK ${defaults?.topK ?? '—'} · 上下文 topN ${defaults?.topN ?? '—'}`
|
|
760
760
|
|
|
761
761
|
/*
|
|
762
762
|
* 这一栏的横带节奏交给**容器**统一给(`.tita-recallPanel` 是一个 gap 14px 的网格),
|
|
@@ -781,20 +781,23 @@ export function RecallPanel({ kbId, kbName, visible, variant = 'recall', default
|
|
|
781
781
|
<div className={styles.inputRow}>
|
|
782
782
|
<Input value={query} placeholder="请输入要测试的内容"
|
|
783
783
|
onChange={event => setQuery(event.target.value)}
|
|
784
|
-
|
|
784
|
+
// 回车与按钮走**同一条判断**:按钮上写着 `disabled={busy}`,而回车原来没有这一条,
|
|
785
|
+
// 于是「测试中连敲回车」会同时开出好几个请求。空串也不打 —— 那时它在报一个
|
|
786
|
+
// 人还没写完的输入。
|
|
787
|
+
onKeyDown={event => { if (event.key === 'Enter' && !busy && query.trim() !== '') void run() }} />
|
|
785
788
|
<Button variant="default" onClick={() => void run()} disabled={busy}>
|
|
786
789
|
{variant === 'runner' && <Play size={13} />}{busy ? '测试中…' : variant === 'runner' ? '运行检查' : '测试'}
|
|
787
790
|
</Button>
|
|
788
791
|
</div>
|
|
789
792
|
{result?.queryAnalysis && <QueryAnalysisSummary analysis={result.queryAnalysis} />}
|
|
790
793
|
{/* 参数不再常驻一条横带(0050 第三版):平时只留**一行只读摘要**,值与设置里的默认
|
|
791
|
-
|
|
792
|
-
|
|
794
|
+
都在这一行上说清;要改才展开片段数量。
|
|
795
|
+
为什么不是整块搬进设置抽屉:这一栏里的两个值是**这一次运行**的参数,设置抽屉里那
|
|
793
796
|
三个是**默认值** —— 搬过去就等于把「临时改一次」变成「改掉全方案的默认」。
|
|
794
797
|
两者不一致时这一行会写明,这正是 0050 那版注释里记着的坑
|
|
795
798
|
(「设置里 topK=20、召回面板还按 10 跑」)。 */}
|
|
796
799
|
<p className={styles.recallParamLine}>
|
|
797
|
-
<b
|
|
800
|
+
<b>多路径召回</b>
|
|
798
801
|
<span>召回 topK <b>{topK}</b></span>
|
|
799
802
|
<span>上下文 topN <b>{Math.min(topN, topK)}</b></span>
|
|
800
803
|
{overridden && <span className={styles.recallParamOver} title={defaultHint}>非默认</span>}
|
|
@@ -802,18 +805,17 @@ export function RecallPanel({ kbId, kbName, visible, variant = 'recall', default
|
|
|
802
805
|
onClick={() => setParamOpen(open => !open)}>{paramOpen ? '收起参数' : '改参数'}</button>
|
|
803
806
|
</p>
|
|
804
807
|
{paramOpen && <div className={styles.recallControls}>
|
|
805
|
-
<div className={styles.recallControl}>
|
|
806
|
-
<span>路线</span>
|
|
807
|
-
<SelectMenu className="w-auto" value={mode} disabled={busy} onValueChange={setMode} aria-label="召回路线"
|
|
808
|
-
options={RECALL_MODES.map(item => ({ value: item.id, label: item.label }))} />
|
|
809
|
-
</div>
|
|
810
808
|
<label>召回 topK
|
|
811
|
-
<Input type="number" min={1} max={50} value={
|
|
812
|
-
onChange={event =>
|
|
809
|
+
<Input type="number" min={1} max={50} value={topKDraft} disabled={busy}
|
|
810
|
+
onChange={event => setTopKDraft(event.target.value)}
|
|
811
|
+
onBlur={commitTopK}
|
|
812
|
+
onKeyDown={event => { if (event.key === 'Enter') commitTopK() }} />
|
|
813
813
|
</label>
|
|
814
814
|
<label>上下文 topN
|
|
815
|
-
<Input type="number" min={1} max={topK} value={
|
|
816
|
-
onChange={event =>
|
|
815
|
+
<Input type="number" min={1} max={topK} value={topNDraft} disabled={busy}
|
|
816
|
+
onChange={event => setTopNDraft(event.target.value)}
|
|
817
|
+
onBlur={commitTopN}
|
|
818
|
+
onKeyDown={event => { if (event.key === 'Enter') commitTopN() }} />
|
|
817
819
|
</label>
|
|
818
820
|
</div>}
|
|
819
821
|
{error && <p className={cn(styles.kbNotice, styles.kbNoticeError)} role="alert">{error}</p>}
|
|
@@ -866,7 +868,7 @@ export function RecallPanel({ kbId, kbName, visible, variant = 'recall', default
|
|
|
866
868
|
但这枚 chip 不能删 —— 它是从单路视角回到合并视角的唯一入口。
|
|
867
869
|
*/}
|
|
868
870
|
<button type="button" className={cn(styles.filterChip, routeView === 'all' && styles.filterChipOn)}
|
|
869
|
-
title={
|
|
871
|
+
title={`全部:四路去重融合后的命中列表(这次 ${fusedCount} 条候选,重排留下 ${result?.hits.length ?? 0} 条)`}
|
|
870
872
|
onClick={() => setRouteView('all')}>
|
|
871
873
|
全部
|
|
872
874
|
</button>
|
|
@@ -874,7 +876,8 @@ export function RecallPanel({ kbId, kbName, visible, variant = 'recall', default
|
|
|
874
876
|
const detail = routesDetail.find(item => item.route === route.id)
|
|
875
877
|
const rows = route.id === 'coordinate'
|
|
876
878
|
? result?.ledger?.coordinate ?? []
|
|
877
|
-
: route.id === '
|
|
879
|
+
: route.id === 'relation' ? result?.ledger?.relation ?? []
|
|
880
|
+
: route.id === 'fts' ? result?.ledger?.fts ?? [] : result?.ledger?.vector ?? []
|
|
878
881
|
const kept = detail?.kept ?? rows.filter(row => row.kept).length
|
|
879
882
|
const total = detail?.candidates ?? rows.length
|
|
880
883
|
// 降级与「这一路没有候选」是两件事:前者要能一眼看出来(0031 的诚实边界)。
|
|
@@ -882,7 +885,7 @@ export function RecallPanel({ kbId, kbName, visible, variant = 'recall', default
|
|
|
882
885
|
return <button key={route.id} type="button"
|
|
883
886
|
title={degraded && detail?.reason ? `${route.hint} —— ${detail.reason}` : route.hint}
|
|
884
887
|
className={cn(styles.filterChip, routeView === route.id && styles.filterChipOn, degraded && styles.filterChipWarn)}
|
|
885
|
-
onClick={() => setRouteView(route.id as 'coordinate' | 'fts' | 'vector')}>
|
|
888
|
+
onClick={() => setRouteView(route.id as 'coordinate' | 'relation' | 'fts' | 'vector')}>
|
|
886
889
|
{route.label} {degraded ? '降级' : `${kept}/${total}`}
|
|
887
890
|
</button>
|
|
888
891
|
})}
|
|
@@ -921,7 +924,8 @@ export function RecallPanel({ kbId, kbName, visible, variant = 'recall', default
|
|
|
921
924
|
: <LedgerList
|
|
922
925
|
rows={routeView === 'coordinate'
|
|
923
926
|
? result.ledger?.coordinate ?? []
|
|
924
|
-
: routeView === '
|
|
927
|
+
: routeView === 'relation' ? result.ledger?.relation ?? []
|
|
928
|
+
: routeView === 'fts' ? result.ledger?.fts ?? [] : result.ledger?.vector ?? []}
|
|
925
929
|
scoreLabel={row => row.score.toFixed(3)}
|
|
926
930
|
droppedLabel="低于阈值"
|
|
927
931
|
/>}
|