OllamaEmbeddingGemma-300m轻量级语义匹配方案部署教程1. 引言为什么你需要一个本地化的语义匹配工具想象一下这个场景你手里有一堆产品文档、用户反馈或者技术文章想快速找出和某个问题最相关的内容。传统的关键词搜索经常失灵比如搜“苹果”出来的既有水果信息也有科技公司的新闻完全不是你想要的。你需要的是能理解“意思”的搜索。这就是语义匹配的价值。它不看你输入了什么词而是理解你输入的“意思”然后去找意思相近的内容。过去这种能力通常需要连接云端的大型API或者部署昂贵的GPU服务器门槛很高。现在情况变了。谷歌开源的EmbeddingGemma-300m模型只有3亿参数却能在你的笔记本电脑上流畅运行。结合Ollama这个轻量级的模型运行框架你可以轻松在本地搭建一个属于自己的语义理解引擎。今天这篇教程我就带你从零开始一步步部署EmbeddingGemma-300m并把它用在实际项目中。整个过程不需要深度学习专家也不需要高端硬件跟着做就行。2. 环境准备与Ollama部署2.1 第一步安装OllamaOllama就像是一个模型的“应用商店”和“运行环境”。它帮你处理模型下载、版本管理和服务启动这些繁琐的事情。对于macOS和Linux用户打开终端一行命令搞定curl -fsSL https://ollama.com/install.sh | sh安装脚本会自动完成所有工作。完成后你可以验证一下ollama --version如果看到版本号说明安装成功了。对于Windows用户更简单。直接访问Ollama官网https://ollama.com下载那个.exe安装文件双击运行跟着向导点“下一步”就行。安装完成后Ollama服务会自动在后台启动。默认情况下它会监听本地的11434端口为我们提供API服务。2.2 第二步拉取EmbeddingGemma-300m模型模型已经准备好了我们把它“下载”到本地。打开终端Windows用户用PowerShell或CMD输入ollama pull embeddinggemma:300m你会看到下载进度条。模型大小约1.2GB根据你的网速可能需要几分钟到十几分钟。耐心等待这是唯一需要等待的步骤。下载完成后检查一下ollama list你应该能看到类似这样的输出NAME ID SIZE MODIFIED embeddinggemma:300m 7c8f27f1b4a3 1.2 GB 5 minutes ago看到这个恭喜你模型已经就位。重要提醒很多人在这里会犯一个习惯性错误——尝试用ollama run embeddinggemma:300m来启动它。千万别这么做这个命令是用来启动“聊天模型”的比如ChatGPT那种你问我答的模型。EmbeddingGemma是一个“嵌入模型”它的工作方式完全不同我们接下来会通过API来调用它。3. 验证服务与基础API调用3.1 第三步验证Ollama服务状态在开始调用模型之前我们先确认服务跑起来了。打开浏览器访问http://localhost:11434如果看到Ollama的欢迎页面或者简单的API响应说明服务运行正常。更直接的方法是使用命令行检查curl http://localhost:11434/api/tags这个命令会列出所有已下载的模型。你应该能在返回的JSON数据里找到embeddinggemma:300m。3.2 第四步你的第一次API调用现在我们来真正使用这个模型。打开终端我们用一个最简单的curl命令来测试curl -X POST http://localhost:11434/api/embeddings \ -H Content-Type: application/json \ -d { model: embeddinggemma:300m, prompt: 什么是人工智能 }稍等片刻你会看到一串长长的数字数组像这样{ embedding: [0.023, -0.045, 0.118, -0.207, 0.392, ...] // 总共300个数字 }这300个数字就是“什么是人工智能”这句话的向量表示也就是它的“语义指纹”。模型把这句话的意思压缩成了一串有意义的数字。3.3 第五步用Python封装API调用在实际项目中我们肯定要用代码来调用。下面是一个简单的Python封装import requests import json class EmbeddingClient: def __init__(self, base_urlhttp://localhost:11434): self.base_url base_url self.embedding_url f{base_url}/api/embeddings def get_embedding(self, text, modelembeddinggemma:300m): 获取单段文本的向量表示 payload { model: model, prompt: text } try: response requests.post(self.embedding_url, jsonpayload, timeout30) response.raise_for_status() # 如果状态码不是200抛出异常 result response.json() return result.get(embedding, []) except requests.exceptions.RequestException as e: print(fAPI调用失败: {e}) return None def batch_get_embeddings(self, texts, modelembeddinggemma:300m): 批量获取文本向量顺序处理 embeddings [] for i, text in enumerate(texts): print(f处理第 {i1}/{len(texts)} 条文本...) embedding self.get_embedding(text, model) if embedding: embeddings.append(embedding) else: embeddings.append(None) # 或者根据需求处理错误 return embeddings # 使用示例 if __name__ __main__: client EmbeddingClient() # 测试单条文本 test_text 机器学习是人工智能的一个分支 vector client.get_embedding(test_text) if vector: print(f文本: {test_text}) print(f向量长度: {len(vector)}) # 应该是300 print(f前5个值: {vector[:5]}) # 看看向量长什么样这个类提供了两个基本方法get_embedding处理单条文本batch_get_embeddings处理批量文本。在实际使用中你可能需要根据网络情况调整超时时间或者添加重试逻辑。4. 构建语义相似度计算工具4.1 第六步理解相似度计算拿到向量只是第一步更重要的是比较向量之间的相似度。最常用的方法是余弦相似度。简单理解把两个向量想象成空间中的两个箭头。余弦相似度计算的是这两个箭头之间夹角的余弦值。夹角越小余弦值越接近1说明两个向量方向越一致语义越相似。相似度接近1两个文本意思几乎相同相似度接近0两个文本不相关相似度接近-1两个文本意思相反在文本中很少见4.2 第七步实现相似度计算函数让我们用代码实现这个计算import numpy as np from numpy.linalg import norm class SimilarityCalculator: staticmethod def cosine_similarity(vec1, vec2): 计算两个向量的余弦相似度 # 转换为numpy数组以便计算 vec1 np.array(vec1) vec2 np.array(vec2) # 点积除以模长的乘积 dot_product np.dot(vec1, vec2) norm1 norm(vec1) norm2 norm(vec2) # 避免除以零 if norm1 0 or norm2 0: return 0.0 similarity dot_product / (norm1 * norm2) return float(similarity) staticmethod def find_most_similar(query_vector, document_vectors, top_k5): 在文档向量中查找与查询向量最相似的top_k个 similarities [] for i, doc_vector in enumerate(document_vectors): if doc_vector is None: # 跳过处理失败的文档 continue sim SimilarityCalculator.cosine_similarity(query_vector, doc_vector) similarities.append((i, sim)) # 按相似度降序排序 similarities.sort(keylambda x: x[1], reverseTrue) # 返回top_k个结果 return similarities[:top_k] # 使用示例 if __name__ __main__: # 初始化客户端和计算器 client EmbeddingClient() calculator SimilarityCalculator() # 准备一些测试文本 documents [ 苹果是一种常见的水果富含维生素, 苹果公司发布了新款iPhone手机, 香蕉是热带水果口感香甜, 科技公司不断推出创新产品, 水果对健康有益应该每天食用 ] # 获取所有文档的向量 print(正在计算文档向量...) doc_vectors client.batch_get_embeddings(documents) # 用户查询 query 我想买一些新鲜水果 print(f\n用户查询: {query}) # 获取查询的向量 query_vector client.get_embedding(query) if query_vector and all(doc_vectors): # 查找最相似的文档 results calculator.find_most_similar(query_vector, doc_vectors, top_k3) print(\n最相似的文档:) for rank, (doc_idx, similarity) in enumerate(results, 1): print(f{rank}. 相似度: {similarity:.4f}) print(f 文档: {documents[doc_idx]}) print()运行这段代码你会看到模型成功区分了“水果苹果”和“苹果公司”把关于水果的文档排在了前面。这就是语义搜索的魅力——它理解你的意图而不是机械匹配关键词。4.3 第八步相似度计算的实用技巧在实际使用中有几个技巧能让相似度计算更准确技巧一文本预处理很重要模型对输入文本的质量很敏感。建议def preprocess_text(text): 简单的文本预处理 # 1. 去除多余空白 text .join(text.split()) # 2. 对于太短的文本考虑添加上下文 if len(text) 10: # 少于10个字符 # 根据场景添加上下文这里只是示例 # 实际中可能需要更智能的处理 pass # 3. 对于太长的文本考虑截断或分段 # EmbeddingGemma-300m的上下文长度是512token # 如果超过这个长度效果会下降 return text # 使用预处理 raw_text 苹果 processed_text preprocess_text(raw_text) # 或者更好的方式提供更完整的上下文 better_text 我们讨论的是作为水果的苹果技巧二设置合理的相似度阈值不同的应用场景需要不同的阈值class SimilarityThresholds: 不同应用场景的相似度阈值建议 staticmethod def for_duplicate_detection(): 重复检测要求高度相似 return 0.85 # 高于0.85认为是重复内容 staticmethod def for_semantic_search(): 语义搜索相关即可 return 0.65 # 高于0.65认为是相关文档 staticmethod def for_topic_clustering(): 主题聚类宽松一些 return 0.50 # 高于0.50可以聚为一类 staticmethod def is_highly_similar(similarity, applicationsearch): 根据应用判断是否高度相似 thresholds { duplicate: 0.85, search: 0.65, clustering: 0.50 } threshold thresholds.get(application, 0.65) return similarity threshold技巧三处理多义词和歧义像“苹果”这样的多义词可以通过添加上下文来区分# 不够好的方式 text1 苹果 text2 苹果 # 更好的方式添加上下文 text1 苹果是一种水果富含维生素C text2 苹果公司是全球知名的科技企业 # 或者在实际应用中利用文档的上下文 document_context 这篇文档讨论健康饮食提到苹果的营养价值 query_with_context f{document_context} {text1}5. 实战项目构建本地语义搜索系统5.1 第九步设计搜索系统架构现在我们把前面学到的组合起来构建一个实用的本地语义搜索系统。这个系统可以用于搜索你的个人文档、知识库内容或者产品说明。系统的主要组件文档处理模块读取文档生成向量向量存储模块保存向量方便快速检索查询处理模块处理用户查询计算相似度结果排序模块按相关性排序返回结果5.2 第十步完整实现代码下面是完整的实现import json import pickle import os from pathlib import Path from typing import List, Dict, Any import numpy as np from datetime import datetime class LocalSemanticSearch: 本地语义搜索系统 def __init__(self, data_dir./search_data, model_nameembeddinggemma:300m): 初始化搜索系统 参数: data_dir: 数据存储目录 model_name: 使用的模型名称 self.data_dir Path(data_dir) self.data_dir.mkdir(exist_okTrue) # 创建目录如果不存在 self.model_name model_name self.documents_file self.data_dir / documents.json self.embeddings_file self.data_dir / embeddings.pkl # 从之前的示例导入 from embedding_client import EmbeddingClient from similarity_calculator import SimilarityCalculator self.client EmbeddingClient() self.calculator SimilarityCalculator() # 内存中的数据 self.documents [] # 文档列表[{id: ..., text: ..., metadata: {...}}] self.embeddings [] # 对应的向量列表 # 加载已有数据 self._load_data() def _load_data(self): 加载已保存的文档和向量 if self.documents_file.exists(): with open(self.documents_file, r, encodingutf-8) as f: self.documents json.load(f) print(f已加载 {len(self.documents)} 个文档) if self.embeddings_file.exists(): with open(self.embeddings_file, rb) as f: self.embeddings pickle.load(f) print(f已加载 {len(self.embeddings)} 个向量) def _save_data(self): 保存文档和向量到文件 with open(self.documents_file, w, encodingutf-8) as f: json.dump(self.documents, f, ensure_asciiFalse, indent2) with open(self.embeddings_file, wb) as f: pickle.dump(self.embeddings, f) def add_document(self, text: str, metadata: Dict[str, Any] None) - str: 添加文档到搜索系统 参数: text: 文档文本内容 metadata: 文档元数据如来源、时间等 返回: 文档ID # 生成文档ID doc_id fdoc_{len(self.documents)}_{datetime.now().strftime(%Y%m%d_%H%M%S)} # 获取文档向量 print(f正在处理文档: {doc_id}) embedding self.client.get_embedding(text, self.model_name) if embedding is None: print(f警告: 文档 {doc_id} 向量生成失败) return None # 保存文档信息 doc_info { id: doc_id, text: text, metadata: metadata or {}, added_at: datetime.now().isoformat() } self.documents.append(doc_info) self.embeddings.append(embedding) # 保存到文件 self._save_data() print(f文档添加成功: {doc_id}) return doc_id def add_documents_batch(self, texts: List[str], metadata_list: List[Dict] None): 批量添加文档 if metadata_list is None: metadata_list [{}] * len(texts) for i, (text, metadata) in enumerate(zip(texts, metadata_list)): print(f批量处理进度: {i1}/{len(texts)}) self.add_document(text, metadata) def search(self, query: str, top_k: int 5, threshold: float 0.0) - List[Dict]: 语义搜索 参数: query: 查询文本 top_k: 返回最相关的k个结果 threshold: 相似度阈值低于此值的结果不返回 返回: 搜索结果列表按相似度降序排列 if not self.documents: print(搜索系统为空请先添加文档) return [] # 获取查询向量 query_vector self.client.get_embedding(query, self.model_name) if query_vector is None: print(查询向量生成失败) return [] # 计算相似度 results [] for i, (doc, doc_vector) in enumerate(zip(self.documents, self.embeddings)): if doc_vector is None: continue similarity self.calculator.cosine_similarity(query_vector, doc_vector) if similarity threshold: result { id: doc[id], text: doc[text], similarity: similarity, metadata: doc[metadata] } results.append(result) # 按相似度排序 results.sort(keylambda x: x[similarity], reverseTrue) # 返回top_k个结果 return results[:top_k] def search_with_highlight(self, query: str, top_k: int 3) - List[Dict]: 带高亮显示的搜索简单版本 在实际应用中你可能需要更复杂的高亮逻辑 results self.search(query, top_k) # 简单的关键词高亮这里只是示例实际语义搜索的高亮更复杂 query_keywords set(query.lower().split()) for result in results: text result[text] # 在实际实现中这里应该使用更智能的高亮算法 # 比如基于语义单元而不是简单关键词 result[highlighted_text] text # 简化版本实际需要实现高亮 return results def get_document_count(self) - int: 获取文档数量 return len(self.documents) def clear_all(self): 清空所有数据 self.documents [] self.embeddings [] # 删除文件 if self.documents_file.exists(): self.documents_file.unlink() if self.embeddings_file.exists(): self.embeddings_file.unlink() print(所有数据已清空) # 使用示例 def demo_semantic_search(): 演示语义搜索系统的使用 # 初始化搜索系统 print(初始化语义搜索系统...) search_system LocalSemanticSearch(data_dir./my_search_db) # 添加一些示例文档比如产品FAQ faq_documents [ { text: 如何重置路由器密码找到路由器背面的reset按钮按住10秒钟直到指示灯闪烁。, metadata: {category: 网络, source: 用户手册} }, { text: 退货政策购买后30天内商品未使用且包装完好可以无理由退货。, metadata: {category: 售后, source: 官网政策} }, { text: 会员特权黄金会员享受全年免费配送服务优先客服支持。, metadata: {category: 会员, source: 会员条款} }, { text: WiFi连接问题请检查密码是否正确尝试重启路由器和设备。, metadata: {category: 网络, source: 故障排除} }, { text: 支付方式我们支持支付宝、微信支付、银联信用卡等多种支付方式。, metadata: {category: 支付, source: 帮助中心} }, { text: 订单查询登录账户后在我的订单页面可以查看所有订单状态。, metadata: {category: 订单, source: 用户指南} }, { text: 密码找回在登录页面点击忘记密码通过注册邮箱重置密码。, metadata: {category: 账户, source: 安全指南} } ] # 批量添加文档 print(\n添加文档到搜索系统...) for doc in faq_documents: search_system.add_document(doc[text], doc[metadata]) print(f\n系统中共有 {search_system.get_document_count()} 个文档) # 测试搜索 test_queries [ 我忘了路由器密码怎么办, 怎么退货, 会员有什么好处, 网络连不上, 怎么付款 ] for query in test_queries: print(f\n{*50}) print(f搜索查询: {query}) print(f{*50}) results search_system.search(query, top_k2) if results: for i, result in enumerate(results, 1): print(f{i}. [相似度: {result[similarity]:.3f}]) print(f 内容: {result[text][:80]}...) print(f 分类: {result[metadata].get(category, 未知)}) print() else: print(未找到相关结果) # 保存搜索历史示例 search_history [] for query in test_queries: results search_system.search(query, top_k1) if results: search_history.append({ query: query, top_result: results[0][text][:50] ..., similarity: results[0][similarity], time: datetime.now().isoformat() }) print(\n搜索历史摘要:) for item in search_history: print(f查询: {item[query]} - 最佳匹配: {item[top_result]} (相似度: {item[similarity]:.3f})) if __name__ __main__: demo_semantic_search()5.3 第十一步扩展功能持久化与性能优化上面的基础版本已经能用但在实际使用中我们还需要考虑持久化和性能。持久化改进使用更高效的向量存储import numpy as np import sqlite3 from typing import List class VectorDatabase: 使用SQLite存储向量和文档的优化版本 def __init__(self, db_path./vectors.db): self.db_path db_path self.conn sqlite3.connect(db_path) self._init_database() def _init_database(self): 初始化数据库表 cursor self.conn.cursor() # 创建文档表 cursor.execute( CREATE TABLE IF NOT EXISTS documents ( id TEXT PRIMARY KEY, text TEXT NOT NULL, metadata TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ) # 创建向量表 cursor.execute( CREATE TABLE IF NOT EXISTS vectors ( doc_id TEXT, vector_data BLOB, FOREIGN KEY (doc_id) REFERENCES documents (id) ) ) # 创建索引以提高搜索速度 cursor.execute(CREATE INDEX IF NOT EXISTS idx_doc_id ON vectors (doc_id)) self.conn.commit() def add_document_with_vector(self, doc_id: str, text: str, vector: List[float], metadata: dict None): 添加文档和向量 cursor self.conn.cursor() # 存储文档 metadata_json json.dumps(metadata) if metadata else {} cursor.execute( INSERT OR REPLACE INTO documents (id, text, metadata) VALUES (?, ?, ?), (doc_id, text, metadata_json) ) # 存储向量转换为二进制 vector_array np.array(vector, dtypenp.float32) vector_blob vector_array.tobytes() cursor.execute( INSERT OR REPLACE INTO vectors (doc_id, vector_data) VALUES (?, ?), (doc_id, vector_blob) ) self.conn.commit() def search_similar(self, query_vector: List[float], top_k: int 5) - List[dict]: 搜索相似向量简化版本实际需要更复杂的相似度计算 cursor self.conn.cursor() # 获取所有向量对于大量数据这里需要优化 cursor.execute(SELECT doc_id, vector_data FROM vectors) all_vectors cursor.fetchall() results [] query_array np.array(query_vector, dtypenp.float32) for doc_id, vector_blob in all_vectors: # 从二进制恢复向量 vector_array np.frombuffer(vector_blob, dtypenp.float32) # 计算相似度这里使用简单的余弦相似度 similarity self._cosine_similarity(query_array, vector_array) # 获取文档信息 cursor.execute(SELECT text, metadata FROM documents WHERE id ?, (doc_id,)) doc_info cursor.fetchone() if doc_info: text, metadata_json doc_info metadata json.loads(metadata_json) if metadata_json else {} results.append({ doc_id: doc_id, text: text, similarity: similarity, metadata: metadata }) # 排序并返回top_k results.sort(keylambda x: x[similarity], reverseTrue) return results[:top_k] def _cosine_similarity(self, vec1: np.ndarray, vec2: np.ndarray) - float: 计算余弦相似度 dot_product np.dot(vec1, vec2) norm1 np.linalg.norm(vec1) norm2 np.linalg.norm(vec2) if norm1 0 or norm2 0: return 0.0 return dot_product / (norm1 * norm2) def close(self): 关闭数据库连接 self.conn.close()性能优化批量处理和缓存from concurrent.futures import ThreadPoolExecutor, as_completed import time from functools import lru_cache class OptimizedEmbeddingClient(EmbeddingClient): 优化版的嵌入客户端支持批量和缓存 def __init__(self, base_urlhttp://localhost:11434, max_workers5, cache_size1000): super().__init__(base_url) self.max_workers max_workers self.request_timeout 30 # 简单的内存缓存对于重复查询很有用 self._cache {} self.cache_size cache_size lru_cache(maxsize1000) def get_embedding_cached(self, text: str, model: str embeddinggemma:300m) - List[float]: 带缓存的嵌入获取基于文本内容缓存 cache_key f{model}:{text} if cache_key in self._cache: return self._cache[cache_key] embedding self.get_embedding(text, model) if embedding and len(self._cache) self.cache_size: self._cache[cache_key] embedding return embedding def batch_get_embeddings_parallel(self, texts: List[str], model: str embeddinggemma:300m) - List[List[float]]: 并行批量获取嵌入 embeddings [None] * len(texts) with ThreadPoolExecutor(max_workersself.max_workers) as executor: # 提交所有任务 future_to_index { executor.submit(self.get_embedding, text, model): i for i, text in enumerate(texts) } # 收集结果 for future in as_completed(future_to_index): index future_to_index[future] try: embedding future.result(timeoutself.request_timeout) embeddings[index] embedding except Exception as e: print(f处理文本 {index} 时出错: {e}) embeddings[index] None return embeddings def benchmark(self, texts: List[str], model: str embeddinggemma:300m): 性能基准测试 print(f性能测试: 处理 {len(texts)} 条文本) # 测试顺序处理 start_time time.time() embeddings_seq self.batch_get_embeddings(texts, model) seq_time time.time() - start_time print(f顺序处理时间: {seq_time:.2f}秒, 平均每条: {seq_time/len(texts):.3f}秒) # 测试并行处理 start_time time.time() embeddings_par self.batch_get_embeddings_parallel(texts, model) par_time time.time() - start_time print(f并行处理时间: {par_time:.2f}秒, 平均每条: {par_time/len(texts):.3f}秒) # 测试缓存效果重复查询 if len(texts) 2: start_time time.time() for text in texts[:10]: # 重复查询前10条 _ self.get_embedding_cached(text, model) cache_time time.time() - start_time print(f缓存查询时间10次重复: {cache_time:.2f}秒) return embeddings_seq, embeddings_par # 使用优化版本 def demo_optimized_search(): 演示优化后的搜索系统 # 初始化优化客户端 client OptimizedEmbeddingClient(max_workers3) # 准备测试数据 test_texts [ 人工智能技术发展迅速, 机器学习是AI的重要分支, 深度学习需要大量数据, 自然语言处理让机器理解人类语言, 计算机视觉识别图像内容, 强化学习通过试错学习, 神经网络模仿人脑结构, 大数据是AI的燃料, 算法优化提升模型性能, 云计算支持AI训练 ] * 3 # 重复3次共30条文本 print(开始性能测试...) client.benchmark(test_texts) # 测试缓存效果 print(\n测试缓存效果:) # 第一次查询未缓存 start time.time() result1 client.get_embedding_cached(test_texts[0]) time1 time.time() - start print(f第一次查询未缓存: {time1:.4f}秒) # 第二次查询已缓存 start time.time() result2 client.get_embedding_cached(test_texts[0]) time2 time.time() - start print(f第二次查询已缓存: {time2:.4f}秒) print(f缓存加速比: {time1/time2:.1f}倍)6. 总结6.1 关键要点回顾通过这篇教程我们完成了从零开始部署和使用EmbeddingGemma-300m的完整流程环境搭建安装Ollama并拉取embeddinggemma:300m模型这是所有工作的基础。服务验证通过简单的API调用确认服务正常运行理解了嵌入模型与聊天模型的区别。核心功能实现实现了文本向量化和余弦相似度计算这是语义匹配的核心。实用技巧掌握学会了文本预处理、阈值设置、多义词处理等提升效果的方法。完整系统构建构建了一个可用的本地语义搜索系统包括文档管理、向量存储和搜索功能。性能优化通过批量处理、并行计算和缓存机制提升了系统效率。6.2 实际应用建议基于这个系统你可以轻松扩展出很多实用功能知识库问答系统# 简化的知识库问答 def answer_from_knowledge_base(question, knowledge_base, similarity_threshold0.7): 基于知识库回答问题 # 1. 在知识库中搜索相关问题 search_results search_system.search(question, top_k3) # 2. 如果找到高度相关的内容直接返回 for result in search_results: if result[similarity] similarity_threshold: return f根据知识库{result[text]} # 3. 如果没有高度匹配的返回最相关的内容或提示 if search_results: best_match search_results[0] return f未找到完全匹配的答案以下是最相关的内容{best_match[text][:200]}... return 抱歉知识库中没有找到相关信息。文档去重检测def find_duplicates(documents, similarity_threshold0.85): 查找重复或高度相似的文档 duplicates [] for i in range(len(documents)): for j in range(i 1, len(documents)): sim calculator.cosine_similarity( client.get_embedding(documents[i]), client.get_embedding(documents[j]) ) if sim similarity_threshold: duplicates.append((i, j, sim)) return duplicates内容推荐系统def recommend_content(user_history, available_content, top_n5): 基于用户历史推荐内容 # 计算用户历史向量的平均值 history_vectors [ client.get_embedding(item) for item in user_history ] if not history_vectors: return [] user_profile_vector np.mean(history_vectors, axis0) # 计算与所有可用内容的相似度 recommendations [] for i, content in enumerate(available_content): content_vector client.get_embedding(content) similarity calculator.cosine_similarity(user_profile_vector, content_vector) recommendations.append((i, content, similarity)) # 按相似度排序 recommendations.sort(keylambda x: x[2], reverseTrue) return recommendations[:top_n]6.3 下一步学习方向如果你已经掌握了本教程的内容可以继续探索结合向量数据库对于大量数据可以集成Chroma、Weaviate等专业向量数据库。模型微调在自己的专业领域数据上微调EmbeddingGemma提升特定任务的效果。多语言支持利用模型的多语言能力构建跨语言搜索系统。实时更新机制实现文档的增量更新和向量实时重建。用户反馈学习根据用户的点击和反馈优化搜索结果排序。EmbeddingGemma-300m的最大优势在于平衡——它足够强大能处理实际的语义理解任务又足够轻量能在普通硬件上运行。无论是个人项目、创业公司还是企业内部工具这都是一个值得考虑的解决方案。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。