@layer-ai/core 2.0.10 → 2.0.12
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 +36 -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,41 @@ 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
|
+
// Schema is already in the correct format from DB
|
|
55
|
+
chatData.responseFormat = gateConfig.responseFormatSchema;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
chatData.responseFormat = gateConfig.responseFormatType; // 'text' or 'json_object'
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// Non-OpenAI providers: Beta mode - inject instructions into system prompt
|
|
63
|
+
if (gateConfig.responseFormatType !== 'text') {
|
|
64
|
+
let schemaInstructions = '';
|
|
65
|
+
if (gateConfig.responseFormatType === 'json_schema' && gateConfig.responseFormatSchema) {
|
|
66
|
+
// Extract just the schema portion if it's the full OpenAI format
|
|
67
|
+
const schemaObj = gateConfig.responseFormatSchema;
|
|
68
|
+
const actualSchema = schemaObj.json_schema?.schema || schemaObj;
|
|
69
|
+
schemaInstructions = `\n\nYou 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.\n\nRequired JSON Schema:\n${JSON.stringify(actualSchema, null, 2)}`;
|
|
70
|
+
}
|
|
71
|
+
else if (gateConfig.responseFormatType === 'json_object') {
|
|
72
|
+
schemaInstructions = `\n\nYou 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.`;
|
|
73
|
+
}
|
|
74
|
+
// Append to existing system prompt or create new one
|
|
75
|
+
chatData.systemPrompt = (chatData.systemPrompt || '') + schemaInstructions;
|
|
76
|
+
// Log info message about beta mode
|
|
77
|
+
console.log(`[Layer AI - Structured Output Beta] Gate "${gateConfig.name}" (ID: ${gateConfig.id}) ` +
|
|
78
|
+
`is using structured output with provider "${modelProvider}". This is a beta feature that relies on ` +
|
|
79
|
+
`prompt engineering and may not be as reliable as OpenAI's native support.`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
48
83
|
return {
|
|
49
84
|
...request,
|
|
50
85
|
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.12",
|
|
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.4"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/bcryptjs": "^2.4.6",
|