importosfromoptimum.rblnimportRBLNLlamaForCausalLMmodel_id="meta-llama/Meta-Llama-3-8B-Instruct"# Compile and exportmodel=RBLNLlamaForCausalLM.from_pretrained(model_id=model_id,export=True,rbln_batch_size=1,rbln_max_seq_len=8192,rbln_num_devices=1,)# Save compiled results to diskmodel.save_pretrained(os.path.basename(model_id))
importosfromoptimum.rblnimportRBLNLlamaForCausalLMmodel_id="meta-llama/Meta-Llama-3-8B-Instruct"# Compile and exportmodel=RBLNLlamaForCausalLM.from_pretrained(model_id=model_id,export=True,rbln_batch_size=4,rbln_max_seq_len=8192,rbln_num_devices=4,)# Save compiled results to diskmodel.save_pretrained(os.path.basename(model_id))
Ray Serve에서 리소스를 할당하는 방식은 각 서빙 작업(Actor, Deployment)별로 resources 파라미터를 통해 NPU 자원을 할당할 수 있습니다.
아래 Actor는 @ray.remote(resources={"RBLN": <NUM_NPUS>})로 RBLN NPU 리소스를 요청하는 방법을 보여줍니다. <NUM_NPUS>는 컴파일할 때 사용한 rbln_num_devices 값과 같게 설정합니다. RBLNActor 클래스는 할당된 RBLN NPU ID를 Serve Deployment로 전달하는데 사용합니다. 이에 대한 자세한 내용은 Ray에서 RBLN NPU 사용에서 확인할 수 있습니다.
Ray Serve deployment는 @serve.deployment 데코레이터를 활용하여 클래스를 하나의 Deployment(배포 단위)로 정의합니다. 이 데코레이터를 적용하면 해당 클래스가 Ray Serve의 서비스 엔드포인트로 등록되어, 각 Deployment의 라이프사이클(배포, 확장, 업데이트 등)과 관리를 Ray Serve가 담당하게 됩니다.
importjsonimportosfromunittest.mockimportMagicMockimportrayfromfastapiimportFastAPI,HTTPExceptionfromrayimportservefromstarlette.requestsimportRequestfromstarlette.responsesimportStreamingResponsefromvllmimportAsyncEngineArgs,AsyncLLMEnginefromvllm.entrypoints.openai.chat_completion.protocolimport(ChatCompletionRequest,)fromvllm.entrypoints.openai.chat_completion.servingimportOpenAIServingChatfromvllm.entrypoints.openai.completion.protocolimportCompletionRequestfromvllm.entrypoints.openai.completion.servingimportOpenAIServingCompletionfromvllm.entrypoints.openai.models.protocolimportBaseModelPathfromvllm.entrypoints.openai.models.servingimportOpenAIServingModelsfromvllm.entrypoints.serve.engine.protocolimportErrorResponsefromvllm.renderers.online_rendererimportOnlineRendererapp=FastAPI()ray.init(resources={"RBLN":1})@ray.remote(resources={"RBLN":1})classRBLNActor:defgetDeviceId(self):returnray.get_runtime_context().get_accelerator_ids()["RBLN"]@serve.deployment(num_replicas=1,ray_actor_options={"num_cpus":16})@serve.ingress(app)classLlama3_8B:def__init__(self,rbln_actor:RBLNActor):""" Initialize actor. :return: """self.engine=Noneself.rbln_actor=rbln_actorself.model_name="Meta-Llama-3-8B-Instruct"self.raw_request=Noneself.vllm_engine=Noneself.openai_serving_models=Noneself.completion_service=Noneself.chat_completion_service=Noneself.ids=ray.get(rbln_actor.getDeviceId.remote())self.os_environment_vars()self.initialize()defos_environment_vars(self):""" Redefine the environment variables to be passed to the RBLN runtime and vLLM :return: """ifself.idsisNoneorlen(self.ids)<=0:os.environ.pop("RBLN_DEVICES")os.environ["RBLN_DEVICES"]=",".join(self.ids)os.environ["VLLM_WORKER_MULTIPROC_METHOD"]="spawn"definitialize(self):""" Initialize model. This will be called during model loading time :return: """vllm_engine_args=AsyncEngineArgs(model=self.model_name)self.vllm_engine=AsyncLLMEngine.from_engine_args(vllm_engine_args)self.openai_serving_models=OpenAIServingModels(engine_client=self.vllm_engine,base_model_paths=[BaseModelPath(name=self.model_name,model_path=os.getcwd())],)openai_serving_render=OnlineRenderer(model_config=self.vllm_engine.model_config,renderer=self.vllm_engine.renderer,request_logger=None,chat_template=None,chat_template_content_format="auto",)self.completion_service=OpenAIServingCompletion(self.vllm_engine,self.openai_serving_models,online_renderer=openai_serving_render,request_logger=None,)self.chat_completion_service=OpenAIServingChat(self.vllm_engine,self.openai_serving_models,"assistant",online_renderer=openai_serving_render,request_logger=None,chat_template_content_format="auto",chat_template=None,)asyncdefisd():returnFalseself.raw_request=MagicMock()self.raw_request.headers={}self.raw_request.is_disconnected=isd@app.post("/v1/chat/completions")asyncdefchat_completion(self,http_request:Request):""" Handle chat completion request. :param http_request: The HTTP request object :return: The chat completion response """try:json_string:dict=awaithttp_request.json()exceptjson.JSONDecodeError:raiseHTTPException(status_code=400,detail="Invalid JSON format request")request:ChatCompletionRequest=ChatCompletionRequest.model_validate(json_string)g=awaitself.chat_completion_service.create_chat_completion(request,self.raw_request)ifisinstance(g,ErrorResponse):return[g.model_dump()]ifrequest.stream:asyncdefstream_generator():asyncforresponseing:yieldresponsereturnStreamingResponse(stream_generator(),media_type="text/event-stream")else:return[g.model_dump()]@app.post("/v1/completions")asyncdefcompletion(self,http_request:Request):""" Handle completion request. :param http_request: The HTTP request object :return: The completion response """try:json_string:dict=awaithttp_request.json()exceptjson.JSONDecodeError:raiseHTTPException(status_code=400,detail="Invalid JSON format request")request:CompletionRequest=CompletionRequest.model_validate(json_string)g=awaitself.completion_service.create_completion(request,self.raw_request)ifisinstance(g,ErrorResponse):return[g.model_dump()]ifrequest.stream:asyncdefstream_generator():asyncforresponseing:yieldresponsereturnStreamingResponse(stream_generator(),media_type="text/event-stream")else:return[g.model_dump()]rbln_actor=RBLNActor.remote()app=Llama3_8B.bind(rbln_actor)
importjsonimportosfromunittest.mockimportMagicMockimportrayfromfastapiimportFastAPI,HTTPExceptionfromrayimportservefromstarlette.requestsimportRequestfromstarlette.responsesimportStreamingResponsefromvllmimportAsyncEngineArgs,AsyncLLMEnginefromvllm.entrypoints.openai.chat_completion.protocolimport(ChatCompletionRequest,)fromvllm.entrypoints.openai.chat_completion.servingimportOpenAIServingChatfromvllm.entrypoints.openai.completion.protocolimportCompletionRequestfromvllm.entrypoints.openai.completion.servingimportOpenAIServingCompletionfromvllm.entrypoints.openai.models.protocolimportBaseModelPathfromvllm.entrypoints.openai.models.servingimportOpenAIServingModelsfromvllm.entrypoints.serve.engine.protocolimportErrorResponsefromvllm.renderers.online_rendererimportOnlineRendererapp=FastAPI()ray.init(resources={"RBLN":4})@ray.remote(resources={"RBLN":4})classRBLNActor:defgetDeviceId(self):returnray.get_runtime_context().get_accelerator_ids()["RBLN"]@serve.deployment(num_replicas=1,ray_actor_options={"num_cpus":16})@serve.ingress(app)classLlama3_8B:def__init__(self,rbln_actor:RBLNActor):""" Initialize actor. :return: """self.engine=Noneself.rbln_actor=rbln_actorself.model_name="Meta-Llama-3-8B-Instruct"self.raw_request=Noneself.vllm_engine=Noneself.openai_serving_models=Noneself.completion_service=Noneself.chat_completion_service=Noneself.ids=ray.get(rbln_actor.getDeviceId.remote())self.os_environment_vars()self.initialize()defos_environment_vars(self):""" Redefine the environment variables to be passed to the RBLN runtime and vLLM :return: """ifself.idsisNoneorlen(self.ids)<=0:os.environ.pop("RBLN_DEVICES")os.environ["RBLN_DEVICES"]=",".join(self.ids)os.environ["VLLM_WORKER_MULTIPROC_METHOD"]="spawn"definitialize(self):""" Initialize model. This will be called during model loading time :return: """vllm_engine_args=AsyncEngineArgs(model=self.model_name)self.vllm_engine=AsyncLLMEngine.from_engine_args(vllm_engine_args)self.openai_serving_models=OpenAIServingModels(engine_client=self.vllm_engine,base_model_paths=[BaseModelPath(name=self.model_name,model_path=os.getcwd())],)openai_serving_render=OnlineRenderer(model_config=self.vllm_engine.model_config,renderer=self.vllm_engine.renderer,request_logger=None,chat_template=None,chat_template_content_format="auto",)self.completion_service=OpenAIServingCompletion(self.vllm_engine,self.openai_serving_models,online_renderer=openai_serving_render,request_logger=None,)self.chat_completion_service=OpenAIServingChat(self.vllm_engine,self.openai_serving_models,"assistant",online_renderer=openai_serving_render,request_logger=None,chat_template_content_format="auto",chat_template=None,)asyncdefisd():returnFalseself.raw_request=MagicMock()self.raw_request.headers={}self.raw_request.is_disconnected=isd@app.post("/v1/chat/completions")asyncdefchat_completion(self,http_request:Request):""" Handle chat completion request. :param http_request: The HTTP request object :return: The chat completion response """try:json_string:dict=awaithttp_request.json()exceptjson.JSONDecodeError:raiseHTTPException(status_code=400,detail="Invalid JSON format request")request:ChatCompletionRequest=ChatCompletionRequest.model_validate(json_string)g=awaitself.chat_completion_service.create_chat_completion(request,self.raw_request)ifisinstance(g,ErrorResponse):return[g.model_dump()]ifrequest.stream:asyncdefstream_generator():asyncforresponseing:yieldresponsereturnStreamingResponse(stream_generator(),media_type="text/event-stream")else:return[g.model_dump()]@app.post("/v1/completions")asyncdefcompletion(self,http_request:Request):""" Handle completion request. :param http_request: The HTTP request object :return: The completion response """try:json_string:dict=awaithttp_request.json()exceptjson.JSONDecodeError:raiseHTTPException(status_code=400,detail="Invalid JSON format request")request:CompletionRequest=CompletionRequest.model_validate(json_string)g=awaitself.completion_service.create_completion(request,self.raw_request)ifisinstance(g,ErrorResponse):return[g.model_dump()]ifrequest.stream:asyncdefstream_generator():asyncforresponseing:yieldresponsereturnStreamingResponse(stream_generator(),media_type="text/event-stream")else:return[g.model_dump()]rbln_actor=RBLNActor.remote()app=Llama3_8B.bind(rbln_actor)
echo'{"model": "Meta-Llama-3-8B-Instruct","prompt": "A robot may not injure a human being","stream": false}'|curl-sN-H"Content-Type: application/json"-XPOST--data-binary@-\http://localhost:8000/v1/completions|jq.
[{"id":"cmpl-6e39b262d7064dc882c3c3655f396906","object":"text_completion","created":1762938935,"model":"Meta-Llama-3-8B-Instruct","choices":[{"index":0,"text":" or, through inaction, allow a human being to come to harm.\nA","logprobs":null,"finish_reason":"length","stop_reason":null,"token_ids":null,"prompt_logprobs":null,"prompt_token_ids":null}],"service_tier":null,"system_fingerprint":null,"usage":{"prompt_tokens":10,"total_tokens":26,"completion_tokens":16,"prompt_tokens_details":null},"kv_transfer_params":null}]
echo'{"model": "Meta-Llama-3-8B-Instruct","messages": [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Who won the world series in 2020?"}, {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."}, {"role": "user", "content": "Where was it played?"}],"temperature": 0.0,"max_tokens": 50,"stream": false}'|curl-sN-H"Content-Type: application/json"-XPOST--data-binary@-\http://localhost:8000/v1/chat/completions|jq.
[{"id":"chatcmpl-3bbd9db1dc1243549ab942a74dabd2d8","object":"chat.completion","created":1762941547,"model":"Meta-Llama-3-8B-Instruct","choices":[{"index":0,"message":{"role":"assistant","content":"The 2020 World Series was played at Globe Life Field in Arlington, Texas, which is the home stadium of the Texas Rangers. However, the series was played with no fans in attendance due to the COVID-19 pandemic.","refusal":null,"annotations":null,"audio":null,"function_call":null,"tool_calls":[],"reasoning_content":null},"logprobs":null,"finish_reason":"stop","stop_reason":null,"token_ids":null}],"service_tier":null,"system_fingerprint":null,"usage":{"prompt_tokens":59,"total_tokens":106,"completion_tokens":47,"prompt_tokens_details":null},"prompt_logprobs":null,"prompt_token_ids":null,"kv_transfer_params":null}]