GTE中文语义相似度服务代码实例:多模型集成
1. 项目背景与技术价值
在自然语言处理(NLP)领域,语义相似度计算是信息检索、问答系统、文本去重和推荐系统等任务的核心基础。传统的关键词匹配方法难以捕捉句子间的深层语义关联,而基于预训练语言模型的向量表示技术则能有效解决这一问题。
GTE(General Text Embedding)是由达摩院推出的一系列通用文本嵌入模型,专为高质量文本向量生成设计。其GTE-Base模型在中文语义检索权威榜单 C-MTEB 上表现优异,具备强大的语义理解能力。本项目基于 ModelScope 平台提供的 GTE 中文向量模型,构建了一个轻量级、可扩展的语义相似度服务系统,支持 WebUI 可视化交互与 API 接口调用,适用于 CPU 环境部署,满足中小规模应用场景的需求。
该服务不仅实现了高精度的语义向量化与余弦相似度计算,还集成了动态仪表盘展示功能,极大提升了用户体验和调试效率。
2. 系统架构与核心组件
2.1 整体架构设计
系统采用前后端分离架构,后端使用 Flask 构建 RESTful API 和 Web 服务,前端通过 HTML/CSS/JavaScript 实现可视化界面。整体流程如下:
- 用户在 Web 页面输入两个中文句子;
- 前端将数据发送至 Flask 后端;
- 后端调用 GTE 模型对两段文本进行编码,得到对应的向量表示;
- 计算两个向量之间的余弦相似度;
- 返回结果并驱动前端仪表盘动态显示评分。
[用户输入] → [Flask WebUI/API] → [GTE 模型推理] → [余弦相似度计算] → [结果返回 + 可视化]2.2 核心依赖与环境配置
为确保兼容性和稳定性,项目锁定以下关键依赖版本:
transformers == 4.35.2 torch == 1.13.1 flask == 2.3.3 numpy == 1.24.3 scikit-learn == 1.3.0特别说明:transformers==4.35.2是经过验证的稳定版本,避免了新版中因 tokenizer 输出格式变化导致的张量维度错误问题。同时,模型加载时设置return_dict=False,以适配原始输出结构,防止推理中断。
2.3 模型加载与向量编码逻辑
GTE 模型通过AutoModel和AutoTokenizer加载,支持自动从 ModelScope 模型库下载指定中文模型。以下是核心初始化代码:
from modelscope import AutoTokenizer, AutoModel import torch # 加载 GTE 中文 base 模型 model_name = "damo/nlp_gte_sentence-embedding_chinese-base" tokenizer = AutoTokenizer.from_modelscope(model_name) model = AutoModel.from_modelscope(model_name) # 设置为评估模式 model.eval()文本编码过程包括分词、张量转换和池化操作。由于 GTE 输出为[batch_size, seq_len, hidden_dim]的隐状态,需通过Mean Pooling获取句向量:
def encode_text(text): inputs = tokenizer(text, padding=True, truncation=True, return_tensors="pt", max_length=512) with torch.no_grad(): outputs = model(**inputs) embeddings = outputs[0] # 取出最后一层隐藏状态 attention_mask = inputs['attention_mask'] # Mean Pooling: 使用 attention mask 对有效 token 求平均 sentence_embedding = torch.sum(embeddings * attention_mask.unsqueeze(-1), dim=1) / torch.sum(attention_mask, dim=1, keepdim=True) return sentence_embedding.squeeze(0).numpy() # 转为 numpy array📌 技术要点:Mean Pooling 能有效保留上下文信息,相比 [CLS] 向量更适合语义相似度任务。
3. 相似度计算与结果解析
3.1 余弦相似度算法原理
余弦相似度衡量两个向量方向的夹角余弦值,范围在 [-1, 1] 之间。对于归一化的向量,其计算简化为点积运算:
$$ \text{similarity} = \cos(\theta) = \frac{\mathbf{A} \cdot \mathbf{B}}{|\mathbf{A}| |\mathbf{B}|} $$
当两个向量均为单位向量时,公式退化为: $$ \text{similarity} = \mathbf{A} \cdot \mathbf{B} $$
Python 实现如下:
from sklearn.metrics.pairwise import cosine_similarity import numpy as np def calculate_similarity(sent_a, sent_b): vec_a = encode_text(sent_a) vec_b = encode_text(sent_b) # reshape 为二维数组以适配 sklearn 输入要求 sim = cosine_similarity([vec_a], [vec_b])[0][0] return float(sim) # 返回标量数值也可手动实现以减少依赖:
def cosine_sim_manual(vec_a, vec_b): dot_product = np.dot(vec_a, vec_b) norm_a = np.linalg.norm(vec_a) norm_b = np.linalg.norm(vec_b) return dot_product / (norm_a * norm_b)3.2 结果映射与语义判定规则
原始相似度值为浮点数(0~1),为便于理解,将其映射为百分比形式,并设定分级判断标准:
| 分数区间 | 判定结果 | 语义解释 |
|---|---|---|
| 90%~100% | 高度相似 | 几乎同义或表达一致含义 |
| 70%~89% | 较为相似 | 主题相近,表述略有差异 |
| 50%~69% | 一般相关 | 存在部分共通语义 |
| 30%~49% | 弱相关 | 仅有少量词汇或主题重叠 |
| 0%~29% | 基本不相关 | 语义完全无关 |
此规则可用于自动化分类决策,如客服问答匹配、新闻聚类等场景。
4. WebUI 可视化实现方案
4.1 Flask 后端接口设计
Flask 提供两个主要路由:首页渲染 (/) 和相似度计算接口 (/api/similarity)。
from flask import Flask, request, jsonify, render_template app = Flask(__name__) @app.route('/') def index(): return render_template('index.html') @app.route('/api/similarity', methods=['POST']) def api_similarity(): data = request.get_json() sent_a = data.get('sentence_a', '').strip() sent_b = data.get('sentence_b', '').strip() if not sent_a or not sent_b: return jsonify({'error': '请输入完整的两个句子'}), 400 try: similarity_score = calculate_similarity(sent_a, sent_b) percent = round(similarity_score * 100, 1) # 判定等级 if percent >= 90: level = "高度相似" elif percent >= 70: level = "较为相似" elif percent >= 50: level = "一般相关" elif percent >= 30: level = "弱相关" else: level = "基本不相关" return jsonify({ 'similarity': percent, 'level': level }) except Exception as e: return jsonify({'error': str(e)}), 5004.2 前端动态仪表盘实现
前端使用 Chart.js 创建圆形进度条模拟仪表盘效果,实时反映相似度数值。HTML 结构如下:
<canvas id="gaugeChart" width="200" height="100"></canvas> <div id="resultText">相似度:--%</div>JavaScript 动态更新图表:
const ctx = document.getElementById('gaugeChart').getContext('2d'); let gaugeChart = new Chart(ctx, { type: 'doughnut', data: { datasets: [{ data: [0, 100], backgroundColor: ['#4caf50', '#e0e0e0'], borderWidth: 0 }] }, options: { circumference: Math.PI, rotation: Math.PI, cutout: '70%', animation: { animateRotate: true }, plugins: { legend: { display: false } } } }); function updateGauge(value) { const percentage = value; gaugeChart.data.datasets[0].data = [percentage, 100 - percentage]; gaugeChart.update(); document.getElementById('resultText').textContent = `相似度:${percentage}%`; }点击“计算”按钮触发 AJAX 请求:
document.getElementById('calculateBtn').addEventListener('click', async () => { const sentA = document.getElementById('sentenceA').value; const sentB = document.getElementById('sentenceB').value; const response = await fetch('/api/similarity', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sentence_a: sentA, sentence_b: sentB }) }); const result = await response.json(); if (result.error) { alert(result.error); } else { updateGauge(result.similarity); document.getElementById('levelText').textContent = `判定:${result.level}`; } });5. 多模型集成扩展建议
虽然当前系统基于单一 GTE 模型运行,但可通过“多模型集成”策略进一步提升鲁棒性与准确性。常见集成方式包括:
5.1 模型投票机制
加载多个不同结构的中文向量模型(如 GTE、SimCSE、CoSENT、ConSERT),分别计算相似度后取平均值或加权平均:
models = [ ("gte", gte_encode), ("simcse", simcse_encode), ("cosent", cosent_encode) ] def ensemble_similarity(sent_a, sent_b): scores = [] for name, encoder in models: vec_a = encoder(sent_a) vec_b = encoder(sent_b) sim = cosine_similarity([vec_a], [vec_b])[0][0] scores.append(sim) return np.mean(scores) # 或按性能赋权重5.2 场景自适应切换
根据不同业务场景动态选择最优模型。例如:
- 短文本匹配:优先使用 GTE
- 长文档对比:选用支持长序列的模型(如 Longformer + Pooling)
- 专业术语密集:微调过的领域专用模型
可通过配置文件或 API 参数控制模型选择:
POST /api/similarity { "sentence_a": "糖尿病的症状有哪些?", "sentence_b": "高血糖会引起哪些身体反应?", "model": "medical-gte-v1" }6. 总结
6. 总结
本文详细介绍了基于 GTE 中文向量模型构建的语义相似度服务系统,涵盖模型加载、向量编码、余弦相似度计算、WebUI 可视化及 API 接口开发全过程。系统已在 CPU 环境下完成轻量化优化,具备启动快、推理稳、零报错的特点,适合快速部署于本地测试或边缘设备。
核心成果包括:
- 高精度语义分析能力:依托达摩院 GTE-Base 模型,在中文语义理解任务中达到行业领先水平;
- 直观可视化体验:通过 Flask + Chart.js 实现动态仪表盘,提升交互友好性;
- 工程化落地保障:锁定 transformers 版本并修复输入格式问题,确保生产环境稳定运行;
- 可扩展性强:支持后续接入多模型集成、缓存机制、批量处理等功能。
未来可进一步探索模型蒸馏压缩、异步批处理优化以及与 RAG(检索增强生成)系统的结合应用,持续提升服务效能与适用边界。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。