Skip to content

DO NOT MERGE: Add dataset builder docs - #1857

Open
Jack Keene (Jack-Keene) wants to merge 13 commits into
mainfrom
signals-dataset-builder
Open

DO NOT MERGE: Add dataset builder docs#1857
Jack Keene (Jack-Keene) wants to merge 13 commits into
mainfrom
signals-dataset-builder

Conversation

@Jack-Keene

@Jack-Keene Jack Keene (Jack-Keene) commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

What changed?

Docs for as yet unreleased dataset builder AISP 1401 & 1402

AI reviews

Claude will automatically review this PR against the docs style guide.

If you have questions or want it to look again at something specific, tag @claude in a comment.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 16, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
documentation 96d0049 Commit Preview URL

Branch Preview URL
Aug 04 2026, 09:17 AM

@claude

claude Bot commented Jul 16, 2026

Copy link
Copy Markdown

Documentation style review

Overall this is a well-structured, cleanly written page — good frontmatter, sentence-case headings, 4 H2 sections (within the 3–5 limit), correct terminology, and all internal links (attribute-groups, connection) end in /index.md and resolve. No external URLs were touched. A few style items to address:

1. Bold used for non-UI text (CLAUDE.md)

CLAUDE.md: "Use bold only for UI elements (buttons, page titles)." The stage names in the "How it works" list are bolded but aren't UI elements:

1. **Anchors** - identify moments in historical sessions...
2. **Attributes** - compute attribute values...
3. **Assembly** - join anchors...

Suggest removing the bold (the names are already emphasized by their list position), e.g. 1. Anchors: identify moments in historical sessions.... Note CLAUDE.md overrides the style guide's more permissive "bold or italic to highlight key phrases" here.

2. Underscore name not in backticks (style guide)

Style guide: "If the name has underscores, use code formatting."

| ... | Default: page_ping events excluded |

Should be `page_ping`.

3. Spaced hyphens used as dashes (minor)

Several sentences use a spaced hyphen - as a dash, e.g.:

"You specify a goal - the criteria that define a positive outcome - and a time window to scan."

Prefer an em dash or restructure with a colon/commas, e.g. "You specify a goal (the criteria that define a positive outcome) and a time window to scan." This applies in a few other places (the "How it works" list items, "Session anchors" intro).

Minor note

The ### Snowflake heading is followed immediately by a code block with no prose of its own (the style guide asks that every heading be preceded/backed by a paragraph). The parent H2 has a lead-in sentence, so this is borderline — optional to add a short introductory line.

Comment thread docs/signals/applications/create-training-datasets/index.md Outdated
Comment thread docs/signals/applications/create-training-datasets/index.md Outdated
Comment thread docs/signals/applications/create-training-datasets/index.md Outdated
Comment thread docs/signals/applications/create-training-datasets/index.md Outdated
Comment thread docs/signals/applications/create-training-datasets/index.md Outdated

@jborlase-snowplow jborlase-snowplow left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some comments.

I think we need a tutorial to alongside the release of this to make it clear on how we expect this to be used.


The dataset builder produces a training dataset in three stages:

1. **Anchors** - identify moments in historical sessions where a user either achieved a goal (positive label) or did not (negative label)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this section could use a diagram to make it clear how anchors and attributes work


Use the Signals Python SDK to build labeled training datasets from your [attribute groups](/docs/signals/attributes/attribute-groups/index.md). The dataset builder generates SQL that computes attribute values over historical data and joins them with labeled anchor events, producing a dataset ready for model training.

Start by [connecting to Signals](/docs/signals/connection/index.md) to create a `Signals` client object.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have a more high-level why / how it works section showing how this is meant to be used to enable you to train ML models using same definitions as your attribute groups that you can use to serve the attributes to your ML models

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and there we can highlight why PIT correctness is important

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also highlight the overall process we expect users to take - not just the flow on how the dataset builder works.

schema="ml",
table="my_anchor_events",
),
has_label=True,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does label need to look like?

from snowplow_signals import UserSuppliedAnchors, WarehouseTable

