Skip to content

Postero

PosterO prompt-config package.

PosterOAgent

Bases: BaseLayoutAgent[RawPosterOResponse]

High-level PosterO runner for prompt construction, parsing, and retries.

Parameters:

Name Type Description Default
model ModelLike

Optional Pydantic AI model object or provider model id.

None
config PosterOConfig

Runtime prompt and parser configuration.

required

Raises:

Type Description
ValueError

If config options are unsupported.

Examples:

>>> from pydantic_ai.models.test import TestModel
>>> from postero.config import PosterOConfig
>>> agent = PosterOAgent(model=TestModel(custom_output_args={"text": "<svg></svg>"}), config=PosterOConfig())
>>> isinstance(agent, PosterOAgent)
True
Source code in models/postero/src/postero/agent.py
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
class PosterOAgent(BaseLayoutAgent[RawPosterOResponse]):
    """High-level PosterO runner for prompt construction, parsing, and retries.

    Args:
        model: Optional Pydantic AI model object or provider model id.
        config: Runtime prompt and parser configuration.

    Raises:
        ValueError: If config options are unsupported.

    Examples:
        >>> from pydantic_ai.models.test import TestModel
        >>> from postero.config import PosterOConfig
        >>> agent = PosterOAgent(model=TestModel(custom_output_args={"text": "<svg></svg>"}), config=PosterOConfig())
        >>> isinstance(agent, PosterOAgent)
        True
    """

    def __init__(self, *, model: ModelLike = None, config: PosterOConfig) -> None:
        """Create a PosterO runner from explicit config."""
        self.config = config
        super().__init__(
            model=model,
            model_env_var=DEFAULT_MODEL_ENV_VAR,
            raw_response_type=RawPosterOResponse,
            instructions=INSTRUCTIONS,
        )

    def build_prompt(
        self,
        query_record: PosterORecord,
        *,
        candidate_records: Sequence[PosterORecord],
        labels: Sequence[int | str] | None = None,
        seed: int | None = None,
        generator: torch.Generator | None = None,
    ) -> tuple[str, list[PosterORecord]]:
        """Select exemplars and build the provider prompt.

        Args:
            query_record: Query poster record.
            candidate_records: Candidate exemplar records.
            labels: Optional labels to allocate.
            seed: Optional deterministic seed for random selection.
            generator: Optional torch generator. Takes precedence over ``seed``.

        Returns:
            Prompt text and selected exemplars.
        """
        exemplars = select_exemplars(
            query_record,
            candidate_records,
            config=self.config,
            seed=seed,
            generator=generator,
        )
        return (
            build_prompt(query_record, exemplars, config=self.config, labels=labels),
            exemplars,
        )

    def run_sync(
        self,
        query_record: PosterORecord,
        *,
        candidate_records: Sequence[PosterORecord],
        labels: Sequence[int | str] | None = None,
        model: ModelLike = None,
        seed: int | None = None,
        generator: torch.Generator | None = None,
        model_settings: ModelSettings | None = None,
    ) -> PosterOOutput:
        """Run the configured provider until enough valid SVGs are parsed.

        Args:
            query_record: Query poster record.
            candidate_records: Candidate exemplar records.
            labels: Optional labels to allocate.
            model: Optional per-call provider override.
            seed: Optional deterministic seed.
            generator: Optional torch generator. Takes precedence over ``seed``.
            model_settings: Optional provider sampling settings.

        Returns:
            Parsed PosterO output.

        Raises:
            RuntimeError: If no valid response is parsed within ``num_return``.
        """
        prompt, exemplars = self.build_prompt(
            query_record,
            candidate_records=candidate_records,
            labels=labels,
            seed=seed,
            generator=generator,
        )
        selected_ids = [record.id for record in exemplars]
        outputs: list[PosterOOutput] = []
        errors: list[str] = []
        for attempt in range(1, self.config.num_return + 1):
            raw = self.run_raw_sync(
                prompt,
                model=model,
                model_settings=model_settings
                or ModelSettings(
                    temperature=self.config.temperature,
                    top_p=self.config.top_p,
                    max_tokens=self.config.max_tokens,
                    frequency_penalty=self.config.frequency_penalty,
                    presence_penalty=self.config.presence_penalty,
                ),
            )
            try:
                elements, diagnostics = parse_svg_response(raw.text, config=self.config)
            except ValueError as exc:
                errors.append(str(exc))
                continue
            outputs.append(
                PosterOOutput(
                    prompt=prompt,
                    raw_text=raw.text,
                    elements=elements,
                    id2label=self.config.id2label or {},
                    canvas_size=self.config.canvas_size,
                    selected_exemplar_ids=selected_ids,
                    attempts=attempt,
                    parser_diagnostics=diagnostics,
                    parser_errors=list(errors),
                )
            )
            valid_count = sum(len(output.elements) for output in outputs)
            if valid_count >= self.config.n_valid_layouts:
                return merged_output(outputs, config=self.config)
        if outputs:
            return merged_output(outputs, config=self.config)
        msg = "PosterO could not parse a valid SVG response"
        raise RuntimeError(msg)

    def __call__(
        self,
        *,
        query_record: PosterORecord,
        candidate_records: Sequence[PosterORecord],
        batch_size: int = 1,
        seed: int | None = None,
        generator: torch.Generator | None = None,
        condition_type: str | ConditionType = ConditionType.content_image,
        labels: Int[torch.Tensor, "batch elements"] | list[int | str] | None = None,
        bbox: Float[torch.Tensor, "batch elements 4"]
        | Sequence[ArrayLikeInput]
        | None = None,
        mask: Bool[torch.Tensor, "batch elements"]
        | Sequence[ArrayLikeInput]
        | None = None,
        num_elements: int | list[int] | Int[torch.Tensor, "batch"] | None = None,
        box_format: str | BoxFormat = BoxFormat.xywh,
        normalized: bool = True,
        canvas_size: tuple[int, int] | None = None,
        num_inference_steps: int | None = None,
        output_type: str | OutputType = OutputType.dataclass,
        return_intermediates: bool = False,
        model: ModelLike = None,
        model_settings: ModelSettings | None = None,
    ) -> LayoutGenerationOutput | LayoutOutputDict:
        """Generate a poster layout through the shared public surface.

        Args:
            query_record: Query poster record with content-aware regions.
            candidate_records: Candidate records for retrieval.
            batch_size: Shared API batch size. PosterO supports ``1``.
            seed: Optional deterministic seed.
            generator: Optional torch generator. Takes precedence over ``seed``.
            condition_type: ``content_image`` or ``retrieval``.
            labels: Optional labels to allocate.
            bbox: Accepted for shared interface compatibility.
            mask: Accepted for shared interface compatibility.
            num_elements: Accepted for shared interface compatibility.
            box_format: Public input box format name.
            normalized: Accepted for shared interface compatibility.
            canvas_size: Optional canvas override; must match config.
            num_inference_steps: Accepted for shared interface compatibility.
            output_type: ``dataclass`` or ``dict``.
            return_intermediates: Whether to include prompt/parser metadata.
            model: Optional per-call provider override.
            model_settings: Optional provider settings override.

        Returns:
            Shared layout output dataclass or dictionary.

        Raises:
            ValueError: If shared arguments request unsupported behavior.
            RuntimeError: If provider responses cannot be parsed.
        """
        del bbox, mask, num_elements, normalized, num_inference_steps
        self._validate_request(
            batch_size=batch_size,
            condition_type=condition_type,
            box_format=box_format,
            canvas_size=canvas_size,
        )
        normalized_output_type = coerce_enum(output_type, OutputType)
        label_values = _labels_from_public(labels)
        output = self.run_sync(
            query_record,
            candidate_records=candidate_records,
            labels=label_values,
            model=model,
            seed=seed,
            generator=generator,
            model_settings=model_settings,
        ).to_layout_generation_output(return_intermediates=return_intermediates)
        if normalized_output_type is OutputType.dataclass:
            return output
        if normalized_output_type is OutputType.dict:
            return self.output_to_dict(output)
        assert_never(normalized_output_type)

    generate = __call__

    def save_pretrained(self, save_directory: str | os.PathLike[str]) -> None:
        """Persist prompt and parser configuration without provider state.

        Args:
            save_directory: Target directory for ``postero_config.json``.

        Returns:
            None.
        """
        path = Path(save_directory)
        path.mkdir(parents=True, exist_ok=True)
        (path / "postero_config.json").write_text(
            json.dumps(self.config.model_dump(mode="json"), indent=2, sort_keys=True)
            + "\n",
            encoding="utf-8",
        )

    @classmethod
    def from_pretrained(
        cls,
        pretrained_model_name_or_path: str | os.PathLike[str],
        *,
        model: ModelLike = None,
    ) -> "PosterOAgent":
        """Load saved PosterO prompt and parser configuration.

        Args:
            pretrained_model_name_or_path: Directory containing
                ``postero_config.json``.
            model: Replacement provider model.

        Returns:
            Configured PosterO agent.
        """
        path = Path(pretrained_model_name_or_path) / "postero_config.json"
        config_data = json.loads(path.read_text(encoding="utf-8"))
        return cls(model=model, config=PosterOConfig(**config_data))

    def resolve_model(self, model: ModelLike = None) -> ModelLike:
        """Resolve explicit model, environment model, or Pydantic default."""
        return (
            model or os.getenv(DEFAULT_MODEL_ENV_VAR) or os.getenv("PYDANTIC_AI_MODEL")
        )

    def _validate_request(
        self,
        *,
        batch_size: int,
        condition_type: str | ConditionType,
        box_format: str | BoxFormat,
        canvas_size: tuple[int, int] | None,
    ) -> None:
        normalized_condition = normalize_condition_type(condition_type)
        normalize_box_format(box_format)
        if batch_size != 1:
            msg = "PosterO currently supports batch_size=1."
            raise ValueError(msg)

        if normalized_condition not in SUPPORTED_CONDITION_TYPES:
            msg = f"unsupported condition_type for PosterO: {normalized_condition}"
            raise ValueError(msg)

        if canvas_size is not None and canvas_size != self.config.canvas_size:
            msg = "PosterO canvas_size must match the saved prompt config."
            raise ValueError(msg)

__init__

__init__(
    *, model: ModelLike = None, config: PosterOConfig
) -> None

Create a PosterO runner from explicit config.

Source code in models/postero/src/postero/agent.py
60
61
62
63
64
65
66
67
68
def __init__(self, *, model: ModelLike = None, config: PosterOConfig) -> None:
    """Create a PosterO runner from explicit config."""
    self.config = config
    super().__init__(
        model=model,
        model_env_var=DEFAULT_MODEL_ENV_VAR,
        raw_response_type=RawPosterOResponse,
        instructions=INSTRUCTIONS,
    )

build_prompt

build_prompt(
    query_record: PosterORecord,
    *,
    candidate_records: Sequence[PosterORecord],
    labels: Sequence[int | str] | None = None,
    seed: int | None = None,
    generator: Generator | None = None,
) -> tuple[str, list[PosterORecord]]

Select exemplars and build the provider prompt.

Parameters:

Name Type Description Default
query_record PosterORecord

Query poster record.

required
candidate_records Sequence[PosterORecord]

Candidate exemplar records.

required
labels Sequence[int | str] | None

Optional labels to allocate.

None
seed int | None

Optional deterministic seed for random selection.

None
generator Generator | None

Optional torch generator. Takes precedence over seed.

None

Returns:

Type Description
tuple[str, list[PosterORecord]]

Prompt text and selected exemplars.

Source code in models/postero/src/postero/agent.py
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
def build_prompt(
    self,
    query_record: PosterORecord,
    *,
    candidate_records: Sequence[PosterORecord],
    labels: Sequence[int | str] | None = None,
    seed: int | None = None,
    generator: torch.Generator | None = None,
) -> tuple[str, list[PosterORecord]]:
    """Select exemplars and build the provider prompt.

    Args:
        query_record: Query poster record.
        candidate_records: Candidate exemplar records.
        labels: Optional labels to allocate.
        seed: Optional deterministic seed for random selection.
        generator: Optional torch generator. Takes precedence over ``seed``.

    Returns:
        Prompt text and selected exemplars.
    """
    exemplars = select_exemplars(
        query_record,
        candidate_records,
        config=self.config,
        seed=seed,
        generator=generator,
    )
    return (
        build_prompt(query_record, exemplars, config=self.config, labels=labels),
        exemplars,
    )

run_sync

run_sync(
    query_record: PosterORecord,
    *,
    candidate_records: Sequence[PosterORecord],
    labels: Sequence[int | str] | None = None,
    model: ModelLike = None,
    seed: int | None = None,
    generator: Generator | None = None,
    model_settings: ModelSettings | None = None,
) -> PosterOOutput

