@jaypie/llm 1.3.12 → 1.3.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/cjs/index.cjs +79 -3
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/operate/adapters/FireworksAdapter.d.ts +1 -0
- package/dist/cjs/operate/adapters/ProviderAdapter.interface.d.ts +13 -0
- package/dist/cjs/operate/types.d.ts +9 -0
- package/dist/esm/index.js +79 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/operate/adapters/FireworksAdapter.d.ts +1 -0
- package/dist/esm/operate/adapters/ProviderAdapter.interface.d.ts +13 -0
- package/dist/esm/operate/types.d.ts +9 -0
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -485,6 +485,15 @@ function resolveModelChain(model) {
|
|
|
485
485
|
* Providers can extend this class to reduce boilerplate.
|
|
486
486
|
*/
|
|
487
487
|
class BaseProviderAdapter {
|
|
488
|
+
constructor() {
|
|
489
|
+
/**
|
|
490
|
+
* Whether OperateLoop may take a corrective turn when a `format` request
|
|
491
|
+
* completes with prose instead of structured output. Providers whose
|
|
492
|
+
* structured output rides a tool emulation (where compliance is a model
|
|
493
|
+
* decision) opt in; native grammar-constrained providers do not need it.
|
|
494
|
+
*/
|
|
495
|
+
this.supportsStructuredOutputRetry = false;
|
|
496
|
+
}
|
|
488
497
|
/**
|
|
489
498
|
* Default implementation checks if error is retryable via classifyError
|
|
490
499
|
*/
|
|
@@ -3412,6 +3421,10 @@ class FireworksAdapter extends BaseProviderAdapter {
|
|
|
3412
3421
|
super(...arguments);
|
|
3413
3422
|
this.name = PROVIDER.FIREWORKS.NAME;
|
|
3414
3423
|
this.defaultModel = PROVIDER.FIREWORKS.DEFAULT;
|
|
3424
|
+
// Structured output with tools rides the structured_output tool emulation
|
|
3425
|
+
// (Fireworks rejects response_format + tools), and emulation compliance is
|
|
3426
|
+
// a model decision — opt in to OperateLoop's corrective retry turn.
|
|
3427
|
+
this.supportsStructuredOutputRetry = true;
|
|
3415
3428
|
// Session-level cache of models observed to reject native
|
|
3416
3429
|
// `response_format: json_schema`. When a model is in this set, buildRequest
|
|
3417
3430
|
// engages the legacy fake-tool path instead of native structured output.
|
|
@@ -3466,9 +3479,10 @@ class FireworksAdapter extends BaseProviderAdapter {
|
|
|
3466
3479
|
const useFallbackStructuredOutput = Boolean(request.format) &&
|
|
3467
3480
|
(hasCallerTools ||
|
|
3468
3481
|
!this.supportsStructuredOutput(fireworksRequest.model));
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3482
|
+
// On a corrective retry turn (the model answered a format request with
|
|
3483
|
+
// prose), offer only the structured_output tool so the demanded call is
|
|
3484
|
+
// the sole option.
|
|
3485
|
+
const allTools = request.tools && !request.structuredOutputRetry ? [...request.tools] : [];
|
|
3472
3486
|
if (useFallbackStructuredOutput && request.format) {
|
|
3473
3487
|
log$1.log.warn(hasCallerTools
|
|
3474
3488
|
? `[FireworksAdapter] Fireworks does not support response_format combined with tools; using structured_output tool emulation for model ${fireworksRequest.model}.`
|
|
@@ -8009,6 +8023,31 @@ function createErrorClassifier(adapter) {
|
|
|
8009
8023
|
},
|
|
8010
8024
|
};
|
|
8011
8025
|
}
|
|
8026
|
+
/**
|
|
8027
|
+
* Attempt to read a prose response as the structured payload itself: parse the
|
|
8028
|
+
* text (stripping a Markdown code fence if present) and return the object, or
|
|
8029
|
+
* undefined when the text is not a JSON object.
|
|
8030
|
+
*/
|
|
8031
|
+
function tryParseJsonObject(text) {
|
|
8032
|
+
let candidate = text.trim();
|
|
8033
|
+
const fence = candidate.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/);
|
|
8034
|
+
if (fence) {
|
|
8035
|
+
candidate = fence[1].trim();
|
|
8036
|
+
}
|
|
8037
|
+
if (!candidate.startsWith("{")) {
|
|
8038
|
+
return undefined;
|
|
8039
|
+
}
|
|
8040
|
+
try {
|
|
8041
|
+
const parsed = JSON.parse(candidate);
|
|
8042
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
8043
|
+
return parsed;
|
|
8044
|
+
}
|
|
8045
|
+
}
|
|
8046
|
+
catch {
|
|
8047
|
+
// Not JSON; caller falls through to the corrective-turn path.
|
|
8048
|
+
}
|
|
8049
|
+
return undefined;
|
|
8050
|
+
}
|
|
8012
8051
|
//
|
|
8013
8052
|
//
|
|
8014
8053
|
// Main
|
|
@@ -8077,6 +8116,7 @@ class OperateLoop {
|
|
|
8077
8116
|
messages: state.currentInput,
|
|
8078
8117
|
model: modelName,
|
|
8079
8118
|
providerOptions: options.providerOptions,
|
|
8119
|
+
structuredOutputRetry: state.structuredOutputRetry,
|
|
8080
8120
|
system: options.system,
|
|
8081
8121
|
temperature: options.temperature,
|
|
8082
8122
|
tools: state.formattedTools,
|
|
@@ -8480,6 +8520,42 @@ class OperateLoop {
|
|
|
8480
8520
|
return true; // Continue to next turn
|
|
8481
8521
|
}
|
|
8482
8522
|
}
|
|
8523
|
+
// Format contract enforcement: the loop is about to complete but the
|
|
8524
|
+
// model answered with prose instead of structured output.
|
|
8525
|
+
if (state.formattedFormat && typeof parsed.content === "string") {
|
|
8526
|
+
// First salvage attempt: the text may be the JSON itself (with or
|
|
8527
|
+
// without a code fence).
|
|
8528
|
+
const salvaged = tryParseJsonObject(parsed.content);
|
|
8529
|
+
if (salvaged) {
|
|
8530
|
+
state.responseBuilder.setContent(this.applyFormatArrayDefaults(salvaged, options));
|
|
8531
|
+
state.responseBuilder.complete();
|
|
8532
|
+
for (const item of this.adapter.responseToHistoryItems(parsed.raw)) {
|
|
8533
|
+
state.responseBuilder.appendToHistory(item);
|
|
8534
|
+
}
|
|
8535
|
+
return false; // Stop loop
|
|
8536
|
+
}
|
|
8537
|
+
// Corrective turn: for adapters whose structured output rides a tool
|
|
8538
|
+
// emulation, take another turn offering only the structured_output tool
|
|
8539
|
+
// and demand it be called. Bounded by maxTurns.
|
|
8540
|
+
if (this.adapter.supportsStructuredOutputRetry &&
|
|
8541
|
+
state.currentTurn < state.maxTurns) {
|
|
8542
|
+
log.warn(`[operate] Model returned text despite format on turn ${state.currentTurn}; retrying with structured_output tool only`);
|
|
8543
|
+
for (const item of this.adapter.responseToHistoryItems(parsed.raw)) {
|
|
8544
|
+
state.currentInput.push(item);
|
|
8545
|
+
state.responseBuilder.appendToHistory(item);
|
|
8546
|
+
}
|
|
8547
|
+
const corrective = {
|
|
8548
|
+
content: "You must provide your final answer by calling the structured_output tool " +
|
|
8549
|
+
"with arguments matching the required schema. Do not respond with text.",
|
|
8550
|
+
role: exports.LlmMessageRole.User,
|
|
8551
|
+
type: exports.LlmMessageType.Message,
|
|
8552
|
+
};
|
|
8553
|
+
state.currentInput.push(corrective);
|
|
8554
|
+
state.responseBuilder.appendToHistory(corrective);
|
|
8555
|
+
state.structuredOutputRetry = true;
|
|
8556
|
+
return true; // Continue to corrective turn
|
|
8557
|
+
}
|
|
8558
|
+
}
|
|
8483
8559
|
// No tool calls or no toolkit - we're done
|
|
8484
8560
|
state.responseBuilder.setContent(this.applyFormatArrayDefaults(parsed.content, options));
|
|
8485
8561
|
state.responseBuilder.complete();
|