文本向量化怎么做?text2vec 的语义匹配、相似检索与模型微调一步到位
【免费下载链接】text2vectext2vec, text to vector. 文本向量表征工具,把文本转化为向量矩阵,实现了Word2Vec、RankBM25、Sentence-BERT、CoSENT等文本表征、文本相似度计算模型,开箱即用。项目地址: https://gitcode.com/GitHub_Trending/te/text2vec
做过语义匹配的同学都有体会:要判断"如何更换花呗绑定银行卡"和"花呗更改绑定银行卡"是否同义,字面重合度为零,词袋、编辑距离这类方法全部失效。你需要把文本映射到一个连续向量空间,用语义距离代替字面距离——这就是**文本向量化(text to vector)**要解决的事。
text2vec 是一个开箱即用的文本向量表征工具包:内置Word2Vec、RankBM25、Sentence-BERT、CoSENT、BGE五类模型的推理与训练代码,配套 8 个已发布的中文/多语言预训练模型,覆盖从"单条相似度打分"到"百万级语料入库检索"的完整链路。
图 1:项目作者在 HuggingFace 上发布的 text2vec 中文语义相似度在线 demo,输入两个句子即可得到余弦分数
谁在什么场景下需要 text2vec
先看三类典型使用者:
- 搜索与推荐工程师:query 改写、近重复问题推荐、召回阶段的语义向量检索,需要"给一堆文本批量算向量 + 算余弦分数"的稳定接口。
- NLP 算法工程师:手里有一批句子对标注数据(相似/不相似,或 0~5 的相关性打分),想在通用预训练模型上继续微调出领域匹配模型。
- 业务开发:没有 GPU,只有 CPU,想先跑通"两句话像不像"的最小功能。
一句话定义:text2vec 把词、句子、段落编码为定长浮点向量矩阵,并提供相似度计算、Top-k 语义搜索和模型微调三大能力。
输入→处理→输出:text2vec 的工作流水线
以默认模型SentenceModel为例,整条链路分三层(实现位于text2vec/sentence_model.py):
输入层:一批字符串进入encode()。内部先按文本长度排序后再分批(减少 padding 浪费),经 tokenizer 转成input_ids+attention_mask。
处理层:BERT 编码器输出所有 token 的上下文向量,再按encoder_type做池化压缩成单个句向量。支持MEAN、CLS、FIRST_LAST_AVG、LAST_AVG、POOLER五种池化方式,默认MEAN:
# text2vec/sentence_model.py 中 MEAN 池化的核心逻辑 token_embeddings = model_output.last_hidden_state # [batch, 序列长, 768] input_mask_expanded = attention_mask.unsqueeze(-1).expand(token_embeddings.size()).float() final_encoding = torch.sum(token_embeddings * input_mask_expanded, 1) \ / torch.clamp(input_mask_expanded.sum(1), min=1e-9) # 只对真实 token 取平均输出层:返回 shape 为(句子数, 768)的 numpy 矩阵;需要打分时,Similarity.get_score()对两条句向量做余弦,输出 [-1, 1] 的标量;需要检索时,semantic_search()在候选库向量上取 Top-k:
# 相似度与检索的最小调用 from text2vec import Similarity, SentenceModel, semantic_search sim = Similarity() # 默认加载 text2vec-base-chinese score = sim.get_score("如何更换花呗绑定银行卡", "花呗更改绑定银行卡") # 0.9477 model = SentenceModel() corpus_emb = model.encode(corpus_texts) # 候选库向量,可离线缓存 query_emb = model.encode([query]) hits = semantic_search(query_emb, corpus_emb, top_k=5)CoSENT 是其中推荐度最高的架构:训练时用余弦排序损失让"打分排序"直接贴近最终预测目标,推理时退化为两个独立句向量 + 一次余弦。官方评测里,同一底座下 CoSENT 的中文平均 Spearman 比 SBERT 高约 5~6 分(68.53 vs 63.15,见 README 评测表)。
图 2:CoSENT 训练结构,成对文本各自编码后,损失函数直接作用于两两余弦值的排序关系
四步完成从安装到语义搜索
步骤 1:安装。先装 PyTorch,再装 text2vec 本体:
pip install torch pip install -U text2vec步骤 2:编码文本。首次运行会自动从 HuggingFace 拉取默认模型(缓存在~/.cache/huggingface/transformers),预期输出(1, 768)的向量:
from text2vec import SentenceModel model = SentenceModel() # 默认 shibing624/text2vec-base-chinese vec = model.encode("如何更换花呗绑定银行卡") print(vec.shape) # (1, 768)步骤 3:算相似度与搜索。get_score支持两条句子任意组合打分;semantic_search从候选库取 Top-k,预期最相关的"花呗更改绑定银行卡"以 0.9477 分排第一:
from text2vec import Similarity, semantic_search sim = Similarity() print(sim.get_score("如何更换花呗绑定银行卡", "花呗更改绑定银行卡")) # 0.9477 hits = semantic_search(model.encode([query]), corpus_emb, top_k=3) for hit in hits[0]: print(corpus[hit["corpus_id"]], round(hit["score"], 4))步骤 4:批量处理与多卡。文本量大时用 CLI 直接批处理,--chunk_size控制落盘分片,避免一次性写爆磁盘:
text2vec --input_file input.txt --output_file out.csv \ --batch_size 128 --chunk_size 1000 --multi_gpu True输入要求一句话一行,输出为 CSV 向量文件。多卡场景下 CLI 会按进程池把每张卡派给一个 worker,吞吐近似线性提升。
相似度分数与 Spearman 该怎么读
余弦分数:范围 [-1, 1],数值越大语义越接近。项目 demo 里的经验值:同义改写句 0.9477、语义相关但表述不同的句对 0.3~0.6、无关句对 0.0 附近甚至为负。阈值不要拍脑袋,建议在自己的验证集上画"分数 vs 人工标注"分布后切分。
Spearman 相关系数:项目所有模型评测统一用 Spearman(compute_spearmanr),它衡量"模型分数与人工相关性打分的排序一致性",取值 [-1, 1],越接近 1 说明排序越准。读评测表时记住两点:
- 同一底座横向比架构:MacBERT 底座上 CoSENT 平均 68.53,SBERT 63.15,差距来自损失函数而非底座;
- 跨底座比泛化:未训练过的 SOHU 测试集上,
text2vec-base-chinese-paraphrase平均 63.08,比基于 MacBERT 训练的text2vec-base-chinese(51.61)高 11 分以上,说明数据集的多样性比底座大小更影响泛化。
Top-k 结果的读法:看第一名的分数绝对值 + 与第二名的分差。分差大(如 0.95 vs 0.36)说明检索置信度高;第一名只有 0.3 左右时,多半是候选库里没有真正相关的内容,应触发"无结果"兜底而不是硬取 Top-1。
图 3:SBERT 双塔结构,两条句子独立编码后取余弦,与 CoSENT 推理路径一致,区别在训练损失
工程化手段:让向量算得快、存得小
- 调大
batch_size:encode(batch_size=128)在 V100 上比默认 32 有可观的吞吐提升,代价是显存;OOM 就降档。README 的 QPS 数据(V100 实测):text2vec-base-chinese约 3008 条/秒,而 Word2Vec 约 23769 条/秒——纯 CPU 场景选后者更划算。 - 收窄
max_seq_length:默认 256,短问句场景设 64~128 可显著减少 padding 计算量,BGE 微调脚本默认就是 query 32 / passage 128。 - 开 bf16 与多卡训练:
train_model(bf16=True)配合data_parallel=True+torchrun --nproc_per_node 2起多进程数据并行,训练耗时接近减半,数值稳定性在 A100/V100 上无感知差异。 - 长文本先排序分批:
encode()内部已按长度排序,避免长短句混在一个 batch 里互相拖慢 padding;自定义 batch 逻辑时保留这一策略。 - 向量入库前降维:项目模型可用
sentence-transformers加载,直接复用其 PCA 降维脚本把 768 维压到 384/256 维,向量数据库存储压力减半,README 提到效果还有轻微提升。 - 归一化后换点积:
encode(normalize_embeddings=True)之后,余弦相似度可退化为一次点积,向量检索库中点积算子比余弦快。
避坑清单
| 现象 | 原因 | 解法 |
|---|---|---|
| 相似度分数普遍偏低、排序混乱 | 推理时的encoder_type与模型训练时不一致(如用CLS加载按FIRST_LAST_AVG训练的模型) | 按模型发布说明设置,中文 CoSENT 模型用FIRST_LAST_AVG或MEAN |
| 长句子打分明显变差 | 超过max_seq_length(默认 256)部分被truncation=True直接截断 | 按需调大max_seq_length,或对长文分段编码后聚合 |
| jsonl 训练数据一行都没读进去 | 字段名不是text1/text2或sentence1/sentence2 | 对齐 examples/data/snli_zh_50.jsonl 的格式,label支持 0/1 或 0~5 分 |
| CPU 上 QPS 只有个位数 | 768 维 BERT 在 CPU 上单条约数十毫秒 | 换Word2Vec(QPS 2 万+)或上 GPU;短期可用--multi_gpu True多进程分摊 |
| 字面相同的短文本反而分数不高 | 语义模型对极短文本(1~2 个字)区分度有限 | 短文本匹配场景优先用Word2Vec+Similarity(embedding_type=WORD2VEC),冷启动同样适用 |
两个落地场景的选型要点
智能客服的问题推荐与去重
- 意图匹配:用户 query 对 FAQ 库做
semantic_search(top_k=5),第一名分数 > 0.8 直接命中答案,0.5~0.8 走人工审核队列; - 去重:FAQ 入库前两两算余弦,> 0.92 判为重复条目合并,避免同义问题分散权重;
- 迭代:把客服对话中"已解答/未解答"的句对沉淀为 jsonl,定期用
training_sup_text_matching_model_jsonl_data.py微调。
语料库的近重复检索
- 百万级文档先离线
encode成向量存库(CLI 批量 +chunk_size分片),在线只做 query 单条编码,响应时间压到一次前向传播; - 阈值分层:分数 0.9 以上进"重复"区、0.7~0.9 进"相关"区、低于 0.7 不展示,分层阈值需在自身数据上校准;
- 冷启动无 GPU 时先用
Word2Vec跑通链路,后续换 BERT 类模型只改model_name一行。
回顾与下一步行动清单
- text2vec 提供"文本 → 768 维向量 → 余弦分数/Top-k 检索"的完整链路,五类模型统一了
encode()接口; - CoSENT 以余弦排序损失训练,同底座下比 SBERT 高约 5~6 分 Spearman,是中文语义匹配的首选架构;
- 默认模型
shibing624/text2vec-base-chinese三行代码即可出分,短文本/冷启动场景用Word2Vec兜底; - 性能杠杆排序:batch_size、max_seq_length、bf16+多卡、PCA 降维,全部有真实 API 支撑。
下一步行动清单
- 用 examples/semantic_text_similarity_demo.py 在你自己的句对上跑一遍,标定业务阈值;
- 若效果不达标,用 examples/training_sup_text_matching_model_jsonl_data.py 在自有 jsonl 数据上微调 1~2 个 epoch,用 tests/model_spearman.py 复测 Spearman;
- 向量入库前用
sentence-transformers的 PCA 脚本降维,核对存储与召回率; - 生产化部署参考 examples/fastapi_server_demo.py(HTTP)或 examples/jina_server_demo.py(gRPC),按并发需求选其一。
【免费下载链接】text2vectext2vec, text to vector. 文本向量表征工具,把文本转化为向量矩阵,实现了Word2Vec、RankBM25、Sentence-BERT、CoSENT等文本表征、文本相似度计算模型,开箱即用。项目地址: https://gitcode.com/GitHub_Trending/te/text2vec
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考