Run the configured provider until enough valid SVGs are parsed.

Parameters:

Name Type Description Default
query_record PosterORecord

Query poster record.

required
candidate_records Sequence[PosterORecord]

Candidate exemplar records.

required
labels Sequence[int | str] | None

Optional labels to allocate.

None
model ModelLike

Optional per-call provider override.

None
seed int | None

Optional deterministic seed.

None
generator Generator | None

Optional torch generator. Takes precedence over seed.

None
model_settings ModelSettings | None

Optional provider sampling settings.

None

Returns:

Type Description
PosterOOutput

Parsed PosterO output.

Raises:

Type Description
RuntimeError

If no valid response is parsed within num_return.

Source code in models/postero/src/postero/agent.py
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
def run_sync(
    self,
    query_record: PosterORecord,
    *,
    candidate_records: Sequence[PosterORecord],
    labels: Sequence[int | str] | None = None,
    model: ModelLike = None,
    seed: int | None = None,
    generator: torch.Generator | None = None,
    model_settings: ModelSettings | None = None,
) -> PosterOOutput:
    """Run the configured provider until enough valid SVGs are parsed.

    Args:
        query_record: Query poster record.
        candidate_records: Candidate exemplar records.
        labels: Optional labels to allocate.
        model: Optional per-call provider override.
        seed: Optional deterministic seed.
        generator: Optional torch generator. Takes precedence over ``seed``.
        model_settings: Optional provider sampling settings.

    Returns:
        Parsed PosterO output.

    Raises:
        RuntimeError: If no valid response is parsed within ``num_return``.
    """
    prompt, exemplars = self.build_prompt(
        query_record,
        candidate_records=candidate_records,
        labels=labels,
        seed=seed,
        generator=generator,
    )
    selected_ids = [record.id for record in exemplars]
    outputs: list[PosterOOutput] = []
    errors: list[str] = []
    for attempt in range(1, self.config.num_return + 1):
        raw = self.run_raw_sync(
            prompt,
            model=model,
            model_settings=model_settings
            or ModelSettings(
                temperature=self.config.temperature,
                top_p=self.config.top_p,
                max_tokens=self.config.max_tokens,
                frequency_penalty=self.config.frequency_penalty,
                presence_penalty=self.config.presence_penalty,
            ),
        )
        try:
            elements, diagnostics = parse_svg_response(raw.text, config=self.config)
        except ValueError as exc:
            errors.append(str(exc))
            continue
        outputs.append(
            PosterOOutput(
                prompt=prompt,
                raw_text=raw.text,
                elements=elements,
                id2label=self.config.id2label or {},
                canvas_size=self.config.canvas_size,
                selected_exemplar_ids=selected_ids,
                attempts=attempt,
                parser_diagnostics=diagnostics,
                parser_errors=list(errors),
            )
        )
        valid_count = sum(len(output.elements) for output in outputs)
        if valid_count >= self.config.n_valid_layouts:
            return merged_output(outputs, config=self.config)
    if outputs:
        return merged_output(outputs, config=self.config)
    msg = "PosterO could not parse a valid SVG response"
    raise RuntimeError(msg)

__call__

__call__(
    *,
    query_record: PosterORecord,
    candidate_records: Sequence[PosterORecord],
    batch_size: int = 1,
    seed: int | None = None,
    generator: Generator | None = None,
    condition_type: str
    | ConditionType = ConditionType.content_image,
    labels: Int[Tensor, "batch elements"]
    | list[int | str]
    | None = None,
    bbox: Float[Tensor, "batch elements 4"]
    | Sequence[ArrayLikeInput]
    | None = None,
    mask: Bool[Tensor, "batch elements"]
    | Sequence[ArrayLikeInput]
    | None = None,
    num_elements: int
    | list[int]
    | Int[Tensor, "batch"]
    | None = None,
    box_format: str | BoxFormat = BoxFormat.xywh,
    normalized: bool = True,
    canvas_size: tuple[int, int] | None = None,
    num_inference_steps: int | None = None,
    output_type: str | OutputType = OutputType.dataclass,
    return_intermediates: bool = False,
    model: ModelLike = None,
    model_settings: ModelSettings | None = None,
) -> LayoutGenerationOutput | LayoutOutputDict

Generate a poster layout through the shared public surface.

Parameters:

Name Type Description Default
query_record PosterORecord

Query poster record with content-aware regions.

required
candidate_records Sequence[PosterORecord]

Candidate records for retrieval.

required
batch_size int

Shared API batch size. PosterO supports 1.

1
seed int | None

Optional deterministic seed.

None
generator Generator | None

Optional torch generator. Takes precedence over seed.

None
condition_type str | ConditionType

content_image or retrieval.

content_image
labels Int[Tensor, 'batch elements'] | list[int | str] | None

Optional labels to allocate.

None
bbox Float[Tensor, 'batch elements 4'] | Sequence[ArrayLikeInput] | None

Accepted for shared interface compatibility.

None
mask Bool[Tensor, 'batch elements'] | Sequence[ArrayLikeInput] | None

Accepted for shared interface compatibility.

None
num_elements int | list[int] | Int[Tensor, 'batch'] | None

Accepted for shared interface compatibility.

None
box_format str | BoxFormat

Public input box format name.

xywh
normalized bool

Accepted for shared interface compatibility.

True
canvas_size tuple[int, int] | None

Optional canvas override; must match config.

None
num_inference_steps int | None

Accepted for shared interface compatibility.

None
output_type str | OutputType

dataclass or dict.

dataclass
return_intermediates bool

Whether to include prompt/parser metadata.

False
model ModelLike

Optional per-call provider override.

None
model_settings ModelSettings | None

Optional provider settings override.

None

Returns:

Type Description
LayoutGenerationOutput | LayoutOutputDict

Shared layout output dataclass or dictionary.

Raises:

Type Description
ValueError

If shared arguments request unsupported behavior.

RuntimeError

If provider responses cannot be parsed.

Source code in models/postero/src/postero/agent.py
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
def __call__(
    self,
    *,
    query_record: PosterORecord,
    candidate_records: Sequence[PosterORecord],
    batch_size: int = 1,
    seed: int | None = None,
    generator: torch.Generator | None = None,
    condition_type: str | ConditionType = ConditionType.content_image,
    labels: Int[torch.Tensor, "batch elements"] | list[int | str] | None = None,
    bbox: Float[torch.Tensor, "batch elements 4"]
    | Sequence[ArrayLikeInput]
    | None = None,
    mask: Bool[torch.Tensor, "batch elements"]
    | Sequence[ArrayLikeInput]
    | None = None,
    num_elements: int | list[int] | Int[torch.Tensor, "batch"] | None = None,
    box_format: str | BoxFormat = BoxFormat.xywh,
    normalized: bool = True,
    canvas_size: tuple[int, int] | None = None,
    num_inference_steps: int | None = None,
    output_type: str | OutputType = OutputType.dataclass,
    return_intermediates: bool = False,
    model: ModelLike = None,
    model_settings: ModelSettings | None = None,
) -> LayoutGenerationOutput | LayoutOutputDict:
    """Generate a poster layout through the shared public surface.

    Args:
        query_record: Query poster record with content-aware regions.
        candidate_records: Candidate records for retrieval.
        batch_size: Shared API batch size. PosterO supports ``1``.
        seed: Optional deterministic seed.
        generator: Optional torch generator. Takes precedence over ``seed``.
        condition_type: ``content_image`` or ``retrieval``.
        labels: Optional labels to allocate.
        bbox: Accepted for shared interface compatibility.
        mask: Accepted for shared interface compatibility.
        num_elements: Accepted for shared interface compatibility.
        box_format: Public input box format name.
        normalized: Accepted for shared interface compatibility.
        canvas_size: Optional canvas override; must match config.
        num_inference_steps: Accepted for shared interface compatibility.
        output_type: ``dataclass`` or ``dict``.
        return_intermediates: Whether to include prompt/parser metadata.
        model: Optional per-call provider override.
        model_settings: Optional provider settings override.

    Returns:
        Shared layout output dataclass or dictionary.

    Raises:
        ValueError: If shared arguments request unsupported behavior.
        RuntimeError: If provider responses cannot be parsed.
    """
    del bbox, mask, num_elements, normalized, num_inference_steps
    self._validate_request(
        batch_size=batch_size,
        condition_type=condition_type,
        box_format=box_format,
        canvas_size=canvas_size,
    )
    normalized_output_type = coerce_enum(output_type, OutputType)
    label_values = _labels_from_public(labels)
    output = self.run_sync(
        query_record,
        candidate_records=candidate_records,
        labels=label_values,
        model=model,
        seed=seed,
        generator=generator,
        model_settings=model_settings,
    ).to_layout_generation_output(return_intermediates=return_intermediates)
    if normalized_output_type is OutputType.dataclass:
        return output
    if normalized_output_type is OutputType.dict:
        return self.output_to_dict(output)
    assert_never(normalized_output_type)

save_pretrained

save_pretrained(
    save_directory: str | PathLike[str],
) -> None

Persist prompt and parser configuration without provider state.

Parameters:

Name Type Description Default
save_directory str | PathLike[str]

Target directory for postero_config.json.

required

Returns:

Type Description
None

None.

Source code in models/postero/src/postero/agent.py
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
def save_pretrained(self, save_directory: str | os.PathLike[str]) -> None:
    """Persist prompt and parser configuration without provider state.

    Args:
        save_directory: Target directory for ``postero_config.json``.

    Returns:
        None.
    """
    path = Path(save_directory)
    path.mkdir(parents=True, exist_ok=True)
    (path / "postero_config.json").write_text(
        json.dumps(self.config.model_dump(mode="json"), indent=2, sort_keys=True)
        + "\n",
        encoding="utf-8",
    )

from_pretrained classmethod

from_pretrained(
    pretrained_model_name_or_path: str | PathLike[str],
    *,
    model: ModelLike = None,
) -> "PosterOAgent"

Load saved PosterO prompt and parser configuration.

Parameters:

Name Type Description Default
pretrained_model_name_or_path str | PathLike[str]

Directory containing postero_config.json.

required
model ModelLike

Replacement provider model.

None

Returns:

Type Description
'PosterOAgent'

Configured PosterO agent.

Source code in models/postero/src/postero/agent.py
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
@classmethod
def from_pretrained(
    cls,
    pretrained_model_name_or_path: str | os.PathLike[str],
    *,
    model: ModelLike = None,
) -> "PosterOAgent":
    """Load saved PosterO prompt and parser configuration.

    Args:
        pretrained_model_name_or_path: Directory containing
            ``postero_config.json``.
        model: Replacement provider model.

    Returns:
        Configured PosterO agent.
    """
    path = Path(pretrained_model_name_or_path) / "postero_config.json"
    config_data = json.loads(path.read_text(encoding="utf-8"))
    return cls(model=model, config=PosterOConfig(**config_data))

resolve_model

resolve_model(model: ModelLike = None) -> ModelLike

Resolve explicit model, environment model, or Pydantic default.

Source code in models/postero/src/postero/agent.py
299
300
301
302
303
def resolve_model(self, model: ModelLike = None) -> ModelLike:
    """Resolve explicit model, environment model, or Pydantic default."""
    return (
        model or os.getenv(DEFAULT_MODEL_ENV_VAR) or os.getenv("PYDANTIC_AI_MODEL")
    )

PosterOConfig

Bases: BaseModel

Runtime prompt, retrieval, parser, and provider settings.

Parameters:

Name Type Description Default
dataset_name

Poster dataset name. Public aliases are normalized through posgen.common.

required
structure

Prompt serialization structure.

required
injection

Available-area injection strategy.

required
pool_strategy

Candidate pool strategy.

required
rank_strategy

Exemplar ranking strategy.

required
sample_size

Number of candidate records considered before ranking.

required
num_return

Maximum provider attempts for one public call.

required
n_valid_layouts

Number of valid parsed layouts requested.

required
canvas_size

Canvas size as (width, height).

required
temperature

Provider sampling temperature.

required
top_p

Provider nucleus sampling value.

required
max_tokens

Maximum response tokens requested from a provider.

required
frequency_penalty

Provider frequency penalty.

required
presence_penalty

Provider presence penalty.

required
stop_token

Provider stop token.

required
label_rback

Whether parser labels are mapped back to configured ids.

required
prompt_target

Structured response target.

required
id2label

Public label ids. Defaults preserve PosterO issue mappings.

required

Raises:

Type Description
ValueError

If a closed mode or dataset name is unsupported.

Examples:

