updating serverless worker to include http streaming

This commit is contained in:
Jorg Doku
2023-07-17 16:28:55 -05:00
parent 57d7d7b589
commit 2c186072d2
2 changed files with 39 additions and 11 deletions
+1 -1
View File
@@ -30,6 +30,6 @@ RUN --mount=type=cache,target=/root/.cache/pip \
ADD src .
# Quick temporary updates
RUN pip install git+https://github.com/runpod/runpod-python@multijob#egg=runpod --compile
RUN pip install git+https://github.com/runpod/runpod-python@multijob#egg=runpod --compile
CMD python -u /handler.py
+38 -10
View File
@@ -1,6 +1,8 @@
#!/usr/bin/env python
''' Contains the handler function that will be called by the serverless. '''
from typing import Dict
import json
import types
from typing import AsyncGenerator, Dict
# Start the VLLM serving layer on our RunPod worker.
from vllm import AsyncLLMEngine, SamplingParams, AsyncEngineArgs
@@ -21,7 +23,11 @@ engine_args = AsyncEngineArgs(
seed = 0,
worker_use_ray=False,
)
# Create the vLLM asynchronous engine
llm = AsyncLLMEngine.from_engine_args(engine_args)
# Run the engine for one step without inputs to ensure it's ready for handling.
llm.engine.step()
def handler_fully_utilized() -> bool:
@@ -76,6 +82,7 @@ def validate_sampling_params(sampling_params):
'logprobs': logprobs,
}
async def handler(job):
'''
This is the handler function that will be called by the serverless worker.
@@ -88,6 +95,9 @@ async def handler(job):
# Prompts
prompt = job_input['prompt']
# Streaming
streaming = job_input['streaming'] or False
# Validate the inputs
sampling_params = job_input.get('sampling_params', None)
if sampling_params:
@@ -103,14 +113,32 @@ async def handler(job):
request_id = random_uuid()
results_generator = llm.generate(prompt, sampling_params, request_id)
# Non-streaming case
final_output = None
async for request_output in results_generator:
final_output = request_output
# Enable HTTP Streaming
async def stream_output():
# Streaming case
async for request_output in results_generator:
prompt = request_output.prompt
text_outputs = [
prompt + output.text for output in request_output.outputs
]
ret = {"text": text_outputs}
yield ret
prompt = final_output.prompt
text_outputs = [prompt + output.text for output in final_output.outputs]
ret = {"outputs": text_outputs}
return ret
# Regular submission
async def submit_output():
# Non-streaming case
final_output = None
async for request_output in results_generator:
final_output = request_output
runpod.serverless.start({"handler": handler, "multiprocessing": True, "handler_fully_utilized": handler_fully_utilized})
prompt = final_output.prompt
text_outputs = [prompt + output.text for output in final_output.outputs]
ret = {"outputs": text_outputs}
return ret
if streaming:
return await stream_output()
else:
return await submit_output()
runpod.serverless.start({"handler": handler, "handler_fully_utilized": handler_fully_utilized})