大厂Java面试实录:从Spring Boot到AI技术的在线教育场景深度解析

大厂Java面试实录:从Spring Boot到AI技术的在线教育场景深度解析

大厂Java面试实录:从Spring Boot到AI技术的在线教育场景深度解析

面试场景:在线教育平台技术面试

面试官:谢飞机,欢迎来到我们公司面试。今天我们将围绕在线教育平台进行技术交流,请你放松心态,如实回答。

谢飞机:谢谢面试官,我会尽力表现的!


第一轮提问:Spring Boot基础与教育系统架构

面试官:首先,在线教育平台需要处理大量的课程和学生数据。请问我使用Spring Boot构建教育系统时,如何利用自动配置来简化开发?

谢飞机:嗯...Spring Boot的自动配置就是会根据类路径下的jar包自动配置Bean。比如如果看到spring-boot-starter-web,就会自动配置Tomcat、DispatcherServlet这些。在教育系统里,我们可以用@SpringBootApplication注解,然后通过@ConditionalOnClass这样的条件注解来控制Bean的创建。

面试官:回答得不错。那在教育平台中,我们经常需要实时推送课程更新和作业提醒,请问如何使用Spring WebFlux来实现响应式的实时通知?

谢飞机:Spring WebFlux是基于响应式编程的,可以用Mono和Flux来处理异步数据流。对于实时通知,我们可以创建一个Flux,然后通过WebSocket或者Server-Sent Events实时推送通知。这样可以避免阻塞,提高系统的并发处理能力。

面试官:很好。在教育平台中,课程信息需要频繁查询,请问我应该如何设计Redis缓存来优化课程信息的读取性能?

谢飞机:Redis缓存的话,可以用String结构存储课程JSON数据,Key可以用"course:#{courseId}"这样的格式。对于热门课程,可以用Set来维护。还可以用Redis的过期时间自动清理不活跃的课程数据。对了,还可以用Pipeline批量减少网络开销。

面试官:思路清晰。最后一个问题,教育平台需要处理大量的学生作业,请问如何使用Spring Data JPA来优化作业的批量查询和更新?

谢飞机:Spring Data JPA的话,可以用@Query注解写原生SQL,或者用Specification动态查询。批量更新的话,可以用saveAll()方法,或者用@Modifying注解写批量更新语句。对于分页查询,用Pageable对象配合Page返回结果。

面试官:很好,第一轮回答得不错。接下来我们进入第二轮。


第二轮提问:微服务架构与教育系统高并发

面试官:在线教育平台通常采用微服务架构,请问在微服务拆分时,如何合理设计课程服务的边界?

谢飞机:课程服务的边界...应该按照业务能力来拆分。比如可以分成课程管理服务、学生服务、作业服务、考试服务等等。每个服务都有自己的数据库,通过API互相调用。课程服务可以负责课程内容的存储和管理,学生服务负责用户信息和学习进度跟踪。

面试官:那在微服务通信中,我们如何使用OpenFeign来实现服务间的优雅调用?

谢飞机:OpenFeign是声明式的HTTP客户端,可以用@FeignClient注解定义接口。比如定义一个StudentClient接口,用@GetMapping("/api/students/{id}")这样的注解来调用学生服务。OpenFeign会自动实现HTTP调用,还支持负载均衡、熔断这些功能。

面试官:在教育平台中,学生选课和退课操作频繁,请问如何使用Kafka来实现课程状态变更的异步通知?

谢飞机:Kafka的话,可以创建一个"course-events"主题,课程服务在状态变更时发送消息。其他服务比如学生服务、作业服务可以订阅这个主题。消息可以用JSON格式,包含课程ID、操作类型、学生ID这些字段。这样可以实现服务解耦,提高系统的响应速度。

面试官:很好。最后一个问题,教育平台需要保证高可用性,请问如何使用Resilience4j来实现服务的熔断和限流?