>>> config = PosterOConfig(dataset_name="pku")
>>> config.id2label[1]
'text'
Source code in models/postero/src/postero/config.py
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
class PosterOConfig(BaseModel):
    """Runtime prompt, retrieval, parser, and provider settings.

    Args:
        dataset_name: Poster dataset name. Public aliases are normalized through
            ``posgen.common``.
        structure: Prompt serialization structure.
        injection: Available-area injection strategy.
        pool_strategy: Candidate pool strategy.
        rank_strategy: Exemplar ranking strategy.
        sample_size: Number of candidate records considered before ranking.
        num_return: Maximum provider attempts for one public call.
        n_valid_layouts: Number of valid parsed layouts requested.
        canvas_size: Canvas size as ``(width, height)``.
        temperature: Provider sampling temperature.
        top_p: Provider nucleus sampling value.
        max_tokens: Maximum response tokens requested from a provider.
        frequency_penalty: Provider frequency penalty.
        presence_penalty: Provider presence penalty.
        stop_token: Provider stop token.
        label_rback: Whether parser labels are mapped back to configured ids.
        prompt_target: Structured response target.
        id2label: Public label ids. Defaults preserve PosterO issue mappings.

    Raises:
        ValueError: If a closed mode or dataset name is unsupported.

    Examples:
        >>> config = PosterOConfig(dataset_name="pku")
        >>> config.id2label[1]
        'text'
    """

    dataset_name: DatasetName | str = DatasetName.pku_posterlayout
    structure: PosterOStructure | str = PosterOStructure.hierarchical
    injection: PosterOInjection | str = PosterOInjection.top
    pool_strategy: PosterOPoolStrategy | str = PosterOPoolStrategy.metric_filter
    rank_strategy: PosterORankStrategy | str = PosterORankStrategy.rank_by_feature
    sample_size: int = Field(default=10, ge=1)
    num_return: int = Field(default=10, ge=1)
    n_valid_layouts: int = Field(default=10, ge=1)
    canvas_size: tuple[int, int] = DEFAULT_CANVAS_SIZE
    temperature: float = 0.7
    top_p: float = 1.0
    max_tokens: int = 800
    frequency_penalty: float = 0.0
    presence_penalty: float = 0.0
    stop_token: str = "\n\n"
    label_rback: bool = True
    prompt_target: PromptTarget | str = PromptTarget.rect_only
    id2label: dict[int, str] | None = None

    model_config = ConfigDict(frozen=True)

    @field_validator("dataset_name")
    @classmethod
    def normalize_dataset(cls, value: DatasetName | str) -> DatasetName:
        """Normalize poster dataset aliases at the config boundary."""
        return normalize_dataset_name(value)

    @field_validator("structure")
    @classmethod
    def normalize_structure(cls, value: PosterOStructure | str) -> PosterOStructure:
        """Normalize prompt structure."""
        return coerce_enum(value, PosterOStructure)

    @field_validator("injection")
    @classmethod
    def normalize_injection(cls, value: PosterOInjection | str) -> PosterOInjection:
        """Normalize available-area injection mode."""
        return coerce_enum(value, PosterOInjection)

    @field_validator("pool_strategy")
    @classmethod
    def normalize_pool_strategy(
        cls, value: PosterOPoolStrategy | str
    ) -> PosterOPoolStrategy:
        """Normalize pool strategy."""
        return coerce_enum(value, PosterOPoolStrategy)

    @field_validator("rank_strategy")
    @classmethod
    def normalize_rank_strategy(
        cls, value: PosterORankStrategy | str
    ) -> PosterORankStrategy:
        """Normalize rank strategy."""
        return coerce_enum(value, PosterORankStrategy)

    @field_validator("prompt_target")
    @classmethod
    def normalize_prompt_target(cls, value: PromptTarget | str) -> PromptTarget:
        """Normalize prompt target."""
        return coerce_enum(value, PromptTarget)

    @model_validator(mode="after")
    def fill_id2label(self) -> "PosterOConfig":
        """Fill dataset-specific label ids when no explicit map is stored."""
        if self.id2label is not None:
            return self
        mapping = (
            CGL_ID2LABEL
            if self.dataset_name in {DatasetName.cgl, DatasetName.cgl_v2}
            else PKU_ID2LABEL
        )
        object.__setattr__(self, "id2label", dict(mapping))
        return self

normalize_dataset classmethod

normalize_dataset(value: DatasetName | str) -> DatasetName

Normalize poster dataset aliases at the config boundary.

Source code in models/postero/src/postero/config.py
83
84
85
86
87
@field_validator("dataset_name")
@classmethod
def normalize_dataset(cls, value: DatasetName | str) -> DatasetName:
    """Normalize poster dataset aliases at the config boundary."""
    return normalize_dataset_name(value)

normalize_structure classmethod

normalize_structure(
    value: PosterOStructure | str,
) -> PosterOStructure

Normalize prompt structure.

Source code in models/postero/src/postero/config.py
89
90
91
92
93
@field_validator("structure")
@classmethod
def normalize_structure(cls, value: PosterOStructure | str) -> PosterOStructure:
    """Normalize prompt structure."""
    return coerce_enum(value, PosterOStructure)

normalize_injection classmethod

normalize_injection(
    value: PosterOInjection | str,
) -> PosterOInjection

Normalize available-area injection mode.

Source code in models/postero/src/postero/config.py
95
96
97
98
99
@field_validator("injection")
@classmethod
def normalize_injection(cls, value: PosterOInjection | str) -> PosterOInjection:
    """Normalize available-area injection mode."""
    return coerce_enum(value, PosterOInjection)

normalize_pool_strategy classmethod

normalize_pool_strategy(
    value: PosterOPoolStrategy | str,
) -> PosterOPoolStrategy

Normalize pool strategy.

Source code in models/postero/src/postero/config.py
101
102
103
104
105
106
107
@field_validator("pool_strategy")
@classmethod
def normalize_pool_strategy(
    cls, value: PosterOPoolStrategy | str
) -> PosterOPoolStrategy:
    """Normalize pool strategy."""
    return coerce_enum(value, PosterOPoolStrategy)

normalize_rank_strategy classmethod

normalize_rank_strategy(
    value: PosterORankStrategy | str,
) -> PosterORankStrategy

Normalize rank strategy.

Source code in models/postero/src/postero/config.py
109
110
111
112
113
114
115
@field_validator("rank_strategy")
@classmethod
def normalize_rank_strategy(
    cls, value: PosterORankStrategy | str
) -> PosterORankStrategy:
    """Normalize rank strategy."""
    return coerce_enum(value, PosterORankStrategy)

normalize_prompt_target classmethod

normalize_prompt_target(
    value: PromptTarget | str,
) -> PromptTarget

Normalize prompt target.

Source code in models/postero/src/postero/config.py
117
118
119
120
121
@field_validator("prompt_target")
@classmethod
def normalize_prompt_target(cls, value: PromptTarget | str) -> PromptTarget:
    """Normalize prompt target."""
    return coerce_enum(value, PromptTarget)

fill_id2label

fill_id2label() -> 'PosterOConfig'

Fill dataset-specific label ids when no explicit map is stored.

Source code in models/postero/src/postero/config.py
123
124
125
126
127
128
129
130
131
132
133
134
@model_validator(mode="after")
def fill_id2label(self) -> "PosterOConfig":
    """Fill dataset-specific label ids when no explicit map is stored."""
    if self.id2label is not None:
        return self
    mapping = (
        CGL_ID2LABEL
        if self.dataset_name in {DatasetName.cgl, DatasetName.cgl_v2}
        else PKU_ID2LABEL
    )
    object.__setattr__(self, "id2label", dict(mapping))
    return self

AvailableRegion

Bases: BaseModel

One available poster area in pixel ltrb coordinates.

Source code in models/postero/src/postero/records.py
14
15
16
17
18
19
class AvailableRegion(BaseModel):
    """One available poster area in pixel ``ltrb`` coordinates."""

    bbox_ltrb: tuple[float, float, float, float]

    model_config = ConfigDict(frozen=True)

PosterLayoutElement

Bases: BaseModel

One poster layout element in pixel ltrb coordinates.

Source code in models/postero/src/postero/records.py
22
23
24
25
26
27
28
29
30
class PosterLayoutElement(BaseModel):
    """One poster layout element in pixel ``ltrb`` coordinates."""

    label: int | str
    bbox_ltrb: tuple[float, float, float, float]
    rotation: float | None = None
    path_data: str | None = None

    model_config = ConfigDict(frozen=True)

PosterORecord

Bases: BaseModel

One poster prompt or exemplar record.

Parameters:

Name Type Description Default
id

Stable record id used in parity reports.

required
dataset

Dataset key.

required
poster_path

Optional source image path.

required
canvas_size

Canvas size as (width, height).

required
available_regions

Content-aware available regions.

required
elements

Ground-truth or generated layout elements.

required
features

Optional precomputed retrieval feature vector.

required
metrics

Optional quality metrics used by pool filtering.

required
metadata

Extra non-runtime metadata.

required
Source code in models/postero/src/postero/records.py
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class PosterORecord(BaseModel):
    """One poster prompt or exemplar record.

    Args:
        id: Stable record id used in parity reports.
        dataset: Dataset key.
        poster_path: Optional source image path.
        canvas_size: Canvas size as ``(width, height)``.
        available_regions: Content-aware available regions.
        elements: Ground-truth or generated layout elements.
        features: Optional precomputed retrieval feature vector.
        metrics: Optional quality metrics used by pool filtering.
        metadata: Extra non-runtime metadata.
    """

    id: str
    dataset: str
    poster_path: str | None = None
    canvas_size: tuple[int, int] = (513, 750)
    available_regions: list[AvailableRegion] = Field(default_factory=list)
    elements: list[PosterLayoutElement] = Field(default_factory=list)
    features: list[float] | None = None
    metrics: dict[str, float] = Field(default_factory=dict)
    metadata: dict[str, object] = Field(default_factory=dict)

    model_config = ConfigDict(frozen=True)

agent

Provider-agnostic Pydantic AI wrapper for PosterO.

PosterOAgent

Bases: BaseLayoutAgent[RawPosterOResponse]

High-level PosterO runner for prompt construction, parsing, and retries.

Parameters:

Name Type Description Default
model ModelLike

Optional Pydantic AI model object or provider model id.

None
config PosterOConfig

Runtime prompt and parser configuration.

required

Raises:

Type Description
ValueError

If config options are unsupported.

Examples:

>>> from pydantic_ai.models.test import TestModel
>>> from postero.config import PosterOConfig
>>> agent = PosterOAgent(model=TestModel(custom_output_args={"text": "<svg></svg>"}), config=PosterOConfig())
>>> isinstance(agent, PosterOAgent)
True
Source code in models/postero/src/postero/agent.py
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
class PosterOAgent(BaseLayoutAgent[RawPosterOResponse]):
    """High-level PosterO runner for prompt construction, parsing, and retries.

    Args:
        model: Optional Pydantic AI model object or provider model id.
        config: Runtime prompt and parser configuration.

    Raises:
        ValueError: If config options are unsupported.

    Examples:
        >>> from pydantic_ai.models.test import TestModel
        >>> from postero.config import PosterOConfig
        >>> agent = PosterOAgent(model=TestModel(custom_output_args={"text": "<svg></svg>"}), config=PosterOConfig())
        >>> isinstance(agent, PosterOAgent)
        True
    """

    def __init__(self, *, model: ModelLike = None, config: PosterOConfig) -> None:
        """Create a PosterO runner from explicit config."""
        self.config = config
        super().__init__(
            model=model,
            model_env_var=DEFAULT_MODEL_ENV_VAR,
            raw_response_type=RawPosterOResponse,
            instructions=INSTRUCTIONS,
        )

    def build_prompt(
        self,
        query_record: PosterORecord,
        *,
        candidate_records: Sequence[PosterORecord],
        labels: Sequence[int | str] | None = None,
        seed: int | None = None,
        generator: torch.Generator | None = None,
    ) -> tuple[str, list[PosterORecord]]:
        """Select exemplars and build the provider prompt.

        Args:
            query_record: Query poster record.
            candidate_records: Candidate exemplar records.
            labels: Optional labels to allocate.
            seed: Optional deterministic seed for random selection.
            generator: Optional torch generator. Takes precedence over ``seed``.

        Returns:
            Prompt text and selected exemplars.
        """
        exemplars = select_exemplars(
            query_record,
            candidate_records,
            config=self.config,
            seed=seed,
            generator=generator,
        )
        return (
            build_prompt(query_record, exemplars, config=self.config, labels=labels),
            exemplars,
        )

    def run_sync(
        self,
        query_record: PosterORecord,
        *,
        candidate_records: Sequence[PosterORecord],
        labels: Sequence[int | str] | None = None,
        model: ModelLike = None,
        seed: int | None = None,
        generator: torch.Generator | None = None,
        model_settings: ModelSettings | None = None,
    ) -> PosterOOutput:
        """Run the configured provider until enough valid SVGs are parsed.

        Args:
            query_record: Query poster record.
            candidate_records: Candidate exemplar records.
            labels: Optional labels to allocate.
            model: Optional per-call provider override.
            seed: Optional deterministic seed.
            generator: Optional torch generator. Takes precedence over ``seed``.
            model_settings: Optional provider sampling settings.

        Returns:
            Parsed PosterO output.

        Raises:
            RuntimeError: If no valid response is parsed within ``num_return``.
        """
        prompt, exemplars = self.build_prompt(
            query_record,
            candidate_records=candidate_records,
            labels=labels,
            seed=seed,
            generator=generator,
        )
        selected_ids = [record.id for record in exemplars]
        outputs: list[PosterOOutput] = []
        errors: list[str] = []
        for attempt in range(1, self.config.num_return + 1):
            raw = self.run_raw_sync(
                prompt,
                model=model,
                model_settings=model_settings
                or ModelSettings(
                    temperature=self.config.temperature,
                    top_p=self.config.top_p,
                    max_tokens=self.config.max_tokens,
                    frequency_penalty=self.config.frequency_penalty,
                    presence_penalty=self.config.presence_penalty,
                ),
            )
            try:
                elements, diagnostics = parse_svg_response(raw.text, config=self.config)
            except ValueError as exc:
                errors.append(str(exc))
                continue
            outputs.append(
                PosterOOutput(
                    prompt=prompt,
                    raw_text=raw.text,
                    elements=elements,
                    id2label=self.config.id2label or {},
                    canvas_size=self.config.canvas_size,
                    selected_exemplar_ids=selected_ids,
                    attempts=attempt,
                    parser_diagnostics=diagnostics,
                    parser_errors=list(errors),
                )
            )
            valid_count = sum(len(output.elements) for output in outputs)
            if valid_count >= self.config.n_valid_layouts:
                return merged_output(outputs, config=self.config)
        if outputs:
            return merged_output(outputs, config=self.config)
        msg = "PosterO could not parse a valid SVG response"
        raise RuntimeError(msg)

    def __call__(
        self,
        *,
        query_record: PosterORecord,
        candidate_records: Sequence[PosterORecord],
        batch_size: int = 1,
        seed: int | None = None,
        generator: torch.Generator | None = None,
        condition_type: str | ConditionType = ConditionType.content_image,
        labels: Int[torch.Tensor, "batch elements"] | list[int | str] | None = None,
        bbox: Float[torch.Tensor, "batch elements 4"]
        | Sequence[ArrayLikeInput]
        | None = None,
        mask: Bool[torch.Tensor, "batch elements"]
        | Sequence[ArrayLikeInput]
        | None = None,
        num_elements: int | list[int] | Int[torch.Tensor, "batch"] | None = None,
        box_format: str | BoxFormat = BoxFormat.xywh,
        normalized: bool = True,
        canvas_size: tuple[int, int] | None = None,
        num_inference_steps: int | None = None,
        output_type: str | OutputType = OutputType.dataclass,
        return_intermediates: bool = False,
        model: ModelLike = None,
        model_settings: ModelSettings | None = None,
    ) -> LayoutGenerationOutput | LayoutOutputDict:
        """Generate a poster layout through the shared public surface.

        Args:
            query_record: Query poster record with content-aware regions.
            candidate_records: Candidate records for retrieval.
            batch_size: Shared API batch size. PosterO supports ``1``.
            seed: Optional deterministic seed.
            generator: Optional torch generator. Takes precedence over ``seed``.
            condition_type: ``content_image`` or ``retrieval``.
            labels: Optional labels to allocate.
            bbox: Accepted for shared interface compatibility.
            mask: Accepted for shared interface compatibility.
            num_elements: Accepted for shared interface compatibility.
            box_format: Public input box format name.
            normalized: Accepted for shared interface compatibility.
            canvas_size: Optional canvas override; must match config.
            num_inference_steps: Accepted for shared interface compatibility.
            output_type: ``dataclass`` or ``dict``.
            return_intermediates: Whether to include prompt/parser metadata.
            model: Optional per-call provider override.
            model_settings: Optional provider settings override.

        Returns:
            Shared layout output dataclass or dictionary.

        Raises:
            ValueError: If shared arguments request unsupported behavior.
            RuntimeError: If provider responses cannot be parsed.
        """
        del bbox, mask, num_elements, normalized, num_inference_steps
        self._validate_request(
            batch_size=batch_size,
            condition_type=condition_type,
            box_format=box_format,
            canvas_size=canvas_size,
        )
        normalized_output_type = coerce_enum(output_type, OutputType)
        label_values = _labels_from_public(labels)
        output = self.run_sync(
            query_record,
            candidate_records=candidate_records,
            labels=label_values,
            model=model,
            seed=seed,
            generator=generator,
            model_settings=model_settings,
        ).to_layout_generation_output(return_intermediates=return_intermediates)
        if normalized_output_type is OutputType.dataclass:
            return output
        if normalized_output_type is OutputType.dict:
            return self.output_to_dict(output)
        assert_never(normalized_output_type)

    generate = __call__

    def save_pretrained(self, save_directory: str | os.PathLike[str]) -> None:
        """Persist prompt and parser configuration without provider state.

        Args:
            save_directory: Target directory for ``postero_config.json``.

        Returns:
            None.
        """
        path = Path(save_directory)
        path.mkdir(parents=True, exist_ok=True)
        (path / "postero_config.json").write_text(
            json.dumps(self.config.model_dump(mode="json"), indent=2, sort_keys=True)
            + "\n",
            encoding="utf-8",
        )

    @classmethod
    def from_pretrained(
        cls,
        pretrained_model_name_or_path: str | os.PathLike[str],
        *,
        model: ModelLike = None,
    ) -> "PosterOAgent":
        """Load saved PosterO prompt and parser configuration.

        Args:
            pretrained_model_name_or_path: Directory containing
                ``postero_config.json``.
            model: Replacement provider model.

        Returns:
            Configured PosterO agent.
        """
        path = Path(pretrained_model_name_or_path) / "postero_config.json"
        config_data = json.loads(path.read_text(encoding="utf-8"))
        return cls(model=model, config=PosterOConfig(**config_data))

    def resolve_model(self, model: ModelLike = None) -> ModelLike:
        """Resolve explicit model, environment model, or Pydantic default."""
        return (
            model or os.getenv(DEFAULT_MODEL_ENV_VAR) or os.getenv("PYDANTIC_AI_MODEL")
        )

    def _validate_request(
        self,
        *,
        batch_size: int,
        condition_type: str | ConditionType,
        box_format: str | BoxFormat,
        canvas_size: tuple[int, int] | None,
    ) -> None:
        normalized_condition = normalize_condition_type(condition_type)
        normalize_box_format(box_format)
        if batch_size != 1:
            msg = "PosterO currently supports batch_size=1."
            raise ValueError(msg)

        if normalized_condition not in SUPPORTED_CONDITION_TYPES:
            msg = f"unsupported condition_type for PosterO: {normalized_condition}"
            raise ValueError(msg)

        if canvas_size is not None and canvas_size != self.config.canvas_size:
            msg = "PosterO canvas_size must match the saved prompt config."
            raise ValueError(msg)

__init__

__init__(
    *, model: ModelLike = None, config: PosterOConfig
) -> None

Create a PosterO runner from explicit config.

Source code in models/postero/src/postero/agent.py
60
61
62
63
64
65
66
67
68
def __init__(self, *, model: ModelLike = None, config: PosterOConfig) -> None:
    """Create a PosterO runner from explicit config."""
    self.config = config
    super().__init__(
        model=model,
        model_env_var=DEFAULT_MODEL_ENV_VAR,
        raw_response_type=RawPosterOResponse,
        instructions=INSTRUCTIONS,
    )

build_prompt

build_prompt(
    query_record: PosterORecord,
    *,
    candidate_records: Sequence[PosterORecord],
    labels: Sequence[int | str] | None = None,
    seed: int | None = None,
    generator: Generator | None = None,
) -> tuple[str, list[PosterORecord]]

Select exemplars and build the provider prompt.

Parameters:

Name Type Description Default
query_record PosterORecord

Query poster record.

required
candidate_records Sequence[PosterORecord]

Candidate exemplar records.

required
labels Sequence[int | str] | None

Optional labels to allocate.

None
seed int | None

Optional deterministic seed for random selection.

None
generator Generator | None

Optional torch generator. Takes precedence over seed.

None

Returns:

Type Description
tuple[str, list[PosterORecord]]

Prompt text and selected exemplars.

Source code in models/postero/src/postero/agent.py
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
def build_prompt(
    self,
    query_record: PosterORecord,
    *,
    candidate_records: Sequence[PosterORecord],
    labels: Sequence[int | str] | None = None,
    seed: int | None = None,
    generator: torch.Generator | None = None,
) -> tuple[str, list[PosterORecord]]:
    """Select exemplars and build the provider prompt.

    Args:
        query_record: Query poster record.
        candidate_records: Candidate exemplar records.
        labels: Optional labels to allocate.
        seed: Optional deterministic seed for random selection.
        generator: Optional torch generator. Takes precedence over ``seed``.

    Returns:
        Prompt text and selected exemplars.
    """
    exemplars = select_exemplars(
        query_record,
        candidate_records,
        config=self.config,
        seed=seed,
        generator=generator,
    )
    return (
        build_prompt(query_record, exemplars, config=self.config, labels=labels),
        exemplars,
    )

run_sync

run_sync(
    query_record: PosterORecord,
    *,
    candidate_records: Sequence[PosterORecord],
    labels: Sequence[int | str] | None = None,
    model: ModelLike = None,
    seed: int | None = None,
    generator: Generator | None = None,
    model_settings: ModelSettings | None = None,
) -> PosterOOutput

Run the configured provider until enough valid SVGs are parsed.

Parameters:

Name Type Description Default
query_record PosterORecord

Query poster record.

required
candidate_records Sequence[PosterORecord]

Candidate exemplar records.

required
labels Sequence[int | str] | None

Optional labels to allocate.

None
model ModelLike

Optional per-call provider override.

None
seed int | None

Optional deterministic seed.

None
generator Generator | None

Optional torch generator. Takes precedence over seed.

None
model_settings ModelSettings | None

Optional provider sampling settings.

None

Returns:

Type Description
PosterOOutput

Parsed PosterO output.

Raises:

Type Description
RuntimeError

If no valid response is parsed within num_return.

Source code in models/postero/src/postero/agent.py
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
def run_sync(
    self,
    query_record: PosterORecord,
    *,
    candidate_records: Sequence[PosterORecord],
    labels: Sequence[int | str] | None = None,
    model: ModelLike = None,
    seed: int | None = None,
    generator: torch.Generator | None = None,
    model_settings: ModelSettings | None = None,
) -> PosterOOutput:
    """Run the configured provider until enough valid SVGs are parsed.

    Args:
        query_record: Query poster record.
        candidate_records: Candidate exemplar records.
        labels: Optional labels to allocate.
        model: Optional per-call provider override.
        seed: Optional deterministic seed.
        generator: Optional torch generator. Takes precedence over ``seed``.
        model_settings: Optional provider sampling settings.

    Returns:
        Parsed PosterO output.

    Raises:
        RuntimeError: If no valid response is parsed within ``num_return``.
    """
    prompt, exemplars = self.build_prompt(
        query_record,
        candidate_records=candidate_records,
        labels=labels,
        seed=seed,
        generator=generator,
    )
    selected_ids = [record.id for record in exemplars]
    outputs: list[PosterOOutput] = []
    errors: list[str] = []
    for attempt in range(1, self.config.num_return + 1):
        raw = self.run_raw_sync(
            prompt,
            model=model,
            model_settings=model_settings
            or ModelSettings(
                temperature=self.config.temperature,
                top_p=self.config.top_p,
                max_tokens=self.config.max_tokens,
                frequency_penalty=self.config.frequency_penalty,
                presence_penalty=self.config.presence_penalty,
            ),
        )
        try:
            elements, diagnostics = parse_svg_response(raw.text, config=self.config)
        except ValueError as exc:
            errors.append(str(exc))
            continue
        outputs.append(
            PosterOOutput(
                prompt=prompt,
                raw_text=raw.text,
                elements=elements,
                id2label=self.config.id2label or {},
                canvas_size=self.config.canvas_size,
                selected_exemplar_ids=selected_ids,
                attempts=attempt,
                parser_diagnostics=diagnostics,
                parser_errors=list(errors),
            )
        )
        valid_count = sum(len(output.elements) for output in outputs)
        if valid_count >= self.config.n_valid_layouts:
            return merged_output(outputs, config=self.config)
    if outputs:
        return merged_output(outputs, config=self.config)
    msg = "PosterO could not parse a valid SVG response"
    raise RuntimeError(msg)

