EmbeddingGemma-300m与SpringBoot集成构建企业级语义服务API最近在做一个内部知识库项目需要给文档做语义搜索。试了几个开源嵌入模型要么太大部署麻烦要么效果不太理想。直到发现了EmbeddingGemma-300m这个300M参数的小模型效果居然相当不错而且特别适合集成到现有的Java技术栈里。今天就跟大家分享一下怎么把EmbeddingGemma-300m集成到SpringBoot框架里搭建一个企业级的语义服务API。整个过程不复杂但有几个关键点需要注意我会把踩过的坑都告诉你。1. 为什么选择EmbeddingGemma-300m先说说为什么选这个模型。我们团队之前用过一些更大的嵌入模型比如BGE-M3567M参数效果确实好但部署成本高响应速度也慢。后来看到Google新出的EmbeddingGemma300M参数专门为资源有限的环境设计就决定试试。用下来发现几个优点模型小只有300M参数本地部署毫无压力多语言支持训练数据覆盖100多种语言对我们这种有国际化需求的项目很友好输出灵活默认768维向量但可以通过MRL技术降到512、256或128维根据实际需求调整部署简单通过Ollama管理一条命令就能跑起来最让我惊喜的是在语义相似度任务上它的表现跟那些大模型差距不大但推理速度快了不少。对于我们这种需要实时响应的应用场景这个优势太重要了。2. 环境准备与Ollama部署开始之前你需要准备好这些环境2.1 安装OllamaOllama是管理本地大模型的工具安装特别简单。去官网下载对应系统的安装包或者用命令行安装# Linux/macOS安装 curl -fsSL https://ollama.com/install.sh | sh # Windows直接下载安装包安装完成后启动Ollama服务# 启动服务 ollama serve服务默认运行在11434端口你可以用浏览器打开http://localhost:11434看看是否正常。2.2 拉取EmbeddingGemma模型模型部署就一句话的事ollama pull embeddinggemma:300m这个命令会下载300M参数的EmbeddingGemma模型。第一次下载可能需要几分钟取决于你的网络速度。下载完成后你可以用下面的命令测试一下curl http://localhost:11434/api/embed \ -d { model: embeddinggemma:300m, input: 为什么天空是蓝色的 }如果返回一个768维的向量数组说明模型部署成功了。2.3 SpringBoot项目初始化用Spring Initializr创建一个新项目选择这些依赖Spring Web提供REST API支持Spring Boot DevTools开发工具Lombok简化代码Spring Configuration Processor配置处理Maven的pom.xml关键依赖dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies3. 项目结构设计好的项目结构能让后续开发维护轻松很多。我设计的结构是这样的src/main/java/com/example/embeddingservice/ ├── config/ # 配置类 ├── controller/ # 控制器层 ├── service/ # 服务层 ├── client/ # HTTP客户端 ├── dto/ # 数据传输对象 └── EmbeddingServiceApplication.java每个目录的作用config放Spring配置类比如HTTP客户端配置、线程池配置controller定义REST API接口service业务逻辑调用Ollama APIclient封装对Ollama的HTTP调用dto请求和响应的数据模型4. 核心代码实现4.1 定义数据模型先定义几个基础的数据类用来封装请求和响应// EmbeddingRequest.java - 嵌入请求 Data AllArgsConstructor NoArgsConstructor public class EmbeddingRequest { private String model embeddinggemma:300m; private ListString input; // 单文本构造方法 public EmbeddingRequest(String text) { this.input Collections.singletonList(text); } // 多文本构造方法 public EmbeddingRequest(ListString texts) { this.input texts; } } // EmbeddingResponse.java - 嵌入响应 Data public class EmbeddingResponse { private String model; private ListListFloat embeddings; private Long totalDuration; } // SimilarityRequest.java - 相似度计算请求 Data public class SimilarityRequest { private String text1; private String text2; } // SimilarityResponse.java - 相似度计算结果 Data public class SimilarityResponse { private Float similarity; private Long duration; }4.2 封装Ollama客户端接下来封装一个HTTP客户端专门调用Ollama的API// OllamaClient.java Component Slf4j public class OllamaClient { private final RestTemplate restTemplate; private final String ollamaUrl; public OllamaClient(Value(${ollama.url:http://localhost:11434}) String ollamaUrl) { this.ollamaUrl ollamaUrl; this.restTemplate new RestTemplate(); // 设置连接超时和读取超时 SimpleClientHttpRequestFactory factory new SimpleClientHttpRequestFactory(); factory.setConnectTimeout(5000); // 5秒连接超时 factory.setReadTimeout(30000); // 30秒读取超时 restTemplate.setRequestFactory(factory); } public ListListFloat getEmbeddings(ListString texts) { String url ollamaUrl /api/embed; EmbeddingRequest request new EmbeddingRequest(texts); try { long startTime System.currentTimeMillis(); HttpHeaders headers new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntityEmbeddingRequest entity new HttpEntity(request, headers); ResponseEntityEmbeddingResponse response restTemplate.exchange( url, HttpMethod.POST, entity, EmbeddingResponse.class); long endTime System.currentTimeMillis(); log.info(嵌入请求完成文本数量{}耗时{}ms, texts.size(), endTime - startTime); return response.getBody().getEmbeddings(); } catch (Exception e) { log.error(调用Ollama API失败, e); throw new RuntimeException(嵌入服务调用失败, e); } } public ListFloat getEmbedding(String text) { ListListFloat embeddings getEmbeddings(Collections.singletonList(text)); return embeddings.get(0); } }4.3 实现业务服务层服务层负责具体的业务逻辑比如计算相似度// EmbeddingService.java Service Slf4j public class EmbeddingService { private final OllamaClient ollamaClient; public EmbeddingService(OllamaClient ollamaClient) { this.ollamaClient ollamaClient; } // 获取单个文本的嵌入向量 public ListFloat embedText(String text) { log.debug(开始嵌入文本{}, text.substring(0, Math.min(text.length(), 50)) ...); return ollamaClient.getEmbedding(text); } // 批量获取嵌入向量 public ListListFloat embedTexts(ListString texts) { log.debug(开始批量嵌入文本数量{}, texts.size()); return ollamaClient.getEmbeddings(texts); } // 计算两个文本的余弦相似度 public float calculateSimilarity(String text1, String text2) { long startTime System.currentTimeMillis(); // 获取两个文本的嵌入向量 ListFloat embedding1 embedText(text1); ListFloat embedding2 embedText(text2); // 计算余弦相似度 float similarity cosineSimilarity(embedding1, embedding2); long endTime System.currentTimeMillis(); log.info(相似度计算完成文本1{}文本2{}相似度{}耗时{}ms, text1.substring(0, Math.min(text1.length(), 30)), text2.substring(0, Math.min(text2.length(), 30)), similarity, endTime - startTime); return similarity; } // 计算余弦相似度的辅助方法 private float cosineSimilarity(ListFloat vec1, ListFloat vec2) { if (vec1.size() ! vec2.size()) { throw new IllegalArgumentException(向量维度不一致); } float dotProduct 0.0f; float norm1 0.0f; float norm2 0.0f; for (int i 0; i vec1.size(); i) { dotProduct vec1.get(i) * vec2.get(i); norm1 vec1.get(i) * vec1.get(i); norm2 vec2.get(i) * vec2.get(i); } if (norm1 0 || norm2 0) { return 0.0f; } return (float) (dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2))); } // 查找最相似的文本 public String findMostSimilar(String query, ListString candidates) { if (candidates null || candidates.isEmpty()) { return null; } // 批量获取所有候选文本的嵌入向量 ListListFloat candidateEmbeddings embedTexts(candidates); ListFloat queryEmbedding embedText(query); int mostSimilarIndex -1; float highestSimilarity -1.0f; // 计算每个候选文本与查询的相似度 for (int i 0; i candidateEmbeddings.size(); i) { float similarity cosineSimilarity(queryEmbedding, candidateEmbeddings.get(i)); if (similarity highestSimilarity) { highestSimilarity similarity; mostSimilarIndex i; } } return candidates.get(mostSimilarIndex); } }4.4 创建REST API控制器最后把这些功能通过REST API暴露出来// EmbeddingController.java RestController RequestMapping(/api/embedding) Slf4j public class EmbeddingController { private final EmbeddingService embeddingService; public EmbeddingController(EmbeddingService embeddingService) { this.embeddingService embeddingService; } PostMapping(/single) public ResponseEntityEmbeddingResponse embedSingle(RequestBody MapString, String request) { String text request.get(text); if (text null || text.trim().isEmpty()) { return ResponseEntity.badRequest().build(); } long startTime System.currentTimeMillis(); ListFloat embedding embeddingService.embedText(text); long endTime System.currentTimeMillis(); EmbeddingResponse response new EmbeddingResponse(); response.setModel(embeddinggemma:300m); response.setEmbeddings(Collections.singletonList(embedding)); response.setTotalDuration(endTime - startTime); return ResponseEntity.ok(response); } PostMapping(/batch) public ResponseEntityEmbeddingResponse embedBatch(RequestBody MapString, ListString request) { ListString texts request.get(texts); if (texts null || texts.isEmpty()) { return ResponseEntity.badRequest().build(); } long startTime System.currentTimeMillis(); ListListFloat embeddings embeddingService.embedTexts(texts); long endTime System.currentTimeMillis(); EmbeddingResponse response new EmbeddingResponse(); response.setModel(embeddinggemma:300m); response.setEmbeddings(embeddings); response.setTotalDuration(endTime - startTime); return ResponseEntity.ok(response); } PostMapping(/similarity) public ResponseEntitySimilarityResponse calculateSimilarity(RequestBody SimilarityRequest request) { if (request.getText1() null || request.getText2() null) { return ResponseEntity.badRequest().build(); } long startTime System.currentTimeMillis(); float similarity embeddingService.calculateSimilarity(request.getText1(), request.getText2()); long endTime System.currentTimeMillis(); SimilarityResponse response new SimilarityResponse(); response.setSimilarity(similarity); response.setDuration(endTime - startTime); return ResponseEntity.ok(response); } PostMapping(/search) public ResponseEntityMapString, Object searchSimilar(RequestBody MapString, Object request) { String query (String) request.get(query); SuppressWarnings(unchecked) ListString candidates (ListString) request.get(candidates); if (query null || candidates null || candidates.isEmpty()) { return ResponseEntity.badRequest().build(); } long startTime System.currentTimeMillis(); String mostSimilar embeddingService.findMostSimilar(query, candidates); long endTime System.currentTimeMillis(); MapString, Object response new HashMap(); response.put(query, query); response.put(mostSimilar, mostSimilar); response.put(duration, endTime - startTime); return ResponseEntity.ok(response); } GetMapping(/health) public ResponseEntityMapString, String healthCheck() { MapString, String response new HashMap(); response.put(status, UP); response.put(model, embeddinggemma:300m); response.put(timestamp, Instant.now().toString()); return ResponseEntity.ok(response); } }5. 配置优化与性能调优基础功能实现后还需要做一些优化让服务更稳定、性能更好。5.1 应用配置在application.yml中添加配置server: port: 8080 servlet: context-path: /embedding-service ollama: url: http://localhost:11434 spring: application: name: embedding-service logging: level: com.example.embeddingservice: DEBUG org.springframework.web: INFO5.2 添加异步处理对于批量处理请求使用异步可以提高吞吐量// AsyncEmbeddingService.java Service Slf4j public class AsyncEmbeddingService { private final EmbeddingService embeddingService; private final ExecutorService executorService; public AsyncEmbeddingService(EmbeddingService embeddingService) { this.embeddingService embeddingService; // 创建线程池根据CPU核心数调整 int corePoolSize Runtime.getRuntime().availableProcessors(); this.executorService Executors.newFixedThreadPool(corePoolSize); } public CompletableFutureListFloat embedTextAsync(String text) { return CompletableFuture.supplyAsync(() - embeddingService.embedText(text), executorService); } public CompletableFutureListListFloat embedTextsAsync(ListString texts) { return CompletableFuture.supplyAsync(() - embeddingService.embedTexts(texts), executorService); } public CompletableFutureFloat calculateSimilarityAsync(String text1, String text2) { return CompletableFuture.supplyAsync(() - embeddingService.calculateSimilarity(text1, text2), executorService); } PreDestroy public void shutdown() { executorService.shutdown(); try { if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) { executorService.shutdownNow(); } } catch (InterruptedException e) { executorService.shutdownNow(); Thread.currentThread().interrupt(); } } }5.3 添加缓存机制对于频繁查询的文本可以添加缓存减少重复计算// CachedEmbeddingService.java Service Slf4j public class CachedEmbeddingService { private final EmbeddingService embeddingService; private final CacheString, ListFloat embeddingCache; public CachedEmbeddingService(EmbeddingService embeddingService) { this.embeddingService embeddingService; // 使用Caffeine创建缓存 this.embeddingCache Caffeine.newBuilder() .maximumSize(1000) // 最多缓存1000个文本 .expireAfterWrite(1, TimeUnit.HOURS) // 1小时后过期 .recordStats() .build(); } public ListFloat getCachedEmbedding(String text) { return embeddingCache.get(text, key - { log.debug(缓存未命中计算文本嵌入{}, key.substring(0, Math.min(key.length(), 50))); return embeddingService.embedText(key); }); } public float calculateSimilarityWithCache(String text1, String text2) { ListFloat embedding1 getCachedEmbedding(text1); ListFloat embedding2 getCachedEmbedding(text2); // 计算余弦相似度 float dotProduct 0.0f; float norm1 0.0f; float norm2 0.0f; for (int i 0; i embedding1.size(); i) { dotProduct embedding1.get(i) * embedding2.get(i); norm1 embedding1.get(i) * embedding1.get(i); norm2 embedding2.get(i) * embedding2.get(i); } if (norm1 0 || norm2 0) { return 0.0f; } return (float) (dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2))); } public CacheStats getCacheStats() { return embeddingCache.stats(); } }6. 实际应用场景这个语义服务API搭建好后可以在很多场景下使用。我们团队主要用在下面几个地方6.1 智能客服问答匹配以前客服系统只能做关键词匹配用户问怎么退款和如何退货系统可能识别不出来这是同一个问题。现在用语义相似度准确率提升了很多。// 客服问题匹配示例 public class CustomerServiceMatcher { private final EmbeddingService embeddingService; private ListString faqQuestions; // 常见问题库 private ListListFloat faqEmbeddings; // 预计算的嵌入向量 public CustomerServiceMatcher(EmbeddingService embeddingService, ListString faqQuestions) { this.embeddingService embeddingService; this.faqQuestions faqQuestions; // 预计算所有FAQ的嵌入向量 this.faqEmbeddings embeddingService.embedTexts(faqQuestions); } public String findBestAnswer(String userQuestion) { ListFloat questionEmbedding embeddingService.embedText(userQuestion); int bestMatchIndex -1; float bestSimilarity 0.7f; // 设置相似度阈值 for (int i 0; i faqEmbeddings.size(); i) { float similarity calculateCosineSimilarity(questionEmbedding, faqEmbeddings.get(i)); if (similarity bestSimilarity) { bestSimilarity similarity; bestMatchIndex i; } } if (bestMatchIndex ! -1) { return 匹配到问题 faqQuestions.get(bestMatchIndex) 相似度 String.format(%.2f, bestSimilarity); } return 未找到匹配的问题请转人工客服; } }6.2 文档内容去重我们有个文档管理系统用户上传的文档经常有重复或高度相似的内容。用这个语义服务可以自动识别// 文档去重服务 Service public class DocumentDeduplicationService { private final EmbeddingService embeddingService; public DocumentDeduplicationService(EmbeddingService embeddingService) { this.embeddingService embeddingService; } public ListListString findDuplicateDocuments(ListDocument documents) { // 提取文档主要内容 ListString contents documents.stream() .map(Document::getContent) .limit(1000) // 限制长度 .collect(Collectors.toList()); // 批量计算嵌入向量 ListListFloat embeddings embeddingService.embedTexts(contents); // 找出相似度高的文档对 ListListString duplicates new ArrayList(); float similarityThreshold 0.85f; // 相似度阈值 for (int i 0; i embeddings.size(); i) { for (int j i 1; j embeddings.size(); j) { float similarity calculateCosineSimilarity(embeddings.get(i), embeddings.get(j)); if (similarity similarityThreshold) { duplicates.add(Arrays.asList( documents.get(i).getTitle(), documents.get(j).getTitle() )); } } } return duplicates; } }6.3 内容推荐系统根据用户浏览的内容推荐相似的文章或产品// 内容推荐服务 Service public class ContentRecommendationService { private final EmbeddingService embeddingService; private final MapString, ListFloat contentEmbeddings; // 内容ID到嵌入向量的映射 public ContentRecommendationService(EmbeddingService embeddingService) { this.embeddingService embeddingService; this.contentEmbeddings new ConcurrentHashMap(); } public void indexContent(String contentId, String content) { ListFloat embedding embeddingService.embedText(content); contentEmbeddings.put(contentId, embedding); } public ListString recommendSimilarContent(String referenceContentId, int topK) { ListFloat referenceEmbedding contentEmbeddings.get(referenceContentId); if (referenceEmbedding null) { return Collections.emptyList(); } // 计算与所有内容的相似度 ListContentScore scores new ArrayList(); for (Map.EntryString, ListFloat entry : contentEmbeddings.entrySet()) { if (!entry.getKey().equals(referenceContentId)) { float similarity calculateCosineSimilarity(referenceEmbedding, entry.getValue()); scores.add(new ContentScore(entry.getKey(), similarity)); } } // 按相似度排序返回topK return scores.stream() .sorted((a, b) - Float.compare(b.score, a.score)) .limit(topK) .map(score - score.contentId) .collect(Collectors.toList()); } private static class ContentScore { String contentId; float score; ContentScore(String contentId, float score) { this.contentId contentId; this.score score; } } }7. 部署与监控7.1 Docker容器化部署为了方便部署可以把整个服务打包成Docker镜像# Dockerfile FROM openjdk:11-jre-slim WORKDIR /app # 复制JAR文件 COPY target/embedding-service-*.jar app.jar # 创建非root用户 RUN useradd -m -u 1000 appuser USER appuser # 健康检查 HEALTHCHECK --interval30s --timeout3s --start-period5s --retries3 \ CMD curl -f http://localhost:8080/embedding-service/api/embedding/health || exit 1 EXPOSE 8080 ENTRYPOINT [java, -jar, app.jar]对应的docker-compose.ymlversion: 3.8 services: ollama: image: ollama/ollama:latest container_name: ollama ports: - 11434:11434 volumes: - ollama_data:/root/.ollama restart: unless-stopped embedding-service: build: . container_name: embedding-service ports: - 8080:8080 environment: - OLLAMA_URLhttp://ollama:11434 depends_on: - ollama restart: unless-stopped volumes: ollama_data:7.2 添加监控端点Spring Boot Actuator可以提供应用监控!-- pom.xml添加依赖 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-actuator/artifactId /dependency配置application.ymlmanagement: endpoints: web: exposure: include: health,info,metrics,prometheus metrics: export: prometheus: enabled: true endpoint: health: show-details: always7.3 性能监控添加自定义的监控指标// MetricsService.java Service public class MetricsService { private final MeterRegistry meterRegistry; private final Counter embeddingRequestsCounter; private final Timer embeddingTimer; public MetricsService(MeterRegistry meterRegistry) { this.meterRegistry meterRegistry; // 创建自定义指标 this.embeddingRequestsCounter Counter.builder(embedding.requests) .description(嵌入请求总数) .register(meterRegistry); this.embeddingTimer Timer.builder(embedding.duration) .description(嵌入处理耗时) .register(meterRegistry); } public void recordEmbeddingRequest(int textCount, long durationMs) { embeddingRequestsCounter.increment(); embeddingTimer.record(durationMs, TimeUnit.MILLISECONDS); // 记录文本数量分布 meterRegistry.summary(embedding.text.count) .record(textCount); } public MapString, Object getMetrics() { MapString, Object metrics new HashMap(); // 获取请求总数 metrics.put(totalRequests, embeddingRequestsCounter.count()); // 获取平均处理时间 metrics.put(avgDurationMs, embeddingTimer.mean(TimeUnit.MILLISECONDS)); return metrics; } }8. 遇到的问题和解决方案在实际使用中我们遇到了一些问题这里分享一下解决方案8.1 性能优化问题刚开始的时候发现批量处理速度不够快。通过分析发现两个问题Ollama API调用没有充分利用批量能力每次只发送一个文本HTTP连接没有复用每次请求都新建连接解决方案是使用Ollama的批量API一次发送多个文本配置HTTP连接池复用连接// 优化后的Ollama客户端配置 Configuration public class HttpClientConfig { Bean public RestTemplate restTemplate() { RestTemplate restTemplate new RestTemplate(); // 使用HttpComponentsClientHttpRequestFactory支持连接池 HttpComponentsClientHttpRequestFactory factory new HttpComponentsClientHttpRequestFactory(); // 配置连接池 PoolingHttpClientConnectionManager connectionManager new PoolingHttpClientConnectionManager(); connectionManager.setMaxTotal(100); // 最大连接数 connectionManager.setDefaultMaxPerRoute(20); // 每个路由最大连接数 // 配置超时 RequestConfig requestConfig RequestConfig.custom() .setConnectTimeout(5000) .setSocketTimeout(30000) .setConnectionRequestTimeout(5000) .build(); CloseableHttpClient httpClient HttpClients.custom() .setConnectionManager(connectionManager) .setDefaultRequestConfig(requestConfig) .build(); factory.setHttpClient(httpClient); restTemplate.setRequestFactory(factory); return restTemplate; } }8.2 内存管理问题处理大量文本时内存占用较高。我们做了这些优化流式处理对于大量文本分批处理向量维度压缩使用EmbeddingGemma的MRL功能将768维降到256维// 流式处理大量文本 public class BatchEmbeddingProcessor { private final EmbeddingService embeddingService; private final int batchSize 50; // 每批处理50个文本 public ListListFloat processLargeBatch(ListString texts) { ListListFloat allEmbeddings new ArrayList(); // 分批处理 for (int i 0; i texts.size(); i batchSize) { int end Math.min(i batchSize, texts.size()); ListString batch texts.subList(i, end); ListListFloat batchEmbeddings embeddingService.embedTexts(batch); allEmbeddings.addAll(batchEmbeddings); // 每处理完一批提示一下进度 log.info(已处理 {}/{} 个文本, end, texts.size()); // 给系统一点喘息时间避免内存压力过大 if (i % 500 0) { System.gc(); } } return allEmbeddings; } }8.3 错误处理和重试机制网络不稳定或Ollama服务重启时需要良好的错误处理// 带重试机制的嵌入服务 Service public class RetryEmbeddingService { private final EmbeddingService embeddingService; private final RetryTemplate retryTemplate; public RetryEmbeddingService(EmbeddingService embeddingService) { this.embeddingService embeddingService; // 配置重试策略 this.retryTemplate RetryTemplate.builder() .maxAttempts(3) // 最多重试3次 .exponentialBackoff(1000, 2, 10000) // 指数退避 .retryOn(RuntimeException.class) // 对运行时异常重试 .build(); } public ListFloat embedWithRetry(String text) { return retryTemplate.execute(context - { log.info(第{}次尝试嵌入文本, context.getRetryCount() 1); return embeddingService.embedText(text); }); } public ListListFloat embedBatchWithRetry(ListString texts) { return retryTemplate.execute(context - { log.info(第{}次尝试批量嵌入文本数量{}, context.getRetryCount() 1, texts.size()); return embeddingService.embedTexts(texts); }); } }9. 总结把EmbeddingGemma-300m集成到SpringBoot框架里搭建企业级语义服务API整个过程比想象中要顺利。这个组合的优势很明显EmbeddingGemma模型小而精适合企业部署SpringBoot生态完善开发效率高。实际用下来这套方案在语义搜索、内容推荐、文档去重等场景表现都不错。虽然300M参数不算大但在大多数业务场景下够用了而且推理速度快资源消耗少特别适合中小型企业。如果你也在考虑给系统添加语义理解能力但又担心大模型部署成本高不妨试试这个方案。从我的经验来看投入产出比还是挺高的。当然具体效果还要看你的实际业务场景建议先小范围试点验证效果后再大规模应用。最后提醒一点虽然EmbeddingGemma支持多语言但对于特别专业的领域术语可能还需要针对性的优化。不过好在它支持微调如果有必要的话可以用自己的数据进一步优化模型效果。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。