Annotations¶
rfgen splits dataset generation into two phases: Phase 1 writes IQ samples, labels, and verified metadata; Phase 2 turns that metadata into natural-language artifacts for multimodal training. This page covers Phase 2: captions, QA pairs, reasoning traces, scene reports, and contrastive pairs. The metadata-to-text pattern follows RF-GPT’s synthetic RF instruction generation workflow and WavCaps’ LLM-assisted caption-cleaning pipeline [1, 2].
Annotations are grounded in metadata only. The annotation layer does not see in-phase / quadrature (IQ) samples, spectrograms, or raw samples. It reads structured records, renders constrained prompts, calls an inference client, validates the returned JSON, and appends the text back to storage.
Minimal Example¶
from rfgen.annotators import MetadataAnnotator, Templater, whitelist_filter
from rfgen.enums import AnnotationType
from rfgen.inference.clients import inference_client_registry
# store.read() returns a full Record with IQ, labels, and metadata.
store_handle = ...
raw = store_handle.read("sha256:abc")
record = whitelist_filter(raw, sample_id="sha256:abc")
client = inference_client_registry.get("<your-provider>")()
templater = Templater()
annotator = MetadataAnnotator.from_components(client=client, templater=templater)
prompt = templater.render(
record=record,
annotation_type=AnnotationType.CAPTION,
template_id="caption.dense.v3",
)
response = client.complete(prompt=prompt.user, json_schema=prompt.output_schema)
annotated = annotator.annotate(
record,
annotation_type=AnnotationType.CAPTION,
template_id="caption.dense.v3",
run_id="run-2026-07-08",
)
"<your-provider>" is the provider key from the rfgen config. The
Templater returns a Prompt with system text, user text, and an output
schema; passing json_schema=prompt.output_schema asks the inference client to return
JSON that can be validated against that schema. The caption.dense.v3
identifier follows the <type>.<variant>.v<version> convention described in
Reference / Annotation Templates § Versioning.
The exact client classes, model IDs, schemas, and orchestration commands belong
in Reference / Annotation Templates
and Reference / API / rfgen.annotators.
Two-Phase Generation¶
Phase 1 writes IQ samples, labels, and verified metadata. Phase 2 reads that metadata and appends text.
The split is deliberate:
IQ generation and text generation have different cost models, retry policies, and scaling limits.
Text runs can be reprocessed without regenerating IQ.
Multiple annotation templates can coexist against the same Phase 1 dataset.
Failed annotation jobs can resume by checking which
(sample_id, annotation_type, template_id, run_id)outputs already exist.
Phase 2 is append-only. A new run creates a new overlay instead of silently overwriting a previous result. Template changes are part of the authenticated annotation payload: reusing an existing overlay identity with a different template is a conflict, so use a new run for that change.
Source. RF-GPT separates standards-compliant RF scene generation from LLM-produced instruction data, and WavCaps uses a staged LLM pipeline to turn noisy source descriptions into usable captions [1, 2].
Grounding Contract¶
The text layer may only use fields that are explicitly present in the structured record or derived labels. This keeps captions auditable and prevents the LLM from inventing RF attributes it cannot observe.
Grounding controls:
Control |
Purpose |
Source |
|---|---|---|
Metadata-only prompts |
Prevent the model from inferring unsupported signal properties from rendered media. |
RF-GPT metadata-derived instruction data [1] |
Deterministic templating |
Defines which facts each annotation must mention before the model rewrites them. |
WavCaps LLM-assisted filtering and transformation pipeline [2] |
JSON-constrained output |
Makes validation mechanical instead of regex-based. |
JSON Schema validation vocabulary [5] |
Closed vocabulary |
Rejects modulation, channel, unit, or taxonomy terms outside the ClosedVocab, for example unsupported |
RF-Analyzer hallucination and prompt-leakage checks [3] |
Verifier subset |
Samples generated text and checks whether physical attributes can be recovered from it. |
RF-Analyzer PAES metric [3] |
The verifier does not make text “true” by itself. It is an audit layer that measures whether generated annotations preserve the physical facts present in metadata.
Annotation Types¶
An annotation job carries the logical selector
(sample_id, annotation_type, template_id, run_id). The durable overlay key is
slightly different:
(dataset_id, sample_id, annotation_type, run_id)
dataset_id binds the row to one dataset. sample_id is assigned during Phase
1 storage, annotation_type is selected from the
AnnotationType enum, and the command
derives the durable UUID run_id from the job’s run identifier. template_id
is not a second index dimension. It is carried inside the RFC 8785 canonical
row envelope with the result and error, so a resume verifies that the stored
template matches the requested job. This preserves the job-level template
contract without allowing two different template payloads to occupy one
append-only overlay.
Provider/model metadata, output-schema versions, and ClosedVocab versions remain reproducibility data alongside the annotation; they are not overlay-key fields.
The annotation types are:
Member |
Typical use |
Source |
|---|---|---|
|
Concise natural-language description of the scene or component. |
RF-GPT dense RF captions and WavCaps audio captions [1, 2] |
|
Question-answer pairs grounded in known metadata. |
RF-GPT instruction-answer generation [1] |
|
Stepwise explanation for a metadata-derived conclusion. |
RF-GPT multi-task instruction data [1] |
|
Denser summary of emitters, receivers, signal-to-noise ratios (SNRs), overlap, and channel conditions. |
RF-Analyzer physical-attribute extraction dimensions [3] |
|
Paired descriptions for similarity, difference, or retrieval training. |
CLIP image-text contrastive objective [4] |
Exact schemas and token budgets belong in the annotation-template reference.
Transactional Overlay Publication¶
AnnotationOverlayTransactions publishes a canonical row through the Layer 17
transaction coordinator. The idempotency key is the SHA-256 digest of RFC 8785
bytes containing both the durable overlay key and the complete row envelope.
The caller must supply that exact digest; an arbitrary retry token is rejected.
Each dataset has one authoritative append-only annotation index. Its committed
LATEST pointer names an immutable index object and the immutable row objects
introduced by that revision. A reader resolves the index before reading a row,
then verifies the row’s key, canonical bytes, and digest. Therefore an
immutable row staged before a crash is not visible until an index revision
references it. Single-row and batch publication both merge into this same
dataset index; they do not maintain competing per-row pointers.
The publication lifecycle is STAGED, COMMITTED, CONFLICT, or ABORTED.
For an identical replay, the existing canonical row returns its original
committed revision without another visible write. A different canonical row for
the same overlay raises AnnotationConflictError and leaves the visible index
unchanged. A single-row first append may also require that an
expected_revision equal the currently observed index revision.
Batches, Contention, And Recovery¶
A batch is restricted to one dataset. Before writing, it canonicalizes rows, sorts them by durable overlay key, collapses exact duplicates, and rejects a divergent duplicate. The new rows and the one merged dataset index are staged and published in one Layer 17 transaction. A failed batch therefore leaves the previous dataset index visible rather than a visible prefix; only committed keys become persistence checkpoints.
Independent writers reread the current dataset index after a conditional pointer conflict. Identical writers converge on the same committed revision; writers offering different bytes for the same overlay conflict. If a commit response is lost, publication asks the coordinator to reconcile the transaction before retrying, rather than issuing a blind pointer update. This covers crashes after row staging, index staging, or the pointer compare-and-swap: recovery settles to one committed index containing the rows or leaves no newly visible rows.
Command Persistence Scope¶
When rfgen annotate receives a local path or file: store URI, it binds
annotation persistence to a Layer 17 local transaction backend rooted beside
that dataset. Provider execution can still produce results, but durable command
publication currently requires that local transaction backend. A nonlocal
store_uri is rejected explicitly until the matching provider transaction
backend is configured; it is not treated as a local filesystem path or silently
persisted through the legacy append API.
Batch And Provider Abstraction¶
Production annotation should use provider batch APIs where available. Developer iteration can use synchronous calls, and verifier runs may use a smaller synchronous subset if that is simpler operationally.
Provider choice is a configuration concern. The durable architecture is:
a bulk inference tier for rewriting deterministic template output into natural language;
a verifier tier for quality measurement;
an optional self-hosted tier for restricted or air-gapped data.
Specific model SKUs change too often for a concept page. Pin exact model IDs, prices, and refresh dates in an ADR or reference page.
Source. WavCaps uses LLMs for high-volume caption transformation, while RF-Analyzer’s PAES motivates a separate verifier pass for physical-attribute consistency [2, 3].
Determinism And Versioning¶
Phase 1 aims for deterministic IQ samples and labels. Phase 2 is different: hosted LLMs do not generally guarantee byte-identical text across time, even at low sampling temperature, the common LLM control for output randomness. Annotation reproducibility therefore comes from versioned inputs and append-only outputs:
template_ididentifies the prompt template.run_ididentifies a concrete annotation run.provider and model metadata identify the inference endpoint.
output schemas and ClosedVocab versions identify validation rules.
Changing any of these should produce a new run, not mutate an old one. In
particular, changing template_id while reusing the same durable run identity
is a conflict rather than a second row.
Design Rationale¶
Why metadata-only instead of spectrogram-conditioned?
For synthetic data, the pipeline already has ground truth. Metadata-only annotation is cheaper, easier to validate, and easier to audit than asking a vision-language model to infer attributes from a rendered spectrogram. Models trained on the resulting data still learn from IQ downstream; the LLM just creates text supervision.
Why JSON instead of free-form text?
JSON gives the pipeline a structured envelope for schema validation, closed-vocabulary checks, and downstream conversion. The natural language still lives inside JSON fields, but the record remains machine-checkable.
What can go wrong?
The main risks are schema drift, unsupported facts in prompts, prompt templates that leak task answers, verifier prompts that do not match bulk outputs, and provider/model rotation. The mitigation is to version templates, schemas, closed vocabularies, and runs together.
References¶
Zayoud, M. et al. RF-GPT: Teaching AI to See the Wireless World. arXiv:2602.14833, 2026. https://arxiv.org/abs/2602.14833. (Synthetic RF scenes converted into RF-grounded captions and instruction-answer data)
Mei, X. et al. WavCaps: A ChatGPT-Assisted Weakly-Labelled Audio Captioning Dataset for Audio-Language Multimodal Research. arXiv:2303.17395, 2023. https://arxiv.org/abs/2303.17395. (LLM-assisted filtering and transformation pipeline for captions)
Bara, A. et al. RF-Analyzer: Can Vision-Language Models Learn RF Understanding from Synthetic Data? arXiv:2605.04676, 2026. https://arxiv.org/abs/2605.04676. (Physical Attribute Extraction Score, prompt leakage, and hallucination checks)
Radford, A. et al. Learning Transferable Visual Models From Natural Language Supervision. ICML, 2021. https://arxiv.org/abs/2103.00020. (Contrastive image-text training objective)
JSON Schema contributors. JSON Schema: A Media Type for Describing JSON Documents. https://json-schema.org/draft/2020-12/json-schema-core. (Schema vocabulary for validating JSON documents)
See Also¶
Reference / API /
rfgen.annotatorsfor class signatures and method contracts.Reference / Annotation Templates for prompt structure, output schemas, token budgets, and closed vocabulary.
How-to / Annotate existing dataset for running Phase 2 against an existing Phase 1 corpus.
Concepts / Labels for the metadata and labels that ground annotations.
Concepts / Storage for append-only text runs.
Background / Design Decisions for the broader two-phase rationale.