Guides / 视频转图文攻略

Jev 简历筛选实战:Express + Jev JavaScript SDK 搭一个 AI 简历评估器

逐帧拆解 Mohammad Azam 的 Resume Evaluator 演示:上传 PDF 简历,面对 10 道类型化 Jev 问题——8 道 noul 技能判定、1 道 choice 经验级别、1 道 score 技术匹配——输出带置信度百分比的 Yes/No 技能卡与 Excellent/Poor Match 裁决。

速览结论

Mohammad Azam(azamsharp)这支 6 分 48 秒的演示用 Express 服务器加 Jev JavaScript SDK 跑通了完整的 Jev 简历筛选闭环。应用叫「Resume Evaluator」,是一个静态单页,招聘岗位写明 Senior SwiftUI Developer,Downloads 文件夹里备好三份合成简历:资深 SwiftUI 开发者、入门级 SwiftUI 开发者,以及一位本不该来投递的 Python 开发者。上传简历会 POST 到 /api/upload:multer 存下文件,readPdf 加 extractText({ mergePages: true }) 抽出全文,再由 client.systemOne({ state: { document: text }, questions: resumeQuestions }) 把文本交给 Jev。问题集覆盖全部三种类型化原语:8 道 noul 判断题(SwiftUI、SwiftData、网络/REST API、Swift 并发、测试、架构、持久化、生产应用经验,每题一句话,比如「Does the candidate have experience with SwiftUI?」)、1 道 choice 题(experience_level,criteria 分 entry_level / mid_level / senior 三档)、1 道 score 题(technical_fit 按三级 rubric 从「证据有限」打到「资深 SwiftUI 能力证据充分」)。mapResumeEvaluation 把原始概率整形成 UI 可直接渲染的 JSON:hasExperience 取 answers.<question>.noul >= 0.5,confidence 就是同一个 noul 值,experienceLevel 取 choice,technicalFit 取 score。演示数据里,资深简历全部 Yes、置信度 95–99%,Experience Level「Senior」88%、Technical Fit「Excellent Match」95%;入门级简历在测试和生产应用两项上拿到 No,落到「Entry Level / Poor Match」;Python 简历在 SwiftUI、SwiftData 上吃到 No,照样 Poor Match。分数都是假简历上的演示数据,但收尾建议是实打实的生产经验:把评估放进服务端一层,结果写入数据库,候选人只看到「已收到你的简历」,雇主在管理后台查看全部评估。

视频来源

Mohammad Azam

6:48eY2QScteZIs

