配置要求高配台式机即可1、32G内存 1T硬盘主流CPU要求8G显卡正常市场价格1万元左右的台式机2、Windows系统64位最好在当今企业信息化建设中知识管理已成为核心竞争力的一部分。然而许多企业面临数据安全、网络限制等挑战使得在线大模型方案难以落地。本文将介绍一套完全离线的企业知识库问答系统结合向量化检索RAG与语音交互技术实现安全、高效、自然的问答体验。一、系统架构概览本系统的核心架构包含四大模块┌─────────────────────────────────────────────────────────┐ │ 用户交互层 │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 语音唤醒 │→│ 语音听写 │→│ 语音合成 │ │ │ └──────────┘ └──────────┘ └──────────┘ │ └─────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────┐ │ 智能处理层 │ │ ┌──────────────────────────────────────────────────┐ │ │ │ RAG向量化检索 本地大模型 │ │ │ └──────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────┐ │ 数据存储层 │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 知识库 │ │ 对话历史 │ │ 配置文件 │ │ │ └──────────┘ └──────────┘ └──────────┘ │ └─────────────────────────────────────────────────────────┘技术选型模块技术方案说明语音唤醒讯飞IVW离线唤醒支持自定义唤醒词语音听写Vosk离线识别中文模型16kHz采样语音合成讯飞TTS离线合成实时流式播放大语言模型Ollama DeepSeek本地部署完全离线向量检索自定义RAG实现基于TF-IDF 余弦相似度二、核心实现详解2.1 离线语音唤醒模块语音唤醒是交互的第一步系统通过讯飞IVW模块监听麦克风检测预设唤醒词“小甲小甲”。public static void startIvw() { // 1. 登录唤醒服务 Integer ret IvwService.INSTANCE.MSPLogin(null, null, Constants.IVW_LOGIN_PARAMS); // 2. 开启唤醒会话 String sessionId IvwService.INSTANCE.QIVWSessionBegin(null, Constants.IVW_SSB_PARAMS, Constants.IVW_ERROR_CODE); // 3. 注册回调函数 ret IvwService.INSTANCE.QIVWRegisterNotify(sessionId, new IvwCallback(), null); // 4. 循环读取麦克风音频并写入 while (true) { byte[] audioDataByteArray new byte[Constants.IVW_FRAME_SIZE]; int len new AudioInputStream(Constants.IVW_ASR_TARGET_DATA_LINE).read(audioDataByteArray); ret IvwService.INSTANCE.QIVWAudioWrite(sessionId, audioDataByteArray, len, Constants.IVW_AUDIO_STATUS); Thread.sleep(200); // 每200ms写入一帧 } }关键点音频帧大小需与模型匹配通常16k采样20ms帧长使用回调机制异步处理唤醒事件2.2 离线语音听写ASR唤醒后系统启动Vosk识别器将语音转换为文字public static void startIat() { // 初始化Vosk模型中文模型约1GB model new Model(src/main/resources/vosk-model-cn-0.22); recognizer new Recognizer(model, 16000); while (true) { bytesRead Constants.IVW_ASR_TARGET_DATA_LINE.read(buffer, 0, buffer.length); if (recognizer.acceptWaveForm(buffer, bytesRead)) { // 获取最终识别结果 JsonParseFinal result gson.fromJson(recognizer.getFinalResult(), JsonParseFinal.class); startModel(result.text); // 调用大模型处理 break; } } }2.3 向量化检索RAG这是系统的核心亮点。在调用大模型前系统先从知识库中检索相关内容// 1. 读取知识库文件支持txt、pdf等 ListString inputContentList ReadFiles.readFilesWork(src/main/resources/word_files/); // 2. 向量化检索相关片段 String knowledge Rag.ragWork( inputContentList, // 知识库内容 mySettings.getMax(), // 最大返回片段数 userQuestion, // 用户问题 mySettings.getTop(), // 检索TopK mySettings.getSimilarity() // 相似度阈值 ); // 3. 构造增强提示词 String prompt 根据已知知识答复我的问题。如果问题和已知知识无关忽略已知知识直接答复问题。 我的问题是【 userQuestion 】\n 已知知识 knowledge;RAG检索算法实现Rag.javapublic class Rag { // TF-IDF向量化 public static MapString, Double computeTFIDF(ListString documents) { // 计算词频和逆文档频率 // 返回特征向量 } // 余弦相似度计算 public static double cosineSimilarity(MapString, Double vec1, MapString, Double vec2) { double dotProduct 0.0; double norm1 0.0; double norm2 0.0; // 计算向量夹角余弦值 return dotProduct / (norm1 * norm2); } // 主检索逻辑 public static String ragWork(ListString documents, int maxReturn, String query, int topK, double threshold) { // 1. 对文档分块 // 2. 计算每个块的向量 // 3. 计算问题向量与各块的相似度 // 4. 返回TopK相关片段 } }2.4 离线大模型调用系统通过Ollama调用本地部署的DeepSeek模型public static void startModel(String userQuestion) throws Exception { // 1. 读取配置和对话历史 Settings mySettings gson.fromJson(settings, Settings.class); ListModelHistory modelHistoryList loadHistory(); // 2. 构建请求支持上下文 JSONArray messages new JSONArray(); if (mySettings.getContext() modelHistoryList ! null) { for (ModelHistory temp : modelHistoryList) { messages.put(new JSONObject() .put(role, temp.getRole()) .put(content, temp.getContent())); } } // 3. 添加RAG检索的知识 messages.put(new JSONObject() .put(role, user) .put(content, enhancedPrompt)); // 4. 流式调用Ollama API Request request new Request.Builder() .url(http://localhost:11434/v1/chat/completions) .post(body) .build(); // 5. 处理流式响应 while ((line responseBody.source().readUtf8Line()) ! null) { if (line.contains(data: ) !line.contains([DONE])) { // 解析并实时合成语音 AIMain.startTts(tempRes); } } }2.5 实时语音合成TTS采用流式合成策略边生成边播放public static void startTts(String ttsText) { // 1. 开启会话 String session_id TtsService.INSTANCE.QTTSSessionBegin(params, errorCode); // 2. 放入待合成文本 TtsService.INSTANCE.QTTSTextPut(session_id, ttsText, ttsText.length(), null); // 3. 循环获取音频并实时播放 while (true) { Pointer audioPointer TtsService.INSTANCE.QTTSAudioGet(session_id, audioLen, status, errorCode); byte[] audioData audioPointer.getByteArray(0, audioLen.getValue()); Constants.TTS_SOURCE_DATA_LINE.write(audioData, 0, audioLen.getValue()); if (status.getValue() 2) { // 音频取完 break; } } }2.6 打断功能实现为了提升用户体验系统支持语音播报打断new Thread(() - { Scanner scanner new Scanner(System.in); while (true) { String input scanner.nextLine(); if (input.isEmpty()) { // 回车打断 STOP_FLAG true; break; } } }).start(); // 在TTS播放时检查打断标志 if (!STOP_FLAG) { Constants.TTS_SOURCE_DATA_LINE.write(audioDataByteArray, 0, length); }三、配置文件设计Settings.json{ model: deepseek-v2:16b, context: true, clear: false, max: 5, top: 3, similarity: 0.6 }参数说明modelOllama模型名称context是否启用对话上下文clear是否清空历史记录max最大检索文档数topTopK检索数量similarity相似度阈值四、系统部署指南4.1 环境要求JDK 11内存 ≥ 8GB推荐16GB操作系统Windows/Linux/macOS4.2 安装步骤# 1. 安装Ollama curl -fsSL https://ollama.com/install.sh | sh # 2. 下载DeepSeek模型 ollama pull deepseek-v2:16b # 3. 下载Vosk中文模型 wget https://alphacephei.com/vosk/models/vosk-model-cn-0.22.zip unzip vosk-model-cn-0.22.zip -d src/main/resources/ # 4. 配置讯飞SDK # 将libmsc32.so/msc.dll放入项目资源目录 # 5. 准备知识库 # 将文档放入 src/main/resources/word_files/4.3 运行mvn clean compile mvn exec:java -Dexec.mainClasscom.day.AIMain五、性能优化建议5.1 检索优化分块策略建议按段落分块每块200-500字缓存机制对常见问题的检索结果进行缓存索引预建启动时预计算知识库向量5.2 语音交互优化音频缓冲使用双缓冲减少播放延迟唤醒阈值根据环境调整唤醒灵敏度打断响应降低音频帧读取延迟5.3 大模型优化量化部署使用INT8量化减少显存占用并发控制限制同时处理的请求数流式输出减少首字延迟六、应用场景场景应用方式企业内部培训员工语音查询产品知识、流程规范智能客服离线部署保障数据安全教育辅导中学生学科问题解答医疗辅助病历知识库查询七、总结本文实现的企业知识库离线问答系统具有以下优势数据安全完全离线部署杜绝数据泄露风险成本可控无需支付API调用费用交互自然全语音交互支持打断知识精准RAG检索确保答案有据可依