> [!NOTE]
> 本文档由 WeHub 基于上游 README 翻译整理,属于社区翻译,非官方中文文档。
> [English](./README.en.md) · [原始项目](https://github.com/interviewstreet/hiring-agent) · [上游 README](https://github.com/interviewstreet/hiring-agent/blob/HEAD/README.md)
> 原作者、版权与许可证归属以原始项目及本仓库 LICENSE 文件为准。
# Hiring Agent
简历转评分流水线(Resume-to-Score pipeline),可从 PDF 提取结构化数据,结合 GitHub 信号进行增强,并输出公平、可解释的评价结果。
---
## 目录
- [概述](#overview)
- [架构](#architecture)
- [安装与配置](#installation-and-setup)
- [前置要求](#prerequisites)
- [使用 pip 快速安装](#quick-setup-with-pip)
- [Ollama 模型](#ollama-models)
- [配置](#configuration)
- [工作原理](#how-it-works)
- [CLI 用法](#cli-usage)
- [目录结构](#directory-layout)
- [提供商详情](#provider-details)
- [贡献](#contributing)
- [许可证](#license)
---
## 概述
Hiring Agent 将简历 PDF 解析为 Markdown,使用本地或托管 LLM 提取分节 JSON,并用 GitHub 个人资料与仓库信号增强数据,最终生成客观评价,包含分类得分、证据、加分项与扣分项。你可以通过 Ollama 完全在本地运行,或使用 Google Gemini。
---
## 架构
|
**流程**
1. `pymupdf_rag.py` 将 PDF 页面转换为类 Markdown 文本。
2. `pdf.py` 使用 `prompts/templates` 下的 Jinja 模板,按章节调用 LLM。
3. `github.py` 获取个人资料与仓库,对项目进行分类,并让 LLM 选出前 7 个。
4. `evaluator.py` 在公平性约束下执行严格评分评价。
5. `score.py` 端到端编排整个流程,并在开发模式开启时写入 CSV。
|
**核心模块**
- `models.py`
Pydantic 模式(schema)与 LLM 提供商接口。
- `llm_utils.py`
提供商初始化与响应清理。
- `transform.py`
将松散的 LLM JSON 规范化为 JSON Resume 风格。
- `prompts/`
用于提取与评分的全部 Jinja 模板。
|
---
## 安装与配置
### 前置要求
- **Python 3.11+**
本仓库将 `.python-version` 固定为 3.11.13。
- **一个 LLM 后端**(二选一)
- **Ollama** 用于本地模型
从[官方网站](https://ollama.com/), 安装,然后运行 `ollama serve`。
- **Google Gemini**:如果你有 API 密钥,可从[此处](https://aistudio.google.com/api-keys). 获取。
### 使用 pip 快速安装
```bash
$ git clone https://github.com/interviewstreet/hiring-agent
$ cd hiring-agent
$ python -m venv .venv
# Linux or macOS
$ source .venv/bin/activate
# Windows
# .venv\Scripts\activate
$ pip install -r requirements.txt
```
### Ollama 模型
拉取你想使用的模型。例如:
```bash
$ ollama pull gemma3:4b
```
如果想要不同结果,可以拉取其他模型,例如:
```bash
# For higher system configuration
$ ollama pull gemma3:12b
# For lower system configuration
$ ollama pull gemma3:1b
```
---
## 配置
复制模板并设置环境变量。
```bash
$ cp .env.example .env
```
**环境变量**
| Variable | Values | Description |
| ---------------- | ------------------------------------------- | ---------------------------------------------------------------------- |
| `LLM_PROVIDER` | `ollama` or `gemini` | 选择提供商。默认为 Ollama。 |
| `DEFAULT_MODEL` | for example `gemma3:4b` or `gemini-2.5-pro` | 传递给提供商的模型名称。 |
| `GEMINI_API_KEY` | string | 当 `LLM_PROVIDER=gemini` 时为必填项。 |
| `GITHUB_TOKEN` | optional | 继承自 shell 环境,可改善 GitHub API 速率限制。 |
提供商映射位于 `prompt.py` 与 `models.py`。`config.py` 文件包含一个标志:
```python
# config.py
DEVELOPMENT_MODE = True # enables caching and CSV export
```
迭代期间可保持开启。详见下一节。
---
## 工作原理
1) PDF 提取
- `pymupdf_rag.py` 与 `pdf.py` 使用 PyMuPDF 读取 PDF,并将页面转换为类 Markdown 文本。
- `to_markdown` 例程处理标题、链接、表格及基本格式。
2) 基于模板的章节解析
- `prompts/templates/*.jinja` 为各章节定义严格指令
Basics、Work、Education、Skills、Projects、Awards。
- `pdf.PDFHandler` 按章节调用 LLM,并组装 `JSONResume` 对象(见 `models.py`)。
3) GitHub 增强
- `github.py` 从简历 profiles 中提取用户名,获取个人资料与仓库,并对每个项目进行分类。
- 它让 LLM 恰好选出 7 个不重复的项目,要求达到最低作者提交阈值,并优先选择有意义的贡献。
4) 评价
- `evaluator.py` 使用编码了公平性与评分规则的模板。
- 得分包括 `open_source`、`self_projects`、`production` 与 `technical_skills`,以及加分与扣分,随后为证据提供说明。
5) 输出与 CSV 导出
- `score.py` 向 stdout 打印可读摘要。
- 当 `DEVELOPMENT_MODE=True` 时,会创建或追加 `resume_evaluations.csv`(包含关键字段),并在 `cache/` 下缓存中间 JSON。
---
## CLI 用法
### 端到端评分
提供简历 PDF 的路径。
```bash
$ python score.py /path/to/resume.pdf
```
执行过程:
1. 若开发模式开启,PDF 提取结果会缓存到 `cache/resumecache_.json`。
2. 若在简历中找到 GitHub 个人资料,会获取仓库并缓存到 `cache/githubcache_.json`。
3. 评价器打印报告;在开发模式下,会向 `resume_evaluations.csv` 追加一行 CSV。
---
## 目录结构
```text
.
├── .env.example
├── .python-version
├── config.py
├── evaluator.py
├── github.py
├── llm_utils.py
├── models.py
├── pdf.py
├── prompt.py
├── prompts/
│ ├── template_manager.py
│ └── templates/
│ ├── awards.jinja
│ ├── basics.jinja
│ ├── education.jinja
│ ├── github_project_selection.jinja
│ ├── projects.jinja
│ ├── resume_evaluation_criteria.jinja
│ ├── resume_evaluation_system_message.jinja
│ ├── skills.jinja
│ ├── system_message.jinja
│ └── work.jinja
├── pymupdf_rag.py
├── requirements.txt
├── score.py
└── transform.py
```
---
## 提供商详情
### Ollama
- 设置 `LLM_PROVIDER=ollama`
- 将 `DEFAULT_MODEL` 设为任意已拉取的模型,例如 `gemma3:4b`
- `models.OllamaProvider` 中的提供商封装会调用 `ollama.chat`
### Gemini
- 设置 `LLM_PROVIDER=gemini`
- 将 `DEFAULT_MODEL` 设为受支持的 Gemini 模型,例如 `gemini-2.0-flash`
- 提供 `GEMINI_API_KEY`
- `models.GeminiProvider` 中的封装会将响应适配为统一格式
---
## 贡献
请阅读 [CONTRIBUTING.md](./CONTRIBUTING.md),了解提交 issue、提出变更与提交 pull request 的详细指南。核心原则包括:
- 保持 prompt 声明式且与提供商无关。
- 在不同提供商下用几份真实简历验证变更。
- 添加或调整无单元测试的冒烟测试(smoke test),以最小输入调用各阶段。
---
## 许可证
[MIT](https://github.com/interviewstreet/hiring-agent/blob/master/LICENSE) © HackerRank