分步图文攻略

  1. 1

    先看应用:一个上传框,一个 Senior SwiftUI Developer 岗位

    演示开场是「Resume Evaluator」静态单页,副标题就是岗位说明:「Upload your resume to evaluate your experience for a SwiftUI Developer position」。整个客户端只有一个 index.html 文件——一个 Choose File 输入框加一个黑色 Evaluate Resume 按钮。前端没有框架、没有构建,所有智能决策都发生在按钮背后的服务器上。

    Resume Evaluator 上传页面:Choose File 输入框与 Evaluate Resume 按钮,标题写明为 SwiftUI Developer 岗位评估简历经验
    一个静态页、一个按钮——Jev 评估完全放在服务端。跳转至 0:10
  2. 2

    挑一位候选人:三份假简历,一个岗位

    macOS 文件选择器里是 Downloads 目录下的测试语料:python_developer_resume.pdf、entry_level_swiftui_developer_resume.pdf,以及资深候选人的 swiftui_developer_resume.pdf。三份都是为演示写的合成简历。Python 那份是刻意的反例——岗位是 Senior SwiftUI Developer,这份简历就不该得高分;看它失败,是验证评估真的在读文本的最快方式。

    macOS 文件选择器在 Downloads 目录列出 python_developer_resume.pdf、entry_level_swiftui_developer_resume.pdf 和高亮的 swiftui_developer_resume.pdf
    错误技术栈的简历是测试语料的一部分——它不该通过。跳转至 0:45
  3. 3

    资深简历:七项技能全部 Yes,还带置信度

    资深简历的结果卡是一片绿。Skills 下面七项检查全是 Yes——SwiftUI 99%、SwiftData 99%、REST APIs 99%、Swift Concurrency 95%、Testing 97%、Architecture 98%、Persistence 99%——Professional Experience 再加一条 Production App Experience:Yes,95%。每一行都是一道 noul 问题的概率答案,UI 把概率渲染成百分比(假简历上的演示数据,但结构就是生产环境会返回的样子)。

    Resume Evaluation 结果卡:SwiftUI、SwiftData、REST APIs、Swift Concurrency、Testing、Architecture、Persistence 全部 Yes,置信度 95% 到 99%
    每个 Jev 答案都自带置信度,而不只是一个结论。跳转至 1:24
  4. 4

    裁决出炉:Senior 88%,Technical Fit「Excellent Match」

    滚到同一张结果卡底部,Overall Evaluation 区块把两个类型化答案变成招聘裁决。Experience Level 显示 Senior、置信度 88%——这是 choice 题的答案;Technical Fit 显示 Excellent Match、置信度 95%——这是 score 题按三级 rubric 打出的答案。雇主真正读的就是这一对:级别和匹配度,各自带着自己的确定性。

    Overall Evaluation 面板:Experience Level Senior 置信度 88%,Technical Fit Excellent Match 置信度 95%
    choice 给级别,score 给匹配——两个类型化答案合成裁决。跳转至 1:35
  5. 5

    入门级简历:同一套问题,更严的裁决

    入门级 SwiftUI 简历证明了这套问题真的能拉开差距。Testing 拿到 No、置信度 78%,Production App Experience 拿到 No、置信度 84%,Overall Evaluation 落在 Experience Level「Entry Level」置信度 100%、Technical Fit「Poor Match」置信度 98%。有些行仍然是 Yes——但定义资深岗位的那两项不及格,裁决跟着 rubric 走,而不是把绿色平均掉。

    Resume Evaluator 结果卡:Experience Level Entry Level 置信度 100%,Technical Fit Poor Match 裁决
    初级简历过了几项,但输在了最关键的两项上。跳转至 2:06
  6. 6

    技术栈不对,投了也白投:Python 开发者简历

    Python 开发者的结果卡是压力测试。SwiftUI 拿 No、置信度 95%,SwiftData 拿 No、置信度 99%,Swift Concurrency 拿 No、Testing 拿 No——而 REST APIs(89%)、Architecture(71%)、Persistence(94%)保持 Yes,因为数据库和 API 经验可以迁移,框架经验不能。Production App Experience:No,76%。最终裁决:Experience Level「Entry Level」,Technical Fit「Poor Match」。开发者很优秀,但投错了岗位——评估逐行把这话说了出来。

    Python 开发者简历的 Resume Evaluation 结果:SwiftUI 与 SwiftData 标 No,REST APIs、Architecture、Persistence 仍为 Yes
    技术栈对不上,再优秀的开发者也是 Poor Match。跳转至 2:45
  7. 7

    掀开引擎盖:一个 Express 端点跑完整条流水线

    Server 目录里的 app.js 小得令人愉快。app.post('/api/upload', upload.single('resume')) 用 multer 接收文件,readPdf(req.file.path) 和 extractText(new Uint8Array(buffer), { mergePages: true }) 抽出简历全文。这段文本就是 Jev 的 state:const response = await client.systemOne({ state: { document: text }, questions: resumeQuestions })。mapResumeEvaluation(response) 把答案整形成 UI 需要的形状,res.json(evaluation) 返回。下方终端跑着 nodemon,端口 8080——上传、抽取、评估、映射、响应。

    Express app.js 上传端点:依次调用 readPdf、mergePages 为 true 的 extractText,再把简历文本和 resumeQuestions 交给 client.systemOne,最后 mapResumeEvaluation
    上传、抽取、评估、映射——二十来行代码就是整条 Jev 流水线。跳转至 3:28
  8. 8

    写问题:八道 noul 检查覆盖整个技术栈

    Server/questions 下的 resumeQuestions.js 定义了要问 Jev 什么。八条 type: "noul"——has_swiftui_experience、has_swiftdata_experience、has_networking_experience(「是否消费 REST API 或发起网络请求的经验」)、has_concurrency_experience(async/await、Task、actor)、has_testing_experience(为 iOS 应用写自动化测试)、has_architecture_experience、has_persistence_experience(SwiftData、Core Data、SQLite)、has_production_experience(「是否有真实用户在生产环境用过的应用经验」)。每题一句平实的英文——整套 rubric 一屏读完。

    resumeQuestions.js 文件定义八道 type 为 noul 的问题,包括 has_swiftui_experience、has_swiftdata_experience、has_persistence_experience,各配一句话说明
    每道题就是一句话,模型用一个「是」的概率来回答。跳转至 4:12
  9. 9

    不止是非题:choice 和 score 给候选人排位

    同一文件的下半段展示另外两种类型化原语。experience_level 是 type: "choice"——「候选人的 iOS 开发经验级别是什么?」,criteria 写明 entry_level(「以教育、个人项目、实习为主」)、mid_level(「数年专业 iOS 开发经验,能独立负责功能」)、senior(「在架构、复杂系统、技术主导或领导方面经验深厚」)。technical_fit 是 type: "score",按三行 rubric 打分,从证据有限一路到「资深 SwiftUI 能力、大量专业 iOS 经验、架构主导权与资深技术责任的有力证据」。

    resumeQuestions.js 中 experience_level 为 choice 问题,含 entry_level、mid_level、senior 三档 criteria,technical_fit 为 score 问题,配三级评分 rubric
    choice 返回标签,score 返回等级——都是类型化、都靠 rubric 驱动。跳转至 4:20
  10. 10

    映射响应:一个 0.5 阈值把概率变成 Yes 或 No

    Server/mappers/resumeEvaluationMapper.js 把 Jev 的原始输出变成 UI JSON。每项技能的 hasExperience 取 response.answers.has_swiftui_experience.noul >= 0.5,confidence 就是同一个 noul 值——0.5 这个阈值是概率变成标签的唯一位置,不同岗位可以调。映射器继续处理 productionExperience、experienceLevel(choice 加置信度)和 technicalFit(score 加置信度),页面永远不会看到它渲染不了的东西。

    mapResumeEvaluation 函数:用 0.5 阈值把 response.answers.has_swiftui_experience.noul 转成布尔值,并把同一个 noul 值复制为 confidence
    Yes/No 的分界线就这一个数字——默认 0.5,按岗位可调。跳转至 4:38