__call__

__call__(
    *,
    query_record: PosterORecord,
    candidate_records: Sequence[PosterORecord],
    batch_size: int = 1,
    seed: int | None = None,
    generator: Generator | None = None,
    condition_type: str
    | ConditionType = ConditionType.content_image,
    labels: Int[Tensor, "batch elements"]
    | list[int | str]
    | None = None,
    bbox: Float[Tensor, "batch elements 4"]
    | Sequence[ArrayLikeInput]
    | None = None,
    mask: Bool[Tensor, "batch elements"]
    | Sequence[ArrayLikeInput]
    | None = None,
    num_elements: int
    | list[int]
    | Int[Tensor, "batch"]
    | None = None,
    box_format: str | BoxFormat = BoxFormat.xywh,
    normalized: bool = True,
    canvas_size: tuple[int, int] | None = None,
    num_inference_steps: int | None = None,
    output_type: str | OutputType = OutputType.dataclass,
    return_intermediates: bool = False,
    model: ModelLike = None,
    model_settings: ModelSettings | None = None,
) -> LayoutGenerationOutput | LayoutOutputDict

Generate a poster layout through the shared public surface.

Parameters:

Name Type Description Default
query_record PosterORecord

Query poster record with content-aware regions.

required
candidate_records Sequence[PosterORecord]

Candidate records for retrieval.

required
batch_size int

Shared API batch size. PosterO supports 1.

1
seed int | None

Optional deterministic seed.

None
generator Generator | None

Optional torch generator. Takes precedence over seed.

None
condition_type str | ConditionType

content_image or retrieval.

content_image
labels Int[Tensor, 'batch elements'] | list[int | str] | None

Optional labels to allocate.

None
bbox Float[Tensor, 'batch elements 4'] | Sequence[ArrayLikeInput] | None

Accepted for shared interface compatibility.

None
mask Bool[Tensor, 'batch elements'] | Sequence[ArrayLikeInput] | None

Accepted for shared interface compatibility.

None
num_elements int | list[int] | Int[Tensor, 'batch'] | None

Accepted for shared interface compatibility.

None
box_format str | BoxFormat

Public input box format name.

xywh
normalized bool

Accepted for shared interface compatibility.

True
canvas_size tuple[int, int] | None

Optional canvas override; must match config.

None
num_inference_steps int | None

Accepted for shared interface compatibility.

None
output_type str | OutputType

dataclass or dict.

dataclass
return_intermediates bool

Whether to include prompt/parser metadata.

False
model ModelLike

Optional per-call provider override.

None
model_settings ModelSettings | None

Optional provider settings override.

None

Returns:

Type Description
LayoutGenerationOutput | LayoutOutputDict

Shared layout output dataclass or dictionary.

Raises:

Type Description
ValueError

If shared arguments request unsupported behavior.

RuntimeError

If provider responses cannot be parsed.

Source code in models/postero/src/postero/agent.py
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
def __call__(
    self,
    *,
    query_record: PosterORecord,
    candidate_records: Sequence[PosterORecord],
    batch_size: int = 1,
    seed: int | None = None,
    generator: torch.Generator | None = None,
    condition_type: str | ConditionType = ConditionType.content_image,
    labels: Int[torch.Tensor, "batch elements"] | list[int | str] | None = None,
    bbox: Float[torch.Tensor, "batch elements 4"]
    | Sequence[ArrayLikeInput]
    | None = None,
    mask: Bool[torch.Tensor, "batch elements"]
    | Sequence[ArrayLikeInput]
    | None = None,
    num_elements: int | list[int] | Int[torch.Tensor, "batch"] | None = None,
    box_format: str | BoxFormat = BoxFormat.xywh,
    normalized: bool = True,
    canvas_size: tuple[int, int] | None = None,
    num_inference_steps: int | None = None,
    output_type: str | OutputType = OutputType.dataclass,
    return_intermediates: bool = False,
    model: ModelLike = None,
    model_settings: ModelSettings | None = None,
) -> LayoutGenerationOutput | LayoutOutputDict:
    """Generate a poster layout through the shared public surface.

    Args:
        query_record: Query poster record with content-aware regions.
        candidate_records: Candidate records for retrieval.
        batch_size: Shared API batch size. PosterO supports ``1``.
        seed: Optional deterministic seed.
        generator: Optional torch generator. Takes precedence over ``seed``.
        condition_type: ``content_image`` or ``retrieval``.
        labels: Optional labels to allocate.
        bbox: Accepted for shared interface compatibility.
        mask: Accepted for shared interface compatibility.
        num_elements: Accepted for shared interface compatibility.
        box_format: Public input box format name.
        normalized: Accepted for shared interface compatibility.
        canvas_size: Optional canvas override; must match config.
        num_inference_steps: Accepted for shared interface compatibility.
        output_type: ``dataclass`` or ``dict``.
        return_intermediates: Whether to include prompt/parser metadata.
        model: Optional per-call provider override.
        model_settings: Optional provider settings override.

    Returns:
        Shared layout output dataclass or dictionary.

    Raises:
        ValueError: If shared arguments request unsupported behavior.
        RuntimeError: If provider responses cannot be parsed.
    """
    del bbox, mask, num_elements, normalized, num_inference_steps
    self._validate_request(
        batch_size=batch_size,
        condition_type=condition_type,
        box_format=box_format,
        canvas_size=canvas_size,
    )
    normalized_output_type = coerce_enum(output_type, OutputType)
    label_values = _labels_from_public(labels)
    output = self.run_sync(
        query_record,
        candidate_records=candidate_records,
        labels=label_values,
        model=model,
        seed=seed,
        generator=generator,
        model_settings=model_settings,
    ).to_layout_generation_output(return_intermediates=return_intermediates)
    if normalized_output_type is OutputType.dataclass:
        return output
    if normalized_output_type is OutputType.dict:
        return self.output_to_dict(output)
    assert_never(normalized_output_type)

save_pretrained

save_pretrained(
    save_directory: str | PathLike[str],
) -> None

Persist prompt and parser configuration without provider state.

Parameters:

Name Type Description Default
save_directory str | PathLike[str]

Target directory for postero_config.json.

required

Returns:

Type Description
None

None.

Source code in models/postero/src/postero/agent.py
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
def save_pretrained(self, save_directory: str | os.PathLike[str]) -> None:
    """Persist prompt and parser configuration without provider state.

    Args:
        save_directory: Target directory for ``postero_config.json``.

    Returns:
        None.
    """
    path = Path(save_directory)
    path.mkdir(parents=True, exist_ok=True)
    (path / "postero_config.json").write_text(
        json.dumps(self.config.model_dump(mode="json"), indent=2, sort_keys=True)
        + "\n",
        encoding="utf-8",
    )

from_pretrained classmethod

from_pretrained(
    pretrained_model_name_or_path: str | PathLike[str],
    *,
    model: ModelLike = None,
) -> "PosterOAgent"

Load saved PosterO prompt and parser configuration.

Parameters:

Name Type Description Default
pretrained_model_name_or_path str | PathLike[str]

Directory containing postero_config.json.

required
model ModelLike

Replacement provider model.

None

Returns:

Type Description
'PosterOAgent'

Configured PosterO agent.

Source code in models/postero/src/postero/agent.py
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
@classmethod
def from_pretrained(
    cls,
    pretrained_model_name_or_path: str | os.PathLike[str],
    *,
    model: ModelLike = None,
) -> "PosterOAgent":
    """Load saved PosterO prompt and parser configuration.

    Args:
        pretrained_model_name_or_path: Directory containing
            ``postero_config.json``.
        model: Replacement provider model.

    Returns:
        Configured PosterO agent.
    """
    path = Path(pretrained_model_name_or_path) / "postero_config.json"
    config_data = json.loads(path.read_text(encoding="utf-8"))
    return cls(model=model, config=PosterOConfig(**config_data))

resolve_model

resolve_model(model: ModelLike = None) -> ModelLike

Resolve explicit model, environment model, or Pydantic default.

Source code in models/postero/src/postero/agent.py
299
300
301
302
303
def resolve_model(self, model: ModelLike = None) -> ModelLike:
    """Resolve explicit model, environment model, or Pydantic default."""
    return (
        model or os.getenv(DEFAULT_MODEL_ENV_VAR) or os.getenv("PYDANTIC_AI_MODEL")
    )

config

Configuration for PosterO prompt construction and parsing.

PosterOConfig

Bases: BaseModel

Runtime prompt, retrieval, parser, and provider settings.

Parameters:

Name Type Description Default
dataset_name

Poster dataset name. Public aliases are normalized through posgen.common.

required
structure

Prompt serialization structure.

required
injection

Available-area injection strategy.

required
pool_strategy

Candidate pool strategy.

required
rank_strategy

Exemplar ranking strategy.

required
sample_size

Number of candidate records considered before ranking.

required
num_return

Maximum provider attempts for one public call.

required
n_valid_layouts

Number of valid parsed layouts requested.

required
canvas_size

Canvas size as (width, height).

required
temperature

Provider sampling temperature.

required
top_p

Provider nucleus sampling value.

required
max_tokens

Maximum response tokens requested from a provider.

required
frequency_penalty

Provider frequency penalty.

required
presence_penalty

Provider presence penalty.

required
stop_token

Provider stop token.

required
label_rback

Whether parser labels are mapped back to configured ids.

required
prompt_target

Structured response target.

required
id2label

Public label ids. Defaults preserve PosterO issue mappings.

required

Raises:

Type Description
ValueError

If a closed mode or dataset name is unsupported.

Examples:

>>> config = PosterOConfig(dataset_name="pku")
>>> config.id2label[1]
'text'
Source code in models/postero/src/postero/config.py
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
class PosterOConfig(BaseModel):
    """Runtime prompt, retrieval, parser, and provider settings.

    Args:
        dataset_name: Poster dataset name. Public aliases are normalized through
            ``posgen.common``.
        structure: Prompt serialization structure.
        injection: Available-area injection strategy.
        pool_strategy: Candidate pool strategy.
        rank_strategy: Exemplar ranking strategy.
        sample_size: Number of candidate records considered before ranking.
        num_return: Maximum provider attempts for one public call.
        n_valid_layouts: Number of valid parsed layouts requested.
        canvas_size: Canvas size as ``(width, height)``.
        temperature: Provider sampling temperature.
        top_p: Provider nucleus sampling value.
        max_tokens: Maximum response tokens requested from a provider.
        frequency_penalty: Provider frequency penalty.
        presence_penalty: Provider presence penalty.
        stop_token: Provider stop token.
        label_rback: Whether parser labels are mapped back to configured ids.
        prompt_target: Structured response target.
        id2label: Public label ids. Defaults preserve PosterO issue mappings.

    Raises:
        ValueError: If a closed mode or dataset name is unsupported.

    Examples:
        >>> config = PosterOConfig(dataset_name="pku")
        >>> config.id2label[1]
        'text'
    """

    dataset_name: DatasetName | str = DatasetName.pku_posterlayout
    structure: PosterOStructure | str = PosterOStructure.hierarchical
    injection: PosterOInjection | str = PosterOInjection.top
    pool_strategy: PosterOPoolStrategy | str = PosterOPoolStrategy.metric_filter
    rank_strategy: PosterORankStrategy | str = PosterORankStrategy.rank_by_feature
    sample_size: int = Field(default=10, ge=1)
    num_return: int = Field(default=10, ge=1)
    n_valid_layouts: int = Field(default=10, ge=1)
    canvas_size: tuple[int, int] = DEFAULT_CANVAS_SIZE
    temperature: float = 0.7
    top_p: float = 1.0
    max_tokens: int = 800
    frequency_penalty: float = 0.0
    presence_penalty: float = 0.0
    stop_token: str = "\n\n"
    label_rback: bool = True
    prompt_target: PromptTarget | str = PromptTarget.rect_only
    id2label: dict[int, str] | None = None

    model_config = ConfigDict(frozen=True)

    @field_validator("dataset_name")
    @classmethod
    def normalize_dataset(cls, value: DatasetName | str) -> DatasetName:
        """Normalize poster dataset aliases at the config boundary."""
        return normalize_dataset_name(value)

    @field_validator("structure")
    @classmethod
    def normalize_structure(cls, value: PosterOStructure | str) -> PosterOStructure:
        """Normalize prompt structure."""
        return coerce_enum(value, PosterOStructure)

    @field_validator("injection")
    @classmethod
    def normalize_injection(cls, value: PosterOInjection | str) -> PosterOInjection:
        """Normalize available-area injection mode."""
        return coerce_enum(value, PosterOInjection)

    @field_validator("pool_strategy")
    @classmethod
    def normalize_pool_strategy(
        cls, value: PosterOPoolStrategy | str
    ) -> PosterOPoolStrategy:
        """Normalize pool strategy."""
        return coerce_enum(value, PosterOPoolStrategy)

    @field_validator("rank_strategy")
    @classmethod
    def normalize_rank_strategy(
        cls, value: PosterORankStrategy | str
    ) -> PosterORankStrategy:
        """Normalize rank strategy."""
        return coerce_enum(value, PosterORankStrategy)

    @field_validator("prompt_target")
    @classmethod
    def normalize_prompt_target(cls, value: PromptTarget | str) -> PromptTarget:
        """Normalize prompt target."""
        return coerce_enum(value, PromptTarget)

    @model_validator(mode="after")
    def fill_id2label(self) -> "PosterOConfig":
        """Fill dataset-specific label ids when no explicit map is stored."""
        if self.id2label is not None:
            return self
        mapping = (
            CGL_ID2LABEL
            if self.dataset_name in {DatasetName.cgl, DatasetName.cgl_v2}
            else PKU_ID2LABEL
        )
        object.__setattr__(self, "id2label", dict(mapping))
        return self

