为什么要使用工作流?
直接让 LLM “一步到位”往往会导致不稳定的输出。通过工作流模式,我们可以:
- 分解复杂度:将大任务拆解为小步骤。
- 提高可靠性:在步骤之间加入检查和重试机制。
- 降低成本:简单的步骤使用小模型,复杂的步骤使用大模型。
AI SDK 总结了 5 种最常用的模式:顺序处理、路由、并行处理、编排者-执行者、评估-优化。
1. 顺序处理 (Sequential Processing)
这是最基础的模式。上一步的输出作为下一步的输入,形成一条链。适合内容生成流水线或数据转换。
场景:写一段营销文案,然后检查质量,如果质量不达标则重写。
TypeScript
import { generateText, generateObject } from 'ai';
import { z } from 'zod';
import { anthropic } from '@ai-sdk/anthropic'; // 假设使用 Anthropic
async function generateMarketingCopy(input: string) {
const model = anthropic('claude-3-5-sonnet-20240620');
// 第一步:生成初稿
const { text: copy } = await generateText({
model,
prompt: `为以下产品撰写有说服力的营销文案:${input}。注重利益点和情感共鸣。`,
});
// 第二步:质量检查 (结构化输出)
const { object: qualityMetrics } = await generateObject({
model,
schema: z.object({
hasCallToAction: z.boolean(), // 是否有号召性用语
emotionalAppeal: z.number().min(1).max(10), // 情感分
clarity: z.number().min(1).max(10), // 清晰度
}),
prompt: `评估这段文案:
1. 是否包含号召性用语 (true/false)
2. 情感吸引力 (1-10)
3. 清晰度 (1-10)
待评估文案:${copy}`,
});
// 第三步:根据检查结果决定是否重写 (条件逻辑)
if (
!qualityMetrics.hasCallToAction ||
qualityMetrics.emotionalAppeal < 7 ||
qualityMetrics.clarity < 7
) {
const { text: improvedCopy } = await generateText({
model,
prompt: `重写这段文案,必须包含:
${!qualityMetrics.hasCallToAction ? '- 清晰的号召性用语' : ''}
${qualityMetrics.emotionalAppeal < 7 ? '- 更强的情感吸引力' : ''}
${qualityMetrics.clarity < 7 ? '- 提高清晰度和直接性' : ''}
原文:${copy}`,
});
return { copy: improvedCopy, qualityMetrics, status: 'improved' };
}
return { copy, qualityMetrics, status: 'original' };
}
2. 路由 (Routing)
路由模式让 LLM 充当“交通指挥官”。它分析用户的意图,然后决定下一步由哪个模型处理,或者使用什么 Prompt。
场景:根据用户咨询的类型(退款、技术支持、一般问题),分配给不同的处理逻辑或不同大小的模型。
TypeScript
import { generateObject, generateText } from 'ai';
import { z } from 'zod';
import { openai } from '@ai-sdk/openai';
async function handleCustomerQuery(query: string) {
const classifierModel = openai('gpt-4o'); // 智能分类用强模型
// 第一步:分类查询意图
const { object: classification } = await generateObject({
model: classifierModel,
schema: z.object({
reasoning: z.string(),
type: z.enum(['general', 'refund', 'technical']),
complexity: z.enum(['simple', 'complex']),
}),
prompt: `对该客户查询进行分类:
${query}
请确定:
1. 查询类型 (general, refund, technical)
2. 复杂度 (simple, complex)
3. 分类理由`,
});
// 第二步:路由逻辑
// 根据复杂度选择模型:简单问题用小模型省钱,复杂问题用大模型
const targetModel = classification.complexity === 'simple'
? openai('gpt-4o-mini')
: openai('gpt-4o');
// 根据类型选择系统提示词 (System Prompt)
const systemPrompts = {
general: '你是一位专业的客服代表,处理一般性咨询。',
refund: '你是一位专门处理退款的客服。请遵循公司政策并收集必要信息。',
technical: '你是一位拥有深厚产品知识的技术支持专家。专注于清晰的分步故障排除。',
};
const { text: response } = await generateText({
model: targetModel,
system: systemPrompts[classification.type],
prompt: query,
});
return { response, classification };
}
3. 并行处理 (Parallel Processing)
当任务包含多个相互独立的部分时,可以同时运行它们。这既提高了速度,又能让每个 Prompt 专注于单一职责。
场景:代码审查(Code Review)。同时从“安全性”、“性能”和“可维护性”三个维度进行审查,最后汇总。
TypeScript
import { generateText, generateObject } from 'ai';
import { z } from 'zod';
import { anthropic } from '@ai-sdk/anthropic';
async function parallelCodeReview(code: string) {
const model = anthropic('claude-3-5-sonnet-20240620');
// 使用 Promise.all 并行执行三个独立的审查任务
const [securityReview, performanceReview, maintainabilityReview] = await Promise.all([
generateObject({
model,
system: '你是代码安全专家。专注于识别漏洞、注入风险和认证问题。',
schema: z.object({
vulnerabilities: z.array(z.string()),
riskLevel: z.enum(['low', 'medium', 'high']),
suggestions: z.array(z.string()),
}),
prompt: `审查代码:${code}`,
}),
generateObject({
model,
system: '你是性能优化专家。专注于识别瓶颈、内存泄漏和优化机会。',
schema: z.object({
issues: z.array(z.string()),
impact: z.enum(['low', 'medium', 'high']),
optimizations: z.array(z.string()),
}),
prompt: `审查代码:${code}`,
}),
generateObject({
model,
system: '你是代码质量专家。专注于代码结构、可读性和最佳实践。',
schema: z.object({
concerns: z.array(z.string()),
qualityScore: z.number().min(1).max(10),
recommendations: z.array(z.string()),
}),
prompt: `审查代码:${code}`,
}),
]);
// 数据聚合
const reviews = [ { ...securityReview.object, type: 'security' }, { ...performanceReview.object, type: 'performance' }, { ...maintainabilityReview.object, type: 'maintainability' }, ];
// 最后一步:汇总报告
const { text: summary } = await generateText({
model,
system: '你是技术负责人,负责汇总多份代码审查报告。',
prompt: `将这些代码审查结果综合成一份简明的摘要,列出关键行动项:
${JSON.stringify(reviews, null, 2)}`,
});
return { reviews, summary };
}
4. 编排者-执行者 (Orchestrator-Worker)
这是处理复杂任务的强力模式。一个“编排者”模型负责制定计划(Plan),然后拆分出多个子任务,交给“执行者”模型去完成。
场景:实现一个新功能。编排者决定需要修改哪些文件,执行者分别去写每个文件的代码。
TypeScript
import { generateObject } from 'ai';
import { z } from 'zod';
import { anthropic } from '@ai-sdk/anthropic';
async function implementFeature(featureRequest: string) {
const model = anthropic('claude-3-5-sonnet-20240620');
// 1. 编排者 (Orchestrator):制定实施计划
const { object: implementationPlan } = await generateObject({
model,
schema: z.object({
files: z.array(
z.object({
purpose: z.string(),
filePath: z.string(),
changeType: z.enum(['create', 'modify', 'delete']),
}),
),
estimatedComplexity: z.enum(['low', 'medium', 'high']),
}),
system: '你是一位高级软件架构师,负责规划功能实现。',
prompt: `分析此功能请求并制定实施计划:
${featureRequest}`,
});
// 2. 执行者 (Workers):根据计划并行执行
const fileChanges = await Promise.all(
implementationPlan.files.map(async (file) => {
// 针对不同的修改类型,定制 System Prompt
const workerSystemPrompt = {
create: '你是实现新文件的专家,遵循最佳实践和项目模式。',
modify: '你是修改现有代码的专家,保持一致性并避免回退。',
delete: '你是安全删除代码的专家,确保不破坏现有功能。',
}[file.changeType];
const { object: change } = await generateObject({
model,
schema: z.object({
explanation: z.string(),
code: z.string(),
}),
system: workerSystemPrompt,
prompt: `为 ${file.filePath} 实现变更以支持:
${file.purpose}
考虑整体功能上下文:
${featureRequest}`,
});
return {
file,
implementation: change,
};
})
);
return {
plan: implementationPlan,
changes: fileChanges,
};
}
5. 评估-优化循环 (Evaluator-Optimizer)
这是一种“自愈”模式。模型生成结果后,自己(或另一个模型)进行评估。如果不达标,则根据反馈进行优化,直到满足条件或达到最大重试次数。
场景:文学翻译。翻译 -> 评分 -> (如果不完美) 根据意见修正 -> 再次评分。
TypeScript
import { generateText, generateObject } from 'ai';
import { z } from 'zod';
import { anthropic } from '@ai-sdk/anthropic';
async function translateWithFeedback(text: string, targetLanguage: string) {
const model = anthropic('claude-3-5-sonnet-20240620');
let currentTranslation = '';
let iterations = 0;
const MAX_ITERATIONS = 3; // 防止死循环
// 1. 初始翻译
const { text: translation } = await generateText({
model,
system: '你是一位专业的文学翻译家。',
prompt: `将此文本翻译成 ${targetLanguage},保留语气和文化细微差别:
${text}`,
});
currentTranslation = translation;
// 2. 评估-优化 循环
while (iterations < MAX_ITERATIONS) {
// 评估当前翻译
const { object: evaluation } = await generateObject({
model,
schema: z.object({
qualityScore: z.number().min(1).max(10),
preservesTone: z.boolean(),
preservesNuance: z.boolean(),
culturallyAccurate: z.boolean(),
specificIssues: z.array(z.string()),
improvementSuggestions: z.array(z.string()),
}),
system: '你是一位文学翻译评估专家。',
prompt: `评估此翻译:
原文:${text}
翻译:${currentTranslation}
请考虑:整体质量、语气保留、细微差别、文化准确性。`,
});
// 检查是否达到高质量标准
if (
evaluation.qualityScore >= 8 &&
evaluation.preservesTone &&
evaluation.preservesNuance &&
evaluation.culturallyAccurate
) {
break; // 质量达标,跳出循环
}
// 根据反馈生成改进后的翻译
const { text: improvedTranslation } = await generateText({
model,
system: '你是一位专业的文学翻译家。',
prompt: `根据以下反馈改进此翻译:
${evaluation.specificIssues.join('\n')}
${evaluation.improvementSuggestions.join('\n')}
原文:${text}
当前翻译:${currentTranslation}`,
});
currentTranslation = improvedTranslation;
iterations++;
}
return {
finalTranslation: currentTranslation,
iterationsRequired: iterations,
};
}
总结:如何选择?
| 模式 | 适用场景 | 核心优势 |
|---|---|---|
| 顺序处理 | 只有一条路径的任务 | 简单、易维护 |
| 路由 | 输入类型多样的任务 | 针对性强、可优化成本 |
| 并行处理 | 任务可拆分独立的子任务 | 速度快、多视角分析 |
| 编排者-执行者 | 复杂、多步骤、动态子任务 | 处理复杂系统工程能力强 |
| 评估-优化 | 对质量要求极高的任务 | 自我纠错、结果更可靠 |
Vercel AI SDK 通过 generateText 和 generateObject 这两个基础 API,配合 zod 的结构化能力,让实现这些高级模式变得非常简单(且类型安全!)。
希望这篇教程能帮你在项目中构建更强大的 AI Agent!🚀