基于 Spring Boot 4.1、Java 25、Spring AI 2.0、React、PostgreSQL/pgvector、Redis 和 RustFS 构建的开源 AI 面试平台,支持简历智能分析、模拟面试、语音面试和知识库 RAG。
See the codeInterviewGuide 是一个集成了简历分析、模拟面试(文字 + 语音)、面试安排、知识库管理、知识库题库面试和多模型配置的智能面试辅助平台。系统利用大语言模型(LLM)、向量数据库、Redis Stream 异步任务和实时语音技术,为求职者、HR 和培训机构提供智能化的简历评估、面试练习、知识库问答和面试日程管理能力。

本项目承诺完整功能免费开源,也不会做所谓的 Pro 版或“付费解锁核心功能”之类的设计。
如果你想学习这个项目,或者希望把它作为个人项目经历 / 毕设选题,我也整理了一套相对细致的教程:从基础设施搭建、核心业务实现,到最后如何在面试中讲清楚思路与亮点,尽量把容易卡住的地方讲透。
如果你确实需要更系统的辅导,可以点这里了解详情(教程为付费内容,主要是想覆盖一些时间成本,望理解,感谢支持):《SpringAI 智能面试平台+RAG 知识库》。
| 技术 | 版本 | 说明 |
|---|---|---|
| Spring Boot | 4.1.0 | 应用框架 |
| Java | 25 | 开发语言(虚拟线程) |
| Spring AI | 2.0.0 | AI 集成框架、OpenAI 兼容模型接入 |
| Spring AI Agent Utils | 0.10.0 | Skill 资源加载、Advisor 能力扩展 |
| PostgreSQL + pgvector | 14+ | 关系数据库 + 向量存储(Compose 默认 PG16) |
| Redis + Redisson | 6+ / 4.0.0 | 缓存 + 消息队列(Stream) |
| Apache Tika | 2.9.2 | 文档解析 |
| iText 8 | 8.0.5 | PDF 导出 |
| MapStruct | 1.6.3 | 对象映射 |
| SpringDoc OpenAPI | 3.0.2 | API 接口文档 |
| DashScope SDK | 2.22.7 | 语音识别/合成(Qwen3 ASR/TTS) |
| AWS S3 SDK | 2.29.51 | S3 兼容对象存储(MinIO/RustFS) |
| WebSocket | - | 语音面试实时双向通信 |
| Gradle | 9.6.1 | 构建工具 |
技术选型常见问题解答:
ConcurrentHashMap 实现面试会话的缓存。| 技术 | 版本 | 说明 |
|---|---|---|
| React | 18.3 | UI 框架 |
| TypeScript | 5.6 | 开发语言 |
| Vite | 5.4 | 构建工具 |
| Tailwind CSS | 4.1 | 样式框架 |
| React Router | 7.11 | 路由管理 |
| Framer Motion | 12.23 | 动画库 |
| Recharts | 3.6 | 图表库 |
| Lucide React | 0.468 | 图标库 |
| React Big Calendar | 1.19 | 面试日历组件 |
| React Virtuoso | 4.18 | RAG 聊天虚拟列表 |
| pnpm | 10.26 | 前端包管理器 |
SKILL.md 定义考察范围、难度分布和参考知识库。实时语音对话面试,WebSocket + 千问3 语音模型(ASR/TTS/LLM 统一 API Key):
已知问题:端到端延迟偏高(服务端音频中转)、无耳机时回声泄漏、TTS 音色单一、弱网音频断续。后续计划探索 WebRTC、客户端 VAD 降噪、端到端语音模型等方案。
~/.interview-guide/,支持 API Key 加密配置。面试中心:

Skill 出题 + JD 解析:

简历库:

简历上传分析:

简历分析详情:

面试记录:

面试详情:

模拟面试:

面试安排

多模型切换 + 语音服务设置:

知识库管理:

问答助手:

