企业解决方案十-企业知识库离线问答带知识检索与语音问答
配置要求:
高配台式机即可
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等)
List<String> 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.java)
public class Rag {
// TF-IDF向量化
public static Map<String, Double> computeTFIDF(List<String> documents) {
// 计算词频和逆文档频率
// 返回特征向量
}
// 余弦相似度计算
public static double cosineSimilarity(Map<String, Double> vec1, Map<String, Double> vec2) {
double dotProduct = 0.0;
double norm1 = 0.0;
double norm2 = 0.0;
// 计算向量夹角余弦值
return dotProduct / (norm1 * norm2);
}
// 主检索逻辑
public static String ragWork(List<String> 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);
List<ModelHistory> 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
}
| 参数 | 说明 |
|---|---|
| model | Ollama模型名称 |
| context | 是否启用对话上下文 |
| clear | 是否清空历史记录 |
| max | 最大检索文档数 |
| top | TopK检索数量 |
| similarity | 相似度阈值 |
四、系统部署指南
4.1 环境要求
-
JDK 11+
-
内存 ≥ 8GB(推荐16GB)
-
操作系统:Windows/Linux/macOS
4.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.mainClass="com.day.AIMain"
五、性能优化建议
5.1 检索优化
-
分块策略:建议按段落分块,每块200-500字
-
缓存机制:对常见问题的检索结果进行缓存
-
索引预建:启动时预计算知识库向量
5.2 语音交互优化
-
音频缓冲:使用双缓冲减少播放延迟
-
唤醒阈值:根据环境调整唤醒灵敏度
-
打断响应:降低音频帧读取延迟
5.3 大模型优化
-
量化部署:使用INT8量化减少显存占用
-
并发控制:限制同时处理的请求数
-
流式输出:减少首字延迟
六、应用场景
| 场景 | 应用方式 |
|---|---|
| 企业内部培训 | 员工语音查询产品知识、流程规范 |
| 智能客服 | 离线部署,保障数据安全 |
| 教育辅导 | 中学生学科问题解答 |
| 医疗辅助 | 病历知识库查询 |
七、总结
本文实现的企业知识库离线问答系统具有以下优势:
-
数据安全:完全离线部署,杜绝数据泄露风险
-
成本可控:无需支付API调用费用
-
交互自然:全语音交互,支持打断
-
知识精准:RAG检索确保答案有据可依
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)