normalize_dataset classmethod

normalize_dataset(value: DatasetName | str) -> DatasetName

Normalize poster dataset aliases at the config boundary.

Source code in models/postero/src/postero/config.py
83
84
85
86
87
@field_validator("dataset_name")
@classmethod
def normalize_dataset(cls, value: DatasetName | str) -> DatasetName:
    """Normalize poster dataset aliases at the config boundary."""
    return normalize_dataset_name(value)

normalize_structure classmethod

normalize_structure(
    value: PosterOStructure | str,
) -> PosterOStructure

Normalize prompt structure.

Source code in models/postero/src/postero/config.py
89
90
91
92
93
@field_validator("structure")
@classmethod
def normalize_structure(cls, value: PosterOStructure | str) -> PosterOStructure:
    """Normalize prompt structure."""
    return coerce_enum(value, PosterOStructure)

normalize_injection classmethod

normalize_injection(
    value: PosterOInjection | str,
) -> PosterOInjection

Normalize available-area injection mode.

Source code in models/postero/src/postero/config.py
95
96
97
98
99
@field_validator("injection")
@classmethod
def normalize_injection(cls, value: PosterOInjection | str) -> PosterOInjection:
    """Normalize available-area injection mode."""
    return coerce_enum(value, PosterOInjection)

normalize_pool_strategy classmethod

normalize_pool_strategy(
    value: PosterOPoolStrategy | str,
) -> PosterOPoolStrategy

Normalize pool strategy.

Source code in models/postero/src/postero/config.py
101
102
103
104
105
106
107
@field_validator("pool_strategy")
@classmethod
def normalize_pool_strategy(
    cls, value: PosterOPoolStrategy | str
) -> PosterOPoolStrategy:
    """Normalize pool strategy."""
    return coerce_enum(value, PosterOPoolStrategy)

normalize_rank_strategy classmethod

normalize_rank_strategy(
    value: PosterORankStrategy | str,
) -> PosterORankStrategy

Normalize rank strategy.

Source code in models/postero/src/postero/config.py
109
110
111
112
113
114
115
@field_validator("rank_strategy")
@classmethod
def normalize_rank_strategy(
    cls, value: PosterORankStrategy | str
) -> PosterORankStrategy:
    """Normalize rank strategy."""
    return coerce_enum(value, PosterORankStrategy)

normalize_prompt_target classmethod

normalize_prompt_target(
    value: PromptTarget | str,
) -> PromptTarget

Normalize prompt target.

Source code in models/postero/src/postero/config.py
117
118
119
120
121
@field_validator("prompt_target")
@classmethod
def normalize_prompt_target(cls, value: PromptTarget | str) -> PromptTarget:
    """Normalize prompt target."""
    return coerce_enum(value, PromptTarget)

fill_id2label

fill_id2label() -> 'PosterOConfig'

Fill dataset-specific label ids when no explicit map is stored.

Source code in models/postero/src/postero/config.py
123
124
125
126
127
128
129
130
131
132
133
134
@model_validator(mode="after")
def fill_id2label(self) -> "PosterOConfig":
    """Fill dataset-specific label ids when no explicit map is stored."""
    if self.id2label is not None:
        return self
    mapping = (
        CGL_ID2LABEL
        if self.dataset_name in {DatasetName.cgl, DatasetName.cgl_v2}
        else PKU_ID2LABEL
    )
    object.__setattr__(self, "id2label", dict(mapping))
    return self

enums

Closed string modes used by the PosterO package.

PosterOStructure

Bases: StrEnum

Prompt structure options.

Source code in models/postero/src/postero/enums.py
11
12
13
14
15
class PosterOStructure(StrEnum):
    """Prompt structure options."""

    plain = auto()
    hierarchical = auto()

PosterOInjection

Bases: StrEnum

Available-area injection options.

Source code in models/postero/src/postero/enums.py
18
19
20
21
22
23
24
class PosterOInjection(StrEnum):
    """Available-area injection options."""

    none = auto()
    top = auto()
    pulse = auto()
    pulse_wh = auto()

PosterOPoolStrategy

Bases: StrEnum

Candidate-pool construction strategies.

Source code in models/postero/src/postero/enums.py
27
28
29
30
31
32
33
class PosterOPoolStrategy(StrEnum):
    """Candidate-pool construction strategies."""

    all = auto()
    metric_filter = auto()
    metric_describe = auto()
    metric_filter_describe = auto()

PosterORankStrategy

Bases: StrEnum

Exemplar ranking strategies.

Source code in models/postero/src/postero/enums.py
36
37
38
39
40
41
42
class PosterORankStrategy(StrEnum):
    """Exemplar ranking strategies."""

    random = auto()
    rank_by_label = auto()
    rank_by_denbox = auto()
    rank_by_feature = auto()

OutputType

Bases: StrEnum

Public return container names.

Source code in models/postero/src/postero/enums.py
45
46
47
48
49
class OutputType(StrEnum):
    """Public return container names."""

    dataclass = auto()
    dict = auto()

PromptTarget

Bases: StrEnum

Structured response target requested from the language model.

Source code in models/postero/src/postero/enums.py
52
53
54
55
56
class PromptTarget(StrEnum):
    """Structured response target requested from the language model."""

    rect_only = auto()
    generalized_svg = auto()

coerce_enum

coerce_enum(
    value: str | EnumT, enum_type: type[EnumT]
) -> EnumT

Normalize a public string-or-enum value.

Parameters:

Name Type Description Default
value str | EnumT

String or enum value.

required
enum_type type[EnumT]

Expected enum type.

required

Returns:

Type Description
EnumT

Normalized enum value.

Raises:

Type Description
ValueError

If the string does not belong to enum_type.

Examples:

>>> coerce_enum("plain", PosterOStructure)
<PosterOStructure.plain: 'plain'>
Source code in models/postero/src/postero/enums.py
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
def coerce_enum(value: str | EnumT, enum_type: type[EnumT]) -> EnumT:
    """Normalize a public string-or-enum value.

    Args:
        value: String or enum value.
        enum_type: Expected enum type.

    Returns:
        Normalized enum value.

    Raises:
        ValueError: If the string does not belong to ``enum_type``.

    Examples:
        >>> coerce_enum("plain", PosterOStructure)
        <PosterOStructure.plain: 'plain'>
    """
    if isinstance(value, enum_type):
        return value
    return enum_type(value)

exemplars

Exemplar selection for PosterO prompts.

select_exemplars

select_exemplars(
    query: PosterORecord,
    candidates: Sequence[PosterORecord],
    *,
    config: PosterOConfig,
    seed: int | None = None,
    generator: Generator | None = None,
) -> list[PosterORecord]

Select prompt exemplars from in-memory records.

Parameters:

Name Type Description Default
query PosterORecord

Query record.

required
candidates Sequence[PosterORecord]

Candidate exemplar records.

required
config PosterOConfig

Prompt/retrieval configuration.

required
seed int | None

Optional deterministic seed.

None
generator Generator | None

Optional torch generator. Takes precedence over seed.

None

Returns:

Type Description
list[PosterORecord]

Selected exemplar records in prompt order.

Raises:

Type Description
ValueError

If no candidates survive filtering.

Source code in models/postero/src/postero/exemplars.py
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
def select_exemplars(
    query: PosterORecord,
    candidates: Sequence[PosterORecord],
    *,
    config: PosterOConfig,
    seed: int | None = None,
    generator: torch.Generator | None = None,
) -> list[PosterORecord]:
    """Select prompt exemplars from in-memory records.

    Args:
        query: Query record.
        candidates: Candidate exemplar records.
        config: Prompt/retrieval configuration.
        seed: Optional deterministic seed.
        generator: Optional torch generator. Takes precedence over ``seed``.

    Returns:
        Selected exemplar records in prompt order.

    Raises:
        ValueError: If no candidates survive filtering.
    """
    pool_strategy = cast(PosterOPoolStrategy, config.pool_strategy)
    pool = _pool(candidates, pool_strategy)
    if not pool:
        msg = "PosterO exemplar selection requires at least one candidate"
        raise ValueError(msg)

    ranked = _rank(query, pool, config=config, seed=seed, generator=generator)
    return ranked[: config.sample_size]

parser

SVG response parsing for PosterO.

ParsedPosterElement

Bases: BaseModel

One parsed PosterO SVG element.

Source code in models/postero/src/postero/parser.py
17
18
19
20
21
22
23
class ParsedPosterElement(BaseModel):
    """One parsed PosterO SVG element."""

    label: int
    bbox_ltrb: tuple[float, float, float, float]

    model_config = ConfigDict(frozen=True)

ParseDiagnostics

Bases: BaseModel

Parser diagnostics recorded in intermediates.

Source code in models/postero/src/postero/parser.py
26
27
28
29
30
31
32
33
class ParseDiagnostics(BaseModel):
    """Parser diagnostics recorded in ``intermediates``."""

    raw_label: str
    normalized_label: str
    label_id: int

    model_config = ConfigDict(frozen=True)

extract_svg

extract_svg(text: str) -> str

Extract the first SVG block from provider text.

Parameters:

Name Type Description Default
text str

Raw provider response.

required

Returns:

Type Description
str

SVG XML string.

Raises:

Type Description
ValueError

If no SVG block is present.

Source code in models/postero/src/postero/parser.py
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
def extract_svg(text: str) -> str:
    """Extract the first SVG block from provider text.

    Args:
        text: Raw provider response.

    Returns:
        SVG XML string.

    Raises:
        ValueError: If no SVG block is present.
    """
    match = SVG_RE.search(text)
    if match is None:
        msg = "No <svg> block found in PosterO response"
        raise ValueError(msg)

    return match.group(0)

parse_svg_response

parse_svg_response(
    text: str, *, config: PosterOConfig
) -> tuple[
    list[ParsedPosterElement], list[ParseDiagnostics]
]

Parse provider SVG into PosterO elements.

Parameters:

Name Type Description Default
text str

Raw provider response.

required
config PosterOConfig

Parser configuration.

required

Returns:

Type Description
tuple[list[ParsedPosterElement], list[ParseDiagnostics]]

Parsed elements and diagnostics.

Raises:

Type Description
ValueError

If SVG is missing, invalid, or contains unknown labels.

Examples:

>>> from postero.config import PosterOConfig
>>> parse_svg_response('<svg><rect data-label="text_1" x="0" y="0" width="10" height="20"/></svg>', config=PosterOConfig())[0][0].label
1
Source code in models/postero/src/postero/parser.py
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
def parse_svg_response(
    text: str, *, config: PosterOConfig
) -> tuple[list[ParsedPosterElement], list[ParseDiagnostics]]:
    """Parse provider SVG into PosterO elements.

    Args:
        text: Raw provider response.
        config: Parser configuration.

    Returns:
        Parsed elements and diagnostics.

    Raises:
        ValueError: If SVG is missing, invalid, or contains unknown labels.

    Examples:
        >>> from postero.config import PosterOConfig
        >>> parse_svg_response('<svg><rect data-label="text_1" x="0" y="0" width="10" height="20"/></svg>', config=PosterOConfig())[0][0].label
        1
    """
    svg = extract_svg(text)
    root = ET.fromstring(svg)
    label2id = _label2id(config.id2label or {})
    elements: list[ParsedPosterElement] = []
    diagnostics: list[ParseDiagnostics] = []
    for node in root.iter():
        if _strip_namespace(node.tag) != "rect":
            continue
        raw_label = _label_from_node(node.attrib)
        normalized_label = normalize_generated_label(raw_label, config=config)
        if normalized_label == "canvas":
            continue
        try:
            label_id = label2id[normalized_label]
        except KeyError as exc:
            msg = f"Unknown generated PosterO label: {raw_label}"
            raise ValueError(msg) from exc

        left = float(node.attrib.get("x", "0"))
        top = float(node.attrib.get("y", "0"))
        width = float(node.attrib.get("width", "0"))
        height = float(node.attrib.get("height", "0"))
        if width <= 0 or height <= 0:
            continue
        elements.append(
            ParsedPosterElement(
                label=label_id,
                bbox_ltrb=(left, top, left + width, top + height),
            )
        )
        diagnostics.append(
            ParseDiagnostics(
                raw_label=raw_label,
                normalized_label=normalized_label,
                label_id=label_id,
            )
        )
    if not elements:
        msg = "No valid <rect> elements found in PosterO response"
        raise ValueError(msg)

    return elements, diagnostics