谢飞机:Resilience4j是一个轻量级的容错库。可以用CircuitBreaker来设置熔断规则,当错误率达到阈值就熔断。用RateLimiter来限制请求频率,用Bulkhead来限制并发线程数。比如在调用外部API时,可以加上@CircuitBreaker注解,当服务不可用时快速失败。

面试官:不错,第二轮回答得还可以。接下来我们进入最后一轮。


第三轮提问:AI技术与教育智能化

面试官:现代在线教育平台都在引入AI技术来个性化学习体验。请问在Spring Boot中如何集成Spring AI来实现智能学习推荐?

谢飞机:Spring AI...这个我了解不多,应该是Spring框架对AI的支持。可以用Spring AI的客户端调用大模型API,把学生的学习历史、课程难度、学习进度作为输入,让AI推荐最适合的课程内容。然后把这个推荐结果保存到数据库,供学生使用。

面试官:那在教育平台中,我们如何使用向量数据库来实现相似课程的快速检索?

谢飞机:向量数据库...这个我接触不多。应该是把课程内容的特征转换成向量,然后存储在Milvus或者Chroma这样的向量数据库里。当需要查找相似课程时,可以用余弦相似度来计算课程之间的相似性,这样可以快速找到相似的学习资源。

面试官:在教育智能辅导中,我们如何使用RAG技术来提高回答的准确性和相关性?

谢飞机:RAG是检索增强生成...应该是先从教材和课程资料中检索相关的知识,然后结合这些知识来生成回答。比如当学生问数学问题时,系统先从知识库中查找相关的公式和例题,然后基于这些信息给出详细的解答。

面试官:最后一个问题,教育平台需要处理大量的自然语言查询,请问如何使用Embedding模型来实现智能语义搜索?

谢飞机:Embedding模型...这个我了解不多。应该是把学生的自然语言查询转换成向量,然后在向量空间中进行相似度匹配。比如学生问"如何学习Java编程",系统把这个查询转换成向量,然后在课程数据库中查找相似的课程内容,推荐相关的学习资源。

面试官:好的,今天的面试就到这里。你的回答有对有错,我们会综合评估。请你回家等通知吧。

谢飞机:谢谢面试官,我会继续学习的!


详细答案解析

第一轮答案详解

1. Spring Boot自动配置在教育系统中的应用

业务场景:在线教育平台需要快速构建基础架构,处理课程管理、学生管理、作业管理、考试管理等核心功能。

技术实现

java 复制代码
@SpringBootApplication
public class EducationApplication {
    public static void main(String[] args) {
        SpringApplication.run(EducationApplication.class, args);
    }
}

@Configuration
@ConditionalOnClass(DataSource.class)
public class DataSourceAutoConfiguration {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }
}

@Service
public class CourseService {
    @Autowired
    private CourseRepository courseRepository;
    
    public Course getCourseById(Long courseId) {
        return courseRepository.findById(courseId).orElse(null);
    }
}

技术要点

  • @SpringBootApplication包含@EnableAutoConfiguration,自动配置Spring上下文
  • @ConditionalOnClass根据类路径条件自动配置Bean
  • @ConfigurationProperties绑定配置文件属性到Bean
  • 教育系统中可自动配置数据源、Redis、消息队列等基础设施
2. Spring WebFlux实现响应式实时通知

业务场景:实时推送课程更新、作业提醒、考试通知等信息,支持大量并发连接,避免阻塞式I/O影响系统性能。

技术实现

java 复制代码
@RestController
@RequestMapping("/api/notifications")
public class NotificationController {
    
    @GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<Notification> getNotificationStream() {
        return notificationService.getRealTimeNotifications();
    }
    
    @MessageMapping("/course.update")
    @SendTo("/topic/notifications")
    public Notification updateNotification(Notification notification) {
        return notificationService.updateNotification(notification);
    }
}

@Service
public class NotificationService {
    
    public Flux<Notification> getRealTimeNotifications() {
        return Flux.interval(Duration.ofSeconds(1))
                  .flatMap(i -> notificationRepository.findAll());
    }
    
    public Notification updateNotification(Notification notification) {
        return notificationRepository.save(notification);
    }
}

