# virtual_interview **Repository Path**: zhang_-on/virtual_interview ## Basic Information - **Project Name**: virtual_interview - **Description**: 一个面向求职者的智能化虚拟面试平台后端:基于 Spring Boot +Spring AI + MySQL + Redis + WebSocket,集成科大讯飞大模型(对话/面试官)、RAG 知识库增强、ASR 实时转写与 TTS 语音合成,并提供面试过程分析报告、面经社区与简历管理,助力高效模拟与提升面试能力。 - **Primary Language**: Java - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 11 - **Forks**: 1 - **Created**: 2025-06-21 - **Last Updated**: 2025-11-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: Java, AI, 面试平台, SpringAI, RAG ## README # 虚拟面试平台(Virtual Interview Backend) 一个面向求职者的智能化虚拟面试与学习平台后端,提供面试对话、语音识别与合成、AI 评估分析、知识库检索、内容社区等能力,帮助用户模拟真实面试、获得结构化反馈与学习资源。 ## 基本信息 ### 功能亮点 - **账号与安全**:注册登录、JWT 鉴权、权限拦截、跨域与全局异常处理。 - **面试对话**:基于科大讯飞大模型的聊天与面试专家(`InterviewExpert`、`ChatExpert`),支持会话记忆与上下文管理(MySQL 持久化)。 - **语音能力**: - ASR 实时语音转写(Iflytek RTASR),WebSocket 流式处理,日志落盘到 `asr_audio_logs/`。 - TTS 语音合成(Iflytek TTS),支持选择发音人,音频输出至 `tts_audio_logs/`。 - **视频与表情分析(可选)**:`flask-realtime-face-eye/` 子模块提供人脸与眼动/表情检测的实时分析服务,便于评估面试表现(姿态、表情、注视等)。 - **AI 评估与报告**:半分钟阶段性报告、回合分析、综合分析报告与学习资源推荐,支持图表与结构化指标输出。 - **知识库检索(RAG)**:集成 Spring AI 与讯飞知识库,支持向量检索、增强生成,提升答案的专业性与可解释性。 - **内容社区**:面经/帖子、评论、点赞收藏、排行榜、学习计划与资源管理。 - **文件上传与对象存储**:阿里云 OSS 集成,简化简历等文件的上传管理。 - **可观测性**:Actuator 端点、统一日志、全局异常返回结构。 ### 技术栈 - **语言与运行环境**:Java 21、Maven、Spring Boot 3.4.x - **Web 框架**:Spring Web MVC、Spring WebFlux(部分接口流式/响应式) - **数据访问**:MyBatis-Plus、MyBatis、MySQL - **缓存与消息**:Redis(Spring Cache)、Lettuce 连接池 - **安全**:JWT(jjwt)、拦截器鉴权、AOP 日志 - **文档与调试**:Springdoc OpenAPI(`/swagger-ui.html`、`/api-docs`) - **AI 能力**:Spring AI、Iflytek 大模型(Chat/Knowledge)、RAG(向量检索、Advisors) - **实时通信**:Spring WebSocket、Java-WebSocket(客户端场景) - **对象存储**:阿里云 OSS SDK - **工具**:Hutool、Jackson、Fastjson、Apache POI、OkHttp、Lombok - **可观测**:Spring Boot Actuator ### AI 能力详解 - **对话与面试专家(LLM)**:基于科大讯飞 Spark(`pro-128k`),通过 Spring AI 封装的 `XunFeiChatModel`、`XunFeiConfig`、`XunFeiProperties` 与提示词集 `InterviewPrompts`,实现通用聊天(`ChatExpert`)与面试官角色(`InterviewExpert`)。支持流式输出(WebFlux/SSE 或 WebSocket)。 - **会话记忆(Chat Memory)**:`MysqlChatMemory`、`MysqlInterviewMemory` 将多轮消息持久化至 MySQL,结合用户上下文与历史对话提升连续性与一致性。 - **RAG 知识增强**:集成讯飞知识库与 Spring AI 向量检索(`spring-ai-advisors-vector-store`、`spring-ai-markdown-document-reader`),通过 `XfyunSparkKnowledgeClient`、`XfyunSparkKnowledgeRetriever`、`XfyunKnowledgeHelper` 等组件,在生成前进行检索与上下文增强,知识库名配置为 `interview`。 - **ASR 实时转写**:`utils/rtasr/IflytekAsrClient` 进行 WebSocket 流式语音转写(RTASR),请求/响应使用 `model/dto/interview/audio/*`,落盘日志在 `asr_audio_logs/`,便于追踪与复现。 - **TTS 语音合成**:`utils/tst/TtsService` 基于 Iflytek TTS 输出音频,参数由 `TtsRequest` 控制(发音人 `vcn` 等),产物写入 `tts_audio_logs/`,可用于语音播报与面试官语音化。 - **表情/姿态分析**:`utils/face/IflytekExpressionService`、`model/dto/interview/process/*`(如 `HeadPose`、`IflytekExpressionResponse`)结合 `flask-realtime-face-eye/` 子服务,支持面试过程中的表情、注视点与头部姿态评估。 - **流式通信与控制**:`WebSocketConfig`、`InterviewWsController` 提供面试过程中的实时通道,便于推送问题、接收答案、同步评估指标与控制面板。 - **评估与报告**:阶段性/回合性分析(`HalfMinuteReport`、`TurnAnalysisResponse`)与综合报告(`AnalysisReportDTO`),用于面试结束后的拆解与学习建议生成。 ### 目录结构(关键部分) ``` virtual_interview/ ├─ src/main/java/com/echo/virtual_interview/ │ ├─ controller/ # 账户、面试、聊天、简历、内容社区等接口 │ ├─ service/ # 业务逻辑与集成实现(ASR/TTS/分析/RAG/OSS) │ ├─ model/ # DTO/VO/Entity/枚举 │ ├─ mapper/ # MyBatis-Plus Mapper 接口 │ ├─ config/ # 全局配置、拦截器、CORS、WebSocket、线程池等 │ ├─ aop/ # 日志与鉴权切面/拦截器 │ └─ utils/ # JWT、ASR/TTS、表情分析等工具 ├─ src/main/resources/ │ ├─ application.yml # 全局配置(使用 prod/dev 外部化变量) │ └─ mapper/ # MyBatis XML 映射 ├─ flask-realtime-face-eye/ # 可选的表情/人脸/注视实时分析子服务(Flask) ├─ asr_audio_logs/ # 语音转写日志 ├─ tts_audio_logs/ # 语音合成音频日志 └─ logs/ # 应用运行日志 ``` ### 配置说明 - 在 `src/main/resources/application.yml` 中,应用名为 `virtual_interview`,默认 `spring.profiles.active=prod`。 - 数据源、Redis、OSS 与 Iflytek 等敏感配置通过占位符 `${echo.*}` 注入,请在实际运行环境中通过 `application-prod.yml` 或系统环境变量提供: - `echo.datasource.*`(host、port、database、username、password、driver-class-name) - `echo.redis.*`(host、port、database、password) - `echo.oss.*`(endpoint、access-key-id、access-key-secret、bucket-name) - `xunfei.*`(api/rtasr/tts/knowledge/face-score 等) - JWT:`jwt.secret`、`jwt.expiration` 可按需调整。 - Swagger:`/swagger-ui.html`,接口包扫描 `com.echo.virtual_interview.controller`。 ## 完整业务流程 ```plain 用户创建面试会话 ↓ 选择公司、职位、上传简历 ↓ ┌─────────────────────────────────────┐ │ 面试阶段(实时语音交互) │ │ - WebSocket双向通信 │ │ - 语音转文字(ASR/AST) │ │ - AI生成问题(InterviewExpert) │ │ - 文字转语音(TTS流式合成) │ │ - 视频流实时分析(表情、眼神) │ │ - 每轮对话异步分析(评分、建议) │ │ - 意图分析助手判断阶段转换 │ └─────────────────────────────────────┘ ↓ 面试结束 ↓ ┌─────────────────────────────────────┐ │ 异步生成综合分析报告 │ │ - 收集所有对话记录 │ │ - 提取紧张度曲线、口头禅、眼神交流 │ │ - AI生成综合分析 │ │ - 生成雷达图、折线图等可视化数据 │ │ - 智能推荐学习资源 │ └─────────────────────────────────────┘ ↓ 查看分析报告 ↓ ┌─────────────────────────────────────┐ │ 面经社区功能 │ │ - 一键创建面经(基于面试报告) │ │ - 分享面试经验 │ │ - 点赞、评论互动 │ │ - 查看他人面经 │ └─────────────────────────────────────┘ ↓ 查看综合报告 ↓ ┌─────────────────────────────────────┐ │ AI对话助手 │ │ - 基于面试报告进行个性化对话 │ │ - 解答学习疑问 │ │ - 提供改进建议 │ │ - 职业规划咨询 │ └─────────────────────────────────────┘ ``` ## 🎯 核心亮点 ### 1. 双智能体协同设计 #### 1.1 智能体架构 系统采用**双智能体架构**,两个AI智能体各司其职,协同工作: ```plain ┌─────────────────────────────────────────────────────────┐ │ 用户输入/回答 │ └────────────────────┬────────────────────────────────────┘ │ ┌───────────┴───────────┐ │ │ ▼ ▼ ┌─────────────────┐ ┌──────────────────────┐ │ InterviewExpert │ │ InterviewAnalysisExpert│ │ (面试官角色) │ │ (意图分析助手) │ │ │ │ │ │ - 生成面试问题 │ │ - 分析对话完成度 │ │ - 使用RAG检索 │ │ - 判断阶段转换 │ │ - 阶段感知提问 │ │ - 单轮评分分析 │ └────────┬────────┘ └──────────┬───────────┘ │ │ │ │ ▼ ▼ ┌─────────────────────────────────────────────┐ │ 异步并行处理 │ │ - 内容分析(评分、建议、分析) │ │ - 状态决策(是否切换阶段) │ └─────────────────────────────────────────────┘ ``` #### 1.2 面试官智能体(InterviewExpert) **职责**:扮演面试官角色,根据当前阶段和上下文生成专业的面试问题 **核心功能**: + **阶段感知提问**:根据5个面试阶段(项目深挖→技能考察→行为问题→候选人提问→总结)动态调整提问策略 + **RAG增强检索**:在技能考察阶段,主动从多知识库检索相关面试题,基于题库生成问题 + **上下文记忆**:使用MySQL记忆存储,可回顾60轮历史对话,保证问题连贯性 + **语音识别容错**:智能识别和处理语音转写错误(如"63框架"→Vue.js) **关键技术点**: ```java // 技能考察阶段主动触发RAG检索 if (shouldTriggerProactiveRagRetrieval(context)) { // 提取技术标签 List techTags = extractTechTagsFromContext(context); // 构建检索查询 enhancedUserMessage = buildRagRetrievalQuery(context); // 设置ThreadLocal上下文供检索器使用 RagContext.setTags(techTags); } ``` #### 1.3 意图分析智能体(InterviewAnalysisExpert) **职责**:分析对话完成度,智能决策是否切换面试阶段 **核心功能**: + **对话深度分析**:评估候选人回答的技术深度、逻辑性、相关性 + **阶段转换决策**:基于AI分析+规则兜底的双层决策机制 + **单轮评分分析**:对每轮对话进行结构化评分(1-100分)、建议和分析 **决策流程**: ```plain 1. 分析当前阶段对话历史 ↓ 2. AI判断(三种状态): - CONTINUE_CURRENT_TOPIC(继续深挖) - COMPLETED_MOVE_ON(充分,转换阶段) - INVALID_ANSWER_REPEAT_QUESTION(回答无效,重复问题) ↓ 3. 结合规则兜底: - AI明确建议转换 → 立即转换 - 达到最大轮数上限 → 强制转换(防止无限循环) ↓ 4. 更新会话阶段 ``` **亮点**: + **双层决策机制**:AI决策优先,轮数上限作为兜底,保证系统健壮性 + **配置化轮数限制**:各阶段最大轮数可配置(如项目深挖8轮、技能考察6轮) + **异常容错**:AI分析失败时,自动降级到轮数计数法 #### 1.4 交互流程示例 ```plain 【第1轮对话】 用户:我负责XX项目的后端开发... InterviewExpert:你在项目中是如何设计缓存策略的? ↓ 【异步并行处理】 ├─ InterviewAnalysisExpert:分析本轮回答 → 评分75分,建议"可以更详细说明缓存淘汰策略" └─ InterviewAnalysisExpert:判断阶段完成度 → CONTINUE(继续深挖项目) ↓ 【第2轮对话】 用户:我们使用了Redis,采用LRU淘汰策略... InterviewExpert:那在高并发场景下,如何避免缓存穿透? ↓ 【异步并行处理】 ├─ InterviewAnalysisExpert:分析本轮回答 → 评分85分 └─ InterviewAnalysisExpert:判断阶段完成度 → COMPLETED(已充分,切换到技能考察) ↓ 【阶段切换】 系统:更新会话阶段 PROJECT_DEEP_DIVE → SKILL_PROBING InterviewExpert:触发RAG检索,从知识库检索Java、Spring相关面试题 ``` --- ### 2. 实时语音处理架构(TTS + RTASR) #### 2.1 技术架构 系统实现了**语音→文本→AI回复→语音**的完整闭环,采用响应式编程模型: ```plain ┌─────────────────────────────────────────────────────────────┐ │ 前端WebSocket发送音频流 │ └────────────────────┬────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ AsrProcessingService │ │ - 接收音频片段(Base64编码) │ │ - 存入阻塞队列(LinkedBlockingQueue) │ │ - 定时任务池发送到讯飞服务器 │ └────────────────────┬────────────────────────────────────────┘ │ ┌───────────┴───────────┐ │ │ ▼ ▼ ┌─────────────────┐ ┌──────────────────────┐ │ RTASR识别 │ │ AST识别(流式) │ │ (实时转写) │ │ (分段识别) │ └────────┬────────┘ └──────────┬───────────┘ │ │ ▼ ▼ ┌─────────────────────────────────────────────┐ │ 实时推送转录文本到前端 │ └────────────────────┬────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────┐ │ 用户结束说话 → 获取完整识别文本 │ └────────────────────┬────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────┐ │ InterviewService.interviewProcess() │ │ - 获取AI流式文本回复 │ │ - 实时推送AI文本到前端 │ └────────────────────┬────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────┐ │ 响应式TTS合成链 │ │ 1. 收集完整AI回复 │ │ 2. 按标点分句 │ │ 3. 响应式合成每句 │ │ 4. 顺序推送音频流 │ └─────────────────────────────────────────────┘ ``` #### 2.2 核心亮点 ##### 2.2.1 线程池优化 **问题**:大量并发会话需要管理音频发送任务,传统方式会创建大量线程 **解决方案**: ```java // 动态线程池:根据CPU核心数自适应 int corePoolSize = Math.max(4, Runtime.getRuntime().availableProcessors()); this.sendingScheduler = Executors.newScheduledThreadPool(corePoolSize); ``` **优势**: + **资源利用率高**:根据服务器CPU核心数动态调整,充分利用硬件资源 + **统一管理**:所有音频发送任务由调度线程池统一管理,避免线程泛滥 + **优雅关闭**:服务关闭时统一清理,防止资源泄漏 **应用场景**: + 定时从阻塞队列取音频片段发送到讯飞服务器 + 每个会话一个定时任务(每100ms检查一次队列) + 支持高并发:可同时处理数百个会话 ##### 2.2.2 响应式编程(Reactor) **问题**:TTS合成是异步回调模式,需要整合到流式处理链中 **解决方案**:使用Reactor将回调式API封装为响应式流 ```java private Flux reactiveSynthesizeSentence(String sentence) { return Flux.create(sink -> { // 将回调转换为响应式流 ttsService.synthesize( sentence, audioBase64 -> sink.next(new AudioResponseDto(audioBase64, false)), () -> sink.complete(), errorMsg -> sink.error(new RuntimeException(errorMsg)) ); }) .retryWhen(Retry.max(2) // 连接失败自动重试2次 .filter(throwable -> throwable instanceof ConnectException)) .doOnError(error -> log.error("TTS合成失败: {}", sentence, error)); } ``` **优势**: + **背压控制**:自动处理生产消费速度不匹配 + **错误处理**:统一的重试和错误处理机制 + **流式处理**:句子顺序合成,避免语音重叠 ##### 2.2.3 实时转写优化 **AST(Audio Stream Transcription)模式**: 系统支持AST流式识别,可以实时返回部分识别结果: ```java // AST分段识别处理 Consumer onMessageCallback = (text, segId) -> { // 处理累积更新逻辑 if (text.contains(existingText)) { // 累积更新:新文本包含旧文本 → 替换 segmentMap.put(segId, text); } else if (existingText.contains(text)) { // 标点修正:旧文本包含新文本 → 忽略 } else { // 新内容:追加到finalResult,实时推送前端 finalResult.append(existingText); messagingTemplate.convertAndSendToUser(userId, DEST_USER_TRANSCRIPT, ...); } }; ``` **亮点**: + **实时反馈**:用户说话过程中即可看到转写结果,提升体验 + **智能去重**:处理AST的累积更新和标点修正,避免重复显示 + **分段管理**:使用seg_id管理多个识别段,支持多说话人场景 ##### 2.2.4 并发控制 **问题**:同一会话可能并发收到多个音频片段,需要防止重复创建客户端 **解决方案**:使用`ConcurrentHashMap`和`AtomicBoolean`实现细粒度锁 ```java // 防止并发创建客户端的锁 private final Set creatingSessions = ConcurrentHashMap.newKeySet(); if (creatingSessions.add(sessionId)) { try { // 双重检查 client = activeClients.get(sessionId); if (client == null) { client = createAndConnectClient(sessionId, userId); activeClients.put(sessionId, client); } } finally { creatingSessions.remove(sessionId); } } ``` **优势**: + **无锁设计**:使用CAS操作,性能优于synchronized + **细粒度控制**:只锁定正在创建的会话,不影响其他会话 + **防止死锁**:finally块确保锁一定会释放 --- ### 3. RAG(检索增强生成)系统 #### 3.1 多知识库架构 系统实现了**多知识库智能检索**,支持基于标签的精准匹配: ```plain ┌─────────────────────────────────────────────────────────┐ │ InterviewExpert │ │ - 提取技术标签(Java, Spring, MySQL...) │ │ - 设置RagContext(ThreadLocal) │ └────────────────────┬────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────┐ │ RagCloudAdvisor (Spring AI) │ │ - 拦截用户查询 │ │ - 调用DocumentRetriever │ └────────────────────┬────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────┐ │ MultiKnowledgeBaseRetriever │ │ 1. 从RagContext提取标签 │ │ 2. 根据标签匹配知识库 │ │ 3. 并行检索多个知识库 │ │ 4. 合并去重排序 │ └────────────────────┬────────────────────────────────────┘ │ ┌───────────┴───────────┐ │ │ ▼ ▼ ┌─────────────────┐ ┌──────────────────────┐ │ Java后端知识库 │ │ 前端知识库 │ │ (标签:Java...) │ │ (标签:Vue...) │ └─────────────────┘ └──────────────────────┘ ``` #### 3.2 核心亮点 ##### 3.2.1 智能标签匹配 **标签提取**: + 从岗位要求中提取技术标签 + 从简历技能中提取技术标签 + 使用关键词匹配算法(可扩展为NLP提取) **知识库匹配**: ```java private List selectKnowledgeBases(List tags) { // 1. 根据标签匹配知识库(只使用内存缓存,零数据库查询) List matchedBases = knowledgeBaseConfig.findBasesByTags(tags); // 2. 如果未匹配到,使用所有知识库(兜底策略) if (matchedBases.isEmpty()) { // 包括动态发现的知识库 return getAllCachedKnowledgeBases(); } return matchedBases; } ``` ##### 3.2.2 高性能缓存机制 **启动时自动加载**: ```java @PostConstruct public void initialize() { // 1. 加载配置文件中的知识库 loadConfiguredBases(); // 2. 自动从数据库发现新知识库(无需修改配置) discoverAndAddKnowledgeBasesFromDatabase(); // 3. 为每个知识库缓存文件ID列表 retrieverCache.forEach((name, retriever) -> { retriever.initialize(); // 缓存文件ID }); } ``` **检索时零数据库查询**: + 所有知识库配置和文件ID都在内存缓存中 + 检索时完全使用缓存,不查询数据库 + 性能提升:从数百毫秒降低到几十毫秒 ##### 3.2.3 自动发现机制 **亮点**:上传文档到新知识库时,系统自动发现并加载,无需修改配置 ```java private int discoverAndAddKnowledgeBasesFromDatabase() { // 查询所有不同的知识库名称 List allRepoNames = documentService.getAllDistinctKnowledgeBaseNames(); for (String repoName : allRepoNames) { if (!retrieverCache.containsKey(repoName)) { // 动态创建检索器并添加到缓存 ensureKnowledgeBaseInCache(repoName); } } } ``` **优势**: + **零配置**:新知识库自动可用,无需修改yaml配置 + **动态扩展**:系统运行时也能发现新知识库 + **配置可选**:只为需要精确匹配的知识库配置标签和优先级 ##### 3.2.4 结果合并与去重 **去重策略**: ```java private List deduplicateAndSort(List documents) { // 1. 根据文档ID去重(相同文档只保留相似度最高的) Map uniqueDocMap = new HashMap<>(); for (Document doc : documents) { String docId = doc.getId(); if (!uniqueDocMap.containsKey(docId)) { uniqueDocMap.put(docId, doc); } else { // 比较相似度,保留更高的 if (getScore(doc) > getScore(uniqueDocMap.get(docId))) { uniqueDocMap.put(docId, doc); } } } // 2. 排序:相似度降序,相同相似度时优先级升序 result.sort((d1, d2) -> { if (score1 != score2) return Double.compare(score2, score1); return Integer.compare(priority1, priority2); }); } ``` **文档数量限制**: + 最多返回5个最相关的文档,防止上下文过长淹没系统提示词 + 保留相似度最高的文档,保证检索质量 #### 3.3 使用场景 **技能考察阶段主动检索**: ```java if (shouldTriggerProactiveRagRetrieval(context)) { // 第1轮进入技能考察阶段时触发 // 1. 提取标签:["Java", "Spring", "MySQL"] List techTags = extractTechTagsFromContext(context); // 2. 构建检索查询 String query = "Java后端开发 面试题 Spring MySQL"; // 3. 设置ThreadLocal上下文 RagContext.setTags(techTags); // 4. RAG检索器自动使用这些标签匹配知识库 } ``` --- ## 核心设计思想 ### 面试流程设计 - 状态机模式 系统采用**状态机模式**设计面试流程,确保流程可控、可预测。整个面试过程被划分为5个清晰的阶段: ```plain PROJECT_DEEP_DIVE (项目深挖) ↓ SKILL_PROBING (核心技能考察) ↓ BEHAVIORAL_QUESTION (行为与软技能) ↓ CANDIDATE_QNA (候选人提问) ↓ CLOSING (总结与结束) ↓ COMPLETED (已完成) ``` **设计亮点:** 1. **阶段转换的智能决策机制** - **双层决策系统**:AI意图分析 + 规则兜底 - **意图分析助手**:分析每轮对话的充分度,判断是否进入下一阶段 - **规则兜底**:当AI决策失败时,基于轮次计数自动转换,防止流程卡死 - **可配置的轮数限制**:每个阶段都有最小轮数和最大轮数阈值,保证面试质量和时长控制 2. **动态提示词生成** - 根据当前阶段动态生成系统提示词 - 每个阶段有专门的提问策略和评分标准 - 注入岗位要求和简历信息,实现个性化面试 3. **防止重复提问机制** - AI会回顾对话历史,避免相似问题重复出现 - 项目深挖阶段限制同一项目最多3轮提问,强制切换项目 ### 配置抽离设计 - 可配置化架构 将硬编码的业务参数抽离到配置文件,实现**配置驱动开发**: **配置文件结构:** ```yaml interview: strategy: intent-analysis: max-turns-per-phase: 5 # 单个阶段最大轮数 early-warning-turns: 4 # 提前预警轮数 phase-transition: max-turns-per-phase-map: # 各阶段最大轮数 PROJECT_DEEP_DIVE: 8 SKILL_PROBING: 6 BEHAVIORAL_QUESTION: 5 min-turns-per-phase-map: # 各阶段最小轮数 PROJECT_DEEP_DIVE: 3 SKILL_PROBING: 3 memory: interview-memory-size: 60 # 面试记忆回溯条数 chat-memory-size: 15 # 聊天记忆回溯条数 question-strategy: max-turns-per-project: 3 # 同一项目最大提问轮数 ``` **设计优势:** 1. **参数化调整**:无需修改代码,只需调整配置文件即可改变面试策略 2. **环境隔离**:开发、测试、生产环境可以使用不同的配置参数 3. **快速迭代**:可以根据实际效果快速调整轮数、记忆大小等参数 4. **可维护性**:所有业务参数集中管理,易于理解和维护 ### 异步处理架构 - 非阻塞设计 **核心思想:不阻塞用户体验** 1. **对话分析的异步化** - 每轮对话结束后,立即返回AI回复给用户 - 对话评分、建议、分析等耗时操作通过 `CompletableFuture.runAsync()` 异步执行 - 用户无需等待分析完成即可继续下一轮对话 2. **响应式流式处理** - 使用 Reactor 的 `Flux` 实现流式文本输出 - TTS合成采用 `concatMap` 保证句子顺序播放,避免音频重叠 - 音频流和文本流并行推送,提升实时性 3. **异步报告生成** - 面试结束后的综合报告通过 `@Async` 异步生成并保存 - 报告生成期间,用户可以查看已生成的单轮分析结果 - 支持缓存机制(Redis L1 + 数据库 L2),已生成的报告秒级返回 ### 缓存设计 - 多级缓存策略 1. **RAG知识库缓存** - **启动时预加载**:系统启动时自动发现并加载所有知识库到内存 - **零数据库查询**:检索时完全使用内存缓存,大幅提升检索性能 - **自动刷新机制**:文档上传后自动刷新缓存,保证数据一致性 2. **面试报告缓存** - **三级缓存体系**:Redis缓存 → 数据库持久化 → 实时生成 - **缓存预热**:面试结束后立即生成并缓存报告 - **智能失效**:支持手动刷新缓存,保证报告实时性 3. **会话元数据缓存** - 面试过程中的岗位要求、简历信息存储在Redis - 避免频繁查询数据库,提升响应速度 ## 产品图片介绍 #### 数据库UML图 ![图片1.png](https://img.remit.ee/api/file/BQACAgUAAyEGAASHRsPbAAECLIFozQ0HwE7IZI0nKWnPiGxUUAYg4gAC5BgAAhwQaVYxTCz2tzZgMDYE.png) #### 登录界面 ![图片2.png](https://img.remit.ee/api/file/BQACAgUAAyEGAASHRsPbAAECLIBozQ0CUn0i0Tf6JVzH2G7bbIv8BQAC4xgAAhwQaVbPkriNEnqyszYE.png) #### 智能对话 ![图片3.png](https://img.remit.ee/api/file/BQACAgUAAyEGAASHRsPbAAECLHxozQ0BQwW2I0R-qQTWGiK83dBCygAC3xgAAhwQaVbi8N4OAdN9uzYE.png) #### 选择面试 ![微信图片_20250919160351_855_4.png](https://img.remit.ee/api/file/BQACAgUAAyEGAASHRsPbAAECLKNozQ7Zlc0J3SK7OOLsCQ5ljTRIJAACBhkAAhwQaVZkI1LfzQ0AAa42BA.png) #### 面试过程 ![微信图片_20250919155653_854_4.png](https://img.remit.ee/api/file/BQACAgUAAyEGAASHRsPbAAECLIJozQ0H7fEZ5KTVbSpNAe_3n8y0lwAC5RgAAhwQaVZdsEul3xEeNTYE.png) #### RAG知识库页面 ##### rag上传文档 ![图片3.png](https://youke1.picui.cn/s1/2025/11/22/69214e4446a32.png) ![图片3.png](https://youke1.picui.cn/s1/2025/11/22/69214e4397c2a.png) ![图片3.png](https://youke1.picui.cn/s1/2025/11/22/69214e4438811.png) ##### rag向量化测试: ![图片3.png](https://youke1.picui.cn/s1/2025/11/22/69214e43757a6.png) ##### 查询结果: ![图片3.png](https://youke1.picui.cn/s1/2025/11/22/69214e43547dc.png) #### 分析报告 ![图片4.png](https://img.remit.ee/api/file/BQACAgUAAyEGAASHRsPbAAECLH1ozQ0BiO1jW_NsoO7pCwGyPHjq4wAC4BgAAhwQaVZ8GWJLUaN1CjYE.png) #### 发布面经 ![图片5.png](https://img.remit.ee/api/file/BQACAgUAAyEGAASHRsPbAAECLKJozQ7Y2F-B7IcOBymnBeB0cNZQBQACBRkAAhwQaVafAAHkYVF9O5k2BA.png) #### 面经广场 ![微信图片_20250919160715_856_4.png](https://img.remit.ee/api/file/BQACAgUAAyEGAASHRsPbAAECLKVozQ8_swEc99aVtMWoJWWXKaozJQACCxkAAhwQaVaGGetIf2dxuTYE.png) #### 填写简历 ![微信图片_20250919160909_857_4.png](https://img.remit.ee/api/file/BQACAgUAAyEGAASHRsPbAAECLKdozQ-wEXJwKu6QmkvZ-qGkMkSuRgACDRkAAhwQaVY-g7mEgGcqyDYE.png) #### 综合评估 ![图片6.png](https://img.remit.ee/api/file/BQACAgUAAyEGAASHRsPbAAECLH9ozQ0CrFoFmq5qsT9Ule1PmeD1lQAC4hgAAhwQaVbY-A591mAdRzYE.png) ### 快速开始 1) 环境要求 - JDK 21、Maven 3.9+ - MySQL 8.x 与 Redis 6+ - 可选:阿里云 OSS、Iflytek API 账户 2) 初始化数据库 - 导入 `src/main/resources/virtual_interview_db_*.sql` 初始化表结构与基础数据。 3) 配置应用 - 在 `src/main/resources/application-prod.yml` 中设置数据库、Redis、OSS、Iflytek 等参数,或使用环境变量覆盖。 4) 构建与运行 ```bash # 构建 mvn clean package -DskipTests # 运行(Jar) java -jar target/virtual_interview-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod ``` 5) 访问与验证 - Swagger 文档:`http://localhost:8080/swagger-ui.html` - 健康检查:`/actuator/health` ### 关键模块与能力映射 - **鉴权与基础设施**:`annotation/AuthCheck`、`aop/*`、`config/*`、`exception/*`、`common/*` - **面试与聊天**:`controller/InterviewController`、`controller/ai/*`、`service/impl/*Interview*` - **会话记忆**:`controller/ai/chatMemory/*`、`service/impl/*Memory*`(MySQL 持久化) - **ASR/TTS**:`utils/rtasr/*`、`utils/tst/TtsService`、`model/dto/interview/audio/*` - **表情/姿态**:`utils/face/IflytekExpressionService` 与 `flask-realtime-face-eye/` - **RAG 知识库**:`controller/ai/rag/*`、`XfyunSparkKnowledge*`、`spring-ai-*` 相关配置 - **内容社区**:`Experience*` 与 `Channel*` 相关 `controller`、`service`、`mapper`、`model` - **文件上传**:`OssUploadController` + `config/OssConfig` ### 开发与调试建议 - 使用 `application-dev.yml` 本地开发,并将敏感参数置于环境变量或 `.properties` 外部化。 - 开启 `mybatis-plus.configuration.log-impl` 可查看 SQL 日志。 - 利用 `spring-cache` + Redis 提升查询性能;热点数据可加过期策略与手动失效。 - 善用 `@Validated` 与全局错误码(`common/ErrorCode`)统一返回结构。 ### 常见问题(FAQ) - 启动失败:检查数据库/Redis/OSS/Iflytek 配置是否正确,网络是否可达。 - Swagger 无法访问:推荐使用apifox,联系负责人免费发送apifox接口文件。 - ASR/TTS 不工作:核对 Iflytek 凭据与区域、WebSocket/HTTP 接口地址是否匹配;查看 `asr_audio_logs/` 与 `tts_audio_logs/`。 - 面试官问题质量问题:与模型本身有关,推荐使用超长上下文的模型,因为向量检索后可能会造成内容过长问题。(或者自行调整参数) - 其他问题:可咨询负责人or推荐issues ### 完整后端代码内容 - 新增RAG快捷创建知识库、文档打Tag功能等 ![知识库.png](https://img.remit.ee/api/file/BQACAgUAAyEGAASHRsPbAAEEM3BpBI0Ka6V9seVhg5McKyaVSIVNHQACESgAAgJcIVQMr5g00CX-VTYE.png) - 新增多智能体交互,使用阶段分析助手+面试官AI助手+兜底机制三方协作,优化面试流程与阶段 - 新增使用Tag+向量检索功能,确保面试质量 - 优化配置,面试参数可在yaml进行快捷配置 ![配置.png](https://img.remit.ee/api/file/BQACAgUAAyEGAASHRsPbAAEEM3FpBI0KTr68o6fwG-10ukLxb9soDwACEigAAgJcIVQXvnLxyvTQJTYE.png) ## 联系 需要 完整前后端、安卓端(可直接运行/源码)版 联系vx: _echo0z