GEMMA DEVELOPER AGENTSAVED EVIDENCE
← Dataset Exploration
ARCHIVED TRAINING / holoviz/param

holoviz__param-1117

This is a preserved training example. Membership in the current training wave has not been verified.
holoviz/param · Task 77 of 169

Problem statement

Shared rx inputs are not reused
Just filing an issue that a user reported elsewhere

MRE: upstream re-evaluation when multiple .rx.pipe() consumers share one pn.rx()

Problem
=======
We have an **expensive computation** driven by reactive inputs.  The result
 is a dict/object with many keys.  We want N downstream consumers (one 
 per tree node) to each display a different slice of that result.

The natural pattern is:

    shared_rx = pn.rx(expensive_compute)(input_a, input_b, input_c)
    out_1 = shared_rx.rx.pipe(lambda d: d["key_1"])
    out_2 = shared_rx.rx.pipe(lambda d: d["key_2"])
    ...
    out_N = shared_rx.rx.pipe(lambda d: d["key_N"])

The `.rx` pattern is preferred because it feels easier to describe the relationships this 
way vs with `.depends` or watchers.

Expected behaviour
------------------
Changing **one input** triggers ``expensive_compute`` **once**; the N pipes
each receive the cached result and extract their slice cheaply.

Observed behaviour
------------------
Changing **one input** triggers ``expensive_compute`` **N times** — once per
``.rx.pipe()`` subscriber.  Each invocation receives the *same* input values
and produces the *same* result.

Impact
------
In our real app, ``expensive_compute`` takes ~150 ms (API calls + matrix math).
With 12 downstream pipes (12 tree nodes × 1 pipe each), toggling compute on
causes **12 × 150 ms ≈ 1.8 s** of redundant work.  With 3 pipes per node
(our original design), it's **36 × 150 ms ≈ 5.4 s**.

Reproducer
==========
Run:  ``panel serve mre_rx_pipe.py --show``
Then change any one slider and observe the terminal output — ``expensive_compute``
is called **4×** per input change (once per pipe), not 1×.  There are 3 inputs
but 4 output pipes, proving the number of calls is driven by the **output count**.

Questions
==============================
1. Is this the intended behaviour of ``.rx.pipe()``?  i.e. is there no
   result-caching / shared-evaluation in the rx DAG?

2. What is the **recommended pattern** when one expensive reactive expression
   needs to fan out to N cheap consumers?


```
import time
import param
import panel as pn

pn.extension()

call_count = 0


class Model(param.Parameterized):
    a = param.Number(default=1.0)
    b = param.Number(default=2.0)
    c = param.Number(default=3.0)


model = Model()


def expensive_compute(_a, _b, _c):
    """Simulates an expensive computation that returns a multi-key result."""
    global call_count
    call_count += 1
    result = {
        "x": _a + _b + _c,
        "y": _a * _b * _c,
        "z": _a - _b - _c,
        "w": (_a + _b) / max(_c, 0.01),
    }
    print(f"[expensive_compute] call #{call_count}  "
          f"a={_a} b={_b} c={_c} → {result}")
    return result


# ── The pattern under test ──────────────────────────────────────────────
# One shared rx expression…
shared_rx = pn.rx(expensive_compute)(model.param.a, model.param.b, model.param.c)

# …with 4 downstream pipes (one per output key) — more pipes than inputs.
x_rx = shared_rx.rx.pipe(lambda d: f"x = {d['x']:.2f}")
y_rx = shared_rx.rx.pipe(lambda d: f"y = {d['y']:.2f}")
z_rx = shared_rx.rx.pipe(lambda d: f"z = {d['z']:.2f}")
w_rx = shared_rx.rx.pipe(lambda d: f"w = {d['w']:.2f}")

# ── UI ──────────────────────────────────────────────────────────────────
a_input = pn.widgets.FloatInput(name="a", value=model.a, step=0.5)
b_input = pn.widgets.FloatInput(name="b", value=model.b, step=0.5)
c_input = pn.widgets.FloatInput(name="c", value=model.c, step=0.5)

a_input.link(model, value="a")
b_input.link(model, value="b")
c_input.link(model, value="c")

layout = pn.Column(
    "## MRE: 3 inputs, 4 output pipes — `expensive_compute` runs 4× per change",
    pn.pane.Markdown(
        "Change **one** input and check the terminal.  \n"
        "`expensive_compute` is called **4×** per change (once per pipe), "
        "not 1×.  3 inputs but **4 outputs** proves the call count is driven "
        "by the number of `.rx.pipe()` consumers."
    ),
    pn.Row(a_input, b_input, c_input),
    pn.pane.Str(x_rx),
    pn.pane.Str(y_rx),
    pn.pane.Str(z_rx),
    pn.pane.Str(w_rx),
)
layout.servable()
```

