From 44bd31df38a09b4cfd17e3e7713de3fab613a9ad Mon Sep 17 00:00:00 2001 From: PopSoda2002 Date: Mon, 26 Jan 2026 04:48:07 +0000 Subject: [PATCH 1/2] VLM RLVR bug fix --- areal/workflow/vision_rlvr.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/areal/workflow/vision_rlvr.py b/areal/workflow/vision_rlvr.py index 64505c75fc..5dca232804 100644 --- a/areal/workflow/vision_rlvr.py +++ b/areal/workflow/vision_rlvr.py @@ -24,9 +24,9 @@ class VisionRLVRWorkflow(RLVRWorkflow): def __init__( self, - reward_fn: Callable[..., Any], + reward_fn: Callable[..., Any] | str, gconfig: GenerationHyperparameters, - tokenizer: PreTrainedTokenizerFast, + tokenizer: PreTrainedTokenizerFast | str, processor: AutoProcessor | str, enable_thinking: bool, ): @@ -101,6 +101,14 @@ async def _collect_samples( async def arun_episode( self, engine: InferenceEngine, data: dict[str, Any] ) -> dict[str, torch.Tensor]: + # NOTE: load reward function dynamically if given as string + if isinstance(self.reward_fn, str): + from areal.utils.dynamic_import import import_from_string + from areal.api.reward_api import AsyncRewardWrapper + + self.reward_fn = import_from_string(self.reward_fn) + self.async_reward_fn = AsyncRewardWrapper(self.reward_fn) + processor_callable = cast(Callable[..., dict[str, Any]], self.processor) processed_input = processor_callable( images=data["images"], From 229abcc47a6bec2ca2bc0c09833834f4396590db Mon Sep 17 00:00:00 2001 From: PopSoda2002 Date: Mon, 26 Jan 2026 04:54:54 +0000 Subject: [PATCH 2/2] fix bug --- areal/workflow/vision_rlvr.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/areal/workflow/vision_rlvr.py b/areal/workflow/vision_rlvr.py index 5dca232804..1df0da7704 100644 --- a/areal/workflow/vision_rlvr.py +++ b/areal/workflow/vision_rlvr.py @@ -8,8 +8,10 @@ from areal.api.cli_args import GenerationHyperparameters from areal.api.engine_api import InferenceEngine from areal.api.io_struct import ModelRequest, ModelResponse +from areal.api.reward_api import AsyncRewardWrapper from areal.core import workflow_context from areal.utils import logging, stats_tracker +from areal.utils.dynamic_import import import_from_string from areal.utils.image import image2base64 from areal.utils.perf_tracer import ( atrace_session_phase, @@ -103,12 +105,9 @@ async def arun_episode( ) -> dict[str, torch.Tensor]: # NOTE: load reward function dynamically if given as string if isinstance(self.reward_fn, str): - from areal.utils.dynamic_import import import_from_string - from areal.api.reward_api import AsyncRewardWrapper - self.reward_fn = import_from_string(self.reward_fn) self.async_reward_fn = AsyncRewardWrapper(self.reward_fn) - + processor_callable = cast(Callable[..., dict[str, Any]], self.processor) processed_input = processor_callable( images=data["images"],