常见问题(FAQ)

什么是 Jev 简历筛选?

就是视频里演示的流程:抽取上传简历的文本,用 Jev System One 按一套固定的类型化问题来评估,让每位候选人都按同一把尺子打分——八道是非题技能检查、一道经验级别 choice、一道技术匹配 score——而不是拿到一份每次形状都不一样的自由发挥式 LLM 总结。

结果卡里的置信度百分比是什么意思?

每个 noul 答案是一个 0 到 1 之间、「答案为是」的概率。映射器用 0.5 阈值切出 Yes/No 标签,UI 用 Math.round(confidence * 100) 显示成「99% confidence」——答案为 No 时显示 1 减概率。视频里的具体数字都是假简历上的演示数据。

noul、choice、score 三种问题类型分别是什么?

noul 是返回概率的是非题(「候选人是否有 SwiftData 经验?」);choice 从一组带判据的标签里返回一个——演示里的 experience_level 提供 entry_level、mid_level、senior 三档,各配文字判据;score 按有序 rubric 打分——technical_fit 分三级,从「证据有限」到「资深 SwiftUI 能力的有力证据」。

这个 demo 怎么走向生产环境?

作者自己的收尾建议:把评估放进服务端一层。真实的招聘应用里,候选人上传简历,服务器跑 Jev 评估,结果写入数据库。候选人只会看到「感谢投递简历」,而雇主在管理后台查看每一次评估。

相关推荐

更多视频攻略