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
package/src/wiki-trial.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeKnowledgeExtraction } from './knowledge-contract.js'
|
|
1
2
|
/**
|
|
2
3
|
* Wiki 抽取试跑(0063):**调一次模型**按新方案判一遍,不落盘。
|
|
3
4
|
*
|
|
@@ -29,10 +30,11 @@
|
|
|
29
30
|
* 顺序里有一条硬规矩:**先把"知识是什么"搞清楚,再决定"这些知识怎么组织成 Wiki Card"。**
|
|
30
31
|
* Wiki Card 是组织结果,不是知识合并结果。
|
|
31
32
|
*
|
|
32
|
-
* ##
|
|
33
|
+
* ## 主抽取只调一次
|
|
33
34
|
*
|
|
34
|
-
* 七步是给人 review
|
|
35
|
+
* 七步是给人 review 的,不是给模型分的工。主抽取一次输入全文,输出一个 JSON:
|
|
35
36
|
* `subject` / `knowledge` / `objects` / `actions` / `scenes` / `dropped`。
|
|
37
|
+
* 编译时若坐标不能直接命中,系统会把有候选的坐标合并成一次受约束的补判请求;没有候选时不补判。
|
|
36
38
|
* 分块只在文档塞不进上下文时才做。
|
|
37
39
|
*
|
|
38
40
|
* ## 对象 × 动作矩阵
|
|
@@ -53,16 +55,18 @@ import type { ModelCall } from './extract-model.js'
|
|
|
53
55
|
// 类型定义在 `wiki-trial-types.ts`:客户端也 import 那一份,所以只有一份定义。
|
|
54
56
|
// 这里再导出一次,让 `./wiki-trial.js` 仍然是一个完整的入口。
|
|
55
57
|
export type {
|
|
56
|
-
TrialActor, TrialPhase, TrialSource, TrialKnowledge, TrialAxis, TrialPlacement,
|
|
58
|
+
TrialActor, TrialPhase, TrialSource, TrialKnowledge, TrialEvent, TrialEventStepKind, TrialAxis, TrialPlacement,
|
|
57
59
|
TrialWikiCard, TrialMatrixGroup, TrialMatrixCell, TrialMatrixLoose, TrialMatrix,
|
|
58
|
-
TrialStepItem, TrialStep, TrialCheck, TrialAudit, TrialReport,
|
|
60
|
+
TrialStepItem, TrialStep, TrialCheck, TrialAudit, TrialModelCallTrace, TrialReport,
|
|
61
|
+
TrialTokenUsage,
|
|
59
62
|
} from './wiki-trial-types.js'
|
|
60
63
|
import type {
|
|
61
|
-
TrialActor, TrialPhase, TrialSource, TrialKnowledge, TrialAxis,
|
|
64
|
+
TrialActor, TrialPhase, TrialSource, TrialKnowledge, TrialEvent, TrialEventStepKind, TrialAxis,
|
|
62
65
|
TrialWikiCard, TrialMatrixGroup, TrialMatrixCell, TrialMatrixLoose, TrialMatrix,
|
|
63
|
-
TrialStepItem, TrialStep, TrialCheck, TrialReport,
|
|
66
|
+
TrialStepItem, TrialStep, TrialCheck, TrialModelCallTrace, TrialReport, TrialTokenUsage,
|
|
64
67
|
} from './wiki-trial-types.js'
|
|
65
|
-
import {
|
|
68
|
+
import { buildTrialSystem } from './extract-contract.js'
|
|
69
|
+
import { decodeExtractionTable } from './extract-table.js'
|
|
66
70
|
|
|
67
71
|
/**
|
|
68
72
|
* 抽取契约(0063 §5.6)。**这是契约,不是要抄进代码的字符串。**
|
|
@@ -74,103 +78,9 @@ import { AXIS_CONTRACT_LINES } from './axis-contract.js'
|
|
|
74
78
|
* 2. 三个分量**可以全空** —— §九 明写"允许 Knowledge 没有领域坐标"。
|
|
75
79
|
* 文档 §5.6 里"每条至少挂一个 object 或一个 action"与它冲突。
|
|
76
80
|
*/
|
|
77
|
-
/**
|
|
78
|
-
* 把骨架允许的小节拼成提示词里那一条。
|
|
79
|
-
*
|
|
80
|
-
* §5.3.2 说「`section` 的合法取值来自类型定义」—— 那就应当**下发**给它,帮助模型
|
|
81
|
-
* 使用一致的小节名。不下发的话,那句「合法取值来自类型定义」只是一句写在文档里的愿望。
|
|
82
|
-
*/
|
|
83
|
-
function sectionRule(sections: string[] | undefined): string[] {
|
|
84
|
-
const legal = (sections ?? []).map(section => section.trim()).filter(Boolean)
|
|
85
|
-
if (legal.length === 0) {
|
|
86
|
-
return ['- section 是这条知识在卡片里的位置。拿不准就填「字段」。']
|
|
87
|
-
}
|
|
88
|
-
return [
|
|
89
|
-
`- section 只能填这几个之一:${legal.join(' / ')},或者「字段」。`,
|
|
90
|
-
'- 拿不准就填「字段」。**不要自创小节名** —— 卡片是按骨架校验的,编出来的名字对不上。',
|
|
91
|
-
]
|
|
92
|
-
}
|
|
93
81
|
|
|
94
|
-
/**
|
|
95
|
-
|
|
96
|
-
*
|
|
97
|
-
* 编译链路用 `buildTrialSystem(profileSections)`;试跑面板用默认实例(不下发小节清单),
|
|
98
|
-
* 因为那一层没有「本库骨架」这个概念。
|
|
99
|
-
*/
|
|
100
|
-
export function buildTrialSystem(sections?: string[]): string {
|
|
101
|
-
return trialSystemBody(sectionRule(sections))
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const trialSystemBody = (positionRule: string[]): string => [
|
|
105
|
-
'你在把一份业务文档拆成知识库要用的内容。知识以 Knowledge 为单位:',
|
|
106
|
-
'一条可独立检索、验证或执行的最小知识单元。',
|
|
107
|
-
'',
|
|
108
|
-
'只回一个 JSON 对象,不要散文,不要代码围栏。',
|
|
109
|
-
'',
|
|
110
|
-
'输出形状:',
|
|
111
|
-
'{',
|
|
112
|
-
' "subject": "这份文档讲的业务主体",',
|
|
113
|
-
' "knowledge": [',
|
|
114
|
-
' { "id": "k1",',
|
|
115
|
-
' "text": "一条可独立检索、验证或执行的最小知识单元",',
|
|
116
|
-
' "object": "对象名或 null", "action": "动作名或 null", "scene": "场景名或 null",',
|
|
117
|
-
' "section": "步骤", "order": 1,',
|
|
118
|
-
' "sources": [ { "quote": "原文里原样复制的一段", "heading_path": ["一级", "二级"] } ] }',
|
|
119
|
-
' ],',
|
|
120
|
-
' "objects": [ { "mention": "原文中的对象叫法", "definition": "一句话说清它指什么、边界在哪", "evidence": "支持它的原文短引文", "existing": "已有对象的名字(没有就省略这个键)" } ],',
|
|
121
|
-
' "actions": [ { "mention": "原文中的动作叫法", "definition": "同上", "evidence": "支持它的原文短引文", "existing": "…" } ],',
|
|
122
|
-
' "scenes": [ { "mention": "原文中的场景叫法", "definition": "同上", "evidence": "支持它的原文短引文", "existing": "…" } ],',
|
|
123
|
-
' "dropped": [ { "quote": "原文片段", "why": "为什么丢掉" } ]',
|
|
124
|
-
'}',
|
|
125
|
-
'',
|
|
126
|
-
'# 知识:一条只讲一个单元',
|
|
127
|
-
'- text 是一条能脱离上下文独立阅读的最小知识单元。事实要能判断真假,操作步骤要能被执行。',
|
|
128
|
-
'- 一段原文里有几个独立单元就写几条。不要压成一条,也不要拆碎。',
|
|
129
|
-
' 不该拆:「SPM 由 spm_b、spm_c、spm_d 三部分构成」是一个完整事实。',
|
|
130
|
-
' 该拆:「spm_c 是楼层 ID」「楼层拖拽后 ID 会变化」「取数不能写死楼层 ID」是三条。',
|
|
131
|
-
'- 不许推理出原文没有的事实。只做压缩、归一化、结构化。不许编原文没有的步骤。',
|
|
132
|
-
'- 不要写「该字段」「上述」这种指代 —— 读者看不到上下文。',
|
|
133
|
-
'',
|
|
134
|
-
...AXIS_CONTRACT_LINES,
|
|
135
|
-
'',
|
|
136
|
-
'- 一条 Knowledge 只挂一个 object、一个 action、一个 scene。那是它的家。',
|
|
137
|
-
' 别的卡片可以引用它 —— 那是卡片的事,不是坐标的事,不要为它多挂几个坐标。',
|
|
138
|
-
'- 三个都留 null 是允许的。它不进矩阵、不成卡,但仍然可被全库命中。',
|
|
139
|
-
' 不要为了让它成卡而编一个坐标。',
|
|
140
|
-
'- 不要造"动作实例"。「通天塔spm取数」不是动作,它是坐标(通天塔 × 取数 × SPM)推出来的卡名。',
|
|
141
|
-
'',
|
|
142
|
-
'# 坐标:定义与证据',
|
|
143
|
-
'- 每个 object / action / scene 都写 `definition`:一句话说清**它指什么、边界在哪**。',
|
|
144
|
-
' 它是下一次抽取的参考 —— 名字只能让人认出写法相同的东西,定义才能认出「换了说法但同一个」。',
|
|
145
|
-
' 写「通天塔坑位click:通天塔投放位上的一次点击上报」这种能判断的句子,不要写「一个对象」这种空话。',
|
|
146
|
-
'- 每个 object / action / scene 都写 `evidence`:从原文复制支持该坐标及其定义的最短片段。没有证据就不要抽这个坐标。',
|
|
147
|
-
'- `definition` 只能总结原文和已有坐标定义能支持的范围,不要补造原文没有的属性、状态或因果。',
|
|
148
|
-
'',
|
|
149
|
-
'# 坐标:先看用户消息里的「已有坐标」',
|
|
150
|
-
'- 你讲的东西如果就是清单里的某一个(哪怕原文用的是另一个说法),就写**它的名字**,',
|
|
151
|
-
' 并把 `existing` 写成那个名字。别造一个近似的名字 —— 那会让库里长出两个只在写法上不同的实体。',
|
|
152
|
-
'- 清单里没有的才写新名字(`existing` 留空)。拿不准就写新名字:解析那一步会兜底。',
|
|
153
|
-
'- 清单是**参考**,不是限制:库里没有的东西照样可以抽出来。',
|
|
154
|
-
'',
|
|
155
|
-
'# 来源:原样,别改写',
|
|
156
|
-
'- quote 必须一个字都不改,从原文原样复制。',
|
|
157
|
-
'- 挑最短的必要片段,不要整段照抄。',
|
|
158
|
-
'- 一段原文支撑多条知识时,每条都要各自写上它的 quote。',
|
|
159
|
-
'- heading_path 是从外到内的标题路径,只作定位线索。',
|
|
160
|
-
'',
|
|
161
|
-
'# 位置:这条知识在卡里排哪',
|
|
162
|
-
...positionRule,
|
|
163
|
-
'- order 是同一小节内的第几位,从 1 开始。',
|
|
164
|
-
'- 不要写卡片正文,也不要写导语、备注、警告。你只给"哪条知识放在哪个小节、排第几"。',
|
|
165
|
-
'',
|
|
166
|
-
'# 别把排版当结构',
|
|
167
|
-
'- 原文里的小节标题只是作者写给"人顺着读"的排版,不是知识边界。',
|
|
168
|
-
'- 一个标题里可以装几件事,一件事也可以跨几个标题。不要按标题切。',
|
|
169
|
-
'',
|
|
170
|
-
'- 不含知识的片段放 dropped,写清 why。不许悄悄丢。',
|
|
171
|
-
'',
|
|
172
|
-
'每条 quote 必须从原文原样复制,一个字都不要改。没有 quote 的判断一律不要。',
|
|
173
|
-
].join('\n')
|
|
82
|
+
/** 抽取契约的 system 段搬到了 `extract-contract.ts`(说明页要显示它,而这里进不了浏览器)。 */
|
|
83
|
+
export { buildTrialSystem } from './extract-contract.js'
|
|
174
84
|
|
|
175
85
|
/** 默认的 system 段(不下发骨架小节)。试跑面板用它。 */
|
|
176
86
|
export const TRIAL_SYSTEM = buildTrialSystem()
|
|
@@ -191,13 +101,14 @@ export function buildTrialPrompt(input: {
|
|
|
191
101
|
axes?: AxisPromptBlock
|
|
192
102
|
/** 这一库的坐标约定,人写的(0068)。 */
|
|
193
103
|
note?: string
|
|
104
|
+
outputFormat?: 'table' | 'json'
|
|
194
105
|
}): string {
|
|
195
106
|
const sections: string[] = ['# 文档', `文件名:${input.title}`, '', input.text.trim(), '']
|
|
196
107
|
const block = renderAxisBlock(input.axes)
|
|
197
108
|
if (block !== '') sections.push(block, '')
|
|
198
109
|
const note = (input.note ?? '').trim()
|
|
199
110
|
if (note !== '') sections.push('# 本库的坐标约定(人写的,优先听它)', note, '')
|
|
200
|
-
sections.push('# 输出',
|
|
111
|
+
sections.push('# 输出', `按 system 中的版本协议返回${input.outputFormat === 'json' ? ' JSON 对象' : ' TOON 表格'},不要混用格式。`)
|
|
201
112
|
return sections.join('\n')
|
|
202
113
|
}
|
|
203
114
|
|
|
@@ -266,6 +177,8 @@ function renderAxisBlock(block: AxisPromptBlock | undefined): string {
|
|
|
266
177
|
/** 从可能带 ``` 围栏的文本里取出 JSON。与 `extract-model.ts` 同构。 */
|
|
267
178
|
function parseJsonObject(raw: string): unknown {
|
|
268
179
|
const trimmed = raw.trim()
|
|
180
|
+
// Parse the transport first: code fences inside JSON string values are source data.
|
|
181
|
+
try { return JSON.parse(trimmed) } catch { /* tolerate an outer Markdown wrapper */ }
|
|
269
182
|
const fenced = trimmed.match(/```(?:json)?\s*([\s\S]*?)```/)
|
|
270
183
|
const body = (fenced ? fenced[1] : trimmed).trim()
|
|
271
184
|
try { return JSON.parse(body) } catch { /* 退一步取首尾大括号 */ }
|
|
@@ -294,7 +207,7 @@ function plainRecord(value: unknown): Record<string, unknown> {
|
|
|
294
207
|
* 被误报为「清单外」并置空,最终整批 Knowledge 都变成「无坐标」。先把它们补回
|
|
295
208
|
* 抽取清单,再走同一套 Entity Resolution,既不猜坐标,也不绕过注册表。
|
|
296
209
|
*/
|
|
297
|
-
function
|
|
210
|
+
function axisMentionsFromItems(raw: unknown): Record<AxisKind, Array<{ mention: string }>> {
|
|
298
211
|
const out: Record<AxisKind, Array<{ mention: string }>> = { object: [], action: [], scene: [] }
|
|
299
212
|
if (!Array.isArray(raw)) return out
|
|
300
213
|
const fields: Array<{ kind: AxisKind; keys: string[] }> = [
|
|
@@ -315,6 +228,14 @@ function axisMentionsFromKnowledge(raw: unknown): Record<AxisKind, Array<{ menti
|
|
|
315
228
|
return out
|
|
316
229
|
}
|
|
317
230
|
|
|
231
|
+
function axisMentionsFromKnowledge(raw: unknown): Record<AxisKind, Array<{ mention: string }>> {
|
|
232
|
+
return axisMentionsFromItems(raw)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function axisMentionsFromEvents(raw: unknown): Record<AxisKind, Array<{ mention: string }>> {
|
|
236
|
+
return axisMentionsFromItems(raw)
|
|
237
|
+
}
|
|
238
|
+
|
|
318
239
|
/** 顶层轴清单优先,Knowledge 坐标只补缺项;readAxes 会按归一化名称去重。 */
|
|
319
240
|
function mergeAxisMentions(raw: unknown, supplements: Array<{ mention: string }>): unknown[] {
|
|
320
241
|
return [...(Array.isArray(raw) ? raw : []), ...supplements]
|
|
@@ -604,6 +525,9 @@ function readKnowledge(raw: unknown, options: ReadKnowledgeOptions): { knowledge
|
|
|
604
525
|
const order = typeof rawOrder === 'number' && Number.isFinite(rawOrder) ? Math.trunc(rawOrder) : 1
|
|
605
526
|
knowledge.push({
|
|
606
527
|
id,
|
|
528
|
+
kind: record.kind === 'procedure' ? 'procedure' : 'fact',
|
|
529
|
+
...(record.scope_identity === true ? { scopeIdentity: true } : {}),
|
|
530
|
+
...(record.data && typeof record.data === 'object' ? { data: record.data as TrialKnowledge['data'] } : {}),
|
|
607
531
|
text,
|
|
608
532
|
object,
|
|
609
533
|
action,
|
|
@@ -617,6 +541,136 @@ function readKnowledge(raw: unknown, options: ReadKnowledgeOptions): { knowledge
|
|
|
617
541
|
return { knowledge, problems }
|
|
618
542
|
}
|
|
619
543
|
|
|
544
|
+
interface ReadEventOptions extends ReadKnowledgeOptions {}
|
|
545
|
+
|
|
546
|
+
function readTrialSources(raw: unknown, options: Pick<ReadEventOptions, 'text' | 'documentId'>): TrialSource[] {
|
|
547
|
+
if (!Array.isArray(raw)) return []
|
|
548
|
+
const sources: TrialSource[] = []
|
|
549
|
+
for (const item of raw) {
|
|
550
|
+
if (item === null || typeof item !== 'object') continue
|
|
551
|
+
const source = item as Record<string, unknown>
|
|
552
|
+
const quote = str(source.quote)
|
|
553
|
+
if (!quote) continue
|
|
554
|
+
const located = locateQuote(options.text, quote)
|
|
555
|
+
sources.push({
|
|
556
|
+
documentId: options.documentId,
|
|
557
|
+
quote,
|
|
558
|
+
...(located.locator ? { locator: located.locator } : {}),
|
|
559
|
+
headingPath: strList(source.heading_path),
|
|
560
|
+
found: located.found,
|
|
561
|
+
})
|
|
562
|
+
}
|
|
563
|
+
return sources
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/** 读取一次具体事件;缺失字段保留为空,不用模型补猜。 */
|
|
567
|
+
function readEvents(raw: unknown, options: ReadEventOptions): { events: TrialEvent[]; problems: string[] } {
|
|
568
|
+
if (!Array.isArray(raw)) return { events: [], problems: [] }
|
|
569
|
+
const objectMap = new Map(options.objects.flatMap(axis => [axis.name, ...axis.aliases].map(name => [normalizeAxisName(name), axis.name] as const)))
|
|
570
|
+
const actionMap = new Map(options.actions.flatMap(axis => [axis.name, ...axis.aliases].map(name => [normalizeAxisName(name), axis.name] as const)))
|
|
571
|
+
const sceneMap = new Map(options.scenes.flatMap(axis => [axis.name, ...axis.aliases].map(name => [normalizeAxisName(name), axis.name] as const)))
|
|
572
|
+
const events: TrialEvent[] = []
|
|
573
|
+
const problems: string[] = []
|
|
574
|
+
const ids = new Set<string>()
|
|
575
|
+
for (const entry of raw) {
|
|
576
|
+
if (entry === null || typeof entry !== 'object') continue
|
|
577
|
+
const record = entry as Record<string, unknown>
|
|
578
|
+
const id = str(record.id) || `e${events.length + 1}`
|
|
579
|
+
if (ids.has(id)) {
|
|
580
|
+
problems.push(`Event id「${id}」重复,后续条目已跳过`)
|
|
581
|
+
continue
|
|
582
|
+
}
|
|
583
|
+
ids.add(id)
|
|
584
|
+
const title = str(record.title)
|
|
585
|
+
const summary = str(record.summary) || title
|
|
586
|
+
if (!title && !summary) {
|
|
587
|
+
problems.push(`Event「${id}」没有标题或摘要,已跳过`)
|
|
588
|
+
continue
|
|
589
|
+
}
|
|
590
|
+
const coordinate = plainRecord(record.coordinate)
|
|
591
|
+
const resolve = (value: unknown, map: Map<string, string>, axis: string): string | null => {
|
|
592
|
+
const mention = str(value)
|
|
593
|
+
if (!mention) return null
|
|
594
|
+
const canonical = map.get(normalizeAxisName(mention))
|
|
595
|
+
if (canonical) return canonical
|
|
596
|
+
problems.push(`Event「${id}」的${axis}「${mention}」没有进入轴清单,已置空`)
|
|
597
|
+
return null
|
|
598
|
+
}
|
|
599
|
+
const object = resolve(coordinate.object_mention ?? coordinate.object, objectMap, '对象')
|
|
600
|
+
const action = resolve(coordinate.action_mention ?? coordinate.action, actionMap, '动作')
|
|
601
|
+
const scene = resolve(coordinate.scene_mention ?? coordinate.scene, sceneMap, '场景')
|
|
602
|
+
|
|
603
|
+
const timeline: TrialEvent['timeline'] = []
|
|
604
|
+
if (Array.isArray(record.timeline)) {
|
|
605
|
+
for (const [index, rawStep] of record.timeline.entries()) {
|
|
606
|
+
if (rawStep === null || typeof rawStep !== 'object') continue
|
|
607
|
+
const step = rawStep as Record<string, unknown>
|
|
608
|
+
const description = str(step.description)
|
|
609
|
+
if (!description) continue
|
|
610
|
+
const candidateType = str(step.type)
|
|
611
|
+
const type: TrialEventStepKind = ['observation', 'check', 'action', 'result', 'conclusion'].includes(candidateType)
|
|
612
|
+
? candidateType as TrialEventStepKind
|
|
613
|
+
: 'observation'
|
|
614
|
+
const sources = readTrialSources(step.sources, options)
|
|
615
|
+
if (!sources.some(source => source.found)) problems.push(`Event「${id}」时间线第 ${index + 1} 项没有可核验的原文引文`)
|
|
616
|
+
timeline.push({
|
|
617
|
+
id: str(step.id) || `${id}.t${index + 1}`,
|
|
618
|
+
type,
|
|
619
|
+
description,
|
|
620
|
+
result: str(step.result) || null,
|
|
621
|
+
at: str(step.at) || null,
|
|
622
|
+
sources,
|
|
623
|
+
})
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
const sources = readTrialSources(record.sources, options)
|
|
627
|
+
const evidence = [...sources, ...timeline.flatMap(step => step.sources)]
|
|
628
|
+
if (!evidence.some(source => source.found)) {
|
|
629
|
+
problems.push(`Event「${id}」没有可核验的原文引文,已留在抽取轨迹但不进入 Event 真源`)
|
|
630
|
+
continue
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
const rawRootCause = record.root_cause
|
|
634
|
+
const root = typeof rawRootCause === 'string' ? { text: rawRootCause, status: 'suspected' } : plainRecord(rawRootCause)
|
|
635
|
+
const rootCause = str(root.text) || null
|
|
636
|
+
const rootStatus = str(root.status)
|
|
637
|
+
const rootCauseStatus: TrialEvent['rootCauseStatus'] = rootCause && (rootStatus === 'confirmed' || rootStatus === 'suspected')
|
|
638
|
+
? rootStatus
|
|
639
|
+
: null
|
|
640
|
+
const missing = strList(record.missing)
|
|
641
|
+
const addMissing = (label: string, missingValue: unknown): void => {
|
|
642
|
+
if (!str(missingValue) && !missing.includes(label)) missing.push(label)
|
|
643
|
+
}
|
|
644
|
+
const occurredAt = str(record.occurred_at) || null
|
|
645
|
+
const symptom = str(record.symptom) || null
|
|
646
|
+
const outcome = str(record.outcome) || null
|
|
647
|
+
addMissing('发生时间', occurredAt)
|
|
648
|
+
addMissing('问题现象', symptom)
|
|
649
|
+
addMissing('根因', rootCause)
|
|
650
|
+
addMissing('处理结果', outcome)
|
|
651
|
+
addMissing('问题坐标', object || action || scene)
|
|
652
|
+
events.push({
|
|
653
|
+
id,
|
|
654
|
+
externalId: str(record.external_id) || null,
|
|
655
|
+
title: title || summary,
|
|
656
|
+
summary,
|
|
657
|
+
object,
|
|
658
|
+
action,
|
|
659
|
+
scene,
|
|
660
|
+
occurredAt,
|
|
661
|
+
symptom,
|
|
662
|
+
timeline,
|
|
663
|
+
rootCause,
|
|
664
|
+
rootCauseStatus,
|
|
665
|
+
outcome,
|
|
666
|
+
missing,
|
|
667
|
+
sources,
|
|
668
|
+
noCoordinate: !object && !action && !scene,
|
|
669
|
+
})
|
|
670
|
+
}
|
|
671
|
+
return { events, problems }
|
|
672
|
+
}
|
|
673
|
+
|
|
620
674
|
// ------------------------------------------------------------ 本地推导
|
|
621
675
|
|
|
622
676
|
/**
|
|
@@ -631,27 +685,39 @@ function readKnowledge(raw: unknown, options: ReadKnowledgeOptions): { knowledge
|
|
|
631
685
|
* **没有"要不要建卡"这个问题。** 一个坐标 + 至少一条知识,就天然要建。
|
|
632
686
|
* 三个分量全空的知识不成卡 —— 它没有坐标。
|
|
633
687
|
*/
|
|
634
|
-
export function materialize(knowledge: TrialKnowledge[]): TrialWikiCard[] {
|
|
688
|
+
export function materialize(knowledge: TrialKnowledge[], events: TrialEvent[] = []): TrialWikiCard[] {
|
|
635
689
|
const groups = new Map<string, TrialWikiCard>()
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
const key = `${item.object ?? ''}\u0001${item.action ?? ''}\u0001${item.scene ?? ''}`
|
|
690
|
+
const groupOf = (object: string | null, action: string | null, scene: string | null): TrialWikiCard => {
|
|
691
|
+
const key = `${object ?? ''}\u0001${action ?? ''}\u0001${scene ?? ''}`
|
|
639
692
|
let card = groups.get(key)
|
|
640
693
|
if (!card) {
|
|
641
694
|
card = {
|
|
642
|
-
object
|
|
643
|
-
action
|
|
644
|
-
scene
|
|
645
|
-
name: cardNameFor(
|
|
695
|
+
object,
|
|
696
|
+
action,
|
|
697
|
+
scene,
|
|
698
|
+
name: cardNameFor(object, action, scene),
|
|
646
699
|
placements: [],
|
|
700
|
+
events: [],
|
|
647
701
|
}
|
|
648
702
|
groups.set(key, card)
|
|
649
703
|
}
|
|
704
|
+
return card
|
|
705
|
+
}
|
|
706
|
+
for (const item of knowledge) {
|
|
707
|
+
if (item.noCoordinate) continue
|
|
708
|
+
const card = groupOf(item.object, item.action, item.scene)
|
|
650
709
|
card.placements.push({ item: item.id, section: item.section, order: item.order })
|
|
651
710
|
}
|
|
711
|
+
for (const event of events) {
|
|
712
|
+
if (event.noCoordinate) continue
|
|
713
|
+
const key = `${event.object ?? ''}\u0001${event.action ?? ''}\u0001${event.scene ?? ''}`
|
|
714
|
+
// A WikiCard is created by Knowledge. Event only adds a reference to an existing knowledge group.
|
|
715
|
+
groups.get(key)?.events.push(event.id)
|
|
716
|
+
}
|
|
652
717
|
for (const card of groups.values()) {
|
|
653
718
|
card.placements.sort((left, right) =>
|
|
654
719
|
left.section.localeCompare(right.section) || left.order - right.order || left.item.localeCompare(right.item))
|
|
720
|
+
card.events.sort((left, right) => left.localeCompare(right))
|
|
655
721
|
}
|
|
656
722
|
return [...groups.values()]
|
|
657
723
|
}
|
|
@@ -671,15 +737,15 @@ export function materialize(knowledge: TrialKnowledge[]): TrialWikiCard[] {
|
|
|
671
737
|
* 组是**最小的可点单位**:点一个数字要看到的就是那一组的知识。
|
|
672
738
|
*/
|
|
673
739
|
export function buildMatrix(
|
|
674
|
-
objects: string[], actions: string[], knowledge: TrialKnowledge[], wikiCards: TrialWikiCard[],
|
|
740
|
+
objects: string[], actions: string[], knowledge: TrialKnowledge[], wikiCards: TrialWikiCard[], events: TrialEvent[] = [],
|
|
675
741
|
): TrialMatrix {
|
|
676
742
|
/** 一组一组的桶。键是 `object\u0001action\u0001scene`。 */
|
|
677
|
-
const buckets = new Map<string, { object: string | null; action: string | null; scene: string; knowledge: number; items: string[] }>()
|
|
743
|
+
const buckets = new Map<string, { object: string | null; action: string | null; scene: string; knowledge: number; events: number; items: string[]; eventItems: string[] }>()
|
|
678
744
|
const bucketOf = (object: string | null, action: string | null, scene: string) => {
|
|
679
745
|
const key = `${object ?? '\u0000'}\u0001${action ?? '\u0000'}\u0001${scene}`
|
|
680
746
|
const hit = buckets.get(key)
|
|
681
747
|
if (hit) return hit
|
|
682
|
-
const created = { object, action, scene, knowledge: 0, items: [] as string[] }
|
|
748
|
+
const created = { object, action, scene, knowledge: 0, events: 0, items: [] as string[], eventItems: [] as string[] }
|
|
683
749
|
buckets.set(key, created)
|
|
684
750
|
return created
|
|
685
751
|
}
|
|
@@ -690,6 +756,12 @@ export function buildMatrix(
|
|
|
690
756
|
bucket.knowledge += 1
|
|
691
757
|
bucket.items.push(item.id)
|
|
692
758
|
}
|
|
759
|
+
for (const event of events) {
|
|
760
|
+
if (event.noCoordinate) continue
|
|
761
|
+
const bucket = bucketOf(event.object, event.action, event.scene ?? '')
|
|
762
|
+
bucket.events += 1
|
|
763
|
+
bucket.eventItems.push(event.id)
|
|
764
|
+
}
|
|
693
765
|
|
|
694
766
|
// 卡名叠进它自己那一组。一个 `(object, action, scene)` 至多一张卡,所以是赋值不是追加。
|
|
695
767
|
const cardOf = new Map<string, string>()
|
|
@@ -704,8 +776,10 @@ export function buildMatrix(
|
|
|
704
776
|
out.push({
|
|
705
777
|
scene: bucket.scene,
|
|
706
778
|
knowledge: bucket.knowledge,
|
|
779
|
+
events: bucket.events,
|
|
707
780
|
card: cardOf.get(`${object ?? '\u0000'}\u0001${action ?? '\u0000'}\u0001${bucket.scene}`) ?? '',
|
|
708
781
|
items: bucket.items,
|
|
782
|
+
eventItems: bucket.eventItems,
|
|
709
783
|
})
|
|
710
784
|
}
|
|
711
785
|
// 场景名的阅读顺序:先空场景(它是「没有细分」的那一组),再按名字。
|
|
@@ -718,7 +792,7 @@ export function buildMatrix(
|
|
|
718
792
|
for (const action of actions) {
|
|
719
793
|
const groups = groupsFor(object, action)
|
|
720
794
|
if (groups.length === 0) continue
|
|
721
|
-
cells.push({ object, action, groups, knowledge: groups.reduce((sum, group) => sum + group.knowledge, 0) })
|
|
795
|
+
cells.push({ object, action, groups, knowledge: groups.reduce((sum, group) => sum + group.knowledge, 0), events: groups.reduce((sum, group) => sum + group.events, 0) })
|
|
722
796
|
}
|
|
723
797
|
}
|
|
724
798
|
|
|
@@ -726,12 +800,12 @@ export function buildMatrix(
|
|
|
726
800
|
const noAction: TrialMatrixLoose[] = []
|
|
727
801
|
for (const object of objects) {
|
|
728
802
|
const groups = groupsFor(object, null)
|
|
729
|
-
if (groups.length > 0) noAction.push({ name: object, groups, knowledge: groups.reduce((sum, group) => sum + group.knowledge, 0) })
|
|
803
|
+
if (groups.length > 0) noAction.push({ name: object, groups, knowledge: groups.reduce((sum, group) => sum + group.knowledge, 0), events: groups.reduce((sum, group) => sum + group.events, 0) })
|
|
730
804
|
}
|
|
731
805
|
const noObject: TrialMatrixLoose[] = []
|
|
732
806
|
for (const action of actions) {
|
|
733
807
|
const groups = groupsFor(null, action)
|
|
734
|
-
if (groups.length > 0) noObject.push({ name: action, groups, knowledge: groups.reduce((sum, group) => sum + group.knowledge, 0) })
|
|
808
|
+
if (groups.length > 0) noObject.push({ name: action, groups, knowledge: groups.reduce((sum, group) => sum + group.knowledge, 0), events: groups.reduce((sum, group) => sum + group.events, 0) })
|
|
735
809
|
}
|
|
736
810
|
|
|
737
811
|
return {
|
|
@@ -741,6 +815,7 @@ export function buildMatrix(
|
|
|
741
815
|
noAction,
|
|
742
816
|
noObject,
|
|
743
817
|
noCoordinate: knowledge.filter(item => item.noCoordinate).length,
|
|
818
|
+
noCoordinateEvents: events.filter(item => item.noCoordinate).length,
|
|
744
819
|
withKnowledge: cells.filter(cell => cell.knowledge > 0).length,
|
|
745
820
|
filled: cells.length,
|
|
746
821
|
slots: objects.length * actions.length,
|
|
@@ -789,7 +864,7 @@ function findTwins(knowledge: TrialKnowledge[]): Array<{ key: string; ids: strin
|
|
|
789
864
|
* 每一步给两样:`rows`(按什么判、缺什么)和 `items`(**逐条判出的实际值**)。
|
|
790
865
|
* 试跑面板是给人逐步 review 的,只有统计没有值就没法 review。
|
|
791
866
|
*
|
|
792
|
-
* 第 2、3
|
|
867
|
+
* 第 2、3 步里如实写明能力边界:轴归一需要库内注册表,候选歧义可在编译时补判;知识同义与冲突仍不做模型裁决。
|
|
793
868
|
*/
|
|
794
869
|
export function buildReport(input: {
|
|
795
870
|
title: string
|
|
@@ -799,18 +874,19 @@ export function buildReport(input: {
|
|
|
799
874
|
actions: TrialAxis[]
|
|
800
875
|
scenes: TrialAxis[]
|
|
801
876
|
knowledge: TrialKnowledge[]
|
|
877
|
+
events: TrialEvent[]
|
|
802
878
|
wikiCards: TrialWikiCard[]
|
|
803
879
|
matrix: TrialMatrix
|
|
804
880
|
problems: string[]
|
|
805
881
|
dropped: Array<{ quote: string; why: string }>
|
|
806
|
-
model:
|
|
882
|
+
model: TrialReport['model']
|
|
807
883
|
promptUser: string
|
|
808
884
|
/** 这一次**真的发出去**的 system 段。面板要摊开它,不能显示一份理想版。 */
|
|
809
885
|
system?: string
|
|
810
886
|
/** 这一次下发了多少已有坐标(0068)。省略 = 没有下发。 */
|
|
811
887
|
axesContext?: { injected: number; totals: number; truncated: number; selection?: 'full' | 'relevant' | 'head' }
|
|
812
888
|
}): TrialReport {
|
|
813
|
-
const { objects, actions, scenes, knowledge, wikiCards, matrix, dropped } = input
|
|
889
|
+
const { objects, actions, scenes, knowledge, events, wikiCards, matrix, dropped } = input
|
|
814
890
|
const headings = scanHeadings(input.text)
|
|
815
891
|
const axes = [...objects, ...actions, ...scenes]
|
|
816
892
|
const aliased = axes.filter(axis => axis.aliases.length > 0)
|
|
@@ -827,8 +903,14 @@ export function buildReport(input: {
|
|
|
827
903
|
if (!source.found) invented.push({ id: item.id, quote: source.quote })
|
|
828
904
|
}
|
|
829
905
|
}
|
|
906
|
+
for (const event of events) {
|
|
907
|
+
for (const source of [...event.sources, ...event.timeline.flatMap(step => step.sources)]) {
|
|
908
|
+
if (!source.found) invented.push({ id: event.id, quote: source.quote })
|
|
909
|
+
}
|
|
910
|
+
}
|
|
830
911
|
const noSource = knowledge.filter(item => item.sources.length === 0)
|
|
831
912
|
const noCoordinate = knowledge.filter(item => item.noCoordinate)
|
|
913
|
+
const noCoordinateEvents = events.filter(item => item.noCoordinate)
|
|
832
914
|
const twins = findTwins(knowledge)
|
|
833
915
|
const collisions = findCollisions(wikiCards)
|
|
834
916
|
const sections = new Set(knowledge.flatMap(item => item.section))
|
|
@@ -837,30 +919,38 @@ export function buildReport(input: {
|
|
|
837
919
|
const steps: TrialStep[] = [
|
|
838
920
|
{
|
|
839
921
|
id: 'extract', order: 1, name: '语义抽取', phase: '① Extract · 抽取', actor: '模型',
|
|
840
|
-
needsHuman: noCoordinate.length > 0 || noSource.length > 0 || knowledge.length === 0,
|
|
841
|
-
summary: `${knowledge.length}
|
|
922
|
+
needsHuman: noCoordinate.length > 0 || noSource.length > 0 || knowledge.length === 0 || events.some(event => event.missing.length > 0),
|
|
923
|
+
summary: `${knowledge.length} 条 Knowledge · ${events.length} 个 Event · ${objects.length} 对象 · ${actions.length} 动作 · ${scenes.length} 场景 · 一次调用`,
|
|
842
924
|
rows: [
|
|
843
925
|
{ label: '输入', value: `${input.text.split(/\r?\n/).length} 行 / ${countChars(input.text)} 字 / ${headings.length} 个标题,全文进去,不切块` },
|
|
844
|
-
{ label: '一次调用出全部', value: '
|
|
926
|
+
{ label: '一次调用出全部', value: '同一份 Document 并行抽取 Knowledge 与 Event,再提取 Object / Action / Scene mentions' },
|
|
845
927
|
{ label: '这一步不解决', value: '这是不是已有知识(第 3 步)· 这些名字是不是已有实体(第 2 步)· 应该生成哪张卡(第 5 步)' },
|
|
846
928
|
{ label: '五条规则', value: '一条只讲一个单元 · 不推理出原文没有的事实 · 不写「该字段」这种指代 · 坐标各一个 · quote 原样复制' },
|
|
847
|
-
{ label: '没有出处', value: noSource.length > 0 ? `${noSource.length}
|
|
929
|
+
{ label: '没有出处', value: noSource.length > 0 ? `${noSource.length} 条 Knowledge 一个 quote 都没给` : 'Knowledge / Event 都有可核验出处' },
|
|
848
930
|
],
|
|
849
|
-
items:
|
|
931
|
+
items: [
|
|
932
|
+
...knowledge.map(item => makeItem(
|
|
850
933
|
item.id,
|
|
851
934
|
shortQuote(item.text),
|
|
852
935
|
`${coordLabel(item.object, item.action, item.scene)} · ${item.sources.length} 条出处`,
|
|
853
936
|
item.noCoordinate || item.sources.length === 0 ? 'warn' : undefined,
|
|
854
|
-
|
|
937
|
+
)),
|
|
938
|
+
...events.map(event => makeItem(
|
|
939
|
+
`Event ${event.id}`,
|
|
940
|
+
event.title,
|
|
941
|
+
`${coordLabel(event.object, event.action, event.scene)} · ${event.timeline.length} 个时间线节点 · ${event.missing.length} 项待补`,
|
|
942
|
+
event.noCoordinate || event.missing.length > 0 ? 'warn' : undefined,
|
|
943
|
+
)),
|
|
944
|
+
],
|
|
855
945
|
},
|
|
856
946
|
{
|
|
857
947
|
id: 'entity', order: 2, name: '轴实体归一', phase: '② Resolve · 归一', actor: '系统',
|
|
858
948
|
needsHuman: aliased.length > 0 || ambiguous.length > 0 || created.length > 0,
|
|
859
949
|
summary: `${axes.length} 个轴实体 · 命中 ${matched.length} · 新建候选 ${created.length} · 不唯一 ${ambiguous.length}`,
|
|
860
950
|
rows: [
|
|
861
|
-
{ label: '顺序', value: '
|
|
951
|
+
{ label: '顺序', value: '注册表直接命中 → 对有候选的歧义坐标合并一次模型补判 → 未命中时新建候选' },
|
|
862
952
|
{ label: '三个轴同一套', value: 'Object / Action / Scene 走同一套流程,没有哪个更特殊' },
|
|
863
|
-
{ label: '不唯一就不猜', value: '
|
|
953
|
+
{ label: '不唯一就不猜', value: '模型只在给定候选中选择;证据不足时保留歧义。猜错等于把知识挂到错误的对象上,而那个错误会一路传到卡名' },
|
|
864
954
|
{ label: '不机械拼前缀', value: '只有原文、章节、SourceRaw 元数据提供了作用域证据,才生成全限定名 —— 「通天塔」+ 每个对象会把「楼层」错加成「通天塔楼层」。人写的指导随已有坐标一起下发,由模型据此判断' },
|
|
865
955
|
/*
|
|
866
956
|
* 「这一次发了多少参考」必须露出来(0068)。模型看不到某条坐标时会以为库里没有它,
|
|
@@ -869,8 +959,10 @@ export function buildReport(input: {
|
|
|
869
959
|
{ label: '已有坐标', value: input.axesContext === undefined
|
|
870
960
|
? '这一次没有下发(没接注册表,或者库里还没有实体)—— 模型只能自己造名字'
|
|
871
961
|
: `下发 ${input.axesContext.injected} / 共 ${input.axesContext.totals} 条${input.axesContext.truncated > 0 ? ` · 未下发 ${input.axesContext.truncated} 条` : ''}${input.axesContext.selection === 'relevant' ? ' · 当前文档相关候选' : input.axesContext.selection === 'full' ? ' · 全集' : ''},含名字、别名、定义与人写的指导` },
|
|
872
|
-
{ label: '
|
|
873
|
-
|
|
962
|
+
{ label: '模型补判', value: input.model.axisResolution
|
|
963
|
+
? '本次对无法直接命中的坐标发出了一次合并请求;模型只能返回候选 ID,代码会验(查得到 / 同类 / 没被并)'
|
|
964
|
+
: '本次坐标都可直接解析,或没有可比较的候选,因此没有额外模型请求' },
|
|
965
|
+
{ label: '新建的是候选', value: '模型确认没有匹配项后才建 status=candidate;证据不足时保留歧义,等人确认' },
|
|
874
966
|
{ label: '三类绝不进别名', value: '上位概念(「通天塔spm取数」不能含「通天塔」)· 组成部分(不能含「spm取数」)· 相关但不同(不能含「通天塔埋点」)' },
|
|
875
967
|
{ label: '注册表', value: axes.some(axis => axis.outcome === 'no-registry')
|
|
876
968
|
? '这次没有查到库内注册表(这个部署上没有,或调用方没给)。所以只判得动文档内的写法变体'
|
|
@@ -918,20 +1010,20 @@ export function buildReport(input: {
|
|
|
918
1010
|
},
|
|
919
1011
|
{
|
|
920
1012
|
id: 'materialize', order: 5, name: '按坐标成卡', phase: '③ Materialize · 物化', actor: '系统',
|
|
921
|
-
needsHuman: collisions.length > 0 || noCoordinate.length > 0,
|
|
922
|
-
summary: `${wikiCards.length} 张 Wiki Card · ${placements}
|
|
1013
|
+
needsHuman: collisions.length > 0 || noCoordinate.length > 0 || events.some(event => event.noCoordinate),
|
|
1014
|
+
summary: `${wikiCards.length} 张 Wiki Card · ${placements} 条 Knowledge · ${events.filter(event => !event.noCoordinate).length} 个 Event`,
|
|
923
1015
|
rows: [
|
|
924
1016
|
{ label: '三步', value: '按 (object, action, scene) 分组 → 每组物化成一张 Wiki Card → 生成自然语言标题' },
|
|
925
1017
|
{ label: '标题组织', value: '完整坐标写成「对象在场景下的动作」;缺少分量时退化为通顺的短标题;旧拼接标题保留为 alias' },
|
|
926
1018
|
{ label: '为什么不让模型做', value: '坐标是卡片主键 · 标题是确定的展示投影 · 模型判会漂移(同一坐标每次给不同标题会污染召回)' },
|
|
927
|
-
{ label: '
|
|
928
|
-
{ label: '不成卡的那些', value: noCoordinate.length > 0 ? `${noCoordinate.length}
|
|
1019
|
+
{ label: '卡片由 Knowledge 生成', value: '坐标下至少有一条 Knowledge 才物化 WikiCard;同坐标 Event 只建立引用,不单独建卡' },
|
|
1020
|
+
{ label: '不成卡的那些', value: noCoordinate.length + events.filter(event => event.noCoordinate).length > 0 ? `${noCoordinate.length} 条 Knowledge、${events.filter(event => event.noCoordinate).length} 个 Event 缺少坐标,不归入坐标卡` : '无' },
|
|
929
1021
|
],
|
|
930
1022
|
items: wikiCards.length > 0
|
|
931
1023
|
? wikiCards.map(card => makeItem(
|
|
932
1024
|
coordLabel(card.object, card.action, card.scene),
|
|
933
1025
|
card.name,
|
|
934
|
-
`${card.placements.length}
|
|
1026
|
+
`${card.placements.length} 条 Knowledge · ${card.events.length} 个 Event`,
|
|
935
1027
|
))
|
|
936
1028
|
: [makeItem('—', '没有成卡', '知识一条都没有坐标,或者模型没给出知识', 'warn')],
|
|
937
1029
|
},
|
|
@@ -971,7 +1063,7 @@ export function buildReport(input: {
|
|
|
971
1063
|
],
|
|
972
1064
|
items: [
|
|
973
1065
|
makeItem('召回单元', `${sections.size} 个 section`, '卡片按 ## 小节切成一节一条'),
|
|
974
|
-
makeItem('Knowledge', `${knowledge.length}
|
|
1066
|
+
makeItem('Knowledge / Event', `${knowledge.length} / ${events.length}`, '两类并列真源;Knowledge 生成 WikiCard,Event 通过引用关联'),
|
|
975
1067
|
makeItem('轴注册表', `${axes.length} 条`, 'canonical name + aliases —— 不是索引'),
|
|
976
1068
|
],
|
|
977
1069
|
},
|
|
@@ -1012,6 +1104,7 @@ export function buildReport(input: {
|
|
|
1012
1104
|
exceptions.push({ step: '作用域不确定', message: `「${axis.name}」在多个作用域里都命中,没有足够证据选一个 —— ${axis.how}` })
|
|
1013
1105
|
}
|
|
1014
1106
|
for (const item of noCoordinate) exceptions.push({ step: '无坐标', message: `「${shortQuote(item.text)}」三个坐标分量都空。它不进矩阵、不成卡,但仍可被全库命中 —— 要人决定补坐标还是单独归档` })
|
|
1107
|
+
for (const event of noCoordinateEvents) exceptions.push({ step: 'Event 无坐标', message: `Event「${shortQuote(event.title)}」没有坐标,因此没有归入 Wiki Card;Event 本身和出处仍保留` })
|
|
1015
1108
|
for (const twin of twins) exceptions.push({ step: '同义候选', message: `${twin.ids.join(' / ')} 文本归一化后相同,要人确认是不是同一条知识` })
|
|
1016
1109
|
for (const collision of collisions) {
|
|
1017
1110
|
const where = collision.cards.map(card => coordLabel(card.object, card.action, card.scene)).join(' / ')
|
|
@@ -1029,6 +1122,7 @@ export function buildReport(input: {
|
|
|
1029
1122
|
actions,
|
|
1030
1123
|
scenes,
|
|
1031
1124
|
knowledge,
|
|
1125
|
+
events,
|
|
1032
1126
|
wikiCards,
|
|
1033
1127
|
matrix,
|
|
1034
1128
|
checks,
|
|
@@ -1046,16 +1140,17 @@ function emptyReport(input: {
|
|
|
1046
1140
|
title: string; text: string; subject: string; promptUser: string
|
|
1047
1141
|
system?: string
|
|
1048
1142
|
axesContext?: { injected: number; totals: number; truncated: number; selection?: 'full' | 'relevant' | 'head' }
|
|
1049
|
-
model:
|
|
1143
|
+
model: TrialReport['model']
|
|
1050
1144
|
}): TrialReport {
|
|
1051
1145
|
const objects: TrialAxis[] = []
|
|
1052
1146
|
const actions: TrialAxis[] = []
|
|
1053
1147
|
const scenes: TrialAxis[] = []
|
|
1054
1148
|
const knowledge: TrialKnowledge[] = []
|
|
1149
|
+
const events: TrialEvent[] = []
|
|
1055
1150
|
const wikiCards: TrialWikiCard[] = []
|
|
1056
1151
|
return buildReport({
|
|
1057
1152
|
title: input.title, text: input.text, subject: input.subject,
|
|
1058
|
-
objects, actions, scenes, knowledge, wikiCards, dropped: [],
|
|
1153
|
+
objects, actions, scenes, knowledge, events, wikiCards, dropped: [],
|
|
1059
1154
|
matrix: buildMatrix([], [], [], []),
|
|
1060
1155
|
problems: [],
|
|
1061
1156
|
model: input.model, promptUser: input.promptUser,
|
|
@@ -1087,6 +1182,11 @@ export async function runWikiTrial(input: {
|
|
|
1087
1182
|
* 能新建候选);不给就退化成文档内的机械归一,报告里写 `no-registry`。
|
|
1088
1183
|
*/
|
|
1089
1184
|
resolveAxis?: TrialAxisResolver
|
|
1185
|
+
/**
|
|
1186
|
+
* 编译链路的批量解析入口。先由注册表直接解析,再把仍有候选的 mention 合并成一次模型补判。
|
|
1187
|
+
* 试跑面板保留 `resolveAxis` 的单条解析路径。
|
|
1188
|
+
*/
|
|
1189
|
+
resolveAxisSet?: TrialAxisSetResolver
|
|
1090
1190
|
/**
|
|
1091
1191
|
* 已有坐标,**下发进用户提示词**(0068)。
|
|
1092
1192
|
*
|
|
@@ -1108,14 +1208,20 @@ export async function runWikiTrial(input: {
|
|
|
1108
1208
|
* 试跑面板不传,用默认值。
|
|
1109
1209
|
*/
|
|
1110
1210
|
sessionId?: string
|
|
1211
|
+
/** 实际模型选择。凭据不进入轨迹。 */
|
|
1212
|
+
modelRequest?: Omit<NonNullable<TrialReport['model']['request']>, 'sessionId'>
|
|
1111
1213
|
call?: ModelCall
|
|
1112
1214
|
callWhy?: string
|
|
1215
|
+
outputFormat?: 'table' | 'json'
|
|
1216
|
+
onDelta?: (text: string) => void
|
|
1113
1217
|
}): Promise<TrialReport> {
|
|
1114
1218
|
const subject = (input.subject ?? '').trim()
|
|
1115
1219
|
const docId = (input.docId ?? '').trim()
|
|
1116
1220
|
// 提示词先组装好再走分支:模型不可用时它照样要回给界面 —— 用户要看的正是"本来会发出去什么"。
|
|
1117
|
-
const promptUser = buildTrialPrompt({ title: input.title, text: input.text, ...(input.axes === undefined ? {} : { axes: input.axes }), ...(input.note ? { note: input.note } : {}) })
|
|
1118
|
-
const system = buildTrialSystem(input.sections)
|
|
1221
|
+
const promptUser = buildTrialPrompt({ title: input.title, text: input.text, ...(input.axes === undefined ? {} : { axes: input.axes }), ...(input.note ? { note: input.note } : {}), outputFormat: input.outputFormat })
|
|
1222
|
+
const system = buildTrialSystem(input.sections, input.outputFormat)
|
|
1223
|
+
const sessionId = input.sessionId ?? 'knowledge:trial'
|
|
1224
|
+
const request = { ...input.modelRequest, sessionId }
|
|
1119
1225
|
const axesContext = input.axes === undefined ? undefined : {
|
|
1120
1226
|
injected: (['object', 'action', 'scene'] as AxisKind[]).reduce((sum, kind) => sum + (input.axes!.entries[kind]?.length ?? 0), 0),
|
|
1121
1227
|
totals: (['object', 'action', 'scene'] as AxisKind[]).reduce((sum, kind) => sum + (input.axes!.totals[kind] ?? 0), 0),
|
|
@@ -1127,22 +1233,37 @@ export async function runWikiTrial(input: {
|
|
|
1127
1233
|
return emptyReport({
|
|
1128
1234
|
title: input.title, text: input.text, subject: subject || input.title, promptUser, system,
|
|
1129
1235
|
axesContext,
|
|
1130
|
-
model: { ok: false, why: input.callWhy ?? '模型不可用' },
|
|
1236
|
+
model: { ok: false, why: input.callWhy ?? '模型不可用', request },
|
|
1131
1237
|
})
|
|
1132
1238
|
}
|
|
1133
1239
|
|
|
1134
1240
|
let raw = ''
|
|
1241
|
+
let usage: TrialTokenUsage | undefined
|
|
1135
1242
|
try {
|
|
1136
|
-
raw = await input.call({ system, prompt: promptUser, sessionId:
|
|
1243
|
+
raw = await input.call({ system, prompt: promptUser, sessionId, onUsage: value => { usage = value }, onDelta: text => { raw += text; input.onDelta?.(text) } })
|
|
1137
1244
|
} catch (cause) {
|
|
1138
1245
|
return emptyReport({
|
|
1139
1246
|
title: input.title, text: input.text, subject: subject || input.title, promptUser, system,
|
|
1140
1247
|
axesContext,
|
|
1141
|
-
model: {
|
|
1248
|
+
model: {
|
|
1249
|
+
ok: false,
|
|
1250
|
+
why: `调用模型失败:${cause instanceof Error ? cause.message : String(cause)}`,
|
|
1251
|
+
request,
|
|
1252
|
+
...(raw ? { response: raw } : {}),
|
|
1253
|
+
...(usage ? { usage } : {}),
|
|
1254
|
+
},
|
|
1142
1255
|
})
|
|
1143
1256
|
}
|
|
1144
1257
|
|
|
1145
|
-
|
|
1258
|
+
let parsed: unknown
|
|
1259
|
+
let outputFormat: 'table' | 'json' = 'json'
|
|
1260
|
+
let parseError = ''
|
|
1261
|
+
const body = raw.trim().replace(/^```(?:toon|text)?\s*\n/, '').replace(/\n```\s*$/, '')
|
|
1262
|
+
try {
|
|
1263
|
+
if (/^format:\s*knowledge-table-v[12]\s*$/m.test(body)) { parsed = decodeExtractionTable(body); outputFormat = 'table' }
|
|
1264
|
+
else parsed = parseJsonObject(raw)
|
|
1265
|
+
if (parsed) parsed = normalizeKnowledgeExtraction(parsed)
|
|
1266
|
+
} catch (cause) { parseError = cause instanceof Error ? cause.message : String(cause) }
|
|
1146
1267
|
const record = parsed !== null && typeof parsed === 'object' ? parsed as Record<string, unknown> : undefined
|
|
1147
1268
|
if (!record) {
|
|
1148
1269
|
return emptyReport({
|
|
@@ -1150,7 +1271,10 @@ export async function runWikiTrial(input: {
|
|
|
1150
1271
|
axesContext,
|
|
1151
1272
|
model: {
|
|
1152
1273
|
ok: false,
|
|
1153
|
-
why: '
|
|
1274
|
+
why: parseError || '模型返回不是有效的抽取表格或兼容 JSON',
|
|
1275
|
+
request,
|
|
1276
|
+
response: raw,
|
|
1277
|
+
...(usage ? { usage } : {}),
|
|
1154
1278
|
// 把模型实际说的那一段带上:只报「不是 JSON」的话,人不知道该去改什么。
|
|
1155
1279
|
...(raw.trim() ? { raw: raw.trim().replace(/\s+/g, ' ').slice(0, 160) } : {}),
|
|
1156
1280
|
},
|
|
@@ -1164,9 +1288,10 @@ export async function runWikiTrial(input: {
|
|
|
1164
1288
|
*/
|
|
1165
1289
|
const mentions = plainRecord(record.axis_mentions)
|
|
1166
1290
|
const knowledgeAxes = axisMentionsFromKnowledge(record.knowledge)
|
|
1167
|
-
const
|
|
1168
|
-
const
|
|
1169
|
-
const
|
|
1291
|
+
const eventAxes = axisMentionsFromEvents(record.events)
|
|
1292
|
+
const objectRead = readAxes(mergeAxisMentions(mentions.objects ?? record.objects, [...knowledgeAxes.object, ...eventAxes.object]), 'object')
|
|
1293
|
+
const actionRead = readAxes(mergeAxisMentions(mentions.actions ?? record.actions, [...knowledgeAxes.action, ...eventAxes.action]), 'action')
|
|
1294
|
+
const sceneRead = readAxes(mergeAxisMentions(mentions.scenes ?? record.scenes, [...knowledgeAxes.scene, ...eventAxes.scene]), 'scene')
|
|
1170
1295
|
|
|
1171
1296
|
|
|
1172
1297
|
/**
|
|
@@ -1179,18 +1304,39 @@ export async function runWikiTrial(input: {
|
|
|
1179
1304
|
* (`坑位click` → `通天塔坑位click`),而 Knowledge 的坐标写的是 mention。
|
|
1180
1305
|
* 顺序反了,那条知识就会因为「坐标不在清单里」被当成编造的坐标丢掉。
|
|
1181
1306
|
*/
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1307
|
+
let objects: TrialAxis[]
|
|
1308
|
+
let actions: TrialAxis[]
|
|
1309
|
+
let scenes: TrialAxis[]
|
|
1310
|
+
let axisResolution: TrialModelCallTrace | undefined
|
|
1311
|
+
if (input.resolveAxisSet) {
|
|
1312
|
+
const resolved = await input.resolveAxisSet({
|
|
1313
|
+
objects: objectRead.axes,
|
|
1314
|
+
actions: actionRead.axes,
|
|
1315
|
+
scenes: sceneRead.axes,
|
|
1316
|
+
})
|
|
1317
|
+
objects = resolved.objects
|
|
1318
|
+
actions = resolved.actions
|
|
1319
|
+
scenes = resolved.scenes
|
|
1320
|
+
axisResolution = resolved.trace
|
|
1321
|
+
} else {
|
|
1322
|
+
objects = await resolveAxes('object', objectRead.axes, input.resolveAxis)
|
|
1323
|
+
actions = await resolveAxes('action', actionRead.axes, input.resolveAxis)
|
|
1324
|
+
scenes = await resolveAxes('scene', sceneRead.axes, input.resolveAxis)
|
|
1325
|
+
}
|
|
1185
1326
|
const knowledgeRead = readKnowledge(record.knowledge, {
|
|
1186
1327
|
text: input.text,
|
|
1187
1328
|
// 有真文档就用它的 id:来源要指得回那份文档,而不是一个标题字符串。
|
|
1188
1329
|
documentId: docId || input.title,
|
|
1189
1330
|
objects, actions, scenes,
|
|
1190
1331
|
})
|
|
1332
|
+
const eventRead = readEvents(record.events, {
|
|
1333
|
+
text: input.text,
|
|
1334
|
+
documentId: docId || input.title,
|
|
1335
|
+
objects, actions, scenes,
|
|
1336
|
+
})
|
|
1191
1337
|
// `dropped` 在新契约里收在 `audit` 下 —— 它是审计,不是知识模型的一部分(§5.5)。
|
|
1192
1338
|
const dropped = readDropped(plainRecord(record.audit).dropped ?? record.dropped)
|
|
1193
|
-
const wikiCards = materialize(knowledgeRead.knowledge)
|
|
1339
|
+
const wikiCards = materialize(knowledgeRead.knowledge, eventRead.events)
|
|
1194
1340
|
const modelSubject = str(record.subject) || subject || input.title
|
|
1195
1341
|
|
|
1196
1342
|
return buildReport({
|
|
@@ -1199,13 +1345,25 @@ export async function runWikiTrial(input: {
|
|
|
1199
1345
|
actions,
|
|
1200
1346
|
scenes,
|
|
1201
1347
|
knowledge: knowledgeRead.knowledge,
|
|
1348
|
+
events: eventRead.events,
|
|
1202
1349
|
wikiCards,
|
|
1203
|
-
matrix: buildMatrix(objects.map(axis => axis.name), actions.map(axis => axis.name), knowledgeRead.knowledge, wikiCards),
|
|
1204
|
-
problems: [...objectRead.problems, ...actionRead.problems, ...sceneRead.problems, ...knowledgeRead.problems],
|
|
1350
|
+
matrix: buildMatrix(objects.map(axis => axis.name), actions.map(axis => axis.name), knowledgeRead.knowledge, wikiCards, eventRead.events),
|
|
1351
|
+
problems: [...objectRead.problems, ...actionRead.problems, ...sceneRead.problems, ...knowledgeRead.problems, ...eventRead.problems],
|
|
1205
1352
|
dropped,
|
|
1206
|
-
model:
|
|
1207
|
-
|
|
1208
|
-
:
|
|
1353
|
+
model: {
|
|
1354
|
+
ok: knowledgeRead.knowledge.length > 0 || eventRead.events.length > 0,
|
|
1355
|
+
parsed: Array.isArray(record.knowledge) && Array.isArray(record.events ?? [])
|
|
1356
|
+
&& knowledgeRead.knowledge.length === record.knowledge.length
|
|
1357
|
+
&& eventRead.events.length === (Array.isArray(record.events) ? record.events.length : 0)
|
|
1358
|
+
&& knowledgeRead.knowledge.every(item => item.sources.length > 0 && item.sources.every(source => source.found))
|
|
1359
|
+
&& eventRead.events.every(item => [...item.sources, ...item.timeline.flatMap(step => step.sources)].every(source => source.found)),
|
|
1360
|
+
outputFormat,
|
|
1361
|
+
...(!(knowledgeRead.knowledge.length > 0 || eventRead.events.length > 0) ? { why: '模型没有给出 Knowledge 或 Event' } : {}),
|
|
1362
|
+
request,
|
|
1363
|
+
response: raw,
|
|
1364
|
+
...(usage ? { usage } : {}),
|
|
1365
|
+
...(axisResolution ? { axisResolution } : {}),
|
|
1366
|
+
},
|
|
1209
1367
|
promptUser, system,
|
|
1210
1368
|
...(axesContext === undefined ? {} : { axesContext }),
|
|
1211
1369
|
})
|
|
@@ -1227,6 +1385,18 @@ export type TrialAxisResolver = (
|
|
|
1227
1385
|
extra?: { preferMention?: string; description?: string },
|
|
1228
1386
|
) => Promise<AxisResolution | null>
|
|
1229
1387
|
|
|
1388
|
+
export interface TrialAxisSet {
|
|
1389
|
+
objects: TrialAxis[]
|
|
1390
|
+
actions: TrialAxis[]
|
|
1391
|
+
scenes: TrialAxis[]
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
export interface TrialAxisSetResolution extends TrialAxisSet {
|
|
1395
|
+
trace?: TrialModelCallTrace
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
export type TrialAxisSetResolver = (axes: TrialAxisSet) => Promise<TrialAxisSetResolution>
|
|
1399
|
+
|
|
1230
1400
|
/** 命中方式 → 给人看的一句话。 */
|
|
1231
1401
|
function describeHit(resolution: AxisResolution): string {
|
|
1232
1402
|
switch (resolution.how) {
|
|
@@ -1263,33 +1433,35 @@ async function resolveAxes(
|
|
|
1263
1433
|
})
|
|
1264
1434
|
// `null` = 这个部署上没有注册表。那不是「没命中」,是「这一次没查过」。
|
|
1265
1435
|
if (resolution === null) return axes
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1436
|
+
out.push(applyTrialAxisResolution(axis, resolution))
|
|
1437
|
+
}
|
|
1438
|
+
return out
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
/** 将注册表结论变成报告里的坐标。供批量补判复用同一套字段处理。 */
|
|
1442
|
+
export function applyTrialAxisResolution(axis: TrialAxis, resolution: AxisResolution | null): TrialAxis {
|
|
1443
|
+
if (resolution === null) return { ...axis, outcome: 'no-registry', how: '只做了文档内的机械归一' }
|
|
1444
|
+
if ((resolution.outcome === 'matched' || resolution.outcome === 'created') && resolution.entity) {
|
|
1445
|
+
const entity = resolution.entity
|
|
1446
|
+
return {
|
|
1447
|
+
name: entity.name,
|
|
1448
|
+
id: entity.id,
|
|
1449
|
+
aliases: [...new Set([...axis.aliases, ...(entity.name === axis.name ? [] : [axis.name])])],
|
|
1450
|
+
outcome: resolution.outcome === 'created' ? 'new' : 'matched',
|
|
1451
|
+
how: describeHit(resolution),
|
|
1452
|
+
...(entity.description ? { definition: entity.description } : axis.definition ? { definition: axis.definition } : {}),
|
|
1453
|
+
...(axis.evidence ? { evidence: axis.evidence } : {}),
|
|
1280
1454
|
}
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
}
|
|
1288
|
-
continue
|
|
1455
|
+
}
|
|
1456
|
+
if (resolution.outcome === 'ambiguous') {
|
|
1457
|
+
const names = (resolution.candidates ?? []).map(candidate => candidate.name)
|
|
1458
|
+
return {
|
|
1459
|
+
...axis,
|
|
1460
|
+
outcome: 'ambiguous',
|
|
1461
|
+
how: names.length > 0 ? `不唯一,候选:${names.join('、')}` : '不唯一,但注册表里没有候选',
|
|
1289
1462
|
}
|
|
1290
|
-
out.push({ ...axis, outcome: 'no-registry', how: '只做了文档内的机械归一' })
|
|
1291
1463
|
}
|
|
1292
|
-
return
|
|
1464
|
+
return { ...axis, outcome: 'ambiguous', how: '坐标为空,无法解析' }
|
|
1293
1465
|
}
|
|
1294
1466
|
|
|
1295
1467
|
/** 读 `dropped`。它是**审计轨迹**(§5.5),不进知识模型。 */
|
|
@@ -1308,10 +1480,10 @@ function readDropped(raw: unknown): Array<{ quote: string; why: string }> {
|
|
|
1308
1480
|
|
|
1309
1481
|
/** 给界面用的一句话规模描述。矩阵的规模由界面自己从 `matrix` 取。 */
|
|
1310
1482
|
export function trialSummary(report: TrialReport): string {
|
|
1311
|
-
|
|
1483
|
+
const pieces = [
|
|
1312
1484
|
`${report.lines} 行`, `${report.chars} 字`,
|
|
1313
1485
|
`${report.objects.length} 对象`, `${report.actions.length} 动作`, `${report.scenes.length} 场景`,
|
|
1314
|
-
`${report.knowledge.length}
|
|
1486
|
+
`${report.knowledge.length} Knowledge`, `${report.events.length} Event`, `${report.wikiCards.length} Wiki Card`,
|
|
1315
1487
|
]
|
|
1316
1488
|
const dropped = report.audit.dropped.length
|
|
1317
1489
|
if (dropped > 0) pieces.push(`丢弃 ${dropped} 段`)
|