anchors = UserSuppliedAnchors(
source=WarehouseTable(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we show an example input table and requirements?

start_time=datetime(2024, 1, 1, tzinfo=timezone.utc),
end_time=datetime(2024, 4, 1, tzinfo=timezone.utc),
),
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we show example output of what this creates?


## Execute against your warehouse

Execute the generated SQL directly against your warehouse to produce the training dataset.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should explain a bit about how - for example - using your existing Signals warehouse connection...

account=os.environ["SNOWFLAKE_ACCOUNT"],
user=os.environ["SNOWFLAKE_USER"],
warehouse=os.environ["SNOWFLAKE_WAREHOUSE"],
private_key=private_key_der,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the private key? Do we just auth via this? Is that the Snowflake term?

| `source` | Table containing your pre-built anchor events | `WarehouseTable` | ✅ |
| `has_label` | Whether the source table contains a label column | `bool` | Default: `True` |

## Build the dataset

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This header shouldn't be build the dataset - its more related to building the SQL rather than the actual dataset

print(df.head())
```

You can also inspect the execution stages:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the execution stages?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it is for monitoring execution - this doesn't feel like it should be in this section

After execution, convert the result to a pandas DataFrame for analysis or model training.

```python
df = result.to_pandas()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should show example of what is the output

After execution, access the `dataframe` attribute to get the training dataset as a pandas DataFrame, ready for model training.

```python
df = result.dataframe

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note to update this to reflect the changes in the SDK.

@jborlase-snowplow jborlase-snowplow left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few more suggestions to the structure

4. Execute the SQL against your warehouse to produce the training dataset
5. Train your model on the resulting DataFrame
6. Deploy your model, serving it the same attributes in real time via [Retrieve attributes](/docs/signals/applications/retrieve-attributes/index.md)
2. Submit a dataset run by calling the appropriate method - `submit_dataset_run_with_session_anchors()` for auto-generated anchors, or `submit_dataset_run_with_custom_anchors()` for a pre-existing anchor table

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should abstract these steps - as both methods now exists.

  1. Prepare the dataset SQL...
  2. Generate your SQL by running the queries against your warehouse - you can do this by X or Y.

### Session anchors

Use `build_dataset_with_session_anchors()` to automatically generate anchors from your event data. You specify a goal (the criteria that define a positive outcome) and a time window to scan. Signals scans all sessions in the training window and labels each based on whether the goal was achieved. For positive sessions, anchors are placed at the goal event itself. For negative sessions (where the goal was never achieved), anchors are placed at randomly selected events within the session. Negative anchors are then downsampled according to `max_negative_ratio` to avoid class imbalance.
Use `submit_dataset_run_with_session_anchors()` to automatically generate anchors from your event data and build the training dataset server-side. You specify a goal (the criteria that define a positive outcome) and a time window to scan. Signals scans all sessions in the training window and labels each based on whether the goal was achieved. For positive sessions, anchors are placed at the goal event itself. For negative sessions (where the goal was never achieved), anchors are placed at randomly selected events within the session. Negative anchors are then downsampled according to `max_negative_ratio` to avoid class imbalance.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did we completely remove the other option? Shouldn't there be both in here now?

| `max_lookback_days` | How far back from each anchor timestamp to look for events when computing attributes. By default, this is derived from the longest period defined across your attributes. | `int` | Default: derived from attribute periods |

## Inspect and save the SQL bundle
## Poll for completion and retrieve results

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, this should be additional and probably under a heading where customers can decide to run it themselves or let us manage it.

### Get results as a DataFrame

After execution, call `to_pandas()` to pull the training dataset into a pandas DataFrame, ready for model training. By default, it fetches up to 10,000 rows.
Once the run status is `success`, call `get_dataset_run_preview()` to fetch a preview of the completed dataset. By default, it returns up to 100 rows. You can set `limit` up to 10,000.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why just a preview?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be millions of rows - its probably best not to load it into python

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not let customers decide how to configure it?

You'd expect to need millions of rows and might have a powerful environment to do just that?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry probably wasn't clear - this is returned via the signals API, so if we loaded too much data into the json response it could crash our server. I think its ok to expect the customer to fetch the full dataset directly from Snowflake

| 1 | def-456 | 2024-01-15 10:01:00 | 0 | 3 | 0 |
| 2 | ghi-789 | 2024-01-16 14:22:00 | 1 | 8 | 4 |

The full dataset is also written to your warehouse at the table location shown in `run.dataset`. You can query this table directly for the complete result set.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we require them to query table directly - then we should provide example on how to do that

sp_signals.cancel_dataset_run(run.id)
```

## Inspect the generated SQL

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see its down here - I would arrange this page into the higher level abstractions as headings I mentioned above, and then within that give the customers the option to choose which way they do it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants