Artifacts
Artifacts let you attach large files to a trial — model snapshots, generated images, chemical structures, prediction dumps — that are too big for the study database. The study storage keeps the small structured data (params, values, attributes); an artifact store keeps the blobs, linked back to the trial by id. This recipe walks the two standard setups.
This is the how-to. The Artifacts guide documents the full
IArtifactStoreprotocol, every backend, and theArtifactFunctionssurface.
Scenario 1: SQLite + local file system
For a run that stays on one machine, pair the SQLite RDBStorage with a
FileSystemArtifactStore pointed at any directory. Inside the objective, write a file, upload it, and
remember its id on the trial so you can find it later:
using OptunaSharp;
using OptunaSharp.Artifacts;
using OptunaSharp.Storages;
using var storage = new RDBStorage("sqlite:///example.db");
var artifactStore = new FileSystemArtifactStore("./artifacts"); // any directory
var study = Optuna.CreateStudy(storage: storage, studyName: "test_study", loadIfExists: true);
double Objective(Trial trial)
{
double x = trial.SuggestFloat("x", -10, 10);
// Produce a file for this trial (a model snapshot, an image, a structure dump, …).
string filePath = GenerateExample(x);
string artifactId = ArtifactFunctions.UploadArtifact(artifactStore, filePath, trial);
trial.SetUserAttr("artifact_id", artifactId); // store the id in the RDB for later reference
return (x - 2) * (x - 2);
}
study.Optimize(Objective, nTrials: 100);
// Download the artifact attached to the best trial.
var bestArtifactId = (string)study.BestTrial.UserAttrs["artifact_id"]!;
ArtifactFunctions.DownloadArtifact(artifactStore, "./best_artifact.bin", bestArtifactId);
Alternatively, list a trial's artifacts without tracking ids yourself — GetAllArtifactMeta returns
the ArtifactMeta (id, filename, MIME type) recorded on each upload. A FrozenTrial needs the
storage passed in:
foreach (ArtifactMeta meta in ArtifactFunctions.GetAllArtifactMeta(study.BestTrial, storage))
ArtifactFunctions.DownloadArtifact(artifactStore, $"./restored/{meta.Filename}", meta.ArtifactId);
Scenario 2: remote database + cloud object store
When optimization is distributed across nodes, a local directory won't do. Keep the study in a remote
database (OptunaSharp.Storage.EFCore for PostgreSQL/MySQL)
and the artifacts in cloud object storage. Install OptunaSharp.Artifacts.S3 and swap the artifact
store for Boto3ArtifactStore — everything else in the objective is identical:
using OptunaSharp.Artifacts; // OptunaSharp.Artifacts.S3
// Ambient AWS credentials, or pass a configured IAmazonS3 client.
var artifactStore = new Boto3ArtifactStore("example-bucket");
Optuna's storage and artifact modules resolve race conditions when many workers upload in parallel, so reads and writes stay transparent even though the params live in the database and the files live in the object store. GCS, Azure Blob, and Cloudflare R2 stores work the same way — see the cloud artifacts guide.
A note on large scientific data
Optuna's original tutorial optimizes chemical adsorption structures, saving each candidate structure as an artifact. The pattern is exactly Scenario 1: whenever a trial produces data too large or too binary for the RDB — a molecule, an image, a model checkpoint — write it to a file and upload it. For small structures it's fine to serialize into a user attribute instead; the artifact module is what you reach for once the data outgrows the database.
Relationship to Optuna
| Optuna (Python) | OptunaSharp |
|---|---|
from optuna.artifacts import FileSystemArtifactStore |
new FileSystemArtifactStore("./artifacts") |
upload_artifact(artifact_store=…, file_path=…, study_or_trial=trial) |
ArtifactFunctions.UploadArtifact(store, filePath, trial) |
download_artifact(artifact_store=…, file_path=…, artifact_id=…) |
ArtifactFunctions.DownloadArtifact(store, filePath, artifactId) |
Boto3ArtifactStore(client=…, bucket_name="example_bucket") |
new Boto3ArtifactStore("example-bucket") |
trial.set_user_attr("artifact_id", artifact_id) |
trial.SetUserAttr("artifact_id", artifactId) |
See also
Artifacts guide · Storage · User attributes · the cloud artifacts integration.