专栏名称: GiantPandaLLM
专注于机器学习、深度学习、计算机视觉、图像处理等多个方向技术分享。团队由一群热爱技术且热衷于分享的小伙伴组成。我们坚持原创,每天一到两篇原创技术分享。希望在传播知识、分享知识的同时能够启发你,大家一起共同进步(・ω<)☆
目录
相关文章推荐
GiantPandaLLM  ·  【博客转载】Row-Major VS ... ·  昨天  
51好读  ›  专栏  ›  GiantPandaLLM

小白视角:利用 SGL 来 Serve Embedding Model

GiantPandaLLM  · 公众号  · 3D  · 2024-11-16 20:21

主要观点总结

本文介绍了关于SGLang和Infinity框架在embedding模型服务上的使用体验和问题反馈。首先描述了项目需求以及使用的模型,然后对比了两个框架的优缺点和使用难度。接着详细描述了采用SGLang框架进行embedding模型服务部署的过程和优点。同时提到了SGLang目前存在的问题和改进思路。

关键观点总结

关键观点1: 项目需求和使用模型

项目需要使用embedding进行简单的聚类算法,采用了sentence_transformers中的模型进行示例。

关键观点2: Infinity框架的缺点

作者尝试使用Infinity框架进行embedding模型服务部署,但遇到了显存管理不稳定和模型支持有限的问题。

关键观点3: SGLang框架的优点

相比Infinity框架,SGLang在latency和显存稳定性方面表现更好,支持更多的模型,并且可以复用已有的模型类。但也有一些缺点,如暂不支持batch embedding和某些模型的support有限。

关键观点4: 迁移gte模型到SGLang的思路和解决方法

介绍了迁移gte模型到SGLang的思路和步骤,包括找到模型的真实architecture和复用已有的模型类等。同时提出了解决architecture冲突的方法,即通过添加参数来区分不同的返回类型。


正文

请到「今天看啥」查看全文


粗糙的显存管理导致了 serving 时显著不稳定。对于 vllm 和 SGLang,启动了 server 后显存占用几乎是固定的(实际上会有少许波动,因此对 SGLang memory upper bound 不宜高于 0.87)。采用比较保守的参数后,serving 服务相当的稳定;然而 Infinity 的 serving 就显著存在稳定性问题。

我在 48G A6000 上用我的上述参数启动了 Infinity server 后,显存占去了 32G(实际上与直接用 sentence_former 的占用一致,我合理怀疑 Infinity 仅仅是大量复用了 HuggingFace 的源码而添加了 API 接口)。 然而,大量的请求之后,会直接 OOM。OOM 后,serving 并不会断掉,反而是进入了“可以接到请求但是无法返回任何内容”的垃圾状态。 (我个人理解 OpenAI 的 client 利用了类似三次握手的机制,如果第一次握手能成功就会等待,而不成功则会直接返回 Connection Error。对于 SGLang 和 vllm 而言,发生 OOM 后 client 会直接得到 error,而 Infinity 居然能握手一次导致直接陷入垃圾等待状态)

看似完全的模型支持

Infinity 据称可以支持任意的 embedding model,因此我在 7b 的 gte model OOM 后立刻改用了 1.5B 的 gte model。我心想此时应该不会出现 OOM 问题,然而更大的问题出现了, 仅仅是将 serve 的模型改为 qw2_1.5b_emb 并更改了 API 请求里的 model 后,embedding 的返回值居然完全成了 [None, ...]

总之,这两点问题的存在,让我直接放弃了这个框架。当然,我的描述可能存在很多不准确内容,如果有对 Infinity 较为熟悉的读者或者作者团队的一员,请一定指正。

改用 SGLang serve Embeeding Model

我立刻改用了 SGLang 来进行 serving,请注意我的模型从前文的 gte-7b 更改为了 intfloat/e5-mistral-7b-instruct(本地命名为 e5_7b,更换模型的原因会在后文叙述):

CUDA_VISIBLE_DEVICES=3 python -m sglang.launch_server --enable-p2p-check \
--model-path e5_7b --dtype auto --tensor-parallel-size 1 \
--context-length 4096 --chunked-prefill-size 512  --port 7798 \
--host 0.0.0.0 --api-key HeiShenHuaWuKongVWo300 \
--enable-torch-compile  --mem-fraction-static 0.87

然后我们使用如下的代码来得到 embedding 结果:

from openai import OpenAI

emb_client = OpenAI(base_url="http://127.0.0.1:7798/v1", api_key="HeiShenHuaWuKongVWo300")


def online_emb(input_str):
   ret = emb_client.embeddings.create(input=input_str, model="e5_7b").data[0].embedding
   return ret

请注意 base_url 的结尾有了 v1 字样,事实上这才该是 OpenAI 的标准接口模样。(我不理解为什么 Infinity 居然没有这个 v1 标识)。

然后,SGLang 的优点就比较明确了:

  1. latency 显著低于 Infinity:当然我猜测这是 attention 方法优化的直接好处;

  2. 显存稳定:如上所述,不会出现运行时显存炸裂的情况;

基于这两点,当然我毫不犹豫的使用了 SGLang(囿于时间原因没有继续测试 vllm,当然 vllm 也支持 serve Embedding Model)。

当然,SGLang 目前在 serve Embedding Model 上也存在较多问题:

  1. 文档还没有描述怎么 serve Embedding Model:实际上和 serve completion model 是完全一致的,但是在文档的 OpenAI Compatible API 这一部分还没有写出(这是很小的瑕疵,主要是我比较菜,需要自己摸索下;经常烧 OpenAI API 的读者应该不存在这个问题)

  2. Support 的 Model 还比较有限:实际上目前仅仅 support e5 model,这也是我更换了模型的原因。一方面是 support 的 Model 比较少(目前仅仅一个 ),另一方面是 e5 的 context length 目前不宜超过 4k,和 gte 这种动辄 32k 的 context length 比起来还是相形见绌。

  3. 暂不支持 batch embedding:注意到我前文所有的 embedding request 都是 single string,而 SGLang 目前还暂不支持对于 batch of strings 的 embedding。

试试看让 SGLang support gte 模型呢?

当然,我已经尝试过了,不过目前暂未完成

我可以简单描述下这个过程的合理思路:

1. 找到 gte 模型在官网上的 modeling_qwen.py 文件:

https://huggingface.co/Alibaba-NLP/gte-Qwen2-7B-instruct/blob/main/modeling_qwen.py






请到「今天看啥」查看全文