Skip to content

Commit d8c8cf8

Browse files
committed
fix: gen obj retry
1 parent adb0874 commit d8c8cf8

File tree

2 files changed

+45
-18
lines changed

2 files changed

+45
-18
lines changed

src/agent.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,8 @@ ${k.references[0]}
6767
</url>
6868
` : ''}
6969
70-
<answer>
70+
7171
${k.answer}
72-
</answer>
7372
`.trim();
7473
messages.push({role: 'assistant', content: removeExtraLineBreaks(aMsg)});
7574
});
@@ -490,6 +489,7 @@ export async function getResponse(question?: string,
490489
schema,
491490
system,
492491
messages: msgWithKnowledge,
492+
numRetries: 2,
493493
});
494494
thisStep = {
495495
action: result.object.action,
@@ -617,7 +617,7 @@ ${currentQuestion}
617617
</question>
618618
619619
<answer>
620-
${thisStep.answer}
620+
${buildMdFromAnswer(thisStep)}
621621
</answer>
622622
`,
623623
answer: `
@@ -900,7 +900,8 @@ But unfortunately, you failed to solve the issue. You need to think out of the b
900900
model: 'agentBeastMode',
901901
schema,
902902
system,
903-
messages: msgWithKnowledge
903+
messages: msgWithKnowledge,
904+
numRetries: 2
904905
});
905906
thisStep = {
906907
action: result.object.action,

src/utils/safe-generator.ts

+40-14
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ interface GenerateOptions<T> {
2121
prompt?: string;
2222
system?: string;
2323
messages?: CoreMessage[];
24+
numRetries?: number;
2425
}
2526

2627
export class ObjectGeneratorSafe {
@@ -135,8 +136,13 @@ export class ObjectGeneratorSafe {
135136
prompt,
136137
system,
137138
messages,
139+
numRetries = 0,
138140
} = options;
139141

142+
if (!model || !schema) {
143+
throw new Error('Model and schema are required parameters');
144+
}
145+
140146
try {
141147
// Primary attempt with main model
142148
const result = await generateObject({
@@ -160,36 +166,56 @@ export class ObjectGeneratorSafe {
160166
return errorResult;
161167

162168
} catch (parseError) {
163-
// Second fallback: Try with fallback model if provided
164-
const fallbackModel = getModel('fallback');
165-
if (NoObjectGeneratedError.isInstance(parseError)) {
166-
const failedOutput = (parseError as any).text;
167-
console.error(`${model} failed on object generation ${failedOutput} -> manual parsing failed again -> trying fallback model`);
169+
170+
if (numRetries > 0) {
171+
console.error(`${model} failed on object generation -> manual parsing failed -> retry with ${numRetries - 1} retries remaining`);
172+
return this.generateObject({
173+
model,
174+
schema,
175+
prompt,
176+
system,
177+
messages,
178+
numRetries: numRetries - 1
179+
});
180+
} else {
181+
// Second fallback: Try with fallback model if provided
182+
const fallbackModel = getModel('fallback');
183+
console.error(`${model} failed on object generation -> manual parsing failed -> trying fallback with distilled schema`);
168184
try {
185+
let failedOutput = '';
186+
187+
if (NoObjectGeneratedError.isInstance(parseError)) {
188+
failedOutput = (parseError as any).text;
189+
// find last `"url":` appear in the string, which is the source of the problem
190+
failedOutput = failedOutput.slice(0, Math.min(failedOutput.lastIndexOf('"url":'), 8000));
191+
}
192+
169193
// Create a distilled version of the schema without descriptions
170194
const distilledSchema = this.createDistilledSchema(schema);
171-
// find last `"url":` appear in the string, which is the source of the problem
172-
const tailoredOutput = failedOutput.slice(0, Math.min(failedOutput.lastIndexOf('"url":'), 8000));
173195

174196
const fallbackResult = await generateObject({
175197
model: fallbackModel,
176198
schema: distilledSchema,
177-
prompt: `Following the given JSON schema, extract the field from below: \n\n ${tailoredOutput}`,
199+
prompt: `Following the given JSON schema, extract the field from below: \n\n ${failedOutput}`,
178200
maxTokens: getToolConfig('fallback').maxTokens,
179201
temperature: getToolConfig('fallback').temperature,
180202
});
181203

182-
this.tokenTracker.trackUsage(model, fallbackResult.usage);
183-
console.log('Distilled schema parse success!')
204+
this.tokenTracker.trackUsage(fallbackModel, fallbackResult.usage); // Track against fallback model
205+
console.log('Distilled schema parse success!');
184206
return fallbackResult;
185207
} catch (fallbackError) {
186208
// If fallback model also fails, try parsing its error response
187-
return await this.handleGenerateObjectError<T>(fallbackError);
209+
try {
210+
const lastChanceResult = await this.handleGenerateObjectError<T>(fallbackError);
211+
this.tokenTracker.trackUsage(fallbackModel, lastChanceResult.usage);
212+
return lastChanceResult;
213+
} catch (finalError) {
214+
console.error(`All recovery mechanisms failed`);
215+
throw error; // Throw original error for better debugging
216+
}
188217
}
189218
}
190-
191-
// If no fallback model or all attempts failed, throw the original error
192-
throw error;
193219
}
194220
}
195221
}

0 commit comments

Comments
 (0)