@qvac/sdk 0.10.0 → 0.10.1
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/NOTICE +28 -28
- package/dist/examples/{llamacpp-native-tools.js → tools/llamacpp-native-tools.js} +4 -47
- package/dist/examples/tools/llamacpp-tools-harmony-multiturn.d.ts +2 -0
- package/dist/examples/tools/llamacpp-tools-harmony-multiturn.js +81 -0
- package/dist/examples/{llamacpp-tools-pythonic.js → tools/llamacpp-tools-pythonic.js} +1 -20
- package/dist/examples/tools/shared.d.ts +21 -0
- package/dist/examples/tools/shared.js +42 -0
- package/dist/models/registry/models.d.ts +312 -1231
- package/dist/models/registry/models.js +2081 -3025
- package/dist/models/update-models/registry.d.ts +1 -0
- package/dist/models/update-models/registry.js +19 -1
- package/dist/schemas/common.d.ts +1 -0
- package/dist/schemas/completion-stream.d.ts +4 -0
- package/dist/schemas/completion-stream.js +2 -1
- package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +1 -0
- package/dist/server/bare/plugins/llamacpp-completion/plugin.js +3 -3
- package/dist/server/bare/plugins/nmtcpp-translation/plugin.js +1 -82
- package/dist/server/bare/plugins/nmtcpp-translation/resolve-vocab.d.ts +32 -0
- package/dist/server/bare/plugins/nmtcpp-translation/resolve-vocab.js +117 -0
- package/dist/server/utils/completion-normalizer.js +168 -56
- package/dist/server/utils/tools/dialect.js +2 -0
- package/dist/server/utils/tools/parser.js +6 -0
- package/dist/server/utils/tools/parsers/harmony.d.ts +4 -0
- package/dist/server/utils/tools/parsers/harmony.js +59 -0
- package/package.json +1 -1
- /package/dist/examples/{llamacpp-native-tools.d.ts → tools/llamacpp-native-tools.d.ts} +0 -0
- /package/dist/examples/{llamacpp-tools-pythonic.d.ts → tools/llamacpp-tools-pythonic.d.ts} +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CollectOptions, ProcessedModel } from "./types";
|
|
2
2
|
export { processRegistryModel, extractModelName, toHexString, } from "./processing";
|
|
3
3
|
export declare function collectModels(options?: CollectOptions): Promise<ProcessedModel[]>;
|
|
4
|
+
export declare function deduplicateModels(models: ProcessedModel[], showDuplicates: boolean): ProcessedModel[];
|
|
4
5
|
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -32,7 +32,20 @@ export async function collectModels(options = {}) {
|
|
|
32
32
|
}
|
|
33
33
|
return deduplicateModels(withCompanions, showDuplicates);
|
|
34
34
|
}
|
|
35
|
-
function deduplicateModels(models, showDuplicates) {
|
|
35
|
+
export function deduplicateModels(models, showDuplicates) {
|
|
36
|
+
// Paths referenced as companion files in any companion set. Dropping one of
|
|
37
|
+
// these on sha256 collision would leave its companion set without a
|
|
38
|
+
// standalone RegistryItem that `getModelByPath()` can resolve, causing
|
|
39
|
+
// recursive registry resolutions (e.g. the Bergamot shared vocab) to fall
|
|
40
|
+
// into the metadata-less fallback where `expectedSize` is `0`.
|
|
41
|
+
const companionReferencedPaths = new Set();
|
|
42
|
+
for (const m of models) {
|
|
43
|
+
if (!m.companionSet)
|
|
44
|
+
continue;
|
|
45
|
+
for (const f of m.companionSet.files) {
|
|
46
|
+
companionReferencedPaths.add(`${f.registrySource}:${f.registryPath}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
36
49
|
const seenChecksums = new Map();
|
|
37
50
|
const dedupedModels = [];
|
|
38
51
|
const skipped = [];
|
|
@@ -42,6 +55,11 @@ function deduplicateModels(models, showDuplicates) {
|
|
|
42
55
|
continue;
|
|
43
56
|
}
|
|
44
57
|
if (seenChecksums.has(model.sha256Checksum)) {
|
|
58
|
+
const pathKey = `${model.registrySource}:${model.registryPath}`;
|
|
59
|
+
if (companionReferencedPaths.has(pathKey)) {
|
|
60
|
+
dedupedModels.push(model);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
45
63
|
skipped.push({
|
|
46
64
|
name: model.registryPath,
|
|
47
65
|
checksum: model.sha256Checksum,
|
package/dist/schemas/common.d.ts
CHANGED
|
@@ -3384,6 +3384,7 @@ export declare const requestSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
3384
3384
|
hermes: "hermes";
|
|
3385
3385
|
pythonic: "pythonic";
|
|
3386
3386
|
json: "json";
|
|
3387
|
+
harmony: "harmony";
|
|
3387
3388
|
}>>;
|
|
3388
3389
|
responseFormat: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
3389
3390
|
type: z.ZodLiteral<"text">;
|
|
@@ -8,11 +8,13 @@ export { completionStatsSchema, type CompletionStats } from "./completion-event"
|
|
|
8
8
|
* - `"hermes"`: `<tool_call>{"name":"get_weather","arguments":{"city":"Tokyo"}}</tool_call>`
|
|
9
9
|
* - `"pythonic"`: `[get_weather(city="Tokyo")]` (optionally `<|tool_call_start|>...<|tool_call_end|>`-wrapped)
|
|
10
10
|
* - `"json"`: `{"name":"get_weather","arguments":{"city":"Tokyo"}}` or `{"tool_calls":[{"name":"...","arguments":{...}}]}`
|
|
11
|
+
* - `"harmony"`: `<|channel|>commentary to=functions.get_weather <|constrain|>json<|message|>{"city":"Tokyo"}<|call|>`
|
|
11
12
|
*/
|
|
12
13
|
export declare const toolDialectSchema: z.ZodEnum<{
|
|
13
14
|
hermes: "hermes";
|
|
14
15
|
pythonic: "pythonic";
|
|
15
16
|
json: "json";
|
|
17
|
+
harmony: "harmony";
|
|
16
18
|
}>;
|
|
17
19
|
export declare const attachmentSchema: z.ZodObject<{
|
|
18
20
|
path: z.ZodString;
|
|
@@ -99,6 +101,7 @@ export declare const completionClientParamsSchema: z.ZodObject<{
|
|
|
99
101
|
hermes: "hermes";
|
|
100
102
|
pythonic: "pythonic";
|
|
101
103
|
json: "json";
|
|
104
|
+
harmony: "harmony";
|
|
102
105
|
}>>;
|
|
103
106
|
responseFormat: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
104
107
|
type: z.ZodLiteral<"text">;
|
|
@@ -162,6 +165,7 @@ export declare const completionStreamRequestSchema: z.ZodObject<{
|
|
|
162
165
|
hermes: "hermes";
|
|
163
166
|
pythonic: "pythonic";
|
|
164
167
|
json: "json";
|
|
168
|
+
harmony: "harmony";
|
|
165
169
|
}>>;
|
|
166
170
|
responseFormat: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
167
171
|
type: z.ZodLiteral<"text">;
|
|
@@ -10,8 +10,9 @@ export { completionStatsSchema } from "./completion-event.js";
|
|
|
10
10
|
* - `"hermes"`: `<tool_call>{"name":"get_weather","arguments":{"city":"Tokyo"}}</tool_call>`
|
|
11
11
|
* - `"pythonic"`: `[get_weather(city="Tokyo")]` (optionally `<|tool_call_start|>...<|tool_call_end|>`-wrapped)
|
|
12
12
|
* - `"json"`: `{"name":"get_weather","arguments":{"city":"Tokyo"}}` or `{"tool_calls":[{"name":"...","arguments":{...}}]}`
|
|
13
|
+
* - `"harmony"`: `<|channel|>commentary to=functions.get_weather <|constrain|>json<|message|>{"city":"Tokyo"}<|call|>`
|
|
13
14
|
*/
|
|
14
|
-
export const toolDialectSchema = z.enum(["hermes", "pythonic", "json"]);
|
|
15
|
+
export const toolDialectSchema = z.enum(["hermes", "pythonic", "json", "harmony"]);
|
|
15
16
|
export const attachmentSchema = z.object({
|
|
16
17
|
path: z
|
|
17
18
|
.string()
|
|
@@ -165,6 +165,7 @@ export declare const llmPlugin: {
|
|
|
165
165
|
hermes: "hermes";
|
|
166
166
|
pythonic: "pythonic";
|
|
167
167
|
json: "json";
|
|
168
|
+
harmony: "harmony";
|
|
168
169
|
}>>;
|
|
169
170
|
responseFormat: import("zod").ZodOptional<import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
|
|
170
171
|
type: import("zod").ZodLiteral<"text">;
|
|
@@ -91,9 +91,9 @@ export const llmPlugin = definePlugin({
|
|
|
91
91
|
toolCalling: toolsActive ? "textParse" : "none",
|
|
92
92
|
thinkingFraming: request.captureThinking ? "thinkTags" : "none",
|
|
93
93
|
};
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
// Dialect runs regardless of tool availability — thinking/content
|
|
95
|
+
// stripping is needed even on plain completions.
|
|
96
|
+
const dialect = request.toolDialect ?? detectToolDialect(request.modelId);
|
|
97
97
|
const normalizer = createCompletionNormalizer({
|
|
98
98
|
capabilities,
|
|
99
99
|
tools: request.tools ?? [],
|
|
@@ -3,35 +3,9 @@ import TranslationNmtcpp, {} from "@qvac/translation-nmtcpp";
|
|
|
3
3
|
import { definePlugin, defineHandler, translateRequestSchema, translateResponseSchema, ModelType, nmtConfigBaseSchema, ADDON_NMT, BERGAMOT_CJK_LANG_PAIRS, } from "../../../../schemas/index.js";
|
|
4
4
|
import { createStreamLogger, registerAddonLogger } from "../../../../logging/index.js";
|
|
5
5
|
import path from "bare-path";
|
|
6
|
-
import { ModelLoadFailedError } from "../../../../utils/errors-server.js";
|
|
7
6
|
import { translate } from "../../ops/translate.js";
|
|
8
7
|
import { attachModelExecutionMs } from "../../../../profiling/model-execution.js";
|
|
9
|
-
|
|
10
|
-
if (BERGAMOT_CJK_LANG_PAIRS.includes(langPair)) {
|
|
11
|
-
return {
|
|
12
|
-
srcVocabSrc: `${basePath}srcvocab.${langPair}.spm`,
|
|
13
|
-
dstVocabSrc: `${basePath}trgvocab.${langPair}.spm`,
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
const sharedVocab = `${basePath}vocab.${langPair}.spm`;
|
|
17
|
-
return { srcVocabSrc: sharedVocab, dstVocabSrc: sharedVocab };
|
|
18
|
-
}
|
|
19
|
-
function deriveBergamotVocabSources(modelSrc) {
|
|
20
|
-
const match = modelSrc.match(/^pear:\/\/([a-f0-9]+)\/model\.([a-z]+)\.intgemm\.alphas\.bin$/);
|
|
21
|
-
if (!match?.[1] || !match[2])
|
|
22
|
-
return null;
|
|
23
|
-
const basePath = `pear://${match[1]}/`;
|
|
24
|
-
const langPair = match[2];
|
|
25
|
-
return buildBergamotVocabSources(basePath, langPair);
|
|
26
|
-
}
|
|
27
|
-
function deriveBergamotRegistryVocabSources(modelSrc) {
|
|
28
|
-
const match = modelSrc.match(/^(registry:\/\/.+\/)model\.([a-z]+)\.intgemm\.alphas\.bin$/);
|
|
29
|
-
if (!match?.[1] || !match[2])
|
|
30
|
-
return null;
|
|
31
|
-
const basePath = match[1];
|
|
32
|
-
const langPair = match[2];
|
|
33
|
-
return buildBergamotVocabSources(basePath, langPair);
|
|
34
|
-
}
|
|
8
|
+
import { resolveBergamotVocab, } from "./resolve-vocab.js";
|
|
35
9
|
/**
|
|
36
10
|
* Derive absolute vocab paths from a resolved Bergamot model path.
|
|
37
11
|
* Works for both companion-set layout (colocated files) and any layout where
|
|
@@ -101,61 +75,6 @@ function createNmtModel(modelId, modelPath, nmtConfig, srcVocabPath, dstVocabPat
|
|
|
101
75
|
});
|
|
102
76
|
return { model };
|
|
103
77
|
}
|
|
104
|
-
async function resolveBergamotVocab(nmtConfig, ctx, srcVocabSrc, dstVocabSrc, pivotModel) {
|
|
105
|
-
let srcSrc = srcVocabSrc;
|
|
106
|
-
let dstSrc = dstVocabSrc;
|
|
107
|
-
if (!srcSrc || !dstSrc) {
|
|
108
|
-
const derived = ctx.modelSrc.startsWith("pear://")
|
|
109
|
-
? deriveBergamotVocabSources(ctx.modelSrc)
|
|
110
|
-
: ctx.modelSrc.startsWith("registry://")
|
|
111
|
-
? deriveBergamotRegistryVocabSources(ctx.modelSrc)
|
|
112
|
-
: null;
|
|
113
|
-
if (derived) {
|
|
114
|
-
srcSrc = srcSrc ?? derived.srcVocabSrc;
|
|
115
|
-
dstSrc = dstSrc ?? derived.dstVocabSrc;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
if (!srcSrc || !dstSrc) {
|
|
119
|
-
throw new ModelLoadFailedError("Bergamot requires srcVocabSrc and dstVocabSrc. Provide them in modelConfig or use a pear:// or registry:// model source for auto-derivation.");
|
|
120
|
-
}
|
|
121
|
-
if (!pivotModel) {
|
|
122
|
-
const [srcVocabPath, dstVocabPath] = await Promise.all([
|
|
123
|
-
ctx.resolveModelPath(srcSrc),
|
|
124
|
-
ctx.resolveModelPath(dstSrc),
|
|
125
|
-
]);
|
|
126
|
-
return {
|
|
127
|
-
config: nmtConfig,
|
|
128
|
-
artifacts: { srcVocabPath, dstVocabPath },
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
let pivotSrcSrc = pivotModel.srcVocabSrc;
|
|
132
|
-
let pivotDstSrc = pivotModel.dstVocabSrc;
|
|
133
|
-
if (!pivotSrcSrc || !pivotDstSrc) {
|
|
134
|
-
const pivotDerived = pivotModel.modelSrc.startsWith("pear://")
|
|
135
|
-
? deriveBergamotVocabSources(pivotModel.modelSrc)
|
|
136
|
-
: pivotModel.modelSrc.startsWith("registry://")
|
|
137
|
-
? deriveBergamotRegistryVocabSources(pivotModel.modelSrc)
|
|
138
|
-
: null;
|
|
139
|
-
if (pivotDerived) {
|
|
140
|
-
pivotSrcSrc = pivotSrcSrc ?? pivotDerived.srcVocabSrc;
|
|
141
|
-
pivotDstSrc = pivotDstSrc ?? pivotDerived.dstVocabSrc;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
if (!pivotSrcSrc || !pivotDstSrc) {
|
|
145
|
-
throw new ModelLoadFailedError("Bergamot pivot model requires srcVocabSrc and dstVocabSrc. Provide them in modelConfig or use a pear:// or registry:// model source for auto-derivation.");
|
|
146
|
-
}
|
|
147
|
-
const [srcVocabPath, dstVocabPath, pivotSrcVocabPath, pivotDstVocabPath, pivotModelPath] = await Promise.all([
|
|
148
|
-
ctx.resolveModelPath(srcSrc),
|
|
149
|
-
ctx.resolveModelPath(dstSrc),
|
|
150
|
-
ctx.resolveModelPath(pivotSrcSrc),
|
|
151
|
-
ctx.resolveModelPath(pivotDstSrc),
|
|
152
|
-
ctx.resolveModelPath(pivotModel.modelSrc),
|
|
153
|
-
]);
|
|
154
|
-
return {
|
|
155
|
-
config: nmtConfig,
|
|
156
|
-
artifacts: { srcVocabPath, dstVocabPath, pivotSrcVocabPath, pivotDstVocabPath, pivotModelPath },
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
78
|
export const nmtPlugin = definePlugin({
|
|
160
79
|
modelType: ModelType.nmtcppTranslation,
|
|
161
80
|
displayName: "NMT (nmtcpp)",
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type ModelSrcInput, type NmtConfig, type ResolveContext, type ResolveResult } from "../../../../schemas/index";
|
|
2
|
+
export interface PivotModelConfig {
|
|
3
|
+
modelSrc: string;
|
|
4
|
+
srcVocabSrc?: ModelSrcInput;
|
|
5
|
+
dstVocabSrc?: ModelSrcInput;
|
|
6
|
+
}
|
|
7
|
+
export declare function buildBergamotVocabSources(basePath: string, langPair: string): {
|
|
8
|
+
srcVocabSrc: string;
|
|
9
|
+
dstVocabSrc: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function deriveBergamotVocabSources(modelSrc: string): {
|
|
12
|
+
srcVocabSrc: string;
|
|
13
|
+
dstVocabSrc: string;
|
|
14
|
+
} | null;
|
|
15
|
+
export declare function deriveBergamotRegistryVocabSources(modelSrc: string): {
|
|
16
|
+
srcVocabSrc: string;
|
|
17
|
+
dstVocabSrc: string;
|
|
18
|
+
} | null;
|
|
19
|
+
/**
|
|
20
|
+
* Resolves Bergamot vocab sources to absolute filesystem paths via the SDK
|
|
21
|
+
* resolver context, optionally including a pivot model.
|
|
22
|
+
*
|
|
23
|
+
* For `registry://` sources with auto-derived vocabs, this skips per-vocab
|
|
24
|
+
* resolution because the companion-set download already colocates the vocabs
|
|
25
|
+
* next to the primary model under `sets/<setKey>/`. `createModel` then derives
|
|
26
|
+
* the colocated paths via `deriveColocatedBergamotVocabPaths`. This avoids a
|
|
27
|
+
* redundant flat-cache copy and sidesteps the dedup edge case in QVAC-18420
|
|
28
|
+
* where two directions of a bidirectional pair ship the same vocab blob under
|
|
29
|
+
* distinct registry paths and only one survives sha256 dedup.
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolveBergamotVocab(nmtConfig: NmtConfig, ctx: ResolveContext, srcVocabSrc: ModelSrcInput | undefined, dstVocabSrc: ModelSrcInput | undefined, pivotModel?: PivotModelConfig): Promise<ResolveResult<Record<string, unknown>>>;
|
|
32
|
+
//# sourceMappingURL=resolve-vocab.d.ts.map
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { BERGAMOT_CJK_LANG_PAIRS, } from "../../../../schemas/index.js";
|
|
2
|
+
import { ModelLoadFailedError } from "../../../../utils/errors-server.js";
|
|
3
|
+
export function buildBergamotVocabSources(basePath, langPair) {
|
|
4
|
+
if (BERGAMOT_CJK_LANG_PAIRS.includes(langPair)) {
|
|
5
|
+
return {
|
|
6
|
+
srcVocabSrc: `${basePath}srcvocab.${langPair}.spm`,
|
|
7
|
+
dstVocabSrc: `${basePath}trgvocab.${langPair}.spm`,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
const sharedVocab = `${basePath}vocab.${langPair}.spm`;
|
|
11
|
+
return { srcVocabSrc: sharedVocab, dstVocabSrc: sharedVocab };
|
|
12
|
+
}
|
|
13
|
+
export function deriveBergamotVocabSources(modelSrc) {
|
|
14
|
+
const match = modelSrc.match(/^pear:\/\/([a-f0-9]+)\/model\.([a-z]+)\.intgemm\.alphas\.bin$/);
|
|
15
|
+
if (!match?.[1] || !match[2])
|
|
16
|
+
return null;
|
|
17
|
+
const basePath = `pear://${match[1]}/`;
|
|
18
|
+
const langPair = match[2];
|
|
19
|
+
return buildBergamotVocabSources(basePath, langPair);
|
|
20
|
+
}
|
|
21
|
+
export function deriveBergamotRegistryVocabSources(modelSrc) {
|
|
22
|
+
const match = modelSrc.match(/^(registry:\/\/.+\/)model\.([a-z]+)\.intgemm\.alphas\.bin$/);
|
|
23
|
+
if (!match?.[1] || !match[2])
|
|
24
|
+
return null;
|
|
25
|
+
const basePath = match[1];
|
|
26
|
+
const langPair = match[2];
|
|
27
|
+
return buildBergamotVocabSources(basePath, langPair);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Resolves Bergamot vocab sources to absolute filesystem paths via the SDK
|
|
31
|
+
* resolver context, optionally including a pivot model.
|
|
32
|
+
*
|
|
33
|
+
* For `registry://` sources with auto-derived vocabs, this skips per-vocab
|
|
34
|
+
* resolution because the companion-set download already colocates the vocabs
|
|
35
|
+
* next to the primary model under `sets/<setKey>/`. `createModel` then derives
|
|
36
|
+
* the colocated paths via `deriveColocatedBergamotVocabPaths`. This avoids a
|
|
37
|
+
* redundant flat-cache copy and sidesteps the dedup edge case in QVAC-18420
|
|
38
|
+
* where two directions of a bidirectional pair ship the same vocab blob under
|
|
39
|
+
* distinct registry paths and only one survives sha256 dedup.
|
|
40
|
+
*/
|
|
41
|
+
export async function resolveBergamotVocab(nmtConfig, ctx, srcVocabSrc, dstVocabSrc, pivotModel) {
|
|
42
|
+
let srcSrc = srcVocabSrc;
|
|
43
|
+
let dstSrc = dstVocabSrc;
|
|
44
|
+
if (!srcSrc || !dstSrc) {
|
|
45
|
+
const derived = ctx.modelSrc.startsWith("pear://")
|
|
46
|
+
? deriveBergamotVocabSources(ctx.modelSrc)
|
|
47
|
+
: ctx.modelSrc.startsWith("registry://")
|
|
48
|
+
? deriveBergamotRegistryVocabSources(ctx.modelSrc)
|
|
49
|
+
: null;
|
|
50
|
+
if (derived) {
|
|
51
|
+
srcSrc = srcSrc ?? derived.srcVocabSrc;
|
|
52
|
+
dstSrc = dstSrc ?? derived.dstVocabSrc;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (!srcSrc || !dstSrc) {
|
|
56
|
+
throw new ModelLoadFailedError("Bergamot requires srcVocabSrc and dstVocabSrc. Provide them in modelConfig or use a pear:// or registry:// model source for auto-derivation.");
|
|
57
|
+
}
|
|
58
|
+
if (!pivotModel) {
|
|
59
|
+
const modelIsRegistry = ctx.modelSrc.startsWith("registry://");
|
|
60
|
+
const vocabsAreDerived = !srcVocabSrc && !dstVocabSrc;
|
|
61
|
+
if (modelIsRegistry && vocabsAreDerived) {
|
|
62
|
+
return { config: nmtConfig };
|
|
63
|
+
}
|
|
64
|
+
const [srcVocabPath, dstVocabPath] = await Promise.all([
|
|
65
|
+
ctx.resolveModelPath(srcSrc),
|
|
66
|
+
ctx.resolveModelPath(dstSrc),
|
|
67
|
+
]);
|
|
68
|
+
return {
|
|
69
|
+
config: nmtConfig,
|
|
70
|
+
artifacts: { srcVocabPath, dstVocabPath },
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
let pivotSrcSrc = pivotModel.srcVocabSrc;
|
|
74
|
+
let pivotDstSrc = pivotModel.dstVocabSrc;
|
|
75
|
+
if (!pivotSrcSrc || !pivotDstSrc) {
|
|
76
|
+
const pivotDerived = pivotModel.modelSrc.startsWith("pear://")
|
|
77
|
+
? deriveBergamotVocabSources(pivotModel.modelSrc)
|
|
78
|
+
: pivotModel.modelSrc.startsWith("registry://")
|
|
79
|
+
? deriveBergamotRegistryVocabSources(pivotModel.modelSrc)
|
|
80
|
+
: null;
|
|
81
|
+
if (pivotDerived) {
|
|
82
|
+
pivotSrcSrc = pivotSrcSrc ?? pivotDerived.srcVocabSrc;
|
|
83
|
+
pivotDstSrc = pivotDstSrc ?? pivotDerived.dstVocabSrc;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (!pivotSrcSrc || !pivotDstSrc) {
|
|
87
|
+
throw new ModelLoadFailedError("Bergamot pivot model requires srcVocabSrc and dstVocabSrc. Provide them in modelConfig or use a pear:// or registry:// model source for auto-derivation.");
|
|
88
|
+
}
|
|
89
|
+
const modelIsRegistry = ctx.modelSrc.startsWith("registry://");
|
|
90
|
+
const pivotIsRegistry = pivotModel.modelSrc.startsWith("registry://");
|
|
91
|
+
const primaryVocabsAreDerived = !srcVocabSrc && !dstVocabSrc;
|
|
92
|
+
const pivotVocabsAreDerived = !pivotModel.srcVocabSrc && !pivotModel.dstVocabSrc;
|
|
93
|
+
if (modelIsRegistry &&
|
|
94
|
+
pivotIsRegistry &&
|
|
95
|
+
primaryVocabsAreDerived &&
|
|
96
|
+
pivotVocabsAreDerived) {
|
|
97
|
+
const pivotModelPath = await ctx.resolveModelPath(pivotModel.modelSrc);
|
|
98
|
+
return { config: nmtConfig, artifacts: { pivotModelPath } };
|
|
99
|
+
}
|
|
100
|
+
const [srcVocabPath, dstVocabPath, pivotSrcVocabPath, pivotDstVocabPath, pivotModelPath,] = await Promise.all([
|
|
101
|
+
ctx.resolveModelPath(srcSrc),
|
|
102
|
+
ctx.resolveModelPath(dstSrc),
|
|
103
|
+
ctx.resolveModelPath(pivotSrcSrc),
|
|
104
|
+
ctx.resolveModelPath(pivotDstSrc),
|
|
105
|
+
ctx.resolveModelPath(pivotModel.modelSrc),
|
|
106
|
+
]);
|
|
107
|
+
return {
|
|
108
|
+
config: nmtConfig,
|
|
109
|
+
artifacts: {
|
|
110
|
+
srcVocabPath,
|
|
111
|
+
dstVocabPath,
|
|
112
|
+
pivotSrcVocabPath,
|
|
113
|
+
pivotDstVocabPath,
|
|
114
|
+
pivotModelPath,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|