Skip to content

feat(engine): declare seed tables and close out the extension work - #134

Open
3mei wants to merge 9 commits into
yev/refactor/capabilities-in-probe-packagesfrom
yev/feat/close-out-probe-work
Open

3mei wants to merge 9 commits into
yev/refactor/capabilities-in-probe-packagesfrom
yev/feat/close-out-probe-work

Conversation

@3mei

@3mei 3mei commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

What changed and why

A probe declares the seed table its rows sample, so the run setup names no probe; a tool_calling row's theme is its toolset; new probes get a test template that runs through run_episode with nothing patched; and the run manifest records the extensions installed and where each probe read its assets.

Builds on #133.

  • tool_calling's themes in its assets (first commit). assets/tool_calling/en_US/themes.json holds them, read by the probe's themes() with load_seeds, as the general probes read their topics. build_simulator_config_builder and materialize_episode_inputs take no tool_calling_themes, and the run manifest's scope records none; a manifest that holds the key still loads. The catalog README says the themes reach a row only when its toolset has no category: the probe takes a row's theme from its toolset's category and name, and every shipped toolset has one.
  • Seed tables (second commit). BaseProbe.seed_dataset names a table in the probe's asset folder, <name>.parquet or <name>.jsonl, that a run attaches as its seed dataset, so each row gets the columns of one of its rows. tool_calling declares its toolset catalog, toolsets_seed, and reads its tools from the row's tools column unless the run sets tools_column. resolve_seed_dataset_for_mix finds the table of the probe in the mix that declares one and refuses a mix with two; --toolset-seed-path and toolset_seed_path= keep their names and override that table. usersim smoke and assert_probe_conforms check the table is there, the extension fixture declares one so make check-extensions resolves it from an installed package, and the tool-calling template declares one. The CLI pipeline names tool_calling only in the default probe mix.
  • The test template (third commit). Every episode runs through usersim.testing.run_episode with scripted models, nothing patched: conformance, a run end to end, the row's area in the user model's instructions, the columns the probe writes, a declining assistant scripted by a ScriptedModel subclass, the placeholder warning, and hosted parity. AUTHORING_A_PROBE.md and the template README describe the same tests, and the README's checklist says a probe's scorer and capabilities live in its own package.
  • Docs (fourth commit). The README links docs/extensions.md and docs/extension_api.md, and docs/extensions.md says how a package builds against a change in User Sim before a release has it.
  • The run manifest (fifth commit). code.extensions records each installed package that advertises a User Sim entry point, with its version, and asset_versions.probe_assets the folder each probe in the mix read its assets from.
  • Small fixes (sixth to eighth commits). The health probes' asset_problems loads each client's clinical-profile bank, so usersim smoke checks all 14 probes' assets; the extension template and guide set asyncio_default_fixture_loop_scope, so the template's tests run without a deprecation warning; and tests/_asset_audit.py reads SHIPPED_LOCALES.
  • A tool_calling row's theme is its toolset (ninth commit). The user prompt takes a row's theme from its toolset's category and name. Every shipped toolset has a category, so a theme drawn from themes.json reaches no conversation, while the row stores it in its theme column, where the preview and exports show it beside an unrelated toolset. The probe lists no themes, so its rows hold the run's __not_used__ placeholder, as the rows of every probe that draws its area from its own data do, and themes.json is removed. A catalog without categories gives each row its toolset's name; the preview shows the toolset and its category. No prompt, judge or scorer reads the theme column of these rows, so shipped conversations, scores and trajectory ids stay the same.

Changes for callers

  • build_simulator_config_builder and materialize_episode_inputs in usersim.cli._pipeline, and build_run_manifest and write_simulator_manifest in usersim.engine.core.manifest, take no tool_calling_themes, and a run manifest's scope has no tool_calling_themes key.
  • resolve_toolset_seed_path, resolve_toolset_seed_for_mix and TOOLSET_SEED_SUFFIXES in usersim.cli._pipeline become resolve_seed_dataset_path, resolve_seed_dataset_for_mix and SEED_DATASET_SUFFIXES (in usersim.engine.core.probes). DEFAULT_TOOL_CALLING_THEMES has no counterpart, since a tool_calling row's theme is its toolset.
  • A tool_calling row's theme column holds __not_used__; its toolset_category and toolset_name columns say what the conversation is about.

How it was verified

At each commit, on that commit's tree:

$ make check-all && make test && make smoke
All checks passed!
381 files already formatted
4707 passed in 103.70s (0:01:43)
All checks passed.

That is the first commit's tree. The later ones pass with 4711, 4711, 4711, 4715, 4724, 4724, 4724 and 4731, as each adds its tests. The pre-commit hooks pass on every file the commits touch, at each commit.

At the head:

$ make check-license-headers
🎉 All files have correct license headers!
$ make check-doc-links
✓ every relative link, and every link into this repository's main branch, resolves
$ make check-notebooks-clean
OK 4 notebook(s) carry no outputs
$ make check-dist
✓ installed package runs from a clean environment
$ make check-extensions
      ok  seed_dataset resolves a contributed seed table
