Skip to content

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's prose_rate and value_checks say 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_heavy when 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) or unsupervised.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: true with text_embedding_mode augment or replace. The source is config.stateful_fe.text_embedding (clustering: unsupervised.text_embedding.source and .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's question_id in a session, or carries paid_services_approved: true outside one, set only after the user said yes.
  • Clustering — unsupervised.text_block_weight when 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"): the embedding row's sentence_embedding_model requirement 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.