任务:
把 juejin.cn/post/769598... 的手动流程改成一个 for 循环。
三样东西缺一不可:
- 终止条件:
finish_reason === 'stop', 或者没有tool_calls - 最大步数: 必须有,否则它会反复调同一个工具,安静地烧完你的额度
- 异常兜底: 工具执行失败时,把错误信息作为结果回填给模型
typescript
const MAX_STEPS = 5; //最大调用次数
const runAgent = async () => {
for (let setup = 1; setup <= MAX_STEPS; setup++) {
const started = Date.now();
const response = await client.chat.completions.create({
model: MODEL,
messages,
tools,
})
const choice = response.choices?.[0];
if (!choice) {
console.log(`当前模型没有返回任何结果`);
return;
}
messages.push(choice.message);
// 对话结束
if (choice.finish_reason === "stop") {
console.log(`当前模型对话结束: ${choice.message.content}`);
dumpMessages(messages);
return;
}
// 对话超出长度被截取
if (choice.finish_reason === "length") {
console.log(`当前对话超出最大长度, 请调大max_token`);
return;
}
// 调用工具
if (choice.finish_reason === "tool_calls" && choice.message.tool_calls) {
for (const toolCall of choice.message.tool_calls) {
let content: string;
// 错误处理
try {
const args = JSON.parse(toolCall.function.arguments)
const name = toolCall.function.name
content = JSON.stringify(executeTool(name, args))
} catch (error) {
content = `工具执行失败: ${error instanceof Error ? error.message : String(error)}`
}
messages.push({
role: "tool",
tool_call_id: toolCall.id,
content,
});
}
continue;
}
console.log(`没有出现预期的 finish_reason: ${choice.finish_reason}`);
return;
}
console.log(`对话达到最高次数 ${MAX_STEPS},仍未结束`);
}