[Vibe Coding] 降低大模型幻觉 - 重试机制
/**
* 带重试的 LLM 调用执行器
*
* 默认行为:重试时自动将错误信息反馈给 LLM,让它能够根据错误修正输出
*
* @param model 可调用的模型(需要有 invoke 方法)
* @param messages 初始消息数组
* @param options 重试配置
* @returns 执行结果
*
* @example
* const result = await withRetry(structuredModel, messages, {
* maxRetries: 3,
* onRetry: (attempt, error) => console.warn(`Retry ${attempt}:`, error.message)
* });
*/
export async function withRetry<T>(
model: InvokableModel<T>,
messages: any[],
options: RetryOptions = {},
): Promise<T> {
const {
maxRetries = DEFAULT_MAX_RETRIES,
onRetry,
formatErrorFeedback = defaultErrorFeedback,
} = options;
let lastError: Error | null = null;
let currentMessages = [...messages];
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await model.invoke(currentMessages);
} catch (error) {
lastError = error instanceof Error ? error : new Error(String(error));
if (attempt < maxRetries) {
onRetry?.(attempt, lastError);
// 追加错误反馈消息用于下次重试
currentMessages = [
...messages,
new HumanMessage(formatErrorFeedback(lastError)),
];
}
}
}
throw lastError;
}
Usage
// ========== 3. AI 命名调用 ==========
const structuredModel = getStructuredModel(SectionNamingOutputSchema);
const messages = [
new SystemMessage(getSectionNamingSystemPrompt()),
new HumanMessage(getSectionNamingHumanPrompt(sectionsInfo)),
];
console.log("⏳ [SectionNamingNode] 正在调用 AI 命名...");
let result: T_SectionNamingOutput;
try {
result = await withRetry(structuredModel, messages, {
maxRetries: 2,
onRetry: (attempt, error) => {
console.warn(
`⚠️ [SectionNamingNode] 命名重试 ${attempt}: ${error.message}`,
);
},
});
} catch (error) {
console.error("❌ [SectionNamingNode] AI 命名失败:", error);
// Fallback: 使用默认命名
console.log("⚠️ [SectionNamingNode] 使用默认命名作为 fallback");
result = {
namedSections: sections.map((s, i) => ({
index: s.index,
componentName: `Section${i + 1}`,
description: `页面第 ${i + 1} 区域,包含 ${s.totalBlocks} 个元素`,
fileName: `Section${i + 1}`,
})),
};
}

浙公网安备 33010602011771号