技术要点

  • 使用Flux<Notification>处理异步数据流
  • MediaType.TEXT_EVENT_STREAM_VALUE支持Server-Sent Events
  • WebSocket集成实现双向实时通信
  • 响应式编程避免阻塞,提高并发处理能力
3. Redis缓存优化课程信息读取

业务场景:课程信息频繁查询,需要减少数据库压力,提高响应速度,特别是在选课高峰期。

技术实现

java 复制代码
@Service
public class CourseCacheService {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    public Course getCourseFromCache(Long courseId) {
        String key = "course:" + courseId;
        return (Course) redisTemplate.opsForValue().get(key);
    }
    
    public void cacheCourse(Course course) {
        String key = "course:" + courseId;
        redisTemplate.opsForValue().set(key, course, 30, TimeUnit.MINUTES);
    }
    
    public void batchCacheCourses(List<Course> courses) {
        Map<String, Object> map = new HashMap<>();
        courses.forEach(c -> map.put("course:" + c.getId(), c));
        redisTemplate.opsForValue().multiSet(map);
    }
}

技术要点

  • 使用String结构存储JSON序列化的课程数据
  • 合理设置过期时间,避免内存泄漏
  • Pipeline批量操作减少网络开销
  • 设置合理的缓存穿透和缓存雪崩防护
4. Spring Data JPA优化作业批量操作

业务场景:批量查询和更新学生作业,提高数据处理效率,特别是在批改作业和统计分析时。

技术实现

java 复制代码
@Repository
public interface AssignmentRepository extends JpaRepository<Assignment, Long> {
    
    @Query("SELECT a FROM Assignment a WHERE a.status = :status")
    List<Assignment> findByStatus(@Param("status") AssignmentStatus status);
    
    @Query(value = "SELECT * FROM assignments WHERE status = ?1 LIMIT ?2", nativeQuery = true)
    Page<Assignment> findByStatusNative(AssignmentStatus status, Pageable pageable);
    
    @Modifying
    @Query("UPDATE Assignment a SET a.status = :newStatus WHERE a.id IN :ids")
    int updateStatusByIds(@Param("newStatus") AssignmentStatus newStatus, 
                         @Param("ids") List<Long> ids);
}

@Service
public class AssignmentService {
    
    @Autowired
    private AssignmentRepository assignmentRepository;
    
    public List<Assignment> getPendingAssignments() {
        return assignmentRepository.findByStatus(AssignmentStatus.PENDING);
    }
    
    public Page<Assignment> getAssignmentsByPage(AssignmentStatus status, int page, int size) {
        Pageable pageable = PageRequest.of(page, size, Sort.by("submitTime").descending());
        return assignmentRepository.findByStatusNative(status, pageable);
    }
    
    @Transactional
    public void batchUpdateStatus(List<Long> ids, AssignmentStatus newStatus) {
        assignmentRepository.updateStatusByIds(newStatus, ids);
    }
}

技术要点

  • 使用@Query注解优化复杂查询
  • 原生SQL查询提高性能
  • @Modifying注解支持批量更新
  • 分页查询避免内存溢出
  • 事务管理保证数据一致性

第二轮答案详解

1. 微服务边界设计

业务场景:在线教育系统复杂度高,需要合理拆分微服务,提高系统可维护性和扩展性。

技术实现

java 复制代码
// 课程服务边界设计
@RestController
@RequestMapping("/api/courses")
public class CourseController {
    
    @Autowired
    private CourseService courseService;
    
    @PostMapping
    public ResponseEntity<Course> createCourse(@RequestBody CourseRequest request) {
        Course course = courseService.createCourse(request);
        return ResponseEntity.ok(course);
    }
    
    @GetMapping("/{id}/content")
    public ResponseEntity<CourseContent> getCourseContent(@PathVariable Long id) {
        CourseContent content = courseService.getCourseContent(id);
        return ResponseEntity.ok(content);
    }
}

// 学生服务边界设计
@RestController
@RequestMapping("/api/students")
public class StudentController {
    
