Playbook — text use cases¶
Text is not an experiment type of its own: it is free text, tag lists or packed tokens that carry
the signal of a supervised, anomaly or clustering problem — claim notes that reveal fraud,
support tickets grouped into themes, a ticket that contradicts itself. Follow the type's playbook
(get_playbook("type-supervised") or get_playbook("type-unsupervised")) and add this one at
each step. ParleML encodes text several ways; use its options before writing keyword SQL.
Frame¶
- Which columns carry the signal —
get_eda(section="columns"): each string column'sprose_rateandvalue_checkssay whether it is prose, a tag list or weighted tokens. Ask the person what each field is and when it is written: notes added during an investigation are written after the moment, and their words can give the outcome away. - The requirement choice — supervised:
text_heavywhen free text carries the signal, with the person told that neural embeddings cost compute. Clustering: whether an embedding model may run (a local one needs its weights; a provider sends the text out and is paid per call — the user approves it before it is used,overview.md, Paid external services). - What the person wants to read back — the terms and tags behind a prediction (supervised), the themes behind a cluster (clustering), a reason a reviewer can check.
Data¶
Map every text-like column with prepare_data(action="columns") (get_playbook("deliver"),
Column domains); the same mapping drives every type:
| Domain | Supervised | Anomaly | Clustering |
|---|---|---|---|
{type: "text"} (prose) |
TF-IDF terms, their topics and a stacked linear score | TF-IDF | TF-IDF |
{type: "text", domain: "embedding"} |
sentence embeddings | not encoded (embeddings are clustering-only) | sentence embeddings, fused with the other columns |
{type: "text", domain: "mt", delimiter} (tag list) |
one feature per tag, learned in each fold | topics (NMF) | topics (NMF) |
{type: "text", domain: "wt", delimiter} (weighted tokens) |
token counts, compressed | topics (NMF) | topics (NMF) |
For clustering and anomaly runs, also list the text columns in feature_cols. A text column with
no domain is read as one opaque category: map it, or ignore it for a reason you can name.
Clustering: fields people want described per cluster but not clustered on go in the block's
unsupervised.passive_columns; unsupervised.use_text_embeddings: false turns the embedding
pass off.
Validation¶
The type's validation applies. Text adds one leakage check: the words. A term that only appears once the outcome is known ("confirmed", "referred to SIU", "refund issued") is a leak, whatever the split.
Baseline¶
On a support-case table — after mapping a short Subject to {type: "text"} and a long
Description to {type: "text", domain: "embedding"}:
{
"experiment": {
"workspace_id": "<workspace_id>", "name": "support themes baseline", "type": "cluster",
"dataset_id": "<dataset_id>",
"unsupervised": {
"task": "clustering",
"feature_cols": ["Subject", "Description"],
"unsupervised": {"passive_columns": ["Case Record Type", "Priority", "Status"]},
"clustering": {"algorithm": "kmeans", "n_clusters": "auto"}
}
},
"hypothesis": {"lever": "baseline", "expected_effect": "The case text separates a handful of support themes."}
}
On a claims table — after mapping a tag list to mt, weighted tokens to wt, a short note to
{type: "text"} and a long description to embedding — and only once each text field is
known to be written before the prediction moment (a note written during an investigation
carries its outcome):
{
"experiment": {
"workspace_id": "<workspace_id>", "name": "claims fraud baseline", "type": "supervised",
"dataset_id": "<dataset_id>", "target": "fraud", "template_name": "text_heavy",
"config": {"ml_task": "binary_classification", "eval_metric": "average_precision", "positive_class": "fraudulent"}
},
"hypothesis": {"lever": "baseline", "expected_effect": "Loss tags and adjuster notes carry most of the fraud signal."}
}
Iterate¶
Text settings are levers (other, or column_roles for a domain). Each experiment should test
a justified hypothesis, citing the text_insight (or cluster profile) evidence behind it:
- A column's encoding — TF-IDF ↔ embedding, a tag list's delimiter, through the plan's
column_roles.overrides(supervised) orunsupervised.tfidf_columns/nmf_columns/text_columns(clustering, anomaly); a column dropped because its words are written too late. - Supervised TF-IDF (
config.stateful_fe):text_analyzer: "char_wb"when the top terms are fragments, codes or misspellings;text_ngram_range: [1, 3]when phrases carry the meaning;text_stop_words: "english"when stop words crowd the top terms;text_max_features,text_svd_components. - Supervised embeddings —
add_text_embeddings: truewithtext_embedding_modeaugmentorreplace. The source isconfig.stateful_fe.text_embedding(clustering:unsupervised.text_embedding.sourceand.connection): on this server by default;{source: "provider", connection}sends the text to that provider — a paid service — at training and at every scoring call, so the user approves it first:run_experiment(action="launch")cites the gate'squestion_idin a session, or carriespaid_services_approved: trueoutside one, set only after the user said yes. - Clustering —
unsupervised.text_block_weightwhen the text dominates the clusters or vanishes from them;tfidf_svd_components,nmf_components;unsupervised.text_stop_words(one word per entry) for words that are in the text but must not shape the groups — product names substituted into templated subjects — kept out of the TF-IDF encoding and the cluster keywords alike (an embedding column still reads them: strip those with a recipe). - The embedding domain needs its model —
describe_platform("domains"): theembeddingrow'ssentence_embedding_modelrequirement says whether this server can embed; a clustering plan that embeds a column the server cannot is refused with the remedies.
A readable reason a reviewer needs ("urgent delivery note") comes from the run's own text reads
(text_insight terms, rules on text features) before any hand-coded keyword flag; a keyword flag
in SQL is the last resort, and says which terms it took from which read.
Insights¶
| Read | For |
|---|---|
get_capabilities(experiment_id) |
insight_encoders: the text and tag columns the run can explain |
get_insight(kind="text_insight", params={encoder, feature}) |
supervised: relevant encoder/feature pairs, showing the terms or tags behind a text driver and their direction |
get_insight(kind="engineered_features") |
supervised: which derived columns (loss_tags_MT_0, adjuster_notes_TSVD_3 …) came from which text column, and how important each is |
get_insight(kind="unsupervised_summary"), get_insight(kind="unsupervised_features") |
clustering and anomaly: the text blocks used and the clusters they formed |
A cluster's profile reports a text column on a derived axis (rel, best of N dims): never
restate it as standard deviations of the column (get_playbook("schema-unsupervised")).
Challenge¶
Read the top terms of every text driver (get_insight(kind="text_insight", params={encoder,
feature})) for words that are only written after the outcome, and say which column wrote them.
A cluster name generated from the text is AI-written: judge the cluster by its computed profile.
Decide¶
The type's decision applies; text changes nothing in how the operating point is chosen.
Release and operate¶
The type's release applies. State in the release record's limitations which text columns the model reads and how each is encoded; new text with a different vocabulary (a new product, a new form) is drift the column statistics can miss — compare the top terms of a rescored batch with the training ones.