normalize_generated_label

normalize_generated_label(
    label: str, *, config: PosterOConfig
) -> str

Normalize generated element labels before id lookup.

Source code in models/postero/src/postero/parser.py
120
121
122
123
124
125
def normalize_generated_label(label: str, *, config: PosterOConfig) -> str:
    """Normalize generated element labels before id lookup."""
    normalized = label.strip().lower().replace("-", "_")
    if config.label_rback:
        normalized = TRAILING_INDEX_RE.sub("", normalized)
    return normalized.replace("_", " ")

prompts

Prompt construction for PosterO.

build_prompt

build_prompt(
    query: PosterORecord,
    exemplars: Sequence[PosterORecord],
    *,
    config: PosterOConfig,
    labels: Sequence[int | str] | None = None,
) -> str

Build a deterministic PosterO prompt.

Parameters:

Name Type Description Default
query PosterORecord

Query poster record.

required
exemplars Sequence[PosterORecord]

Selected in-context records.

required
config PosterOConfig

Prompt configuration.

required
labels Sequence[int | str] | None

Optional labels to allocate. Defaults to labels from query.

None

Returns:

Type Description
str

Full prompt bytes as a Python string.

Source code in models/postero/src/postero/prompts.py
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
def build_prompt(
    query: PosterORecord,
    exemplars: Sequence[PosterORecord],
    *,
    config: PosterOConfig,
    labels: Sequence[int | str] | None = None,
) -> str:
    """Build a deterministic PosterO prompt.

    Args:
        query: Query poster record.
        exemplars: Selected in-context records.
        config: Prompt configuration.
        labels: Optional labels to allocate. Defaults to labels from ``query``.

    Returns:
        Full prompt bytes as a Python string.
    """
    exemplar_blocks = [
        PROMPT_RAG_OPENING.format(index) + head + svg
        for index, record in enumerate(exemplars)
        for head, svg in [serialize_record(record, config)]
    ]
    final_labels = list(labels) if labels is not None else labels_for_record(query)
    return "\n".join(
        [
            PROMPT_PREAMBLE,
            "\n".join(exemplar_blocks),
            PROMPT_RULE,
            build_final_svg_prompt(final_labels, query, config),
        ]
    )

records

Typed in-memory records consumed by PosterO prompts.

AvailableRegion

Bases: BaseModel

One available poster area in pixel ltrb coordinates.

Source code in models/postero/src/postero/records.py
14
15
16
17
18
19
class AvailableRegion(BaseModel):
    """One available poster area in pixel ``ltrb`` coordinates."""

    bbox_ltrb: tuple[float, float, float, float]

    model_config = ConfigDict(frozen=True)

PosterLayoutElement

Bases: BaseModel

One poster layout element in pixel ltrb coordinates.

Source code in models/postero/src/postero/records.py
22
23
24
25
26
27
28
29
30
class PosterLayoutElement(BaseModel):
    """One poster layout element in pixel ``ltrb`` coordinates."""

    label: int | str
    bbox_ltrb: tuple[float, float, float, float]
    rotation: float | None = None
    path_data: str | None = None

    model_config = ConfigDict(frozen=True)

PosterORecord

Bases: BaseModel

One poster prompt or exemplar record.

Parameters:

Name Type Description Default
id

Stable record id used in parity reports.

required
dataset

Dataset key.

required
poster_path

Optional source image path.

required
canvas_size

Canvas size as (width, height).

required
available_regions

Content-aware available regions.

required
elements

Ground-truth or generated layout elements.

required
features

Optional precomputed retrieval feature vector.

required
metrics

Optional quality metrics used by pool filtering.

required
metadata

Extra non-runtime metadata.

required
Source code in models/postero/src/postero/records.py
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class PosterORecord(BaseModel):
    """One poster prompt or exemplar record.

    Args:
        id: Stable record id used in parity reports.
        dataset: Dataset key.
        poster_path: Optional source image path.
        canvas_size: Canvas size as ``(width, height)``.
        available_regions: Content-aware available regions.
        elements: Ground-truth or generated layout elements.
        features: Optional precomputed retrieval feature vector.
        metrics: Optional quality metrics used by pool filtering.
        metadata: Extra non-runtime metadata.
    """

    id: str
    dataset: str
    poster_path: str | None = None
    canvas_size: tuple[int, int] = (513, 750)
    available_regions: list[AvailableRegion] = Field(default_factory=list)
    elements: list[PosterLayoutElement] = Field(default_factory=list)
    features: list[float] | None = None
    metrics: dict[str, float] = Field(default_factory=dict)
    metadata: dict[str, object] = Field(default_factory=dict)

    model_config = ConfigDict(frozen=True)

record_from_mapping

record_from_mapping(
    row: Mapping[str, JSONValue],
    *,
    id2label: Mapping[int, str],
) -> PosterORecord

Build a PosterORecord from a lightweight mapping.

Parameters:

Name Type Description Default
row Mapping[str, JSONValue]

Mapping with optional available_regions and elements lists.

required
id2label Mapping[int, str]

Public id-to-label mapping used for integer validation.

required

Returns:

Type Description
PosterORecord

Normalized PosterORecord.

Raises:

Type Description
ValueError

If an integer label is not present in id2label.

Source code in models/postero/src/postero/records.py
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
def record_from_mapping(
    row: Mapping[str, JSONValue], *, id2label: Mapping[int, str]
) -> PosterORecord:
    """Build a ``PosterORecord`` from a lightweight mapping.

    Args:
        row: Mapping with optional ``available_regions`` and ``elements`` lists.
        id2label: Public id-to-label mapping used for integer validation.

    Returns:
        Normalized ``PosterORecord``.

    Raises:
        ValueError: If an integer label is not present in ``id2label``.
    """
    elements = [
        _element_from_mapping(element, id2label=id2label)
        for element in _sequence(row.get("elements", ()))
    ]
    regions = [
        AvailableRegion(bbox_ltrb=_bbox(_mapping(region).get("bbox_ltrb", region)))
        for region in _sequence(row.get("available_regions", ()))
    ]
    return PosterORecord(
        id=str(row["id"]),
        dataset=str(row.get("dataset", "")),
        poster_path=str(row["poster_path"]) if row.get("poster_path") else None,
        canvas_size=_canvas_size(row.get("canvas_size", (513, 750))),
        available_regions=regions,
        elements=elements,
        features=[_float(value) for value in _sequence(row.get("features", ()))],
        metrics={
            str(key): _float(value)
            for key, value in _mapping(row.get("metrics")).items()
        },
        metadata=dict(_mapping(row.get("metadata"))),
    )

record_to_mapping

record_to_mapping(
    record: PosterORecord,
) -> dict[str, JSONValue]

Serialize a record to a JSON-compatible mapping.

Source code in models/postero/src/postero/records.py
100
101
102
def record_to_mapping(record: PosterORecord) -> dict[str, JSONValue]:
    """Serialize a record to a JSON-compatible mapping."""
    return cast(dict[str, JSONValue], record.model_dump(mode="json"))

labels_for_record

labels_for_record(record: PosterORecord) -> list[int | str]

Return element labels in record order.

Source code in models/postero/src/postero/records.py
105
106
107
def labels_for_record(record: PosterORecord) -> list[int | str]:
    """Return element labels in record order."""
    return [element.label for element in record.elements]

schemas

Pydantic schemas for PosterO structured responses.

RawPosterOResponse

Bases: BaseModel

Structured model response before SVG parsing.

Source code in models/postero/src/postero/schemas.py
19
20
21
22
class RawPosterOResponse(BaseModel):
    """Structured model response before SVG parsing."""

    text: str

PosterOOutput

Bases: BaseModel

Parsed PosterO response with prompt metadata.

Source code in models/postero/src/postero/schemas.py
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
class PosterOOutput(BaseModel):
    """Parsed PosterO response with prompt metadata."""

    prompt: str
    raw_text: str
    elements: list[ParsedPosterElement]
    id2label: dict[int, str]
    canvas_size: tuple[int, int]
    selected_exemplar_ids: list[str]
    attempts: int
    parser_diagnostics: list[ParseDiagnostics]
    parser_errors: list[str]

    model_config = ConfigDict(frozen=True)

    def to_layout_generation_output(
        self, *, return_intermediates: bool = True
    ) -> LayoutGenerationOutput:
        """Convert parsed PosterO output to the shared layout schema.

        Args:
            return_intermediates: Whether to attach prompt/parser metadata.

        Returns:
            ``LayoutGenerationOutput`` with normalized center ``xywh`` boxes.
        """
        bbox = torch.tensor(
            [[element.bbox_ltrb for element in self.elements]], dtype=torch.float32
        )
        labels = torch.tensor(
            [[element.label for element in self.elements]], dtype=torch.long
        )
        mask = torch.ones(labels.shape, dtype=torch.bool)
        normalized_bbox = normalize_boxes(
            bbox, canvas_size=self.canvas_size, box_format="ltrb"
        )
        return LayoutGenerationOutput(
            bbox=normalized_bbox,
            labels=labels,
            mask=mask,
            id2label=dict(self.id2label),
            intermediates=self._intermediates() if return_intermediates else None,
        )

    def _intermediates(self) -> dict[str, JSONValue]:
        return {
            "prompt": self.prompt,
            "raw_text": self.raw_text,
            "selected_exemplar_ids": self.selected_exemplar_ids,
            "attempts": self.attempts,
            "parser_diagnostics": [
                diagnostic.model_dump(mode="json")
                for diagnostic in self.parser_diagnostics
            ],
            "parser_errors": list(self.parser_errors),
            "retrieval": {"selected_exemplar_ids": self.selected_exemplar_ids},
        }

to_layout_generation_output

to_layout_generation_output(
    *, return_intermediates: bool = True
) -> LayoutGenerationOutput

Convert parsed PosterO output to the shared layout schema.

Parameters:

Name Type Description Default
return_intermediates bool

Whether to attach prompt/parser metadata.

True

Returns:

Type Description
LayoutGenerationOutput

LayoutGenerationOutput with normalized center xywh boxes.

Source code in models/postero/src/postero/schemas.py
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
def to_layout_generation_output(
    self, *, return_intermediates: bool = True
) -> LayoutGenerationOutput:
    """Convert parsed PosterO output to the shared layout schema.

    Args:
        return_intermediates: Whether to attach prompt/parser metadata.

    Returns:
        ``LayoutGenerationOutput`` with normalized center ``xywh`` boxes.
    """
    bbox = torch.tensor(
        [[element.bbox_ltrb for element in self.elements]], dtype=torch.float32
    )
    labels = torch.tensor(
        [[element.label for element in self.elements]], dtype=torch.long
    )
    mask = torch.ones(labels.shape, dtype=torch.bool)
    normalized_bbox = normalize_boxes(
        bbox, canvas_size=self.canvas_size, box_format="ltrb"
    )
    return LayoutGenerationOutput(
        bbox=normalized_bbox,
        labels=labels,
        mask=mask,
        id2label=dict(self.id2label),
        intermediates=self._intermediates() if return_intermediates else None,
    )

merged_output

merged_output(
    outputs: Sequence[PosterOOutput],
    *,
    config: PosterOConfig,
) -> PosterOOutput

Merge parsed candidates into one public output.

Source code in models/postero/src/postero/schemas.py
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
def merged_output(
    outputs: Sequence[PosterOOutput], *, config: PosterOConfig
) -> PosterOOutput:
    """Merge parsed candidates into one public output."""
    elements = [element for output in outputs for element in output.elements]
    diagnostics = [
        diagnostic for output in outputs for diagnostic in output.parser_diagnostics
    ]
    return PosterOOutput(
        prompt=outputs[0].prompt,
        raw_text="\n\n".join(output.raw_text for output in outputs),
        elements=elements,
        id2label=config.id2label or {},
        canvas_size=config.canvas_size,
        selected_exemplar_ids=outputs[0].selected_exemplar_ids,
        attempts=outputs[-1].attempts,
        parser_diagnostics=diagnostics,
        parser_errors=[error for output in outputs for error in output.parser_errors],
    )

serialization

SVG and prompt-fragment serialization for PosterO.

TreeNode dataclass

