引言
最近 AI 圈子很热闹,各种新模型层出不穷。但作为一个一直在写代码的开发者,我越来越感觉到:跑通 Demo 和做一个能上线的业务系统,中间隔着巨大的鸿沟。
这段时间我一直在死磕一个基于大模型的智能就业服务系统(包含简历深度解析、人岗精准匹配、AI 模拟面试官)。在这个过程中,我踩了无数个坑,重构了三版代码。
今天不想发什么“震惊体”新闻,只想以一个开发者的身份,和大家聊聊真东西。不管你是正在做毕设的同学,还是想转型 AI 开发的同行,希望能通过这次复盘,和大家在这个浮躁的圈子里做一次纯粹的技术交流。
一、 为什么传统的 RAG 在“人岗匹配”里完全行不通?
在项目初期,我天真地以为:把 JD(职位描述)存进向量数据库,把简历 Embedding 一下,算个 Cosine Similarity(余弦相似度)不就完事了吗?
现实狠狠打了我的脸。
1. 语义相似度的陷阱
当我搜“Java 高级工程师”时,向量数据库经常给我召回“Java 培训班讲师”。
原因在于: 在向量空间里,“写 Java 代码”和“教 Java 代码”在语义上极度接近,但在业务逻辑上却是南辕北辙。通用的大模型 Embedding(如 OpenAI 的 text-embedding-3)很难理解这种垂直领域的细微差异。
2. 我的解决方案:两段式检索 + 业务重排
为了解决这个问题,我把检索流程重构成了一个“漏斗”:
-
第一层:硬性过滤 (SQL Where)
在 Embedding 之前,先提取元数据(Metadata)。利用 LLM 把非结构化的 JD 转化为 JSON:
{ "min_salary": 15000, "location": "Hangzhou", "degree": "Bachelor" }检索时,直接把不符合硬性条件的数据 Pass 掉。这步不靠 AI,靠传统数据库,稳准狠。
-
第二层:混合检索 (Hybrid Search)
同时通过 BM25(关键词匹配)和 Vector(语义匹配)去召回。因为在招聘领域,“SpringBoot”、“Vue3”这些专有名词的精确匹配权重,往往高于语义理解。
-
第三层:BGE Rerank (重排序)
这是最关键的一步。我接入了一个专门的 Rerank 模型,把前 50 个召回结果重新打分。它能精准识别出:“虽然这个简历里提到了 Java,但他主要经历是做销售”,从而把它排到最后。
👉 交流点: 大家在做垂直领域 RAG 时,是用什么策略解决“幻觉检索”的?有没有试过 GraphRAG(知识图谱检索)?最近我也在研究这个方向,欢迎探讨。
二、 让 AI 稳定输出:从“调教 Prompt”到“类型工程”
做简历解析模块时,我最大的痛苦是:LLM 太不可控了。
同一个 Prompt,第一次它输出完美的 JSON,第二次它就在 JSON 外面给你加了一句:“这是您要的结果,注意查收哦~”。这直接导致后端解析失败。
我深刻体会到:Prompt Engineering(提示词工程)的尽头是 Type Engineering(类型工程)。
放弃“自然语言乞求”,拥抱 Schema
后来我全面转向了 Pydantic + LangChain Structured Output 的模式。
我不告诉模型“请输出 JSON”,我直接把 Python 的 Class 定义传给它:
class ProjectExperience(BaseModel):
name: str = Field(..., description="项目名称")
role: str = Field(..., description="担任角色,如:后端负责人")
tech_stack: List[str] = Field(..., description="提取出的技术栈列表,标准化命名")
difficulty_score: int = Field(..., description="根据项目描述,评估技术难度(1-10)")
这样做的好处是,模型不仅知道要输出什么格式,甚至能帮我做数据清洗(比如把“Vue.js”、“Vue2”都标准化为“Vue”)。
👉 交流点: 你们在处理长文本(比如超过 10k token 的超长简历或论文)提取时,是采用 MapReduce 分段提取,还是由长窗口模型(如 Gemini-1.5-Pro)直接硬吞?我很想听听大家的实测体验。
三、 Agent 开发:当 Chain 变成了 Graph
项目后期开发“模拟面试官”时,线性的 Chain(链式调用)已经不够用了。
面试是一个动态过程:
- 如果用户回答得好 -> 追问底层原理(难度 Upgrade)
- 如果用户回答不上来 -> 换个话题或给提示(难度 Downgrade)
- 如果用户偏题 -> 纠正方向
这实际上是一个状态机(State Machine) 。
于是我把架构从 LangChain 迁移到了 LangGraph。通过定义 State(状态)和 Edge(流转条件),让 AI 能够根据用户的实时反馈动态决定下一步动作,而不是傻傻地按顺序提问。
虽然 LangGraph 的上手门槛有点高,代码量也上去了,但它让 Agent 真正有了“脑子”,而不是复读机。
四、 一些心里话与资料分享
在这个系统的开发过程中,我最大的感触是:AI 只是核心引擎,软件工程才是底盘。 即使模型再强,没有好的架构设计、错误处理和数据清洗,做出来的也就是个玩具。
因为篇幅有限,很多代码细节(比如怎么做 PDF 表格还原、Rerank 的参数微调、Agent 的内存管理机制)没法在这里一一展开。
既然是技术交流,我也想把我的经验分享出来。
我花了两天时间,把自己在这个项目中的技术架构图、RAG 优化清单以及核心模块的脱敏代码整理成了一份 AI 工程化实战笔记。
如果你是:
- 正在为 AI 毕设/论文发愁的学生;
- 想自己动手写一个 AI 应用的开发者;
- 或者单纯想找人聊聊 AI 技术落地的同行;
欢迎在评论区留言“交流”,或者直接后台滴滴我。
我不是什么大神,只是一个喜欢折腾代码的普通开发者。发这篇文章的初衷,就是想在这个快节奏的时代,找几个能一起静下心来聊技术、聊代码的朋友。
希望能和大家在 AI 的路上结伴而行。