@futdevpro/nts-dynamo 1.15.105 → 1.15.110
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/.dynamo/logs/cicd-pipeline/output.log +1621 -1669
- package/.dynamo/logs/cicd-pipeline/status.json +43 -29
- package/build/_modules/ai/_collections/ai-model-config-validator.util.d.ts +32 -0
- package/build/_modules/ai/_collections/ai-model-config-validator.util.d.ts.map +1 -0
- package/build/_modules/ai/_collections/ai-model-config-validator.util.js +95 -0
- package/build/_modules/ai/_collections/ai-model-config-validator.util.js.map +1 -0
- package/build/_modules/ai/_collections/ai-provider-error.util.d.ts +44 -0
- package/build/_modules/ai/_collections/ai-provider-error.util.d.ts.map +1 -0
- package/build/_modules/ai/_collections/ai-provider-error.util.js +121 -0
- package/build/_modules/ai/_collections/ai-provider-error.util.js.map +1 -0
- package/build/_modules/ai/_models/interfaces/dynts-ai-provider-error.interface.d.ts +17 -0
- package/build/_modules/ai/_models/interfaces/dynts-ai-provider-error.interface.d.ts.map +1 -0
- package/build/_modules/ai/_models/interfaces/dynts-ai-provider-error.interface.js +3 -0
- package/build/_modules/ai/_models/interfaces/dynts-ai-provider-error.interface.js.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_collections/aim-default-collection.util.d.ts +23 -0
- package/build/_modules/ai/_modules/ai-mock/_collections/aim-default-collection.util.d.ts.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_collections/aim-default-collection.util.js +52 -0
- package/build/_modules/ai/_modules/ai-mock/_collections/aim-default-collection.util.js.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_collections/aim-fixture-match.util.d.ts +34 -0
- package/build/_modules/ai/_modules/ai-mock/_collections/aim-fixture-match.util.d.ts.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_collections/aim-fixture-match.util.js +56 -0
- package/build/_modules/ai/_modules/ai-mock/_collections/aim-fixture-match.util.js.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_collections/aim-fixture-serializer.util.d.ts +33 -0
- package/build/_modules/ai/_modules/ai-mock/_collections/aim-fixture-serializer.util.d.ts.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_collections/aim-fixture-serializer.util.js +89 -0
- package/build/_modules/ai/_modules/ai-mock/_collections/aim-fixture-serializer.util.js.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_enums/aim-modality.enum.d.ts +16 -0
- package/build/_modules/ai/_modules/ai-mock/_enums/aim-modality.enum.d.ts.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_enums/aim-modality.enum.js +20 -0
- package/build/_modules/ai/_modules/ai-mock/_enums/aim-modality.enum.js.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-call-input.interface.d.ts +15 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-call-input.interface.d.ts.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-call-input.interface.js +3 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-call-input.interface.js.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-error.interface.d.ts +11 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-error.interface.d.ts.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-error.interface.js +3 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-error.interface.js.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-fixture.interface.d.ts +30 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-fixture.interface.d.ts.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-fixture.interface.js +3 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-fixture.interface.js.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-request.interface.d.ts +19 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-request.interface.d.ts.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-request.interface.js +3 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-request.interface.js.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-service-collection.interface.d.ts +19 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-service-collection.interface.d.ts.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-service-collection.interface.js +3 -0
- package/build/_modules/ai/_modules/ai-mock/_models/interfaces/aim-service-collection.interface.js.map +1 -0
- package/build/_modules/ai/{_services → _modules/ai-mock/_services}/ai-embedding-mock.service.d.ts +2 -2
- package/build/_modules/ai/_modules/ai-mock/_services/ai-embedding-mock.service.d.ts.map +1 -0
- package/build/_modules/ai/{_services → _modules/ai-mock/_services}/ai-embedding-mock.service.js +1 -1
- package/build/_modules/ai/_modules/ai-mock/_services/ai-embedding-mock.service.js.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_services/aim-fixture-harness.service.d.ts +48 -0
- package/build/_modules/ai/_modules/ai-mock/_services/aim-fixture-harness.service.d.ts.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_services/aim-fixture-harness.service.js +104 -0
- package/build/_modules/ai/_modules/ai-mock/_services/aim-fixture-harness.service.js.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_services/aim-fixture-store.service.d.ts +35 -0
- package/build/_modules/ai/_modules/ai-mock/_services/aim-fixture-store.service.d.ts.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_services/aim-fixture-store.service.js +60 -0
- package/build/_modules/ai/_modules/ai-mock/_services/aim-fixture-store.service.js.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_services/aim-mock.service.d.ts +60 -0
- package/build/_modules/ai/_modules/ai-mock/_services/aim-mock.service.d.ts.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/_services/aim-mock.service.js +121 -0
- package/build/_modules/ai/_modules/ai-mock/_services/aim-mock.service.js.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/index.d.ts +14 -0
- package/build/_modules/ai/_modules/ai-mock/index.d.ts.map +1 -0
- package/build/_modules/ai/_modules/ai-mock/index.js +41 -0
- package/build/_modules/ai/_modules/ai-mock/index.js.map +1 -0
- package/build/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.d.ts +31 -3
- package/build/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.d.ts.map +1 -1
- package/build/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.js +71 -33
- package/build/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.js.map +1 -1
- package/build/_modules/ai/_services/ai-embedding-provider.registry.d.ts +1 -1
- package/build/_modules/ai/_services/ai-embedding-provider.registry.d.ts.map +1 -1
- package/build/_modules/ai/_services/ai-embedding-provider.registry.js +1 -1
- package/build/_modules/ai/_services/ai-embedding-provider.registry.js.map +1 -1
- package/build/_modules/ai/_services/ai-llm.service-base.d.ts +16 -0
- package/build/_modules/ai/_services/ai-llm.service-base.d.ts.map +1 -1
- package/build/_modules/ai/_services/ai-llm.service-base.js +65 -0
- package/build/_modules/ai/_services/ai-llm.service-base.js.map +1 -1
- package/build/_modules/ai/index.d.ts +4 -1
- package/build/_modules/ai/index.d.ts.map +1 -1
- package/build/_modules/ai/index.js +9 -1
- package/build/_modules/ai/index.js.map +1 -1
- package/build/_modules/server/server-status/server-status.control-service.d.ts +10 -0
- package/build/_modules/server/server-status/server-status.control-service.d.ts.map +1 -1
- package/build/_modules/server/server-status/server-status.control-service.js +21 -0
- package/build/_modules/server/server-status/server-status.control-service.js.map +1 -1
- package/package.json +11 -2
- package/src/_modules/ai/_collections/ai-model-config-validator.util.spec.ts +150 -0
- package/src/_modules/ai/_collections/ai-model-config-validator.util.ts +131 -0
- package/src/_modules/ai/_collections/ai-provider-error.util.ts +144 -0
- package/src/_modules/ai/_models/interfaces/dynts-ai-provider-error.interface.ts +16 -0
- package/src/_modules/ai/_modules/ai-mock/_collections/aim-default-collection.util.spec.ts +72 -0
- package/src/_modules/ai/_modules/ai-mock/_collections/aim-default-collection.util.ts +71 -0
- package/src/_modules/ai/_modules/ai-mock/_collections/aim-fixture-match.util.spec.ts +57 -0
- package/src/_modules/ai/_modules/ai-mock/_collections/aim-fixture-match.util.ts +60 -0
- package/src/_modules/ai/_modules/ai-mock/_collections/aim-fixture-serializer.util.spec.ts +56 -0
- package/src/_modules/ai/_modules/ai-mock/_collections/aim-fixture-serializer.util.ts +107 -0
- package/src/_modules/ai/_modules/ai-mock/_enums/aim-modality.enum.ts +15 -0
- package/src/_modules/ai/_modules/ai-mock/_models/interfaces/aim-call-input.interface.ts +14 -0
- package/src/_modules/ai/_modules/ai-mock/_models/interfaces/aim-error.interface.ts +11 -0
- package/src/_modules/ai/_modules/ai-mock/_models/interfaces/aim-fixture.interface.ts +30 -0
- package/src/_modules/ai/_modules/ai-mock/_models/interfaces/aim-request.interface.ts +19 -0
- package/src/_modules/ai/_modules/ai-mock/_models/interfaces/aim-service-collection.interface.ts +20 -0
- package/src/_modules/ai/{_services → _modules/ai-mock/_services}/ai-embedding-mock.service.spec.ts +1 -1
- package/src/_modules/ai/{_services → _modules/ai-mock/_services}/ai-embedding-mock.service.ts +2 -2
- package/src/_modules/ai/_modules/ai-mock/_services/aim-fixture-harness.service.spec.ts +134 -0
- package/src/_modules/ai/_modules/ai-mock/_services/aim-fixture-harness.service.ts +127 -0
- package/src/_modules/ai/_modules/ai-mock/_services/aim-fixture-pipeline.spec.ts +105 -0
- package/src/_modules/ai/_modules/ai-mock/_services/aim-fixture-store.service.spec.ts +50 -0
- package/src/_modules/ai/_modules/ai-mock/_services/aim-fixture-store.service.ts +65 -0
- package/src/_modules/ai/_modules/ai-mock/_services/aim-mock.service.spec.ts +112 -0
- package/src/_modules/ai/_modules/ai-mock/_services/aim-mock.service.ts +142 -0
- package/src/_modules/ai/_modules/ai-mock/index.ts +44 -0
- package/src/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.ts +90 -38
- package/src/_modules/ai/_services/ai-embedding-provider.registry.spec.ts +1 -1
- package/src/_modules/ai/_services/ai-embedding-provider.registry.ts +1 -1
- package/src/_modules/ai/_services/ai-llm.service-base.reconciler.spec.ts +133 -0
- package/src/_modules/ai/_services/ai-llm.service-base.ts +80 -0
- package/src/_modules/ai/index.ts +11 -1
- package/src/_modules/server/server-status/server-status.control-service.spec.ts +40 -0
- package/src/_modules/server/server-status/server-status.control-service.ts +40 -0
- package/build/_modules/ai/_services/ai-embedding-mock.service.d.ts.map +0 -1
- package/build/_modules/ai/_services/ai-embedding-mock.service.js.map +0 -1
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { DyFM_Error } from '@futdevpro/fsm-dynamo';
|
|
2
|
+
import { DyFM_AI_ModelInfo, DyFM_AI_ModelType, DyFM_AI_Provider } from '@futdevpro/fsm-dynamo/ai';
|
|
3
|
+
|
|
4
|
+
import { DyNTS_AI_ModelConfig_Validator } from './ai-model-config-validator.util';
|
|
5
|
+
|
|
6
|
+
describe('| DyNTS_AI_ModelConfig_Validator (FR-048 validate-mode)', () => {
|
|
7
|
+
|
|
8
|
+
const registry: DyFM_AI_ModelInfo[] = [
|
|
9
|
+
{
|
|
10
|
+
id: 'reasoning-model',
|
|
11
|
+
provider: DyFM_AI_Provider.OpenAI,
|
|
12
|
+
modelType: DyFM_AI_ModelType.Chat,
|
|
13
|
+
capabilities: {} as any,
|
|
14
|
+
settingsSchema: { unsupported: ['temperature', 'topP'] },
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: 'opus-model',
|
|
18
|
+
provider: DyFM_AI_Provider.Anthropic,
|
|
19
|
+
modelType: DyFM_AI_ModelType.Chat,
|
|
20
|
+
capabilities: {} as any,
|
|
21
|
+
settingsSchema: { unsupported: ['temperature'] },
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: 'plain-model',
|
|
25
|
+
provider: DyFM_AI_Provider.OpenAI,
|
|
26
|
+
modelType: DyFM_AI_ModelType.Chat,
|
|
27
|
+
capabilities: {} as any,
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: 'constrained-model',
|
|
31
|
+
provider: DyFM_AI_Provider.OpenAI,
|
|
32
|
+
modelType: DyFM_AI_ModelType.Chat,
|
|
33
|
+
capabilities: {} as any,
|
|
34
|
+
settingsSchema: {
|
|
35
|
+
supported: ['maxTokens', 'reasoningEffort'],
|
|
36
|
+
constraints: {
|
|
37
|
+
reasoningEffort: { allowed: ['low', 'medium', 'high'] },
|
|
38
|
+
maxTokens: { min: 10, max: 100 },
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
it('| nem tamogatott param → provider-faithful DyFM_Error', () => {
|
|
45
|
+
const error: DyFM_Error = DyNTS_AI_ModelConfig_Validator.validate({
|
|
46
|
+
provider: 'open-ai',
|
|
47
|
+
model: 'reasoning-model',
|
|
48
|
+
config: { temperature: 0.5 },
|
|
49
|
+
registry: registry,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
expect(error instanceof DyFM_Error).toBe(true);
|
|
53
|
+
expect(error.message).toContain('unsupported_parameter:temperature');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('| csak tamogatott paramok → null (OK)', () => {
|
|
57
|
+
const error: DyFM_Error = DyNTS_AI_ModelConfig_Validator.validate({
|
|
58
|
+
provider: 'open-ai',
|
|
59
|
+
model: 'reasoning-model',
|
|
60
|
+
config: { maxTokens: 100 },
|
|
61
|
+
registry: registry,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
expect(error).toBeNull();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('| Anthropic provider → anthropic-alaku hiba-body', () => {
|
|
68
|
+
const error: DyFM_Error = DyNTS_AI_ModelConfig_Validator.validate({
|
|
69
|
+
provider: 'anthropic',
|
|
70
|
+
model: 'opus-model',
|
|
71
|
+
config: { temperature: 0.5 },
|
|
72
|
+
registry: registry,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
expect(error.message).toContain('invalid_request_error:temperature');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('| schema-mentes modell → null (permissziv, nem talalgat)', () => {
|
|
79
|
+
const error: DyFM_Error = DyNTS_AI_ModelConfig_Validator.validate({
|
|
80
|
+
provider: 'open-ai',
|
|
81
|
+
model: 'plain-model',
|
|
82
|
+
config: { temperature: 0.5 },
|
|
83
|
+
registry: registry,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
expect(error).toBeNull();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('| ismeretlen modell → null (permissziv)', () => {
|
|
90
|
+
const error: DyFM_Error = DyNTS_AI_ModelConfig_Validator.validate({
|
|
91
|
+
provider: 'open-ai',
|
|
92
|
+
model: 'nincs-ilyen',
|
|
93
|
+
config: { temperature: 0.5 },
|
|
94
|
+
registry: registry,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
expect(error).toBeNull();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('| constraints.allowed megsertve → invalid_value hiba', () => {
|
|
101
|
+
const error: DyFM_Error = DyNTS_AI_ModelConfig_Validator.validate({
|
|
102
|
+
provider: 'open-ai',
|
|
103
|
+
model: 'constrained-model',
|
|
104
|
+
config: { reasoningEffort: 'ultra' },
|
|
105
|
+
registry: registry,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
expect(error instanceof DyFM_Error).toBe(true);
|
|
109
|
+
expect(error.message).toContain('invalid_value:reasoningEffort');
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('| constraints.allowed betartva → null', () => {
|
|
113
|
+
expect(DyNTS_AI_ModelConfig_Validator.validate({
|
|
114
|
+
provider: 'open-ai',
|
|
115
|
+
model: 'constrained-model',
|
|
116
|
+
config: { reasoningEffort: 'medium' },
|
|
117
|
+
registry: registry,
|
|
118
|
+
})).toBeNull();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('| constraints min/max megsertve → invalid_value hiba', () => {
|
|
122
|
+
const tooHigh: DyFM_Error = DyNTS_AI_ModelConfig_Validator.validate({
|
|
123
|
+
provider: 'open-ai',
|
|
124
|
+
model: 'constrained-model',
|
|
125
|
+
config: { maxTokens: 5000 },
|
|
126
|
+
registry: registry,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
expect(tooHigh.message).toContain('invalid_value:maxTokens');
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('| constraints tartomanyon belul → null', () => {
|
|
133
|
+
expect(DyNTS_AI_ModelConfig_Validator.validate({
|
|
134
|
+
provider: 'open-ai',
|
|
135
|
+
model: 'constrained-model',
|
|
136
|
+
config: { maxTokens: 50 },
|
|
137
|
+
registry: registry,
|
|
138
|
+
})).toBeNull();
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('| config nelkul → null', () => {
|
|
142
|
+
const error: DyFM_Error = DyNTS_AI_ModelConfig_Validator.validate({
|
|
143
|
+
provider: 'open-ai',
|
|
144
|
+
model: 'reasoning-model',
|
|
145
|
+
registry: registry,
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
expect(error).toBeNull();
|
|
149
|
+
});
|
|
150
|
+
});
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { DyFM_Error } from '@futdevpro/fsm-dynamo';
|
|
2
|
+
import {
|
|
3
|
+
DyFM_AI_ModelInfo,
|
|
4
|
+
DyFM_AI_ModelRegistry_Util,
|
|
5
|
+
DyFM_AI_ModelSettingsSchema,
|
|
6
|
+
DyFM_AI_SettingConstraint,
|
|
7
|
+
} from '@futdevpro/fsm-dynamo/ai';
|
|
8
|
+
|
|
9
|
+
import { DyNTS_AI_ProviderError } from '../_models/interfaces/dynts-ai-provider-error.interface';
|
|
10
|
+
import { DyNTS_AI_ProviderError_Util } from './ai-provider-error.util';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* FR-048 **validate-mode** — a per-model `settingsSchema` szerinti config-ellenorzes MUTACIO NELKUL.
|
|
14
|
+
*
|
|
15
|
+
* Testvere a `DyNTS_AI_LLM_ServiceBase.reconcileCallSettings`-nek: a reconciler a hivas elott CSENDBEN
|
|
16
|
+
* dropol/clampel (hogy a hivas atmenjen), ez viszont HIBAT AD — igy hasznalhato **production
|
|
17
|
+
* pre-validaciora** (UI-form submit elott, backend service-boundary-n) es tesztben egyarant.
|
|
18
|
+
* **Ugyanabbol az egy forrasbol** (`settingsSchema`) dolgozik mindketto — nincs parhuzamos szabaly-keszlet.
|
|
19
|
+
*
|
|
20
|
+
* A visszateres `null` = OK; kulonben provider-faithful `DyFM_Error` (a nativ hiba-body az
|
|
21
|
+
* `additionalContent.providerErrorBody`-ban).
|
|
22
|
+
*
|
|
23
|
+
* Ismeretlen modell / schema-mentes registry-bejegyzes → `null` (permissziv, best-effort) — NEM talalgatunk.
|
|
24
|
+
*/
|
|
25
|
+
export class DyNTS_AI_ModelConfig_Validator {
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Egy hivas-config ellenorzese a modell `settingsSchema`-ja ellen.
|
|
29
|
+
* @param set - provider + modell + a vizsgalando config + a provider modell-registry-je
|
|
30
|
+
*/
|
|
31
|
+
static validate(
|
|
32
|
+
set: {
|
|
33
|
+
provider: string,
|
|
34
|
+
model: string,
|
|
35
|
+
config?: Record<string, unknown>,
|
|
36
|
+
registry: DyFM_AI_ModelInfo[],
|
|
37
|
+
}
|
|
38
|
+
): DyFM_Error {
|
|
39
|
+
if (!set.config) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const modelInfo: DyFM_AI_ModelInfo = DyFM_AI_ModelRegistry_Util.findModelInfo(set.registry ?? [], set.model);
|
|
44
|
+
const schema: DyFM_AI_ModelSettingsSchema = modelInfo?.settingsSchema;
|
|
45
|
+
|
|
46
|
+
if (!schema) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 1) NEM tamogatott parameter (a modell 400-zal elutasitana)
|
|
51
|
+
for (const param of schema.unsupported ?? []) {
|
|
52
|
+
if (set.config[param] !== undefined) {
|
|
53
|
+
return this.toError(
|
|
54
|
+
DyNTS_AI_ProviderError_Util.buildUnsupportedParamError({
|
|
55
|
+
provider: set.provider,
|
|
56
|
+
model: set.model,
|
|
57
|
+
param: param,
|
|
58
|
+
})
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 2) Tamogatott parameter, de ervenytelen ertek (constraints: allowed / min / max)
|
|
64
|
+
return this.validateConstraints({
|
|
65
|
+
provider: set.provider,
|
|
66
|
+
model: set.model,
|
|
67
|
+
config: set.config,
|
|
68
|
+
schema: schema,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** A `constraints` (allowed / min / max) ellenorzese. `null` = OK. */
|
|
73
|
+
private static validateConstraints(
|
|
74
|
+
set: {
|
|
75
|
+
provider: string,
|
|
76
|
+
model: string,
|
|
77
|
+
config: Record<string, unknown>,
|
|
78
|
+
schema: DyFM_AI_ModelSettingsSchema,
|
|
79
|
+
}
|
|
80
|
+
): DyFM_Error {
|
|
81
|
+
const constraints: Record<string, DyFM_AI_SettingConstraint> = set.schema.constraints ?? {};
|
|
82
|
+
|
|
83
|
+
for (const param of Object.keys(constraints)) {
|
|
84
|
+
const constraint: DyFM_AI_SettingConstraint = constraints[param];
|
|
85
|
+
const value: unknown = set.config[param];
|
|
86
|
+
|
|
87
|
+
if (value === undefined) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (constraint.allowed?.length && !constraint.allowed.includes(value)) {
|
|
92
|
+
return this.toError(
|
|
93
|
+
DyNTS_AI_ProviderError_Util.buildInvalidValueError({
|
|
94
|
+
provider: set.provider,
|
|
95
|
+
model: set.model,
|
|
96
|
+
param: param,
|
|
97
|
+
detail: `must be one of [${constraint.allowed.join(', ')}]`,
|
|
98
|
+
})
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (typeof value === 'number') {
|
|
103
|
+
const belowMin: boolean = typeof constraint.min === 'number' && value < constraint.min;
|
|
104
|
+
const aboveMax: boolean = typeof constraint.max === 'number' && value > constraint.max;
|
|
105
|
+
|
|
106
|
+
if (belowMin || aboveMax) {
|
|
107
|
+
return this.toError(
|
|
108
|
+
DyNTS_AI_ProviderError_Util.buildInvalidValueError({
|
|
109
|
+
provider: set.provider,
|
|
110
|
+
model: set.model,
|
|
111
|
+
param: param,
|
|
112
|
+
detail: `out of range (${constraint.min ?? '-∞'}..${constraint.max ?? '∞'})`,
|
|
113
|
+
})
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Provider-faithful hiba-leiroból a `DyFM_Error`. */
|
|
123
|
+
private static toError(providerError: DyNTS_AI_ProviderError): DyFM_Error {
|
|
124
|
+
return new DyFM_Error({
|
|
125
|
+
message: `[FR-048] provider-faithful error (HTTP ${providerError.httpStatus}): ${providerError.reason}`,
|
|
126
|
+
userMessage: 'The AI request contains a parameter this model does not accept.',
|
|
127
|
+
errorCode: 'DyNTS-AICFG-UNSUP',
|
|
128
|
+
additionalContent: { providerErrorBody: providerError.providerErrorBody },
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { DyFM_AI_Provider } from '@futdevpro/fsm-dynamo/ai';
|
|
2
|
+
|
|
3
|
+
import { DyNTS_AI_ProviderError } from '../_models/interfaces/dynts-ai-provider-error.interface';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Provider-faithful hiba-alakok eloallitasa a FR-048 `settingsSchema` szabalysertesekhez — ugyanaz a
|
|
7
|
+
* hiba-alak, mint amit a valodi provider adna. A forras-igazsag a `settingsSchema` (SSoT); itt CSAK a
|
|
8
|
+
* hiba formazasa tortenik, szabaly-duplikatum nincs.
|
|
9
|
+
*
|
|
10
|
+
* **Pontossag (D4):** a hiba **strukturaja** (mezok + `code`/`type`) a dokumentalt provider-alak szerint
|
|
11
|
+
* keszult; a `message` SZOVEGE a valodi capture-ig kozelites. A gepileg fogyasztott resz (`reason`, `code`,
|
|
12
|
+
* `param`, `httpStatus`) a stabil — a byte-hu message a fixture-capture passzal pontosithato.
|
|
13
|
+
*/
|
|
14
|
+
export class DyNTS_AI_ProviderError_Util {
|
|
15
|
+
|
|
16
|
+
/** Az Anthropic provider-azonositoja (a hiba-alak valasztasahoz) — az enumbol, nem beegetett stringkent. */
|
|
17
|
+
private static readonly anthropicProviderId: string = DyFM_AI_Provider.Anthropic;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Nem tamogatott parameter → provider-hu HTTP 400 hiba-leiro.
|
|
21
|
+
* @param set - provider-azonosito + modell-azonosito + a kifogasolt parameter neve
|
|
22
|
+
*/
|
|
23
|
+
static buildUnsupportedParamError(
|
|
24
|
+
set: {
|
|
25
|
+
provider: string,
|
|
26
|
+
model: string,
|
|
27
|
+
param: string,
|
|
28
|
+
}
|
|
29
|
+
): DyNTS_AI_ProviderError {
|
|
30
|
+
if (set.provider === this.anthropicProviderId) {
|
|
31
|
+
return {
|
|
32
|
+
httpStatus: 400,
|
|
33
|
+
providerErrorBody: {
|
|
34
|
+
type: 'error',
|
|
35
|
+
error: {
|
|
36
|
+
type: 'invalid_request_error',
|
|
37
|
+
// MERT (capture 2026-07-21, claude-opus-4-8 + temperature): a valodi uzenet ez, NEM a korabbi
|
|
38
|
+
// kozelitesem ("Extra inputs are not permitted").
|
|
39
|
+
message: `\`${set.param}\` is deprecated for this model.`,
|
|
40
|
+
},
|
|
41
|
+
// VERIFIED (capture 2026-07-21): a valodi Anthropic hiba-body TOP-LEVEL `request_id`-t is hoz —
|
|
42
|
+
// ez korabban hianyzott a sablonbol. Fixture-oknel a rogzitett valodi ertek szerepel; itt
|
|
43
|
+
// szintetikus placeholder, hogy az ALAK hu legyen.
|
|
44
|
+
request_id: 'req_mock',
|
|
45
|
+
},
|
|
46
|
+
reason: `invalid_request_error:${set.param}`,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
httpStatus: 400,
|
|
52
|
+
providerErrorBody: {
|
|
53
|
+
error: {
|
|
54
|
+
message: `Unsupported parameter: '${set.param}' is not supported with model '${set.model}'.`,
|
|
55
|
+
type: 'invalid_request_error',
|
|
56
|
+
param: set.param,
|
|
57
|
+
code: 'unsupported_parameter',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
reason: `unsupported_parameter:${set.param}`,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Tamogatott parameter, de ERVENYTELEN ertek (tartomanyon kivul, vagy nem az engedett keszletbol) →
|
|
66
|
+
* provider-hu HTTP 400. Ez a `settingsSchema.constraints` (min/max/allowed) megsertese.
|
|
67
|
+
* @param set - provider + modell + parameter-nev + a rovid indoklas (pl. 'out of range 0..2')
|
|
68
|
+
*/
|
|
69
|
+
static buildInvalidValueError(
|
|
70
|
+
set: {
|
|
71
|
+
provider: string,
|
|
72
|
+
model: string,
|
|
73
|
+
param: string,
|
|
74
|
+
detail: string,
|
|
75
|
+
}
|
|
76
|
+
): DyNTS_AI_ProviderError {
|
|
77
|
+
if (set.provider === this.anthropicProviderId) {
|
|
78
|
+
return {
|
|
79
|
+
httpStatus: 400,
|
|
80
|
+
providerErrorBody: {
|
|
81
|
+
type: 'error',
|
|
82
|
+
error: {
|
|
83
|
+
type: 'invalid_request_error',
|
|
84
|
+
message: `${set.param}: ${set.detail} (model '${set.model}').`,
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
reason: `invalid_request_error:${set.param}`,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// MERT (capture 2026-07-21, gpt-4o-mini + temperature: 3): a valodi OpenAI range-hiba kodja
|
|
92
|
+
// `decimal_above_max_value`, NEM az altalam felteteleztt `invalid_value`, es a message formatuma ez:
|
|
93
|
+
// "Invalid 'temperature': decimal above maximum value. Expected a value <= 2, but got 3 instead."
|
|
94
|
+
return {
|
|
95
|
+
httpStatus: 400,
|
|
96
|
+
providerErrorBody: {
|
|
97
|
+
error: {
|
|
98
|
+
message: `Invalid '${set.param}': ${set.detail}.`,
|
|
99
|
+
type: 'invalid_request_error',
|
|
100
|
+
param: set.param,
|
|
101
|
+
code: 'decimal_above_max_value',
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
reason: `invalid_value:${set.param}`,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Ismeretlen modell → **HTTP 404** (NEM 400), `code: 'model_not_found'`.
|
|
110
|
+
* MERT (capture 2026-07-21): `The model \`X\` does not exist or you do not have access to it.`
|
|
111
|
+
* @param set - provider + a nem letezo modell-azonosito
|
|
112
|
+
*/
|
|
113
|
+
static buildModelNotFoundError(
|
|
114
|
+
set: {
|
|
115
|
+
provider: string,
|
|
116
|
+
model: string,
|
|
117
|
+
}
|
|
118
|
+
): DyNTS_AI_ProviderError {
|
|
119
|
+
if (set.provider === this.anthropicProviderId) {
|
|
120
|
+
return {
|
|
121
|
+
httpStatus: 404,
|
|
122
|
+
providerErrorBody: {
|
|
123
|
+
type: 'error',
|
|
124
|
+
error: { type: 'not_found_error', message: `model: ${set.model}` },
|
|
125
|
+
request_id: 'req_mock',
|
|
126
|
+
},
|
|
127
|
+
reason: `not_found_error:${set.model}`,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
httpStatus: 404,
|
|
133
|
+
providerErrorBody: {
|
|
134
|
+
error: {
|
|
135
|
+
message: `The model \`${set.model}\` does not exist or you do not have access to it.`,
|
|
136
|
+
type: 'invalid_request_error',
|
|
137
|
+
param: null,
|
|
138
|
+
code: 'model_not_found',
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
reason: `model_not_found:${set.model}`,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider-faithful hiba-leiro — azt irja le, MILYEN hibat adna a valodi provider egy szabalytalan
|
|
3
|
+
* hivasra (FR-048). A `providerErrorBody` a provider NATIV hiba-JSON-ja (OpenAI:
|
|
4
|
+
* `{error:{message,type,param,code}}`, Anthropic: `{type:'error',error:{type,message}}`).
|
|
5
|
+
*
|
|
6
|
+
* Egy helyen definialva, hogy a Layer A validator (`DyNTS_AI_ModelConfig_Validator`) es a Layer B
|
|
7
|
+
* mock-fixture-ok UGYANAZT az alakot hasznaljak — nincs parhuzamos hiba-shape (SSoT).
|
|
8
|
+
*/
|
|
9
|
+
export interface DyNTS_AI_ProviderError {
|
|
10
|
+
/** A reprodukalando HTTP-statusz (pl. 400). */
|
|
11
|
+
httpStatus: number;
|
|
12
|
+
/** A provider nativ hiba-body-ja. */
|
|
13
|
+
providerErrorBody: unknown;
|
|
14
|
+
/** Rovid, gepi ok-jeloles (pl. 'unsupported_parameter:temperature'). */
|
|
15
|
+
reason: string;
|
|
16
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { DyFM_AI_Provider } from '@futdevpro/fsm-dynamo/ai';
|
|
2
|
+
|
|
3
|
+
import { DyNTS_AIMock_Modality } from '../_enums/aim-modality.enum';
|
|
4
|
+
import { DyNTS_AIMock_Fixture } from '../_models/interfaces/aim-fixture.interface';
|
|
5
|
+
import { DyNTS_AIMock_ServiceCollection } from '../_models/interfaces/aim-service-collection.interface';
|
|
6
|
+
import { DyNTS_AIMock_FixtureMatch_Util } from './aim-fixture-match.util';
|
|
7
|
+
import { getDefaultAiMockServiceCollection } from './aim-default-collection.util';
|
|
8
|
+
|
|
9
|
+
describe('| getDefaultAiMockServiceCollection (MP-7 SP-7.1)', () => {
|
|
10
|
+
|
|
11
|
+
function fixture(modality: DyNTS_AIMock_Modality, input: string): DyNTS_AIMock_Fixture {
|
|
12
|
+
return {
|
|
13
|
+
provider: 'open-ai',
|
|
14
|
+
model: 'gpt-5.4-mini',
|
|
15
|
+
modality: modality,
|
|
16
|
+
input: input,
|
|
17
|
+
inputHash: DyNTS_AIMock_FixtureMatch_Util.buildInputHash(input),
|
|
18
|
+
output: 'out',
|
|
19
|
+
capturedAt: '2026-07-21T00:00:00.000Z',
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
it('| default: mindharom schema-s provider registry-je be van kotve', () => {
|
|
24
|
+
const collection: DyNTS_AIMock_ServiceCollection = getDefaultAiMockServiceCollection();
|
|
25
|
+
|
|
26
|
+
expect(collection.registry.length).toBeGreaterThan(0);
|
|
27
|
+
expect(collection.registry.some((model) => model.provider === DyFM_AI_Provider.OpenAI)).toBe(true);
|
|
28
|
+
expect(collection.registry.some((model) => model.provider === DyFM_AI_Provider.Anthropic)).toBe(true);
|
|
29
|
+
expect(collection.registry.some((model) => model.provider === DyFM_AI_Provider.Google)).toBe(true);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('| providers szukites: csak a kert provider modelljei', () => {
|
|
33
|
+
const collection: DyNTS_AIMock_ServiceCollection = getDefaultAiMockServiceCollection({
|
|
34
|
+
providers: [DyFM_AI_Provider.OpenAI],
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
expect(collection.registry.length).toBeGreaterThan(0);
|
|
38
|
+
expect(collection.registry.every((model) => model.provider === DyFM_AI_Provider.OpenAI)).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('| service + store ossze van drotozva (a store futas kozben bovitheto)', () => {
|
|
42
|
+
const collection: DyNTS_AIMock_ServiceCollection = getDefaultAiMockServiceCollection();
|
|
43
|
+
|
|
44
|
+
expect(collection.store.size).toBe(0);
|
|
45
|
+
|
|
46
|
+
collection.store.register([fixture(DyNTS_AIMock_Modality.text, 'ping')]);
|
|
47
|
+
|
|
48
|
+
expect(collection.store.size).toBe(1);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('| modalities szukites: csak az adott modalitasu fixture-ok kerulnek a tarba', () => {
|
|
52
|
+
const collection: DyNTS_AIMock_ServiceCollection = getDefaultAiMockServiceCollection({
|
|
53
|
+
modalities: [DyNTS_AIMock_Modality.embedding],
|
|
54
|
+
fixtures: [
|
|
55
|
+
fixture(DyNTS_AIMock_Modality.text, 'a'),
|
|
56
|
+
fixture(DyNTS_AIMock_Modality.embedding, 'b'),
|
|
57
|
+
],
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
expect(collection.store.size).toBe(1);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('| a bekototett fixture azonnal replay-elheto a service-en at', async () => {
|
|
64
|
+
const collection: DyNTS_AIMock_ServiceCollection = getDefaultAiMockServiceCollection({
|
|
65
|
+
fixtures: [fixture(DyNTS_AIMock_Modality.text, 'ping')],
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
await expectAsync(
|
|
69
|
+
collection.service.chatCompletion({ provider: 'open-ai', model: 'gpt-5.4-mini', input: 'ping' })
|
|
70
|
+
).toBeResolvedTo('out');
|
|
71
|
+
});
|
|
72
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { DyFM_AI_ModelInfo, DyFM_AI_Provider } from '@futdevpro/fsm-dynamo/ai';
|
|
2
|
+
import { DyFM_OAI_Models } from '@futdevpro/fsm-dynamo/ai/open-ai';
|
|
3
|
+
import { DyFM_AAI_Models } from '@futdevpro/fsm-dynamo/ai/anthropic';
|
|
4
|
+
import { DyFM_GAI_Models } from '@futdevpro/fsm-dynamo/ai/google';
|
|
5
|
+
|
|
6
|
+
import { DyNTS_AIMock_Modality } from '../_enums/aim-modality.enum';
|
|
7
|
+
import { DyNTS_AIMock_Fixture } from '../_models/interfaces/aim-fixture.interface';
|
|
8
|
+
import { DyNTS_AIMock_ServiceCollection } from '../_models/interfaces/aim-service-collection.interface';
|
|
9
|
+
import { DyNTS_AIMock_FixtureStore_Service } from '../_services/aim-fixture-store.service';
|
|
10
|
+
import { DyNTS_AIMock_Service } from '../_services/aim-mock.service';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Provider → modell-registry hozzarendeles.
|
|
14
|
+
*
|
|
15
|
+
* CSAK azok a providerek szerepelnek, amelyeknek van FR-048 `settingsSchema`-juk — a `local-ai` es az
|
|
16
|
+
* `fdp-ai` szandekosan schema-mentes (runtime/gateway-fuggo), igy a registry-be emelesuk a validaciohoz
|
|
17
|
+
* semmit nem adna hozza. L. a fsm registry-fejleceket + `FR-048-LAYER-A.md`.
|
|
18
|
+
*/
|
|
19
|
+
const REGISTRY_BY_PROVIDER: Record<string, DyFM_AI_ModelInfo[]> = {
|
|
20
|
+
[DyFM_AI_Provider.OpenAI]: DyFM_OAI_Models,
|
|
21
|
+
[DyFM_AI_Provider.Anthropic]: DyFM_AAI_Models,
|
|
22
|
+
[DyFM_AI_Provider.Google]: DyFM_GAI_Models,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/** Provider-default: minden schema-val rendelkezo provider. */
|
|
26
|
+
const DEFAULT_PROVIDERS: DyFM_AI_Provider[] = [
|
|
27
|
+
DyFM_AI_Provider.OpenAI,
|
|
28
|
+
DyFM_AI_Provider.Anthropic,
|
|
29
|
+
DyFM_AI_Provider.Google,
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* **Default-bundle factory** (MP-7 SP-7.1) — egy hivassal osszeallit egy hasznalatra kesz AI-mock keszletet:
|
|
34
|
+
* fixture-tar + mock-provider + a config-validaciohoz bekototott modell-registry.
|
|
35
|
+
*
|
|
36
|
+
* A `fdp-templates` `getApiDefaultSettings`-mintajat koveti: a consumer teszt-modul egyetlen sorral kap egy
|
|
37
|
+
* mukodo mockot, es DI-vel a valodi provider helyere teheti.
|
|
38
|
+
*
|
|
39
|
+
* @param set - opcionalis szukites: mely providerek registry-je legyen bekotve, mely modalitasok
|
|
40
|
+
* fixture-oi keruljenek be, es a kezdo fixture-keszlet.
|
|
41
|
+
*/
|
|
42
|
+
export function getDefaultAiMockServiceCollection(
|
|
43
|
+
set?: {
|
|
44
|
+
/** Mely providerek registry-je legyen bekotve a config-validaciohoz (default: mind a harom schema-s). */
|
|
45
|
+
providers?: DyFM_AI_Provider[],
|
|
46
|
+
/** Ha meg van adva, CSAK az itt felsorolt modalitasu fixture-ok kerulnek a tarba. */
|
|
47
|
+
modalities?: DyNTS_AIMock_Modality[],
|
|
48
|
+
/** A kezdo (beegetett) fixture-keszlet. */
|
|
49
|
+
fixtures?: DyNTS_AIMock_Fixture[],
|
|
50
|
+
}
|
|
51
|
+
): DyNTS_AIMock_ServiceCollection {
|
|
52
|
+
const providers: DyFM_AI_Provider[] = set?.providers?.length ? set.providers : DEFAULT_PROVIDERS;
|
|
53
|
+
|
|
54
|
+
const registry: DyFM_AI_ModelInfo[] = providers.reduce(
|
|
55
|
+
(all: DyFM_AI_ModelInfo[], provider: DyFM_AI_Provider) => all.concat(REGISTRY_BY_PROVIDER[provider] ?? []),
|
|
56
|
+
[]
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const allFixtures: DyNTS_AIMock_Fixture[] = set?.fixtures ?? [];
|
|
60
|
+
const fixtures: DyNTS_AIMock_Fixture[] = set?.modalities?.length ?
|
|
61
|
+
allFixtures.filter((fixture: DyNTS_AIMock_Fixture) => set.modalities.includes(fixture.modality)) :
|
|
62
|
+
allFixtures;
|
|
63
|
+
|
|
64
|
+
const store: DyNTS_AIMock_FixtureStore_Service = new DyNTS_AIMock_FixtureStore_Service(fixtures);
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
store: store,
|
|
68
|
+
service: new DyNTS_AIMock_Service(store, registry),
|
|
69
|
+
registry: registry,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { DyNTS_AIMock_Modality } from '../_enums/aim-modality.enum';
|
|
2
|
+
import { DyNTS_AIMock_Request } from '../_models/interfaces/aim-request.interface';
|
|
3
|
+
import { DyNTS_AIMock_FixtureMatch_Util } from './aim-fixture-match.util';
|
|
4
|
+
|
|
5
|
+
describe('DyNTS_AIMock_FixtureMatch_Util', () => {
|
|
6
|
+
|
|
7
|
+
function req(overrides: Partial<DyNTS_AIMock_Request>): DyNTS_AIMock_Request {
|
|
8
|
+
return {
|
|
9
|
+
provider: 'open-ai',
|
|
10
|
+
model: 'gpt-4o-mini',
|
|
11
|
+
modality: DyNTS_AIMock_Modality.text,
|
|
12
|
+
config: { temperature: 0 },
|
|
13
|
+
input: 'ping',
|
|
14
|
+
...overrides,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
it('determinisztikus — azonos request kétszer → azonos kulcs', () => {
|
|
19
|
+
expect(DyNTS_AIMock_FixtureMatch_Util.buildMatchKey(req({}))).toBe(
|
|
20
|
+
DyNTS_AIMock_FixtureMatch_Util.buildMatchKey(req({}))
|
|
21
|
+
);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('config-kulcs-sorrend független', () => {
|
|
25
|
+
const a: string = DyNTS_AIMock_FixtureMatch_Util.buildMatchKey(req({ config: { temperature: 0, topP: 1 } }));
|
|
26
|
+
const b: string = DyNTS_AIMock_FixtureMatch_Util.buildMatchKey(req({ config: { topP: 1, temperature: 0 } }));
|
|
27
|
+
|
|
28
|
+
expect(a).toBe(b);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('input-whitespace független', () => {
|
|
32
|
+
const a: string = DyNTS_AIMock_FixtureMatch_Util.buildMatchKey(req({ input: 'hello world' }));
|
|
33
|
+
const b: string = DyNTS_AIMock_FixtureMatch_Util.buildMatchKey(req({ input: ' hello world ' }));
|
|
34
|
+
|
|
35
|
+
expect(a).toBe(b);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('eltérő input → eltérő kulcs', () => {
|
|
39
|
+
const a: string = DyNTS_AIMock_FixtureMatch_Util.buildMatchKey(req({ input: 'ping' }));
|
|
40
|
+
const b: string = DyNTS_AIMock_FixtureMatch_Util.buildMatchKey(req({ input: 'pong' }));
|
|
41
|
+
|
|
42
|
+
expect(a).not.toBe(b);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('eltérő modalitás → eltérő kulcs (azonos input mellett is)', () => {
|
|
46
|
+
const a: string = DyNTS_AIMock_FixtureMatch_Util.buildMatchKey(req({ modality: DyNTS_AIMock_Modality.text }));
|
|
47
|
+
const b: string = DyNTS_AIMock_FixtureMatch_Util.buildMatchKey(req({ modality: DyNTS_AIMock_Modality.embedding }));
|
|
48
|
+
|
|
49
|
+
expect(a).not.toBe(b);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('buildInputHash stabil ugyanarra a szövegre', () => {
|
|
53
|
+
expect(DyNTS_AIMock_FixtureMatch_Util.buildInputHash('alpha')).toBe(
|
|
54
|
+
DyNTS_AIMock_FixtureMatch_Util.buildInputHash('alpha')
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
});
|