interview-guide/
├── app/ # 后端应用
│ ├── src/main/java/interview/guide/
│ │ ├── App.java # 主启动类
│ │ ├── common/ # 通用基础能力
│ │ │ ├── ai/ # LLM Provider、结构化输出、Prompt 安全
│ │ │ ├── annotation/ # @RateLimit 可重复限流注解
│ │ │ ├── aspect/ # RateLimitAspect + Redis Lua 限流
│ │ │ ├── async/ # Redis Stream 生产者/消费者模板
│ │ │ ├── config/ # CORS、S3、OpenAPI、Jackson 等配置
│ │ │ ├── evaluation/ # 文字/语音共用的统一评估引擎
│ │ │ ├── exception/ # 业务异常与全局异常处理
│ │ │ └── result/ # 统一响应 Result<T>
│ │ ├── infrastructure/ # 基础设施
│ │ │ ├── export/ # PDF 导出
│ │ │ ├── file/ # 文件解析、校验、清洗、S3 存储
│ │ │ ├── mapper/ # MapStruct 映射器
│ │ │ └── redis/ # RedisService、面试会话缓存
│ │ └── modules/ # 业务模块
│ │ ├── interview/ # 模拟面试模块
│ │ ├── interviewschedule/ # 面试安排模块
│ │ ├── knowledgebase/ # 知识库模块
│ │ ├── llmprovider/ # 多模型 Provider 与语音配置
│ │ ├── resume/ # 简历模块
│ │ └── voiceinterview/ # 语音面试模块
│ └── src/main/resources/
│ ├── application.yml # 应用配置
│ ├── prompts/ # AI 提示词模板(StringTemplate)
│ ├── scripts/ # Redis Lua 脚本
│ ├── skills/ # 面试 Skill 定义和参考题库
│ └── voice-interview-opening.yml # 语音面试开场白配置
│
├── frontend/ # 前端应用
│ ├── src/
│ │ ├── api/ # API 接口
│ │ ├── components/ # 公共组件
│ │ ├── hooks/ # 业务 Hooks
│ │ ├── pages/ # 页面组件
│ │ ├── types/ # 类型定义
│ │ └── utils/ # 工具函数
│ ├── package.json
│ └── vite.config.ts
│
├── docker-compose.yml # 完整部署:前端 + 后端 + PostgreSQL + Redis + MinIO
├── docker-compose.dev.yml # 本地开发依赖:PostgreSQL + Redis + RustFS
├── docs/ # 架构设计与改造记录
├── .env.example # 环境变量示例
└── README.md
环境要求:
| 依赖 | 版本 | 必需 | 说明 |
|---|---|---|---|
| JDK | 25 | 是 | 开发语言 |
| Node.js | 18+ | 是 | 前端构建 |
| pnpm | 10+ | 推荐 | 前端包管理器(项目 packageManager 指定 10.26) |
| Docker | - | 推荐 | 一键启动依赖服务(PostgreSQL/Redis/RustFS) |
如果不用 Docker,需要自行安装 PostgreSQL 14+(含 pgvector 扩展)、Redis 6+ 和 S3 兼容存储。
git clone https://github.com/Snailclimb/interview-guide.git
cd interview-guide
推荐复制 .env.example 为 .env,后端 bootRun 会自动读取根目录 .env。最少需要填写 AI_BAILIAN_API_KEY,用于 DashScope 文本模型、ASR 和 TTS:
cp .env.example .env
# 编辑 .env
# AI_BAILIAN_API_KEY=your_dashscope_api_key
# AI_MODEL=qwen3.5-flash
如果你更习惯通过 shell 环境变量注入,也可以这样设置:
# macOS / Linux(zsh)
echo 'export AI_BAILIAN_API_KEY=your_api_key' >> ~/.zshrc
source ~/.zshrc
# Linux(bash)
echo 'export AI_BAILIAN_API_KEY=your_api_key' >> ~/.bashrc
source ~/.bashrc
项目提供了 docker-compose.dev.yml,可一键启动 PostgreSQL、Redis、RustFS(S3 兼容存储)三个依赖:
# 启动依赖服务
docker compose -f docker-compose.dev.yml up -d
# 停止依赖服务
docker compose -f docker-compose.dev.yml down
# 停止并清除数据
docker compose -f docker-compose.dev.yml down -v
如果你之前已经启动过旧版本容器,拉取新代码后建议确认端口映射是否真的生效:
docker ps --format '{{.Names}} {{.Ports}}'
正常情况下应看到:
interview-postgres 0.0.0.0:5432->5432/tcp
interview-redis 0.0.0.0:6379->6379/tcp
如果只看到 interview-postgres 5432/tcp 或 interview-redis 6379/tcp,说明容器内部服务是启动的,但端口没有发布到宿主机。此时通过 ./gradlew :app:bootRun 从宿主机启动后端,会出现类似 Connection to localhost:5432 refused 的报错。可以重建容器配置(不会删除 Docker volume 中的数据):
docker compose -f docker-compose.dev.yml up -d --force-recreate postgres redis
启动后默认账号:
| 服务 | 地址 | 账号 | 密码 |
|---|---|---|---|
| PostgreSQL | localhost:5432 | postgres | 123456 |
| Redis | localhost:6379 | - | - |
| RustFS 控制台 | localhost:9001 | rustfsadmin | rustfsadmin |
注意:应用启动时会自动检查并创建
interview-guideBucket。使用docker-compose.dev.yml+:app:bootRun时,请确保.env中的APP_STORAGE_ACCESS_KEY/APP_STORAGE_SECRET_KEY与 RustFS 账号一致,例如都设为rustfsadmin。如果本地已有 MinIO 或其他 S3 兼容存储,也可以直接使用,在.env中修改APP_STORAGE_*配置即可。
IDEA Docker Debug 提示:如果在 macOS 上使用 IntelliJ IDEA 的 Docker 调试方式启动后端,遇到
mounts denied: The path /Applications/IntelliJ IDEA.app/Contents/lib is not shared from the host,请在 Docker Desktop 的Settings -> Resources -> File Sharing中加入/Applications/IntelliJ IDEA.app/Contents/lib(或整个/Applications/IntelliJ IDEA.app)以及当前项目目录,然后重启 Docker/IDEA 后再运行。普通./gradlew :app:bootRun和docker compose启动不需要这个额外共享路径。
后端:
./gradlew :app:bootRun
后端服务启动于 http://localhost:8080
前端:
cd frontend
corepack enable
pnpm install
pnpm dev
前端服务启动于 http://localhost:5173
本项目提供了完整的 Docker 支持,可以一键启动所有服务(前后端、数据库、中间件)。
Docker Compose 编排了 6 个服务:PostgreSQL(pgvector)、Redis、MinIO(S3 兼容存储)、MinIO Bucket 初始化、Spring Boot 后端、React 前端(Nginx)。数据通过 Docker 命名卷持久化,docker-compose down 不会丢失数据。
在项目根目录下执行:
.env.example 中的 PostgreSQL、Redis、MinIO 已与 docker-compose.yml 对齐(数据库用户 postgres / 密码 password,MinIO minioadmin / minioadmin)。复制为 .env 后主要填写 AI_BAILIAN_API_KEY;若你曾在旧版本中使用过不同的库密码或对象存储密钥,请同步修改 .env,必要时重建 Postgres 卷以免旧数据与密码不一致。
# 1. 复制环境变量配置文件
cp .env.example .env
# 2. 编辑 .env 文件,填入 AI 配置
# vim .env
# 必填:AI_BAILIAN_API_KEY=your_key_here
# 必填:APP_AI_CONFIG_ENCRYPTION_KEY=your_random_long_secret
# 可选:AI_MODEL=qwen3.5-flash # 默认值为 qwen3.5-flash
# 也可以在设置页维护 DashScope、Kimi、DeepSeek、GLM、LM Studio 等 Provider
#
# 面试参数配置(可选):
# APP_INTERVIEW_FOLLOW_UP_COUNT=1 # 每个主问题生成追问数量(默认 1)
# APP_INTERVIEW_EVALUATION_BATCH_SIZE=8 # 回答评估分批大小(默认 8)
# 3. 构建并启动所有服务
docker-compose up -d --build
仅启动依赖服务:如果只想本地开发调试(用
./gradlew :app:bootRun启动后端),可以只启动基础设施:docker compose up -d postgres redis minio createbuckets。将.env.example复制为.env并填写AI_BAILIAN_API_KEY即可,默认账号与docker-compose.yml一致;Bucket 会由初始化任务或应用启动检查自动创建。
启动完成后,您可以通过以下地址访问各个服务:
| 服务 | 地址 | 默认账号 | 默认密码 | 说明 |
|---|---|---|---|---|
| 前端应用 | http://localhost | - | - | 用户访问入口 |
| 后端 API | http://localhost:8080 | - | - | RESTful API |
| 接口文档 | http://localhost:8080/swagger-ui.html | - | - | SpringDoc/Swagger UI |
| MinIO 控制台 | http://localhost:9001 | minioadmin | minioadmin | 对象存储管理 |
| MinIO API | localhost:9000 | - | - | S3 兼容接口 |
| PostgreSQL | localhost:5432 | postgres | password | 数据库 (包含 pgvector) |
| Redis | localhost:6379 | - | - | 缓存与消息队列 |
# 查看服务状态
docker-compose ps
# 查看后端日志
docker-compose logs -f app
# 拉取新代码后重新构建部署
docker-compose up -d --build
# 停止并移除所有服务(数据保留在 Docker 卷中)
docker-compose down
# 停止服务并清除数据卷(慎用,会删除数据库和文件)
docker-compose down -v
# 清理无用镜像(构建产生的中间层)
docker image prune -f
| 用户角色 | 使用场景 |
|---|---|
| 求职者 | 上传简历获取分析建议,进行模拟面试练习 |
| HR/招聘人员 | 批量分析简历,评估候选人能力 |
| 培训机构 | 提供面试培训服务,管理知识库资源 |
本地开发首先检查 JPA 的 ddl-auto 配置。ddl-auto 模式对比:
| 模式 | 行为 | 适用场景 | 数据保留 |
|---|---|---|---|
| update | 表不存在自动创建,存在则尝试增量更新 | 早期开发或临时实验,当前项目不推荐 | ✅ 保留 |
| create | 无条件删除并重建所有表 | 仅首次建表时使用 | ❌ 删除 |
| validate | 只验证,不修改 | 当前项目默认推荐,建表和变更交给 Flyway | ✅ 保留 |
| none | 什么都不做 | 生产环境 | ✅ 保留 |
推荐配置(已默认):
jpa:
hibernate:
ddl-auto: validate # 只校验 schema,建表和变更交给 Flyway
⚠️ 注意:避免使用 create 模式,否则每次重启都会删除所有数据!
vector_store 表已由 Flyway 创建,Spring AI 不再自动建表。
spring:
ai:
vectorstore:
pgvector:
initialize-schema: false
建议保持为 false,避免应用启动时绕过 Flyway 修改数据库 schema。
不需要。数据库 schema 已接入 Flyway,后端应用启动时会自动执行 app/src/main/resources/db/migration/ 下的迁移,并记录到 flyway_schema_history。
当前项目通过 V1__init_schema.sql 支持空库初始化,后续版本通过增量迁移演进;Hibernate ddl-auto 只做 validate 校验。测试环境使用 H2,默认关闭 Flyway。
Connection to localhost:5432 refused 怎么办?这通常不是 Flyway 脚本错误,而是后端从宿主机访问不到 PostgreSQL。先确认依赖容器已启动:
docker compose -f docker-compose.dev.yml up -d
docker ps --format '{{.Names}} {{.Ports}}'
interview-postgres 必须显示 0.0.0.0:5432->5432/tcp,interview-redis 必须显示 0.0.0.0:6379->6379/tcp。如果只显示 5432/tcp 或 6379/tcp,说明旧容器没有应用端口映射配置,重建容器即可:
docker compose -f docker-compose.dev.yml up -d --force-recreate postgres redis
如果你的本机 5432 或 6379 已被其他项目占用,可以修改 .env 中的 POSTGRES_PORT / REDIS_PORT,并同步调整 docker-compose.dev.yml 里的端口映射,确保应用配置和容器发布端口一致。
检查一下阿里云 DashScope API KEY 是否配置正确(申请地址:https://bailian.console.aliyun.com/)。
运行时 Provider 配置默认写到 ~/.interview-guide/llm-providers.yml 和 ~/.interview-guide/llm-providers.env。可以在设置页点击测试连接,或调用 /api/llm-provider/reload 重新加载配置。Docker 部署时如果希望配置持久化,建议为该目录挂载卷。
先在浏览器开发者工具的 Network → WS 中检查 /ws/voice-interview/{sessionId} 的连接,正常握手状态为 101。语音连接与 REST API 使用同一服务入口,HTTPS 页面使用 wss://;不要把远程部署的连接地址写成 ws://localhost:8080,这里的 localhost 指的是访问者的电脑。
/ws 代理,与 /api 共用 VITE_API_PROXY_TARGET,默认后端为 http://localhost:8080。修改代理配置后重启前端。frontend/nginx.conf,重新构建前端镜像。自行配置反向代理时,需要转发 /ws/,并保留 Upgrade、Connection 和包含外部端口的 Host 请求头;长连接需配置足够的读取超时。403:检查 CORS_ALLOWED_ORIGINS 是否包含实际前端来源(协议、域名、端口均须匹配),尤其是 HTTPS 反向代理或显式配置 VITE_API_BASE_URL 的跨域部署。不要通过允许所有来源来绕过检查。语音面试的 ASR/TTS 默认也使用 AI_BAILIAN_API_KEY。请检查浏览器麦克风权限、后端日志中的 DashScope WebSocket 连接状态,以及设置页里的 ASR/TTS 测试结果。无耳机时可能触发回声录入,建议先使用手动提交模式或佩戴耳机测试。
检查 Redis 连接和 Stream Consumer 是否正常运行。查看后端日志确认是否有错误。
项目已内置中文字体(珠圆玉润仿宋),支持跨平台导出。如遇到问题,请检查:
app/src/main/resources/fonts/ZhuqueFangsong-Regular.ttf原因简述:后端与 Logback 按 UTF-8 输出日志;中文 Windows 下控制台默认多为 GBK(代码页 936),且 PowerShell 的 $OutputEncoding、控制台编码若未统一为 UTF-8,显示时就会把同一串字节解释错,出现乱码。
本项目已做的配置(一般无需再改):根目录 gradle.properties(Gradle 进程 UTF-8)、app/src/main/resources/logback-spring.xml(控制台日志 UTF-8)、app/build.gradle 中 bootRun 的 JVM 参数(含 file.encoding / stdout.encoding / stderr.encoding)。
仍乱码时(PowerShell 侧):在启动 .\gradlew.bat :app:bootRun 的同一终端先执行下面一段;或写入 PowerShell 配置文件($PROFILE)以便每次自动生效:
chcp 65001 | Out-Null
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
[Console]::InputEncoding = [System.Text.UTF8Encoding]::new($false)
$OutputEncoding = [System.Text.UTF8Encoding]::new($false)
新建或编辑配置文件:if (!(Test-Path $PROFILE)) { New-Item -Path $PROFILE -ItemType File -Force },再 notepad $PROFILE 将上述内容粘贴保存;新开终端后生效,或执行 . $PROFILE 立即加载。若提示脚本无法执行,可执行一次:Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned。
在 PowerShell 中建议使用 .\gradlew.bat :app:bootRun(或仓库根目录的 .\gradlew.bat),避免与执行策略、路径解析相关的问题。
欢迎提交 Issue 和 Pull Request!
AGPL-3.0 License(只要通过网络提供服务,就必须向用户公开修改后的源码)
基于 Spring Boot 4.1、Java 25、Spring AI 2.0、React、PostgreSQL/pgvector、Redis 和 RustFS 构建的开源 AI 面试平台,支持简历智能分析、模拟面试、语音面试和知识库 RAG。
See the codeInterviewGuide 是一个集成了简历分析、模拟面试(文字 + 语音)、面试安排、知识库管理、知识库题库面试和多模型配置的智能面试辅助平台。系统利用大语言模型(LLM)、向量数据库、Redis Stream 异步任务和实时语音技术,为求职者、HR 和培训机构提供智能化的简历评估、面试练习、知识库问答和面试日程管理能力。

本项目承诺完整功能免费开源,也不会做所谓的 Pro 版或“付费解锁核心功能”之类的设计。
如果你想学习这个项目,或者希望把它作为个人项目经历 / 毕设选题,我也整理了一套相对细致的教程:从基础设施搭建、核心业务实现,到最后如何在面试中讲清楚思路与亮点,尽量把容易卡住的地方讲透。
如果你确实需要更系统的辅导,可以点这里了解详情(教程为付费内容,主要是想覆盖一些时间成本,望理解,感谢支持):《SpringAI 智能面试平台+RAG 知识库》。
| 技术 | 版本 | 说明 |
|---|---|---|
| Spring Boot | 4.1.0 | 应用框架 |
| Java | 25 | 开发语言(虚拟线程) |
| Spring AI | 2.0.0 | AI 集成框架、OpenAI 兼容模型接入 |
| Spring AI Agent Utils | 0.10.0 | Skill 资源加载、Advisor 能力扩展 |
| PostgreSQL + pgvector | 14+ | 关系数据库 + 向量存储(Compose 默认 PG16) |
| Redis + Redisson | 6+ / 4.0.0 | 缓存 + 消息队列(Stream) |
| Apache Tika | 2.9.2 | 文档解析 |
| iText 8 | 8.0.5 | PDF 导出 |
| MapStruct | 1.6.3 | 对象映射 |
| SpringDoc OpenAPI | 3.0.2 | API 接口文档 |
| DashScope SDK | 2.22.7 | 语音识别/合成(Qwen3 ASR/TTS) |
| AWS S3 SDK | 2.29.51 | S3 兼容对象存储(MinIO/RustFS) |
| WebSocket | - | 语音面试实时双向通信 |
| Gradle | 9.6.1 | 构建工具 |
技术选型常见问题解答:
ConcurrentHashMap 实现面试会话的缓存。| 技术 | 版本 | 说明 |
|---|---|---|
| React | 18.3 | UI 框架 |
| TypeScript | 5.6 | 开发语言 |
| Vite | 5.4 | 构建工具 |
| Tailwind CSS | 4.1 | 样式框架 |
| React Router | 7.11 | 路由管理 |
| Framer Motion | 12.23 | 动画库 |
| Recharts | 3.6 | 图表库 |
| Lucide React | 0.468 | 图标库 |
| React Big Calendar | 1.19 | 面试日历组件 |
| React Virtuoso | 4.18 | RAG 聊天虚拟列表 |
| pnpm | 10.26 | 前端包管理器 |
SKILL.md 定义考察范围、难度分布和参考知识库。实时语音对话面试,WebSocket + 千问3 语音模型(ASR/TTS/LLM 统一 API Key):
已知问题:端到端延迟偏高(服务端音频中转)、无耳机时回声泄漏、TTS 音色单一、弱网音频断续。后续计划探索 WebRTC、客户端 VAD 降噪、端到端语音模型等方案。
~/.interview-guide/,支持 API Key 加密配置。面试中心:

Skill 出题 + JD 解析:

简历库:

简历上传分析:

简历分析详情:

面试记录:

面试详情:

模拟面试:

面试安排

多模型切换 + 语音服务设置:

知识库管理:

问答助手:

interview-guide/
├── app/ # 后端应用
│ ├── src/main/java/interview/guide/
│ │ ├── App.java # 主启动类
│ │ ├── common/ # 通用基础能力
│ │ │ ├── ai/ # LLM Provider、结构化输出、Prompt 安全
│ │ │ ├── annotation/ # @RateLimit 可重复限流注解
│ │ │ ├── aspect/ # RateLimitAspect + Redis Lua 限流
│ │ │ ├── async/ # Redis Stream 生产者/消费者模板
│ │ │ ├── config/ # CORS、S3、OpenAPI、Jackson 等配置
│ │ │ ├── evaluation/ # 文字/语音共用的统一评估引擎
│ │ │ ├── exception/ # 业务异常与全局异常处理
│ │ │ └── result/ # 统一响应 Result<T>
│ │ ├── infrastructure/ # 基础设施
│ │ │ ├── export/ # PDF 导出
│ │ │ ├── file/ # 文件解析、校验、清洗、S3 存储
│ │ │ ├── mapper/ # MapStruct 映射器
│ │ │ └── redis/ # RedisService、面试会话缓存
│ │ └── modules/ # 业务模块
│ │ ├── interview/ # 模拟面试模块
│ │ ├── interviewschedule/ # 面试安排模块
│ │ ├── knowledgebase/ # 知识库模块
│ │ ├── llmprovider/ # 多模型 Provider 与语音配置
│ │ ├── resume/ # 简历模块
│ │ └── voiceinterview/ # 语音面试模块
│ └── src/main/resources/
│ ├── application.yml # 应用配置
│ ├── prompts/ # AI 提示词模板(StringTemplate)
│ ├── scripts/ # Redis Lua 脚本
│ ├── skills/ # 面试 Skill 定义和参考题库
│ └── voice-interview-opening.yml # 语音面试开场白配置
│
├── frontend/ # 前端应用
│ ├── src/
│ │ ├── api/ # API 接口
│ │ ├── components/ # 公共组件
│ │ ├── hooks/ # 业务 Hooks
│ │ ├── pages/ # 页面组件
│ │ ├── types/ # 类型定义
│ │ └── utils/ # 工具函数
│ ├── package.json
│ └── vite.config.ts
│
├── docker-compose.yml # 完整部署:前端 + 后端 + PostgreSQL + Redis + MinIO
├── docker-compose.dev.yml # 本地开发依赖:PostgreSQL + Redis + RustFS
├── docs/ # 架构设计与改造记录
├── .env.example # 环境变量示例
└── README.md
环境要求:
| 依赖 | 版本 | 必需 | 说明 |
|---|---|---|---|
| JDK | 25 | 是 | 开发语言 |
| Node.js | 18+ | 是 | 前端构建 |
| pnpm | 10+ | 推荐 | 前端包管理器(项目 packageManager 指定 10.26) |
| Docker | - | 推荐 | 一键启动依赖服务(PostgreSQL/Redis/RustFS) |
如果不用 Docker,需要自行安装 PostgreSQL 14+(含 pgvector 扩展)、Redis 6+ 和 S3 兼容存储。
git clone https://github.com/Snailclimb/interview-guide.git
cd interview-guide
推荐复制 .env.example 为 .env,后端 bootRun 会自动读取根目录 .env。最少需要填写 AI_BAILIAN_API_KEY,用于 DashScope 文本模型、ASR 和 TTS:
cp .env.example .env
# 编辑 .env
# AI_BAILIAN_API_KEY=your_dashscope_api_key
# AI_MODEL=qwen3.5-flash
如果你更习惯通过 shell 环境变量注入,也可以这样设置:
# macOS / Linux(zsh)
echo 'export AI_BAILIAN_API_KEY=your_api_key' >> ~/.zshrc
source ~/.zshrc
# Linux(bash)
echo 'export AI_BAILIAN_API_KEY=your_api_key' >> ~/.bashrc
source ~/.bashrc
项目提供了 docker-compose.dev.yml,可一键启动 PostgreSQL、Redis、RustFS(S3 兼容存储)三个依赖:
# 启动依赖服务
docker compose -f docker-compose.dev.yml up -d
# 停止依赖服务
docker compose -f docker-compose.dev.yml down
# 停止并清除数据
docker compose -f docker-compose.dev.yml down -v
如果你之前已经启动过旧版本容器,拉取新代码后建议确认端口映射是否真的生效:
docker ps --format '{{.Names}} {{.Ports}}'
正常情况下应看到:
interview-postgres 0.0.0.0:5432->5432/tcp
interview-redis 0.0.0.0:6379->6379/tcp
如果只看到 interview-postgres 5432/tcp 或 interview-redis 6379/tcp,说明容器内部服务是启动的,但端口没有发布到宿主机。此时通过 ./gradlew :app:bootRun 从宿主机启动后端,会出现类似 Connection to localhost:5432 refused 的报错。可以重建容器配置(不会删除 Docker volume 中的数据):
docker compose -f docker-compose.dev.yml up -d --force-recreate postgres redis
启动后默认账号:
| 服务 | 地址 | 账号 | 密码 |
|---|---|---|---|
| PostgreSQL | localhost:5432 | postgres | 123456 |
| Redis | localhost:6379 | - | - |
| RustFS 控制台 | localhost:9001 | rustfsadmin | rustfsadmin |
注意:应用启动时会自动检查并创建
interview-guideBucket。使用docker-compose.dev.yml+:app:bootRun时,请确保.env中的APP_STORAGE_ACCESS_KEY/APP_STORAGE_SECRET_KEY与 RustFS 账号一致,例如都设为rustfsadmin。如果本地已有 MinIO 或其他 S3 兼容存储,也可以直接使用,在.env中修改APP_STORAGE_*配置即可。
IDEA Docker Debug 提示:如果在 macOS 上使用 IntelliJ IDEA 的 Docker 调试方式启动后端,遇到
mounts denied: The path /Applications/IntelliJ IDEA.app/Contents/lib is not shared from the host,请在 Docker Desktop 的Settings -> Resources -> File Sharing中加入/Applications/IntelliJ IDEA.app/Contents/lib(或整个/Applications/IntelliJ IDEA.app)以及当前项目目录,然后重启 Docker/IDEA 后再运行。普通./gradlew :app:bootRun和docker compose启动不需要这个额外共享路径。
后端:
./gradlew :app:bootRun
后端服务启动于 http://localhost:8080
前端:
cd frontend
corepack enable
pnpm install
pnpm dev
前端服务启动于 http://localhost:5173
本项目提供了完整的 Docker 支持,可以一键启动所有服务(前后端、数据库、中间件)。
Docker Compose 编排了 6 个服务:PostgreSQL(pgvector)、Redis、MinIO(S3 兼容存储)、MinIO Bucket 初始化、Spring Boot 后端、React 前端(Nginx)。数据通过 Docker 命名卷持久化,docker-compose down 不会丢失数据。
在项目根目录下执行:
.env.example 中的 PostgreSQL、Redis、MinIO 已与 docker-compose.yml 对齐(数据库用户 postgres / 密码 password,MinIO minioadmin / minioadmin)。复制为 .env 后主要填写 AI_BAILIAN_API_KEY;若你曾在旧版本中使用过不同的库密码或对象存储密钥,请同步修改 .env,必要时重建 Postgres 卷以免旧数据与密码不一致。
# 1. 复制环境变量配置文件
cp .env.example .env
# 2. 编辑 .env 文件,填入 AI 配置
# vim .env
# 必填:AI_BAILIAN_API_KEY=your_key_here
# 必填:APP_AI_CONFIG_ENCRYPTION_KEY=your_random_long_secret
# 可选:AI_MODEL=qwen3.5-flash # 默认值为 qwen3.5-flash
# 也可以在设置页维护 DashScope、Kimi、DeepSeek、GLM、LM Studio 等 Provider
#
# 面试参数配置(可选):
# APP_INTERVIEW_FOLLOW_UP_COUNT=1 # 每个主问题生成追问数量(默认 1)
# APP_INTERVIEW_EVALUATION_BATCH_SIZE=8 # 回答评估分批大小(默认 8)
# 3. 构建并启动所有服务
docker-compose up -d --build
仅启动依赖服务:如果只想本地开发调试(用
./gradlew :app:bootRun启动后端),可以只启动基础设施:docker compose up -d postgres redis minio createbuckets。将.env.example复制为.env并填写AI_BAILIAN_API_KEY即可,默认账号与docker-compose.yml一致;Bucket 会由初始化任务或应用启动检查自动创建。
启动完成后,您可以通过以下地址访问各个服务:
| 服务 | 地址 | 默认账号 | 默认密码 | 说明 |
|---|---|---|---|---|
| 前端应用 | http://localhost | - | - | 用户访问入口 |
| 后端 API | http://localhost:8080 | - | - | RESTful API |
| 接口文档 | http://localhost:8080/swagger-ui.html | - | - | SpringDoc/Swagger UI |
| MinIO 控制台 | http://localhost:9001 | minioadmin | minioadmin | 对象存储管理 |
| MinIO API | localhost:9000 | - | - | S3 兼容接口 |
| PostgreSQL | localhost:5432 | postgres | password | 数据库 (包含 pgvector) |
| Redis | localhost:6379 | - | - | 缓存与消息队列 |
# 查看服务状态
docker-compose ps
# 查看后端日志
docker-compose logs -f app
# 拉取新代码后重新构建部署
docker-compose up -d --build
# 停止并移除所有服务(数据保留在 Docker 卷中)
docker-compose down
# 停止服务并清除数据卷(慎用,会删除数据库和文件)
docker-compose down -v
# 清理无用镜像(构建产生的中间层)
docker image prune -f
| 用户角色 | 使用场景 |
|---|---|
| 求职者 | 上传简历获取分析建议,进行模拟面试练习 |
| HR/招聘人员 | 批量分析简历,评估候选人能力 |
| 培训机构 | 提供面试培训服务,管理知识库资源 |
本地开发首先检查 JPA 的 ddl-auto 配置。ddl-auto 模式对比:
| 模式 | 行为 | 适用场景 | 数据保留 |
|---|---|---|---|
| update | 表不存在自动创建,存在则尝试增量更新 | 早期开发或临时实验,当前项目不推荐 | ✅ 保留 |
| create | 无条件删除并重建所有表 | 仅首次建表时使用 | ❌ 删除 |
| validate | 只验证,不修改 | 当前项目默认推荐,建表和变更交给 Flyway | ✅ 保留 |
| none | 什么都不做 | 生产环境 | ✅ 保留 |
推荐配置(已默认):
jpa:
hibernate:
ddl-auto: validate # 只校验 schema,建表和变更交给 Flyway
⚠️ 注意:避免使用 create 模式,否则每次重启都会删除所有数据!
vector_store 表已由 Flyway 创建,Spring AI 不再自动建表。
spring:
ai:
vectorstore:
pgvector:
initialize-schema: false
建议保持为 false,避免应用启动时绕过 Flyway 修改数据库 schema。
不需要。数据库 schema 已接入 Flyway,后端应用启动时会自动执行 app/src/main/resources/db/migration/ 下的迁移,并记录到 flyway_schema_history。
当前项目通过 V1__init_schema.sql 支持空库初始化,后续版本通过增量迁移演进;Hibernate ddl-auto 只做 validate 校验。测试环境使用 H2,默认关闭 Flyway。
Connection to localhost:5432 refused 怎么办?这通常不是 Flyway 脚本错误,而是后端从宿主机访问不到 PostgreSQL。先确认依赖容器已启动:
docker compose -f docker-compose.dev.yml up -d
docker ps --format '{{.Names}} {{.Ports}}'
interview-postgres 必须显示 0.0.0.0:5432->5432/tcp,interview-redis 必须显示 0.0.0.0:6379->6379/tcp。如果只显示 5432/tcp 或 6379/tcp,说明旧容器没有应用端口映射配置,重建容器即可:
docker compose -f docker-compose.dev.yml up -d --force-recreate postgres redis
如果你的本机 5432 或 6379 已被其他项目占用,可以修改 .env 中的 POSTGRES_PORT / REDIS_PORT,并同步调整 docker-compose.dev.yml 里的端口映射,确保应用配置和容器发布端口一致。
检查一下阿里云 DashScope API KEY 是否配置正确(申请地址:https://bailian.console.aliyun.com/)。
运行时 Provider 配置默认写到 ~/.interview-guide/llm-providers.yml 和 ~/.interview-guide/llm-providers.env。可以在设置页点击测试连接,或调用 /api/llm-provider/reload 重新加载配置。Docker 部署时如果希望配置持久化,建议为该目录挂载卷。
先在浏览器开发者工具的 Network → WS 中检查 /ws/voice-interview/{sessionId} 的连接,正常握手状态为 101。语音连接与 REST API 使用同一服务入口,HTTPS 页面使用 wss://;不要把远程部署的连接地址写成 ws://localhost:8080,这里的 localhost 指的是访问者的电脑。
/ws 代理,与 /api 共用 VITE_API_PROXY_TARGET,默认后端为 http://localhost:8080。修改代理配置后重启前端。frontend/nginx.conf,重新构建前端镜像。自行配置反向代理时,需要转发 /ws/,并保留 Upgrade、Connection 和包含外部端口的 Host 请求头;长连接需配置足够的读取超时。403:检查 CORS_ALLOWED_ORIGINS 是否包含实际前端来源(协议、域名、端口均须匹配),尤其是 HTTPS 反向代理或显式配置 VITE_API_BASE_URL 的跨域部署。不要通过允许所有来源来绕过检查。语音面试的 ASR/TTS 默认也使用 AI_BAILIAN_API_KEY。请检查浏览器麦克风权限、后端日志中的 DashScope WebSocket 连接状态,以及设置页里的 ASR/TTS 测试结果。无耳机时可能触发回声录入,建议先使用手动提交模式或佩戴耳机测试。
检查 Redis 连接和 Stream Consumer 是否正常运行。查看后端日志确认是否有错误。
项目已内置中文字体(珠圆玉润仿宋),支持跨平台导出。如遇到问题,请检查:
app/src/main/resources/fonts/ZhuqueFangsong-Regular.ttf原因简述:后端与 Logback 按 UTF-8 输出日志;中文 Windows 下控制台默认多为 GBK(代码页 936),且 PowerShell 的 $OutputEncoding、控制台编码若未统一为 UTF-8,显示时就会把同一串字节解释错,出现乱码。
本项目已做的配置(一般无需再改):根目录 gradle.properties(Gradle 进程 UTF-8)、app/src/main/resources/logback-spring.xml(控制台日志 UTF-8)、app/build.gradle 中 bootRun 的 JVM 参数(含 file.encoding / stdout.encoding / stderr.encoding)。
仍乱码时(PowerShell 侧):在启动 .\gradlew.bat :app:bootRun 的同一终端先执行下面一段;或写入 PowerShell 配置文件($PROFILE)以便每次自动生效:
chcp 65001 | Out-Null
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
[Console]::InputEncoding = [System.Text.UTF8Encoding]::new($false)
$OutputEncoding = [System.Text.UTF8Encoding]::new($false)
新建或编辑配置文件:if (!(Test-Path $PROFILE)) { New-Item -Path $PROFILE -ItemType File -Force },再 notepad $PROFILE 将上述内容粘贴保存;新开终端后生效,或执行 . $PROFILE 立即加载。若提示脚本无法执行,可执行一次:Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned。
在 PowerShell 中建议使用 .\gradlew.bat :app:bootRun(或仓库根目录的 .\gradlew.bat),避免与执行策略、路径解析相关的问题。
欢迎提交 Issue 和 Pull Request!
AGPL-3.0 License(只要通过网络提供服务,就必须向用户公开修改后的源码)