Simple containment tree node used by hierarchical prompts.

Source code in models/postero/src/postero/serialization.py
20
21
22
23
24
25
26
@dataclass
class TreeNode:
    """Simple containment tree node used by hierarchical prompts."""

    label: int | str
    bbox_ltrb: tuple[float, float, float, float]
    children: list["TreeNode"] = field(default_factory=list)

label_name

label_name(
    label: int | str, id2label: Mapping[int, str]
) -> str

Return a display label for an integer or string label.

Source code in models/postero/src/postero/serialization.py
29
30
31
32
33
def label_name(label: int | str, id2label: Mapping[int, str]) -> str:
    """Return a display label for an integer or string label."""
    if isinstance(label, int):
        return id2label[label]
    return str(label)

build_hierarchy

build_hierarchy(
    elements: Sequence[PosterLayoutElement],
    *,
    containment_noise: float = 20.0,
) -> list[TreeNode]

Build a shallow containment hierarchy from element boxes.

Parameters:

Name Type Description Default
elements Sequence[PosterLayoutElement]

Layout elements.

required
containment_noise float

Pixel tolerance used for containment checks.

20.0

Returns:

Type Description
list[TreeNode]

Root nodes with child nodes attached to the smallest containing parent.

Source code in models/postero/src/postero/serialization.py
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
def build_hierarchy(
    elements: Sequence[PosterLayoutElement], *, containment_noise: float = 20.0
) -> list[TreeNode]:
    """Build a shallow containment hierarchy from element boxes.

    Args:
        elements: Layout elements.
        containment_noise: Pixel tolerance used for containment checks.

    Returns:
        Root nodes with child nodes attached to the smallest containing parent.
    """
    nodes = [TreeNode(element.label, element.bbox_ltrb) for element in elements]
    roots: list[TreeNode] = []
    for index, node in enumerate(nodes):
        parent_index = _smallest_parent(index, nodes, containment_noise)
        if parent_index is None:
            roots.append(node)
        else:
            nodes[parent_index].children.append(node)
    return roots

serialize_plain_svg

serialize_plain_svg(
    record: PosterORecord, config: PosterOConfig
) -> tuple[str, str]

Serialize a record as a flat SVG example.

Returns:

Type Description
str

Pair of (description, svg) where description is the prompt-facing

str

text and svg is the deterministic XML fragment.

Source code in models/postero/src/postero/serialization.py
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
def serialize_plain_svg(
    record: PosterORecord, config: PosterOConfig
) -> tuple[str, str]:
    """Serialize a record as a flat SVG example.

    Returns:
        Pair of ``(description, svg)`` where description is the prompt-facing
        text and svg is the deterministic XML fragment.
    """
    svg = "".join(
        [
            build_svg_head(record.canvas_size),
            _available_area_polygons(record, config),
            _canvas_rect(record.canvas_size),
            *(
                _rect(element, config, index=index)
                for index, element in enumerate(record.elements, start=1)
            ),
            "</svg>\n",
        ]
    )
    return build_svg_description(svg, record, config), svg

serialize_hierarchical_svg

serialize_hierarchical_svg(
    record: PosterORecord, config: PosterOConfig
) -> tuple[str, str]

Serialize a record as a hierarchy-aware SVG example.

Source code in models/postero/src/postero/serialization.py
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
def serialize_hierarchical_svg(
    record: PosterORecord, config: PosterOConfig
) -> tuple[str, str]:
    """Serialize a record as a hierarchy-aware SVG example."""
    roots = build_hierarchy(record.elements)
    lines = [
        build_svg_head(record.canvas_size),
        _available_area_polygons(record, config),
        _canvas_rect(record.canvas_size),
    ]
    index = count(start=1)
    for node in roots:
        lines.extend(_node_lines(node, config, depth=1, index=index))
    lines.append("</svg>\n")
    svg = "".join(lines)
    return build_svg_description(svg, record, config), svg

build_svg_head

build_svg_head(canvas_size: tuple[int, int]) -> str

Return the SVG opening tag for canvas_size.

Source code in models/postero/src/postero/serialization.py
101
102
103
104
def build_svg_head(canvas_size: tuple[int, int]) -> str:
    """Return the SVG opening tag for ``canvas_size``."""
    width, height = canvas_size
    return SVG_HEADER_TEMPLATE.format(width=width, height=height) + "\n"

build_svg_description

build_svg_description(
    svg: str, record: PosterORecord, config: PosterOConfig
) -> str

Return the reference prompt-facing SVG head for one exemplar.

Source code in models/postero/src/postero/serialization.py
107
108
109
110
111
112
113
114
115
116
117
118
119
120
def build_svg_description(
    svg: str, record: PosterORecord, config: PosterOConfig
) -> str:
    """Return the reference prompt-facing SVG head for one exemplar."""
    description = f"This svg uses canvas_0 of size {config.canvas_size} "
    if _description_uses_available_regions(config) and record.available_regions:
        description += (
            "with available areas "
            + build_available_area_polygons(record.available_regions, config=config)
            + " "
        )
    rect_ids = _RECT_ID_RE.findall(svg)[1:]
    description += "to allocate { " + ", ".join(rect_ids) + " }.\n"
    return description

build_available_area_polygons

build_available_area_polygons(
    regions: Sequence[AvailableRegion],
    *,
    config: PosterOConfig | None = None,
) -> str

Serialize available regions in deterministic prompt order.

Source code in models/postero/src/postero/serialization.py
123
124
125
126
127
128
129
def build_available_area_polygons(
    regions: Sequence[AvailableRegion], *, config: PosterOConfig | None = None
) -> str:
    """Serialize available regions in deterministic prompt order."""
    if config is not None and config.injection is PosterOInjection.pulse_wh:
        return ", ".join(str(_ltrb_to_ltwh(region.bbox_ltrb)) for region in regions)
    return ", ".join(str(region.bbox_ltrb) for region in regions)

build_final_svg_prompt

build_final_svg_prompt(
    labels: Sequence[int | str],
    record: PosterORecord,
    config: PosterOConfig,
) -> str

Build the final allocation prompt.

Parameters:

Name Type Description Default
labels Sequence[int | str]

Labels to allocate.

required
record PosterORecord

Query record with canvas and available regions.

required
config PosterOConfig

Prompt configuration.

required

Returns:

Type Description
str

Deterministic final prompt text.

Examples:

>>> from postero.config import PosterOConfig
>>> from postero.records import PosterORecord
>>> build_final_svg_prompt([1], PosterORecord(id="q", dataset="pku"), PosterOConfig()).startswith("Final:")
True
Source code in models/postero/src/postero/serialization.py
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
def build_final_svg_prompt(
    labels: Sequence[int | str], record: PosterORecord, config: PosterOConfig
) -> str:
    """Build the final allocation prompt.

    Args:
        labels: Labels to allocate.
        record: Query record with canvas and available regions.
        config: Prompt configuration.

    Returns:
        Deterministic final prompt text.

    Examples:
        >>> from postero.config import PosterOConfig
        >>> from postero.records import PosterORecord
        >>> build_final_svg_prompt([1], PosterORecord(id="q", dataset="pku"), PosterOConfig()).startswith("Final:")
        True
    """
    prompt = f"Final: This svg uses canvas_0 of size {config.canvas_size} "
    if record.available_regions:
        prompt += (
            "with available areas "
            + build_available_area_polygons(record.available_regions)
            + " "
        )
    names = [
        label_name(label, config.id2label or {})
        for label in labels
        if str(label) != "canvas"
    ]
    prompt += "to allocate { " + ", ".join(
        f"{name}_{index + 1}" for index, name in enumerate(names)
    )
    prompt += " }.\n"
    return prompt

serialize_record

serialize_record(
    record: PosterORecord, config: PosterOConfig
) -> tuple[str, str]

Serialize a record using the configured structure.

Source code in models/postero/src/postero/serialization.py
170
171
172
173
174
175
176
177
def serialize_record(record: PosterORecord, config: PosterOConfig) -> tuple[str, str]:
    """Serialize a record using the configured structure."""
    structure = cast(PosterOStructure, config.structure)
    if structure is PosterOStructure.plain:
        return serialize_plain_svg(record, config)
    if structure is PosterOStructure.hierarchical:
        return serialize_hierarchical_svg(record, config)
    assert_never(structure)

vendor_parity

Small deterministic PosterO parity fixtures.

parity_config

parity_config() -> PosterOConfig

Return the deterministic prompt/parser parity configuration.

Source code in models/postero/src/postero/vendor_parity.py
34
35
36
37
38
39
40
41
42
43
44
def parity_config() -> PosterOConfig:
    """Return the deterministic prompt/parser parity configuration."""
    return PosterOConfig(
        structure=PosterOStructure.plain,
        injection=PosterOInjection.top,
        pool_strategy=PosterOPoolStrategy.all,
        rank_strategy=PosterORankStrategy.rank_by_label,
        sample_size=1,
        n_valid_layouts=1,
        num_return=2,
    )

fixture_records

fixture_records() -> tuple[
    PosterORecord, list[PosterORecord]
]

Return query and candidate records shared by tests and scripts.

Source code in models/postero/src/postero/vendor_parity.py
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
def fixture_records() -> tuple[PosterORecord, list[PosterORecord]]:
    """Return query and candidate records shared by tests and scripts."""
    query = PosterORecord(
        id="query-pku",
        dataset="pku_posterlayout",
        available_regions=[AvailableRegion(bbox_ltrb=(20.0, 40.0, 493.0, 710.0))],
        elements=[
            PosterLayoutElement(label=1, bbox_ltrb=(60.0, 80.0, 300.0, 140.0)),
            PosterLayoutElement(label=2, bbox_ltrb=(350.0, 620.0, 460.0, 700.0)),
        ],
        features=[0.0, 1.0],
        metrics={"alignment": 1.0},
    )
    candidates = [
        PosterORecord(
            id="candidate-a",
            dataset="pku_posterlayout",
            available_regions=[AvailableRegion(bbox_ltrb=(18.0, 42.0, 490.0, 708.0))],
            elements=[
                PosterLayoutElement(label=1, bbox_ltrb=(50.0, 70.0, 280.0, 130.0)),
                PosterLayoutElement(label=2, bbox_ltrb=(345.0, 600.0, 460.0, 690.0)),
            ],
            features=[0.0, 0.9],
            metrics={"alignment": 1.0},
        ),
        PosterORecord(
            id="candidate-b",
            dataset="pku_posterlayout",
            elements=[PosterLayoutElement(label=3, bbox_ltrb=(0.0, 0.0, 513.0, 750.0))],
            features=[1.0, 0.0],
            metrics={"alignment": 1.0},
        ),
    ]
    return query, candidates

golden_prompt

golden_prompt() -> str

Return the deterministic prompt fixture for parity tests.

Source code in models/postero/src/postero/vendor_parity.py
83
84
85
86
def golden_prompt() -> str:
    """Return the deterministic prompt fixture for parity tests."""
    query, candidates = fixture_records()
    return build_prompt(query, [candidates[0]], config=parity_config())

implementation_reference

implementation_reference() -> dict[
    str, str | list[str] | list[int] | list[list[float]]
]

Return prompt, selection, and parser metadata from this package.

Source code in models/postero/src/postero/vendor_parity.py
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
def implementation_reference() -> dict[
    str, str | list[str] | list[int] | list[list[float]]
]:
    """Return prompt, selection, and parser metadata from this package."""
    config = parity_config()
    query, candidates = fixture_records()
    selected = select_exemplars(query, candidates, config=config)
    prompt = build_prompt(query, selected, config=config)
    elements, _diagnostics = parse_svg_response(PARSER_RESPONSE, config=config)
    return {
        "prompt": prompt,
        "prompt_sha256": hashlib.sha256(prompt.encode()).hexdigest(),
        "selected_exemplar_ids": [record.id for record in selected],
        "parser_labels": [element.label for element in elements],
        "parser_bbox_ltrb": [list(element.bbox_ltrb) for element in elements],
    }

implementation_retry_calls

implementation_retry_calls() -> int

Run this package's retry loop and return provider call count.

Source code in models/postero/src/postero/vendor_parity.py
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
def implementation_retry_calls() -> int:
    """Run this package's retry loop and return provider call count."""
    config = parity_config()
    query, candidates = fixture_records()
    calls = {"count": 0}
    responses = [INVALID_RESPONSE, PARSER_RESPONSE]

    def respond(_messages: list[ModelMessage], _info: AgentInfo) -> ModelResponse:
        text = responses[calls["count"]]
        calls["count"] += 1
        return ModelResponse(parts=[TextPart(content=json.dumps({"text": text}))])

    PosterOAgent(model=FunctionModel(respond), config=config).run_sync(
        query,
        candidate_records=candidates,
    )
    return calls["count"]