Conversational AI agent that drives scikit-rec via tool use
Project description
scikit-rec-agent
Conversational AI agent that uses scikit-rec as its tool belt. The agent reasons about the user's data and goals, then calls scikit-rec APIs via structured tool use to build, evaluate, and compare recommendation systems.
Install
pip install scikit-rec-agent[anthropic] # with Claude
pip install scikit-rec-agent[openai] # with GPT-4
pip install scikit-rec-agent # bring your own LLM
pip install scikit-rec-agent[anthropic,torch] # + deep-learning models
CLI
export ANTHROPIC_API_KEY=...
scikit-rec-agent chat
Auto-detects the provider from env vars. Pass --provider {anthropic,openai} if both are set.
Library
import anthropic
from scikit_rec_agent import Agent
from scikit_rec_agent.llm.anthropic import AnthropicAdapter
agent = Agent(llm=AnthropicAdapter(anthropic.Anthropic()))
for event in agent.chat_turn("I have click data at /data/interactions.csv — help me build a ranker"):
...
See examples/ for:
custom_tool.py— register a user-defined toolcustom_prompt.py— extend or replace the system promptcustom_llm.py— plug in your company's internal LLM via theBaseLLMprotocolcustom_frontend.py— drive the agent from Jupyter / Slack / webmovielens_session.md— captured transcript of the sweep flow (compare 7 methods on MovieLens-1M)movielens_hierarchical_session.md— captured transcript of the one-model design flow (walk through the picker step by step on the same data)
What it does
Fifteen tools cover the full scikit-rec workflow — from raw data to a saved, tuned model:
| Tool | What it does |
|---|---|
profile_data |
Loads a CSV/parquet and reports shape, dtypes, sparsity, target type, and temporal range. Heuristic role detection for USER_ID / ITEM_ID / OUTCOME / TIMESTAMP. |
validate_data |
Checks a file against scikit-rec's required schema. Suggests column-rename mappings when names are close. |
transform_data |
Reshapes a raw file into one of nine scikit-rec contracts (long, long-with-timestamp, long-multi-reward, wide multi-output, multiclass, prebuilt sequences, sessions, users features, items features). Auto-detects source shape; applies pivot, melt, aggregate, dedupe, and cast as needed. |
create_datasets |
Builds scikit-rec Dataset handles from file paths. Auto-generates schemas from dtypes; auto-dispatches to InteractionsDataset / InteractionMultiOutputDataset / InteractionMultiClassDataset. |
split_data |
Splits a bundle into train/valid/test using temporal, leave-last-n-per-user, random-split-per-user, leave-n-users-out, or random-split. Errors loudly on degenerate splits (e.g. per-user split on one-row-per-user data). |
list_compatible_options |
Drives the hierarchical model-design flow: walks the user through recommender_type → scorer_type → estimator_type → model_type → hyperparameters one step at a time. Each option carries a what_it_is / when_to_pick / tradeoff_vs_alternatives triple. The terminal step returns an assembled_config that plugs straight into train_model. |
train_model |
Trains a recommender from a RecommenderConfig dict via scikit-rec's factory. Failure envelopes carry a category from the diagnose registry plus a one-line hint. |
sweep_methods |
Trains and evaluates multiple methods on the same bundle and returns a ranked leaderboard. Modes: list (menu only), auto (data-aware filter + hyperparameter resize), all (every entry), broad (every capability-compatible triple), or explicit method dicts / short_names. Idempotent across re-runs. |
diagnose_training_failure |
Pattern-matches a failed train_model envelope against a 14-pattern registry and returns ranked candidate fixes with structured actions. Auto-retries the top safe fix; bounded by max_retries to prevent loops. |
evaluate_model |
Runs offline evaluation on a trained model with any of 7 evaluator types × 9 metrics at multiple k values. Auto-builds eval_kwargs from the bundle's validation interactions for the simple evaluator. |
compare_models |
Renders a markdown leaderboard across all (or a chosen subset of) trained models in the session, sorted by a primary metric. |
run_hpo |
Optuna-driven hyperparameter search over a user-specified search_space. Persists the best config and writes the tuned model into the session. |
save_model |
Persists a trained model to the local file-based registry with optional tags. |
list_models |
Lists saved models in the registry with their metadata and tags. |
load_model |
Restores a saved model into the current session for further use. |
The system prompt is built at import time from scikit-rec's live enum maps, so new recommender / scorer / estimator types get picked up automatically.
How to talk to it
The agent expects natural language. There's no DSL, no required prompt structure — just describe your data and goal. Two main paths cover most workflows; the agent picks based on what you ask for.
Path A — Compare-everything sweep
For "I want results — show me which method works best on my data."
"I have click data at /data/interactions.csv with users in users.csv
and items in items.csv. Compare a few methods and tell me which works
best."
What happens:
profile_data+validate_dataon each filetransform_dataif the shape doesn't match the target contractcreate_datasets+split_datasweep_methods(methods="list")— agent surfaces the menu (XGBoost, MF, NCF, Two-Tower, DCN, NFM, SASRec — whichever fit your data) with brief descriptions, asks you to pick or say "all"sweep_methods(methods=[...])— trains + evaluates the picked methods, returns a ranked leaderboard- Agent reports the winner; offers to save / run HPO
The auto-sweep table is data-aware by default (methods="auto"): MF only runs in the high-sparsity regime, embedding methods only when n_rows ≥ 5K, sequential only with timestamps. Hyperparameters are tier-sized to your data scale. Pass methods="all" to override the filter and run every entry as-is.
See examples/movielens_session.md — 7 methods on MovieLens-1M, SASRec wins with NDCG@10 ≈ 0.021.
Path B — Design one good model, with help
For "I want to understand the choice, not just see a leaderboard."
"Walk me through how to choose a recommender for this data. I want
to understand the design space."
What happens — the agent walks the hierarchical flow via list_compatible_options:
recommender_type— Ranking? Sequential? Uplift? Bandits? Each option carries awhat_it_is / when_to_pick / tradeoff_vs_alternativestriple. Options that don't fit your data (e.g. sequential when there's no TIMESTAMP) are filtered out automatically.scorer_type— given your previous pick, what scoring strategy applies. Universal / independent / multioutput / multiclass / sequential / hierarchical, again with explanations.estimator_type— tabular (XGBoost) / embedding (MF, NCF, Two-Tower, DCN, NFM) / sequential (SASRec, HRNN). Filtered by data size (embedding needs ≥5K rows, etc).model_type— pick the specific family.- Terminal step — agent shows the data-tier-sized default hyperparameters with
what_it_isandwhy_this_default. Three actions:train_with_defaults— accept the sized defaults, train one modeltrain_with_overrides— change specific hyperparameters before trainingrun_hpo— search the pre-suggested ranges via Optuna
Uplift gets one extra step. Picking recommender_type=uplift adds required_recommender_params to the terminal payload — control_item_id (which ITEM_ID is the control / no-recommendation case?) and mode (T-Learner / S-Learner / X-Learner, each with its own triple). Both are user-supplied; the agent won't silently default them. train_with_defaults is blocked for uplift; you go through train_with_overrides.
See examples/movielens_hierarchical_session.md for a real walk-through on MovieLens-1M.
Sweep vs design — which to pick
| Goal | Path |
|---|---|
| "What works best on my data?" | A — sweep |
| "Should I use sequential or ranking? Help me choose." | B — design |
| "Compare 3 specific methods I picked." | A — sweep with explicit methods=[...] |
| "I want uplift. Help me set it up." | B — design |
| "Bulk compare everything and run HPO on the winner." | A — sweep, then run_hpo on the winner |
| "Train one specific model I already have a config for." | Skip both — use train_model directly |
Recover from a training failure
"train_model errored — here's the envelope: {error_type: ValueError,
message: 'Input contains NaN', ...}. Help."
The agent calls diagnose_training_failure, pattern-matches the error against a 14-pattern registry, returns ranked candidate fixes with structured actions. Bounded retries (max 2 per model_name) prevent loops; if the category is unknown, it surfaces the raw error to you instead of guessing.
What the agent will ask back
The agent asks targeted clarifying questions when the data or goal is genuinely ambiguous:
- "Which column is your timestamp?" — when
profile_data's heuristic role detection is uncertain - "Ranking or sequential? Your data has timestamps so both are valid" — when a design choice has real tradeoffs
- "Your
gendercolumn isM/Fstrings. Drop it, label-encode (0/1), or one-hot?" — whentrain_modelwould otherwise fail on object-dtype features - "What's your control item ID for uplift?" — when the design path lands on uplift and there's no sensible default
It does not ask you to write any code. Tool calls happen behind the scenes; you only see them if you watch chat_turn's event stream.
Reading the output
Every tool returns a JSON envelope. The shape is:
{"status": "ok", "data": {...}} // success
{"status": "error", "error_type": "...", "message": "...", // failure
"hint": "actionable next step", "category": "diagnostics-bucket"}
category and hint are populated by the diagnose registry — when present they tell you exactly what failed and how to react. Sweep leaderboards sort by your primary metric; rows with status: "error" are kept in the leaderboard with their per-method failure category for later inspection.
Hallucination safeguards
The agent runs two deterministic detectors on every turn's output:
- URL echo check — flags
https://...links the model introduces that the user did not supply this session. Shipped adapters have no web retrieval, so model-introduced URLs are common fabrications. - Foreign-reference check — scans fenced Python blocks for imports and bare-alias usage outside
{skrec, scikit_rec, scikit_rec_agent, stdlib}. Library APIs we own have a runtime backstop via the scikit-rec factory; external libraries don't.
Warnings are emitted as AgentEvent(type="warning") and never enter conversation history. Opt out with Agent(..., enable_safeguards=False).
Scope and limitations
The detectors are deliberately narrow. They catch the common confident-plausible-looking fabrication case with near-zero false positives, not every possible hallucination. What they do not catch:
- Semantic errors inside trusted APIs (wrong
RecommenderConfigshape, poor metric choice). The scikit-rec factory catches bad configs attrain_model; the rest is on the user. - Invented keyword arguments for external libraries. We flag
pandasas unverified, not the specificmake_up_kwarg=True. - Fabricated dataset names, paper citations, or prose claims. We only inspect URLs and Python code blocks.
- Adversarial evasion (aliased
importlib, f-string import args, triple-backticks inside docstrings,ast.parse-rejecting blocks).
See scikit_rec_agent/safeguards.py for the full contract.
Architecture
See agentic_design.md for the authoritative spec.
Contributing
Contributions welcome — see CONTRIBUTING.md for dev setup, test commands, and where new work fits best.
License
Apache-2.0
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file scikit_rec_agent-0.2.1.tar.gz.
File metadata
- Download URL: scikit_rec_agent-0.2.1.tar.gz
- Upload date:
- Size: 168.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
63c212989f4421d3a8cb5ed8200214417253c2caa8ffbf6cfd2ee8b633787a9f
|
|
| MD5 |
c3bfcdb034b9091c2436b4972b91ca6a
|
|
| BLAKE2b-256 |
b565928635e999c763dac35181c97fcf59a5cc423cae428971b732ea6463fe71
|
Provenance
The following attestation bundles were made for scikit_rec_agent-0.2.1.tar.gz:
Publisher:
publish.yml on intuit/scikit-rec-agent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
scikit_rec_agent-0.2.1.tar.gz -
Subject digest:
63c212989f4421d3a8cb5ed8200214417253c2caa8ffbf6cfd2ee8b633787a9f - Sigstore transparency entry: 1472510918
- Sigstore integration time:
-
Permalink:
intuit/scikit-rec-agent@b1c68c3b5767b27d703b612818b21b5da8c9261f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/intuit
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b1c68c3b5767b27d703b612818b21b5da8c9261f -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file scikit_rec_agent-0.2.1-py3-none-any.whl.
File metadata
- Download URL: scikit_rec_agent-0.2.1-py3-none-any.whl
- Upload date:
- Size: 101.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
51fe1db54435c74ff96a00432fba5e66f06839116bb4c324455962a345e4e185
|
|
| MD5 |
685acc621bd9929eabd5338c0dd8e4b9
|
|
| BLAKE2b-256 |
e47284b491585eca3efab01bee9096dab39e493bb38d24b9bacc57cfc600617c
|
Provenance
The following attestation bundles were made for scikit_rec_agent-0.2.1-py3-none-any.whl:
Publisher:
publish.yml on intuit/scikit-rec-agent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
scikit_rec_agent-0.2.1-py3-none-any.whl -
Subject digest:
51fe1db54435c74ff96a00432fba5e66f06839116bb4c324455962a345e4e185 - Sigstore transparency entry: 1472511162
- Sigstore integration time:
-
Permalink:
intuit/scikit-rec-agent@b1c68c3b5767b27d703b612818b21b5da8c9261f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/intuit
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b1c68c3b5767b27d703b612818b21b5da8c9261f -
Trigger Event:
workflow_dispatch
-
Statement type: