技术札记

垂类大模型不是一个模型:我如何构建本地 AI 求职系统 Atlas

基于 Qwen3-0.6B、MLX LoRA、本地岗位索引、简历解析、规则引擎与意图路由,复盘实习僧 Atlas 从通用模型走向招聘垂类 AI 系统的工程实践。

HOUHUIYANG.COM

扫码继续阅读

正在生成…

垂类大模型不是一个模型:我如何构建本地 AI 求职系统 Atlas

houhuiyang.com/zh/notes/building-atlas-vertical-ai-system

市面上很多产品都被称为“法律大模型”“医疗大模型”或“招聘大模型”。这个名字很容易让人以为,团队从随机权重开始训练了一个全新的行业基础模型。

真实情况通常不是这样。

多数垂类 AI 产品的核心,是把通用基座模型放进一套完整的行业系统:垂直数据负责提供领域经验,RAG 和数据库负责提供事实,规则引擎负责确定性判断,工具负责执行动作,路由负责选择能力,权限与评测体系则决定模型可以看到什么、可以做什么,以及结果是否足够可靠。

我最近构建的实习僧 Atlas,就是这样一个本地 AI 求职模型系统。

Atlas 回答“你是谁”

它并不是从零训练的新基础模型。当前研发版本以 Qwen/Qwen3-0.6B-MLX-4bit 为基座,使用招聘相关性数据进行 MLX LoRA 微调,再结合本地岗位快照、简历解析、检索与排序、资格规则和任务工作流,形成面向校招与实习场景的完整产品。

这篇文章记录的重点,不是如何给通用聊天界面换一层招聘皮肤,而是:怎样让模型只负责它擅长的理解与解释,把事实、权限和执行交给更可靠的系统组件。

垂类大模型首先是系统,而不是权重文件

一个可用的垂类产品通常可以概括为:

通用基础模型
+ 行业 Prompt / LoRA 微调
+ 企业知识库与业务数据库
+ 检索和排序
+ 规则引擎
+ 工具调用与任务工作流
+ 意图路由
+ 权限与安全控制
+ 离线评测与发布门禁

模型权重只是其中一层。

如果让大模型同时承担岗位数量查询、学历条件判断、相关性排序、匹配解释和实际投递,它既容易编造事实,也很难审计。一个生成流畅的模型,并不天然具备事务一致性,更不能凭语言自信程度判断某次投递是否真的成功。

因此 Atlas 从设计之初就把能力拆开:

能力Atlas 中的责任组件
岗位数量与真实字段本地岗位数据库
岗位召回本地向量索引与关键词检索
城市、学历、实习时长等硬条件确定性资格规则
简历与岗位相关性排序逻辑与 Atlas 模型
匹配原因和求职建议本地大语言模型
简历读取范围上下文权限控制
一键投递用户确认后的确定性工作流
模型能否发布冻结评测集与质量门禁

这条边界非常重要:事实由数据源回答,规则由代码执行,语言模型负责理解、归纳和解释。

Atlas 当前的模型身份

Atlas 对自己的回答必须可追溯,而不能只说“我是一个 AI 助手”。当前版本的身份信息包括:

最后一项尤其不能隐藏。适配器已经完成训练并跑通加载与推理链路,不代表它已经达到生产质量。当前数据规模、结构化输出稳定性和独立评测结果仍不足以通过发布门禁,因此产品界面明确标记为实验版。

“训练成功”与“可以上线”是两件不同的事。

三种真实应用场景

目前 Atlas 已经跑通三条面向求职用户的本地工作流。下面的画面均来自当前实验版本的真实问答,不是设计稿或静态演示数据。

1. 根据简历寻找单个城市的工作机会

用户选择一份本机简历后,可以直接询问“帮我寻找深圳的工作机会”。Atlas 从本地岗位库检索并排序,返回相关机会数量、高度匹配数量、推荐岗位和可核查的匹配原因。

Atlas 根据本机简历检索深圳工作机会并解释岗位匹配原因

2. 对比两个城市的机会数量

面对“深圳和杭州哪个城市的机会更多”这类问题,数量来自本地岗位索引的确定性统计,而不是让语言模型猜测。回答同时说明统计口径,避免把简历关键词初筛数量误解为城市全部岗位数。

Atlas 对比深圳与杭州的简历相关岗位数量

3. 跨城市比较并执行模拟投递

Atlas 可以检索两个城市的匹配岗位、生成对比表、把每个城市的首选岗位加入当前会话的投递计划,并执行本机模拟投递。当前实验版不会向任何企业发送真实申请;这条链路用于验证用户确认、任务状态和结果反馈。

Atlas 比较深圳与杭州岗位并完成本机模拟投递流程

四类意图,而不是一个万能聊天入口

用户在求职产品里发出的消息差异很大:

帮我找北京的产品实习
分析一下我的简历
产品经理面试应该怎么准备
唐朝有哪些著名诗人

如果所有消息都进入同一个 Prompt,并自动携带简历与岗位上下文,不仅会浪费推理资源,还可能造成隐私越界和任务污染。

Atlas 目前先把请求路由为四类:

Atlas 整体路由架构:从用户输入到事实校验与输出

路由典型任务是否读取简历岗位策略
job_search搜索、推荐、比较岗位重新检索本地岗位
resume_analysis分析和优化简历不自动推荐岗位
career_chat面试准备、求职建议、岗位追问按需沿用已有结果
general_chat非招聘通用问题不读取岗位

下面这张简化图更直接地展示了四种业务模式与安全兜底如何汇入统一回答层:

Atlas 四模式简化路由架构

路由之后,系统再决定使用哪套系统提示词、是否注入候选人画像、是否访问本地岗位索引,以及回答是来自确定性逻辑还是模型生成。

例如,“北京有多少个适合我的岗位”不应由模型根据语感猜一个数字。系统先查询与当前简历相关的本地索引,再把确定结果交给回答层。模型可以解释这些岗位为什么值得关注,但不能改写岗位数量。

同一个模型可以有两种上下文,但仍有局限

当前 Atlas MVP 使用同一个 Qwen3 0.6B 基座和同一个 Atlas LoRA,通过两套系统提示词与上下文隔离支持通用模式和求职模式:

用户消息
→ 意图分类
→ 选择 general 或 career 系统提示词
→ 按路由决定是否读取简历与岗位
→ 本地模型生成或确定性旁路回答

这套设计开发快、运行简单,适合验证本地产品闭环。它已经解决了一个关键问题:通用问题不会收到简历、岗位列表或岗位数量等招聘上下文。

但它仍有明显限制:通用模式虽然换了 Prompt,却仍然加载招聘 LoRA。 微调形成的招聘倾向可能残留在通用回答里。Prompt 可以约束当前任务,却不能完全抹掉适配器对模型行为的影响。

因此更成熟的下一步不是继续堆 Prompt,而是按任务切换适配器:

general_chat
→ 通用 Instruct 基座
→ 不加载招聘 LoRA
→ 不读取简历和岗位

resume_analysis / career_chat
→ 相同基础模型
→ 按需加载 Atlas 招聘 LoRA
→ 只读取已授权上下文

job_search
→ 本地岗位索引与确定性规则
→ 模型只负责解释

投递任务
→ 用户确认
→ 确定性业务接口执行
→ 返回真实操作状态

这样既能共享 tokenizer、基础权重和推理设施,又能避免招聘微调持续影响通用能力。

本地运行不是一句隐私口号

Atlas 的简历、岗位索引、会话数据库和模型推理都保留在本机。macOS 桌面端使用原生 AppKit 与 WebKit,只作为本地服务的轻量外壳;模型通过 MLX 在 Apple Silicon 上加载和推理。

但“本地”本身并不自动等于“安全”。系统仍需要明确:

真正的隐私来自可验证的数据流,而不只是界面上的“本地 AI”标签。

为什么小模型仍值得做

Qwen3-0.6B 是一个实验级小模型。它的知识广度、复杂推理和指令稳定性都不能与更大的生产模型相比。

但小模型对这一阶段仍然有价值:

如果一个产品只有在模型“无所不能”时才成立,它通常还没有形成可靠架构。相反,当 0.6B 模型只承担受控的语言任务,系统仍能提供真实岗位、可解释匹配和安全执行,这套产品骨架才有长期价值。

当前实验版本与线上模型规划

需要特别说明的是,本文展示的 Qwen3-0.6B-MLX-4bit + LoRA 只是当前本地实验版本。现阶段的目标不是证明 0.6B 小模型已经具备生产级招聘能力,而是先用较低成本跑通数据处理、LoRA 训练、模型加载、意图路由、上下文隔离、本地检索、规则判断和质量评测这一整条链路。

线上版本规划采用更强的 Qwen/Qwen3.5-27B + QLoRA。届时仍会保留现在已经验证过的系统边界:岗位事实来自数据库,硬性条件由规则判断,模型主要负责语义理解、相关性分析和解释生成,高风险动作则必须经过用户确认和确定性工作流。

因此,当前 0.6B 版本更像是一套可运行的工程验证环境,而不是最终模型结论。它帮助我尽早暴露数据、训练、路由、隐私和评测问题;等整条链路稳定后,再把更大的训练与推理成本投入线上模型,避免一开始就用昂贵模型掩盖系统设计上的缺陷。

我从 Atlas 得到的结论

所谓“垂类大模型”,更准确地说是一个以行业模型为核心、但不把所有责任推给模型的产品系统。

它的竞争力不只来自一次 LoRA 训练,而来自一整套持续积累:

因此,我会把 Atlas 描述为:

基于 Qwen3-0.6B-MLX-4bit,通过 Atlas 招聘数据进行 LoRA 微调,并结合本地岗位检索、简历解析、资格规则、意图路由和任务工作流构建的招聘垂类模型系统。

它不是从零训练的全新基础模型,也还不是生产级产品。但它已经验证了一条更务实的路线:用通用模型获得语言能力,用垂直数据获得领域偏好,用数据库和规则守住事实,再用权限、评测与工作流把模型变成真正可用的产品。

返回技术札记