lang: support direct video inference (#9936)

Co-authored-by: Lianmin Zheng <lianminzheng@gmail.com>
This commit is contained in:
Mick
2025-10-23 18:12:39 -07:00
committed by GitHub
co-authored by Lianmin Zheng
parent 14a4d80e57
commit 823b442945
8 changed files with 52 additions and 69 deletions
+1 -1
View File
@@ -229,7 +229,7 @@ def image(expr: SglExpr):
return SglImage(expr)
def video(path: str, num_frames: int):
def video(path: str, num_frames: int = -1):
return SglVideo(path, num_frames)
@@ -104,6 +104,7 @@ class RuntimeEndpoint(BaseBackend):
def commit_lazy_operations(self, s: StreamExecutor):
data = {"text": s.text_, "sampling_params": {"max_new_tokens": 0}}
self._add_images(s, data)
self._add_videos(s, data)
res = http_request(
self.base_url + "/generate",
json=data,
@@ -115,6 +116,7 @@ class RuntimeEndpoint(BaseBackend):
def fill_image(self, s: StreamExecutor):
data = {"text": s.text_, "sampling_params": {"max_new_tokens": 0}}
self._add_images(s, data)
res = http_request(
self.base_url + "/generate",
json=data,
@@ -181,6 +183,7 @@ class RuntimeEndpoint(BaseBackend):
data[item] = value
self._add_images(s, data)
self._add_videos(s, data)
res = http_request(
self.base_url + "/generate",
@@ -222,6 +225,7 @@ class RuntimeEndpoint(BaseBackend):
data["stream"] = True
self._add_images(s, data)
self._add_videos(s, data)
res = http_request(
self.base_url + "/generate",
@@ -324,6 +328,8 @@ class RuntimeEndpoint(BaseBackend):
def _generate_http_request(self, s: StreamExecutor, data):
self._add_images(s, data)
self._add_videos(s, data)
res = http_request(
self.base_url + "/generate",
json=data,
@@ -338,6 +344,11 @@ class RuntimeEndpoint(BaseBackend):
assert len(s.images_) == 1, "Only support one image."
data["image_data"] = s.images_[0][1]
def _add_videos(self, s: StreamExecutor, data):
if s.videos_:
assert len(s.videos_) == 1, "Only support one video."
data["video_data"] = s.videos_
def _assert_success(self, res):
if res.status_code != 200:
try:
+3
View File
@@ -16,7 +16,9 @@ class ChatTemplate:
role_prefix_and_suffix: Dict[str, Tuple[str, str]]
stop_str: List[str] = ()
image_token: str = "<image>"
video_token: str = "<video>"
audio_token: str = "<audio>"
style: ChatTemplateStyle = ChatTemplateStyle.PLAIN
def get_prefix_and_suffix(
@@ -161,6 +163,7 @@ register_chat_template(
style=ChatTemplateStyle.PLAIN,
stop_str=("<|im_end|>",),
image_token="<|vision_start|><|image_pad|><|vision_end|>",
video_token="<|vision_start|><|video_pad|><|vision_end|>",
)
)
+5 -11
View File
@@ -32,11 +32,7 @@ from sglang.lang.ir import (
SglVarScopeEnd,
SglVideo,
)
from sglang.utils import (
encode_image_base64,
encode_video_base64,
get_exception_traceback,
)
from sglang.utils import encode_image_base64, get_exception_traceback
def run_internal(state, program, func_args, func_kwargs, sync):
@@ -286,6 +282,7 @@ class StreamExecutor:
# For vision
self.images_ = []
self.cur_images = []
self.videos_ = []
# For fork/join
self.fork_start_text_pos = None
@@ -372,6 +369,7 @@ class StreamExecutor:
exes[i].cur_role_begin_pos = self.cur_role_begin_pos
exes[i].fork_start_text_pos = len(self.text_)
exes[i].images_ = list(self.images_)
exes[i].videos_ = list(self.videos_)
# TODO(ying): handle API speculative execution
@@ -508,13 +506,9 @@ class StreamExecutor:
def _execute_video(self, expr: SglVideo):
path = expr.path
num_frames = expr.num_frames
base64_data = encode_video_base64(path, num_frames)
self.images_.append((path, base64_data))
self.cur_images.append((path, base64_data))
self.text_ += self.chat_template.image_token
self.videos_.append(path)
self.text_ += self.chat_template.video_token
def _spec_gen(self, sampling_params):
stop = sampling_params.stop
+1 -1
View File
@@ -445,7 +445,7 @@ class SglImage(SglExpr):
class SglVideo(SglExpr):
def __init__(self, path: str, num_frames: int):
def __init__(self, path: str, num_frames: int = -1):
self.path = path
self.num_frames = num_frames