Training membership

opd_e4b_pure_v6b

Task issues extracted from preserved verified_rft_messages training examples. This is not a verified current RL wave manifest.

Task and snapshot provenance

Snapshot captured 2026-11-12T17:06:59.476467+00:00 · Autoresearch-Arena/gemma-4-developer-agent

{
  "datasets": [
    "opd_e4b_pure_v6b"
  ],
  "examples": 3,
  "instance_id": "holoviz__param-1117",
  "problem_statement": "Shared rx inputs are not reused\nJust filing an issue that a user reported elsewhere\n\nMRE: upstream re-evaluation when multiple .rx.pipe() consumers share one pn.rx()\n\nProblem\n=======\nWe have an **expensive computation** driven by reactive inputs.  The result\n is a dict/object with many keys.  We want N downstream consumers (one \n per tree node) to each display a different slice of that result.\n\nThe natural pattern is:\n\n    shared_rx = pn.rx(expensive_compute)(input_a, input_b, input_c)\n    out_1 = shared_rx.rx.pipe(lambda d: d[\"key_1\"])\n    out_2 = shared_rx.rx.pipe(lambda d: d[\"key_2\"])\n    ...\n    out_N = shared_rx.rx.pipe(lambda d: d[\"key_N\"])\n\nThe `.rx` pattern is preferred because it feels easier to describe the relationships this \nway vs with `.depends` or watchers.\n\nExpected behaviour\n------------------\nChanging **one input** triggers ``expensive_compute`` **once**; the N pipes\neach receive the cached result and extract their slice cheaply.\n\nObserved behaviour\n------------------\nChanging **one input** triggers ``expensive_compute`` **N times** — once per\n``.rx.pipe()`` subscriber.  Each invocation receives the *same* input values\nand produces the *same* result.\n\nImpact\n------\nIn our real app, ``expensive_compute`` takes ~150 ms (API calls + matrix math).\nWith 12 downstream pipes (12 tree nodes × 1 pipe each), toggling compute on\ncauses **12 × 150 ms ≈ 1.8 s** of redundant work.  With 3 pipes per node\n(our original design), it's **36 × 150 ms ≈ 5.4 s**.\n\nReproducer\n==========\nRun:  ``panel serve mre_rx_pipe.py --show``\nThen change any one slider and observe the terminal output — ``expensive_compute``\nis called **4×** per input change (once per pipe), not 1×.  There are 3 inputs\nbut 4 output pipes, proving the number of calls is driven by the **output count**.\n\nQuestions\n==============================\n1. Is this the intended behaviour of ``.rx.pipe()``?  i.e. is there no\n   result-caching / shared-evaluation in the rx DAG?\n\n2. What is the **recommended pattern** when one expensive reactive expression\n   needs to fan out to N cheap consumers?\n\n\n```\nimport time\nimport param\nimport panel as pn\n\npn.extension()\n\ncall_count = 0\n\n\nclass Model(param.Parameterized):\n    a = param.Number(default=1.0)\n    b = param.Number(default=2.0)\n    c = param.Number(default=3.0)\n\n\nmodel = Model()\n\n\ndef expensive_compute(_a, _b, _c):\n    \"\"\"Simulates an expensive computation that returns a multi-key result.\"\"\"\n    global call_count\n    call_count += 1\n    result = {\n        \"x\": _a + _b + _c,\n        \"y\": _a * _b * _c,\n        \"z\": _a - _b - _c,\n        \"w\": (_a + _b) / max(_c, 0.01),\n    }\n    print(f\"[expensive_compute] call #{call_count}  \"\n          f\"a={_a} b={_b} c={_c} → {result}\")\n    return result\n\n\n# ── The pattern under test ──────────────────────────────────────────────\n# One shared rx expression…\nshared_rx = pn.rx(expensive_compute)(model.param.a, model.param.b, model.param.c)\n\n# …with 4 downstream pipes (one per output key) — more pipes than inputs.\nx_rx = shared_rx.rx.pipe(lambda d: f\"x = {d['x']:.2f}\")\ny_rx = shared_rx.rx.pipe(lambda d: f\"y = {d['y']:.2f}\")\nz_rx = shared_rx.rx.pipe(lambda d: f\"z = {d['z']:.2f}\")\nw_rx = shared_rx.rx.pipe(lambda d: f\"w = {d['w']:.2f}\")\n\n# ── UI ──────────────────────────────────────────────────────────────────\na_input = pn.widgets.FloatInput(name=\"a\", value=model.a, step=0.5)\nb_input = pn.widgets.FloatInput(name=\"b\", value=model.b, step=0.5)\nc_input = pn.widgets.FloatInput(name=\"c\", value=model.c, step=0.5)\n\na_input.link(model, value=\"a\")\nb_input.link(model, value=\"b\")\nc_input.link(model, value=\"c\")\n\nlayout = pn.Column(\n    \"## MRE: 3 inputs, 4 output pipes — `expensive_compute` runs 4× per change\",\n    pn.pane.Markdown(\n        \"Change **one** input and check the terminal.  \\n\"\n        \"`expensive_compute` is called **4×** per change (once per pipe), \"\n        \"not 1×.  3 inputs but **4 outputs** proves the call count is driven \"\n        \"by the number of `.rx.pipe()` consumers.\"\n    ),\n    pn.Row(a_input, b_input, c_input),\n    pn.pane.Str(x_rx),\n    pn.pane.Str(y_rx),\n    pn.pane.Str(z_rx),\n    pn.pane.Str(w_rx),\n)\nlayout.servable()\n```",
  "repo": "holoviz/param",
  "source": "v2/experiments/train_data/opd_e4b_pure_v6b/verified_rft_messages.jsonl",
  "source_sha256": "0f62460a9706eea5e1605255896f191ab00cb5706c5f1f2e1c293e9a718218dc"
}
{
  "captured_at": "2026-11-12T17:06:59.476467+00:00",
  "membership": "archived training",
  "membership_evidence": "Task issues extracted from preserved verified_rft_messages training examples. This is not a verified current RL wave manifest.",
  "name": "Preserved post-training task archive",
  "source": "Autoresearch-Arena/gemma-4-developer-agent",
  "source_revision": "016496de222aaafca0d4ee4c18efc63ba616f76e",
  "sources": [
    {
      "path": "v2/experiments/train_data/opd_e4b_cispo_v5/verified_rft_messages.jsonl",
      "sha256": "a43610ad0dfb6ace95375cfae09000f41afc0338cc925af870a4ade7a9b20c4c"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_hybrid_v3/verified_rft_messages.jsonl",
      "sha256": "bd326303eb127e8e5e08f03daf97bb88d79d19709d59f3f93f348bc56686a8df"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_onpolicy_v3/verified_rft_messages.jsonl",
      "sha256": "960c680e797e823a0d3a22f4b1d5ef60a72971373d703b877340b0c9126aaf68"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_pure_v6a/verified_rft_messages.jsonl",
      "sha256": "f045b7ca5b3883a1e2eaee81e1c02a4a1b53dd7b7b36e98bacb2ba5823a15148"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_pure_v6b/verified_rft_messages.jsonl",
      "sha256": "0f62460a9706eea5e1605255896f191ab00cb5706c5f1f2e1c293e9a718218dc"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_pure_v7/verified_rft_messages.jsonl",
      "sha256": "e37f7bd675322f3f81500b73559d60d5f602ca0537bf19f5cb06332c728c7b72"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_pure_v7b/verified_rft_messages.jsonl",
      "sha256": "b864bdc8695183433eef6e31cb8d33fad44ba3aded2170c1ade4ad5b2944ce23"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_self_audit_v4/verified_rft_messages.jsonl",
      "sha256": "0026023745afb8f3dc1c176dc7f7171157b4ad5a66656b524af218e8e19ceee6"
    },
    {
      "path": "v2/experiments/train_data/rft_e4b_aligned_v2/verified_rft_messages.jsonl",
      "sha256": "92a4515fee9d152b0d4c510ee3ce4caaaffe2003ba7584469f8027f174aab18c"
    },
    {
      "path": "v2/experiments/train_data/rft_v1/verified_rft_messages.jsonl",
      "sha256": "a42453ccd7ac7680b0a03865e8e7080bc8bf74c8d9d193b440c441ed46f8512b"
    },
    {
      "path": "v2/experiments/train_data/rft_v2/verified_rft_messages.jsonl",
      "sha256": "18f4b3bd7e651f83c6acab479c9475e3fa50dc652a384f309e97146983ac85ba"
    }
  ]
}