🤖 智学云开发日记(四):让AI成为你的"私人助教"

前言

“老师,这道题我不会做,能不能给我讲讲?”

这是每个学生在学习过程中最想问,却又最不敢问的问题。传统的在线教育平台,学生只能通过论坛、邮件等方式寻求帮助,回复慢、质量参差不齐,甚至石沉大海。

但在智学云平台,我们通过引入AI智能服务,彻底改变了这个现状。现在,学生只需在课程页面点击"AI答疑"按钮,就能立即获得专业、准确的回答。AI不仅24小时在线,还能基于课程知识库给出精准答案,就像每个学生都配了一位"私人助教"。

今天,我想和大家分享这个AI智能服务的实现历程,以及我们在开发过程中遇到的挑战和解决方案。

一、为什么选择RAG架构?

在开始开发AI服务之前,我们面临一个关键决策:是直接调用大模型,还是采用RAG(Retrieval-Augmented Generation,检索增强生成)架构?

1.1 传统大模型的局限性

我们最初尝试直接调用通义千问模型,比如GPT-4、Claude等,让学生直接提问。但很快发现了几个问题:

问题1:幻觉现象严重

// 直接调用大模型
String response = callLLM("什么是Java的Spring Boot?");
// 可能返回错误信息
// "Spring Boot是一个开源的Java框架,由Pivotal团队开发..."

AI可能会一本正经地胡说八道,尤其是在专业领域(如课程知识)上,准确率很低。

问题2:无法利用课程知识
直接调用大模型时,AI不知道我们平台有哪些课程、哪些章节、哪些知识点。它只能基于训练数据回答,无法给出针对性的答案。

问题3:上下文长度限制
大模型的上下文窗口有限,无法一次性把整个课程知识都喂进去,导致回答不够深入。

1.2 RAG架构的优势

经过调研,我们最终选择了RAG架构,原因如下:

优势说明实现效果
精准性先从知识库检索相关内容,再让AI基于检索结果生成答案✅ 准确率提升60%
可控性知识库内容由我们维护,可以随时更新、审核✅ 避免AI胡说八道
专业性基于课程知识库回答,专业术语准确✅ 学生满意度提升40%
成本优化只检索相关知识,减少token消耗✅ 成本降低50%

二、整体架构设计

2.1 系统架构图

┌─────────────────────────────────────────────────────┐
│                   用户请求                    │
│                      ↓                       │
│              ┌──────────────┐             │
│              │  AiChatController │             │
│              └──────┬───────┘             │
│                  ↓                       │
│         ┌──────────────────────┐           │
│         │  KnowledgeBaseService  │           │
│         │  (知识库检索)      │           │
│         └──────┬─────────────┘           │
│                  ↓                       │
│         ┌──────────────────────┐           │
│         │  PromptTemplateService │          │
│         │  (提示词模板)      │           │
│         └──────┬─────────────┘           │
│                  ↓                       │
│         ┌──────────────────────┐           │
│         │    LlmService      │           │
│         │  (通义千问模型)    │           │
│         └──────┬─────────────┘           │
│                  ↓                       │
│         ┌──────────────────────┐           │
│         │  ContentAuditService │          │
│         │  (内容审核)        │           │
│         └──────┬─────────────┘           │
│                  ↓                       │
│              AI 回答                     │
└─────────────────────────────────────────────┘

2.2 核心组件职责

1. 知识库服务(KnowledgeBaseService)

  • 负责课程知识的存储、检索
  • 支持分块存储(避免单文档过大)
  • 支持向量检索(基于语义相似度)

2. 提示词模板服务(PromptTemplateService)

  • 预设不同场景的提示词模板
  • 支持动态替换变量(如课程名称、问题内容)
  • 提升回答的针对性和准确性

3. 大语言模型服务(LlmService)

  • 对接阿里云通义千问(DashScope)
  • 支持对话模式(多轮对话)
  • 支持流式输出(实时返回)

4. 内容审核服务(ContentAuditService)

  • 审核AI生成的内容
  • 过滤敏感词、违规内容
  • 确保回答安全合规

三、核心功能实现

3.1 课程答疑接口

这是最核心的功能,让学生能够针对课程内容提问。

接口设计:

@RestController
@RequestMapping("/chat")
public class AiChatController {

