| 76 | |
| 77 | @classmethod |
| 78 | def from_dict( |
| 79 | cls, |
| 80 | data: Mapping[str, Any] | None, |
| 81 | *, |
| 82 | base: SideChannelTaskConfig, |
| 83 | ) -> SideChannelTaskConfig: |
| 84 | if not data: |
| 85 | return base |
| 86 | primary = str(data.get("primary", base.primary)).strip() |
| 87 | if not primary: |
| 88 | raise ValueError("side-channel primary model cannot be empty") |
| 89 | fallback = tuple( |
| 90 | str(model).strip() |
| 91 | for model in data.get("fallback", base.fallback) |
| 92 | if str(model).strip() |
| 93 | ) |
| 94 | task = cls( |
| 95 | primary=primary, |
| 96 | fallback=fallback, |
| 97 | max_tokens=int(data.get("max_tokens", base.max_tokens)), |
| 98 | quality=QualityFallbackPolicy.from_dict( |
| 99 | data.get("quality"), |
| 100 | base=base.quality, |
| 101 | ), |
| 102 | ) |
| 103 | if task.max_tokens <= 0: |
| 104 | raise ValueError("side-channel max_tokens must be > 0") |
| 105 | return task |
| 106 | |
| 107 | def to_dict(self) -> dict[str, Any]: |
| 108 | return { |