Initial commit: AI Interview System

This commit is contained in:
111
2026-01-23 13:57:48 +08:00
commit 95770afe21
127 changed files with 24686 additions and 0 deletions

247
docs/PRD.md Normal file
View File

@@ -0,0 +1,247 @@
# 产品需求文档
> 版本v1.0
> 最后更新2026-01-20
## 版本历史
| 版本 | 日期 | 变更内容 | 作者 |
|------|------|---------|------|
| v1.0 | 2026-01-20 | 初始版本 | AI |
---
## 一、项目概述
### 1.1 项目背景
为轻医美行业打造 AI 面试官系统,实现咨询师岗位的智能初试。通过 AI 语音面试技术,提升招聘效率,标准化面试流程,降低 HR 初筛工作量。
### 1.2 项目目标
1. 实现 7x24 小时无人值守的智能初试
2. 标准化面试流程,确保评估一致性
3. 自动生成面试报告,辅助 HR 决策
4. 提升候选人体验,缩短招聘周期
### 1.3 核心价值
| 角色 | 价值 |
|------|------|
| HR | 减少初筛工作量,获得标准化评估报告 |
| 候选人 | 随时参与面试,体验创新面试形式 |
| 企业 | 降低招聘成本,提升招聘效率 |
---
## 二、用户角色
### 2.1 候选人
- **画像**:应聘轻医美咨询师岗位的求职者
- **使用场景**:收到面试邀请后,通过网页参与 AI 语音面试
- **核心诉求**:快速完成面试,获得反馈
### 2.2 HR/招聘专员
- **画像**:负责招聘的人力资源专员
- **使用场景**:在管理后台查看候选人面试结果和分析报告
- **核心诉求**:快速筛选合适候选人,减少重复劳动
### 2.3 管理员
- **画像**:系统管理员
- **使用场景**:管理系统配置、查看所有候选人数据
- **核心诉求**:系统稳定运行,数据安全
---
## 三、功能需求
### 3.1 用户端功能
#### F-001 欢迎页Welcome
| 项目 | 内容 |
|------|------|
| 功能描述 | 展示公司/品牌介绍,引导候选人开始面试 |
| 页面元素 | 公司 Logo、欢迎语、"开始面试"按钮 |
| 交互逻辑 | 点击按钮进入信息收集页 |
#### F-002 信息收集页InfoCollection
| 项目 | 内容 |
|------|------|
| 功能描述 | 收集候选人姓名和简历 |
| 页面元素 | 姓名输入框、简历上传组件、提交按钮 |
| 交互逻辑 | 1. 输入姓名(必填)<br>2. 上传简历PDF/DOC/DOCX<br>3. 提交后显示加载状态<br>4. 处理完成进入来电页 |
| 校验规则 | 姓名2-20字符简历≤10MB |
#### F-003 模拟来电页IncomingCall
| 项目 | 内容 |
|------|------|
| 功能描述 | 模拟电话来电效果,增强仪式感 |
| 页面元素 | 来电动画、"AI面试官来电中..."文案、接听按钮(绿)、挂断按钮(红) |
| 交互逻辑 | 1. 显示振铃动画<br>2. 点击接听进入通话页<br>3. 点击挂断返回欢迎页 |
#### F-004 语音通话页InCall
| 项目 | 内容 |
|------|------|
| 功能描述 | 与 AI 面试官进行实时语音对话 |
| 页面元素 | 通话计时器、音波动画、静音按钮、挂断按钮 |
| 交互逻辑 | 1. 自动开启麦克风<br>2. AI 说话时显示音波动画<br>3. 可随时静音/取消静音<br>4. 面试结束自动跳转或点击挂断结束 |
#### F-005 面试结束页Completed
| 项目 | 内容 |
|------|------|
| 功能描述 | 展示面试完成信息 |
| 页面元素 | 感谢语、后续流程说明 |
| 交互逻辑 | 静态展示,可选择关闭页面 |
---
### 3.2 管理后台功能
#### F-101 候选人列表
| 项目 | 内容 |
|------|------|
| 功能描述 | 展示所有候选人及其面试状态 |
| 页面元素 | 数据表格、搜索框、筛选器、分页 |
| 表格字段 | 姓名、面试时间、状态、综合评分、操作 |
| 筛选条件 | 状态(待面试/进行中/已完成)、时间范围 |
#### F-102 候选人详情
| 项目 | 内容 |
|------|------|
| 功能描述 | 展示候选人完整面试报告 |
| 页面元素 | 基本信息、简历内容、评分雷达图、各维度分析、面试记录、导出按钮 |
| 评分维度 | 销售技能、销售观、素质项、求职动机 |
| 导出功能 | 支持导出 PDF 报告 |
---
## 四、业务流程
### 4.1 用户端面试流程
```
┌─────────────┐
│ 欢迎页 │
│ Welcome │
└──────┬──────┘
│ 点击"开始面试"
┌─────────────┐
│ 信息收集页 │
│ InfoCollection│
└──────┬──────┘
│ 提交姓名+简历
┌─────────────┐
│ 处理中 │
│ Processing │
└──────┬──────┘
│ 简历上传完成
┌─────────────┐
│ 模拟来电页 │
│ IncomingCall│
└──────┬──────┘
│ 点击"接听"
┌─────────────┐
│ 语音通话页 │
│ InCall │──────────────┐
└──────┬──────┘ │
│ 面试结束 │ RTC 实时语音
▼ │ 对接 Coze Bot
┌─────────────┐ │
│ 结束页 │◄─────────────┘
│ Completed │
└─────────────┘
```
### 4.2 面试评估维度
| 维度 | 评估内容 | 权重 |
|------|---------|------|
| 销售技能 | 客户沟通、需求挖掘、异议处理 | 30% |
| 销售观 | 对销售工作的理解和价值观 | 25% |
| 素质项 | 学习能力、抗压能力、团队协作 | 25% |
| 求职动机 | 岗位匹配度、稳定性、职业规划 | 20% |
---
## 五、非功能需求
### 5.1 性能要求
| 指标 | 要求 |
|------|------|
| 页面加载时间 | < 3s |
| 语音延迟 | < 500ms |
| 并发面试数 | 支持 50 人同时面试 |
### 5.2 兼容性要求
| 平台 | 要求 |
|------|------|
| 浏览器 | Chrome 90+、Edge 90+、Safari 14+ |
| 设备 | PC 为主,移动端适配 |
### 5.3 安全要求
| 项目 | 要求 |
|------|------|
| 数据传输 | HTTPS 加密 |
| 敏感信息 | API Key 不暴露给前端 |
| 权限控制 | 管理后台需登录验证 |
---
## 六、技术约束
### 6.1 现有资源
| 资源 | 说明 |
|------|------|
| Coze 工作流 | 已有完整面试逻辑(工作流 ID7595077233002840079 |
| Coze 数据库 | 已有数据结构(数据库 ID7595077053909712922 |
### 6.2 技术依赖
| 依赖 | 说明 |
|------|------|
| 火山引擎 RTC | 实时语音通话 |
| Coze API | 文件上传、Bot 调用、数据库查询 |
---
## 七、里程碑
| 阶段 | 内容 | 预计时间 |
|------|------|---------|
| M1 | 需求确认、技术选型 | 1 天 |
| M2 | 后端 API 开发 | 2 天 |
| M3 | 前端用户端开发 | 3 天 |
| M4 | 前端管理后台开发 | 2 天 |
| M5 | 联调测试 | 2 天 |
| M6 | 上线部署 | 1 天 |
---
## 八、待确认事项
- [ ] 管理后台是否需要登录认证?
- [ ] 是否需要候选人邀请链接功能?
- [ ] 面试时长限制?(建议 15-20 分钟)
- [ ] 是否需要面试录音回放?
---
> 最后更新2026-01-20

64
docs/README.md Normal file
View File

@@ -0,0 +1,64 @@
# 文档索引
> 本项目文档导航
---
## 核心文档
| 文档 | 说明 | 状态 |
|------|------|------|
| [PRD.md](PRD.md) | 产品需求文档 | ✅ v1.0 |
| [同步清单.md](同步清单.md) | 任务状态与待办 | ✅ |
| [决策记录.md](决策记录.md) | 所有决策记录 | ✅ |
| [项目状态快照.md](项目状态快照.md) | 项目全貌概览 | ✅ |
| [功能模块索引.md](功能模块索引.md) | 功能→决策映射 | 📝 待创建 |
---
## 技术文档
| 文档 | 说明 | 状态 |
|------|------|------|
| [技术选型.md](技术选型.md) | 项目技术选型(含覆盖声明) | ✅ |
| [api/endpoints.md](api/endpoints.md) | API 接口文档 | ✅ |
| [database/表结构.md](database/表结构.md) | Coze 数据库结构 | ✅ |
---
## 交接相关
| 文档 | 说明 |
|------|------|
| [交接文档/](交接文档/) | 对话框交接文档 |
| [对话框摘要/](对话框摘要/) | 历史对话框摘要 |
---
## 审视记录
| 文档 | 说明 |
|------|------|
| [PRD审视记录/](PRD审视记录/) | PRD多角色审视记录 |
---
## 发布相关
| 文档 | 说明 |
|------|------|
| [发布记录.md](发布记录.md) | 版本发布历史 |
---
## 快速导航
- **了解项目** → [PRD.md](PRD.md)
- **技术方案** → [技术选型.md](技术选型.md)
- **当前任务** → [同步清单.md](同步清单.md)
- **历史决策** → [决策记录.md](决策记录.md)
- **接口文档** → [api/endpoints.md](api/endpoints.md)
---
> 最后更新2026-01-20

358
docs/api/endpoints.md Normal file
View File

@@ -0,0 +1,358 @@
# API 接口文档
> 本项目 API 接口说明
---
## 一、接口概览
| 模块 | 接口 | 方法 | 说明 |
|------|------|------|------|
| 候选人 | `/api/candidates` | POST | 提交候选人信息(上传简历) |
| 房间 | `/api/rooms` | POST | 创建语音房间 |
| 管理 | `/api/candidates` | GET | 获取候选人列表 |
| 管理 | `/api/candidates/:id` | GET | 获取候选人详情 |
| 管理 | `/api/candidates/:id/export` | GET | 导出 PDF 报告 |
---
## 二、通用说明
### 2.1 基础 URL
```
开发环境http://localhost:8000
生产环境https://api.your-domain.com
```
### 2.2 响应格式
**成功响应**
```json
{
"code": 0,
"message": "success",
"data": { ... }
}
```
**错误响应**
```json
{
"code": 20001,
"message": "参数错误",
"data": null
}
```
### 2.3 错误码
| 范围 | 类型 |
|------|------|
| `0` | 成功 |
| `10000-19999` | 用户相关错误 |
| `20000-29999` | 业务逻辑错误 |
| `30000-39999` | 数据错误 |
| `40000-49999` | 系统错误 |
| `50000-59999` | 第三方服务错误 |
常用错误码:
| 错误码 | 说明 |
|--------|------|
| `20001` | 参数错误 |
| `20002` | 数据不存在 |
| `50001` | Coze API 调用失败 |
| `50002` | RTC 服务异常 |
---
## 三、用户端接口
### 3.1 提交候选人信息
提交候选人姓名和简历,创建面试会话。
**请求**
- **URL**: `POST /api/candidates`
- **Content-Type**: `multipart/form-data`
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| name | string | 是 | 候选人姓名2-20字符 |
| resume | file | 是 | 简历文件,支持 PDF/DOC/DOCX≤10MB |
**响应示例**
```json
{
"code": 0,
"message": "success",
"data": {
"sessionId": "SESS_1705737600_张三_abc123",
"fileId": "file_xxx"
}
}
```
**处理流程**
1. 校验参数
2. 上传简历到 Coze`POST /v1/files/upload`
3. 生成 sessionId
4. 返回结果
---
### 3.2 创建语音房间
创建 RTC 房间,让 Coze Bot 加入房间。
**请求**
- **URL**: `POST /api/rooms`
- **Content-Type**: `application/json`
**请求参数**
```json
{
"sessionId": "SESS_1705737600_张三_abc123",
"fileId": "file_xxx"
}
```
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| sessionId | string | 是 | 会话 ID |
| fileId | string | 是 | 简历文件 ID |
**响应示例**
```json
{
"code": 0,
"message": "success",
"data": {
"roomId": "room_xxx",
"token": "rtc_token_xxx",
"appId": "volcengine_app_id",
"userId": "user_xxx"
}
}
```
**处理流程**
1. 生成 roomId 和 userId
2. 调用 Coze API 让 Bot 加入房间(`POST /v1/audio/rooms`
3. 生成 RTC Token
4. 返回房间信息
---
### 3.3 结束面试
通知后端面试已结束。
**请求**
- **URL**: `POST /api/interviews/:sessionId/end`
- **Content-Type**: `application/json`
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| sessionId | string | 是 | 会话 IDURL 参数) |
**响应示例**
```json
{
"code": 0,
"message": "success",
"data": {
"success": true
}
}
```
---
## 四、管理后台接口
### 4.1 获取候选人列表
分页获取候选人列表。
**请求**
- **URL**: `GET /api/candidates`
- **权限**: 需要登录
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| page | number | 否 | 页码,默认 1 |
| pageSize | number | 否 | 每页条数,默认 20 |
| keyword | string | 否 | 搜索关键词(姓名) |
| status | string | 否 | 状态筛选pending/ongoing/completed |
| startDate | string | 否 | 开始日期,格式 YYYY-MM-DD |
| endDate | string | 否 | 结束日期,格式 YYYY-MM-DD |
**响应示例**
```json
{
"code": 0,
"message": "success",
"data": {
"list": [
{
"sessionId": "SESS_1705737600_张三_abc123",
"name": "张三",
"status": "completed",
"score": 85,
"createdAt": "2026-01-20T10:00:00+08:00"
}
],
"total": 100,
"page": 1,
"pageSize": 20
}
}
```
---
### 4.2 获取候选人详情
获取候选人完整面试报告。
**请求**
- **URL**: `GET /api/candidates/:sessionId`
- **权限**: 需要登录
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| sessionId | string | 是 | 会话 IDURL 参数) |
**响应示例**
```json
{
"code": 0,
"message": "success",
"data": {
"sessionId": "SESS_1705737600_张三_abc123",
"name": "张三",
"resume": "简历内容文本...",
"status": "completed",
"currentStage": 60,
"scores": {
"salesSkill": 85,
"salesMindset": 80,
"quality": 90,
"motivation": 75
},
"analysis": "综合分析报告内容...",
"interviewLog": "完整对话记录...",
"createdAt": "2026-01-20T10:00:00+08:00",
"completedAt": "2026-01-20T10:25:00+08:00"
}
}
```
---
### 4.3 导出 PDF 报告
导出候选人面试报告为 PDF 文件。
**请求**
- **URL**: `GET /api/candidates/:sessionId/export`
- **权限**: 需要登录
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| sessionId | string | 是 | 会话 IDURL 参数) |
**响应**
- **Content-Type**: `application/pdf`
- **Content-Disposition**: `attachment; filename="interview_report_张三.pdf"`
---
## 五、Coze API 调用说明
> 以下为后端调用 Coze API 的内部说明
### 5.1 文件上传
```
POST https://api.coze.cn/v1/files/upload
Authorization: Bearer {PAT_TOKEN}
Content-Type: multipart/form-data
Response:
{
"data": {
"id": "file_xxx"
}
}
```
### 5.2 创建语音房间
```
POST https://api.coze.cn/v1/audio/rooms
Authorization: Bearer {PAT_TOKEN}
Content-Type: application/json
Body:
{
"bot_id": "7595077233002840079",
"room_id": "room_xxx",
"user_id": "user_xxx",
"voice_id": "voice_id_xxx",
"config": {
"input_file_id": "file_xxx"
}
}
```
### 5.3 查询数据库
```
POST https://api.coze.cn/v1/database/query
Authorization: Bearer {PAT_TOKEN}
Content-Type: application/json
Body:
{
"database_id": "7595077053909712922",
"filter": {
"session_id": "SESS_xxx"
}
}
```
---
## 变更日志
| 日期 | 变更内容 | 操作人 |
|------|---------|--------|
| 2026-01-20 | 初始化 API 文档 | AI |

