基于Ollama与Milvus的Java版RAG知识库搭建指南

📅 2026/8/18 23:22:54
基于Ollama与Milvus的Java版RAG知识库搭建指南
1. 项目概述最近在本地搭建了一个基于Ollama和Milvus的RAG知识库助手整个过程踩了不少坑也积累了一些经验。这个方案特别适合需要私有化部署的企业或个人开发者既能保证数据安全又能利用大语言模型的能力。下面我就把完整的搭建过程分享给大家重点会讲Java环境下的快速实现方案。RAGRetrieval-Augmented Generation技术这两年越来越火它通过结合检索和生成两大能力能显著提升问答系统的准确性和专业性。我们这次用的Ollama负责本地大模型推理Milvus处理向量检索再用Spring Boot把它们整合起来最终效果相当不错。2. 环境准备与工具选型2.1 硬件配置建议实测下来这个方案对硬件要求不算太高CPU至少4核推荐8核以上内存16GB起步处理中文建议32GB显卡非必须有NVIDIA显卡可加速推理存储至少50GB可用空间模型文件较大注意Milvus对内存比较敏感如果遇到OOM错误建议先检查内存分配2.2 软件依赖安装先确保系统已安装Docker建议20.10版本JDK 17必须匹配Spring Boot 3.xMaven 3.6Python 3.8仅用于调试脚本验证Java环境java -version mvn -v2.3 Ollama安装与配置国内用户建议使用镜像源加速下载# 使用国内镜像安装 curl -fsSL https://ollama.mirror.xyz/install.sh | sh # 启动服务 ollama serve 下载中文模型以qwen为例ollama pull qwen:7b如果下载速度慢可以尝试设置镜像代理使用离线包手动导入选择较小的模型版本3. Milvus向量数据库部署3.1 Docker方式安装推荐使用官方docker-compose方案version: 3.5 services: etcd: container_name: milvus-etcd image: quay.io/coreos/etcd:v3.5.5 environment: - ETCD_AUTO_COMPACTION_MODErevision - ETCD_AUTO_COMPACTION_RETENTION1000 - ETCD_QUOTA_BACKEND_BYTES4294967296 volumes: - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/etcd:/etcd command: etcd -advertise-client-urlshttp://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd minio: container_name: milvus-minio image: minio/minio:RELEASE.2023-03-20T20-16-18Z environment: MINIO_ACCESS_KEY: minioadmin MINIO_SECRET_KEY: minioadmin volumes: - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/minio:/minio_data command: minio server /minio_data healthcheck: test: [CMD, curl, -f, http://localhost:9000/minio/health/live] interval: 30s timeout: 20s retries: 3 standalone: container_name: milvus-standalone image: milvusdb/milvus:v2.3.3 command: [milvus, run, standalone] environment: ETCD_ENDPOINTS: etcd:2379 MINIO_ADDRESS: minio:9000 volumes: - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus ports: - 19530:19530 - 9091:9091 depends_on: - etcd - minio启动命令docker-compose up -d3.2 关键配置调优在milvus.yaml中建议修改common: retryTimes: 5 retryInterval: 500ms queryNode: gracefulTime: 5000 schedulerInterval: 10004. Java项目搭建4.1 Spring Boot初始化使用start.spring.io生成基础项目添加依赖dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Milvus Java SDK -- dependency groupIdio.milvus/groupId artifactIdmilvus-sdk-java/artifactId version2.3.3/version /dependency !-- Ollama HTTP Client -- dependency groupIdorg.apache.httpcomponents/groupId artifactIdhttpclient/artifactId version4.5.13/version /dependency /dependencies4.2 核心组件实现4.2.1 向量服务封装Service public class VectorService { private final MilvusServiceClient client; public VectorService() { ConnectParam connectParam ConnectParam.builder() .withHost(localhost) .withPort(19530) .build(); this.client new MilvusServiceClient(connectParam); } public ListLong insertEmbeddings(ListListFloat vectors) { // 实现向量插入逻辑 } public ListSearchResult searchSimilar(ListFloat queryVector, int topK) { // 实现向量搜索 } }4.2.2 Ollama交互模块Component public class LLMService { private static final String OLLAMA_URL http://localhost:11434; public String generateResponse(String prompt) throws IOException { HttpPost httpPost new HttpPost(OLLAMA_URL /api/generate); httpPost.setHeader(Content-Type, application/json); StringEntity entity new StringEntity( String.format({\model\:\qwen:7b\,\prompt\:\%s\}, prompt), StandardCharsets.UTF_8 ); httpPost.setEntity(entity); try (CloseableHttpClient httpClient HttpClients.createDefault(); CloseableHttpResponse response httpClient.execute(httpPost)) { return EntityUtils.toString(response.getEntity()); } } }5. RAG流程实现5.1 知识库构建流程文档预处理public ListString chunkDocuments(File document) { // 实现文档分块 // 建议块大小500-1000字符 // 添加重叠区域overlap提升检索效果 }文本向量化public ListFloat getEmbedding(String text) { // 调用Ollama的embedding接口 // 或使用本地sentence-transformers }向量入库public void buildKnowledgeBase(ListFile documents) { documents.forEach(doc - { ListString chunks chunkDocuments(doc); ListListFloat embeddings chunks.stream() .map(this::getEmbedding) .collect(Collectors.toList()); vectorService.insertEmbeddings(embeddings); }); }5.2 问答流程实现RestController RequestMapping(/api/rag) public class RAGController { PostMapping(/query) public String handleQuery(RequestBody String question) { // 1. 获取问题向量 ListFloat queryVec embeddingService.getEmbedding(question); // 2. 向量检索 ListSearchResult results vectorService.searchSimilar(queryVec, 3); // 3. 构建prompt String context results.stream() .map(SearchResult::getText) .collect(Collectors.joining(\n\n)); String prompt String.format( 基于以下上下文回答问题\n%s\n\n问题%s, context, question ); // 4. 生成回答 return llmService.generateResponse(prompt); } }6. 性能优化技巧6.1 Milvus查询优化索引选择IndexType indexType IndexType.IVF_FLAT; String indexParam {\nlist\:1024}; client.createIndex(collectionName, vector, indexType, indexParam);搜索参数调优SearchParam searchParam SearchParam.newBuilder() .withCollectionName(collectionName) .withMetricType(MetricType.L2) .withTopK(5) .withVectors(vectors) .withParams({\nprobe\:64}) .build();6.2 Ollama推理加速量化模型ollama pull qwen:7b-q4_0批处理请求// 合并多个问题一次性处理 ListString batchResults llmService.batchGenerate(questions);上下文缓存Cacheable(value ragCache, key #question.hashCode()) public String cachedQuery(String question) { return handleQuery(question); }7. 常见问题排查7.1 内存不足问题症状Java进程崩溃报OOM错误解决方案调整JVM参数export JAVA_OPTS-Xmx8g -Xms4g减少并发请求数使用更小的模型版本7.2 向量检索不准可能原因embedding模型不匹配向量维度不一致相似度度量设置错误检查步骤// 验证向量维度 int dim client.getCollectionStatistics(collectionName).getDimension();7.3 Ollama响应慢优化方案使用--numa参数绑定CPUollama serve --numa启用GPU加速如有降低temperature参数8. 进阶扩展方向多模态支持接入图像/音频embedding扩展Milvus schema支持混合检索对话历史管理public class ConversationManager { private DequeString history new ArrayDeque(10); public void addExchange(String question, String answer) { history.offerLast(question); history.offerLast(answer); if(history.size() 20) { history.removeFirst(); history.removeFirst(); } } }自动化知识更新监控文件系统变化增量更新向量库Scheduled(fixedRate 3600000) public void autoRefreshKnowledgeBase() { // 检查文档变更并更新 }这个方案我在多个项目中实际使用过最大的优势是全部组件都可以本地化部署特别适合对数据隐私要求高的场景。最开始搭建可能会遇到各种环境问题建议先按文档一步步验证每个组件是否正常工作再尝试集成。