@layer-ai/core 2.0.10 → 2.0.11
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/lib/db/migrations/006_add_response_format_to_gates.sql +17 -0
- package/dist/lib/db/postgres.d.ts.map +1 -1
- package/dist/lib/db/postgres.js +12 -3
- package/dist/lib/gate-utils.d.ts.map +1 -1
- package/dist/lib/gate-utils.js +3 -0
- package/dist/routes/v3/chat.d.ts.map +1 -1
- package/dist/routes/v3/chat.js +37 -1
- package/dist/services/providers/openai-adapter.d.ts.map +1 -1
- package/dist/services/providers/openai-adapter.js +6 -0
- package/package.json +2 -2
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
-- Migration: 006_add_response_format_to_gates
|
|
2
|
+
-- Description: Add structured output support fields to gates table (OpenAI response_format feature)
|
|
3
|
+
|
|
4
|
+
ALTER TABLE gates
|
|
5
|
+
ADD COLUMN response_format_enabled BOOLEAN DEFAULT FALSE,
|
|
6
|
+
ADD COLUMN response_format_type VARCHAR(20),
|
|
7
|
+
ADD COLUMN response_format_schema JSONB;
|
|
8
|
+
|
|
9
|
+
-- Add index for querying gates with structured output enabled
|
|
10
|
+
CREATE INDEX idx_gates_response_format_enabled
|
|
11
|
+
ON gates(response_format_enabled)
|
|
12
|
+
WHERE response_format_enabled = TRUE;
|
|
13
|
+
|
|
14
|
+
-- Add comments for documentation
|
|
15
|
+
COMMENT ON COLUMN gates.response_format_enabled IS 'Whether structured output is enabled for this gate';
|
|
16
|
+
COMMENT ON COLUMN gates.response_format_type IS 'Response format type: text, json_object, or json_schema';
|
|
17
|
+
COMMENT ON COLUMN gates.response_format_schema IS 'JSON schema for json_schema response format type';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../../src/lib/db/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAyB,WAAW,EAAE,MAAM,eAAe,CAAC;AAO5F,iBAAS,OAAO,IAAI,EAAE,CAAC,IAAI,CAqB1B;AA0BD,eAAO,MAAM,EAAE;gBAEK,MAAM,WAAW,GAAG,EAAE;0BASZ,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;oBAQnC,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;sBAQ3B,MAAM,gBAAgB,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;0BAQxC,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;6BAS5B,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;yBAQnC,MAAM,WAAW,MAAM,aAAa,MAAM,QAAQ,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;kCAQjE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;8BAO1B,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;qBAQnC,MAAM,UAAU,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;iCAS7B,MAAM,YAAY,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;+BAQjD,MAAM,UAAU,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;4BAQhD,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;uBAQ7B,MAAM,QAAQ,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../../src/lib/db/postgres.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/db/postgres.js
CHANGED
|
@@ -102,8 +102,8 @@ export const db = {
|
|
|
102
102
|
return result.rows.map(toCamelCase);
|
|
103
103
|
},
|
|
104
104
|
async createGate(userId, data) {
|
|
105
|
-
const result = await getPool().query(`INSERT INTO gates (user_id, name, description, task_type, model, system_prompt, allow_overrides, temperature, max_tokens, top_p, tags, routing_strategy, fallback_models, cost_weight, latency_weight, quality_weight, analysis_method, reanalysis_period, auto_apply_recommendations, task_analysis)
|
|
106
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20) RETURNING *`, [
|
|
105
|
+
const result = await getPool().query(`INSERT INTO gates (user_id, name, description, task_type, model, system_prompt, allow_overrides, temperature, max_tokens, top_p, tags, routing_strategy, fallback_models, cost_weight, latency_weight, quality_weight, analysis_method, reanalysis_period, auto_apply_recommendations, task_analysis, response_format_enabled, response_format_type, response_format_schema)
|
|
106
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23) RETURNING *`, [
|
|
107
107
|
userId,
|
|
108
108
|
data.name,
|
|
109
109
|
data.description,
|
|
@@ -123,7 +123,10 @@ export const db = {
|
|
|
123
123
|
data.analysisMethod || 'balanced',
|
|
124
124
|
data.reanalysisPeriod || 'never',
|
|
125
125
|
data.autoApplyRecommendations ?? false,
|
|
126
|
-
data.taskAnalysis ? JSON.stringify(data.taskAnalysis) : null
|
|
126
|
+
data.taskAnalysis ? JSON.stringify(data.taskAnalysis) : null,
|
|
127
|
+
data.responseFormatEnabled ?? false,
|
|
128
|
+
data.responseFormatType || null,
|
|
129
|
+
data.responseFormatSchema ? JSON.stringify(data.responseFormatSchema) : null
|
|
127
130
|
]);
|
|
128
131
|
return toCamelCase(result.rows[0]);
|
|
129
132
|
},
|
|
@@ -152,6 +155,9 @@ export const db = {
|
|
|
152
155
|
reanalysis_period = COALESCE($18, reanalysis_period),
|
|
153
156
|
auto_apply_recommendations = COALESCE($19, auto_apply_recommendations),
|
|
154
157
|
task_analysis = COALESCE($20, task_analysis),
|
|
158
|
+
response_format_enabled = COALESCE($21, response_format_enabled),
|
|
159
|
+
response_format_type = COALESCE($22, response_format_type),
|
|
160
|
+
response_format_schema = COALESCE($23, response_format_schema),
|
|
155
161
|
updated_at = NOW()
|
|
156
162
|
WHERE id = $1 RETURNING *`, [
|
|
157
163
|
id,
|
|
@@ -174,6 +180,9 @@ export const db = {
|
|
|
174
180
|
data.reanalysisPeriod,
|
|
175
181
|
data.autoApplyRecommendations,
|
|
176
182
|
data.taskAnalysis ? JSON.stringify(data.taskAnalysis) : null,
|
|
183
|
+
data.responseFormatEnabled,
|
|
184
|
+
data.responseFormatType,
|
|
185
|
+
data.responseFormatSchema ? JSON.stringify(data.responseFormatSchema) : null,
|
|
177
186
|
]);
|
|
178
187
|
return result.rows[0] ? toCamelCase(result.rows[0]) : null;
|
|
179
188
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate-utils.d.ts","sourceRoot":"","sources":["../../src/lib/gate-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,GAAG,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"gate-utils.d.ts","sourceRoot":"","sources":["../../src/lib/gate-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,GAAG,MAAM,EAAE,CA0D9E"}
|
package/dist/lib/gate-utils.js
CHANGED
|
@@ -45,6 +45,9 @@ export function detectSignificantChanges(existing, updates) {
|
|
|
45
45
|
systemPrompt: 'systemPrompt',
|
|
46
46
|
reanalysisPeriod: 'reanalysisPeriod',
|
|
47
47
|
autoApplyRecommendations: 'autoApplyRecommendations',
|
|
48
|
+
responseFormatEnabled: 'responseFormatEnabled',
|
|
49
|
+
responseFormatType: 'responseFormatType',
|
|
50
|
+
responseFormatSchema: 'responseFormatSchema',
|
|
48
51
|
};
|
|
49
52
|
for (const [field, displayName] of Object.entries(significantFields)) {
|
|
50
53
|
if (hasChanged(field, existing[field], updates[field])) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../src/routes/v3/chat.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AAOpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../src/routes/v3/chat.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AAOpD,QAAA,MAAM,MAAM,EAAE,UAAqB,CAAC;AAmTpC,eAAe,MAAM,CAAC"}
|
package/dist/routes/v3/chat.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
2
|
import { db } from '../../lib/db/postgres.js';
|
|
3
3
|
import { authenticate } from '../../middleware/auth.js';
|
|
4
|
-
import { callAdapter, normalizeModelId } from '../../lib/provider-factory.js';
|
|
4
|
+
import { callAdapter, normalizeModelId, getProviderForModel, PROVIDER } from '../../lib/provider-factory.js';
|
|
5
5
|
import { OverrideField } from '@layer-ai/sdk';
|
|
6
6
|
const router = Router();
|
|
7
7
|
// MARK:- Helper Functions
|
|
@@ -45,6 +45,42 @@ function resolveFinalRequest(gateConfig, request) {
|
|
|
45
45
|
else if (chatData.topP !== undefined && !isOverrideAllowed(gateConfig.allowOverrides, OverrideField.TopP)) {
|
|
46
46
|
chatData.topP = gateConfig.topP;
|
|
47
47
|
}
|
|
48
|
+
// Apply structured output (response format) from gate config if enabled
|
|
49
|
+
if (gateConfig.responseFormatEnabled && gateConfig.responseFormatType) {
|
|
50
|
+
const modelProvider = getProviderForModel(finalModel);
|
|
51
|
+
if (modelProvider === PROVIDER.OPENAI) {
|
|
52
|
+
// OpenAI: Use native response_format support
|
|
53
|
+
if (gateConfig.responseFormatType === 'json_schema' && gateConfig.responseFormatSchema) {
|
|
54
|
+
chatData.responseFormat = {
|
|
55
|
+
type: 'json_schema',
|
|
56
|
+
json_schema: gateConfig.responseFormatSchema,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
chatData.responseFormat = gateConfig.responseFormatType; // 'text' or 'json_object'
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
// Non-OpenAI providers: Beta mode - inject instructions into system prompt
|
|
65
|
+
if (gateConfig.responseFormatType !== 'text') {
|
|
66
|
+
let schemaInstructions = '';
|
|
67
|
+
if (gateConfig.responseFormatType === 'json_schema' && gateConfig.responseFormatSchema) {
|
|
68
|
+
// For json_schema mode, include the actual schema
|
|
69
|
+
schemaInstructions = `\n\n[STRUCTURED OUTPUT - BETA] You MUST respond with valid JSON matching this exact schema:\n${JSON.stringify(gateConfig.responseFormatSchema, null, 2)}\n\nIMPORTANT: Output ONLY the JSON object. Do not include any explanatory text, markdown formatting, or code blocks. Just the raw JSON.`;
|
|
70
|
+
}
|
|
71
|
+
else if (gateConfig.responseFormatType === 'json_object') {
|
|
72
|
+
// For json_object mode, just require valid JSON
|
|
73
|
+
schemaInstructions = `\n\n[STRUCTURED OUTPUT - BETA] You MUST respond with valid JSON only. Do not include any explanatory text, markdown formatting, or code blocks. Output should be a raw JSON object.`;
|
|
74
|
+
}
|
|
75
|
+
// Append to existing system prompt or create new one
|
|
76
|
+
chatData.systemPrompt = (chatData.systemPrompt || '') + schemaInstructions;
|
|
77
|
+
// Log info message about beta mode
|
|
78
|
+
console.log(`[Layer AI - Structured Output Beta] Gate "${gateConfig.name}" (ID: ${gateConfig.id}) ` +
|
|
79
|
+
`is using structured output with provider "${modelProvider}". This is a beta feature that relies on ` +
|
|
80
|
+
`prompt engineering and may not be as reliable as OpenAI's native support.`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
48
84
|
return {
|
|
49
85
|
...request,
|
|
50
86
|
type: 'chat',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-adapter.d.ts","sourceRoot":"","sources":["../../../src/services/providers/openai-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EACL,YAAY,EACZ,aAAa,EACb,IAAI,EACJ,WAAW,EACX,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,WAAW,EACX,YAAY,EACb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAoB1E,qBAAa,aAAc,SAAQ,mBAAmB;IACpD,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAmB;IAE/C,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAQ1C;IAEF,SAAS,CAAC,mBAAmB,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAIxD;IAEF,SAAS,CAAC,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAK1D;IAEF,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAQpD;IAEF,SAAS,CAAC,oBAAoB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAG1D;IAEF,SAAS,CAAC,kBAAkB,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAGtD;IAEF,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAKpD;IAEF,SAAS,CAAC,mBAAmB,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAOxD;IAEI,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;YAoB5D,UAAU;
|
|
1
|
+
{"version":3,"file":"openai-adapter.d.ts","sourceRoot":"","sources":["../../../src/services/providers/openai-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EACL,YAAY,EACZ,aAAa,EACb,IAAI,EACJ,WAAW,EACX,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,WAAW,EACX,YAAY,EACb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAoB1E,qBAAa,aAAc,SAAQ,mBAAmB;IACpD,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAmB;IAE/C,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAQ1C;IAEF,SAAS,CAAC,mBAAmB,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAIxD;IAEF,SAAS,CAAC,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAK1D;IAEF,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAQpD;IAEF,SAAS,CAAC,oBAAoB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAG1D;IAEF,SAAS,CAAC,kBAAkB,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAGtD;IAEF,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAKpD;IAEF,SAAS,CAAC,mBAAmB,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAOxD;IAEI,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;YAoB5D,UAAU;YAoHV,qBAAqB;YAuCrB,gBAAgB;YAkChB,kBAAkB;CA+BjC"}
|
|
@@ -161,6 +161,12 @@ export class OpenAIAdapter extends BaseProviderAdapter {
|
|
|
161
161
|
tools: chat.tools,
|
|
162
162
|
...(chat.toolChoice && { tool_choice: chat.toolChoice }),
|
|
163
163
|
}),
|
|
164
|
+
// Structured output support: convert camelCase to snake_case
|
|
165
|
+
...(chat.responseFormat && {
|
|
166
|
+
response_format: (typeof chat.responseFormat === 'string'
|
|
167
|
+
? { type: chat.responseFormat }
|
|
168
|
+
: chat.responseFormat),
|
|
169
|
+
}),
|
|
164
170
|
};
|
|
165
171
|
const response = await client.chat.completions.create(openaiRequest);
|
|
166
172
|
const choice = response.choices[0];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@layer-ai/core",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.11",
|
|
4
4
|
"description": "Core API routes and services for Layer AI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"nanoid": "^5.0.4",
|
|
37
37
|
"openai": "^4.24.0",
|
|
38
38
|
"pg": "^8.11.3",
|
|
39
|
-
"@layer-ai/sdk": "^2.5.
|
|
39
|
+
"@layer-ai/sdk": "^2.5.3"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/bcryptjs": "^2.4.6",
|