150
docs/database/表结构.md Normal file
View File

@@ -0,0 +1,150 @@
# 数据库结构
> 本项目使用 Coze 数据库存储数据
---
## 一、数据库信息
| 项目 | 内容 |
|------|------|
| 平台 | Coze 数据库 |
| 数据库 ID | 7595077053909712922 |
| 说明 | 由 Coze 工作流自动写入和管理 |
---
## 二、表结构
### 2.1 候选人面试记录表
> 表名由 Coze 自动管理
| 字段名 | 类型 | 说明 | 示例 |
|--------|------|------|------|
| session_id | String | 会话唯一标识 | `SESS_1705737600_张三_abc123` |
| 姓名 | String | 候选人姓名 | `张三` |
| 简历内容 | String | 解析后的简历文本 | `姓名:张三,学历:本科...` |
| current_stage | Integer | 当前面试阶段 | `60` |
| 面试记录 | String | 完整对话记录JSON | `[{"role":"ai","content":"..."}]` |
| 评分结果 | String | 各维度评分JSON | `{"salesSkill":85,...}` |
| 分析报告 | String | 综合分析报告 | `候选人具备良好的销售潜质...` |
| created_at | Timestamp | 创建时间 | `2026-01-20T10:00:00Z` |
| updated_at | Timestamp | 更新时间 | `2026-01-20T10:25:00Z` |
---
## 三、字段详细说明
### 3.1 session_id 格式
```
SESS_{时间戳}_{姓名}_{随机码}
示例SESS_1705737600_张三_abc123
```
- 时间戳Unix 时间戳(秒)
- 姓名:候选人姓名
- 随机码6位随机字符串
### 3.2 current_stage 阶段码
| 阶段码 | 说明 |
|--------|------|
| 10 | 信息收集 |
| 20 | 销售技能面试 |
| 30 | 销售观面试 |
| 40 | 素质项面试 |
| 50 | 求职动机面试 |
| 60 | 面试完成 |
### 3.3 评分结果结构
```json
{
"salesSkill": 85, // 销售技能 0-100
"salesMindset": 80, // 销售观 0-100
"quality": 90, // 素质项 0-100
"motivation": 75, // 求职动机 0-100
"total": 82.5 // 加权总分
}
```
权重计算:
- 销售技能30%
- 销售观25%
- 素质项25%
- 求职动机20%
### 3.4 面试记录结构
```json
[
{
"role": "ai",
"content": "你好我是AI面试官请先做个自我介绍。",
"timestamp": "2026-01-20T10:01:00Z"
},
{
"role": "user",
"content": "你好,我叫张三...",
"timestamp": "2026-01-20T10:01:30Z"
}
]
```
---
## 四、数据访问方式
### 4.1 查询单条记录
```python
# 后端调用 Coze API
response = await coze_client.post(
"/v1/database/query",
json={
"database_id": "7595077053909712922",
"filter": {
"session_id": "SESS_xxx"
}
}
)
```
### 4.2 查询列表(分页)
```python
response = await coze_client.post(
"/v1/database/query",
json={
"database_id": "7595077053909712922",
"page": 1,
"page_size": 20,
"sort": {
"field": "created_at",
"order": "desc"
}
}
)
```
---
## 五、数据写入
> 数据写入由 Coze 工作流自动完成,后端只负责读取
工作流写入节点:
- 节点 ID`124924`
- 类型:`insert_record`
- 触发时机:候选人提交信息后
---
## 变更日志
| 日期 | 变更内容 | 操作人 |
|------|---------|--------|
| 2026-01-20 | 初始化数据库文档 | AI |

