构建 AI 招聘助手
在本指南中,你将了解 Mastra 如何帮助你构建使用 LLM 的 Workflow。
你将创建一个 Workflow,从候选人的简历中收集信息,然后根据候选人资料分支到技术问题或行为问题。在此过程中,你会了解如何组织 Workflow 步骤、处理分支,以及集成 LLM 调用。
前提条件前提条件的直接链接
- 已安装 Node.js
v22.13.0或更高版本 - 受支持的 Model Provider 提供的 API 密钥
- 现有的 Mastra 项目(按照安装指南设置新项目)
构建 Workflow构建 Workflow的直接链接
设置 Workflow,定义用于提取和分类候选人数据的步骤,然后提出合适的后续问题。
新建文件
src/mastra/workflows/candidate-workflow.ts并定义 Workflow:src/mastra/workflows/candidate-workflow.tsimport { createWorkflow, createStep } from '@mastra/core/workflows'import { z } from 'zod'export const candidateWorkflow = createWorkflow({id: 'candidate-workflow',inputSchema: z.object({resumeText: z.string(),}),outputSchema: z.object({askAboutSpecialty: z.object({question: z.string(),}),askAboutRole: z.object({question: z.string(),}),}),}).commit()你需要从简历文本中提取候选人的详细信息,并将其分类为“技术”或“非技术”人员。此步骤会调用 LLM 来解析简历,并返回结构化 JSON,其中包含姓名、是否属于技术人员、专业领域和原始简历文本。通过
inputSchema定义后,你可以在execute()内访问resumeText。使用它向 LLM 发出提示,并返回整理后的字段。将以下内容添加到现有的
src/mastra/workflows/candidate-workflow.ts文件:src/mastra/workflows/candidate-workflow.tsimport { Agent } from '@mastra/core/agent'const recruiter = new Agent({id: 'recruiter-agent',name: 'Recruiter Agent',instructions: `You are a recruiter.`,model: 'openai/gpt-5.6-sol',})const gatherCandidateInfo = createStep({id: 'gatherCandidateInfo',inputSchema: z.object({resumeText: z.string(),}),outputSchema: z.object({candidateName: z.string(),isTechnical: z.boolean(),specialty: z.string(),resumeText: z.string(),}),execute: async ({ inputData }) => {const resumeText = inputData?.resumeTextconst prompt = `Extract details from the resume text:"${resumeText}"`const res = await recruiter.generate(prompt, {structuredOutput: {schema: z.object({candidateName: z.string(),isTechnical: z.boolean(),specialty: z.string(),resumeText: z.string(),}),},})return res.object},})由于你在
execute()内使用了 Recruiter Agent,需要在该步骤上方定义它,并添加所需的 import。此步骤会让被识别为“技术”人员的候选人进一步介绍他们如何进入自己的专业领域。它会使用完整的简历文本,以便 LLM 编写相关的后续问题。
将以下内容添加到现有的
src/mastra/workflows/candidate-workflow.ts文件:src/mastra/workflows/candidate-workflow.tsconst askAboutSpecialty = createStep({id: 'askAboutSpecialty',inputSchema: z.object({candidateName: z.string(),isTechnical: z.boolean(),specialty: z.string(),resumeText: z.string(),}),outputSchema: z.object({question: z.string(),}),execute: async ({ inputData: candidateInfo }) => {const prompt = `You are a recruiter. Given the resume below, craft a short questionfor ${candidateInfo?.candidateName} about how they got into "${candidateInfo?.specialty}".Resume: ${candidateInfo?.resumeText}`const res = await recruiter.generate(prompt)return { question: res?.text?.trim() || '' }},})如果候选人属于“非技术”人员,你需要提出不同的后续问题。此步骤会询问他们对该职位最感兴趣的方面,同样会引用其完整简历文本。
execute()函数会让 LLM 生成一个以职位为重点的问题。将以下内容添加到现有的
src/mastra/workflows/candidate-workflow.ts文件:src/mastra/workflows/candidate-workflow.tsconst askAboutRole = createStep({id: 'askAboutRole',inputSchema: z.object({candidateName: z.string(),isTechnical: z.boolean(),specialty: z.string(),resumeText: z.string(),}),outputSchema: z.object({question: z.string(),}),execute: async ({ inputData: candidateInfo }) => {const prompt = `You are a recruiter. Given the resume below, craft a short questionfor ${candidateInfo?.candidateName} asking what interests them most about this role.Resume: ${candidateInfo?.resumeText}`const res = await recruiter.generate(prompt)return { question: res?.text?.trim() || '' }},})现在,把这些步骤组合起来,根据候选人是否属于技术人员实现分支逻辑。Workflow 会先收集候选人数据,然后根据
isTechnical,询问其专业领域或目标职位。具体做法是将gatherCandidateInfo与askAboutSpecialty和askAboutRole串联起来。在现有的
src/mastra/workflows/candidate-workflow.ts文件中,按以下方式更改candidateWorkflow:src/mastra/workflows/candidate-workflow.tsexport const candidateWorkflow = createWorkflow({id: 'candidate-workflow',inputSchema: z.object({resumeText: z.string(),}),outputSchema: z.object({askAboutSpecialty: z.object({question: z.string(),}),askAboutRole: z.object({question: z.string(),}),}),}).then(gatherCandidateInfo).branch([[async ({ inputData: { isTechnical } }) => isTechnical, askAboutSpecialty],[async ({ inputData: { isTechnical } }) => !isTechnical, askAboutRole],]).commit()在
src/mastra/index.ts文件中注册 Workflow:src/mastra/index.tsimport { Mastra } from '@mastra/core'import { candidateWorkflow } from './workflows/candidate-workflow'export const mastra = new Mastra({workflows: { candidateWorkflow },})
测试 Workflow测试 Workflow的直接链接
启动开发服务器后,可以在 Studio 中测试 Workflow:
mastra dev
在侧边栏中转到 Workflows 并选择 candidate-workflow。中间会显示 Workflow 的图形视图,右侧边栏默认选中 Run 选项卡。在此选项卡中,你可以输入简历文本,例如:
Knowledgeable Software Engineer with more than 10 years of experience in software development. Proven expertise in the design and development of software databases and optimization of user interfaces.
输入简历文本后,按下 Run 按钮。此时应该会看到两个状态框(GatherCandidateInfo 和 AskAboutSpecialty),其中包含 Workflow 步骤的输出。
你也可以通过调用 .createRun() 和 .start(),在程序中测试 Workflow。新建文件 src/test-workflow.ts 并添加以下内容:
import { mastra } from './mastra'
const run = await mastra.getWorkflow('candidateWorkflow').createRun()
const res = await run.start({
inputData: {
resumeText:
'Knowledgeable Software Engineer with more than 10 years of experience in software development. Proven expertise in the design and development of software databases and optimization of user interfaces.',
},
})
// Dump the complete workflow result (includes status, steps and result)
console.log(JSON.stringify(res, null, 2))
// Get the workflow output value
if (res.status === 'success') {
const question = res.result.askAboutRole?.question ?? res.result.askAboutSpecialty?.question
console.log(`Output value: ${question}`)
}
现在运行 Workflow,并在终端中查看输出:
npx tsx src/test-workflow.ts
你已经构建了一个 Workflow,它可以解析简历,并根据候选人的技术能力决定要提出的问题。恭喜,祝你开发愉快!