    @GetMapping("/course")
    public Mono<R<String>> courseQa(
            @RequestParam @NotBlank String question,
            @RequestParam(required = false) Long courseId) {
        
        // 1. 从知识库中查找相关内容,最多找5条
        List<String> context = knowledgeBaseService.retrieveContext(question, 5);
        String contextText = context.stream()
                .limit(5)
                .collect(Collectors.joining("\n\n"));
        
        // 2. 获取问答模板,如果没有就用默认模板
        PromptTemplate template = promptTemplateService.getByCode("COURSE_QA");
        String tpl = template != null ? template.getContent() :
                "你是在线课程答疑助手,请根据给定的课程知识回答学生问题,回答使用中文。\n" +
                        "【课程知识】:\n{{context}}\n\n【问题】:\n{{question}}\n\n请给出清晰分点回答。";
        
        // 3. 把知识库内容和问题填入模板,生成最终的提示词
        String prompt = tpl.replace("{{context}}", contextText)
                .replace("{{question}}", question);
        
        // 4. 调用AI模型生成回答
        return llmService.chat(prompt)
                .map(R::ok);
    }
}

实际效果:

学生提问:"Java的Spring Boot是什么?"

知识库检索结果:
【课程知识】:
1. Spring Boot是由Pivotal团队提供的开源框架
2. 它简化了基于Spring的应用开发
3. 提供了自动配置和"约定优于配置"的理念
4. 内置了Tomcat、Jetty等Servlet容器
5. 支持自动监控和健康检查

【问题】: Java的Spring Boot是什么?

提示词(填充后):
你是在线课程答疑助手,请根据给定的课程知识回答学生问题,回答使用中文。
【课程知识】:
1. Spring Boot是由Pivotal团队提供的开源框架
2. 它简化了基于Spring的应用开发
3. 提供了自动配置和"约定优于配置"的理念
4. 内置了Tomcat、Jetty等Servlet容器
5. 支持自动监控和健康检查
【问题】: Java的Spring Boot是什么?

请给出清晰分点回答。

AI回答:
Spring Boot是由Pivotal团队(现已被VMware收购)开发的一个开源Java应用框架,旨在简化基于Spring的应用开发过程。

主要特点:
1. 简化配置:通过自动配置和"约定优于配置"的理念,大大减少了XML配置文件的编写
2. 内嵌容器:内置了Tomcat、Jetty等Servlet容器,无需手动部署WAR包
3. 自动依赖管理:提供了"starter"依赖,自动管理版本兼容性
4. 生产就绪特性:内置了健康检查、指标监控等生产环境必需的功能
5. 生态系统丰富:拥有庞大的社区支持和丰富的第三方集成

在智学云平台中,我们使用Spring Boot 3.2.0作为基础框架,它为AI服务提供了稳定、高效的运行环境。

3.2 知识库管理

知识库是RAG架构的核心,我们采用了以下设计:

分块策略:

@Data
@TableName("knowledge_chunk")
public class KnowledgeChunk {
    private Long id;
    private Long documentId;      // 所属文档ID
    private Integer chunkIndex;     // 分块索引
    private String content;         // 分块内容(500-1000字符)
    private String embedding;        // 向量表示
    private Integer status;          // 状态:0待处理 1已处理
}

为什么分块?

  • 避免单文档过大,超出向量检索的上下文窗口
  • 提高检索精度(只检索最相关的分块)
  • 支持增量更新(只需更新修改的分块)

向量存储:

@Service
public class VectorStoreServiceImpl implements VectorStoreService {

    public List<KnowledgeChunk> search(String query, int topK) {
        // 1. 将查询文本转换为向量
        float[] queryVector = embeddingService.embed(query);
        
        // 2. 在向量数据库中检索最相似的向量
        List<KnowledgeChunk> chunks = vectorRepository.search(queryVector, topK);
        
        return chunks;
    }
}

3.3 内容审核机制

为了确保AI回答的安全性,我们实现了内容审核:

@Service
public class ContentAuditServiceImpl implements ContentAuditService {

    @Override
    public String audit(String content) {
        // 1. 敏感词检测
        if (containsSensitiveWords(content)) {
            return "内容包含敏感词,请修改后重试";
        }
        
        // 2. 违规内容检测
        if (containsIllegalContent(content)) {
            return "内容涉及违规信息,已被拒绝";
        }
        
        // 3. 调用AI审核
        return llmService.audit(content);
    }
}

四、技术挑战与解决方案

4.1 挑战1:向量检索的精度问题

问题描述:
在早期测试中,我们发现向量检索的精度不够高。比如学生问"如何配置Spring Boot的数据库连接?“,检索结果可能包含"Spring Boot配置”、"数据库连接池"等内容,但不包含具体的配置步骤。

解决方案:混合检索策略

public List<KnowledgeChunk> retrieveContext(String question, int topK) {
    // 1. 关键词检索(BM25算法)
    List<KnowledgeChunk> keywordResults = keywordSearch(question, topK / 2);
    
    // 2. 语义检索(向量相似度)
    List<KnowledgeChunk> semanticResults = vectorSearch(question, topK / 2);
    
    // 3. 融合结果(去重、排序)
    return mergeAndRerank(keywordResults, semanticResults, topK);
}

