SemCluster
Recover groups of equivalent or criterion-related values within one Space.
SemCluster is the semantic deduplication operation. It is also useful for grouping
mentions of the same event, entity, intent, or concept. The prompt defines exactly what may share a
cluster.
from scratchpad.api import SemCluster, gates
SemCluster(
name="group-news-events",
input_spaces=("headlines",),
output_space="event-clusters",
primary_key="headline",
prompt=(
"Group headlines only when they report the same developing event. "
"A shared person, company, sport, or broad theme is not enough."
),
provider="openai",
model="gpt-5",
reasoning_effort="low",
batch_size=16,
rho=0.30,
merge_only_if=gates.equal("category"),
)| Parameter | Default | Meaning |
|---|---|---|
input_spaces | required | The Space or Spaces read by the task. |
output_space | required | The Space that receives the task output. |
name | generated | A stable task name used in reviews, sessions, and metrics. |
primary_key | id | The semantically meaningful field that identifies a value for this task. Rows with the same primary key represent one task value and produce one task result. Use Union first when every source identity must remain attached. |
evidence | none | Optional supporting fields shown to the semantic model. Do not repeat a primary-key field or include irrelevant metadata. |
prompt | required | The criterion or transformation written in plain language. |
provider / model | required | The model used for this task's data decisions. |
reasoning_effort | low | OpenAI GPT-5-family reasoning effort. Use none for the lowest-latency, lowest-reasoning-cost path when the task contract is precise; increase it only after representative quality evidence justifies the added time and spend. |
include_reason | true | Whether every model decision includes item-local visible evidence. The compiled prompt defaults to at most ten words; an explicit prompt request for longer visible reasoning is preserved. This is generation guidance; returned reasons are never truncated. Set false only for a validated task where result and confidence suffice. |
confidence_threshold | operator default | Exact boundary between unresolved and accepted evidence. Relifold compiles this value and operator-specific confidence guidance into the effective judge prompt. |
function_parameters | registered gate defaults | Typed values for a generated semantic pair predicate such as merge_only_if, ancestor_only_if, match_only_if, or relate_only_if. The predicate declares the schema and finite candidates; reviewed evidence can then support parameter advice. Closed library gates do not take these bindings. |
max_llm_calls | unlimited | A hard task-level call ceiling. The task stops instead of silently exceeding it. |
max_cost_usd | unlimited | A hard task-level model-cost ceiling. A session-level ceiling may be stricter. |
max_output_tokens | 2048 | Maximum generated tokens per model request. Increase it when one legitimate batch cannot fit its structured result. |
| Parameter | Default | Meaning |
|---|---|---|
batch_size | operator default | Number of values considered together in one semantic request. |
rho | 0.0 | Additional quality-check allowance relative to the initial semantic work. For example, 0.30 allows up to 30% more calls to recheck weak decisions. |
max_rounds | operator default | Maximum iterative clustering rounds. |
max_components | unlimited | Optional upper bound on the number of clusters. |
max_component_size | unlimited | Optional upper bound on cluster size. |
merge_only_if | none | A permanent deterministic cannot-link boundary. Use it only when a false pair must never share a cluster, such as incompatible dates or geography. |
Deduplication boundary
Do not merge a more specific value into a broader one merely because the broader value summarizes it. “Workout” may match a true synonym such as “exercise,” while “running” and “camping” retain information that “workout” does not.
Exact duplicates
If equality is a column comparison, use Union(key=...). It is deterministic and
does not spend model budget.
Indexed hard constraints
Use merge_only_if=gates.equal("category") when different categories are a true final
incompatibility. For human-entered text,
gates.equal("category", normalize_text=True, require_nonempty=True) compares lowercase,
whitespace-normalized values while rejecting blanks. The predicate is both the indexed candidate
boundary and a permanent cannot-link rule: any rejected pair can never merge.
Do not place approximate retrieval, lexical similarity, or embedding thresholds in
merge_only_if unless their false pairs are genuinely impossible under the authored
clustering definition. Keep a lossy approximation in an explicit predecessor task so its recall
tradeoff remains visible and reviewable.
Calibrated gate parameters
from scratchpad.api import FunctionParameter, PythonFunction, SemCluster, gates
eligible_event_pair = PythonFunction(
name="eligible_event_pair",
source="""def eligible_event_pair(left, right, *, max_days):
if left.get('category') != right.get('category'):
return False
return abs(left['event_day'] - right['event_day']) <= max_days
""",
parameters={
"max_days": FunctionParameter(
value_type="number",
default=90,
minimum=1,
maximum=365,
candidates=(30, 90, 180),
description="Maximum possible span of one event thread.",
),
},
candidate_gate=gates.equal("category", require_nonempty=True),
)
SemCluster(
name="group-events",
input_spaces=("event-signatures",),
output_space="events",
primary_key="event_signature",
evidence=("title", "event_day"),
prompt="Merge only reports of the same bounded real-world occurrence.",
provider="openai",
model="gpt-5",
reasoning_effort="low",
merge_only_if=eligible_event_pair,
function_parameters={"max_days": 90},
)
The registered function owns the parameter schema and finite candidates; the task owns this version's resolved value. The candidate index must be a complete sparse-enumeration precondition, while the function applies the full hard boundary. Parameter advice remains unavailable unless the review hand covers every pair a candidate setting could expose.
Large and growing catalogs
Do not send an unbounded connector Space directly into SemCluster. First use a
linear SemTransform to produce a compact meaning-based canonical signature,
consolidate exact signatures while retaining every source identifier, and bound the representative
hand before semantic refinement. Deterministic token cleanup or lexical signatures can assist
retrieval but do not replace the semantic assignment. Keep the full identifier mapping on a
separate lookup path and overlay bounded refinements rather than dropping unselected assignments.
A call or dollar cap limits spend; it does not turn an unbounded relationship result into a
complete partition.
Cost estimate
SemCluster forecasting is based on the final quotient structure. For N values,
M expected final clusters, and Q still-eligible pairs between those
clusters, the certificate has (N-M)+Q witnesses. Compatible complete executions and
draft-research hands teach cluster growth, quotient density, and physical packing. One completed
hand calibrates packing at its exact extent; cross-extent packing requires at least three distinct
completed extents. With less evidence, perfect packing remains a labelled lower-bound scenario and
expected cost stays unknown. Relifold then recomputes the operator geometry for the current
extent; it never multiplies a smaller run's cost by the row ratio. The UI reports the mathematical
floor, evidence-backed expected interval, and
candidate-retirement ceiling separately. Cold token pricing uses the operator's actual response
shape: node-keyed partition hands for SemCluster, rather than pair-label volume. A compatible
complete exact-shape hand supersedes that structural envelope.