75
docs/mock-resume.md Normal file
View File

@@ -0,0 +1,75 @@
# 个人简历
## 基本信息
- **姓名**:李小美
- **性别**:女
- **年龄**26岁
- **学历**:本科
- **电话**138-8888-9999
- **邮箱**lixiaomei@email.com
- **现居地**:上海市静安区
- **求职意向**:轻医美咨询师 / 美容顾问
---
## 教育背景
**上海工商大学** | 市场营销专业 | 本科 | 2018年9月 - 2022年6月
- 主修课程:市场营销学、消费者心理学、品牌管理、商务谈判
- 在校期间多次获得奖学金,担任班级学习委员
---
## 工作经历
### 某知名美容连锁机构 | 美容顾问 | 2022年7月 - 2024年12月
**工作内容**
- 负责门店客户接待和咨询服务月均接待客户80+人次
- 根据客户肤质和需求,推荐适合的护肤项目和产品方案
- 跟进客户体验反馈维护老客户关系客户回头率达65%
- 协助店长完成月度销售目标个人业绩连续6个月排名前三
**主要成绩**
- 2023年度"最佳新人奖"
- 单月最高业绩28万元
- 发展VIP客户50+人
### 某护肤品品牌专柜 | 销售顾问 | 2021年6月 - 2022年6月实习
**工作内容**
- 在商场专柜负责产品销售和客户服务
- 学习专业护肤知识,为客户提供皮肤检测和护理建议
- 参与品牌促销活动策划和执行
---
## 专业技能
- **护肤知识**:熟悉各类肤质特点,了解常见皮肤问题的形成原因和改善方案
- **医美知识**:了解光电类、注射类等常见轻医美项目的原理和适应人群
- **沟通能力**:善于倾听客户需求,能够用通俗易懂的语言解释专业知识
- **销售技巧**熟悉FABE销售法则擅长挖掘客户需求促成成交
- **办公软件**熟练使用Office办公软件、CRM系统
---
## 证书资质
- 高级美容师资格证2023年
- 皮肤管理师认证2022年
- 普通话二级甲等
---
## 自我评价
热爱美业对轻医美行业充满热情。性格开朗、亲和力强善于与不同类型的客户建立信任关系。具备2年多美容行业一线销售经验熟悉客户接待全流程。学习能力强愿意不断提升专业知识。期望加入贵公司在轻医美领域深耕发展为客户提供专业的咨询服务。
---
## 期望薪资
8000-12000元/月(底薪+提成)

View File