效果对比:

检索策略准确率平均响应时间
纯向量检索65%800ms
混合检索82%600ms

4.2 挑战2:提示词工程

问题描述:
最初我们使用简单的提示词:“请回答以下问题”。但AI的回答往往不够结构化,学生需要追问才能得到完整答案。

解决方案:结构化提示词模板

@Data
@TableName("prompt_template")
public class PromptTemplate {
    private String code;           // 模板代码
    private String name;           // 模板名称
    private String content;         // 模板内容
    private List<String> variables; // 可替换变量
    
    // 模板示例
    // 你是在线课程答疑助手,请根据给定的课程知识回答学生问题,回答使用中文。
    // 【课程知识】:\n{{context}}\n\n【问题】:\n{{question}}\n\n请给出清晰分点回答。
}

提示词优化技巧:

  1. 明确角色定位:告诉AI它是什么角色(课程答疑助手)
  2. 提供上下文:明确告诉AI知识库内容是什么
  3. 要求格式:要求AI给出清晰分点回答
  4. 限制范围:要求AI只基于知识库内容回答,不要胡编

4.3 挑战3:并发性能问题

问题描述:
在高峰期(比如晚上8-10点),大量学生同时提问,AI服务的响应时间明显变慢,甚至出现超时。

解决方案:多级缓存策略

@Service
public class LlmServiceImpl implements LlmService {

    private final CacheManager cacheManager;
    
    @Override
    public Mono<String> chat(String prompt) {
        // 1. 生成缓存key
        String cacheKey = "llm:chat:" + DigestUtils.md5Hex(prompt);
        
        // 2. 尝试从缓存获取
        String cached = cacheManager.get(cacheKey);
        if (cached != null) {
            return Mono.just(cached);
        }
        
        // 3. 缓存未命中,调用AI
        return webClient.post()
                .bodyValue(body)
                .retrieve()
                .bodyToMono(String.class)
                .cache(cacheKey, Duration.ofMinutes(30));  // 缓存30分钟
    }
}

性能优化效果:

优化措施缓存命中率平均响应时间
无缓存0%1200ms
L1缓存45%400ms
L2缓存75%150ms

五、实际效果与数据

5.1 使用数据统计

上线一个月后,我们统计了AI服务的使用数据:

指标数值说明
总提问次数156,789次学生提问热情高
平均响应时间380ms性能表现良好
准确率(人工抽检)82%RAG架构效果显著
学生满意度4.2/5.0满意度高
成本(token消耗)降低50%知识库检索优化

5.2 学生反馈

我们收集了学生的真实反馈:

正面反馈:

  • “AI回答很专业,比论坛回复快多了!”
  • “24小时在线,再也不用等老师回复了!”
  • “基于课程知识库,回答很准确!”
  • “分点清晰,学习效率提升!”

负面反馈:

  • “有时候回答不够深入,需要追问”
  • “对于新课程,AI回答不够准确”
  • “希望能支持语音提问”

改进措施:

  1. 增加知识库内容的深度和广度
  2. 优化提示词模板,提高回答的针对性
  3. 引入多模态支持(文本、语音、图片)
  4. 增加AI对话历史记录,支持上下文理解

六、未来规划

6.1 短期优化(1-3个月)

1. 多轮对话支持

@Data
public class ChatSession {
    private String sessionId;
    private Long userId;
    private List<ChatMessage> messages;  // 对话历史
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
}

2. 个性化推荐
基于学生的学习行为,推荐相关课程、知识点:

  • 学习历史分析
  • 错题记录分析
  • 学习时长统计
  • 个性化知识库推送

3. 实时流式输出
让学生看到AI"思考"的过程,提升交互体验:

  • 逐步展示AI的回答
  • 支持中断和重新生成
  • 展示引用的知识库来源

6.2 长期规划(3-6个月)

1. 知识图谱构建
将知识库中的知识点构建成知识图谱,实现:

  • 知识点关联
  • 推理能力
  • 多跳问答

2. 多模态AI
支持更多交互方式:

  • 语音问答
  • 图片识别
  • 代码生成
  • 视频讲解

3. AI助教系统
打造更智能的学习助手:

  • 主动学习提醒
  • 作业批改
  • 学习进度跟踪
  • 个性化学习路径推荐

七、技术总结

7.1 核心技术栈

技术组件版本用途
Spring Boot3.2.0基础框架
Spring WebFlux3.2.0响应式编程
阿里云DashScope通义千问大语言模型
Redis7.0缓存和会话管理
向量数据库Milvus知识库向量存储
Elasticsearch8.11.0全文检索

7.2 关键代码示例

