@memberjunction/ai-vector-dupe 6.2.0-edge.0 → 6.2.0-edge.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 +7 -5
- package/dist/duplicateEntryCheckTypes.d.ts +80 -0
- package/dist/duplicateEntryCheckTypes.d.ts.map +1 -0
- package/dist/duplicateEntryCheckTypes.js +29 -0
- package/dist/duplicateEntryCheckTypes.js.map +1 -0
- package/dist/duplicateRecordDetector.d.ts +153 -13
- package/dist/duplicateRecordDetector.d.ts.map +1 -1
- package/dist/duplicateRecordDetector.js +436 -50
- package/dist/duplicateRecordDetector.js.map +1 -1
- package/dist/entryCheckDeadline.d.ts +73 -0
- package/dist/entryCheckDeadline.d.ts.map +1 -0
- package/dist/entryCheckDeadline.js +118 -0
- package/dist/entryCheckDeadline.js.map +1 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/reasoning/DecisionReasoningProvider.d.ts +177 -0
- package/dist/reasoning/DecisionReasoningProvider.d.ts.map +1 -0
- package/dist/reasoning/DecisionReasoningProvider.js +306 -0
- package/dist/reasoning/DecisionReasoningProvider.js.map +1 -0
- package/dist/reasoning/DecisionThenPromptReasoningProvider.d.ts +88 -0
- package/dist/reasoning/DecisionThenPromptReasoningProvider.d.ts.map +1 -0
- package/dist/reasoning/DecisionThenPromptReasoningProvider.js +159 -0
- package/dist/reasoning/DecisionThenPromptReasoningProvider.js.map +1 -0
- package/dist/reasoning/DuplicateReasoningProvider.d.ts +12 -6
- package/dist/reasoning/DuplicateReasoningProvider.d.ts.map +1 -1
- package/dist/reasoning/DuplicateReasoningProvider.js +12 -6
- package/dist/reasoning/DuplicateReasoningProvider.js.map +1 -1
- package/dist/reasoning/DuplicateReasoningTypes.d.ts +21 -2
- package/dist/reasoning/DuplicateReasoningTypes.d.ts.map +1 -1
- package/dist/reasoning/MatchedSetDeltaBuilder.d.ts +17 -3
- package/dist/reasoning/MatchedSetDeltaBuilder.d.ts.map +1 -1
- package/dist/reasoning/MatchedSetDeltaBuilder.js +49 -2
- package/dist/reasoning/MatchedSetDeltaBuilder.js.map +1 -1
- package/package.json +14 -14
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
| `@memberjunction/ai-vectordb` | Vector database abstraction (query, hybrid search) |
|
|
61
61
|
| `@memberjunction/ai-vectors` | `VectorBase` base class with metadata and RunView helpers |
|
|
62
62
|
| `@memberjunction/ai-vector-sync` | `EntityVectorSyncer` for record vectorization, template parsing |
|
|
63
|
-
| `@memberjunction/ai-prompts` | Runs the reasoning prompt in `'Prompt'` mode (`PromptReasoningProvider`) |
|
|
63
|
+
| `@memberjunction/ai-prompts` | Runs the reasoning prompt in `'Prompt'` mode (`PromptReasoningProvider`) and the typed decision in the `'Decision'` modes (`AIDecisionRunner`) |
|
|
64
64
|
| `@memberjunction/record-comparison` | Computes the field-level deltas across a matched set that the reasoner judges |
|
|
65
65
|
| `@memberjunction/core` | Core types: `PotentialDuplicateRequest`, `DuplicateDetectionOptions`, etc. |
|
|
66
66
|
| `@memberjunction/core-entities` | Generated entity classes for Duplicate Runs, Lists, Entity Documents (incl. the `*Reasoning*` / `AutomationLevel` columns) |
|
|
@@ -253,20 +253,22 @@ All reasoning configuration lives on the `MJ: Entity Documents` record, per enti
|
|
|
253
253
|
| Field | Type | Default | Purpose |
|
|
254
254
|
|---|---|---|---|
|
|
255
255
|
| `EnableLLMReasoning` | `boolean` | `false` | Master switch. Off = vector-only behavior, unchanged. |
|
|
256
|
-
| `ReasoningMode` | `'Prompt' \| 'Agent'` | `'Prompt'` | Which provider runs (see below). |
|
|
256
|
+
| `ReasoningMode` | `'Prompt' \| 'Agent' \| 'Decision' \| 'DecisionThenPrompt'` | `'Prompt'` | Which provider runs (see below). |
|
|
257
257
|
| `ReasoningThreshold` | `number \| null` | `null` | Vector-score gate (0–1). LLM runs only when the set's top score clears this. `null` = reason over any non-empty set. |
|
|
258
258
|
| `ReasoningPromptID` | `string \| null` | -- | The AI Prompt to use in `'Prompt'` mode. Falls back to the seeded "Duplicate Resolution" prompt. |
|
|
259
259
|
| `ReasoningAgentID` | `string \| null` | -- | The AI Agent to use in `'Agent'` mode. Falls back to the seeded "Duplicate Resolution Agent". |
|
|
260
|
-
| `AutomationLevel` | `'ReviewAll' \| 'LLMGated' \| 'AutoMergeAboveAbsolute'` | `'ReviewAll'` | How far automation goes after reasoning (review everything / let the LLM gate review / auto-merge above the absolute threshold). |
|
|
260
|
+
| `AutomationLevel` | `'ReviewAll' \| 'LLMGated' \| 'AutoMergeAboveAbsolute'` | `'ReviewAll'` | How far automation goes after reasoning (review everything / let the LLM gate review / auto-merge a candidate above the absolute threshold whose own verdict is `Merge`). |
|
|
261
261
|
|
|
262
262
|
### The pluggable provider seam
|
|
263
263
|
|
|
264
|
-
Reasoning is delegated through an abstract `DuplicateReasoningProvider`, resolved at runtime via the MJ class factory by `ReasoningMode`.
|
|
264
|
+
Reasoning is delegated through an abstract `DuplicateReasoningProvider`, resolved at runtime via the MJ class factory by `ReasoningMode`. Four providers ship, and all emit the same `DuplicateReasoningOutput`. `Prompt` and `Agent` run the same instruction set, so promoting an entity from `Prompt` to `Agent` is a config change, not a rewrite. The two decision modes put a typed decision model (the seeded "Default Decision" prompt, run through `AIDecisionRunner`) in front of, or in place of, the prompt.
|
|
265
265
|
|
|
266
266
|
| Provider | `@RegisterClass` key | Package | Path |
|
|
267
267
|
|---|---|---|---|
|
|
268
268
|
| `PromptReasoningProvider` | `PROMPT_REASONING_PROVIDER_KEY` (`'Prompt'`) | `@memberjunction/ai-vector-dupe` | Single-shot AI Prompt. Persists `AIPromptRunID`. |
|
|
269
269
|
| `DuplicateReasoningAgentProvider` | `AGENT_REASONING_PROVIDER_KEY` (`'Agent'`) | `@memberjunction/ai-agents` | Orchestrated agent run (unlocks memory-note injection + future context tools). Persists `AIAgentRunID`. |
|
|
270
|
+
| `DecisionReasoningProvider` | `DECISION_REASONING_PROVIDER_KEY` (`'Decision'`) | `@memberjunction/ai-vector-dupe` | One decision call per set, with one Likelihood per candidate. The probability is **calibrated** per decision model (`DUPLICATE_DECISION_CALIBRATION`; override `CalibrationFor` for another model). Recommends only: `Uncertain` (flagged for review) at or above its threshold (a calibrated `0.7` by default, `DEFAULT_UNCERTAIN_ABOVE`), else `NotDuplicate`. A candidate with no calibrated probability (no answer, or a model with no calibration) is `Uncertain`. Never `Merge`, so it never auto-merges. Persists `AIPromptRunID`. |
|
|
271
|
+
| `DecisionThenPromptReasoningProvider` | `DECISION_THEN_PROMPT_REASONING_PROVIDER_KEY` (`'DecisionThenPrompt'`) | `@memberjunction/ai-vector-dupe` | The decision drops candidates below its pre-filter threshold (a calibrated `0.3`, `PRE_FILTER_UNCERTAIN_ABOVE`, which keeps recall), then the `'Prompt'` provider reasons over the survivors and may recommend `Merge`. A candidate with no calibrated probability is kept. A dropped candidate reads `NotDuplicate` and its row points at the decision run. With no survivors the prompt never runs; if the decision fails, every candidate goes to the prompt. Both stages resolve through the class factory, so overrides of `'Decision'` and `'Prompt'` apply inside the chain. |
|
|
270
272
|
|
|
271
273
|
> The Agent provider lives in `@memberjunction/ai-agents`, **not** this package, because `ai-agents` depends on `ai-vector-dupe` -- importing `AgentRunner` here would create a build cycle. It registers against the seam under the `'Agent'` key, so the detector resolves it via the class factory with no static import back into the pipeline. Registration is handled by the class-registration manifest (no `Load*()` helper needed).
|
|
272
274
|
|
|
@@ -295,7 +297,7 @@ export class MyReasoningProvider extends DuplicateReasoningProvider {
|
|
|
295
297
|
|
|
296
298
|
### Per-candidate verdicts
|
|
297
299
|
|
|
298
|
-
A matched set is the top-K neighbors of one source record, so it routinely mixes true duplicates with false positives. The reasoner therefore returns a verdict **per candidate** (`DuplicateReasoningOutput.CandidateVerdicts`), each judged independently against the source -- a false-positive candidate reads `NotDuplicate` even when another candidate in the same set is a confident `Merge`. The detector stamps each candidate's own verdict onto its match row; the set-level `Recommendation`/`Confidence` are *derived* values used
|
|
300
|
+
A matched set is the top-K neighbors of one source record, so it routinely mixes true duplicates with false positives. The reasoner therefore returns a verdict **per candidate** (`DuplicateReasoningOutput.CandidateVerdicts`), each judged independently against the source -- a false-positive candidate reads `NotDuplicate` even when another candidate in the same set is a confident `Merge`. The detector stamps each candidate's own verdict onto its match row; the set-level `Recommendation`/`Confidence` are *derived* values used for the group's dominant display. Auto-merge (`AutoMergeAboveAbsolute`) requires both the set-level recommendation and the candidate's own verdict (carried on `PotentialDuplicate.ReasoningRecommendation`) to be `Merge`, so a candidate is never merged because another candidate in its set is a duplicate.
|
|
299
301
|
|
|
300
302
|
The output also carries a proposed `SurvivorRecordID` and per-field survivor choices (`FieldChoices`) that feed `Metadata.MergeRecords` at merge time. A `null` `Confidence` means the model returned no usable confidence and must be rendered/stored as "unknown" -- never conflated with a real `0` (which reads as "confidently NOT a duplicate"). See `DuplicateReasoningTypes` for the full contract.
|
|
301
303
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Options, limits and result types for the entry-time duplicate check,
|
|
3
|
+
* {@link DuplicateRecordDetector.CheckRecordValues}.
|
|
4
|
+
*
|
|
5
|
+
* The check runs while a person enters a new record. It only flags: it never blocks a save and
|
|
6
|
+
* never merges.
|
|
7
|
+
*
|
|
8
|
+
* @module @memberjunction/ai-vector-dupe
|
|
9
|
+
*/
|
|
10
|
+
import type { DuplicateDetectionOptions } from '@memberjunction/core';
|
|
11
|
+
/**
|
|
12
|
+
* The most time one entry-time check may take on the server, in milliseconds. The form stops
|
|
13
|
+
* waiting at its own budget (`DUPLICATE_ENTRY_CHECK_BUDGET_MS` in `@memberjunction/ng-base-forms`,
|
|
14
|
+
* 1500 ms); this is that budget plus a margin for the round trip, so the server stops working on a
|
|
15
|
+
* check soon after the form has given up on it. A check that runs out is `Failed`, and flags
|
|
16
|
+
* nothing.
|
|
17
|
+
*/
|
|
18
|
+
export declare const DUPLICATE_ENTRY_CHECK_SERVER_BUDGET_MS = 2000;
|
|
19
|
+
/**
|
|
20
|
+
* The most characters of one field's text the check uses. Longer entered text is cut before the
|
|
21
|
+
* template renders it (so before it is embedded), and every field value in the decision state is
|
|
22
|
+
* cut to it, the candidates' stored values included.
|
|
23
|
+
*/
|
|
24
|
+
export declare const DUPLICATE_ENTRY_CHECK_MAX_FIELD_TEXT_LENGTH = 500;
|
|
25
|
+
/**
|
|
26
|
+
* The most differing fields the decision state carries. The fields the person entered come first;
|
|
27
|
+
* the rest are dropped.
|
|
28
|
+
*/
|
|
29
|
+
export declare const DUPLICATE_ENTRY_CHECK_MAX_DECISION_FIELDS = 40;
|
|
30
|
+
/** Options for {@link DuplicateRecordDetector.CheckRecordValues}. */
|
|
31
|
+
export interface DuplicateEntryCheckOptions extends DuplicateDetectionOptions {
|
|
32
|
+
/**
|
|
33
|
+
* The check's time budget, in milliseconds. Defaults to
|
|
34
|
+
* {@link DUPLICATE_ENTRY_CHECK_SERVER_BUDGET_MS}. It bounds every step: the template, the
|
|
35
|
+
* embedding, the vector query, both RunViews and the decision call.
|
|
36
|
+
*/
|
|
37
|
+
TimeoutMS?: number;
|
|
38
|
+
/** Stops the check when aborted. A stopped check is `Failed` and flags nothing. */
|
|
39
|
+
CancellationToken?: AbortSignal;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* How an entry-time duplicate check ended.
|
|
43
|
+
* - `Checked`: the check ran. `Candidates` holds the flagged records, and may be empty.
|
|
44
|
+
* - `NotConfigured`: the entity has no Active entity document with `EnableLLMReasoning` on whose
|
|
45
|
+
* `ReasoningMode` is `'Decision'` or `'DecisionThenPrompt'`, so the check is off for it. Nothing
|
|
46
|
+
* else ran.
|
|
47
|
+
* - `Failed`: the check could not finish, or ran out of its budget. `ErrorMessage` says why, and
|
|
48
|
+
* nothing is flagged.
|
|
49
|
+
*/
|
|
50
|
+
export type DuplicateEntryCheckStatus = 'Checked' | 'NotConfigured' | 'Failed';
|
|
51
|
+
/** An existing record the check flags as a possible duplicate of the values being entered. */
|
|
52
|
+
export interface DuplicateEntryCandidate {
|
|
53
|
+
/**
|
|
54
|
+
* The candidate's primary key as a compact URL segment (`CompositeKey.ToCompactURLSegment`): the
|
|
55
|
+
* bare value for a single-column key, `F1|v1||F2|v2` for a composite one.
|
|
56
|
+
* `CompositeKey.FromURLSegment` reads it back.
|
|
57
|
+
*/
|
|
58
|
+
RecordID: string;
|
|
59
|
+
/** The candidate's name-field values, or its key when the person may not read a name. */
|
|
60
|
+
DisplayName: string;
|
|
61
|
+
/** The vector similarity score that surfaced the candidate. */
|
|
62
|
+
VectorScore: number;
|
|
63
|
+
/**
|
|
64
|
+
* The decision's probability that the candidate is the same real-world entity as the values being
|
|
65
|
+
* entered, or null when the decision gave no answer for it (such a candidate is flagged).
|
|
66
|
+
*/
|
|
67
|
+
Probability: number | null;
|
|
68
|
+
}
|
|
69
|
+
/** The outcome of one entry-time duplicate check. */
|
|
70
|
+
export interface DuplicateEntryCheckResult {
|
|
71
|
+
/** How the check ended. */
|
|
72
|
+
Status: DuplicateEntryCheckStatus;
|
|
73
|
+
/** Why the check failed, when `Status` is `'Failed'`. */
|
|
74
|
+
ErrorMessage?: string;
|
|
75
|
+
/** The flagged candidates, most probable first. Empty unless `Status` is `'Checked'`. */
|
|
76
|
+
Candidates: DuplicateEntryCandidate[];
|
|
77
|
+
/** How long the check took on the server, in milliseconds. */
|
|
78
|
+
ElapsedMs: number;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=duplicateEntryCheckTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duplicateEntryCheckTypes.d.ts","sourceRoot":"","sources":["../src/duplicateEntryCheckTypes.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AAEtE;;;;;;GAMG;AACH,eAAO,MAAM,sCAAsC,OAAO,CAAC;AAE3D;;;;GAIG;AACH,eAAO,MAAM,2CAA2C,MAAM,CAAC;AAE/D;;;GAGG;AACH,eAAO,MAAM,yCAAyC,KAAK,CAAC;AAE5D,qEAAqE;AACrE,MAAM,WAAW,0BAA2B,SAAQ,yBAAyB;IACzE;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,iBAAiB,CAAC,EAAE,WAAW,CAAC;CACnC;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,yBAAyB,GAAG,SAAS,GAAG,eAAe,GAAG,QAAQ,CAAC;AAE/E,8FAA8F;AAC9F,MAAM,WAAW,uBAAuB;IACpC;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,yFAAyF;IACzF,WAAW,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,qDAAqD;AACrD,MAAM,WAAW,yBAAyB;IACtC,2BAA2B;IAC3B,MAAM,EAAE,yBAAyB,CAAC;IAClC,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yFAAyF;IACzF,UAAU,EAAE,uBAAuB,EAAE,CAAC;IACtC,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;CACrB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Options, limits and result types for the entry-time duplicate check,
|
|
3
|
+
* {@link DuplicateRecordDetector.CheckRecordValues}.
|
|
4
|
+
*
|
|
5
|
+
* The check runs while a person enters a new record. It only flags: it never blocks a save and
|
|
6
|
+
* never merges.
|
|
7
|
+
*
|
|
8
|
+
* @module @memberjunction/ai-vector-dupe
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* The most time one entry-time check may take on the server, in milliseconds. The form stops
|
|
12
|
+
* waiting at its own budget (`DUPLICATE_ENTRY_CHECK_BUDGET_MS` in `@memberjunction/ng-base-forms`,
|
|
13
|
+
* 1500 ms); this is that budget plus a margin for the round trip, so the server stops working on a
|
|
14
|
+
* check soon after the form has given up on it. A check that runs out is `Failed`, and flags
|
|
15
|
+
* nothing.
|
|
16
|
+
*/
|
|
17
|
+
export const DUPLICATE_ENTRY_CHECK_SERVER_BUDGET_MS = 2000;
|
|
18
|
+
/**
|
|
19
|
+
* The most characters of one field's text the check uses. Longer entered text is cut before the
|
|
20
|
+
* template renders it (so before it is embedded), and every field value in the decision state is
|
|
21
|
+
* cut to it, the candidates' stored values included.
|
|
22
|
+
*/
|
|
23
|
+
export const DUPLICATE_ENTRY_CHECK_MAX_FIELD_TEXT_LENGTH = 500;
|
|
24
|
+
/**
|
|
25
|
+
* The most differing fields the decision state carries. The fields the person entered come first;
|
|
26
|
+
* the rest are dropped.
|
|
27
|
+
*/
|
|
28
|
+
export const DUPLICATE_ENTRY_CHECK_MAX_DECISION_FIELDS = 40;
|
|
29
|
+
//# sourceMappingURL=duplicateEntryCheckTypes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duplicateEntryCheckTypes.js","sourceRoot":"","sources":["../src/duplicateEntryCheckTypes.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,sCAAsC,GAAG,IAAI,CAAC;AAE3D;;;;GAIG;AACH,MAAM,CAAC,MAAM,2CAA2C,GAAG,GAAG,CAAC;AAE/D;;;GAGG;AACH,MAAM,CAAC,MAAM,yCAAyC,GAAG,EAAE,CAAC"}
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
*
|
|
15
15
|
* @module @memberjunction/ai-vector-dupe
|
|
16
16
|
*/
|
|
17
|
-
import {
|
|
17
|
+
import { AIEmbeddingRunner } from "@memberjunction/ai-prompts";
|
|
18
|
+
import { PotentialDuplicateRequest, PotentialDuplicateResponse, CompositeKey, UserInfo, BaseEntity, PotentialDuplicateResult, EntityInfo, EntityFieldInfo, PotentialDuplicate, DuplicateDetectionOptions } from "@memberjunction/core";
|
|
18
19
|
import { BaseResponse } from "@memberjunction/ai-vectordb";
|
|
19
20
|
import { MJDuplicateRunDetailEntity, MJDuplicateRunDetailMatchEntity, MJDuplicateRunEntity, MJEntityDocumentEntity, MJListEntity } from "@memberjunction/core-entities";
|
|
20
21
|
import { VectorBase } from "@memberjunction/ai-vectors";
|
|
@@ -22,6 +23,9 @@ import { EntityDocumentTemplateParser } from "@memberjunction/entity-documents";
|
|
|
22
23
|
import type { MJTemplateEntityExtended } from "@memberjunction/core-entities";
|
|
23
24
|
import { DuplicateReasoningProvider } from "./reasoning/DuplicateReasoningProvider.js";
|
|
24
25
|
import { DuplicateReasoningInput, DuplicateReasoningOutput, ReasoningFieldDelta } from "./reasoning/DuplicateReasoningTypes.js";
|
|
26
|
+
import type { DecisionReasoningProvider } from "./reasoning/DecisionReasoningProvider.js";
|
|
27
|
+
import { DuplicateEntryCheckOptions, DuplicateEntryCheckResult } from "./duplicateEntryCheckTypes.js";
|
|
28
|
+
import { EntryCheckDeadline } from "./entryCheckDeadline.js";
|
|
25
29
|
/**
|
|
26
30
|
* Internal result from querying duplicates for a single source record.
|
|
27
31
|
*/
|
|
@@ -52,17 +56,23 @@ interface SetReasoning {
|
|
|
52
56
|
* - List-based batch detection (getDuplicateRecords)
|
|
53
57
|
* - View/filter/full-entity batch detection (vector-first approach)
|
|
54
58
|
* - Single-record duplicate check (CheckSingleRecord)
|
|
59
|
+
* - Entry-time check of a new record's unsaved values, flag only (CheckRecordValues)
|
|
55
60
|
* - Hybrid search via RRF when vector DB supports it
|
|
56
61
|
* - Optional post-retrieval reranking via MJ's BaseReranker
|
|
57
62
|
* - Configurable topK, thresholds, and progress reporting
|
|
58
63
|
*/
|
|
59
64
|
export declare class DuplicateRecordDetector extends VectorBase {
|
|
60
65
|
private vectorDB;
|
|
61
|
-
private
|
|
66
|
+
private _embeddingRunner;
|
|
67
|
+
private embeddingModelID;
|
|
68
|
+
/**
|
|
69
|
+
* Protected getter/setter for the AIEmbeddingRunner instance used by duplicate detection.
|
|
70
|
+
*/
|
|
71
|
+
protected get EmbeddingRunner(): AIEmbeddingRunner;
|
|
72
|
+
protected set EmbeddingRunner(value: AIEmbeddingRunner);
|
|
62
73
|
/**
|
|
63
74
|
* The embedding model's API identifier (e.g. 'Xenova/gte-small', 'text-embedding-3-small'),
|
|
64
|
-
* resolved from the entity document's AIModel.
|
|
65
|
-
* providers (which load the named ONNX pipeline) and honored by cloud providers.
|
|
75
|
+
* resolved from the entity document's AIModel.
|
|
66
76
|
*/
|
|
67
77
|
private embeddingModelAPIName;
|
|
68
78
|
/** The Pinecone/pgvector/Qdrant index name resolved from the entity document's VectorIndex */
|
|
@@ -110,6 +120,122 @@ export declare class DuplicateRecordDetector extends VectorBase {
|
|
|
110
120
|
* Embeds the record and queries for matches directly.
|
|
111
121
|
*/
|
|
112
122
|
CheckSingleRecord(EntityDocumentID: string, RecordID: CompositeKey, Options?: DuplicateDetectionOptions, ContextUser?: UserInfo): Promise<PotentialDuplicateResult>;
|
|
123
|
+
/**
|
|
124
|
+
* Check values a person is entering for a new record against the entity's existing records, and
|
|
125
|
+
* flag the plausible duplicates. It only flags: nothing is saved, merged or blocked.
|
|
126
|
+
*
|
|
127
|
+
* 1. **The switch.** The check runs only for an entity with an Active entity document that has
|
|
128
|
+
* `EnableLLMReasoning` on and whose `ReasoningMode` is `'Decision'` or `'DecisionThenPrompt'`
|
|
129
|
+
* (see {@link FindEntryCheckDocument}). Without one the result is `NotConfigured` and nothing
|
|
130
|
+
* else runs.
|
|
131
|
+
* 2. **Candidates.** The values, each text cut to {@link DUPLICATE_ENTRY_CHECK_MAX_FIELD_TEXT_LENGTH},
|
|
132
|
+
* become an unsaved entity object, rendered by the document's template, embedded, and queried
|
|
133
|
+
* with the same TopK and threshold as {@link CheckSingleRecord}.
|
|
134
|
+
* 3. **Permission.** The vector index does not know who is asking, so the candidates are narrowed
|
|
135
|
+
* to those the context user can read, with one RunView as that user.
|
|
136
|
+
* 4. **Decision.** One {@link DecisionReasoningProvider.DecideCandidates} call over the readable
|
|
137
|
+
* candidates, in either mode: the prompt half of `'DecisionThenPrompt'` is too slow for entry,
|
|
138
|
+
* and it can recommend a merge. Its state is bounded by
|
|
139
|
+
* {@link DUPLICATE_ENTRY_CHECK_MAX_DECISION_FIELDS} and the field-text limit. A candidate is
|
|
140
|
+
* flagged when the provider bands it `Uncertain`, by its own threshold, on the probability
|
|
141
|
+
* calibrated for the model that answered. A candidate the decision gave no answer for is
|
|
142
|
+
* flagged. A failed decision flags nothing, and neither does a decision from a model with no
|
|
143
|
+
* calibration: its probabilities can't be banded, and flagging every candidate would be the
|
|
144
|
+
* vector threshold alone. Both give a `Failed` result with the reason.
|
|
145
|
+
*
|
|
146
|
+
* **Budget.** The whole check is bounded by `options.TimeoutMS`
|
|
147
|
+
* ({@link DUPLICATE_ENTRY_CHECK_SERVER_BUDGET_MS} by default) and by `options.CancellationToken`.
|
|
148
|
+
* No step starts once either has fired, the check stops waiting for a running step, and the
|
|
149
|
+
* decision call receives both, so the model call is aborted. A stopped check is `Failed`.
|
|
150
|
+
*
|
|
151
|
+
* Never throws: any failure is a `Failed` result with the reason.
|
|
152
|
+
*
|
|
153
|
+
* @param entityName the entity the new record belongs to
|
|
154
|
+
* @param values the entered values by field name; fields the entity does not have are ignored
|
|
155
|
+
* @param contextUser the person entering the record. Required: the candidates are narrowed to the
|
|
156
|
+
* records this user can read, and without a user the check fails rather than skip that step.
|
|
157
|
+
* @param options overrides for TopK and the potential-match threshold, the budget and cancellation
|
|
158
|
+
* @returns the flagged candidates, most probable first, or why there are none
|
|
159
|
+
*/
|
|
160
|
+
CheckRecordValues(entityName: string, values: Record<string, unknown>, contextUser: UserInfo, options?: DuplicateEntryCheckOptions): Promise<DuplicateEntryCheckResult>;
|
|
161
|
+
/**
|
|
162
|
+
* Render one record with the entity document's template, embed it, and query the vector index
|
|
163
|
+
* for its candidates. Shared by {@link CheckSingleRecord} (a saved record) and
|
|
164
|
+
* {@link CheckRecordValues} (an unsaved one).
|
|
165
|
+
*
|
|
166
|
+
* @param deadline bounds each step, for the entry-time check; without one the steps are unbounded
|
|
167
|
+
* @returns the record's query result, or null when the query produced none
|
|
168
|
+
*/
|
|
169
|
+
protected QueryCandidatesForRecord(record: BaseEntity, entityDocument: MJEntityDocumentEntity, options: DuplicateDetectionOptions, contextUser?: UserInfo, deadline?: EntryCheckDeadline): Promise<RecordQueryResult | null>;
|
|
170
|
+
/**
|
|
171
|
+
* The entity document that turns the entry-time check on for an entity: an Active document with
|
|
172
|
+
* `EnableLLMReasoning` on whose `ReasoningMode` is `'Decision'` or `'DecisionThenPrompt'`. The
|
|
173
|
+
* check makes a decision-model call on every pause in typing, so switching reasoning off on the
|
|
174
|
+
* document turns the check off too, as it turns off reasoning in batch runs
|
|
175
|
+
* ({@link IsReasoningGateOpen}). When several qualify, the oldest wins (earliest
|
|
176
|
+
* `__mj_CreatedAt`, then lowest ID), so adding a document never silently changes which one an
|
|
177
|
+
* entity uses.
|
|
178
|
+
*
|
|
179
|
+
* @returns the document, or null when the check is not configured for the entity
|
|
180
|
+
*/
|
|
181
|
+
protected FindEntryCheckDocument(entityName: string): Promise<MJEntityDocumentEntity | null>;
|
|
182
|
+
/**
|
|
183
|
+
* Build an unsaved entity object holding the entered values, so the entity document's template
|
|
184
|
+
* renders it as it renders a saved record. Values for fields the entity does not have are ignored,
|
|
185
|
+
* and text longer than {@link DUPLICATE_ENTRY_CHECK_MAX_FIELD_TEXT_LENGTH} is cut, so the
|
|
186
|
+
* template, the embedding and the decision state never see more of a field than that.
|
|
187
|
+
*/
|
|
188
|
+
protected BuildUnsavedRecord(entityInfo: EntityInfo, values: Record<string, unknown>, contextUser: UserInfo): Promise<BaseEntity>;
|
|
189
|
+
/**
|
|
190
|
+
* The display names of the candidates the context user can read, from one RunView over the
|
|
191
|
+
* candidate keys run as that user, so entity permissions and row-level security apply. A
|
|
192
|
+
* candidate missing from the map must not be shown. When the RunView fails the map is empty:
|
|
193
|
+
* a candidate is shown only when the user is known to be able to read it.
|
|
194
|
+
*
|
|
195
|
+
* @param contextUser the person the candidates are narrowed for; the RunView runs as this user
|
|
196
|
+
* @returns display name by normalized compact record id ({@link NormalizeUUID})
|
|
197
|
+
*/
|
|
198
|
+
protected LoadReadableCandidateNames(candidates: PotentialDuplicate[], entityInfo: EntityInfo, contextUser: UserInfo): Promise<Map<string, string>>;
|
|
199
|
+
/**
|
|
200
|
+
* The decision provider the entry-time check asks: whatever the class factory holds for the
|
|
201
|
+
* `'Decision'` mode, which is {@link DecisionReasoningProvider} unless an app registers a
|
|
202
|
+
* subclass. Null when that registration is not a decision provider.
|
|
203
|
+
*/
|
|
204
|
+
protected ResolveEntryDecisionProvider(): DecisionReasoningProvider | null;
|
|
205
|
+
/**
|
|
206
|
+
* The fields whose values make up a record's display name: every `IsNameField` field in
|
|
207
|
+
* Sequence order, or the entity's single `NameField` when none is flagged.
|
|
208
|
+
*/
|
|
209
|
+
protected DisplayNameFields(entityInfo: EntityInfo): EntityFieldInfo[];
|
|
210
|
+
/**
|
|
211
|
+
* The steps of {@link CheckRecordValues} after it has recorded the start time, each bounded by
|
|
212
|
+
* the deadline. May throw, {@link EntryCheckStoppedError} included.
|
|
213
|
+
*/
|
|
214
|
+
private runEntryCheck;
|
|
215
|
+
/** Narrow a query result's candidates, in place, to those the context user can read. */
|
|
216
|
+
private keepReadableCandidates;
|
|
217
|
+
/**
|
|
218
|
+
* Ask the decision about the readable candidates, with the unsaved record's own values as the
|
|
219
|
+
* source, and flag the ones the provider bands `Uncertain`. The decision call gets the deadline's
|
|
220
|
+
* signal and remaining time, so the model call is aborted when the check must stop.
|
|
221
|
+
*/
|
|
222
|
+
private decideEntryCandidates;
|
|
223
|
+
/**
|
|
224
|
+
* The entry-time decision's input, bounded: at most {@link DUPLICATE_ENTRY_CHECK_MAX_DECISION_FIELDS}
|
|
225
|
+
* differing fields, the ones the person entered first, and every value and label cut to
|
|
226
|
+
* {@link DUPLICATE_ENTRY_CHECK_MAX_FIELD_TEXT_LENGTH}. A candidate's stored values are cut too:
|
|
227
|
+
* a long Notes field on an existing record would otherwise reach the model in full.
|
|
228
|
+
*/
|
|
229
|
+
protected BoundEntryDecisionInput(input: DuplicateReasoningInput): DuplicateReasoningInput;
|
|
230
|
+
/**
|
|
231
|
+
* The candidates the provider bands `Uncertain` (they cannot be ruled out), most probable first.
|
|
232
|
+
* The decision answers in input order, so each answer lines up with the query's candidate at the
|
|
233
|
+
* same index.
|
|
234
|
+
*/
|
|
235
|
+
private flagEntryCandidates;
|
|
236
|
+
/** A row's name-field values joined with spaces; empty when it has none the user may read. */
|
|
237
|
+
private rowDisplayName;
|
|
238
|
+
private entryCheckResult;
|
|
113
239
|
/**
|
|
114
240
|
* Process a single outer batch of record IDs through the full duplicate detection pipeline.
|
|
115
241
|
*
|
|
@@ -136,7 +262,7 @@ export declare class DuplicateRecordDetector extends VectorBase {
|
|
|
136
262
|
* @param contextUser - The user context for entity operations
|
|
137
263
|
* @returns Combined results and match count for this batch
|
|
138
264
|
*/
|
|
139
|
-
private
|
|
265
|
+
private processBatch;
|
|
140
266
|
/**
|
|
141
267
|
* Load the IDs of records to check, using the appropriate strategy based on the request.
|
|
142
268
|
* Returns an array of primary key value strings.
|
|
@@ -346,11 +472,19 @@ export declare class DuplicateRecordDetector extends VectorBase {
|
|
|
346
472
|
* independently), so a false-positive candidate reads NotDuplicate even when another candidate
|
|
347
473
|
* in the same set is a confident Merge. Falls back to the set-level summary only when the
|
|
348
474
|
* reasoner returned no per-candidate verdict for this record. The proposed survivor + field
|
|
349
|
-
* map stay set-level (they describe the merge of the set's true duplicates).
|
|
475
|
+
* map stay set-level (they describe the merge of the set's true duplicates). The run id is
|
|
476
|
+
* the set's, unless this candidate's verdict came from a run of its own.
|
|
350
477
|
*
|
|
351
478
|
* @param candidateRecordID this candidate's record id (matches the input candidate RecordID)
|
|
352
479
|
*/
|
|
353
480
|
protected applyReasoningToMatch(match: MJDuplicateRunDetailMatchEntity, reasoning: DuplicateReasoningOutput, candidateRecordID: string): void;
|
|
481
|
+
/**
|
|
482
|
+
* Point the match row at the run that produced its verdict: the verdict's own prompt run when
|
|
483
|
+
* it carries one (a candidate `DecisionThenPrompt`'s decision dropped), else the set's run.
|
|
484
|
+
*/
|
|
485
|
+
private applyRunIDsToMatch;
|
|
486
|
+
/** This candidate's own verdict, matched by record id, or undefined when the reasoner returned none for it. */
|
|
487
|
+
private findCandidateVerdict;
|
|
354
488
|
/**
|
|
355
489
|
* Run LLM reasoning for one source record's matched set, ONCE, only when:
|
|
356
490
|
* 1. the entity document has EnableLLMReasoning = true, AND
|
|
@@ -397,8 +531,11 @@ export declare class DuplicateRecordDetector extends VectorBase {
|
|
|
397
531
|
/**
|
|
398
532
|
* Assemble the reasoning input for a matched set: source description, candidate
|
|
399
533
|
* descriptions, and the differing-field deltas loaded for the whole set.
|
|
534
|
+
*
|
|
535
|
+
* @param unsavedSource the source record when it is not saved yet (the entry-time check): its
|
|
536
|
+
* in-memory values stand in for the database row the delta load cannot find
|
|
400
537
|
*/
|
|
401
|
-
protected BuildReasoningInput(qr: RecordQueryResult, entityInfo: EntityInfo, entityDocument: MJEntityDocumentEntity, contextUser?: UserInfo): Promise<DuplicateReasoningInput>;
|
|
538
|
+
protected BuildReasoningInput(qr: RecordQueryResult, entityInfo: EntityInfo, entityDocument: MJEntityDocumentEntity, contextUser?: UserInfo, unsavedSource?: BaseEntity): Promise<DuplicateReasoningInput>;
|
|
402
539
|
/**
|
|
403
540
|
* Resolve a record's display label: prefer the name loaded from the record (via the delta
|
|
404
541
|
* builder), then a secondary fallback (e.g. a candidate's vector-metadata name), then the
|
|
@@ -409,11 +546,12 @@ export declare class DuplicateRecordDetector extends VectorBase {
|
|
|
409
546
|
/** Extract a display label from a candidate's vector metadata snapshot, if present. */
|
|
410
547
|
protected reasoningLabel(metadata?: Record<string, string>): string | null;
|
|
411
548
|
/**
|
|
412
|
-
* Carry the set-level verdict + resolved survivor field map onto the result
|
|
413
|
-
*
|
|
414
|
-
*
|
|
415
|
-
*
|
|
416
|
-
*
|
|
549
|
+
* Carry the set-level verdict + resolved survivor field map onto the result, and each
|
|
550
|
+
* candidate's own verdict onto its {@link PotentialDuplicate}, so the auto-merge step
|
|
551
|
+
* (AutoMergeAboveAbsolute) can consult both recommendations and apply the literal
|
|
552
|
+
* {FieldName, Value} overrides via {@link RecordMergeRequest.FieldMap}. The UI still reads
|
|
553
|
+
* the persisted per-row {@link MJDuplicateRunDetailMatchEntity.LLMProposedFieldMap} (the raw
|
|
554
|
+
* choices) and lets the reviewer override before a manual merge.
|
|
417
555
|
*/
|
|
418
556
|
protected applyReasoningToResult(result: PotentialDuplicateResult, output: DuplicateReasoningOutput, fieldMap: {
|
|
419
557
|
FieldName: string;
|
|
@@ -432,7 +570,9 @@ export declare class DuplicateRecordDetector extends VectorBase {
|
|
|
432
570
|
* Reasoning path (EnableLLMReasoning = true): `AutomationLevel` governs.
|
|
433
571
|
* - ReviewAll / LLMGated → never auto-merge (everything goes to human review).
|
|
434
572
|
* - AutoMergeAboveAbsolute → at/above the absolute threshold AND the set's LLM
|
|
435
|
-
* recommendation is 'Merge'.
|
|
573
|
+
* recommendation is 'Merge' AND this candidate's own verdict is 'Merge'. A set-level
|
|
574
|
+
* 'Merge' only says that SOME candidate is a duplicate, so it never merges a candidate
|
|
575
|
+
* the reasoner judged otherwise, or returned no verdict for.
|
|
436
576
|
*/
|
|
437
577
|
protected IsAutoMergeEligible(dupe: PotentialDuplicate, dupeResult: PotentialDuplicateResult, entityDocument: MJEntityDocumentEntity, absoluteThreshold: number): boolean;
|
|
438
578
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"duplicateRecordDetector.d.ts","sourceRoot":"","sources":["../src/duplicateRecordDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EACH,yBAAyB,EACzB,0BAA0B,EAC1B,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,wBAAwB,EAIxB,UAAU,EACV,kBAAkB,EAClB,yBAAyB,EAE5B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,YAAY,EAA6C,MAAM,6BAA6B,CAAC;AAEtG,OAAO,EACH,0BAA0B,EAC1B,+BAA+B,EAC/B,oBAAoB,EACpB,sBAAsB,EACtB,YAAY,EAEf,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"duplicateRecordDetector.d.ts","sourceRoot":"","sources":["../src/duplicateRecordDetector.ts"],"names":[],"mappings":"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"}
|