Sentence Transformers 应用场景实战指南:从句向量计算到语义搜索、聚类与检索重排
导读
SentenceTransformers 是一个将句子、段落甚至图像编码为稠密向量的开源库,其应用远不止"算一个向量"这么简单。本文以仓库中 examples/sentence_transformer/applications/README.md 为骨架,系统梳理该库的九大核心应用场景:句向量计算、语义搜索、检索与重排(Retrieve & Re-Rank)、文本聚类、平行句挖掘、复述挖掘、图像搜索、文本摘要以及 Cross-Encoder 推断。读完本文,你将掌握每个场景的适用条件、核心 API 调用方式、关键参数含义,并能直接套用仓库中的示例脚本搭建自己的应用。
应用全景:一个模型,九种玩法
SentenceTransformers 的底层是一套"双塔(Siamese / Bi-Encoder)"结构:模型把输入文本映射到一个向量空间,使语义相近的文本在空间中彼此靠近。基于这一能力,应用示例目录 提供了九类开箱即用的示例脚本:
| 应用场景 | 示例目录 | 核心能力 |
|---|---|---|
| 句向量计算 | computing-embeddings | 单机/多 GPU 批量编码文本 |
| 语义搜索 | semantic-search | 按语义相似度在语料中检索 |
| 检索与重排 | retrieve_rerank | Bi-Encoder 召回 + Cross-Encoder 精排 |
| 文本聚类 | clustering | k-Means / 层次聚类 / 社区发现 |
| 平行句挖掘 | parallel-sentence-mining | 双语语料中寻找互译句对 |
| 复述挖掘 | paraphrase-mining | 大规模句子集中发现同义句 |
| 图像搜索 | image-search | 图文统一向量空间,跨模态检索 |
| 文本摘要 | text-summarization | 抽取式摘要(LexRank) |
| Cross-Encoder | cross_encoder/applications | 句对相似度打分 / 重排 |
下面逐一对这些场景展开。
计算句向量:一切应用的地基
所有下游应用都始于句向量计算。安装库之后,最快上手的方式是直接加载一个预训练模型并调用 encode,完整示例见 computing_embeddings.py:
from sentence_transformers import SentenceTransformer
# 1. 加载预训练模型(首次使用会自动下载)
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
# 2. 待编码的句子列表
sentences = [
"The weather is lovely today.",
"It's so sunny outside!",
"He drove to the stadium.",
]
# 3. 计算嵌入向量
embeddings = model.encode(sentences)
print(embeddings.shape)
# [3, 384] —— 3 个句子,每个 384 维
# 4. 计算向量间的相似度
similarities = model.similarity(embeddings, embeddings)
print(similarities)
# tensor([[1.0000, 0.6660, 0.1046],
# [0.6660, 1.0000, 0.1411],
# [0.1046, 0.1411, 1.0000]])
需要说明的是,虽然我们常说的是"sentence embeddings",但该方法同样适用于短语和由多个句子组成的长文本,只是长文本的嵌入质量取决于模型训练时的文本长度(见下文"输入序列长度"小节)。
初始化模型与设备选择
模型名可以是 Hugging Face 上的任意预训练模型 ID,也可以是本地目录:
model = SentenceTransformer("sentence-transformers/all-mpnet-base-v2")
# 或者加载本地微调后的模型目录
model = SentenceTransformer("output/models/mpnet-base-finetuned-all-nli")
模型会自动放置到当前最合适的设备(如 cuda 或 mps),也可以显式指定:
model = SentenceTransformer("sentence-transformers/all-mpnet-base-v2", device="cuda")
从源码看,encode 方法还支持更多推理参数(见 model.py):batch_size(默认 32,控制吞吐与显存)、precision(float32/int8/uint8/binary/ubinary,用于量化推理)、convert_to_numpy(默认 True,返回 NumPy 数组)、convert_to_tensor(返回 PyTorch 张量)、normalize_embeddings(是否归一化为单位向量)以及 truncate_dim(截断嵌入维度)。官方文档特别提示:batch_size 对处理速度影响显著,最佳值取决于硬件、模型大小、精度与输入长度,建议在小样本上先做基准测试。
Prompt 模板:让模型按任务"说话"
部分模型要求使用特定的文本前缀(prompt)才能发挥最佳性能。例如:
intfloat/multilingual-e5-large:查询须加"query: "前缀,段落须加"passage: "前缀;BAAI/bge-large-en-v1.5:检索时输入应加上"Represent this sentence for searching relevant passages: "。
SentenceTransformer 支持通过 prompts 与 default_prompt_name 两个参数管理这些模板,二者也可在模型保存后自动写入 config_sentence_transformers.json,下次加载时免手动指定:
model = SentenceTransformer(
"intfloat/multilingual-e5-large",
prompts={
"classification": "Classify the following text: ",
"retrieval": "Retrieve semantically similar text: ",
"clustering": "Identify the topic or theme based on the text: ",
},
default_prompt_name="retrieval",
)
# 也可在加载后动态赋值:
# model.prompts = {...}; model.default_prompt_name = "retrieval"
推理时应用 prompt 有三种等价方式:
# 1. 显式指定 prompt 文本
embeddings = model.encode("How to bake a strawberry cake", prompt="Retrieve semantically similar text: ")
# 2. 按 prompt 名称引用(来自初始化参数或模型配置)
embeddings = model.encode("How to bake a strawberry cake", prompt_name="retrieval")
# 3. 不指定时,自动套用 default_prompt_name;若其为 None 则不应用任何 prompt
embeddings = model.encode("How to bake a strawberry cake")
三种写法最终编码的是完全相同的文本序列。
输入序列长度:理解截断
以 BERT 为代表的 Transformer 模型,其运行时间与显存需求随输入长度二次方增长,因此每个模型都有最大序列长度,可通过 model.max_seq_length 查看,超长文本会被截断到前 max_seq_length 个 token:
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
print("Max Sequence Length:", model.max_seq_length)
# => Max Sequence Length: 256
model.max_seq_length = 200 # 主动下调
print("Max Sequence Length:", model.max_seq_length)
# => Max Sequence Length: 200
注意两点:其一,不能把长度调到超过底层 Transformer 模型支持的最大值;其二,若模型是在短文本上训练的,对长文本的表示质量可能不佳。
多进程 / 多 GPU 编码
面对超大语料,多进程/多 GPU 编码能带来接近线性的加速(完整示例见 computing_embeddings_multi_gpu.py)。encode 支持两种用法:
方式一:直接在 device 参数传入设备列表(["cuda:0", "cuda:1"] 或 ["cpu", "cpu", "cpu", "cpu"]),每次调用都会新建进程池:
def main():
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
embeddings = model.encode(inputs, device=["cuda:0", "cuda:1"])
if __name__ == "__main__":
main() # 必须放在 main 中,否则 CUDA 多进程会出问题
方式二:先调用 start_multi_process_pool() 创建可复用的进程池,多次 encode 共享同一个池,效率更高:
def main():
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
pool = model.start_multi_process_pool(target_devices=["cuda:0", "cuda:1"])
embeddings = model.encode(inputs, pool=pool)
model.stop_multi_process_pool(pool) # 用完务必关闭
if __name__ == "__main__":
main()
此外,chunk_size 参数控制发给每个进程的分块大小,与 batch_size 不同:例如 chunk_size=1000, batch_size=32 表示先把输入切成每 1000 条一块,每个进程收到一块后按 32 条一批编码。这对大数据的显存管理与性能调优很有帮助。多进程对大数据集收益明显,但小数据集上启动进程的开销可能大于收益。
语义搜索:理解含义,而非匹配字面
语义搜索通过理解查询与语料的语义含义提升检索准确率,对同义词、缩写、拼写错误都更鲁棒——这是纯关键词匹配做不到的。语义搜索示例目录 对此有完整论述。
原理与两种任务形态
核心思想是把语料中的所有条目(句子、段落或文档)嵌入到同一向量空间,检索时把查询也嵌入进来,找出空间中与查询最近的条目。
搭建语义搜索前必须区分对称与非对称任务,并据此选模型:
- 对称语义搜索:查询与语料条目长度、信息量相当。例如"如何在线学 Python?"去匹配"如何在网上学 Python?"。此时交换查询与语料条目也说得通。相关训练示例见 Quora 重复问题训练,适用模型见 预训练句嵌入模型。
- 非对称语义搜索:通常是短查询去匹配长段落。例如查询"What is Python",目标是找到"Python is an interpreted, high-level and general-purpose programming language..."这样的段落。此时交换查询与语料通常没有意义。相关训练示例见 MS MARCO 训练,适用模型见 MS MARCO 预训练模型。
选错模型类型会显著影响效果,务必按任务形态选择。
查询与文档的专用编码方法
针对非对称检索,官方推荐使用 encode_query 编码查询、encode_document 编码语料。与通用的 encode 相比,这两个方法的差异(见 model.py 的文档字符串)在于:
- 若未显式传入
prompt_name或prompt,它们会使用模型prompts字典中预定义的 "query"/"document" prompt; - 它们会把
task置为对应的 "query"/"document" 类型——如果模型带有Router模块,会据此把输入路由到合适的子模块。
encode 是最通用的方法,可用于包括信息检索在内的任何任务;如果模型没有预定义 prompt 和任务类型,三者返回的嵌入完全一致。
手动实现:小语料(约 100 万条以内)
用 encode_document 编码语料、encode_query 编码查询,再用 similarity 计算相似度即可。参考 semantic_search.py 的实现:
import torch
from sentence_transformers import SentenceTransformer
embedder = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
corpus = [
"Machine learning is a field of study that gives computers the ability to learn without being explicitly programmed.",
# ... 更多语料条目
]
# convert_to_tensor=True 让张量尽量留在 GPU 上
corpus_embeddings = embedder.encode_document(corpus, convert_to_tensor=True)
queries = [
"How do artificial neural networks work?",
"What technology is used for modern space exploration?",
"How can we address climate change challenges?",
]
top_k = min(5, len(corpus))
for query in queries:
query_embedding = embedder.encode_query(query, convert_to_tensor=True)
similarity_scores = embedder.similarity(query_embedding, corpus_embeddings)[0]
scores, indices = torch.topk(similarity_scores, k=top_k)
print("\nQuery:", query)
print("Top 5 most similar sentences in corpus:")
for score, idx in zip(scores, indices):
print(f"(Score: {score:.4f})", corpus[idx])
运行示例输出(节选):
Query: How do artificial neural networks work?
Top 5 most similar sentences in corpus:
(Score: 0.5926) Neural networks are computing systems vaguely inspired by the biological neural networks that constitute animal brains.
(Score: 0.5288) Deep learning is part of a broader family of machine learning methods based on artificial neural networks with representation learning.
...
Query: How can we address climate change challenges?
(Score: 0.3760) Global warming is the long-term heating of Earth's climate system observed since the pre-industrial period due to human activities.
(Score: 0.3144) Carbon capture technologies aim to collect CO2 emissions before they enter the atmosphere and store them underground.
可以看到,"神经网络"、"太空探索"、"气候变化"这些查询都能正确命中语义相近而非字面相同的句子。
优化实现:semantic_search 工具函数
官方封装了 semantic_search(位于 sentence_transformers.util),它内部替你完成了批量余弦相似度计算与 top-k 排序:
from sentence_transformers.util import semantic_search
hits = semantic_search(query_embedding, corpus_embeddings, top_k=5)
hits = hits[0] # 取第一个查询的结果
for hit in hits:
print(corpus[hit["corpus_id"]], "(Score: {:.4f})".format(hit["score"]))
其默认行为:最多 100 个查询并行处理,语料按最多 500k 条一块分块。可调大 query_chunk_size 与 corpus_chunk_size 来换取大语料上的更高速度,代价是内存占用上升。
速度优化技巧
将 query_embeddings 与 corpus_embeddings 放在同一块 GPU 上能显著提速;再把语料嵌入归一化为单位向量后,就可以用点积代替余弦相似度计算分数:
from sentence_transformers.util import dot_score, normalize_embeddings, semantic_search
corpus_embeddings = corpus_embeddings.to("cuda")
corpus_embeddings = normalize_embeddings(corpus_embeddings)
query_embeddings = query_embeddings.to("cuda")
query_embeddings = normalize_embeddings(query_embeddings)
hits = semantic_search(query_embeddings, corpus_embeddings, score_function=dot_score)
大规模语料:向量搜索引擎与 ANN
当语料达到百万级,精确最近邻(如 semantic_search 所做)会变慢,需要引入**近似最近邻(ANN)**索引:把数据划分成若干相似嵌入的分区,搜索时只需检索相关分区,毫秒级返回结果;代价是结果不一定精确,可能漏掉高分向量。所有 ANN 方法都存在"召回率-速度"的权衡参数:追求速度则漏检增多,追求召回则变慢。
仓库提供了三大主流 ANN 库的示例:
此外,semantic_search_quora_elasticsearch.py 展示如何利用 Elasticsearch 的稠密向量索引与 HNSW 近似最近邻搜索,在存储向量的同时附带其他业务字段;semantic_search_nq_opensearch.py 则演示用 OpenSearch 在 Natural Questions 数据集上同时实现语义搜索与 BM25 关键词搜索并相互比较。
典型用例一瞥
- 相似问题检索(对称任务):semantic_search_quora_pytorch.py 基于 Quora 重复问题数据集(约 50 万问题,脚本取前 10 万)构建检索系统,使用
sentence-transformers/quora-distilbert-multilingual模型,支持 50+ 语言——用户可以用任意语言输入问题,返回语料中最相似的问题。脚本还会把语料嵌入缓存为.pkl文件,避免重复编码。 - 相似论文检索(对称任务):semantic_search_publications.py 以 EMNLP 2016-2018 论文为语料,用 SPECTER 模型按标题+摘要检索相关论文。
- 问答检索(非对称任务):semantic_search_wikipedia_qa.py 使用在 Natural Questions 数据集(约 10 万条真实 Google 查询 + 维基百科答案段落)上训练的模型,以精简版英文维基百科为语料实现问答式检索。
检索与重排:Bi-Encoder 召回 + Cross-Encoder 精排
复杂检索场景(如问答)中,仅靠语义检索往往不够,官方推荐采用两阶段 Retrieve & Re-Rank 流水线,详见 retrieve_rerank/README.md。
第一阶段(召回/检索):给定查询,先用检索系统取回一批(例如 100 个)可能相关的候选项。检索既可以是基于词法的(如 Elasticsearch 等向量引擎),也可以是基于稠密向量的 Bi-Encoder。召回系统必须对百万级语料高效,但返回的候选中难免混入不相关项。
第二阶段(重排):用基于 Cross-Encoder 的重排器对全部候选按与查询的相关性打分。Cross-Encoder 把查询与文档同时送入 Transformer,输出一个 0~1 之间的相关性分数(见 CrossEncoder 示意图)。由于它让查询与文档之间做完整的注意力交互,精度更高,但直接对百万级(查询, 文档)句对打分太慢,所以只对召回阶段的约 100 个候选重排。
预训练模型速查
- Bi-Encoder(召回):如
sentence-transformers/multi-qa-mpnet-base-dot-v1,对段落与查询独立编码:
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("sentence-transformers/multi-qa-mpnet-base-dot-v1")
docs = ["My first paragraph. That contains information", "Python is a programming language."]
document_embeddings = model.encode(docs)
query = "What is Python?"
query_embedding = model.encode(query)
基于 MS MARCO(来自 Bing 搜索引擎的约 50 万真实用户查询)训练的召回模型见 MS MARCO 模型,Cross-Encoder 重排模型见 MS MARCO Cross-Encoders。
两个可直接运行的示例
- retrieve_rerank_simple_wikipedia.ipynb:以精简版英文维基百科为文档集。先把所有文章切成段落并用 Bi-Encoder 编码;用户输入问题后,用同一 Bi-Encoder 编码查询并按余弦相似度召回段落,再用 Cross-Encoder 对候选打分,返回得分最高的 5 个段落。
- in_document_search_crossencoder.py:面向单文档内搜索,跳过召回阶段。把"Europe"维基词条按段落切句,再以滑动窗口把每 3 个连续句子拼成一个 passage(
window_size可调:越小越丢上下文,越大保留更多上下文但结果更长),然后让 Cross-Encoder 对[query, passage]句对逐条打分并排序返回前 5:
from nltk import sent_tokenize
from sentence_transformers import CrossEncoder
# 文档切句 → 组 passage → 加载 Cross-Encoder
model = CrossEncoder("cross-encoder/ms-marco-TinyBERT-L2")
for query in queries:
model_inputs = [[query, passage] for passage in passages]
scores = model.predict(model_inputs)
results = sorted(
({"input": inp, "score": score} for inp, score in zip(model_inputs, scores)),
key=lambda x: x["score"], reverse=True,
)
for hit in results[0:5]:
print("Score: {:.2f}".format(hit["score"]), "\t", hit["input"][1])
脚本中的 cross-encoder/ms-marco-TinyBERT-L2 是一个仅 2 层的 BERT 模型,速度极快(脚本注释称在 V100 GPU 上每秒可打分的段落数可高达约 9000);想要更好效果可换更大的模型,但速度会下降。注意:由于每个新查询都要对全部段落打分,文档过大时该方法会变得低效。
文本聚类:从 k-Means 到社区发现
SentenceTransformers 可用于对少量或海量句子做聚类,详见 clustering/README.md。
- k-Means(kmeans.py):来自 scikit-learn 的经典算法,需要预先指定簇数量,聚类结果各簇规模大致相当。
- 层次聚类 / Agglomerative(agglomerative.py):与 k-Means 不同,可以指定一个相似度阈值,低于阈值的簇会被合并,因此无需预先知道簇数量;通过阈值可控制得到"多而细"还是"少而粗"的簇。缺点是较大数据集上较慢,只适用于几千句的规模。
- 快速聚类 / 社区发现(fast_clustering.py):面向大规模语料(脚本注释称 5 万句仅需约 5 秒,不含嵌入计算)。它在句子集中寻找"局部社区",即高度相似的句子组,核心是
sentence_transformers.util.community_detection函数:
from sentence_transformers.util import community_detection
# 两个可调参数:
# min_community_size: 至少包含 25 个元素的社区才保留
# threshold: 余弦相似度大于 0.75 才视为相似句对
clusters = community_detection(corpus_embeddings, min_community_size=25, threshold=0.75)
阈值越高只保留极其相似的句子,阈值越低能找到更多相似度较低的句子;min_community_size 则决定簇的最小规模。脚本在 Quora 重复问题数据集上输出的簇形如:
Cluster 1, #83 Elements
What should I do to improve my English ?
What should I do to improve my spoken English?
...
Cluster 2, #79 Elements
How can I earn money online?
How do I earn money online?
...
- 主题建模(Topic Modeling):即从文档集合中发现主题并抽取描述性词汇。SentenceTransformers 可用于识别句子、段落或短文档集合中的主题,相关教程可参考 BERTopic、Top2Vec 等项目;20 新闻组数据集的语义主题可视化 与每主题代表性词汇的可视化 展示了这类效果(图片来源于 Top2Vec 论文)。
平行句挖掘:双语语料中找互译句对
平行句挖掘(bitext mining)指在单语语料中发现互为翻译的句子对,例如从英文维基与德文维基中找出全部英德互译句对。仓库 parallel-sentence-mining/README.md 给出了完整方案。
其"基于边距(Margin Based)"的挖掘流程参照 Artetxe & Schwenk(2018)论文第 4.3 节:
- 先把两个语料中的所有句子编码为嵌入向量(官方论文指出
sentence-transformers/LaBSE是当时双语文本挖掘效果最好的模型,且已集成进库); - 对两个方向上的每个句子找到
k个最近邻,k的典型取值为 4~16; - 按论文 4.3 节公式对所有可能的句对打分;
- 得分最高的句对最有可能是互译句;注意该分数可以大于 1,通常需要一个截断阈值来剔除低质量句对——追求高质量时阈值取 1.2~1.3 效果较好。
仓库提供两个脚本:
- bucc2018.py:在 BUCC 2018 平行句发现评测任务上挖掘互译句对。由于该数据集标注了真实平行句对,脚本会输出使 F1 分数最高的最优阈值,便于评估不同策略。
- bitext_mining.py:读取两个每行一句的文本文件,把找到的平行句对输出到
*parallel-sentences-out.tsv.gz。
复述挖掘:大规模发现同义句
复述挖掘(paraphrase mining)是在大规模句子集合中发现语义相同或相似的句子(例如重复问题、重复句子)。paraphrase-mining/README.md 指出:如果对全部句对做暴力打分排序,复杂度是二次方的,无法扩展到上万句的规模;此时应使用 sentence_transformers.util.paraphrase_mining:
from sentence_transformers import SentenceTransformer
from sentence_transformers.util import paraphrase_mining
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
# 单个句子列表 —— 可以容纳数万句
sentences = [
"The cat sits outside",
"A man is playing guitar",
"I love pasta",
"The new movie is awesome",
"The cat plays in the garden",
"A woman watches TV",
"The new movie is so great",
"Do you like pizza?",
]
paraphrases = paraphrase_mining(model, sentences)
for score, i, j in paraphrases[0:10]:
print("{} \t\t {} \t\t Score: {:.4f}".format(sentences[i], sentences[j], score))
函数的关键参数:
query_chunk_size/corpus_chunk_size:为节省内存与时间,复述挖掘按块进行,每次只比较query_chunk_size * corpus_chunk_size个句对,而非len(sentences) * len(sentences);top_k:每个句子在每块中只保留得分最高的top_k个候选,是可调节的效率-效果权衡参数。例如下面的调用让每个句子只保留 1 个最相关的句子:
paraphrases = paraphrase_mining(model, sentences, corpus_chunk_size=len(sentences), top_k=1)
max_pairs:函数返回的最大复述句对数。
需要提醒的是:如果 B 是 A 最相似的句子,A 不一定是 B 最相似的句子,因此返回列表中可能出现 (A, B) 与 (B, C) 并存的情况。
图像搜索:图文统一向量空间
SentenceTransformers 自 1.0.0 版本起提供图文(image-text)模型,能把图像与文本映射到同一向量空间,从而实现以文搜图、以图搜文、以图搜图、以文搜文以及零样本图像分类。注意该功能仍处于实验阶段,需要安装 transformers 并使用较新的 PyTorch 版本(官方 README 标注的测试版本为 PyTorch 1.7.0)。
image-search/README.md 展示了基于 OpenAI CLIP 的封装用法:
from sentence_transformers import SentenceTransformer
from PIL import Image
# 加载 CLIP 模型
model = SentenceTransformer("sentence-transformers/clip-ViT-B-32")
# 编码图像(仓库 examples 目录自带示例图片 two_dogs_in_snow.jpg)
img_emb = model.encode(Image.open("two_dogs_in_snow.jpg"))
# 编码文本描述
text_emb = model.encode(["Two dogs in the snow", "A cat on a table", "A picture of London at night"])
# 计算相似度
similarity_scores = model.similarity(img_emb, text_emb)
print(similarity_scores)
除了开箱即用的四种跨模态检索,这类模型还可以用常规的 SentenceTransformers 训练代码在自有图文数据上微调。仓库在 image-search 目录 提供了 5 个 Notebook 示例:Image_Search.ipynb(用 2.5 万张 Unsplash 免费图片做文本到图像、图像到图像搜索)、image_search_multilingual.ipynb(50+ 语言的多语言文搜图)、Image_Clustering.ipynb(图像聚类)、Image_Duplicates.ipynb(重复/近似重复图像检测)、Image_Classification.ipynb(多语言零样本图像分类)。
文本摘要:基于 LexRank 的抽取式摘要
text-summarization/README.md 展示了如何用 SentenceTransformers 做抽取式摘要:把长文档切成句子并编码,计算所有句子两两之间的余弦相似度,然后用 LexRank 找出文档中最"中心"的句子——这些中心句就构成摘要的基础。
实现见 text_summarization.py(需要 pip install nltk,且需从仓库 lex_rank.py 引入 degree_centrality_scores,因为 pip 上的 LexRank 实现存在缺陷):
import nltk
import numpy as np
from lex_rank import degree_centrality_scores
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
# 将文档切成句子
sentences = nltk.sent_tokenize(document)
# 计算句嵌入与两两相似度
embeddings = model.encode(sentences)
similarity_scores = model.similarity(embeddings, embeddings).numpy()
# 用 LexRank 计算每个句子的中心度,取最高的 5 句作为摘要
centrality_scores = degree_centrality_scores(similarity_scores, threshold=None)
most_central_sentence_indices = np.argsort(-centrality_scores)
for idx in most_central_sentence_indices[0:5]:
print(sentences[idx].strip())
脚本以维基百科"New York City"词条首段为输入,输出的摘要集中在"纽约是人口最多、最具金融影响力的城市"等关键句上,能较好地概括全文。
Cross-Encoder:另一种模型形态
除句向量模型外,SentenceTransformers 同样支持训练与推断 Cross-Encoder:把两个句子同时送入 Transformer 网络,直接输出一个 0~1 的相似度分数或标签(详见 examples/cross_encoder/applications 目录)。与 Bi-Encoder 相比,Cross-Encoder 精度更高但无法预编码语料,因此它更适用于重排、句对分类等需要逐对打分的场景,而非大规模检索。
快速上手清单
- 环境准备:
pip install sentence-transformers,图像相关功能额外需要transformers与较新的 PyTorch;in_document_search_crossencoder.py、text_summarization.py需要nltk。 - 入门路径:先跑 computing_embeddings.py 感受编码与相似度计算,再根据任务形态(对称/非对称)选择 语义搜索 或 检索重排 示例。
- 大规模扩展:语料在百万级以内用
semantic_search;更大规模切换 ANN(FAISS / Annoy / hnswlib)或向量引擎(Elasticsearch / OpenSearch);海量编码用多进程池;重复句/互译句分别用paraphrase_mining与边距法挖掘。 - 参数速记:
encode的batch_size/precision/normalize_embeddings/truncate_dim控制推理性能;semantic_search的query_chunk_size/corpus_chunk_size控制内存与速度;paraphrase_mining的top_k/max_pairs控制挖掘效率与规模;community_detection的threshold/min_community_size控制聚类粒度;边距挖掘的k(4~16)与截断阈值(1.2~1.3)控制互译句对的召回与质量。
以上所有示例脚本均可从 applications 目录 直接复制运行,配合预训练模型与少量参数调优,即可快速落地各类语义应用。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考