1. LLM配置类

@Data
@Configuration
@ConfigurationProperties(prefix = "ai.dashscope")
public class LlmConfig {
    private String apiKey;      // API密钥
    private String model;        // 模型名称(qwen-plus)
}

2. 知识库检索服务

@Service
public class KnowledgeBaseServiceImpl implements KnowledgeBaseService {

    @Override
    public List<String> retrieveContext(String question, int topK) {
        // 1. 向量化查询
        float[] queryVector = embeddingService.embed(question);
        
        // 2. 向量检索
        List<KnowledgeChunk> chunks = vectorStoreService.search(queryVector, topK);
        
        // 3. 提取文本内容
        return chunks.stream()
                .map(KnowledgeChunk::getContent)
                .collect(Collectors.toList());
    }
}

3. AI对话服务

@Service
public class LlmServiceImpl implements LlmService {

    private Mono<String> chat(String prompt) {
        Map<String, Object> body = Map.of(
            "model", config.getModel(),
            "input", Map.of("messages", new Object[]{
                Map.of("role", "user", "content", prompt)
            })
        );
        
        return webClient.post()
                .bodyValue(body)
                .retrieve()
                .bodyToMono(String.class)
                .map(this::extractContentSafely);
    }
}

八、心得体会

8.1 技术选型的重要性

在开发AI服务的过程中,我深刻体会到技术选型的重要性:

教训1:不要盲目追求最新技术

  • 通义千问模型更新很快,但稳定性和成本更重要
  • 我们选择了成熟稳定的DashScope,而不是最新的模型
  • 这保证了服务的稳定性和成本可控

教训2:架构设计要考虑扩展性

  • RAG架构虽然增加了复杂度,但带来了巨大的价值
  • 知识库可以独立更新,不影响AI服务
  • 为未来引入多模态、知识图谱等打下了基础

8.2 用户体验至上

核心原则:

  1. 响应速度:AI回答必须在3秒内返回
  2. 准确性:基于知识库的准确率要达到80%以上
  3. 可用性:服务可用性要达到99.9%以上
  4. 安全性:严格的内容审核,确保回答安全合规

8.3 持续优化的必要性

AI技术发展迅速,我们需要持续优化:

  • 定期更新知识库内容
  • 优化向量检索算法
  • 调整提示词模板
  • 收集用户反馈,不断改进

8.4 实战经验与最佳实践

经验1:知识库质量决定AI回答质量

  • 知识库内容必须经过人工审核和结构化处理
  • 每个知识块控制在500-1000字符,避免过长或过短
  • 定期清理过期或错误的知识内容
  • 建立知识库版本管理机制

经验2:提示词工程需要反复打磨

  • 不要使用一次性提示词,要建立模板库
  • 提示词要包含:角色定位、任务描述、输出格式、约束条件
  • 通过A/B测试验证不同提示词的效果
  • 记录每次提示词优化的效果数据

经验3:监控和日志至关重要

  • 记录每次AI调用的输入、输出、耗时、token消耗
  • 建立异常报警机制(如响应时间超过3秒)
  • 定期分析日志,发现潜在问题
  • 保存用户反馈与对应回答,用于后续优化

经验4:渐进式上线策略

  • 先在小范围用户中测试(如10%用户)
  • 收集反馈并快速迭代
  • 逐步扩大使用范围
  • 始终保留人工审核通道

经验5:成本控制技巧

  • 合理设置上下文窗口大小
  • 使用缓存减少重复调用
  • 对简单问题使用小模型,复杂问题使用大模型
  • 定期清理无用的对话历史

九、总结

AI智能服务的实现,是智学云平台从"传统在线教育"向"智能教育"转型的重要里程碑。通过引入RAG架构,我们成功解决了传统在线教育平台的痛点:

✅ 解决了什么问题:

  1. 学生提问无人回复 → AI 24小时在线答疑
  2. 回答质量参差不齐 → 基于知识库的精准回答
  3. 响应速度慢 → 平均380ms的快速响应
  4. 成本高昂 → 知识库检索降低50%成本

🎯 核心价值:

  • 让每个学生都配了一位"私人助教"
  • 24小时在线,随时随地答疑
  • 基于课程知识,专业准确回答
  • 提升学习效率,降低学习成本

📈 下一步计划:

  • 支持多轮对话,理解上下文
  • 引入语音问答,提升交互体验
  • 构建知识图谱,实现推理能力
  • 打造AI助教系统,主动服务学生

智学云开发日记系列文章持续更新中,敬请关注!

下一篇预告: 📡 智学云开发日记(五):实时互动服务的实现与思考

#AI智能服务 #RAG架构 #知识库检索 #大语言模型 #在线教育 #技术分享

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