@sudobility/shapeshyft_engine 1.0.0
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/CLAUDE.md +27 -0
- package/README.md +11 -0
- package/dist/config/providers.d.ts +111 -0
- package/dist/config/providers.d.ts.map +1 -0
- package/dist/config/providers.js +1535 -0
- package/dist/config/providers.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api-helper.d.ts +35 -0
- package/dist/lib/api-helper.d.ts.map +1 -0
- package/dist/lib/api-helper.js +123 -0
- package/dist/lib/api-helper.js.map +1 -0
- package/dist/lib/capability-validator.d.ts +36 -0
- package/dist/lib/capability-validator.d.ts.map +1 -0
- package/dist/lib/capability-validator.js +140 -0
- package/dist/lib/capability-validator.js.map +1 -0
- package/dist/lib/media-constants.d.ts +55 -0
- package/dist/lib/media-constants.d.ts.map +1 -0
- package/dist/lib/media-constants.js +166 -0
- package/dist/lib/media-constants.js.map +1 -0
- package/dist/lib/media-conversion.d.ts +36 -0
- package/dist/lib/media-conversion.d.ts.map +1 -0
- package/dist/lib/media-conversion.js +87 -0
- package/dist/lib/media-conversion.js.map +1 -0
- package/dist/lib/media-utils.d.ts +35 -0
- package/dist/lib/media-utils.d.ts.map +1 -0
- package/dist/lib/media-utils.js +173 -0
- package/dist/lib/media-utils.js.map +1 -0
- package/dist/lib/output-limit.d.ts +38 -0
- package/dist/lib/output-limit.d.ts.map +1 -0
- package/dist/lib/output-limit.js +54 -0
- package/dist/lib/output-limit.js.map +1 -0
- package/dist/lib/prompt-builder.d.ts +94 -0
- package/dist/lib/prompt-builder.d.ts.map +1 -0
- package/dist/lib/prompt-builder.js +408 -0
- package/dist/lib/prompt-builder.js.map +1 -0
- package/dist/lib/reserved-fields.d.ts +41 -0
- package/dist/lib/reserved-fields.d.ts.map +1 -0
- package/dist/lib/reserved-fields.js +47 -0
- package/dist/lib/reserved-fields.js.map +1 -0
- package/dist/services/llm/anthropic.d.ts +16 -0
- package/dist/services/llm/anthropic.d.ts.map +1 -0
- package/dist/services/llm/anthropic.js +154 -0
- package/dist/services/llm/anthropic.js.map +1 -0
- package/dist/services/llm/custom.d.ts +51 -0
- package/dist/services/llm/custom.d.ts.map +1 -0
- package/dist/services/llm/custom.js +419 -0
- package/dist/services/llm/custom.js.map +1 -0
- package/dist/services/llm/extract-json.d.ts +17 -0
- package/dist/services/llm/extract-json.d.ts.map +1 -0
- package/dist/services/llm/extract-json.js +60 -0
- package/dist/services/llm/extract-json.js.map +1 -0
- package/dist/services/llm/finish-reason.d.ts +21 -0
- package/dist/services/llm/finish-reason.d.ts.map +1 -0
- package/dist/services/llm/finish-reason.js +55 -0
- package/dist/services/llm/finish-reason.js.map +1 -0
- package/dist/services/llm/gemini.d.ts +26 -0
- package/dist/services/llm/gemini.d.ts.map +1 -0
- package/dist/services/llm/gemini.js +178 -0
- package/dist/services/llm/gemini.js.map +1 -0
- package/dist/services/llm/groq.d.ts +28 -0
- package/dist/services/llm/groq.d.ts.map +1 -0
- package/dist/services/llm/groq.js +237 -0
- package/dist/services/llm/groq.js.map +1 -0
- package/dist/services/llm/index.d.ts +19 -0
- package/dist/services/llm/index.d.ts.map +1 -0
- package/dist/services/llm/index.js +88 -0
- package/dist/services/llm/index.js.map +1 -0
- package/dist/services/llm/openai.d.ts +101 -0
- package/dist/services/llm/openai.d.ts.map +1 -0
- package/dist/services/llm/openai.js +561 -0
- package/dist/services/llm/openai.js.map +1 -0
- package/dist/services/llm/types.d.ts +110 -0
- package/dist/services/llm/types.d.ts.map +1 -0
- package/dist/services/llm/types.js +16 -0
- package/dist/services/llm/types.js.map +1 -0
- package/dist/types/index.d.ts +812 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +366 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +93 -0
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview OpenAI LLM provider
|
|
3
|
+
* @description Implements the ILLMProvider interface for OpenAI models.
|
|
4
|
+
* Also used by Mistral, xAI, DeepSeek, Perplexity, and Cohere
|
|
5
|
+
* (OpenAI-compatible APIs). Supports function calling for structured output,
|
|
6
|
+
* multimodal input (images, audio), and audio output generation.
|
|
7
|
+
*/
|
|
8
|
+
import OpenAI from "openai";
|
|
9
|
+
import { requiresEntityId, } from "./types.js";
|
|
10
|
+
import { getOpenAIAudioFormat } from "../../lib/media-constants.js";
|
|
11
|
+
import { getModelCapabilities } from "../../config/providers.js";
|
|
12
|
+
import { buildOutputStructureSection, buildResponseFormatSection, buildWebSearchRoutingSection, } from "../../lib/prompt-builder.js";
|
|
13
|
+
import { normalizeFinishReason } from "./finish-reason.js";
|
|
14
|
+
const DEFAULT_MODEL = "gpt-4o-mini";
|
|
15
|
+
class OpenAIProviderError extends Error {
|
|
16
|
+
details;
|
|
17
|
+
constructor(message, details) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.name = "OpenAIProviderError";
|
|
20
|
+
this.details = details;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* OpenAI models that reject `max_tokens`.
|
|
25
|
+
*
|
|
26
|
+
* The reasoning-era families — GPT-5 and the o-series. Everything before them
|
|
27
|
+
* (GPT-4o, GPT-4.1) still takes `max_tokens`, and every OpenAI-compatible third
|
|
28
|
+
* party knows only that, so the rule is deliberately narrow rather than
|
|
29
|
+
* "OpenAI always uses the new name".
|
|
30
|
+
*
|
|
31
|
+
* Matched on the family prefix, not an exhaustive list: the point of a family
|
|
32
|
+
* is that its next member behaves like the last, and a list of exact ids would
|
|
33
|
+
* be wrong the day one ships.
|
|
34
|
+
*/
|
|
35
|
+
const REQUIRES_MAX_COMPLETION_TOKENS = /^(gpt-5|o[1-9])/i;
|
|
36
|
+
/**
|
|
37
|
+
* What to call the output cap for this provider and model.
|
|
38
|
+
*
|
|
39
|
+
* Both halves matter. The provider decides the vocabulary available; the model
|
|
40
|
+
* decides which of it applies, and the model is chosen per endpoint rather than
|
|
41
|
+
* per provider — so this cannot be settled when the client is constructed.
|
|
42
|
+
*/
|
|
43
|
+
export function tokenLimitParamFor(isOpenAi, model) {
|
|
44
|
+
return isOpenAi && REQUIRES_MAX_COMPLETION_TOKENS.test(model)
|
|
45
|
+
? "max_completion_tokens"
|
|
46
|
+
: "max_tokens";
|
|
47
|
+
}
|
|
48
|
+
export class OpenAIProvider {
|
|
49
|
+
providerName = "openai";
|
|
50
|
+
client;
|
|
51
|
+
defaultModel;
|
|
52
|
+
disableThinking;
|
|
53
|
+
/** Whether this client talks to OpenAI itself, or an OpenAI-compatible third party. */
|
|
54
|
+
isOpenAi;
|
|
55
|
+
constructor(config,
|
|
56
|
+
/**
|
|
57
|
+
* Per-provider quirks. Defaults keep every provider that works today
|
|
58
|
+
* working; only one known to need otherwise opts out.
|
|
59
|
+
*/
|
|
60
|
+
options = {}) {
|
|
61
|
+
this.disableThinking = options.disableThinking ?? false;
|
|
62
|
+
this.isOpenAi = options.isOpenAi ?? false;
|
|
63
|
+
if (!config.apiKey) {
|
|
64
|
+
throw new Error("OpenAI API key is required");
|
|
65
|
+
}
|
|
66
|
+
// Honor a custom base URL so OpenAI-compatible providers (Mistral, xAI,
|
|
67
|
+
// DeepSeek, Perplexity) reach their own API instead of api.openai.com.
|
|
68
|
+
this.client = new OpenAI({
|
|
69
|
+
apiKey: config.apiKey,
|
|
70
|
+
...(config.endpointUrl ? { baseURL: config.endpointUrl } : {}),
|
|
71
|
+
});
|
|
72
|
+
this.defaultModel = config.model ?? DEFAULT_MODEL;
|
|
73
|
+
}
|
|
74
|
+
async generate(request) {
|
|
75
|
+
console.log(`[llm] generate() called, webSearch=${request.webSearch}, model=${request.model}`);
|
|
76
|
+
// Use Responses API when web search is enabled
|
|
77
|
+
if (request.webSearch) {
|
|
78
|
+
return this.generateWithSearch(request);
|
|
79
|
+
}
|
|
80
|
+
const model = request.model ?? this.defaultModel;
|
|
81
|
+
const startTime = Date.now();
|
|
82
|
+
const caps = getModelCapabilities(model);
|
|
83
|
+
const generatedMedia = [];
|
|
84
|
+
// Build user message content (multimodal)
|
|
85
|
+
const userContent = [];
|
|
86
|
+
if (request.media?.length) {
|
|
87
|
+
for (const m of request.media) {
|
|
88
|
+
if (m.type === "image") {
|
|
89
|
+
userContent.push({
|
|
90
|
+
type: "image_url",
|
|
91
|
+
image_url: {
|
|
92
|
+
url: m.format === "base64"
|
|
93
|
+
? `data:${m.mimeType};base64,${m.data}`
|
|
94
|
+
: m.data,
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
if (m.type === "audio") {
|
|
99
|
+
// Format already validated at capability validation layer
|
|
100
|
+
const format = getOpenAIAudioFormat(m.mimeType);
|
|
101
|
+
userContent.push({
|
|
102
|
+
type: "input_audio",
|
|
103
|
+
input_audio: {
|
|
104
|
+
data: m.data,
|
|
105
|
+
format,
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
userContent.push({ type: "text", text: request.prompt });
|
|
112
|
+
// Build messages array
|
|
113
|
+
const messages = [];
|
|
114
|
+
if (request.systemPrompt) {
|
|
115
|
+
messages.push({ role: "system", content: request.systemPrompt });
|
|
116
|
+
}
|
|
117
|
+
messages.push({ role: "user", content: userContent });
|
|
118
|
+
// Use function calling for structured output
|
|
119
|
+
const tools = [
|
|
120
|
+
{
|
|
121
|
+
type: "function",
|
|
122
|
+
function: {
|
|
123
|
+
name: "structured_response",
|
|
124
|
+
description: "Generate structured response matching the schema",
|
|
125
|
+
parameters: request.outputSchema,
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
];
|
|
129
|
+
// Audio output configuration - ONLY enable when endpoint expects audio output
|
|
130
|
+
const modalities = ["text"];
|
|
131
|
+
let audioConfig;
|
|
132
|
+
if (request.expectsMediaOutput?.audio && caps.audioOutput) {
|
|
133
|
+
modalities.push("audio");
|
|
134
|
+
// V1: Output audio format is fixed to mp3
|
|
135
|
+
audioConfig = {
|
|
136
|
+
voice: "alloy", // V1: Fixed to "alloy"
|
|
137
|
+
format: "mp3", // V1: Fixed to "mp3"
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
const response = (await this.client.chat.completions.create({
|
|
141
|
+
model,
|
|
142
|
+
messages,
|
|
143
|
+
...(audioConfig ? { modalities, audio: audioConfig } : {}),
|
|
144
|
+
tools,
|
|
145
|
+
tool_choice: {
|
|
146
|
+
type: "function",
|
|
147
|
+
function: { name: "structured_response" },
|
|
148
|
+
},
|
|
149
|
+
// Off where the model reasons by default: thinking mode rejects
|
|
150
|
+
// `tool_choice` outright, so this is what keeps the line above legal.
|
|
151
|
+
...(this.disableThinking ? { thinking: { type: "disabled" } } : {}),
|
|
152
|
+
temperature: request.temperature ?? 0,
|
|
153
|
+
[tokenLimitParamFor(this.isOpenAi, model)]: request.maxTokens,
|
|
154
|
+
stream: false,
|
|
155
|
+
}));
|
|
156
|
+
const latencyMs = Date.now() - startTime;
|
|
157
|
+
// Extract audio from response if present
|
|
158
|
+
const message = response.choices[0]
|
|
159
|
+
?.message;
|
|
160
|
+
const audioData = message?.audio;
|
|
161
|
+
if (audioData) {
|
|
162
|
+
const audioMimeType = `audio/${audioData.format}`;
|
|
163
|
+
if (requiresEntityId(request)) {
|
|
164
|
+
// URL output requested but storage upload not implemented in v1
|
|
165
|
+
// For now, return base64 with a warning in the logs
|
|
166
|
+
console.warn("URL output requested but storage upload not implemented. Returning base64.");
|
|
167
|
+
generatedMedia.push({
|
|
168
|
+
type: "audio",
|
|
169
|
+
mimeType: audioMimeType,
|
|
170
|
+
data: audioData.data,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
// Return base64
|
|
175
|
+
generatedMedia.push({
|
|
176
|
+
type: "audio",
|
|
177
|
+
mimeType: audioMimeType,
|
|
178
|
+
data: audioData.data,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// Extract structured response from function call
|
|
183
|
+
const toolCall = response.choices[0]?.message.tool_calls?.[0];
|
|
184
|
+
if (!toolCall || toolCall.function.name !== "structured_response") {
|
|
185
|
+
throw new Error("Expected function call response from OpenAI");
|
|
186
|
+
}
|
|
187
|
+
const rawResponse = toolCall.function.arguments;
|
|
188
|
+
const finishReason = normalizeFinishReason(response.choices[0]?.finish_reason);
|
|
189
|
+
const usage = {
|
|
190
|
+
promptTokens: response.usage?.prompt_tokens ?? 0,
|
|
191
|
+
completionTokens: response.usage?.completion_tokens ?? 0,
|
|
192
|
+
totalTokens: response.usage?.total_tokens ?? 0,
|
|
193
|
+
};
|
|
194
|
+
/*
|
|
195
|
+
Why the stop reason is read BEFORE parsing.
|
|
196
|
+
|
|
197
|
+
A model that hits the output ceiling returns arguments cut off mid-value,
|
|
198
|
+
and `JSON.parse` then fails with something like "Expected ']'". Return the
|
|
199
|
+
raw truncated arguments with finishReason instead, so the route can mark
|
|
200
|
+
the response as truncated and preserve usage for the caller.
|
|
201
|
+
*/
|
|
202
|
+
if (finishReason === "length") {
|
|
203
|
+
return {
|
|
204
|
+
content: rawResponse,
|
|
205
|
+
rawResponse,
|
|
206
|
+
usage,
|
|
207
|
+
model: response.model,
|
|
208
|
+
provider: this.providerName,
|
|
209
|
+
latencyMs,
|
|
210
|
+
finishReason,
|
|
211
|
+
generatedMedia: generatedMedia.length > 0 ? generatedMedia : undefined,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
let content;
|
|
215
|
+
try {
|
|
216
|
+
content = JSON.parse(rawResponse);
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
// Not truncated, so genuinely malformed. Carry a head of the payload:
|
|
220
|
+
// "Unable to parse JSON string" alone leaves nothing to diagnose from.
|
|
221
|
+
throw new Error(`Model returned unparseable JSON (${error instanceof Error ? error.message : String(error)}). First 300 chars: ${rawResponse.slice(0, 300)}`);
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
content,
|
|
225
|
+
rawResponse,
|
|
226
|
+
usage,
|
|
227
|
+
model: response.model,
|
|
228
|
+
provider: this.providerName,
|
|
229
|
+
latencyMs,
|
|
230
|
+
finishReason,
|
|
231
|
+
generatedMedia: generatedMedia.length > 0 ? generatedMedia : undefined,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Generate using the OpenAI Responses API with web search enabled.
|
|
236
|
+
* The model can search the web and then call the structured_response function.
|
|
237
|
+
*/
|
|
238
|
+
// ---------------------------------------------------------------------------
|
|
239
|
+
// Web-search-aware generation (3-step)
|
|
240
|
+
// ---------------------------------------------------------------------------
|
|
241
|
+
static INPUT_LAYOUTS = new Set([
|
|
242
|
+
"input_text",
|
|
243
|
+
"input_numeric",
|
|
244
|
+
"input_date",
|
|
245
|
+
"input_email",
|
|
246
|
+
"input_phone",
|
|
247
|
+
"search",
|
|
248
|
+
"line_select",
|
|
249
|
+
"line_toggle",
|
|
250
|
+
"line_slider",
|
|
251
|
+
]);
|
|
252
|
+
/** Check if a renderable tree contains input controls (clarification). */
|
|
253
|
+
containsInputControls(data) {
|
|
254
|
+
if (typeof data !== "object" || data === null)
|
|
255
|
+
return false;
|
|
256
|
+
const obj = data;
|
|
257
|
+
const view = obj.view;
|
|
258
|
+
if (view?.layout && OpenAIProvider.INPUT_LAYOUTS.has(view.layout))
|
|
259
|
+
return true;
|
|
260
|
+
const children = (view?.children ?? obj.children);
|
|
261
|
+
if (Array.isArray(children)) {
|
|
262
|
+
return children.some(child => this.containsInputControls(child));
|
|
263
|
+
}
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Wrap the user's output schema in a container that lets the AI signal
|
|
268
|
+
* whether it needs a web search before it can answer.
|
|
269
|
+
*/
|
|
270
|
+
buildTriageSchema(userSchema) {
|
|
271
|
+
return {
|
|
272
|
+
type: "object",
|
|
273
|
+
required: ["user_data"],
|
|
274
|
+
properties: {
|
|
275
|
+
user_data: userSchema,
|
|
276
|
+
web_search_needed: {
|
|
277
|
+
type: "boolean",
|
|
278
|
+
default: false,
|
|
279
|
+
description: "Set to true when you would say 'I don't have real-time data' or " +
|
|
280
|
+
"'I cannot access current listings'. The system WILL perform a web search " +
|
|
281
|
+
"and provide you the results. Set to false when asking for clarification " +
|
|
282
|
+
"or when you can answer from training data.",
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
additionalProperties: false,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Build the system prompt for step 1: try to answer fully, signal
|
|
290
|
+
* web_search_needed only if real-time data is genuinely required.
|
|
291
|
+
*/
|
|
292
|
+
/**
|
|
293
|
+
* Call the Responses API with a forced function call.
|
|
294
|
+
* Used for both the triage step and the structuring step.
|
|
295
|
+
*/
|
|
296
|
+
async callResponsesStructured(model, input, schema, temperature, maxTokens) {
|
|
297
|
+
console.log(`[web-search] callResponsesStructured() calling Responses API, model=${model}`);
|
|
298
|
+
const response = await this.client.responses.create({
|
|
299
|
+
model,
|
|
300
|
+
input,
|
|
301
|
+
tools: [
|
|
302
|
+
{
|
|
303
|
+
type: "function",
|
|
304
|
+
name: "structured_response",
|
|
305
|
+
description: "Generate structured response matching the schema",
|
|
306
|
+
parameters: schema,
|
|
307
|
+
strict: false,
|
|
308
|
+
},
|
|
309
|
+
],
|
|
310
|
+
tool_choice: {
|
|
311
|
+
type: "function",
|
|
312
|
+
name: "structured_response",
|
|
313
|
+
},
|
|
314
|
+
temperature,
|
|
315
|
+
max_output_tokens: maxTokens,
|
|
316
|
+
});
|
|
317
|
+
const functionCall = response.output.find((item) => item.type === "function_call" && item.name === "structured_response");
|
|
318
|
+
if (!functionCall) {
|
|
319
|
+
throw new OpenAIProviderError("Expected structured_response function call from Responses API", {
|
|
320
|
+
model,
|
|
321
|
+
responseId: response.id,
|
|
322
|
+
outputItems: response.output.map(item => ({
|
|
323
|
+
type: item.type,
|
|
324
|
+
...("name" in item ? { name: item.name } : {}),
|
|
325
|
+
})),
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
return {
|
|
329
|
+
content: JSON.parse(functionCall.arguments),
|
|
330
|
+
rawResponse: functionCall.arguments,
|
|
331
|
+
usage: {
|
|
332
|
+
inputTokens: response.usage?.input_tokens ?? 0,
|
|
333
|
+
outputTokens: response.usage?.output_tokens ?? 0,
|
|
334
|
+
},
|
|
335
|
+
model: response.model,
|
|
336
|
+
// The Responses API reports truncation as an incomplete status with a
|
|
337
|
+
// reason, rather than a finish_reason on the choice.
|
|
338
|
+
finishReason: response.status === "incomplete"
|
|
339
|
+
? normalizeFinishReason(response.incomplete_details?.reason)
|
|
340
|
+
: "stop",
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Search the web via the Responses API and return a text summary.
|
|
345
|
+
*/
|
|
346
|
+
async searchWeb(model, query, temperature) {
|
|
347
|
+
console.log(`[web-search] searchWeb() calling Responses API for query: "${query.substring(0, 100)}..."`);
|
|
348
|
+
const response = await this.client.responses.create({
|
|
349
|
+
model,
|
|
350
|
+
input: [
|
|
351
|
+
{
|
|
352
|
+
role: "developer",
|
|
353
|
+
content: "Search the web for the requested information. " +
|
|
354
|
+
"Return a thorough summary of the results with specific details, " +
|
|
355
|
+
"names, addresses, dates, and URLs when available.",
|
|
356
|
+
},
|
|
357
|
+
{ role: "user", content: query },
|
|
358
|
+
],
|
|
359
|
+
tools: [{ type: "web_search_preview" }],
|
|
360
|
+
temperature,
|
|
361
|
+
});
|
|
362
|
+
return {
|
|
363
|
+
summary: response.output_text ?? "",
|
|
364
|
+
usage: {
|
|
365
|
+
inputTokens: response.usage?.input_tokens ?? 0,
|
|
366
|
+
outputTokens: response.usage?.output_tokens ?? 0,
|
|
367
|
+
},
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
/** Build Responses API input from an LLM request. */
|
|
371
|
+
buildResponsesInput(systemPrompt, userPrompt, media) {
|
|
372
|
+
const input = [];
|
|
373
|
+
if (systemPrompt) {
|
|
374
|
+
input.push({ role: "developer", content: systemPrompt });
|
|
375
|
+
}
|
|
376
|
+
const userContent = [];
|
|
377
|
+
if (media?.length) {
|
|
378
|
+
for (const m of media) {
|
|
379
|
+
if (m.type === "image") {
|
|
380
|
+
userContent.push({
|
|
381
|
+
type: "input_image",
|
|
382
|
+
image_url: m.format === "base64"
|
|
383
|
+
? `data:${m.mimeType};base64,${m.data}`
|
|
384
|
+
: m.data,
|
|
385
|
+
detail: "auto",
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
userContent.push({ type: "input_text", text: userPrompt });
|
|
391
|
+
input.push({ role: "user", content: userContent });
|
|
392
|
+
return input;
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Main entry point when web search is enabled on the endpoint.
|
|
396
|
+
*
|
|
397
|
+
* 1. Try to answer via Responses API with triage wrapper schema.
|
|
398
|
+
* AI provides full answer OR signals web_search_needed.
|
|
399
|
+
* 2. If no search needed → return user_data directly.
|
|
400
|
+
* 3. If search needed → web search → structure results.
|
|
401
|
+
*/
|
|
402
|
+
async generateWithSearch(request) {
|
|
403
|
+
console.log(`[web-search] generateWithSearch() entered`);
|
|
404
|
+
const model = request.model ?? this.defaultModel;
|
|
405
|
+
const startTime = Date.now();
|
|
406
|
+
const userSchema = request.outputSchema;
|
|
407
|
+
const temperature = request.temperature ?? 0;
|
|
408
|
+
let totalInputTokens = 0;
|
|
409
|
+
let totalOutputTokens = 0;
|
|
410
|
+
// --- Step 1: Try to answer (Responses API, forced function call) ------
|
|
411
|
+
console.log(`[web-search] Step 1: Triage via Responses API, model=${model}`);
|
|
412
|
+
const triageSchema = this.buildTriageSchema(userSchema);
|
|
413
|
+
// Replace the output structure / example / response format sections
|
|
414
|
+
// with ones generated from the triage wrapper schema.
|
|
415
|
+
// Keep everything before "## Output Structure" (base + task description + rules).
|
|
416
|
+
const systemPrompt = request.systemPrompt ?? "";
|
|
417
|
+
const outputStructureIdx = systemPrompt.indexOf("\n## Output Structure");
|
|
418
|
+
const basePart = outputStructureIdx >= 0
|
|
419
|
+
? systemPrompt.substring(0, outputStructureIdx)
|
|
420
|
+
: systemPrompt;
|
|
421
|
+
const triageSystemPrompt = basePart +
|
|
422
|
+
buildWebSearchRoutingSection() +
|
|
423
|
+
buildOutputStructureSection(triageSchema) +
|
|
424
|
+
buildResponseFormatSection();
|
|
425
|
+
console.log(`[web-search] System prompt:\n${triageSystemPrompt}`);
|
|
426
|
+
const triageInput = this.buildResponsesInput(triageSystemPrompt, request.prompt, request.media);
|
|
427
|
+
const triageResult = await this.callResponsesStructured(model, triageInput, triageSchema, temperature, request.maxTokens);
|
|
428
|
+
totalInputTokens += triageResult.usage.inputTokens;
|
|
429
|
+
totalOutputTokens += triageResult.usage.outputTokens;
|
|
430
|
+
const triageData = triageResult.content;
|
|
431
|
+
console.log(`[web-search] Triage result: web_search_needed=${triageData.web_search_needed}`);
|
|
432
|
+
// --- If no search needed, or user_data is a clarification form, return directly
|
|
433
|
+
const isClarification = this.containsInputControls(triageData.user_data);
|
|
434
|
+
const shouldSearch = triageData.web_search_needed === true && !isClarification;
|
|
435
|
+
if (!shouldSearch) {
|
|
436
|
+
if (isClarification && triageData.web_search_needed) {
|
|
437
|
+
console.log(`[web-search] AI set web_search_needed=true but response contains input controls — returning clarification`);
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
440
|
+
console.log(`[web-search] No search needed (web_search_needed=${triageData.web_search_needed}), returning user_data`);
|
|
441
|
+
}
|
|
442
|
+
const rawResponse = JSON.stringify(triageData.user_data);
|
|
443
|
+
return {
|
|
444
|
+
content: triageData.user_data,
|
|
445
|
+
rawResponse,
|
|
446
|
+
usage: {
|
|
447
|
+
promptTokens: totalInputTokens,
|
|
448
|
+
completionTokens: totalOutputTokens,
|
|
449
|
+
totalTokens: totalInputTokens + totalOutputTokens,
|
|
450
|
+
},
|
|
451
|
+
model: triageResult.model,
|
|
452
|
+
provider: this.providerName,
|
|
453
|
+
latencyMs: Date.now() - startTime,
|
|
454
|
+
finishReason: triageResult.finishReason,
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
// --- Step 2: Web search -----------------------------------------------
|
|
458
|
+
console.log(`[web-search] Step 2: Searching the web`);
|
|
459
|
+
const searchResult = await this.searchWeb(model, request.prompt, temperature);
|
|
460
|
+
totalInputTokens += searchResult.usage.inputTokens;
|
|
461
|
+
totalOutputTokens += searchResult.usage.outputTokens;
|
|
462
|
+
console.log(`[web-search] Step 2 done: ${searchResult.summary.length} chars`);
|
|
463
|
+
// --- Step 3: Structure search results (Responses API) -----------------
|
|
464
|
+
console.log(`[web-search] Step 3: Structuring search results`);
|
|
465
|
+
const structureSystemPrompt = (request.systemPrompt ?? "") +
|
|
466
|
+
"\n\n## Important\n" +
|
|
467
|
+
"You are being given web search results. Use ONLY the facts from " +
|
|
468
|
+
"these results to build your response. Do not fabricate any names, " +
|
|
469
|
+
"addresses, or data not found in the search results.";
|
|
470
|
+
const structureInput = this.buildResponsesInput(structureSystemPrompt, `Original request: ${request.prompt}\n\n` +
|
|
471
|
+
`Web search results:\n\n${searchResult.summary}\n\n` +
|
|
472
|
+
"Using ONLY the information from the web search results above, " +
|
|
473
|
+
"generate the structured response.");
|
|
474
|
+
const structureResult = await this.callResponsesStructured(model, structureInput, userSchema, temperature, request.maxTokens);
|
|
475
|
+
totalInputTokens += structureResult.usage.inputTokens;
|
|
476
|
+
totalOutputTokens += structureResult.usage.outputTokens;
|
|
477
|
+
console.log(`[web-search] Step 3 done, total time: ${Date.now() - startTime}ms`);
|
|
478
|
+
return {
|
|
479
|
+
content: structureResult.content,
|
|
480
|
+
rawResponse: structureResult.rawResponse,
|
|
481
|
+
usage: {
|
|
482
|
+
promptTokens: totalInputTokens,
|
|
483
|
+
completionTokens: totalOutputTokens,
|
|
484
|
+
totalTokens: totalInputTokens + totalOutputTokens,
|
|
485
|
+
},
|
|
486
|
+
model: structureResult.model,
|
|
487
|
+
provider: this.providerName,
|
|
488
|
+
latencyMs: Date.now() - startTime,
|
|
489
|
+
finishReason: structureResult.finishReason,
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
buildApiPayload(request) {
|
|
493
|
+
const model = request.model ?? this.defaultModel;
|
|
494
|
+
const caps = getModelCapabilities(model);
|
|
495
|
+
// Build user message content (multimodal)
|
|
496
|
+
const userContent = [];
|
|
497
|
+
if (request.media?.length) {
|
|
498
|
+
for (const m of request.media) {
|
|
499
|
+
if (m.type === "image") {
|
|
500
|
+
userContent.push({
|
|
501
|
+
type: "image_url",
|
|
502
|
+
image_url: {
|
|
503
|
+
url: m.format === "base64"
|
|
504
|
+
? `data:${m.mimeType};base64,${m.data}`
|
|
505
|
+
: m.data,
|
|
506
|
+
},
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
if (m.type === "audio") {
|
|
510
|
+
const format = getOpenAIAudioFormat(m.mimeType);
|
|
511
|
+
userContent.push({
|
|
512
|
+
type: "input_audio",
|
|
513
|
+
input_audio: {
|
|
514
|
+
data: m.data,
|
|
515
|
+
format,
|
|
516
|
+
},
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
userContent.push({ type: "text", text: request.prompt });
|
|
522
|
+
// Build messages array
|
|
523
|
+
const messages = [];
|
|
524
|
+
if (request.systemPrompt) {
|
|
525
|
+
messages.push({ role: "system", content: request.systemPrompt });
|
|
526
|
+
}
|
|
527
|
+
messages.push({ role: "user", content: userContent });
|
|
528
|
+
// Audio output configuration
|
|
529
|
+
const modalities = ["text"];
|
|
530
|
+
let audioConfig;
|
|
531
|
+
if (request.expectsMediaOutput?.audio && caps.audioOutput) {
|
|
532
|
+
modalities.push("audio");
|
|
533
|
+
audioConfig = {
|
|
534
|
+
voice: "alloy",
|
|
535
|
+
format: "mp3",
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
return {
|
|
539
|
+
model,
|
|
540
|
+
messages,
|
|
541
|
+
...(audioConfig ? { modalities, audio: audioConfig } : {}),
|
|
542
|
+
tools: [
|
|
543
|
+
{
|
|
544
|
+
type: "function",
|
|
545
|
+
function: {
|
|
546
|
+
name: "structured_response",
|
|
547
|
+
description: "Generate structured response matching the schema",
|
|
548
|
+
parameters: request.outputSchema,
|
|
549
|
+
},
|
|
550
|
+
},
|
|
551
|
+
],
|
|
552
|
+
tool_choice: {
|
|
553
|
+
type: "function",
|
|
554
|
+
function: { name: "structured_response" },
|
|
555
|
+
},
|
|
556
|
+
temperature: request.temperature ?? 0,
|
|
557
|
+
[tokenLimitParamFor(this.isOpenAi, model)]: request.maxTokens,
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../src/services/llm/openai.ts"],"names":[],"mappings":"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"}
|