@layer-ai/core 2.0.11 → 2.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/routes/tests/test-chat-structured-output.d.ts +7 -0
- package/dist/routes/tests/test-chat-structured-output.d.ts.map +1 -0
- package/dist/routes/tests/test-chat-structured-output.js +320 -0
- package/dist/routes/v1/gates.d.ts.map +1 -1
- package/dist/routes/v1/gates.js +11 -2
- package/dist/routes/v3/chat.d.ts +2 -0
- package/dist/routes/v3/chat.d.ts.map +1 -1
- package/dist/routes/v3/chat.js +8 -9
- package/dist/services/providers/tests/test-json-response-format-anthropic.d.ts +7 -0
- package/dist/services/providers/tests/test-json-response-format-anthropic.d.ts.map +1 -0
- package/dist/services/providers/tests/test-json-response-format-anthropic.js +179 -0
- package/dist/services/providers/tests/test-json-response-format-google.d.ts +7 -0
- package/dist/services/providers/tests/test-json-response-format-google.d.ts.map +1 -0
- package/dist/services/providers/tests/test-json-response-format-google.js +179 -0
- package/dist/services/providers/tests/test-json-response-format-mistral.d.ts +7 -0
- package/dist/services/providers/tests/test-json-response-format-mistral.d.ts.map +1 -0
- package/dist/services/providers/tests/test-json-response-format-mistral.js +179 -0
- package/dist/services/providers/tests/test-json-response-format-openai.d.ts +7 -0
- package/dist/services/providers/tests/test-json-response-format-openai.d.ts.map +1 -0
- package/dist/services/providers/tests/test-json-response-format-openai.js +175 -0
- package/dist/services/providers/tests/test-openai-adapter.js +76 -0
- package/package.json +10 -10
- package/LICENSE +0 -21
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
/**
|
|
3
|
+
* Focused tests for JSON response format structure - Google Provider
|
|
4
|
+
* Tests structured output with prompt engineering (beta mode)
|
|
5
|
+
*/
|
|
6
|
+
import { GoogleAdapter } from '../google-adapter.js';
|
|
7
|
+
const adapter = new GoogleAdapter();
|
|
8
|
+
console.log('='.repeat(80));
|
|
9
|
+
console.log('STRUCTURED OUTPUT - GOOGLE ADAPTER TESTS (BETA MODE)');
|
|
10
|
+
console.log('='.repeat(80));
|
|
11
|
+
console.log('');
|
|
12
|
+
// Helper to extract JSON from markdown or plain text
|
|
13
|
+
function extractJSON(content) {
|
|
14
|
+
const codeBlockMatch = content.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
|
|
15
|
+
if (codeBlockMatch) {
|
|
16
|
+
return JSON.parse(codeBlockMatch[1].trim());
|
|
17
|
+
}
|
|
18
|
+
return JSON.parse(content.trim());
|
|
19
|
+
}
|
|
20
|
+
async function testJsonObjectModeBeta() {
|
|
21
|
+
console.log('Test 1: JSON Object Mode (Beta - Prompt Engineering)');
|
|
22
|
+
console.log('-'.repeat(80));
|
|
23
|
+
const request = {
|
|
24
|
+
gateId: 'test-gate',
|
|
25
|
+
model: 'gemini-2.0-flash',
|
|
26
|
+
type: 'chat',
|
|
27
|
+
data: {
|
|
28
|
+
messages: [
|
|
29
|
+
{ role: 'user', content: 'Generate a user profile with name, age, and city fields' }
|
|
30
|
+
],
|
|
31
|
+
systemPrompt: 'You MUST respond with ONLY a valid JSON object. Do not include ANY text before or after the JSON. Do not wrap it in markdown code blocks. Do not add explanations. ONLY output the raw JSON object.',
|
|
32
|
+
maxTokens: 150,
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
try {
|
|
36
|
+
const response = await adapter.call(request);
|
|
37
|
+
console.log('✓ Request completed');
|
|
38
|
+
console.log('');
|
|
39
|
+
console.log('Raw response content:');
|
|
40
|
+
console.log(response.content);
|
|
41
|
+
console.log('');
|
|
42
|
+
// Try to parse as JSON (with markdown extraction fallback)
|
|
43
|
+
const parsed = extractJSON(response.content || '');
|
|
44
|
+
console.log('✓ Successfully parsed as JSON');
|
|
45
|
+
console.log('');
|
|
46
|
+
console.log('Parsed structure:');
|
|
47
|
+
console.log(JSON.stringify(parsed, null, 2));
|
|
48
|
+
console.log('');
|
|
49
|
+
console.log('✅ JSON Object Mode (Beta): PASSED');
|
|
50
|
+
console.log('');
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
console.log('❌ JSON Object Mode (Beta): FAILED');
|
|
55
|
+
console.log('Error:', error.message);
|
|
56
|
+
console.log('');
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async function testJsonSchemaModeBeta() {
|
|
61
|
+
console.log('Test 2: JSON Schema Mode (Beta - Prompt Engineering)');
|
|
62
|
+
console.log('-'.repeat(80));
|
|
63
|
+
const schema = {
|
|
64
|
+
type: 'object',
|
|
65
|
+
properties: {
|
|
66
|
+
name: { type: 'string' },
|
|
67
|
+
age: { type: 'number' },
|
|
68
|
+
city: { type: 'string' },
|
|
69
|
+
},
|
|
70
|
+
required: ['name', 'age', 'city'],
|
|
71
|
+
additionalProperties: false,
|
|
72
|
+
};
|
|
73
|
+
const systemPrompt = `You MUST respond with ONLY a valid JSON object matching this schema. Do not include ANY text before or after the JSON. Do not wrap it in markdown code blocks. Do not add explanations. ONLY output the raw JSON object.
|
|
74
|
+
|
|
75
|
+
Required JSON Schema:
|
|
76
|
+
${JSON.stringify(schema, null, 2)}`;
|
|
77
|
+
const request = {
|
|
78
|
+
gateId: 'test-gate',
|
|
79
|
+
model: 'gemini-2.0-flash',
|
|
80
|
+
type: 'chat',
|
|
81
|
+
data: {
|
|
82
|
+
messages: [
|
|
83
|
+
{ role: 'user', content: 'Create data for: name=Alice Johnson, age=28, city=Tokyo' }
|
|
84
|
+
],
|
|
85
|
+
systemPrompt,
|
|
86
|
+
maxTokens: 150,
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
try {
|
|
90
|
+
const response = await adapter.call(request);
|
|
91
|
+
console.log('✓ Request completed');
|
|
92
|
+
console.log('');
|
|
93
|
+
console.log('Raw response content:');
|
|
94
|
+
console.log(response.content);
|
|
95
|
+
console.log('');
|
|
96
|
+
// Try to parse as JSON (with markdown extraction fallback)
|
|
97
|
+
const parsed = extractJSON(response.content || '');
|
|
98
|
+
console.log('✓ Successfully parsed as JSON');
|
|
99
|
+
console.log('');
|
|
100
|
+
console.log('Parsed structure:');
|
|
101
|
+
console.log(JSON.stringify(parsed, null, 2));
|
|
102
|
+
console.log('');
|
|
103
|
+
// Validate schema fields
|
|
104
|
+
const hasRequiredFields = parsed.name && typeof parsed.age === 'number' && parsed.city;
|
|
105
|
+
if (!hasRequiredFields) {
|
|
106
|
+
throw new Error('Missing required fields from schema');
|
|
107
|
+
}
|
|
108
|
+
console.log('✓ Schema validation passed');
|
|
109
|
+
console.log('');
|
|
110
|
+
console.log('✅ JSON Schema Mode (Beta): PASSED');
|
|
111
|
+
console.log('');
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
console.log('❌ JSON Schema Mode (Beta): FAILED');
|
|
116
|
+
console.log('Error:', error.message);
|
|
117
|
+
console.log('');
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
async function testTextMode() {
|
|
122
|
+
console.log('Test 3: Text Mode (Control Test)');
|
|
123
|
+
console.log('-'.repeat(80));
|
|
124
|
+
const request = {
|
|
125
|
+
gateId: 'test-gate',
|
|
126
|
+
model: 'gemini-2.0-flash',
|
|
127
|
+
type: 'chat',
|
|
128
|
+
data: {
|
|
129
|
+
messages: [
|
|
130
|
+
{ role: 'user', content: 'Say hello' }
|
|
131
|
+
],
|
|
132
|
+
maxTokens: 50,
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
try {
|
|
136
|
+
const response = await adapter.call(request);
|
|
137
|
+
console.log('✓ Request completed');
|
|
138
|
+
console.log('');
|
|
139
|
+
console.log('Response content:');
|
|
140
|
+
console.log(response.content);
|
|
141
|
+
console.log('');
|
|
142
|
+
console.log('✅ Text Mode: PASSED');
|
|
143
|
+
console.log('');
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
console.log('❌ Text Mode: FAILED');
|
|
148
|
+
console.log('Error:', error.message);
|
|
149
|
+
console.log('');
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
async function runTests() {
|
|
154
|
+
const results = [];
|
|
155
|
+
results.push(await testJsonObjectModeBeta());
|
|
156
|
+
results.push(await testJsonSchemaModeBeta());
|
|
157
|
+
results.push(await testTextMode());
|
|
158
|
+
console.log('='.repeat(80));
|
|
159
|
+
console.log('RESULTS SUMMARY');
|
|
160
|
+
console.log('='.repeat(80));
|
|
161
|
+
console.log('');
|
|
162
|
+
const passed = results.filter(r => r).length;
|
|
163
|
+
const failed = results.filter(r => !r).length;
|
|
164
|
+
console.log(`Total Tests: ${results.length}`);
|
|
165
|
+
console.log(`Passed: ${passed}`);
|
|
166
|
+
console.log(`Failed: ${failed}`);
|
|
167
|
+
console.log('');
|
|
168
|
+
if (failed > 0) {
|
|
169
|
+
console.log('❌ Some tests failed');
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
console.log('✅ All tests passed!');
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
runTests().catch(error => {
|
|
177
|
+
console.error('Test suite failed:', error);
|
|
178
|
+
process.exit(1);
|
|
179
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-json-response-format-mistral.d.ts","sourceRoot":"","sources":["../../../../src/services/providers/tests/test-json-response-format-mistral.ts"],"names":[],"mappings":";AACA;;;GAGG"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
/**
|
|
3
|
+
* Focused tests for JSON response format structure - Mistral Provider
|
|
4
|
+
* Tests structured output with prompt engineering (beta mode)
|
|
5
|
+
*/
|
|
6
|
+
import { MistralAdapter } from '../mistral-adapter.js';
|
|
7
|
+
const adapter = new MistralAdapter();
|
|
8
|
+
console.log('='.repeat(80));
|
|
9
|
+
console.log('STRUCTURED OUTPUT - MISTRAL ADAPTER TESTS (BETA MODE)');
|
|
10
|
+
console.log('='.repeat(80));
|
|
11
|
+
console.log('');
|
|
12
|
+
// Helper to extract JSON from markdown or plain text
|
|
13
|
+
function extractJSON(content) {
|
|
14
|
+
const codeBlockMatch = content.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
|
|
15
|
+
if (codeBlockMatch) {
|
|
16
|
+
return JSON.parse(codeBlockMatch[1].trim());
|
|
17
|
+
}
|
|
18
|
+
return JSON.parse(content.trim());
|
|
19
|
+
}
|
|
20
|
+
async function testJsonObjectModeBeta() {
|
|
21
|
+
console.log('Test 1: JSON Object Mode (Beta - Prompt Engineering)');
|
|
22
|
+
console.log('-'.repeat(80));
|
|
23
|
+
const request = {
|
|
24
|
+
gateId: 'test-gate',
|
|
25
|
+
model: 'mistral-medium-2508',
|
|
26
|
+
type: 'chat',
|
|
27
|
+
data: {
|
|
28
|
+
messages: [
|
|
29
|
+
{ role: 'user', content: 'Generate a user profile with name, age, and city fields' }
|
|
30
|
+
],
|
|
31
|
+
systemPrompt: 'You MUST respond with ONLY a valid JSON object. Do not include ANY text before or after the JSON. Do not wrap it in markdown code blocks. Do not add explanations. ONLY output the raw JSON object.',
|
|
32
|
+
maxTokens: 150,
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
try {
|
|
36
|
+
const response = await adapter.call(request);
|
|
37
|
+
console.log('✓ Request completed');
|
|
38
|
+
console.log('');
|
|
39
|
+
console.log('Raw response content:');
|
|
40
|
+
console.log(response.content);
|
|
41
|
+
console.log('');
|
|
42
|
+
// Try to parse as JSON (with markdown extraction fallback)
|
|
43
|
+
const parsed = extractJSON(response.content || '');
|
|
44
|
+
console.log('✓ Successfully parsed as JSON');
|
|
45
|
+
console.log('');
|
|
46
|
+
console.log('Parsed structure:');
|
|
47
|
+
console.log(JSON.stringify(parsed, null, 2));
|
|
48
|
+
console.log('');
|
|
49
|
+
console.log('✅ JSON Object Mode (Beta): PASSED');
|
|
50
|
+
console.log('');
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
console.log('❌ JSON Object Mode (Beta): FAILED');
|
|
55
|
+
console.log('Error:', error.message);
|
|
56
|
+
console.log('');
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async function testJsonSchemaModeBeta() {
|
|
61
|
+
console.log('Test 2: JSON Schema Mode (Beta - Prompt Engineering)');
|
|
62
|
+
console.log('-'.repeat(80));
|
|
63
|
+
const schema = {
|
|
64
|
+
type: 'object',
|
|
65
|
+
properties: {
|
|
66
|
+
name: { type: 'string' },
|
|
67
|
+
age: { type: 'number' },
|
|
68
|
+
city: { type: 'string' },
|
|
69
|
+
},
|
|
70
|
+
required: ['name', 'age', 'city'],
|
|
71
|
+
additionalProperties: false,
|
|
72
|
+
};
|
|
73
|
+
const systemPrompt = `You MUST respond with ONLY a valid JSON object matching this schema. Do not include ANY text before or after the JSON. Do not wrap it in markdown code blocks. Do not add explanations. ONLY output the raw JSON object.
|
|
74
|
+
|
|
75
|
+
Required JSON Schema:
|
|
76
|
+
${JSON.stringify(schema, null, 2)}`;
|
|
77
|
+
const request = {
|
|
78
|
+
gateId: 'test-gate',
|
|
79
|
+
model: 'mistral-medium-2508',
|
|
80
|
+
type: 'chat',
|
|
81
|
+
data: {
|
|
82
|
+
messages: [
|
|
83
|
+
{ role: 'user', content: 'Create data for: name=Bob Williams, age=35, city=Paris' }
|
|
84
|
+
],
|
|
85
|
+
systemPrompt,
|
|
86
|
+
maxTokens: 150,
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
try {
|
|
90
|
+
const response = await adapter.call(request);
|
|
91
|
+
console.log('✓ Request completed');
|
|
92
|
+
console.log('');
|
|
93
|
+
console.log('Raw response content:');
|
|
94
|
+
console.log(response.content);
|
|
95
|
+
console.log('');
|
|
96
|
+
// Try to parse as JSON (with markdown extraction fallback)
|
|
97
|
+
const parsed = extractJSON(response.content || '');
|
|
98
|
+
console.log('✓ Successfully parsed as JSON');
|
|
99
|
+
console.log('');
|
|
100
|
+
console.log('Parsed structure:');
|
|
101
|
+
console.log(JSON.stringify(parsed, null, 2));
|
|
102
|
+
console.log('');
|
|
103
|
+
// Validate schema fields
|
|
104
|
+
const hasRequiredFields = parsed.name && typeof parsed.age === 'number' && parsed.city;
|
|
105
|
+
if (!hasRequiredFields) {
|
|
106
|
+
throw new Error('Missing required fields from schema');
|
|
107
|
+
}
|
|
108
|
+
console.log('✓ Schema validation passed');
|
|
109
|
+
console.log('');
|
|
110
|
+
console.log('✅ JSON Schema Mode (Beta): PASSED');
|
|
111
|
+
console.log('');
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
console.log('❌ JSON Schema Mode (Beta): FAILED');
|
|
116
|
+
console.log('Error:', error.message);
|
|
117
|
+
console.log('');
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
async function testTextMode() {
|
|
122
|
+
console.log('Test 3: Text Mode (Control Test)');
|
|
123
|
+
console.log('-'.repeat(80));
|
|
124
|
+
const request = {
|
|
125
|
+
gateId: 'test-gate',
|
|
126
|
+
model: 'mistral-medium-2508',
|
|
127
|
+
type: 'chat',
|
|
128
|
+
data: {
|
|
129
|
+
messages: [
|
|
130
|
+
{ role: 'user', content: 'Say hello' }
|
|
131
|
+
],
|
|
132
|
+
maxTokens: 50,
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
try {
|
|
136
|
+
const response = await adapter.call(request);
|
|
137
|
+
console.log('✓ Request completed');
|
|
138
|
+
console.log('');
|
|
139
|
+
console.log('Response content:');
|
|
140
|
+
console.log(response.content);
|
|
141
|
+
console.log('');
|
|
142
|
+
console.log('✅ Text Mode: PASSED');
|
|
143
|
+
console.log('');
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
console.log('❌ Text Mode: FAILED');
|
|
148
|
+
console.log('Error:', error.message);
|
|
149
|
+
console.log('');
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
async function runTests() {
|
|
154
|
+
const results = [];
|
|
155
|
+
results.push(await testJsonObjectModeBeta());
|
|
156
|
+
results.push(await testJsonSchemaModeBeta());
|
|
157
|
+
results.push(await testTextMode());
|
|
158
|
+
console.log('='.repeat(80));
|
|
159
|
+
console.log('RESULTS SUMMARY');
|
|
160
|
+
console.log('='.repeat(80));
|
|
161
|
+
console.log('');
|
|
162
|
+
const passed = results.filter(r => r).length;
|
|
163
|
+
const failed = results.filter(r => !r).length;
|
|
164
|
+
console.log(`Total Tests: ${results.length}`);
|
|
165
|
+
console.log(`Passed: ${passed}`);
|
|
166
|
+
console.log(`Failed: ${failed}`);
|
|
167
|
+
console.log('');
|
|
168
|
+
if (failed > 0) {
|
|
169
|
+
console.log('❌ Some tests failed');
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
console.log('✅ All tests passed!');
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
runTests().catch(error => {
|
|
177
|
+
console.error('Test suite failed:', error);
|
|
178
|
+
process.exit(1);
|
|
179
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-json-response-format-openai.d.ts","sourceRoot":"","sources":["../../../../src/services/providers/tests/test-json-response-format-openai.ts"],"names":[],"mappings":";AACA;;;GAGG"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
/**
|
|
3
|
+
* Focused tests for JSON response format structure
|
|
4
|
+
* Tests ONLY the structured output feature at the adapter level
|
|
5
|
+
*/
|
|
6
|
+
import { OpenAIAdapter } from '../openai-adapter.js';
|
|
7
|
+
const adapter = new OpenAIAdapter();
|
|
8
|
+
console.log('='.repeat(80));
|
|
9
|
+
console.log('STRUCTURED OUTPUT - ADAPTER LEVEL TESTS');
|
|
10
|
+
console.log('='.repeat(80));
|
|
11
|
+
console.log('');
|
|
12
|
+
async function testJsonObjectMode() {
|
|
13
|
+
console.log('Test 1: JSON Object Mode');
|
|
14
|
+
console.log('-'.repeat(80));
|
|
15
|
+
const request = {
|
|
16
|
+
gateId: 'test-gate',
|
|
17
|
+
model: 'gpt-4o-mini',
|
|
18
|
+
type: 'chat',
|
|
19
|
+
data: {
|
|
20
|
+
messages: [
|
|
21
|
+
{ role: 'user', content: 'Generate a JSON user profile with name, age, and city fields' }
|
|
22
|
+
],
|
|
23
|
+
responseFormat: 'json_object',
|
|
24
|
+
maxTokens: 100,
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
try {
|
|
28
|
+
const response = await adapter.call(request);
|
|
29
|
+
console.log('✓ Request completed');
|
|
30
|
+
console.log('');
|
|
31
|
+
console.log('Raw response content:');
|
|
32
|
+
console.log(response.content);
|
|
33
|
+
console.log('');
|
|
34
|
+
// Try to parse as JSON
|
|
35
|
+
const parsed = JSON.parse(response.content || '');
|
|
36
|
+
console.log('✓ Successfully parsed as JSON');
|
|
37
|
+
console.log('');
|
|
38
|
+
console.log('Parsed structure:');
|
|
39
|
+
console.log(JSON.stringify(parsed, null, 2));
|
|
40
|
+
console.log('');
|
|
41
|
+
console.log('✅ JSON Object Mode: PASSED');
|
|
42
|
+
console.log('');
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
console.log('❌ JSON Object Mode: FAILED');
|
|
47
|
+
console.log('Error:', error.message);
|
|
48
|
+
console.log('');
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async function testJsonSchemaMode() {
|
|
53
|
+
console.log('Test 2: JSON Schema Mode');
|
|
54
|
+
console.log('-'.repeat(80));
|
|
55
|
+
const schema = {
|
|
56
|
+
type: 'json_schema',
|
|
57
|
+
json_schema: {
|
|
58
|
+
name: 'user_profile',
|
|
59
|
+
strict: true,
|
|
60
|
+
schema: {
|
|
61
|
+
type: 'object',
|
|
62
|
+
properties: {
|
|
63
|
+
name: { type: 'string' },
|
|
64
|
+
age: { type: 'number' },
|
|
65
|
+
city: { type: 'string' },
|
|
66
|
+
},
|
|
67
|
+
required: ['name', 'age', 'city'],
|
|
68
|
+
additionalProperties: false,
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
const request = {
|
|
73
|
+
gateId: 'test-gate',
|
|
74
|
+
model: 'gpt-4o',
|
|
75
|
+
type: 'chat',
|
|
76
|
+
data: {
|
|
77
|
+
messages: [
|
|
78
|
+
{ role: 'user', content: 'Create a profile for John Doe, age 30, from New York' }
|
|
79
|
+
],
|
|
80
|
+
responseFormat: schema,
|
|
81
|
+
maxTokens: 100,
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
try {
|
|
85
|
+
const response = await adapter.call(request);
|
|
86
|
+
console.log('✓ Request completed');
|
|
87
|
+
console.log('');
|
|
88
|
+
console.log('Raw response content:');
|
|
89
|
+
console.log(response.content);
|
|
90
|
+
console.log('');
|
|
91
|
+
// Try to parse as JSON
|
|
92
|
+
const parsed = JSON.parse(response.content || '');
|
|
93
|
+
console.log('✓ Successfully parsed as JSON');
|
|
94
|
+
console.log('');
|
|
95
|
+
console.log('Parsed structure:');
|
|
96
|
+
console.log(JSON.stringify(parsed, null, 2));
|
|
97
|
+
console.log('');
|
|
98
|
+
// Validate schema fields
|
|
99
|
+
const hasRequiredFields = parsed.name && typeof parsed.age === 'number' && parsed.city;
|
|
100
|
+
if (!hasRequiredFields) {
|
|
101
|
+
throw new Error('Missing required fields from schema');
|
|
102
|
+
}
|
|
103
|
+
console.log('✓ Schema validation passed');
|
|
104
|
+
console.log('');
|
|
105
|
+
console.log('✅ JSON Schema Mode: PASSED');
|
|
106
|
+
console.log('');
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
console.log('❌ JSON Schema Mode: FAILED');
|
|
111
|
+
console.log('Error:', error.message);
|
|
112
|
+
console.log('');
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async function testTextMode() {
|
|
117
|
+
console.log('Test 3: Text Mode (Control Test)');
|
|
118
|
+
console.log('-'.repeat(80));
|
|
119
|
+
const request = {
|
|
120
|
+
gateId: 'test-gate',
|
|
121
|
+
model: 'gpt-4o-mini',
|
|
122
|
+
type: 'chat',
|
|
123
|
+
data: {
|
|
124
|
+
messages: [
|
|
125
|
+
{ role: 'user', content: 'Say hello' }
|
|
126
|
+
],
|
|
127
|
+
responseFormat: 'text',
|
|
128
|
+
maxTokens: 50,
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
try {
|
|
132
|
+
const response = await adapter.call(request);
|
|
133
|
+
console.log('✓ Request completed');
|
|
134
|
+
console.log('');
|
|
135
|
+
console.log('Response content:');
|
|
136
|
+
console.log(response.content);
|
|
137
|
+
console.log('');
|
|
138
|
+
console.log('✅ Text Mode: PASSED');
|
|
139
|
+
console.log('');
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
console.log('❌ Text Mode: FAILED');
|
|
144
|
+
console.log('Error:', error.message);
|
|
145
|
+
console.log('');
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
async function runTests() {
|
|
150
|
+
const results = [];
|
|
151
|
+
results.push(await testJsonObjectMode());
|
|
152
|
+
results.push(await testJsonSchemaMode());
|
|
153
|
+
results.push(await testTextMode());
|
|
154
|
+
console.log('='.repeat(80));
|
|
155
|
+
console.log('RESULTS SUMMARY');
|
|
156
|
+
console.log('='.repeat(80));
|
|
157
|
+
console.log('');
|
|
158
|
+
const passed = results.filter(r => r).length;
|
|
159
|
+
const failed = results.filter(r => !r).length;
|
|
160
|
+
console.log(`Total Tests: ${results.length}`);
|
|
161
|
+
console.log(`Passed: ${passed}`);
|
|
162
|
+
console.log(`Failed: ${failed}`);
|
|
163
|
+
console.log('');
|
|
164
|
+
if (failed > 0) {
|
|
165
|
+
console.log('❌ Some tests failed');
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
console.log('✅ All tests passed!');
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
runTests().catch(error => {
|
|
173
|
+
console.error('Test suite failed:', error);
|
|
174
|
+
process.exit(1);
|
|
175
|
+
});
|
|
@@ -209,6 +209,79 @@ async function testContentAndToolCalls() {
|
|
|
209
209
|
}
|
|
210
210
|
console.log('✅ Content + tool calls test passed\n');
|
|
211
211
|
}
|
|
212
|
+
async function testStructuredOutputJsonObject() {
|
|
213
|
+
console.log('Testing structured output - JSON Object mode...');
|
|
214
|
+
const request = {
|
|
215
|
+
gateId: 'test-gate',
|
|
216
|
+
model: 'gpt-4o',
|
|
217
|
+
type: 'chat',
|
|
218
|
+
data: {
|
|
219
|
+
messages: [
|
|
220
|
+
{ role: 'user', content: 'Generate a JSON user profile with name, age, and city fields' }
|
|
221
|
+
],
|
|
222
|
+
responseFormat: 'json_object',
|
|
223
|
+
maxTokens: 100,
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
const response = await adapter.call(request);
|
|
227
|
+
console.log('Response:', response.content);
|
|
228
|
+
// Try to parse as JSON
|
|
229
|
+
try {
|
|
230
|
+
const parsed = JSON.parse(response.content || '');
|
|
231
|
+
console.log('Parsed JSON:', parsed);
|
|
232
|
+
console.log('✅ JSON Object mode test passed\n');
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
throw new Error(`Response was not valid JSON: ${response.content}`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
async function testStructuredOutputJsonSchema() {
|
|
239
|
+
console.log('Testing structured output - JSON Schema mode...');
|
|
240
|
+
const schema = {
|
|
241
|
+
type: 'json_schema',
|
|
242
|
+
json_schema: {
|
|
243
|
+
name: 'user_profile',
|
|
244
|
+
strict: true,
|
|
245
|
+
schema: {
|
|
246
|
+
type: 'object',
|
|
247
|
+
properties: {
|
|
248
|
+
name: { type: 'string' },
|
|
249
|
+
age: { type: 'number' },
|
|
250
|
+
city: { type: 'string' },
|
|
251
|
+
},
|
|
252
|
+
required: ['name', 'age', 'city'],
|
|
253
|
+
additionalProperties: false,
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
};
|
|
257
|
+
const request = {
|
|
258
|
+
gateId: 'test-gate',
|
|
259
|
+
model: 'gpt-4o',
|
|
260
|
+
type: 'chat',
|
|
261
|
+
data: {
|
|
262
|
+
messages: [
|
|
263
|
+
{ role: 'user', content: 'Create a profile for John Doe, age 30, from New York' }
|
|
264
|
+
],
|
|
265
|
+
responseFormat: schema,
|
|
266
|
+
maxTokens: 100,
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
const response = await adapter.call(request);
|
|
270
|
+
console.log('Response:', response.content);
|
|
271
|
+
// Try to parse as JSON and validate schema
|
|
272
|
+
try {
|
|
273
|
+
const parsed = JSON.parse(response.content || '');
|
|
274
|
+
console.log('Parsed JSON:', parsed);
|
|
275
|
+
// Validate required fields
|
|
276
|
+
if (!parsed.name || typeof parsed.age !== 'number' || !parsed.city) {
|
|
277
|
+
throw new Error('Response does not match schema');
|
|
278
|
+
}
|
|
279
|
+
console.log('✅ JSON Schema mode test passed\n');
|
|
280
|
+
}
|
|
281
|
+
catch (error) {
|
|
282
|
+
throw new Error(`Schema validation failed: ${error}`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
212
285
|
async function runTests() {
|
|
213
286
|
try {
|
|
214
287
|
await testChatCompletion();
|
|
@@ -218,6 +291,9 @@ async function runTests() {
|
|
|
218
291
|
await testToolCalling();
|
|
219
292
|
console.log('Testing content + tool calls...');
|
|
220
293
|
await testContentAndToolCalls();
|
|
294
|
+
console.log('Testing structured output...');
|
|
295
|
+
await testStructuredOutputJsonObject();
|
|
296
|
+
await testStructuredOutputJsonSchema();
|
|
221
297
|
await testImageGeneration();
|
|
222
298
|
await testEmbeddings();
|
|
223
299
|
await testTextToSpeech();
|