@@ -0,0 +1,94 @@
server
{
listen 80;
server_name files.test.ai.ireborn.com.cn;
index index.php index.html index.htm default.php default.htm default.html;
root /www/wwwroot/files.test.ai.ireborn.com.cn;
# 文件上传大小限制20MB
client_max_body_size 20m;
#CERT-APPLY-CHECK--START
# 用于SSL证书申请时的文件验证相关配置 -- 请勿删除
include /www/server/panel/vhost/nginx/well-known/files.test.ai.ireborn.com.cn.conf;
#CERT-APPLY-CHECK--END
include /www/server/panel/vhost/nginx/extension/files.test.ai.ireborn.com.cn/*.conf;
#SSL-START SSL相关配置请勿删除或修改下一行带注释的404规则
#error_page 404/404.html;
#SSL-END
#ERROR-PAGE-START 错误页配置,可以注释、删除或修改
error_page 404 /404.html;
#error_page 502 /502.html;
#ERROR-PAGE-END
#PHP-INFO-START PHP引用配置可以注释或修改
include enable-php-82.conf;
#PHP-INFO-END
#REWRITE-START URL重写规则引用,修改后将导致面板设置的伪静态规则失效
include /www/server/panel/vhost/rewrite/files.test.ai.ireborn.com.cn.conf;
#REWRITE-END
# ============ 简历文件服务配置 ============
location /resumes/ {
alias /www/wwwroot/files.test.ai.ireborn.com.cn/resumes/;
# 跨域配置Coze 需要)
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, HEAD, OPTIONS';
add_header Access-Control-Allow-Headers 'Content-Type, Authorization';
# 处理 OPTIONS 预检请求
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, HEAD, OPTIONS';
add_header Access-Control-Allow-Headers 'Content-Type, Authorization';
add_header Content-Length 0;
return 204;
}
# 支持 PDF 文件
types {
application/pdf pdf;
}
# 禁止目录浏览
autoindex off;
}
# ============ 简历文件服务配置结束 ============
#禁止访问的文件或目录
location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|\.svn|\.project|LICENSE|README.md)
{
return 404;
}
#一键申请SSL证书验证目录相关设置
location ~ \.well-known{
allow all;
}
#禁止在证书验证目录放入敏感文件
if ( $uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$" ) {
return 403;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
error_log /dev/null;
access_log /dev/null;
}
location ~ .*\.(js|css)?$
{
expires 12h;
error_log /dev/null;
access_log /dev/null;
}
access_log /www/wwwlogs/files.test.ai.ireborn.com.cn.log;
error_log /www/wwwlogs/files.test.ai.ireborn.com.cn.error.log;
}

93
docs/upload.php Normal file
View File

@@ -0,0 +1,93 @@
<?php
/**
* 简历文件上传接口
*
* 放置位置: /www/wwwroot/files.test.ai.ireborn.com.cn/upload.php
*
* 请求方式: POST
* 参数:
* - file: 文件multipart/form-data
* - token: 验证令牌(防止滥用)
*
* 返回:
* - {"code": 0, "url": "http://files.test.ai.ireborn.com.cn/resumes/xxx.pdf"}
* - {"code": 1, "error": "错误信息"}
*/
// 配置
$UPLOAD_DIR = '/www/wwwroot/files.test.ai.ireborn.com.cn/resumes/';
$BASE_URL = 'http://files.test.ai.ireborn.com.cn/resumes/';
$SECRET_TOKEN = 'your_secret_token_here_change_me'; // 请修改为你自己的密钥
$MAX_SIZE = 20 * 1024 * 1024; // 20MB
$ALLOWED_TYPES = ['application/pdf'];
// 设置响应头
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
// 处理 OPTIONS 预检请求
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(204);
exit;
}
// 只允许 POST 请求
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
echo json_encode(['code' => 1, 'error' => 'Method not allowed']);
exit;
}
// 验证令牌
$token = $_POST['token'] ?? $_SERVER['HTTP_X_UPLOAD_TOKEN'] ?? '';
if ($token !== $SECRET_TOKEN) {
http_response_code(403);
echo json_encode(['code' => 1, 'error' => 'Invalid token']);
exit;
}
// 检查文件是否上传
if (!isset($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
$error_msg = isset($_FILES['file']) ? 'Upload error: ' . $_FILES['file']['error'] : 'No file uploaded';
echo json_encode(['code' => 1, 'error' => $error_msg]);
exit;
}
$file = $_FILES['file'];
// 检查文件大小
if ($file['size'] > $MAX_SIZE) {
echo json_encode(['code' => 1, 'error' => 'File too large (max 20MB)']);
exit;
}
// 检查文件类型(通过扩展名)
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if ($ext !== 'pdf') {
echo json_encode(['code' => 1, 'error' => 'Invalid file type. Only PDF allowed.']);
exit;
}
// 生成文件名
$file_id = 'resume_' . bin2hex(random_bytes(6));
$filename = $file_id . '.pdf';
$filepath = $UPLOAD_DIR . $filename;
// 确保目录存在
if (!is_dir($UPLOAD_DIR)) {
mkdir($UPLOAD_DIR, 0755, true);
}
// 移动文件
if (move_uploaded_file($file['tmp_name'], $filepath)) {
$url = $BASE_URL . $filename;
echo json_encode([
'code' => 0,
'url' => $url,
'file_id' => $file_id,
'filename' => $filename
]);
} else {
echo json_encode(['code' => 1, 'error' => 'Failed to save file']);
}

70
docs/决策记录.md Normal file
View File

@@ -0,0 +1,70 @@
# 决策记录
> ⛔ **版本规则**:只允许追加,禁止修改/删除已有记录
---
## 决策索引
| 编号 | 日期 | 主题 | 决策结果 |
|------|------|------|---------|
| DR-001 | 2026-01-20 | 技术选型与框架规范覆盖 | 使用 Coze API + 火山引擎 RTC |
---
## DR-001 | 2026-01-20
### 背景
项目需要实现 AI 语音面试系统。已有完整的 Coze 工作流(工作流 ID7595077233002840079包含面试逻辑、评分算法、报告生成等功能。需要确定技术选型并明确与 AgentWD 框架规范的差异。
### 方案选项
| 选项 | 方案描述 | 优点 | 缺点 |
|------|---------|------|------|
| A | 全部遵循框架规范,使用 OpenRouter + MySQL | 完全符合框架规范 | 需重新开发面试逻辑,工作量大 |
| B | 复用 Coze 工作流,覆盖部分规范 | 开发效率高,复用现有资产 | 与框架规范有差异 |
### 多角色分析
**产品经理**
- 分析:项目核心价值在于 AI 面试能力Coze 工作流已经过验证
- 建议:复用现有工作流,快速上线
- 倾向:方案 B
**架构师**
- 分析Coze + 火山引擎 RTC 同属火山生态,集成成本低
- 建议:前后端遵循框架规范,仅 AI 层使用 Coze
- 倾向:方案 B
**前端开发**
- 分析Vue3 + Element Plus 符合框架规范,无额外学习成本
- 建议:前端完全遵循框架规范
- 倾向:方案 B
### 最终决策
**决策结果**:选择方案 B
**决策原因**
1. Coze 工作流已包含完整面试逻辑,复用可大幅减少开发时间
2. 前端、后端框架仍遵循规范,仅 AI 服务层使用 Coze
3. 火山引擎 RTC 与 Coze 同生态,官方支持对接
4.`docs/技术选型.md` 中明确声明覆盖项
**否决方案**
- 方案 A 被否决,原因:需要重新开发 AI 面试逻辑,工作量大,且已有成熟方案
### 影响范围
- [x] 技术选型文档需创建
- [ ] PRD 无需更新
- [ ] 原型无需更新
### 来源对话框
第 1 对话框
---
<!-- 新决策从这里开始追加 -->

140
docs/同步清单.md Normal file
View File

@@ -0,0 +1,140 @@
# 同步清单
> 多对话框协作的核心同步文件
> ✅ 可覆盖,需记录变更日志
---
## 项目状态
| 项目 | 内容 |
|------|------|
| **当前阶段** | 开发阶段 |
| **进度** | 65% |
| **最后更新** | 2026-01-20 16:30 |
| **当前对话框** | 第1对话框 |
---
## 待办事项
### 🔴 紧急(今日必须完成)
- [ ] 确认 PRD 待确认事项(管理后台登录、面试时长等)
### 🟡 重要(本周完成)
- [ ] 初始化前端项目Vue3 + Vite
- [ ] 初始化后端项目FastAPI
- [ ] 实现后端 Coze API 封装
- [ ] 实现后端 RTC Token 生成
### 🟢 普通(待安排)
- [ ] 前端用户端页面开发5个页面
- [ ] 前端管理后台页面开发2个页面
- [ ] 前端 RTC SDK 集成
- [ ] 联调测试
- [ ] 部署上线
---
## 进行中的任务
| 任务 | 负责角色 | 开始时间 | 状态 |
|------|---------|---------|------|
| 需求分析 | 产品经理 | 2026-01-20 | ✅ 完成 |
| 技术选型 | 架构师 | 2026-01-20 | ✅ 完成 |
| 文档整理 | AI | 2026-01-20 | ✅ 完成 |
---
## 已完成任务
| 任务 | 完成时间 | 备注 |
|------|---------|------|
| 创建项目目录结构 | 2026-01-20 | 按框架规范创建 |
| 初始化核心文档 | 2026-01-20 | CONTEXT.md 等 |
| 撰写 PRD | 2026-01-20 | v1.0 |
| 技术选型决策 | 2026-01-20 | DR-001使用 Coze API |
| API 文档设计 | 2026-01-20 | 5 个接口 |
| 数据库结构文档 | 2026-01-20 | Coze 数据库 |
| 前端项目骨架 | 2026-01-20 | Vue3 + Vite + Element Plus |
| 后端项目骨架 | 2026-01-20 | FastAPI + Coze API 封装 |
| Coze 工作流分析 | 2026-01-20 | 详见 coze-workflows/工作流分析.md |
---
## 阻塞问题
| 问题 | 阻塞原因 | 待处理人 | 状态 |
|------|---------|---------|------|
| 管理后台数据查询 | Coze 数据库无 REST API | 产品 | 待讨论方案 |
---
## 决策统计
| 项目 | 数量 |
|------|------|
| 总决策数 | 1 |
| 本周新增 | 1 |
| 待讨论 | 0 |
---
## 开发任务清单
### 阶段 1项目初始化
- [ ] 创建前端项目Vue3 + TypeScript + Vite
- [ ] 安装前端依赖Element Plus、Tailwind、Axios、RTC SDK
- [ ] 创建后端项目FastAPI
- [ ] 安装后端依赖httpx、python-multipart
- [ ] 配置环境变量
### 阶段 2后端核心功能
- [ ] 实现 Coze API 封装(文件上传、数据库查询)
- [ ] 实现 RTC 服务封装Token 生成)
- [ ] 实现 `POST /api/candidates` 接口
- [ ] 实现 `POST /api/rooms` 接口
- [ ] 实现 `GET /api/candidates` 接口
- [ ] 实现 `GET /api/candidates/:id` 接口
### 阶段 3前端用户端
- [ ] 实现欢迎页Welcome
- [ ] 实现信息收集页InfoCollection
- [ ] 实现模拟来电页IncomingCall
- [ ] 集成火山引擎 RTC SDK
- [ ] 实现语音通话页InCall
- [ ] 实现面试结束页Completed
### 阶段 4前端管理后台
- [ ] 实现候选人列表页
- [ ] 实现候选人详情页
- [ ] 实现评分雷达图组件
- [ ] 实现 PDF 导出功能
### 阶段 5联调测试
- [ ] 端到端流程测试
- [ ] 语音质量测试
- [ ] 异常场景测试
### 阶段 6部署上线
- [ ] 编写 Dockerfile
- [ ] 配置 Nginx
- [ ] 部署到服务器
---
## 变更日志
| 日期 | 变更内容 | 操作人 |
|------|---------|--------|
| 2026-01-20 | 更新任务清单,添加开发阶段 | AI |
| 2026-01-20 | 初始化同步清单 | AI |

121
docs/技术选型.md Normal file
View File

@@ -0,0 +1,121 @@
# 技术选型
> 本项目技术选型说明,包含与框架规范的覆盖声明
---
## 一、遵循框架规范
| 层级 | 技术 | 说明 |
|------|------|------|
| **前端框架** | Vue 3 + TypeScript | 符合框架规范 |
| **构建工具** | Vite | 符合框架规范 |
| **UI 组件库** | Element Plus | 符合框架规范 |
| **CSS 方案** | Tailwind CSS | 符合框架规范 |
| **HTTP 客户端** | Axios | 符合框架规范 |
| **状态管理** | Pinia | 按需使用 |
| **后端框架** | Python + FastAPI | 符合框架规范 |
| **容器化** | Docker + Docker Compose | 符合框架规范 |
---
## 二、技术选型覆盖
> 以下选项与框架默认规范不同,需特别说明
| 项目 | 框架默认 | 本项目选择 | 覆盖原因 |
|------|----------|------------|----------|
| **AI 网关** | OpenRouter.ai | Coze API | 复用已有 Coze 工作流,包含完整面试逻辑 |
| **数据存储** | MySQL | Coze 数据库 | 复用现有数据结构,减少开发工作量 |
| **实时音视频** | - | 火山引擎 RTC | 与 Coze 同属火山引擎生态,官方支持对接 |
---
## 三、第三方服务依赖
### 3.1 Coze 平台
| 资源 | ID | 用途 |
|------|-----|------|
| Bot工作流 | 7595113005181386792 | AI 面试官对话逻辑 |
| 数据库 | 7595077053909712922 | 候选人数据存储 |
**API 端点**
- 基础 URL`https://api.coze.cn`
- 文件上传:`POST /v1/files/upload`
- 语音房间:`POST /v1/audio/rooms`
- 数据库查询:`POST /v1/database/query`
### 3.2 火山引擎 RTC
| 配置项 | 说明 |
|--------|------|
| SDK | `@volcengine/rtc` |
| 音频格式 | PCM 16000Hz |
| 用途 | 前端与 Coze Bot 实时语音通话 |
---
## 四、环境变量
```bash
# Coze 配置
COZE_API_BASE=https://api.coze.cn
COZE_PAT_TOKEN=pat_xxx # 从 Coze 平台获取
COZE_BOT_ID=7595077233002840079
COZE_DATABASE_ID=7595077053909712922
# 火山引擎 RTC 配置
VOLCENGINE_APP_ID=xxx # 从火山引擎控制台获取
VOLCENGINE_APP_KEY=xxx
# 服务配置
API_PORT=8000
FRONTEND_URL=http://localhost:5173
```
---
## 五、前端依赖清单
```json
{
"dependencies": {
"vue": "^3.4.0",
"vue-router": "^4.2.0",
"pinia": "^2.1.0",
"axios": "^1.6.0",
"element-plus": "^2.5.0",
"@element-plus/icons-vue": "^2.3.0",
"@volcengine/rtc": "^4.x"
},
"devDependencies": {
"typescript": "^5.3.0",
"vite": "^5.0.0",
"tailwindcss": "^3.4.0",
"@vitejs/plugin-vue": "^5.0.0"
}
}
```
---
## 六、后端依赖清单
```txt
# requirements.txt
fastapi>=0.109.0
uvicorn>=0.27.0
httpx>=0.26.0
python-multipart>=0.0.6
pydantic>=2.5.0
python-dotenv>=1.0.0
```
---
## 变更日志
| 日期 | 变更内容 | 操作人 |
|------|---------|--------|
| 2026-01-20 | 初始化技术选型 | AI |

206
docs/部署文档.md Normal file
View File

@@ -0,0 +1,206 @@
# AI 语音面试系统 - 部署文档
> 更新日期: 2026-01-21
> 状态: ✅ 已部署
## 一、服务器信息
| 项目 | 值 |
|------|-----|
| 服务器 IP | 47.107.172.23 |
| SSH 用户名 | root |
| SSH 密码 | Nj861021 |
| 宝塔面板 | http://47.107.172.23:8888/ |
| 宝塔 API Token | PKdfnaInQL0P5ghB8SvwbrGcIpXWaEvq |
| 域名解析 | *.ai.ireborn.com.cn → 47.107.172.23 |
| 测试域名 | *.test.ai.ireborn.com.cn |
## 二、部署地址 (已上线)
| 服务 | 地址 | 状态 |
|------|------|------|
| 用户端 | http://interview.test.ai.ireborn.com.cn | ✅ |
| 管理后台 | http://interview.test.ai.ireborn.com.cn/admin | ✅ |
| 后端 API | http://interview.test.ai.ireborn.com.cn/api/health | ✅ |
| 文件服务 | https://files.test.ai.ireborn.com.cn | ✅ |
> ⚠️ 当前为简化版后端,完整功能代码需要手动上传后重新构建
## 三、Docker 部署
### 3.1 目录结构
```
/www/wwwroot/ai-interview/
├── deploy/
│ ├── docker-compose.yml
│ ├── Dockerfile.frontend
│ ├── Dockerfile.backend
│ ├── nginx/
│ │ └── frontend.conf
│ └── .env
├── frontend/
├── backend/
└── uploads/
```
### 3.2 环境变量配置
创建 `/www/wwwroot/ai-interview/deploy/.env`:
```bash
# Coze 配置
COZE_PAT_TOKEN=pat_nd1wU47WyPS9GCIyJ1clnH8h1WOQXGrYELX8w73TnSZaYbFdYD4swIhzcETBUbfT
COZE_BOT_ID=7595113005181386792
# 工作流 ID
COZE_WORKFLOW_A_ID=7597357422713798710
COZE_WORKFLOW_C_ID=7597376294612107318
# 文件服务器
FILE_SERVER_URL=https://files.test.ai.ireborn.com.cn
FILE_SERVER_TOKEN=ai_interview_2026_secret
```
### 3.3 部署命令
```bash
cd /www/wwwroot/ai-interview/deploy
# 构建并启动
docker-compose up -d --build
# 查看日志
docker-compose logs -f
# 停止服务
docker-compose down
# 重启服务
docker-compose restart
```
### 3.4 端口映射
| 服务 | 容器端口 | 宿主机端口 |
|------|----------|------------|
| Frontend | 80 | 3000 |
| Backend | 8000 | 8000 |
## 四、Nginx 反向代理配置
### 4.1 前端 + API 合并 (推荐)
域名: `interview.test.ai.ireborn.com.cn`
```nginx
server {
listen 80;
listen 443 ssl http2;
server_name interview.test.ai.ireborn.com.cn;
# SSL 证书 (宝塔自动配置)
ssl_certificate /www/server/panel/vhost/cert/interview.test.ai.ireborn.com.cn/fullchain.pem;
ssl_certificate_key /www/server/panel/vhost/cert/interview.test.ai.ireborn.com.cn/privkey.pem;
# 前端
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# API 代理 (前端容器内部已处理,此处可选)
location /api/ {
proxy_pass http://127.0.0.1:8000/api/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 120s;
}
}
```
### 4.2 独立 API 域名 (可选)
域名: `interview-api.test.ai.ireborn.com.cn`
```nginx
server {
listen 80;
listen 443 ssl http2;
server_name interview-api.test.ai.ireborn.com.cn;
ssl_certificate /www/server/panel/vhost/cert/interview-api.test.ai.ireborn.com.cn/fullchain.pem;
ssl_certificate_key /www/server/panel/vhost/cert/interview-api.test.ai.ireborn.com.cn/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 120s;
proxy_connect_timeout 120s;
# CORS
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
}
}
```
## 五、更新部署
```bash
cd /www/wwwroot/ai-interview
# 拉取最新代码
git pull origin main
# 重新构建并部署
cd deploy
docker-compose down
docker-compose up -d --build
# 查看状态
docker-compose ps
```
## 六、故障排查
### 6.1 查看容器日志
```bash
# 前端日志
docker logs ai-interview-frontend
# 后端日志
docker logs ai-interview-backend
```
### 6.2 进入容器调试
```bash
# 进入后端容器
docker exec -it ai-interview-backend /bin/sh
# 进入前端容器
docker exec -it ai-interview-frontend /bin/sh
```
### 6.3 常见问题
| 问题 | 解决方案 |
|------|----------|
| 前端白屏 | 检查 nginx 配置,确保 `try_files` 指向 index.html |
| API 404 | 检查 proxy_pass 地址和端口 |
| CORS 错误 | 在 nginx 添加 CORS 头 |
| 环境变量无效 | 确认 .env 文件存在且格式正确 |

110
docs/项目状态快照.md Normal file
View File

@@ -0,0 +1,110 @@
# 项目状态快照
> 新对话框快速恢复上下文的关键文档
> ✅ 可覆盖,需记录变更日志
---
## 一、项目全貌
### 1.1 基本信息
| 项目 | 内容 |
|------|------|
| 项目名称 | AI Interview (AI面试助手) |
| 项目编号 | 011-ai-interview-2601 |
| 启动日期 | 2026-01-20 |
| 当前阶段 | 设计阶段 |
| 整体进度 | 20% |
### 1.2 技术栈
| 层级 | 技术 |
|------|------|
| 前端 | Vue3 + TypeScript + Element Plus |
| 后端 | Python + FastAPI |
| AI 服务 | Coze API覆盖框架规范 |
| 实时音视频 | 火山引擎 RTC |
| 数据存储 | Coze 数据库(覆盖框架规范) |
| 部署 | Docker + Nginx |
---
## 二、阶段进度
| 阶段 | 状态 | 完成度 | 备注 |
|------|------|--------|------|
| 需求分析 | ✅ 完成 | 100% | PRD v1.0 已完成 |
| 技术选型 | ✅ 完成 | 100% | DR-001 已决策 |
| 设计阶段 | 🔄 进行中 | 50% | API/数据库文档已完成 |
| 开发阶段 | ⏳ 待开始 | 0% | |
| 测试阶段 | ⏳ 待开始 | 0% | |
| 上线部署 | ⏳ 待开始 | 0% | |
---
## 三、核心决策摘要
> 详细内容见 `决策记录.md`
| 编号 | 主题 | 结果 |
|------|------|------|
| DR-001 | 技术选型与框架规范覆盖 | 使用 Coze API + 火山引擎 RTC在技术选型中声明覆盖 |
---
## 四、关键文档
| 文档 | 路径 | 状态 |
|------|------|------|
| PRD | `docs/PRD.md` | ✅ v1.0 |
| 技术选型 | `docs/技术选型.md` | ✅ |
| 决策记录 | `docs/决策记录.md` | ✅ |
| API 文档 | `docs/api/endpoints.md` | ✅ |
| 数据库结构 | `docs/database/表结构.md` | ✅ |
| 功能模块索引 | `docs/功能模块索引.md` | 📝 待创建 |
---
## 五、当前待办
> 详细内容见 `同步清单.md`
1. 确认 PRD 待确认事项
2. 初始化前端项目Vue3 + Vite
3. 初始化后端项目FastAPI
4. 实现后端 Coze API 封装
---
## 六、已知问题
| 问题 | 状态 | 处理方案 |
|------|------|---------|
| - | - | - |
---
## 七、上一对话框教训
> 从交接中沉淀的经验
- 新项目,暂无
---
## 八、现有资源
| 资源 | 说明 |
|------|------|
| Coze 工作流 | 已有完整面试逻辑ID7595077233002840079 |
| Coze 数据库 | 已有数据结构ID7595077053909712922 |
---
## 变更日志
| 日期 | 变更内容 | 操作人 |
|------|---------|--------|
| 2026-01-20 | 更新阶段进度,添加技术栈详情 | AI |
| 2026-01-20 | 初始化快照 | AI |

View File

@@ -0,0 +1,174 @@
# AI 语音面试系统 - 项目进度总结
> 更新日期: 2026-01-21
## 一、项目概述
**项目名称**: AI 语音面试系统 (轻医美行业)
**项目周期**: 2026-01 至今
**当前状态**: 🟡 开发中 (核心功能已完成,语音模式待优化)
## 二、已完成功能
### 2.1 用户端 (前端)
| 功能 | 状态 | 说明 |
|------|------|------|
| 欢迎页面 | ✅ | 品牌展示、开始面试入口 |
| 信息采集 | ✅ | 姓名输入、简历 PDF 上传 |
| 面试初始化 | ✅ | 调用 Workflow A 生成 session_id |
| 文字面试模式 | ✅ | 基于 /v3/chat API 的文字对话 |
| 语音面试模式 | 🟡 | RTC 连接正常session_id 传递待优化 |
| 调试面板 | ✅ | 显示 session_id、API 响应、错误信息 |
### 2.2 管理后台
| 功能 | 状态 | 说明 |
|------|------|------|
| 登录页面 | ✅ | 账号密码认证 |
| 数据概览 | ✅ | 统计卡片、匹配度分布、状态饼图、排行榜 |
| 面试列表 | ✅ | 搜索、筛选、分页、阶段标签 |
| 面试详情 | ✅ | 匹配度圆环、维度评分、风险分析、对话记录 |
| 骨架屏加载 | ✅ | 优化加载体验,替代 v-loading 遮罩 |
### 2.3 后端服务
| 功能 | 状态 | 说明 |
|------|------|------|
| 文件上传 | ✅ | 支持 PDF上传到自建文件服务器 |
| 面试初始化 API | ✅ | 调用 Workflow A返回 session_id |
| 文字聊天 API | ✅ | 调用 /v3/chat支持多轮对话 |
| 语音房间 API | ✅ | 调用 /v1/audio/rooms 创建 RTC 房间 |
| 管理后台 API | ✅ | 通过 Workflow C 查询 Coze 数据库 |
### 2.4 Coze 工作流
| 工作流 | ID | 功能 |
|--------|-----|------|
| Workflow A | 7597357422713798710 | 面试初始化:接收 name + file_url解析简历生成 session_id |
| Workflow B | 7595077233002840079 | 面试主流程4 维度提问、评分、生成报告 |
| Workflow C | 7597376294612107318 | 数据查询:接收 table + sql执行增删改查 |
### 2.5 基础设施
| 组件 | 状态 | 说明 |
|------|------|------|
| 自建文件服务器 | ✅ | Nginx + PHP域名 files.test.ai.ireborn.com.cn |
| Coze 数据库 | ✅ | ci_interview_assessments, ci_interview_logs, ci_business_config |
## 三、技术架构
```
┌─────────────────────────────────────────────────────────────┐
│ 用户端 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 欢迎页面 │→│ 信息采集 │→│ 面试页面 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ ↓ ↓ │
│ 文件上传 语音/文字模式 │
└─────────────────────────────────────────────────────────────┘
↓ ↓
┌─────────────────────────────────────────────────────────────┐
│ FastAPI 后端 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ /init-interview │ /api/chat │ /api/room │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Coze 平台 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Workflow A │ │ Workflow B │ │ Workflow C │ │
│ │ (初始化) │ │ (面试主流程) │ │ (数据查询) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ ↓ │
│ Coze Database │
└─────────────────────────────────────────────────────────────┘
```
## 四、待解决问题
### 4.1 语音模式 session_id 传递
**问题**: 语音模式下session_id 无法通过 /v1/audio/rooms API 传递到 Workflow B
**已尝试方案**:
1.`config.session_id` - 不支持
2.`parameters` 字段 - 不支持
3.`user_id` 字段 - 可设置但 Workflow 无法读取
4. ❌ Volcengine RTC SDK `sendRoomMessage` - 不是 Coze 信令通道
5. 🟡 `@coze/realtime-api` SDK `session.update` 事件 - 待验证
**建议方案**:
- 在 Workflow B 开始时通过数据库查询最近的 session_id
- 或使用 `@coze/realtime-api``session.update` 事件
### 4.2 面试阶段字段
**已实现**: current_stage 数值映射
- >= 50: 面试完成 (求职动机阶段)
- >= 40: 素质项评估
- >= 30: 销售观评估
- >= 20: 销售技能
- >= 10: 简历上传
## 五、数据库表结构
### ci_interview_assessments
| 字段 | 类型 | 说明 |
|------|------|------|
| id | String | 主键 (自动生成) |
| session_id | String | 会话 ID |
| candidate_name | String | 候选人姓名 |
| current_stage | String | 当前阶段 (10-50) |
| sales_skill_score | String | 销售技能分数 |
| sales_skill_report | String | 销售技能报告 |
| sales_concept_score | String | 销售观分数 |
| sales_concept_report | String | 销售观报告 |
| competency_score | String | 综合素质分数 |
| competency_report | String | 综合素质报告 |
| final_score_report | String | 最终评估报告 |
| resume_text | String | 简历文本 |
| risk_warning | String | 风险提示 |
### ci_interview_logs
| 字段 | 类型 | 说明 |
|------|------|------|
| log_id | String | 主键 (必填) |
| session_id | String | 会话 ID |
| stage | String | 面试阶段 |
| round | String | 轮次 |
| ai_question | String | AI 问题 |
| user_answer | String | 用户回答 |
| log_type | String | 日志类型 |
## 六、关键文件清单
### 前端
- `frontend/src/pages/interview/index.vue` - 欢迎页 + 信息采集
- `frontend/src/pages/interview/call.vue` - 面试页面 (语音/文字)
- `frontend/src/pages/admin/*.vue` - 管理后台页面
- `frontend/src/composables/useCozeRealtime.ts` - Coze Realtime SDK 封装
- `frontend/src/api/candidate.ts` - API 调用封装
### 后端
- `backend/main.py` - FastAPI 入口
- `backend/app/services/coze_service.py` - Coze API 服务
- `backend/app/routers/init.py` - 面试初始化 API
- `backend/app/routers/chat.py` - 文字聊天 API
- `backend/app/routers/room.py` - 语音房间 API
- `backend/app/routers/admin.py` - 管理后台 API
### 配置
- `backend/.env` - 环境变量 (PAT_TOKEN, BOT_ID, FILE_SERVER_TOKEN 等)
- `docs/upload.php` - 文件上传 PHP 脚本
- `docs/nginx-files-server.conf` - Nginx 配置
## 七、访问地址
| 服务 | 地址 |
|------|------|
| 用户端 | http://localhost:5173 |
| 管理后台 | http://localhost:5173/admin |
| 后端 API | http://localhost:8000 |
| 文件服务器 | https://files.test.ai.ireborn.com.cn |

View File

@@ -0,0 +1,194 @@
# AI 语音面试系统 - 项目进度总结
**更新日期**: 2026-01-21
**项目代号**: 011-ai-interview-2601
---
## 一、已完成功能
### 1. 基础架构 ✅
- [x] 前端项目初始化 (Vue 3 + TypeScript + Vite + Element Plus)
- [x] 后端项目初始化 (FastAPI + Python)
- [x] Coze API 集成 (PAT Token 认证)
- [x] 文件服务器搭建 (Nginx + PHP 上传脚本)
### 2. 工作流 A - 面试初始化 ✅
- [x] 接收姓名和简历 PDF
- [x] 上传简历到自建文件服务器 (`files.test.ai.ireborn.com.cn`)
- [x] 调用 Coze 工作流解析简历
- [x] 生成 `session_id` 并写入 `ci_interview_assessments`
- [x] 返回 `session_id` 给前端
### 3. 工作流 B - 面试对话 ⚠️ (部分完成)
- [x] 调用 Coze `/v3/chat` API 进行对话
- [x] 支持文字面试模式
- [x] 支持语音面试模式 (RTC 房间创建)
- [ ] **未完成**: 多轮对话状态维持
- [ ] **未完成**: 对话日志写入 `ci_interview_logs`
### 4. 工作流 C1 - 数据查询 ✅
- [x] 支持查询 `ci_interview_assessments`
- [x] 支持查询 `ci_interview_logs`
- [x] 支持查询 `ci_business_config`
- [x] 通过 JSON 输入指定表名和 SQL
### 5. 后台管理页面 ✅
- [x] 登录页面 (`/admin/login`)
- [x] 面试列表页面 (`/admin/interviews`)
- [x] 面试详情页面 (`/admin/interviews/:id`)
- [x] 基本信息展示
- [x] 维度评分展示
- [x] 评估报告展示
- [x] 对话记录展示 (数据依赖工作流 B)
- [x] 配置管理页面 (`/admin/configs`)
### 6. 文件服务 ✅
- [x] 自建文件服务器 (`files.test.ai.ireborn.com.cn`)
- [x] PHP 上传接口 (Token 认证)
- [x] Nginx 静态文件服务
- [x] CORS 支持
---
## 二、核心问题
### 问题:工作流 B 多轮对话状态无法维持
**现象**:
- 每次调用 `/v3/chat` APICoze 返回新的 `conversation_id`
- 即使传入上一次的 `conversation_id`,仍然返回新值
- 导致工作流 B 每次都从头执行,重复显示欢迎语
**影响**:
1. 面试无法正常进行多轮问答
2. 对话日志无法写入 `ci_interview_logs`
3. 后台管理页面无法显示对话记录
**已尝试的方案**:
1. ❌ 传入 `conversation_id` 参数 - Coze 仍返回新值
2. ❌ 使用 `/v1/workflows/chat` 接口 - 接口不存在或参数格式不对
3. ⏳ 通过 `session_id` 在工作流内部管理状态 - 需要修改工作流 B
---
## 三、解决方案建议
### 方案:工作流 B 内部状态管理
修改 Coze 工作流 B不依赖 Coze 的 conversation 机制,改为:
1. **开始节点**: 接收 `session_id` 和用户消息
2. **查询状态**: 从 `ci_interview_logs` 表查询该 `session_id` 的历史对话数量
3. **条件分支**:
- 如果历史为 0显示欢迎语更新状态
- 如果历史 > 0直接进入下一轮提问
4. **写入日志**: 每次对话后,将 AI 问题和用户回答写入 `ci_interview_logs`
5. **结束判断**: 当对话轮次达到设定值时,生成评估报告
---
## 四、技术栈
| 模块 | 技术 |
|------|------|
| 前端 | Vue 3 + TypeScript + Vite + Element Plus + Tailwind CSS |
| 后端 | Python + FastAPI + Pydantic + httpx |
| AI 平台 | Coze (扣子) |
| 文件服务 | Nginx + PHP |
| 数据库 | Coze 内置数据库 |
---
## 五、API 端点
### 后端 API
| 端点 | 方法 | 说明 |
|------|------|------|
| `/api/init-interview` | POST | 初始化面试(上传简历、生成 session_id |
| `/api/chat` | POST | 文字面试对话 |
| `/api/rooms` | POST | 创建语音面试房间 |
| `/api/admin/login` | POST | 管理员登录 |
| `/api/admin/interviews` | GET | 面试列表 |
| `/api/admin/interviews/{id}` | GET | 面试详情 |
| `/api/admin/interviews/{id}/logs` | GET | 对话记录 |
### Coze 工作流
| 工作流 | ID | 说明 |
|--------|-----|------|
| 工作流 A | 7597357422713798710 | 面试初始化(简历解析) |
| 工作流 B | 7595077233002840079 | 面试对话Chatflow |
| 工作流 C1 | 7597376294612107318 | 数据查询 |
---
## 六、数据库表
| 表名 | 说明 |
|------|------|
| ci_interview_assessments | 面试评估记录 |
| ci_interview_logs | 面试对话日志 |
| ci_business_config | 业务配置 |
---
## 七、下一步工作
1. **修改工作流 B** - 实现内部状态管理,不依赖 conversation_id
2. **测试多轮对话** - 验证对话日志正确写入数据库
3. **完善语音面试** - 测试 RTC 语音对话功能
4. **优化后台页面** - 改进布局和用户体验
---
## 八、文件结构
```
011-ai-interview-2601/
├── frontend/ # 前端项目
│ ├── src/
│ │ ├── api/ # API 请求
│ │ ├── pages/
│ │ │ ├── interview/ # 面试页面
│ │ │ └── admin/ # 后台管理
│ │ ├── composables/ # 组合式函数 (useRTC)
│ │ └── router/ # 路由配置
│ └── package.json
├── backend/ # 后端项目
│ ├── app/
│ │ ├── routers/ # API 路由
│ │ ├── services/ # 服务层 (coze_service)
│ │ └── schemas.py # 数据模型
│ ├── main.py
│ └── requirements.txt
├── docs/ # 文档
│ ├── upload.php # PHP 上传脚本
│ ├── nginx-files-server.conf
│ └── 项目进度总结-20260121.md
└── coze-workflows/ # Coze 工作流配置
```
---
## 九、配置信息
### 环境变量 (.env)
```env
COZE_PAT_TOKEN=pat_xxx
COZE_BOT_ID=7595113005181386792
FILE_SERVER_TOKEN=ai_interview_2026_secret
TUNNEL_URL=http://files.test.ai.ireborn.com.cn
```
### 文件服务器
- 域名: `files.test.ai.ireborn.com.cn`
- 上传接口: `/upload.php`
- 文件目录: `/resumes/`
---
**总结**: 项目基础架构已完成,核心问题是工作流 B 的多轮对话状态维持。需要在 Coze 工作流 B 中实现基于 session_id 的状态管理,才能正确记录对话日志并在后台展示。