@konneal/engine 0.2.37 → 0.2.38
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/dist/{ask-J6NGXPOD.js → ask-VXV2BFNC.js} +2 -2
- package/dist/{chunk-37FSCXBQ.js → chunk-6GAYBMUM.js} +24 -0
- package/dist/{chunk-SEOQWW77.js → chunk-CNFQNCWA.js} +8 -3
- package/dist/{chunk-YEAAGFHB.js → chunk-GDQOFP6B.js} +1 -1
- package/dist/modelplane.d.ts +1 -0
- package/dist/pipeline.d.ts +1 -0
- package/dist/quality.d.ts +6 -0
- package/dist/{search-V6M4KASL.js → search-HBE47CK6.js} +2 -2
- package/dist/worker_public/src/index.js +4 -4
- package/package.json +1 -1
- package/workers/worker_public/src/ask.ts +5 -2
- package/workers/worker_public/src/modelplane.ts +1 -0
- package/workers/worker_public/src/pipeline.ts +2 -0
- package/workers/worker_public/src/quality.ts +48 -0
|
@@ -61,6 +61,27 @@ async function generateOnce(env, model, messages, effort) {
|
|
|
61
61
|
return null;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
// workers/worker_public/src/quality.ts
|
|
65
|
+
var ORDER = { verified: 0, curated: 1, ocr: 2 };
|
|
66
|
+
function hitQuality(m) {
|
|
67
|
+
if (m.model_node || m.model_version || m.producer === "primmel") return "verified";
|
|
68
|
+
if (m.tier === "curated") return "curated";
|
|
69
|
+
return "ocr";
|
|
70
|
+
}
|
|
71
|
+
function answerQuality(qualities) {
|
|
72
|
+
let worst = null;
|
|
73
|
+
for (const q of qualities) {
|
|
74
|
+
if (!q) continue;
|
|
75
|
+
if (!worst || ORDER[q] > ORDER[worst]) worst = q;
|
|
76
|
+
}
|
|
77
|
+
return worst;
|
|
78
|
+
}
|
|
79
|
+
function qualityNote(q) {
|
|
80
|
+
if (q === "verified") return "Grounded in verified sources: this publication's requirements ride a machine-checkable data model.";
|
|
81
|
+
if (q === "curated") return "Grounded in the edited corpus: Metanorma-authored documents, chunked at clause boundaries.";
|
|
82
|
+
return "Partly grounded in experimental OCR text: verify quotations and table values against the official publication.";
|
|
83
|
+
}
|
|
84
|
+
|
|
64
85
|
// workers/worker_public/src/lexical.ts
|
|
65
86
|
var LEXICAL_K = 40;
|
|
66
87
|
function ftsMatchQuery(query) {
|
|
@@ -23515,6 +23536,7 @@ function citations(hits) {
|
|
|
23515
23536
|
status: h.metadata.status ?? "unknown",
|
|
23516
23537
|
superseded_by: h.metadata.superseded_by || void 0,
|
|
23517
23538
|
corpus: h.metadata.corpus || P().publisher.id,
|
|
23539
|
+
quality: hitQuality(h.metadata),
|
|
23518
23540
|
url: publicationUrl(h.metadata),
|
|
23519
23541
|
snippet: h.text.slice(0, 400),
|
|
23520
23542
|
score: h.rerank_score ?? h.score
|
|
@@ -24560,6 +24582,8 @@ async function editionNote(env, u) {
|
|
|
24560
24582
|
export {
|
|
24561
24583
|
embed,
|
|
24562
24584
|
generateOnce,
|
|
24585
|
+
answerQuality,
|
|
24586
|
+
qualityNote,
|
|
24563
24587
|
ftsMatchQuery,
|
|
24564
24588
|
refCodec,
|
|
24565
24589
|
NO_CONTEXT,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
NO_CONTEXT,
|
|
3
|
+
answerQuality,
|
|
3
4
|
appliedContext,
|
|
4
5
|
buildMessages,
|
|
5
6
|
checkQuota,
|
|
@@ -21,6 +22,7 @@ import {
|
|
|
21
22
|
parseContext,
|
|
22
23
|
portModelRunner,
|
|
23
24
|
portStore,
|
|
25
|
+
qualityNote,
|
|
24
26
|
rawSessionToken,
|
|
25
27
|
refCodec,
|
|
26
28
|
resolveDocScope,
|
|
@@ -32,7 +34,7 @@ import {
|
|
|
32
34
|
syntheticUnderstanding,
|
|
33
35
|
telemetry,
|
|
34
36
|
understandQuery
|
|
35
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-6GAYBMUM.js";
|
|
36
38
|
import {
|
|
37
39
|
corsHeaders,
|
|
38
40
|
err,
|
|
@@ -497,6 +499,7 @@ function modelCitation(node) {
|
|
|
497
499
|
clause_title: `${node.kind.replace(/_/g, " ")} \u2014 ${node.name} (${node.node_id})`,
|
|
498
500
|
status: "in-force",
|
|
499
501
|
corpus: "smart-model",
|
|
502
|
+
quality: "verified",
|
|
500
503
|
url: void 0,
|
|
501
504
|
snippet: `${node.node_id}${node.clause ? ` \xB7 ${node.clause.urn}` : ""}${node.content?.statement ? ` \u2014 ${clip(node.content.statement, 240)}` : ""}`,
|
|
502
505
|
score: 1
|
|
@@ -2471,7 +2474,8 @@ Answer account questions from these records ONLY: name the record when you use i
|
|
|
2471
2474
|
|
|
2472
2475
|
`));
|
|
2473
2476
|
send({ type: "read", read: readAs() });
|
|
2474
|
-
|
|
2477
|
+
const sourceQuality = answerQuality(cites.map((c) => c.quality));
|
|
2478
|
+
send({ type: "citations", citations: cites, context_applied: ctxApplied, ...sourceQuality ? { source_quality: sourceQuality, quality_note: qualityNote(sourceQuality) } : {}, ...liveRecords ? { records: liveRecords } : {}, quota });
|
|
2475
2479
|
let full = "";
|
|
2476
2480
|
try {
|
|
2477
2481
|
for await (const tok of sseTokens(stream)) {
|
|
@@ -2604,7 +2608,8 @@ Answer account questions from these records ONLY: name the record when you use i
|
|
|
2604
2608
|
if (completionBlocks.length) console.log("contract completion:", completionBlocks.length, "table block(s) attached server-side");
|
|
2605
2609
|
}
|
|
2606
2610
|
completionBlocks.push(...await completeFigures(env.DB, answer, [...c2ns.blocks, ...completionBlocks], used));
|
|
2607
|
-
const
|
|
2611
|
+
const jsonQuality = answerQuality(finalCites.map((c) => c.quality));
|
|
2612
|
+
const out = { answer, citations: finalCites, ...jsonQuality ? { source_quality: jsonQuality, quality_note: qualityNote(jsonQuality) } : {}, model: MODELS.member, query_hash: queryHash, follow_ups: understanding?.follow_ups ?? [], blocks: [...c2ns.blocks, ...verdictBlock ? [verdictBlock] : [], ...conditionBlock ? [conditionBlock] : [], ...aggregationBlock ? [aggregationBlock] : [], ...completionBlocks], context_applied: ctxApplied, ...liveRecords ? { records: liveRecords } : {} };
|
|
2608
2613
|
const cacheable = !contextual && !declaredCtx && !answer.includes(refusalAnswer()) && finalAnchors.violations.length === 0;
|
|
2609
2614
|
if (cacheable) {
|
|
2610
2615
|
const warmVec = await warmEmbed ?? null;
|
package/dist/modelplane.d.ts
CHANGED
package/dist/pipeline.d.ts
CHANGED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ChunkMeta } from "../../shared/chunk.ts";
|
|
2
|
+
export type SourceQuality = "verified" | "curated" | "ocr";
|
|
3
|
+
export declare function hitQuality(m: ChunkMeta): SourceQuality;
|
|
4
|
+
export declare function answerQuality(qualities: (SourceQuality | undefined)[]): SourceQuality | null;
|
|
5
|
+
/** The one-line posture the interface renders under the answer. */
|
|
6
|
+
export declare function qualityNote(q: SourceQuality): string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
handleSearch
|
|
3
|
-
} from "../../chunk-
|
|
3
|
+
} from "../../chunk-GDQOFP6B.js";
|
|
4
4
|
import {
|
|
5
5
|
bindModelNode,
|
|
6
6
|
checkQuoteAnchors,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
modelGroundingBlock,
|
|
10
10
|
scoreJudge,
|
|
11
11
|
standardForDocNumber
|
|
12
|
-
} from "../../chunk-
|
|
12
|
+
} from "../../chunk-CNFQNCWA.js";
|
|
13
13
|
import {
|
|
14
14
|
buildMessages,
|
|
15
15
|
citations,
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
sessionFrom,
|
|
36
36
|
telemetry,
|
|
37
37
|
understandQuery
|
|
38
|
-
} from "../../chunk-
|
|
38
|
+
} from "../../chunk-6GAYBMUM.js";
|
|
39
39
|
import {
|
|
40
40
|
authenticate,
|
|
41
41
|
corsHeaders,
|
|
@@ -999,7 +999,7 @@ async function handleMcp(env, ctx, req, tier, key) {
|
|
|
999
999
|
// stream:false forces the JSON lane (anon defaults to SSE)
|
|
1000
1000
|
body: JSON.stringify({ ...args, stream: false })
|
|
1001
1001
|
});
|
|
1002
|
-
const res = name === "ask" ? await (await import("../../ask-
|
|
1002
|
+
const res = name === "ask" ? await (await import("../../ask-VXV2BFNC.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-HBE47CK6.js")).handleSearch(env, ctx, inner, tier, key);
|
|
1003
1003
|
return res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
|
|
1004
1004
|
});
|
|
1005
1005
|
if (out.ok && "accepted" in out) return new Response(null, { status: 202 });
|
package/package.json
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"playwright": "^1.62.1",
|
|
28
28
|
"yaml": "^2.9.1"
|
|
29
29
|
},
|
|
30
|
-
"version": "0.2.
|
|
30
|
+
"version": "0.2.38",
|
|
31
31
|
"description": "The Konneal engine: the publisher-agnostic build pipeline and API plane for standards intelligence (retrieval, answer contract, verdicts, evaluation).",
|
|
32
32
|
"license": "BSD-3-Clause",
|
|
33
33
|
"type": "module",
|
|
@@ -25,6 +25,7 @@ import { evaluate as machineEvaluate, verdictNote } from "./verdict";
|
|
|
25
25
|
import { evaluateConditionSets, quantitiesIn, type ConditionVerdict } from "./conditions";
|
|
26
26
|
import { evaluateAggregation, type AggregationVerdict } from "./aggregation";
|
|
27
27
|
import { matchLicensedTopic, boundaryNoteText } from "./boundary";
|
|
28
|
+
import { answerQuality, qualityNote } from "./quality";
|
|
28
29
|
import { detectDraftIntent, prepareDraft } from "./drafts";
|
|
29
30
|
import { detectApiCallIntent, prepareApiCall } from "./apicalls";
|
|
30
31
|
import { memoryNote } from "./memories";
|
|
@@ -1145,7 +1146,8 @@ async function handleAsk(
|
|
|
1145
1146
|
// the reading arrives first: the interpretation that steered
|
|
1146
1147
|
// retrieval, before a single token of the answer
|
|
1147
1148
|
send({ type: "read", read: readAs() });
|
|
1148
|
-
|
|
1149
|
+
const sourceQuality = answerQuality(cites.map((c: any) => c.quality));
|
|
1150
|
+
send({ type: "citations", citations: cites, context_applied: ctxApplied, ...(sourceQuality ? { source_quality: sourceQuality, quality_note: qualityNote(sourceQuality) } : {}), ...(liveRecords ? { records: liveRecords } : {}), quota, });
|
|
1149
1151
|
let full = "";
|
|
1150
1152
|
try {
|
|
1151
1153
|
for await (const tok of sseTokens(stream)) {
|
|
@@ -1339,7 +1341,8 @@ async function handleAsk(
|
|
|
1339
1341
|
// figure completion (#172) — see ./completion for the rationale
|
|
1340
1342
|
completionBlocks.push(...(await completeFigures(env.DB, answer, [...c2ns.blocks, ...completionBlocks], used)));
|
|
1341
1343
|
|
|
1342
|
-
const
|
|
1344
|
+
const jsonQuality = answerQuality(finalCites.map((c: any) => c.quality));
|
|
1345
|
+
const out = { answer, citations: finalCites, ...(jsonQuality ? { source_quality: jsonQuality, quality_note: qualityNote(jsonQuality) } : {}), model: MODELS.member, query_hash: queryHash, follow_ups: understanding?.follow_ups ?? [], blocks: [...c2ns.blocks, ...(verdictBlock ? [verdictBlock] : []), ...(conditionBlock ? [conditionBlock] : []), ...(aggregationBlock ? [aggregationBlock] : []), ...completionBlocks], context_applied: ctxApplied, ...(liveRecords ? { records: liveRecords } : {}) };
|
|
1343
1346
|
const cacheable = !contextual && !declaredCtx && !answer.includes(refusalAnswer()) && finalAnchors.violations.length === 0;
|
|
1344
1347
|
if (cacheable) {
|
|
1345
1348
|
const warmVec = (await warmEmbed) ?? null;
|
|
@@ -287,6 +287,7 @@ export function modelCitation(node: BoundModelNode) {
|
|
|
287
287
|
clause_title: `${node.kind.replace(/_/g, " ")} — ${node.name} (${node.node_id})`,
|
|
288
288
|
status: "in-force",
|
|
289
289
|
corpus: "smart-model",
|
|
290
|
+
quality: "verified",
|
|
290
291
|
url: undefined,
|
|
291
292
|
snippet: `${node.node_id}${node.clause ? ` · ${node.clause.urn}` : ""}${node.content?.statement ? ` — ${clip(node.content.statement, 240)}` : ""}`,
|
|
292
293
|
score: 1,
|
|
@@ -33,6 +33,7 @@ export function fill(template: string, vars: Record<string, string>): string {
|
|
|
33
33
|
return template.replace(/\{\{(\w+)\}\}/g, (_m, k: string) => (k in vars ? vars[k] : ""));
|
|
34
34
|
}
|
|
35
35
|
import { QueryFilters, toVectorizeFilter, standardKeyAllowed } from "./selfquery";
|
|
36
|
+
import { hitQuality } from "./quality";
|
|
36
37
|
import { lexicalPrefilter } from "./lexical";
|
|
37
38
|
import { positionOrder } from "./structural";
|
|
38
39
|
import { STAGES, runStages } from "./stages";
|
|
@@ -404,6 +405,7 @@ export function citations(hits: Hit[]) {
|
|
|
404
405
|
status: h.metadata.status ?? "unknown",
|
|
405
406
|
superseded_by: h.metadata.superseded_by || undefined,
|
|
406
407
|
corpus: h.metadata.corpus || P().publisher.id,
|
|
408
|
+
quality: hitQuality(h.metadata),
|
|
407
409
|
url: publicationUrl(h.metadata),
|
|
408
410
|
snippet: h.text.slice(0, 400),
|
|
409
411
|
score: h.rerank_score ?? h.score,
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// The answer-quality ladder (TODO.rag/13): every citation states what
|
|
2
|
+
// kind of text grounds it, so the answer states how far to trust it.
|
|
3
|
+
// Three rungs, derived from provenance the chunk wire already carries —
|
|
4
|
+
// no new ingest state:
|
|
5
|
+
//
|
|
6
|
+
// verified — the model plane: the chunk rides a primmel data model
|
|
7
|
+
// (model_node/model_version), the Recommendation's semantics are
|
|
8
|
+
// machine-checkable and the golden set measures them (R 60 is the
|
|
9
|
+
// gauge). The answer can be WRONG, but it is wrong against a
|
|
10
|
+
// contract we can see.
|
|
11
|
+
// curated — the edited corpus: Metanorma-authored documents
|
|
12
|
+
// (mn-samples-oiml and the editors' own), clause-boundary chunks,
|
|
13
|
+
// enrichment applied.
|
|
14
|
+
// ocr — the experimental OCR corpus: the broad coverage lane,
|
|
15
|
+
// text recovered from scans; quote anchors may wobble, tables can
|
|
16
|
+
// be mangled. Useful, and marked as experimental on purpose.
|
|
17
|
+
//
|
|
18
|
+
// The answer's tier is the WORST rung its citations stand on: one OCR
|
|
19
|
+
// citation makes the whole answer experimental, because the reader
|
|
20
|
+
// cannot tell which sentence leaned on which chunk.
|
|
21
|
+
|
|
22
|
+
import type { ChunkMeta } from "../../shared/chunk.ts";
|
|
23
|
+
|
|
24
|
+
export type SourceQuality = "verified" | "curated" | "ocr";
|
|
25
|
+
|
|
26
|
+
const ORDER: Record<SourceQuality, number> = { verified: 0, curated: 1, ocr: 2 };
|
|
27
|
+
|
|
28
|
+
export function hitQuality(m: ChunkMeta): SourceQuality {
|
|
29
|
+
if (m.model_node || m.model_version || m.producer === "primmel") return "verified";
|
|
30
|
+
if (m.tier === "curated") return "curated";
|
|
31
|
+
return "ocr";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function answerQuality(qualities: (SourceQuality | undefined)[]): SourceQuality | null {
|
|
35
|
+
let worst: SourceQuality | null = null;
|
|
36
|
+
for (const q of qualities) {
|
|
37
|
+
if (!q) continue;
|
|
38
|
+
if (!worst || ORDER[q] > ORDER[worst]) worst = q;
|
|
39
|
+
}
|
|
40
|
+
return worst;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The one-line posture the interface renders under the answer. */
|
|
44
|
+
export function qualityNote(q: SourceQuality): string {
|
|
45
|
+
if (q === "verified") return "Grounded in verified sources: this publication's requirements ride a machine-checkable data model.";
|
|
46
|
+
if (q === "curated") return "Grounded in the edited corpus: Metanorma-authored documents, chunked at clause boundaries.";
|
|
47
|
+
return "Partly grounded in experimental OCR text: verify quotations and table values against the official publication.";
|
|
48
|
+
}
|