🚀 acge模型
acge模型是由合合信息技术团队研发的一款通用文本编码模型,属于可变长度的向量化模型。合合信息是行业领先的人工智能及大数据科技企业,致力于通过智能文字识别及商业大数据领域的核心技术、C端和B端产品以及行业解决方案为全球企业和个人用户提供创新的数字化、智能化服务。该模型的对外技术试用平台为TextIn,其github开源链接为github。
若您有技术交流需求,请联系yanhui_he@intsig.net;若您有商务合作意向,请联系simon_liu@intsig.net。您还可以点击图片,扫描二维码加入我们的微信社群。如果您想加入合合信息,从事“文档解析”“文档检索”“文档预研”相关工作,可以将简历投递至min_du@intsig.net,也可直接添加HR微信详细了解岗位内容。
acge模型采用了Matryoshka Representation Learning技术,如下图所示:

建议使用的维度为1024或者1792。
属性 |
详情 |
模型名称 |
acge-text-embedding |
模型大小 (GB) |
0.65 |
维度 |
[1024, 1792] |
序列长度 |
1024 |
语言 |
中文 |
检索是否需要指令 |
否 |
✨ 主要特性
- 通用性强:作为通用的文本编码模型,能够处理多种文本相关任务。
- 可变长度:支持可变长度的文本向量化,具有更好的灵活性。
- 技术先进:采用了Matryoshka Representation Learning技术,提升了模型性能。
📦 安装指南
文档未提及安装相关内容,故跳过此章节。
💻 使用示例
基础用法
在sentence-transformer
库中的基本使用方法:
from sentence_transformers import SentenceTransformer
sentences = ["数据1", "数据2"]
model = SentenceTransformer('acge_text_embedding')
print(model.max_seq_length)
embeddings_1 = model.encode(sentences, normalize_embeddings=True)
embeddings_2 = model.encode(sentences, normalize_embeddings=True)
similarity = embeddings_1 @ embeddings_2.T
print(similarity)
高级用法
在sentence-transformer
库中选取不同维度的使用方法:
from sklearn.preprocessing import normalize
from sentence_transformers import SentenceTransformer
sentences = ["数据1", "数据2"]
model = SentenceTransformer('acge_text_embedding')
embeddings = model.encode(sentences, normalize_embeddings=False)
matryoshka_dim = 1024
embeddings = embeddings[..., :matryoshka_dim]
embeddings = normalize(embeddings, norm="l2", axis=1)
print(embeddings.shape)
📚 详细文档
指标评估
C-MTEB排行榜(中文)
测试时,由于数据的随机性、显卡以及推理的数据类型不同,每次推理的结果会存在差异。总共进行了4次测试,使用了不同的显卡(A10、A100)和不同的数据类型,测试结果存放在result
文件夹中。最终选取了精度最低的一次测试作为最终精度测试。根据infgrad的建议,选取不同的输入长度进行测试,当序列长度为512时测试效果最佳。
模型名称 |
GPU |
张量类型 |
模型大小 (GB) |
维度 |
序列长度 |
平均得分 (35) |
分类得分 (9) |
聚类得分 (4) |
成对分类得分 (2) |
重排序得分 (4) |
检索得分 (8) |
语义文本相似度得分 (8) |
acge_text_embedding |
NVIDIA TESLA A10 |
bfloat16 |
0.65 |
1792 |
1024 |
68.91 |
72.76 |
58.22 |
87.82 |
67.67 |
72.48 |
62.24 |
acge_text_embedding |
NVIDIA TESLA A100 |
bfloat16 |
0.65 |
1792 |
1024 |
68.91 |
72.77 |
58.35 |
87.82 |
67.53 |
72.48 |
62.24 |
acge_text_embedding |
NVIDIA TESLA A100 |
float16 |
0.65 |
1792 |
1024 |
68.99 |
72.76 |
58.68 |
87.84 |
67.89 |
72.49 |
62.24 |
acge_text_embedding |
NVIDIA TESLA A100 |
float32 |
0.65 |
1792 |
1024 |
68.98 |
72.76 |
58.58 |
87.83 |
67.91 |
72.49 |
62.24 |
acge_text_embedding |
NVIDIA TESLA A100 |
float16 |
0.65 |
1792 |
768 |
68.95 |
72.76 |
58.68 |
87.84 |
67.86 |
72.48 |
62.07 |
acge_text_embedding |
NVIDIA TESLA A100 |
float16 |
0.65 |
1792 |
512 |
69.07 |
72.75 |
58.7 |
87.84 |
67.99 |
72.93 |
62.09 |
复现结果
C-MTEB:
import torch
import argparse
import functools
from C_MTEB.tasks import *
from typing import List, Dict
from sentence_transformers import SentenceTransformer
from mteb import MTEB, DRESModel
class RetrievalModel(DRESModel):
def __init__(self, encoder, **kwargs):
self.encoder = encoder
def encode_queries(self, queries: List[str], **kwargs) -> np.ndarray:
input_texts = ['{}'.format(q) for q in queries]
return self._do_encode(input_texts)
def encode_corpus(self, corpus: List[Dict[str, str]], **kwargs) -> np.ndarray:
input_texts = ['{} {}'.format(doc.get('title', ''), doc['text']).strip() for doc in corpus]
input_texts = ['{}'.format(t) for t in input_texts]
return self._do_encode(input_texts)
@torch.no_grad()
def _do_encode(self, input_texts: List[str]) -> np.ndarray:
return self.encoder.encode(
sentences=input_texts,
batch_size=512,
normalize_embeddings=True,
convert_to_numpy=True
)
def get_args():
parser = argparse.ArgumentParser()
parser.add_argument('--model_name_or_path', default="acge_text_embedding", type=str)
parser.add_argument('--task_type', default=None, type=str)
parser.add_argument('--pooling_method', default='cls', type=str)
parser.add_argument('--output_dir', default='zh_results',
type=str, help='output directory')
parser.add_argument('--max_len', default=1024, type=int, help='max length')
return parser.parse_args()
if __name__ == '__main__':
args = get_args()
encoder = SentenceTransformer(args.model_name_or_path).half()
encoder.encode = functools.partial(encoder.encode, normalize_embeddings=True)
encoder.max_seq_length = int(args.max_len)
task_names = [t.description["name"] for t in MTEB(task_types=args.task_type,
task_langs=['zh', 'zh-CN']).tasks]
TASKS_WITH_PROMPTS = ["T2Retrieval", "MMarcoRetrieval", "DuRetrieval", "CovidRetrieval", "CmedqaRetrieval",
"EcomRetrieval", "MedicalRetrieval", "VideoRetrieval"]
for task in task_names:
evaluation = MTEB(tasks=[task], task_langs=['zh', 'zh-CN'])
if task in TASKS_WITH_PROMPTS:
evaluation.run(RetrievalModel(encoder), output_folder=args.output_dir, overwrite_results=False)
else:
evaluation.run(encoder, output_folder=args.output_dir, overwrite_results=False)
🔧 技术细节
文档未提及技术实现细节相关内容,故跳过此章节。
📄 许可证
文档未提及许可证信息,故跳过此章节。