    @Autowired
    private StudentService studentService;
    
    @GetMapping("/{id}/progress")
    public ResponseEntity<StudentProgress> getStudentProgress(@PathVariable Long id) {
        StudentProgress progress = studentService.getStudentProgress(id);
        return ResponseEntity.ok(progress);
    }
    
    @PostMapping("/{id}/enroll")
    public ResponseEntity<Student> enrollCourse(@PathVariable Long id, 
                                              @RequestBody EnrollmentRequest request) {
        Student student = studentService.enrollCourse(id, request);
        return ResponseEntity.ok(student);
    }
}

技术要点

  • 按业务能力拆分:课程服务、学生服务、作业服务、考试服务
  • 单一职责原则:每个服务专注于特定业务领域
  • 数据独立性:每个服务有自己的数据库
  • API设计:RESTful接口,清晰明确的资源路径
2. OpenFeign服务间调用

业务场景:微服务间需要优雅的HTTP调用,避免手动处理HTTP请求细节。

技术实现

java 复制代码
// 学生服务客户端
@FeignClient(name = "student-service", url = "${student.service.url}")
public interface StudentClient {
    
    @GetMapping("/api/students/{id}")
    ResponseEntity<Student> getStudentById(@PathVariable Long id);
    
    @GetMapping("/api/students/{id}/progress")
    ResponseEntity<StudentProgress> getStudentProgress(@PathVariable Long id);
    
    @PostMapping("/api/students/{id}/enroll")
    ResponseEntity<Student> enrollCourse(@PathVariable Long id, 
                                        @RequestBody EnrollmentRequest request);
}

// 课程服务中使用
@Service
public class CourseService {
    
    @Autowired
    private StudentClient studentClient;
    
    @Autowired
    private AssignmentClient assignmentClient;
    
    public Course createCourse(CourseRequest request) {
        // 调用学生服务验证学生信息
        Student student = studentClient.getStudentById(request.getInstructorId()).getBody();
        
        // 调用作业服务创建作业模板
        AssignmentTemplate template = assignmentClient.createAssignmentTemplate(request.getAssignmentTemplate());
        
        // 创建课程
        Course course = new Course();
        course.setTitle(request.getTitle());
        course.setDescription(request.getDescription());
        course.setInstructorId(request.getInstructorId());
        course.setAssignmentTemplateId(template.getId());
        
        return courseRepository.save(course);
    }
}

技术要点

  • @FeignClient声明式HTTP客户端
  • 接口定义与远程服务API保持一致
  • 自动集成负载均衡、熔断、重试
  • 简化服务间调用代码,提高可维护性
3. Kafka课程状态异步通知

业务场景:课程状态变更频繁,需要实时通知相关服务,避免同步调用的性能瓶颈。

技术实现

java 复制代码
// 课程服务 - 消息生产者
@Service
public class CourseService {
    
    @Autowired
    private KafkaTemplate<String, CourseEvent> kafkaTemplate;
    
    @Autowired
    private CourseRepository courseRepository;
    
    @Transactional
    public Course updateCourseStatus(Long courseId, CourseStatus newStatus) {
        Course course = courseRepository.findById(courseId)
            .orElseThrow(() -> new CourseNotFoundException(courseId));
        
        CourseStatus oldStatus = course.getStatus();
        course.setStatus(newStatus);
        course = courseRepository.save(course);
        
        // 发送状态变更事件
        CourseEvent event = new CourseEvent();
        event.setCourseId(courseId);
        event.setOldStatus(oldStatus);
        event.setNewStatus(newStatus);
        event.setTimestamp(LocalDateTime.now());
        
        kafkaTemplate.send("course-events", event);
        
        return course;
    }
}

// 学生服务 - 消息消费者
@Service
public class StudentService {
    
    @Autowired
    private StudentRepository studentRepository;
    
    @KafkaListener(topics = "course-events", groupId = "student-group")
    public void handleCourseEvent(CourseEvent event) {
        if (event.getNewStatus() == CourseStatus.PUBLISHED) {
            // 课程发布后通知相关学生
            notifyStudentsForCourse(event.getCourseId());
        } else if (event.getNewStatus() == CourseStatus.CANCELLED) {
            // 课程取消后通知已报名学生
            notifyCancellationToEnrolledStudents(event.getCourseId());
        }
    }
    
    private void notifyStudentsForCourse(Long courseId) {
        // 实现课程通知逻辑
    }
    
    private void notifyCancellationToEnrolledStudents(Long courseId) {
        // 实现取消通知逻辑
    }
}

技术要点

  • 主题设计:按业务事件类型定义主题
  • 消息结构:包含足够的上下文信息
  • 消费者分组:实现消息的负载均衡
  • 事件驱动架构:服务解耦,提高系统弹性
4. Resilience4j服务容错

业务场景:教育系统依赖多个外部服务,需要保证系统在服务不可用时的稳定性。

技术实现

java 复制代码
@Configuration
public class Resilience4jConfig {
    
    @Bean
    public CircuitBreakerConfig circuitBreakerConfig() {
        return CircuitBreakerConfig.custom()
            .failureRateThreshold(50)
            .waitDurationInOpenState(Duration.ofMillis(1000))
            .slidingWindowSize(10)
            .slidingWindowType(SlidingWindowType.COUNT_BASED)
            .build();
    }
    
    @Bean
    public RateLimiterConfig rateLimiterConfig() {
        return RateLimiterConfig.custom()
            .limitForPeriod(100)
            .limitRefreshPeriod(Duration.ofSeconds(1))
            .timeoutDuration(Duration.ofMillis(0))
            .build();
    }
}

@Service
public class ExternalServiceClient {
    
    @Autowired
    private CircuitBreaker circuitBreaker;
    
    @Autowired
    private RateLimiter rateLimiter;
    
    @Autowired
    private RestTemplate restTemplate;
    
    @CircuitBreaker(name = "externalService", fallbackMethod = "getExternalDataFallback")
    @RateLimiter(name = "externalService")
    public ExternalData getExternalData(String endpoint) {
        return restTemplate.getForObject(endpoint, ExternalData.class);
    }
    
    public ExternalData getExternalDataFallback(String endpoint, Exception ex) {
        ExternalData fallbackData = new ExternalData();
        fallbackData.setData("Fallback data due to service unavailability");
        fallbackData.setTimestamp(LocalDateTime.now());
        return fallbackData;
    }
    
    @Bulkhead(name = "externalService", type = Bulkhead.Type.THREADPOOL)
    @Recover
    public ExternalData handleBulkheadFailure(Exception ex) {
        ExternalData fallbackData = new ExternalData();
        fallbackData.setData("System busy, please try again later");
        fallbackData.setTimestamp(LocalDateTime.now());
        return fallbackData;
    }
}

技术要点

  • 熔断器:快速失败,避免资源浪费
  • 限流器:控制请求频率,保护系统
  • 舱壁隔离:限制并发线程数
  • 降级策略:提供备用数据或默认值
  • 配置灵活:可根据业务需求调整参数

第三轮答案详解

1. Spring AI智能学习推荐

业务场景:利用AI技术分析学生学习行为,个性化推荐课程内容和练习题目,提高学习效果。

技术实现

java 复制代码
@Configuration
public class SpringAiConfig {
    
    @Bean
    public OpenAiClient openAiClient() {
        return OpenAiClient.builder()
            .apiKey("${openai.api.key}")
            .build();
    }
}

@Service
public class LearningRecommendationService {
    
    @Autowired
    private OpenAiClient openAiClient;
    
    @Autowired
    private StudentProgressService studentProgressService;
    
    @Autowired
    private CourseContentService courseContentService;
    
    public Recommendation recommendLearningPath(Long studentId) {
        // 构建AI提示
        String prompt = buildPrompt(studentId);
        
        // 调用AI模型
        AiResponse response = openAiClient.complete(prompt);
        
        // 解析AI响应
        Recommendation aiRecommendation = parseAiResponse(response.getContent());
        
        // 验证和优化推荐
        Recommendation optimizedRecommendation = validateAndOptimizeRecommendation(aiRecommendation);
        
        // 保存推荐结果到数据库
        return recommendationRepository.save(optimizedRecommendation);
    }
    
    private String buildPrompt(Long studentId) {
        StudentProgress progress = studentProgressService.getStudentProgress(studentId);
        List<CourseContent> completedContents = courseContentService.getCompletedContents(studentId);
        
        return String.format(
            "作为教育推荐专家,请为以下学生设计个性化学习路径:" +
            "学生信息:%s,已完成内容:%s,学习进度:%s,学习偏好:%s。" +
            "请返回JSON格式的推荐结果,包含推荐课程、练习题目、学习计划等信息。",
            progress.getStudentInfo(),
            completedContents,
            progress.getProgressPercentage(),
            progress.getLearningPreferences()
        );
    }
    
    private Recommendation parseAiResponse(String aiResponse) {
        // 使用JSON解析库解析AI返回的结果
        return JsonUtils.fromJson(aiResponse, Recommendation.class);
    }
    
    private Recommendation validateAndOptimizeRecommendation(Recommendation recommendation) {
        // 验证推荐的合理性
        // 结合学生学习历史优化推荐
        // 考虑课程难度和先修要求
        return recommendation;
    }
}

技术要点

  • Spring AI集成:简化AI模型调用
  • 提示工程:构建高质量的AI提示词
  • 结果解析:JSON格式的结构化数据
  • 推荐验证:结合学生历史数据优化推荐
  • 持久化存储:保存推荐结果供后续使用
2. 向量数据库相似课程检索

业务场景:快速查找相似课程内容,为学生提供相关学习资源,丰富学习体验。

技术实现

java 复制代码
@Service
public class SimilarCourseService {
    
    @Autowired
    private MilvusClient milvusClient;
    
    @Autowired
    private CourseVectorService courseVectorService;
    
    public List<Course> findSimilarCourses(Course targetCourse, int topK) {
        // 将目标课程转换为向量
        float[] targetVector = courseVectorService.courseToVector(targetCourse);
        
        // 在向量数据库中搜索相似课程
        SearchParam searchParam = SearchParam.newBuilder()
            .withCollectionName("course_contents")
            .withVectors(targetVector)
            .withTopK(topK)
            .withMetricType(MetricType.L2)
            .build();
        
        SearchResult searchResult = milvusClient.search(searchParam);
        
        // 解析搜索结果
        return parseSearchResult(searchResult);
    }
    
    public void buildCourseVectors(List<Course> courses) {
        List<InsertParam> insertParams = courses.stream()
            .map(course -> {
                float[] vector = courseVectorService.courseToVector(course);
                return InsertParam.newBuilder()
                    .withCollectionName("course_contents")
                    .withPrimaryField(course.getId())
                    .withVectorField(vector)
                    .withAdditionalFields(course.getFeatures())
                    .build();
            })
            .collect(Collectors.toList());
        
        // 批量插入向量数据
        insertParams.forEach(milvusClient::insert);
    }
    
    private List<Course> parseSearchResult(SearchResult searchResult) {
        return searchResult.getResults().stream()
            .map(result -> {
                Course course = new Course();
                course.setId(result.getId());
                course.setSimilarityScore(result.getScore());
                return course;
            })
            .collect(Collectors.toList());
    }
}

@Component
public class CourseVectorService {
    
    @Autowired
    private EmbeddingModel embeddingModel;
    
    public float[] courseToVector(Course course) {
        // 构建课程特征文本
        String featureText = String.format(
            "课程标题:%s,课程描述:%s,难度级别:%s,分类:%s,标签:%s",
            course.getTitle(),
            course.getDescription(),
            course.getDifficultyLevel(),
            course.getCategory(),
            course.getTags()
        );
        
        // 使用Embedding模型转换为向量
        return embeddingModel.embed(featureText);
    }
}

技术要点

  • 向量化:将课程特征转换为数值向量
  • 相似度计算:使用余弦相似度或欧氏距离
  • Milvus/Chroma:专门的向量数据库
  • 批量处理:提高数据导入效率
  • 特征工程:选择合适的课程特征
3. RAG技术在教育智能辅导中的应用

业务场景:提高智能辅导回答准确性,基于教材和课程资料提供专业的教育咨询服务。

技术实现

java 复制代码
@Service
public class EducationTutorService {
    
    @Autowired
    private DocumentRetriever documentRetriever;
    
    @Autowired
    private ChatModel chatModel;
    
    @Autowired
    private KnowledgeBaseService knowledgeBaseService;
    
    public TutorResponse handleStudentQuery(StudentQuery query) {
        // 1. 检索相关知识文档
        List<Document> relevantDocuments = documentRetriever.retrieve(
            query.getQuestion(), 
            5
        );
        
        // 2. 构建增强提示
        String enhancedPrompt = buildEnhancedPrompt(query, relevantDocuments);
        
        // 3. 调用大模型生成回答
        AiResponse aiResponse = chatModel.complete(enhancedPrompt);
        
        // 4. 处理和验证回答
        TutorResponse response = processResponse(aiResponse, relevantDocuments);
        
        // 5. 记录对话历史
        saveConversationHistory(query, response);
        
        return response;
    }
    
    private String buildEnhancedPrompt(StudentQuery query, List<Document> documents) {
        String context = documents.stream()
            .map(Document::getContent)
            .collect(Collectors.joining("\n\n"));
        
        return String.format(
            "基于以下教育知识库信息,请回答学生的问题:" +
            "\n\n知识库信息:\n%s" +
            "\n\n学生问题:%s" +
            "\n\n请提供准确、专业的教育回答,如果知识库中没有相关信息,请明确告知。",
            context,
            query.getQuestion()
        );
    }
    
    private TutorResponse processResponse(AiResponse aiResponse, List<Document> documents) {
        TutorResponse response = new TutorResponse();
        response.setAnswer(aiResponse.getContent());
        response.setSources(documents.stream()
            .map(Document::getSource)
            .collect(Collectors.toList()));
        response.setConfidence(calculateConfidence(documents));
        return response;
    }
    
    private double calculateConfidence(List<Document> documents) {
        // 基于检索到的文档数量和质量计算置信度
        return Math.min(1.0, documents.size() * 0.2);
    }
    
    @EventListener
    public void handleNewDocument(DocumentAddedEvent event) {
        // 当知识库新增文档时,更新向量索引
        documentRetriever.updateIndex(event.getDocument());
    }
}

技术要点

  • 文档检索:基于语义相似度查找相关知识
  • 提示增强:结合检索结果构建上下文
  • 回答验证:评估回答的准确性和置信度
  • 知识库维护:定期更新和优化文档索引
  • 对话管理:记录学生交互历史
4. Embedding模型实现语义搜索

业务场景:理解学生自然语言查询意图,提供精准的教育资源搜索和学习建议。

技术实现

java 复制代码
@Service
public class EducationSearchService {
    
    @Autowired
    private EmbeddingModel embeddingModel;
    
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    
    @Autowired
    private QueryIntentAnalyzer intentAnalyzer;
    
    public SearchResult semanticSearch(String query) {
        // 1. 分析查询意图
        QueryIntent intent = intentAnalyzer.analyzeIntent(query);
        
        // 2. 将查询转换为向量
        float[] queryVector = embeddingModel.embed(query);
        
        // 3. 构建语义搜索查询
        NativeSearchQuery searchQuery = buildSemanticSearchQuery(queryVector, intent);
        
        // 4. 执行搜索
        SearchHits<EducationDocument> searchHits = 
            elasticsearchTemplate.search(searchQuery, EducationDocument.class);
        
        // 5. 处理和排序结果
        return processSearchResults(searchHits, query);
    }
    
    private NativeSearchQuery buildSemanticSearchQuery(float[] queryVector, QueryIntent intent) {
        // 构建向量相似度查询
        VectorScriptQueryBuilder vectorQuery = QueryBuilders
            .scriptQuery(new Script(
                "cosineSimilarity(params.query_vector, 'doc_vector') + 1.0",
                Collections.singletonMap("query_vector", queryVector)
            ));
        
        // 构建意图过滤器
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
            .must(vectorQuery)
            .filter(buildIntentFilter(intent));
        
        return new NativeSearchQueryBuilder()
            .withQuery(boolQuery)
            .withPageable(PageRequest.of(0, 10))
            .build();
    }
    
    private BoolQueryBuilder buildIntentFilter(QueryIntent intent) {
        BoolQueryBuilder filter = QueryBuilders.boolQuery();
        
        switch (intent.getType()) {
            case COURSE_SEARCH:
                filter.must(QueryBuilders.termQuery("category", "course"));
                break;
            case ASSIGNMENT_HELP:
                filter.must(QueryBuilders.termQuery("category", "assignment"));
                break;
            case EXAM_PREPARATION:
                filter.must(QueryBuilders.termQuery("category", "exam"));
                break;
            default:
                filter.must(QueryBuilders.existsQuery("content"));
        }
        
        return filter;
    }
    
    private SearchResult processSearchResults(SearchHits<EducationDocument> searchHits, String query) {
        SearchResult result = new SearchResult();
        result.setQuery(query);
        result.setTotalResults(searchHits.getTotalHits());
        
        List<SearchResultItem> items = searchHits.stream()
            .map(hit -> {
                SearchResultItem item = new SearchResultItem();
                item.setId(hit.getId());
                item.setTitle(hit.getContent().getTitle());
                item.setSummary(hit.getContent().getSummary());
                item.setRelevanceScore(hit.getScore());
                item.setUrl(hit.getContent().getUrl());
                return item;
            })
            .sorted(Comparator.comparingDouble(SearchResultItem::getRelevanceScore).reversed())
            .collect(Collectors.toList());
        
        result.setItems(items);
        return result;
    }
    
    // 定期重新索引文档
    @Scheduled(fixedRate = 3600000) // 每小时执行一次
    public void reindexDocuments() {
        List<EducationDocument> documents = educationDocumentRepository.findAll();
        
        documents.forEach(doc -> {
            float[] vector = embeddingModel.embed(doc.getContent());
            doc.setVector(vector);
            educationDocumentRepository.save(doc);
        });
    }
}

技术要点

  • 意图识别:分析查询的真实意图
  • 向量化搜索:将查询转换为向量进行相似度匹配
  • 多维度过滤:结合意图和类别进行精确过滤
  • 相关性排序:基于相似度分数排序结果
  • 定期更新:保持向量索引的时效性

相关推荐
IT 行者2 小时前
CentOS 下源码编译安装完整版 Redis 8.0 指南(附 Rust 工具链详解)
redis·rust·centos
2601_949814692 小时前
ubuntu 安装 Redis
linux·redis·ubuntu
希望永不加班2 小时前
SpringBoot Web 模块核心组件:从 DispatcherServlet 讲起
java·前端·spring boot·后端·spring
麦聪聊数据2 小时前
企业数据流通与敏捷API交付实战(二):微服务取数与冗余CRUD
数据库·sql·低代码·微服务·restful
流星雨在线2 小时前
Node.js + Express 项目完整搭建手册(Redis + MySQL + 常用中间件)
redis·node.js·express
流星雨在线2 小时前
SpringBoot 从开发到打包发布完整教程(对比 Node.js)
spring boot·后端·node.js
xiaohuoji1293 小时前
SpringBoot中整合RabbitMQ(测试+部署上线 最完整)
spring boot·rabbitmq·java-rabbitmq
希望永不加班3 小时前
SpringBoot 接口测试:Postman 与 JUnit 5 实战
java·spring boot·后端·junit·postman
yzx9910133 小时前
Java毕业设计实战:基于Spring Boot的在线图书管理系统(完整版)
java·spring boot·课程设计