> Discover all available pages from the documentation index: https://mastra.zisheng.pro/llms.txt # 构建 AI 招聘助手 在本指南中,你将了解 Mastra 如何帮助你构建使用 LLM 的 Workflow。 你将创建一个 Workflow,从候选人的简历中收集信息,然后根据候选人资料分支到技术问题或行为问题。在此过程中,你会了解如何组织 Workflow 步骤、处理分支,以及集成 LLM 调用。 ## 前提条件 - 已安装 Node.js `v22.13.0` 或更高版本 - 受支持的 [Model Provider](https://mastra.zisheng.pro/models) 提供的 API 密钥 - 现有的 Mastra 项目(按照[安装指南](https://mastra.zisheng.pro/guides/getting-started/quickstart)设置新项目) ## 构建 Workflow 设置 Workflow,定义用于提取和分类候选人数据的步骤,然后提出合适的后续问题。 1. 新建文件 `src/mastra/workflows/candidate-workflow.ts` 并定义 Workflow: ```ts import { 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() ``` 2. 你需要从简历文本中提取候选人的详细信息,并将其分类为“技术”或“非技术”人员。此步骤会调用 LLM 来解析简历,并返回结构化 JSON,其中包含姓名、是否属于技术人员、专业领域和原始简历文本。通过 `inputSchema` 定义后,你可以在 `execute()` 内访问 `resumeText`。使用它向 LLM 发出提示,并返回整理后的字段。 将以下内容添加到现有的 `src/mastra/workflows/candidate-workflow.ts` 文件: ```ts import { 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?.resumeText const 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。 3. 此步骤会让被识别为“技术”人员的候选人进一步介绍他们如何进入自己的专业领域。它会使用完整的简历文本,以便 LLM 编写相关的后续问题。 将以下内容添加到现有的 `src/mastra/workflows/candidate-workflow.ts` 文件: ```ts const 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 question for ${candidateInfo?.candidateName} about how they got into "${candidateInfo?.specialty}". Resume: ${candidateInfo?.resumeText}` const res = await recruiter.generate(prompt) return { question: res?.text?.trim() || '' } }, }) ``` 4. 如果候选人属于“非技术”人员,你需要提出不同的后续问题。此步骤会询问他们对该职位最感兴趣的方面,同样会引用其完整简历文本。`execute()` 函数会让 LLM 生成一个以职位为重点的问题。 将以下内容添加到现有的 `src/mastra/workflows/candidate-workflow.ts` 文件: ```ts const 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 question for ${candidateInfo?.candidateName} asking what interests them most about this role. Resume: ${candidateInfo?.resumeText}` const res = await recruiter.generate(prompt) return { question: res?.text?.trim() || '' } }, }) ``` 5. 现在,把这些步骤组合起来,根据候选人是否属于技术人员实现分支逻辑。Workflow 会先收集候选人数据,然后根据 `isTechnical`,询问其专业领域或目标职位。具体做法是将 `gatherCandidateInfo` 与 `askAboutSpecialty` 和 `askAboutRole` 串联起来。 在现有的 `src/mastra/workflows/candidate-workflow.ts` 文件中,按以下方式更改 `candidateWorkflow`: ```ts 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(), }), }), }) .then(gatherCandidateInfo) .branch([ [async ({ inputData: { isTechnical } }) => isTechnical, askAboutSpecialty], [async ({ inputData: { isTechnical } }) => !isTechnical, askAboutRole], ]) .commit() ``` 6. 在 `src/mastra/index.ts` 文件中注册 Workflow: ```ts import { Mastra } from '@mastra/core' import { candidateWorkflow } from './workflows/candidate-workflow' export const mastra = new Mastra({ workflows: { candidateWorkflow }, }) ``` ## 测试 Workflow 启动开发服务器后,可以在 [Studio](https://mastra.zisheng.pro/docs/studio/overview) 中测试 Workflow: ```bash mastra dev ``` 在侧边栏中转到 **Workflows** 并选择 **candidate-workflow**。中间会显示 Workflow 的图形视图,右侧边栏默认选中 **Run** 选项卡。在此选项卡中,你可以输入简历文本,例如: ```text 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()`](https://mastra.zisheng.pro/reference/workflows/workflow-methods/create-run) 和 [`.start()`](https://mastra.zisheng.pro/reference/workflows/run-methods/start),在程序中测试 Workflow。新建文件 `src/test-workflow.ts` 并添加以下内容: ```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,并在终端中查看输出: ```bash npx tsx src/test-workflow.ts ``` 你已经构建了一个 Workflow,它可以解析简历,并根据候选人的技术能力决定要提出的问题。恭喜,祝你开发愉快!