内容
# LinkedIn 工作岗位智能代理
LinkedIn 工作岗位智能代理是一个基于证据的招聘市场智能系统。
该产品的理念很简单:大多数简历匹配工具要求大型语言模型(LLM)阅读简历和职位描述,然后返回一个完善的评估结果。这很容易演示,但很难信任,很难审计,也很难扩展。
该项目采取了相反的路径。它将职位匹配视为一个数据问题。首先收集真实的职位发布信息,保留原始证据,将市场规范化为结构化表格,提取简历证据,计算可重复的分数,并存储每次比较。LLM 不是评判者,而是在管道内部的一个工作者,帮助提取、清理和规范化。
MCP 是通信层。它允许聊天客户端或代理操作系统,但项目的价值在于底层证据引擎:仓库、评分规则、持久比较和解释每个推荐的能力。
## 演示
观看基于证据的简历评分工作流程的实际操作:
[观看演示视频](demo.mp4)
## 本项目的作用
- 从 LinkedIn 访客职位搜索和发布页面构建私有职位市场数据集。
- 在任何解释发生之前,将原始市场证据存储在 Postgres 中。
- 将职位名称、地点、资历级别、公司和技能规范化为仓库-ready 实体。
- 使用 dbt 将数据通过青铜、银、金色的分析层进行转换。
- 从候选人简历中提取简历证据和技能。
- 使用需求覆盖率和技能覆盖率对简历与实际职位发布进行评分。
- 保存排名结果、匹配需求、缺失需求、匹配技能和缺失技能。
- 通过 MCP 工具公开整个工作流程,以便代理可以通过对话驱动系统。
- 跟踪评分进度、取消请求和比较历史。
## 为什么这有所不同
市场上有许多薄 AI 包装,它们通过向模型发送两个文本块来进行简历分析。它们听起来可能很有说服力,但通常无法回答最重要的问题:“是什么证据产生了这个推荐?”
LinkedIn 工作岗位智能代理围绕证据构建:
- 每个职位都作为原始存储记录开始。
- 每个简历解析都存储为提取的证据。
- 每个规范化的职位名称、资历级别、地点和技能都成为可重用的数据。
- 每个语义需求匹配都与职位需求、简历证据和相似度得分一起保存。
- 每个技能匹配都与职位技能、简历技能、模糊得分和匹配结果一起保存。
- 每个最终评分都可以通过持久的中间分数重现。
这使得系统不仅仅是有用的单次简历反馈。它可以成为一个职位市场情报层、简历定位引擎、候选人匹配分析器,或者是需要可追溯性而不是凭直觉的招聘产品的基石。
## 评分策略
评分策略旨在回答一个更严肃的问题,而不是“LLM 是否喜欢这个简历?”。它询问的是:“简历中有哪些需求得到了证据支持,哪些所需的技能实际存在?”
### 1. 需求证据评分
系统从清理的职位描述开始,将其分成个别需求。它还从候选人简历中提取简历要点证据。
每个职位需求都被嵌入并与简历证据进行比较,使用配置的 Ollama 嵌入模型。对于每个需求,系统存储:
- 职位需求
- 最佳匹配的简历要点,如果存在足够强的匹配
- 相似度得分
- 需求是否被视为满足
根据相似度阈值分配信用:
- `>= 0.70`:完整信用
- `>= 0.60`:部分信用
- `>= 0.50`:弱信用
- 低于 `0.50`:无信用
语义得分是总需求信用除以职位需求数量,缩放至 `0-100`。这奖励显示与实际职位需求具体证据相符的简历。
### 2. 技能匹配评分
系统还会从职位发布和简历中分别提取规范化的技能。每个职位技能都使用令牌规范化的模糊匹配与简历技能进行比较。
只有当技能达到配置的模糊阈值时,技能才被视为匹配。技能评分为:
```text
匹配的职位技能 / 总职位技能 * 100
```
这创建了第二个专注于显式技能覆盖的评分。它还生成了可解释的匹配和缺失技能列表。
### 3. 完整评分
最终评分结合了两个信号:
```text
complete_score =
semantic_score * semantic_weight
+ skill_match_score * skill_weight
```
默认权重偏爱证据而不是关键词重叠:
```text
语义权重 = 70%
技能权重 = 30%
```
这意味着简历因证明其能够满足职位责任而获得更多奖励,同时仍然因明确的技能而获得积分。
### 4. 可解释的输出
最终结果不仅仅是一个排名或百分比。系统可以通过显示以下内容来解释为什么匹配某个职位:
- 匹配的职位需求
- 缺失的职位需求
- 匹配的技能
- 缺失的技能
- 每个需求的相似度得分
- 每个技能的模糊匹配得分
这是核心产品论点:聊天体验很方便,但推荐背后的证据图谱才是持久的资产。
## MCP 简历评分流程
MCP 是代理与证据引擎通信的方式。`chat_id` 标识一个用户对话,每个聊天都有一个活跃的简历评分配置,包含三个必填设置字段:
- `resume_parse_id`:从本地 PDF 存储的解析简历。
- `job_title`:规范的目标职位名称。
- `seniority`:目标资历级别。
工作流程是为引导式聊天体验而构建的:
```text
initialize_resume_grading_chat
↓
set_target_resume / set_target_job_title / set_target_seniority
↓
start_resume_grading
↓
get_resume_grading_status
↓
list_resume_grading_results
↓
explain_resume_job_match
```
一旦设置完成,`start_resume_grading` 就会启动后台运行。该运行会抓取 LinkedIn 职位,规范化新的发布,运行 dbt 模型,提取技能,评估简历,并保存比较。聊天层可以列出排名匹配或解释特定职位的需求匹配、缺失需求、技能匹配和缺失技能。
## Medallion 数据模型
仓库使用 medallion 模型,以便系统可以将原始证据与产品-ready 的洞察分开:
- **青铜** 保留原始输入:原始 LinkedIn 卡片、原始职位发布、抓取运行、简历解析、规范化映射和就绪控制。
- **银** 将这些输入转化为可重用的实体和事实:职位名称、公司、地点、职位发布、技能、语义评分、技能评分和完整的简历/职位评分。
- **金** 暴露产品面向的视图:招聘需求、地点需求、顶级技能、简历匹配摘要、匹配需求和缺失需求。
总体流程是:
```text
LinkedIn 和简历输入
↓
青铜:原始记录、运行历史、规范化映射
↓
银:清理的维度、事实、技能和简历/职位评分
↓
金:报告视图和简历匹配摘要
```
## 技术栈
- **Python**:核心应用逻辑、抓取、解析、评分和 MCP 工具。
- **MCP / FastMCP**:通信层,暴露证据引擎作为聊天/代理工具。
- **PostgreSQL**:应用数据库和仓库存储。
- **dbt**:青铜、银和金色数据转换。
- **Docker Compose**:本地 Postgres 和 Adminer 服务。
- **Groq**:LLM 辅助提取、清理和规范化在较大管道内部。
- **Ollama**:本地嵌入模型,用于简历/职位语义评分。
- **BeautifulSoup + requests**:LinkedIn HTML 获取和解析。
- **Pydantic**:请求和响应模式。
## 要求
- Python 3.11 或更新版本
- Docker Desktop 或 Docker Engine
- Ollama
- Groq API 密钥
## 安装
### 1. 克隆仓库
```bash
git clone <repo-url>
cd linkedin-agent
```
### 2. 创建并激活虚拟环境
```bash
python3 -m venv .venv
source .venv/bin/activate
```
### 3. 安装 Python 依赖项
```bash
python -m pip install --upgrade pip
python -m pip install -e .
```
### 4. 添加 Groq API 密钥
在项目根目录下创建 `.secrets.toml` 文件:
```toml
groq_api_keys = [
"your-groq-api-key"
]
```
您可以包含多个密钥。简历评分管道可以在其中一个密钥达到速率限制时轮换使用。
### 5. 启动本地服务
启动所有服务的简单方法是使用包含的脚本:
```bash
bash test/test_scripts/startup.sh
```
它启动:
- Postgres 在 `localhost:5432`
- Adminer 在 `http://localhost:8080`
- Ollama 在 `http://localhost:11434`
- `ResumeConfig.EMBED_MODEL` 中配置的 Ollama 嵌入模型
如果您只需要数据库服务,请运行:
```bash
docker compose up -d
```
### 6. 检查 dbt 连接
```bash
dbt debug --project-dir linkedin_dbt --profiles-dir linkedin_dbt/.dbt
```
然后运行 dbt 模型:
```bash
dbt run --project-dir linkedin_dbt --profiles-dir linkedin_dbt/.dbt
```
## 运行 MCP 服务器
当依赖项和本地服务准备就绪后,启动 MCP 服务器:
```bash
python -m agent_server.server
```
MCP 服务器在 `src/agent_server/server.py` 中定义:
- 主机:`0.0.0.0`
- 端口:`8001`
- 传输:`streamable-http`
`src/agent_server/tools/config.py` 中的配置工具处理简历评分设置的更改。
## 项目结构
```text
src/linkedin_tool/ LinkedIn 抓取、解析、持久化和规范化
src/resume_tool/ 简历提取、语义评分、技能评分和完整评分
src/agent_server/ MCP 服务器和简历评分工具
linkedin_dbt/ dbt 项目,用于青铜、银和金仓库模型
infra/postgresql_init/ Postgres 初始化 SQL
test/test_scripts/ 用于启动、抓取、评分和管道运行的本地脚本
```
## 注意事项
- LinkedIn 抓取可能会受到速率限制或阻止。重试、延迟和会话行为在 `src/config.py` 中配置。
- 默认数据库 URL 在 `Setting.DATABASE_URL` 中定义。
- 默认嵌入模型在 `ResumeConfig.EMBED_MODEL` 中定义。