all extension seams work against an installed distribution
  • The probe test template, filled in for general_open_ended in a scratch folder (the placeholder-warning test left out, since that probe has no bank), passed its six tests.

  • make health-check ran against a custom provider config for tool_calling in en_US and for the default probe, sov_ai_dynamic in ja_JP. Both ended with ✓ simulate, eval and report all completed, and every model's requests show failed=0.

  • usersim simulate with the default mix (tool_calling and the two general probes), then usersim eval --scorers auto, against the same config: each tool_calling row drew a toolset from the attached catalog, stores __not_used__ as its theme, and opens with a request in its toolset's area; the manifest records each probe's asset folder and the seed table and no tool_calling_themes; the judge scored every row and every scorer reported ok.

    tool_calling | status True | theme __not_used__ | toolset <NA> / Fitness Tracker
        first user turn: 'Hey, can you check my workout history and tell me what I've actually been consistent with lately? ...'
    tool_calling | status True | theme __not_used__ | toolset news search / News
        first user turn: "Could you look up what's going on around Perth Amboy and Middlesex County this week? ..."
    judge: scored on 4 of 4 rows
    language_compliance, refusal_basics, response_shape, tool_use: ok on 4 of 4 rows
    

3mei added 2 commits November 4, 2026 11:50
tool_calling's themes live in assets/tool_calling/en_US/themes.json,
which every locale reads unless it has a themes.json of its own, and the
probe's themes() reads them with load_seeds, as the general probes read
their topics. The run setup draws them as it draws every other probe's,
so build_simulator_config_builder and materialize_episode_inputs take no
tool_calling_themes, and the run manifest's scope records none; a
manifest that holds the key still loads. The README says the themes reach
a row only when its toolset has no category, since the probe takes a
row's theme from its toolset's category and name. asset_problems checks
the themes file, and notebook 01 follows.

Signed-off-by: Yev Meyer <ymeyer@nvidia.com>
BaseProbe.seed_dataset names a table in the probe's asset folder,
<name>.parquet or <name>.jsonl, that a run attaches as its seed dataset,
so each row gets the columns of one of the table's rows. tool_calling
declares its toolset catalog, toolsets_seed, and reads its tools from the
row's tools column unless the run sets tools_column, so the run setup
names no probe: resolve_seed_dataset_for_mix finds the table of the probe
in the mix that declares one, refuses a mix with two, and keeps
--toolset-seed-path and toolset_seed_path= as the override for it. usersim
smoke and assert_probe_conforms check that the declared table is there,
the extension fixture declares one so make check-extensions resolves it
from an installed package, and the tool-calling template declares one.
architecture/probes.md, the catalog README, the engine README's config
table and the --toolset-seed-path help describe it.

Signed-off-by: Yev Meyer <ymeyer@nvidia.com>
@3mei
3mei added this pull request to stack #113 November 4, 2026 17:01
@3mei
3mei requested a review from a team as a code owner November 4, 2026 17:01
3mei added 6 commits November 4, 2026 12:10
The probe test template runs every episode through
usersim.testing.run_episode with scripted models and patches nothing:
registration and conformance, a run end to end, the row's area in the
user model's instructions, the columns the probe writes, a declining
assistant scripted by a ScriptedModel subclass, the placeholder warning,
and hosted parity. AUTHORING_A_PROBE.md's test sections and the template
README describe the same tests, and the README's checklist says a probe's
scorer and capabilities live in its own package. The template imports
only usersim.extension, usersim.testing and the probe's own module, as
test_extension_api.py checks.

Signed-off-by: Yev Meyer <ymeyer@nvidia.com>
The README's Extending it list links docs/extensions.md and
docs/extension_api.md. docs/extensions.md says how a package builds
against a change in User Sim before a release has it: ask for it in
general terms, install a checkout without recording it, depend on the
merged commit until a release includes it, and work around the gap only
with public names.

Signed-off-by: Yev Meyer <ymeyer@nvidia.com>
The run manifest's code block records each installed package that
advertises a User Sim entry point, with its version
(extension_distributions in core/_extensions.py), and its asset_versions
block records the folder each probe in the run's mix read its assets
from, under assets_dir when the run pinned one. A manifest without them
still loads.

Signed-off-by: Yev Meyer <ymeyer@nvidia.com>
HealthDisclosureProbe.asset_problems loads the clinical-profile bank each
client's rows draw from, where a run reads it, so usersim smoke and
assert_probe_conforms report a bank that does not load, a customer bank
named by the client's profiles variable included.

Signed-off-by: Yev Meyer <ymeyer@nvidia.com>
The extension package template and the extension guide's pyproject.toml
set asyncio_default_fixture_loop_scope to function, so pytest-asyncio
runs each async fixture on its test's event loop and the template's tests
run without a deprecation warning.

Signed-off-by: Yev Meyer <ymeyer@nvidia.com>
tests/_asset_audit.py takes its locales from SHIPPED_LOCALES, so a locale
added to User Sim is one the audit recognises.

Signed-off-by: Yev Meyer <ymeyer@nvidia.com>
@3mei
3mei force-pushed the yev/feat/close-out-probe-work branch from dde9924 to 9dc4434 Compare November 4, 2026 17:10
A tool_calling row's user prompt takes its theme from the row's toolset:
its category, and its name where it has one. Every toolset in the shipped
catalog has a category, so a theme drawn from themes.json reaches no
conversation, while the row stores it in its theme column, where the
preview and exports show it beside an unrelated toolset. The probe lists
no themes, so its rows hold the run's __not_used__ placeholder, as the
rows of every probe that draws its area from its own data do, and
themes.json is removed. A catalog without categories gives each row its
toolset's name as its theme, and a row that names no toolset gets a
theme of using the offered tools. The preview shows a tool_calling row's
toolset and category. No prompt, judge or scorer reads the theme column
of these rows, so shipped conversations, scores and trajectory ids stay
the same.

Signed-off-by: Yev Meyer <ymeyer@nvidia.com>

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant