大厂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);
        });
    }
}

技术要点

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

相关推荐
dLYG DUMS21 小时前
Redis——使用 python 操作 redis 之从 hmse 迁移到 hset
数据库·redis·python
dEso RSET21 小时前
Skywalking介绍,Skywalking 9.4 安装,SpringBoot集成Skywalking
spring boot·后端·skywalking
青槿吖21 小时前
告别RestTemplate!Feign让微服务调用像点外卖一样简单
java·开发语言·分布式·spring cloud·微服务·云原生·架构
MacroZheng21 小时前
横空出世!IDEA最强Spring插件来了,让你的开发效率成倍提升!
java·spring boot·后端
NEGl DRYN21 小时前
Spring Boot 3.3.4 升级导致 Logback 之前回滚策略配置不兼容问题解决
java·spring boot·logback
希望永不加班21 小时前
SpringBoot 缓存一致性:缓存与数据库双写策略
数据库·spring boot·后端·缓存·oracle
我是无敌小恐龙21 小时前
Java SE 零基础入门 Day02 运算符与流程控制超详细笔记
java·数据结构·spring boot·笔记·python·spring·spring cloud
MiNG MENS21 小时前
Spring Boot + Vue 全栈开发实战指南
vue.js·spring boot·后端
2601_949816581 天前
Spring Boot--@PathVariable、@RequestParam、@RequestBody
java·spring boot·后端
做个文艺程序员1 天前
生产级 AI 服务:限流、鉴权与可观测性【OpenClAW + Spring Boot 系列 第6篇·终章】
人工智能·spring boot·后端