Lightweight Reference/Reward scoring wrapper. The executor runs one full-sequence forward pass with ``use_cache=False`` whenever the wrapped model accepts that argument. It never calls a generation loop and it does not instantiate a paged-KV serving runtime.
| 91 | |
| 92 | |
| 93 | class StatelessForwardExecutor: |
| 94 | """ |
| 95 | Lightweight Reference/Reward scoring wrapper. |
| 96 | |
| 97 | The executor runs one full-sequence forward pass with ``use_cache=False`` |
| 98 | whenever the wrapped model accepts that argument. It never calls a |
| 99 | generation loop and it does not instantiate a paged-KV serving runtime. |
| 100 | """ |
| 101 | |
| 102 | def __init__( |
| 103 | self, |
| 104 | model: torch.nn.Module, |
| 105 | config: Optional[StatelessForwardConfig] = None, |
| 106 | *, |
| 107 | reward_adapter: Optional[RewardAdapter] = None, |
| 108 | ): |
| 109 | self.model = model |
| 110 | self.config = config or StatelessForwardConfig() |
| 111 | self.reward_adapter = reward_adapter or default_reward_adapter |
| 112 | |
| 113 | def score(self, inputs: StatelessForwardInputs) -> StatelessForwardResult: |
| 114 | _validate_inputs(inputs, self.config) |
| 115 | |
| 116 | device = inputs.input_ids.device |
| 117 | cuda_tracking = device.type == "cuda" and torch.cuda.is_available() |
| 118 | if cuda_tracking: |
| 119 | torch.cuda.reset_peak_memory_stats(device) |
| 120 | torch.cuda.synchronize(device) |
| 121 | |
| 122 | started_at = time.perf_counter() |
| 123 | with _temporarily_configure_stateless_model(self.model, self.config) as no_cache_policy: |
| 124 | with torch.no_grad(): |
| 125 | try: |
| 126 | raw_outputs, use_cache_passed = _run_no_cache_forward(self.model, inputs) |
| 127 | no_cache_policy["attention_backend_fallback"] = False |
| 128 | except Exception as exc: |
| 129 | if not _should_fallback_attention_backend(exc, self.config): |
| 130 | raise |
| 131 | fallback_config = replace(self.config, attention_backend="eager") |
| 132 | with _temporarily_configure_stateless_model( |
| 133 | self.model, |
| 134 | fallback_config, |
| 135 | ) as fallback_policy: |
| 136 | raw_outputs, use_cache_passed = _run_no_cache_forward(self.model, inputs) |
| 137 | no_cache_policy.update(fallback_policy) |
| 138 | no_cache_policy.update( |
| 139 | { |
| 140 | "attention_backend_requested": self.config.attention_backend, |
| 141 | "attention_backend_fallback": True, |
| 142 | "attention_backend_fallback_reason": ( |
| 143 | f"{type(exc).__name__}: {str(exc)[:200]}" |
| 144 | ), |
| 145 | } |
| 146 | ) |
| 147 | kv_cache = extract_kv_cache_outputs(raw_outputs) |
| 148 | kv_cache_summary = summarize_tensor_tree(kv_cache) |
| 149 | if self.config.reject_kv_cache_outputs and kv_cache is not None: |
| 150 | raise ValueError( |
no outgoing calls