0%

SGLang的介绍和使用

SGLang是一个针对大语言模型和视觉语言模型的快速高效的服务框架,它的功能与vllm类似,用于部署开源模型,并提高模型的推理速度。

SGLang的安装

SGLang 的安装方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
方式一:
1. 直接使用pip或者uv安装
pip install "sglang[all]>=0.5.2rc2" -i https://pypi.tuna.tsinghua.edu.cn/simple

方式二:
1. 使用docker compose安装
如果需要将模型调用部署成单机或者单节点的服务,可以使用这种方式
1)拉取镜像到本地:docker pull lmsysorg/sglang:latest
2)使用docker-compose执行官方提供的compose.yml文件

compose.yml文件:
https://github.com/sgl-project/sglang/blob/main/docker/compose.yaml

官方还有其他方式,这里就不多介绍了,可以查阅文档:
https://docs.sglang.ai/get_started/install.html

以下代码中使用的是 Llama-3-8B-Instruct 这个模型,运行环境是 ubuntu22.04、RTX 4090D(24GB) * 1、16 vCPU Intel(R) Xeon(R) Platinum 8474C,不同模型对显存的要求不一样,如果模型参数小,可以使用更小的GPU。

由于模型文件和python包所占空间都很大,所以磁盘空间要足够大,不然在下载模型或者安装包的时候会进行不下去。

SGLang的用法

基础用法

离线推理

SGLang支持离线推理,非流式的代码如下:

1
2
3
4
5
6
7
8
9
10
import sglang as sgl


if __name__ == '__main__':
llm = sgl.Engine(model_path="/root/autodl-tmp/cache/models/LLM-Research/Meta-Llama-3-8B-Instruct")
prompt = "The capital of France is"
sampling_params = {"temperature": 0.8, "top_p": 0.95}

output = llm.generate(prompt, sampling_params, stream=True)
print(f"=====output: {output}")

需要流式输出时,在 generate 中加一个 stream=True 参数即可。

可以把离线推理的代码封装在 FastAPI 等web服务器中,通过接口调用离线推理。下面是一个简单的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import sglang as sgl
from fastapi import FastAPI
from pydantic import BaseModel
from contextlib import asynccontextmanager


engine = None


@asynccontextmanager
async def lifespan(app: FastAPI):
global engine
print("Loading SGLang engine...")
engine = sgl.Engine(
model_path="/root/autodl-tmp/cache/models/LLM-Research/Meta-Llama-3-8B-Instruct"
)
print("SGLang engine loaded.")
yield


app = FastAPI(lifespan=lifespan)


class Chat(BaseModel):
prompt: str



# chat completion
@app.post("/api/v1/chat/completion")
async def chat_completion(chat: Chat):
global engine
prompt = chat.prompt
sampling_params = {"temperature": 0.8, "top_p": 0.95}
# 调用 engine 的异步generate方法
output = await engine.async_generate(prompt, sampling_params)
return output


if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8011)

可以通过 python 脚本请求上面的接口:

1
2
3
4
5
6
7
8
9
import requests

response = requests.post(
"http://localhost:8011/api/v1/chat/completion",
json={
"prompt": "Please tell me the capital of France is",
},
)
print(response.json())

通过命令行启动服务

也可以直接通过命令行启动服务:

1
python -m sglang.launch_server --model-path /root/autodl-tmp/cache/models/LLM-Research/Meta-Llama-3-8B-Instruct --port 6006

上面是基于 Llama3-8B-Instruct 模型启动的一个服务,下面是请求这个大模型服务的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import requests


response = requests.post(
"http://localhost:6006/generate",
json={
"text": "The capital of France is", # text参数是输入的提示词
"sampling_params": {
"temperature": 0,
"max_new_tokens": 32,
},
},
)
print(response.json())

如果需要流式输出,可以加上 stream 参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import requests


response = requests.post(
"http://localhost:6006/generate",
json={
"text": "Please tell me the capital of France is",
"sampling_params": {
"temperature": 0,
"max_new_tokens": 32, # 最大输出token数
},
"stream": True, # 大模型的 stream 参数
},
stream=True # request请求的stream参数
)

for chunk in response.iter_lines(decode_unicode=False):
chunk = chunk.decode("utf-8")
print(f"=====chunk: {chunk}")

使用 openai 库调用大模型服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
import openai

client = openai.Client(base_url=f"http://127.0.0.1:6006/v1", api_key="None")

response = client.chat.completions.create(
model="Meta-Llama-3-8B-Instruct",
messages=[
{"role": "user", "content": "List 3 countries and their capitals."},
],
temperature=0,
max_tokens=64,
)
print(response)

通过Python脚本启动服务

SGLang也可以通过python脚本启动服务,就是把命令行的命令在python代码中执行,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
from sglang.test.doc_patch import launch_server_cmd
from sglang.utils import wait_for_server, print_highlight, terminate_process


if __name__ == '__main__':
server_process, port = launch_server_cmd(
"""
python -m sglang.launch_server --model-path /root/autodl-tmp/cache/models/LLM-Research/Meta-Llama-3-8B-Instruct --host 0.0.0.0 --log-level warning
"""
)
print(f"=====port: {port}")
wait_for_server(f"http://localhost:{port}")

调用上面的服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import requests


response = requests.post(
"http://localhost:39955/generate",
json={
"text": "Please tell me the capital of France is",
"sampling_params": {
"temperature": 0,
"max_new_tokens": 32,
},
},
)
print(response.json())

SGLang原生API

SGLang提供了原生API供我们调用大模型服务,上面使用的 /generate 就是其中一个原生API。部分原生API列表:

1
2
3
4
5
6
/generate
/get_model_info 获取模型信息
/get_server_info 获取模型服务的信息
/update_weights 在不重启服务的情况下,从磁盘上更新文件权重
/encode 将文本转换为向量,只适用于向量模型
/v1/rerank 对若干个文档查询对进行重排序,只适用于Cross-encoder的模型

/update_weights api的请求例子如下:

1
2
3
4
5
6
7
8
import requests


response = requests.post(
"http://localhost:39955/update_weights",
json={"model_path": "/root/autodl-tmp/cache/models/LLM-Research/Meta-Llama-3-8B-Instruct"}
)
print(response.json())

高级特性

SGLang Router

SGLang Router是一个高性能的请求分发系统,它可以把推理请求路由到多个 SGLang 运行实例上,它具有缓存感知负载平衡、容错功能,并支持高级部署模式,包括数据并行和预填充解码分解。

安装方式:

1
pip install sglang-router

SGLang Router 支持三种部署模型:

1
2
3
联合启动模式: Router和workers一起启动,适用于单节点部署
分开启动模式: Router和workers分别独立启动,如果是多节点部署,可以选择这种方式
预填充解码分解:分解服务的专用模式

联合启动模式是在一个命令行中同时启动router和worker进程,命令如下:

1
python -m sglang_router.launch_server --model-path /root/autodl-tmp/cache/models/Qwen/Qwen3-4B --dp-size 2 --host 0.0.0.0 --port 12073

通过router的服务调用推理服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
import requests

response = requests.post(
"http://localhost:12073/generate",
json={
"text": "你是谁",
"sampling_params": {
"temperature": 0,
"max_new_tokens": 32,
},
},
)
print(response.json())

分开启动模式是分别启动worker和router,先启动两个推理服务worker:

1
2
python -m sglang.launch_server --model-path /root/autodl-tmp/cache/models/Qwen/Qwen3-4B --mem-fraction-static 0.4 --port 12071
python -m sglang.launch_server --model-path /root/autodl-tmp/cache/models/Qwen/Qwen3-4B --mem-fraction-static 0.5 --port 12072

再启动router服务:

1
2
3
4
5
python -m sglang_router.launch_router \
--worker-urls http://localhost:12071 http://localhost:12072 \
--host 0.0.0.0 \
--port 12070 \
--policy random

可以通过 router 的 12070 端口调用服务,router 会根据策略将请求分发到不同的 worker 上。也可以通过 worker 的端口单独访问某个 worker。

其中,policy参数的可选值有:random、round_robin、cache_aware、power_of_two,默认值是 cache_aware。

policy参数值的含义:

1
2
3
4
random: 在 worker 之间随机分配请求
round_robin: 按顺序循环分发请求
power_of_two: 抽样两个 worker,将请求分配到负载较少的那个 worker 中
cache_aware: 结合了缓存优化与负载均衡的分发的策略

FastAPI中使用SGLang

最后看一个在 FastAPI 中调用 SGLang 的例子,主要功能是通过 SGLang 部署多个模型,然后通过 FastAPI 接口访问不同模型的推理服务。(或者部署多个 SGLang Router 服务,通过 Fast API 接口访问 SGLang Router 服务)

首先使用 SGLang 部署两个模型:

1
2
python -m sglang.launch_server --model-path /root/autodl-tmp/cache/models/Qwen/Qwen3-4B --mem-fraction-static 0.4 --port 12071
python -m sglang.launch_server --model-path /root/autodl-tmp/cache/models/Qwen/Qwen2.5-3B-Instruct --mem-fraction-static 0.5 --port 12072

然后在 FastAPI 接口中请求这两个服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import requests

import uvicorn
from fastapi import FastAPI
from pydantic import BaseModel


app = FastAPI()


# 模型与SGLang服务的映射关系,也可以放在配置文件中
MODEL_SGLANG_SERVER_MAPPING = {
"Qwen3-4B": "http://localhost:12071/generate",
"Qwen2.5-3B-Instruct": "http://localhost:12072/generate"
}


class Chat(BaseModel):
model: str
prompt: str


@app.post("/api/v1/chat/completion")
async def chat_completion(chat: Chat):
model = chat.model
server = MODEL_SGLANG_SERVER_MAPPING.get(model)
if not server:
return None

sampling_params = {"temperature": 0.8, "top_p": 0.95}
resp = requests.post(
server,
json={
"text": chat.prompt,
"sampling_params": sampling_params
}
)
return resp.json()


if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=12070)

调用 FastAPI 接口执行推理:

1
2
3
4
5
6
7
8
9
10
11
12
import requests


response = requests.post(
"http://localhost:12070/api/v1/chat/completion",
json={
"model": "Qwen2.5-3B-Instruct",
"prompt": "你是谁",
"stream": False
}
)
print(response.json())