# AccessibleModels.jl: Automatic UI and Model Fitting for Arbitrary Objects

**URL:** <https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363>\
**Category:** Package Announcements\
**Created:** [September 14, 2025, 3:49am UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363 "2025-09-14T03:49:52Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [September 14, 2025, 3:49am UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/1 "2025-09-14T03:49:52Z")

</div>

Hi all! 👋

I’m excited to share **[AccessibleModels.jl](https://github.com/JuliaAPlavin/AccessibleModels.jl)** – the easiest way to fit/optimize models with parameters being arbitrary Julia objects and create quick UIs for those objects.

I highlighted AccessibleModels.jl in my Accessors talk at this year JuliaCon – see the relevant part here:

[![](https://global.discourse-cdn.com/julialang/original/3X/1/2/12fa5e10cf4cb7d9ce095a664bb75bccf424abe6.jpeg "JuliaCon Global 2025 | Function Room | Day 2") ](https://www.youtube.com/watch?v=1NjovGpDbFk&t=2569)

## Motivation and Design 🎯

When fitting models, we often have parameters naturally represented as complex Julia objects (structs, nested data, etc), but optimization/sampling packages expect flat parameter vectors. This leads to lots of boilerplate code for parameter extraction and reconstruction.

The same applies to interactive UIs: it’s often natural to represent multiple relevant parameters as a single object, but UI libraries tend to work with individual independent controls or vectors.

AccessibleModels.jl uses Accessors.jl to automatically handle parameter management, letting you optimize/sample any Julia object directly. The exact same model and parameter definitions can be used for both model fitting and quick UIs!

Key features:

- **Universal** : Works with basically any Julia struct, flat or nested 🎯
- **Wide ecosystem support** : Works with Optimization.jl, Pigeons.jl (MCMC), and more 🌐
- **Zero boilerplate** : Just define your model - no parameter extraction/reconstruction code ✨
- **Bonus 🎁** : Can create instant interactive UIs for any AccessibleModels model using Makie!

## Usage 💡

Define your model object as an arbitrary struct (no dependency on AccessibleModels required at this stage):

```julia
julia> struct ExpFunction{A,B}
           scale::A
           shift::B
       end

julia> struct SumFunction{T}
           comps::T
       end

julia> (m::ExpFunction)(x) = m.scale * exp(-(x - m.shift)^2)

julia> (m::SumFunction)(x) = sum(c -> c(x), m.comps)

```

Create an interactive Makie UI for adjusting model parameters:

```julia
julia> using AccessibleModels, IntervalSets
julia> using GLMakie

julia> mod0 = SumFunction((
           ExpFunction(1., 1.),
           ExpFunction(2., 2.),
       ))

julia> amodel = AccessibleModel(mod0, (
           (@o _.comps[∗].shift) => 0..10,
           (@o _.comps[∗].scale) => 0..4,
       ))

julia> obj, = SliderGrid(fig[1,1], amodel)

julia> lines(fig[1,2], 0..10, @lift x -> $obj(x))

```

Use the same AccessibleModel for optimization by adding a loss function:

```julia
# Generate example data using a "true" model
julia> data = [(x=x, y=true_model(x) + 0.2 * randn()) for x in 0:0.5:10]
21-element Vector{@NamedTuple{x::Float64, y::Float64}}:
 (x = 0.0, y = 0.158)
 (x = 0.5, y = -0.172)
 (x = 1.0, y = -0.138)
 <...>

julia> loglike(m::SumFunction, data) = sum(r -> logpdf(Normal(m(r.x), 0.3), r.y), data)

# The only change: add the log-likelihood function
julia> amodel = AccessibleModel(Base.Fix2(loglike, data), mod0, (
           (@o _.comps[∗].shift) => 0..10,
           (@o _.comps[∗].scale) => 0..4,
       ))

julia> using Optimization, OptimizationMetaheuristics

julia> op = OptimizationProblem(amodel)

julia> sol = solve(op, ECA(), amodel)

# Get the fitted model:
julia> getobj(sol)
SumFunction((
    ExpFunction(1.983, 3.098),
    ExpFunction(1.574, 7.013)))

```

The same model definition works for MCMC sampling. This is especially convenient with MonteCarloMeasurements to hold the results: 📊

```julia
julia> using Pigeons

julia> pt = pigeons(target=amodel, record=[traces; round_trip; record_default()])
julia> using MonteCarloMeasurements

julia> mcmc_fitted = samples(Particles, pt)
SumFunction((ExpFunction(1.5 ± 0.5, 5.35 ± 2.0), ExpFunction(1.6 ± 0.6, 4.66 ± 2.0)))

julia> lines(0..10, x -> mcmc_fitted(x))
julia> band!(0..10, x -> mcmc_fitted(x))

```

 ![figure3_mcmc_uncertainty](https://global.discourse-cdn.com/julialang/original/3X/8/1/810c9316a6e66ca1f484f9506dd40a3f06e6db13.png)

More examples and explanations in the docs.

## More 📚

This package is a thin layer of plumbing that builds heavily on the Accessors.jl and AccessorsExtra.jl functionality. See the docs and code for more details.

Related works:

- [AccessibleOptimization.jl](https://discourse.julialang.org/t/ann-accessibleoptimization-optimization-with-arbitrary-objects-instead-of-vectors/99695): same concept, but Optimization.jl-only; effectively deprecated, all functionality is available in AccessibleModels.jl with a more unified design.
- [PlutoTables.jl](https://discourse.julialang.org/t/ann-plutotables-edit-any-julia-object-in-a-tabular-interface/99696): same concept, but for Pluto notebook UIs. Currently, AccessibleModels.jl supports Makie UIs, Pluto backend can be added in the future.

Would love to hear your thoughts and feedback! 💭  
AccessibleModels.jl is now registrered in General. 📦

---

<div class="post-metadata">

**Author:** ![klafyvel](https://avatars.discourse-cdn.com/v4/letter/k/a587f6/32.png) [@klafyvel](https://discourse.julialang.org/u/klafyvel)\
**Post date:** [September 14, 2025, 6:23am UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/2 "2025-09-14T06:23:16Z")

</div>

This is looking great! I look forward to try it later this week.

---

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [September 14, 2025, 9:11am UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/3 "2025-09-14T09:11:17Z")

</div>

Accessors really seems to have no limits! 🙂

Question, what are the semantics of `@lift`, exactly?

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [September 14, 2025, 11:59am UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/4 "2025-09-14T11:59:43Z")

</div>

> [@oschulz](#):
>
> Accessors really seems to have no limits! 🙂

True! Somebody asked me after my talk, like “where do you typically use Accessors?” – and my answer was “basically everywhere” 😀  
_(btw added the link to my JuliaCon’25 Accessors.jl talk where I highlight AccessibleModels.jl as well)_

> [@oschulz](#):
>
> Question, what are the semantics of `@lift`, exactly?

Oh, that’s from Makie.jl / Observables.jl, completely independent from Accessors!  
Basically, we return an `Observable` from `SliderGrid(...)`, and this Observable can be used with all the Makie functionality to make dynamic plots.

---

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [September 14, 2025, 1:25pm UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/5 "2025-09-14T13:25:39Z")

</div>

Oh, right, `@lift` is part of Makie. Would actually be nice to have it upstreamed to Observables. Or even have a monadic-lift macro like that in some central place?

---

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [September 14, 2025, 1:29pm UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/6 "2025-09-14T13:29:01Z")

</div>

I wonder why `Observable`s don’t support broadcasting? Then `@lift` would just be `@.` (without `$`-escapes), basically. 🙂

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [September 14, 2025, 1:57pm UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/7 "2025-09-14T13:57:46Z")

</div>

Observables supports `map`, but I kinda like that Makie uses and recommends `lift`/`@lift` instead… These operations are just so different in practice! When I see `lift` in the code, it’s clear that dynamic updates are happening there – not just `map`/broadcast over a collection.

---

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [September 14, 2025, 3:02pm UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/8 "2025-09-14T15:02:35Z")

</div>

Still - if any Makie/Observables dev is reading this, `@lift` could be upstreamed to Observables, right?

---

<div class="post-metadata">

**Author:** ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)\
**Post date:** [September 14, 2025, 6:44pm UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/9 "2025-09-14T18:44:13Z")

</div>

I guess, although I’m personally not a big fan of the macro … One reason is, that it’s always a good idea to think twice before creating an observable, so I don’t mind more verbosity… On the other hand, I don’t find it easy to see what’s going on with most @lift expressions 😉

---

<div class="post-metadata">

**Author:** ![klafyvel](https://avatars.discourse-cdn.com/v4/letter/k/a587f6/32.png) [@klafyvel](https://discourse.julialang.org/u/klafyvel)\
**Post date:** [September 19, 2025, 6:58am UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/10 "2025-09-19T06:58:53Z")

</div>

I’ve been playing the whole week with AccessibleModels.jl, and I’m completely convinced: thanks a lot for this package! The ability to pop an interactive window at almost no cost is really nice for adjusting priors.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [September 19, 2025, 11:15am UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/11 "2025-09-19T11:15:33Z")

</div>

Happy that it worked out for you!  
I have a bunch of further improvements in mind, but not sure about the timeline – they are nice, but not really pressing. For UI specifically, sometimes I miss other widgets, like a checkbox for booleans (or even a text input for strings!). Let me know if something else would be nice to have 🙂

---

<div class="post-metadata">

**Author:** ![klafyvel](https://avatars.discourse-cdn.com/v4/letter/k/a587f6/32.png) [@klafyvel](https://discourse.julialang.org/u/klafyvel)\
**Post date:** [September 19, 2025, 12:19pm UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/12 "2025-09-19T12:19:06Z")

</div>

I’m kinda ok with the way it is now, of course I add stuff to the UI when I need it (like a button to start the fit, some ways to select the fit range…) which are note provided automatically, but Makie is simple enough to use that it’s not a big deal at all.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [February 6, 2026, 12:15am UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/13 "2026-02-06T00:15:11Z")

</div>

A few months ago I added a small feature to AccessibleModels.jl that ended up being _really_ useful for interactive `SliderGrid`s — especially once you have lots of parameters. It makes these UIs much more usable in practice.

### Introducing `state` for persistence

`SliderGrid` now accepts an optional `state` argument, which stores the current values of all controls:

```julia-auto
state = Dict()
SliderGrid(fig[1,1], amodel; state)

```

The key idea is persistence + synchronization:

- when the UI is created, it **initializes sliders from `state`** (if values are present)
- when you move sliders, it **updates `state`** accordingly

(`state` can be any `AbstractDict`/`AbstractDictionary` store)

### Why it’s great in notebooks

This is especially nice in notebooks:

- define `state` in one cell
- create the figure + UI controls in another
- iterate on visuals/layout/setup and re-run the UI cell

Your slider values **survive re-execution** , instead of being reset each time.

### Also useful in scripts: disk-backed `state`

And it works well in scripts too: you can use a **disk-backed dictionary** as `state`. I use `Dictionary` from **SQLCollections.jl** (SQLite-backed), which makes a convenient persistent store and works directly as `AccessibleModels.jl` `state`.

So when you rerun the script (or tweak + rerun), **slider positions don’t reset**.

* * *

Now I don’t worry about UIs with many parameters to control (when they are needed) 🙂

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [February 6, 2026, 8:17am UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/14 "2026-02-06T08:17:53Z")

</div>

That does sound quite useful. Will you release a new version with `SliderGrid` soon?

---

<div class="post-metadata">

**Author:** ![klafyvel](https://avatars.discourse-cdn.com/v4/letter/k/a587f6/32.png) [@klafyvel](https://discourse.julialang.org/u/klafyvel)\
**Post date:** [February 6, 2026, 9:50am UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/15 "2026-02-06T09:50:57Z")

</div>

I think the answer to that is “4 days ago” 🙂 [optimize SliderGrid for performance by blocking layout updates during… · JuliaAPlavin/AccessibleModels.jl@0000000 · GitHub](https://github.com/JuliaAPlavin/AccessibleModels.jl/commit/00000000074649c83ba32f6870e2ed1be94db12e)

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [February 6, 2026, 12:05pm UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/16 "2026-02-06T12:05:52Z")

</div>

> [@Christopher\_Fisher](#):
>
> Will you release a new version with `SliderGrid` soon?

Not sure if I understand the question… `SliderGrid` has been available in AccessibleModels.jl from the beginning. And the `state` argument was added about a month ago, definitely available in the released version!

Do you have any issues accessing it?

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [February 7, 2026, 7:25am UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/17 "2026-02-07T07:25:37Z")

</div>

Sorry for the confusion. I saw that the latest release was in October and incorrectly assumed `SliderGrid` was added after. I’ll give it a try!

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [February 7, 2026, 1:51pm UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/18 "2026-02-07T13:51:04Z")

</div>

> [@Christopher\_Fisher](#):
>
> I saw that the latest release was in October

Hmm, where do you see this? The date is correct on JuliaHub, Feb 2026:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/e/4/e442cbbac88cca800353c0f2032813c7253b1b90.png)

> **[JuliaHub](https://juliahub.com/ui/Packages/General/AccessibleModels)**

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [February 7, 2026, 6:11pm UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/19 "2026-02-07T18:11:36Z")

</div>

Ok. I see the problem. The posted releases on github are out of sync 🤔.

 ![Screenshot from 2026-02-07 13-05-19](https://global.discourse-cdn.com/julialang/original/3X/2/3/23a728072307bb8668cf5adac586e4797bfed2ad.png)

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [February 7, 2026, 6:24pm UTC](https://discourse.julialang.org/t/accessiblemodels-jl-automatic-ui-and-model-fitting-for-arbitrary-objects/132363/20 "2026-02-07T18:24:30Z")

</div>

Yes, the information relevant for Julia package manager and the General registry is shown on the JuliaHub website. Github just shows whatever tags happen to exist in the repo, and calls them “releases” 🙂
