diff --git a/migrations/001_init_schema.sql b/migrations/001_init_schema.sql new file mode 100644 index 0000000..c4a060a --- /dev/null +++ b/migrations/001_init_schema.sql @@ -0,0 +1,170 @@ +-- 简历智能体系统 - 数据库初始化脚本 +-- 支持: MySQL 8.0+ / SQLite 3 / PostgreSQL + +-- ============================================ +-- 1. 候选人主表 +-- ============================================ +CREATE TABLE IF NOT EXISTS candidates ( + id VARCHAR(64) PRIMARY KEY, + source VARCHAR(32) NOT NULL, -- BOSS, LIEPIN, ZHILIAN, OTHER + source_id VARCHAR(128) NOT NULL, -- 来源平台ID + name VARCHAR(64) NOT NULL, + phone VARCHAR(32), + email VARCHAR(128), + wechat VARCHAR(64), + gender TINYINT DEFAULT 0, -- 0:未知, 1:男, 2:女 + age INT, + location VARCHAR(128), + current_company VARCHAR(256), + current_position VARCHAR(128), + work_years DECIMAL(4,1), + education VARCHAR(64), + school VARCHAR(256), + salary_min INT, -- 期望薪资下限(K) + salary_max INT, -- 期望薪资上限(K) + status VARCHAR(32) DEFAULT 'NEW', -- NEW, ANALYZED, PUSHED, CONTACTED, INTERVIEWED, HIRED, REJECTED + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + UNIQUE KEY uk_source_source_id (source, source_id), + INDEX idx_phone (phone), + INDEX idx_email (email), + INDEX idx_name (name), + INDEX idx_status (status), + INDEX idx_created_at (created_at) +); + +-- ============================================ +-- 2. 简历内容表 +-- ============================================ +CREATE TABLE IF NOT EXISTS resumes ( + id VARCHAR(64) PRIMARY KEY, + candidate_id VARCHAR(64) NOT NULL, + raw_content TEXT, -- 原始简历文本 + parsed_content JSON, -- 结构化解析内容 + attachment_url VARCHAR(512), -- 附件URL + attachment_type VARCHAR(32), -- pdf, doc, docx + version INT DEFAULT 1, -- 版本号 + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + FOREIGN KEY (candidate_id) REFERENCES candidates(id) ON DELETE CASCADE, + INDEX idx_candidate_id (candidate_id) +); + +-- ============================================ +-- 3. 职位信息表 +-- ============================================ +CREATE TABLE IF NOT EXISTS jobs ( + id VARCHAR(64) PRIMARY KEY, + source VARCHAR(32) NOT NULL, -- BOSS, LIEPIN, etc. + source_id VARCHAR(128) NOT NULL, + title VARCHAR(256) NOT NULL, + department VARCHAR(128), + location VARCHAR(128), + salary_min INT, + salary_max INT, + requirements TEXT, -- 职位要求JSON + description TEXT, -- 职位描述 + status VARCHAR(32) DEFAULT 'ACTIVE', -- ACTIVE, PAUSED, CLOSED, ARCHIVED + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + UNIQUE KEY uk_source_source_id (source, source_id), + INDEX idx_status (status) +); + +-- ============================================ +-- 4. 评价方案表 +-- ============================================ +CREATE TABLE IF NOT EXISTS evaluation_schemas ( + id VARCHAR(64) PRIMARY KEY, + name VARCHAR(128) NOT NULL, + description TEXT, + dimensions JSON NOT NULL, -- 评价维度配置 + weights JSON NOT NULL, -- 维度权重 + prompt_template TEXT, -- AI提示词模板 + is_default BOOLEAN DEFAULT FALSE, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + INDEX idx_is_default (is_default) +); + +-- ============================================ +-- 5. 评价记录表 +-- ============================================ +CREATE TABLE IF NOT EXISTS evaluations ( + id VARCHAR(64) PRIMARY KEY, + candidate_id VARCHAR(64) NOT NULL, + schema_id VARCHAR(64) NOT NULL, + job_id VARCHAR(64), + overall_score DECIMAL(4,1), -- 综合评分 0-100 + dimension_scores JSON, -- 各维度评分详情 + tags JSON, -- AI标签 + summary TEXT, -- 评价摘要 + strengths JSON, -- 优势列表 + weaknesses JSON, -- 不足列表 + recommendation VARCHAR(32), -- strong_recommend, recommend, consider, not_recommend + raw_response TEXT, -- LLM原始响应 + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (candidate_id) REFERENCES candidates(id) ON DELETE CASCADE, + FOREIGN KEY (schema_id) REFERENCES evaluation_schemas(id), + FOREIGN KEY (job_id) REFERENCES jobs(id) ON DELETE SET NULL, + INDEX idx_candidate_id (candidate_id), + INDEX idx_schema_id (schema_id), + INDEX idx_overall_score (overall_score), + INDEX idx_created_at (created_at) +); + +-- ============================================ +-- 6. 通知记录表 +-- ============================================ +CREATE TABLE IF NOT EXISTS notifications ( + id VARCHAR(64) PRIMARY KEY, + candidate_id VARCHAR(64) NOT NULL, + evaluation_id VARCHAR(64), + channel VARCHAR(32) NOT NULL, -- WECHAT_WORK, DINGTALK, EMAIL, WEBHOOK + content TEXT, + status VARCHAR(32) DEFAULT 'PENDING', -- PENDING, SENT, FAILED + error_message TEXT, + sent_at TIMESTAMP, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (candidate_id) REFERENCES candidates(id) ON DELETE CASCADE, + FOREIGN KEY (evaluation_id) REFERENCES evaluations(id) ON DELETE SET NULL, + INDEX idx_candidate_id (candidate_id), + INDEX idx_status (status), + INDEX idx_created_at (created_at) +); + +-- ============================================ +-- 7. 插入默认评价方案 +-- ============================================ +INSERT INTO evaluation_schemas (id, name, description, dimensions, weights, is_default) VALUES +('general', '通用评价方案', '适用于各类岗位的通用评价方案', + '[ + {"id": "professional", "name": "专业能力", "description": "岗位相关专业技能水平"}, + {"id": "experience", "name": "工作经验", "description": "相关工作经验丰富度"}, + {"id": "education", "name": "教育背景", "description": "学历和专业匹配度"}, + {"id": "potential", "name": "发展潜力", "description": "未来成长空间"}, + {"id": "culture_fit", "name": "文化匹配", "description": "与企业文化的匹配度"} + ]', + '{"professional": 0.30, "experience": 0.25, "education": 0.15, "potential": 0.15, "culture_fit": 0.15}', + TRUE) +ON DUPLICATE KEY UPDATE + name = VALUES(name), + description = VALUES(description), + dimensions = VALUES(dimensions), + weights = VALUES(weights); + +INSERT INTO evaluation_schemas (id, name, description, dimensions, weights) VALUES +('java_backend', 'Java后端工程师评价方案', '针对Java后端开发岗位的综合评价方案', + '[ + {"id": "tech_capability", "name": "技术能力", "description": "Java技术栈掌握程度", "criteria": ["Java基础扎实程度", "Spring生态熟悉度", "数据库设计与优化", "分布式系统经验"]}, + {"id": "project_exp", "name": "项目经验", "description": "项目经历的丰富度和质量", "criteria": ["项目复杂度", "承担角色重要性", "技术挑战解决能力"]}, + {"id": "learning_ability", "name": "学习能力", "description": "学习新技术和适应新环境的能力", "criteria": ["技术广度", "新技术掌握速度", "自我驱动学习"]}, + {"id": "communication", "name": "沟通协作", "description": "团队协作和沟通能力", "criteria": ["跨团队协作经验", "技术文档能力", "问题表达能力"]}, + {"id": "stability", "name": "稳定性", "description": "职业稳定性和忠诚度", "criteria": ["平均在职时长", "跳槽频率", "职业发展规划清晰度"]} + ]', + '{"tech_capability": 0.35, "project_exp": 0.25, "learning_ability": 0.15, "communication": 0.15, "stability": 0.10}') +ON DUPLICATE KEY UPDATE + name = VALUES(name), + description = VALUES(description), + dimensions = VALUES(dimensions), + weights = VALUES(weights); diff --git a/migrations/README.md b/migrations/README.md new file mode 100644 index 0000000..5a2d636 --- /dev/null +++ b/migrations/README.md @@ -0,0 +1,184 @@ +# 数据库配置指南 + +## 1. 数据库设计文档 + +### 核心表结构 + +| 表名 | 说明 | 主要字段 | +|------|------|----------| +| `candidates` | 候选人主表 | 基本信息、职业信息、联系方式、状态 | +| `resumes` | 简历内容表 | 原始内容、解析内容、附件、版本 | +| `jobs` | 职位信息表 | 职位名称、部门、薪资、要求 | +| `evaluation_schemas` | 评价方案表 | 维度配置、权重、提示词模板 | +| `evaluations` | 评价记录表 | 评分结果、AI分析、推荐意见 | +| `notifications` | 通知记录表 | 通知渠道、状态、发送时间 | + +### ER 关系图 + +``` +┌─────────────┐ ┌─────────────┐ ┌─────────────┐ +│ candidates │────<│ resumes │ │ jobs │ +│ (候选人) │ │ (简历) │ │ (职位) │ +└──────┬──────┘ └─────────────┘ └──────┬──────┘ + │ │ + │ ┌─────────────┐ │ + └────────>│ evaluations │<─────────────┘ + │ (评价记录) │ + └──────┬──────┘ + │ + ┌──────┴──────┐ + │ notifications│ + │ (通知记录) │ + └─────────────┘ +``` + +## 2. 数据库配置方法 + +### 方法一:SQLite (开发测试) + +无需额外配置,默认使用 SQLite: + +```bash +# 在项目根目录创建 .env 文件 +echo "DB_URL=sqlite:///./hr_agent.db" > .env +``` + +### 方法二:MySQL (生产环境) + +#### 2.1 创建数据库 + +```sql +CREATE DATABASE hr_agent CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +CREATE USER 'hr_agent'@'%' IDENTIFIED BY 'your_password'; +GRANT ALL PRIVILEGES ON hr_agent.* TO 'hr_agent'@'%'; +FLUSH PRIVILEGES; +``` + +#### 2.2 配置连接 + +```bash +# .env 文件 +echo "DB_URL=mysql+pymysql://hr_agent:your_password@localhost:3306/hr_agent" > .env +``` + +#### 2.3 安装依赖 + +```bash +uv add pymysql cryptography +``` + +### 方法三:PostgreSQL + +#### 3.1 创建数据库 + +```sql +CREATE DATABASE hr_agent ENCODING 'UTF8'; +CREATE USER hr_agent WITH PASSWORD 'your_password'; +GRANT ALL PRIVILEGES ON DATABASE hr_agent TO hr_agent; +``` + +#### 3.2 配置连接 + +```bash +# .env 文件 +echo "DB_URL=postgresql+asyncpg://hr_agent:your_password@localhost:5432/hr_agent" > .env +``` + +#### 3.3 安装依赖 + +```bash +uv add asyncpg +``` + +## 3. 初始化数据库 + +### 3.1 执行 SQL 脚本 + +```bash +# MySQL +mysql -u hr_agent -p hr_agent < migrations/001_init_schema.sql + +# SQLite +sqlite3 hr_agent.db < migrations/001_init_schema.sql + +# PostgreSQL +psql -U hr_agent -d hr_agent -f migrations/001_init_schema.sql +``` + +### 3.2 验证初始化 + +```sql +-- 查看表结构 +SHOW TABLES; + +-- 查看默认评价方案 +SELECT * FROM evaluation_schemas; +``` + +## 4. 环境变量配置 + +在项目根目录创建 `.env` 文件: + +```env +# 数据库配置 +DB_URL=sqlite:///./hr_agent.db +DB_ECHO=false + +# LLM 配置 +LLM_PROVIDER=mock +LLM_API_KEY= +LLM_MODEL=gpt-4 + +# 爬虫配置 +CRAWLER_BOSS_WT_TOKEN=your_boss_token + +# 通知配置 (可选) +NOTIFY_WECHAT_WORK_WEBHOOK= +NOTIFY_DINGTALK_WEBHOOK= +``` + +## 5. 常用查询示例 + +### 查询候选人列表 + +```sql +SELECT + c.id, + c.name, + c.source, + c.current_company, + c.current_position, + c.status, + e.overall_score, + e.recommendation +FROM candidates c +LEFT JOIN evaluations e ON c.id = e.candidate_id +WHERE c.status = 'NEW' +ORDER BY c.created_at DESC; +``` + +### 查询高分候选人 + +```sql +SELECT + c.name, + c.current_company, + e.overall_score, + e.summary +FROM candidates c +JOIN evaluations e ON c.id = e.candidate_id +WHERE e.overall_score >= 80 +AND e.recommendation IN ('strong_recommend', 'recommend') +ORDER BY e.overall_score DESC; +``` + +### 统计各渠道候选人数量 + +```sql +SELECT + source, + COUNT(*) as total, + SUM(CASE WHEN status = 'ANALYZED' THEN 1 ELSE 0 END) as analyzed +FROM candidates +GROUP BY source; +```