sergiopaniego HF Staff commited on
Commit
92a9ea2
·
verified ·
1 Parent(s): 337e9fb

Fix the capture proxy overlap and the who-drives slide

Browse files
Files changed (50) hide show
  1. assets/{index-Bbx2oP2D.js → index-3N5LkWVC.js} +0 -0
  2. assets/index-78cT1rtj.js +0 -0
  3. assets/index-9aq7EliA.js +0 -0
  4. assets/index-B3w3mWdq.js +0 -0
  5. assets/index-B79OyQDv.js +0 -0
  6. assets/index-BDHk57-U.js +0 -0
  7. assets/index-BNmM1o-f.js +0 -0
  8. assets/index-BY2oEqQ1.js +0 -0
  9. assets/index-Bc6DTkhb.js +0 -0
  10. assets/index-BfrUjWqB.js +0 -0
  11. assets/index-Bi3QvGw1.js +0 -0
  12. assets/index-BwFaVWM1.js +0 -0
  13. assets/index-C8_qArG-.js +0 -0
  14. assets/index-CGyAmRGA.js +0 -0
  15. assets/index-CRdwQfQc.js +0 -0
  16. assets/index-CZEXub1c.js +0 -0
  17. assets/index-CafAjbxk.js +0 -0
  18. assets/index-Cat0hfIv.js +0 -0
  19. assets/index-CnLreNlK.js +0 -0
  20. assets/index-Cny3hg0n.js +0 -0
  21. assets/index-Cv1XSF5a.js +0 -0
  22. assets/index-CzjDNvvq.js +0 -0
  23. assets/index-D32RywPE.js +0 -0
  24. assets/index-D5vfjkyj.js +0 -0
  25. assets/index-D9crLrTR.js +0 -0
  26. assets/index-DFu22CmO.js +0 -0
  27. assets/index-DKT5lcVW.js +0 -0
  28. assets/index-DRfgWPNb.js +0 -0
  29. assets/index-Dj13ONdE.js +0 -0
  30. assets/index-DtWIMazP.js +0 -0
  31. assets/index-Dut9o-_5.js +0 -0
  32. assets/index-Dxgi0Fr8.js +0 -0
  33. assets/index-O6tcdK8e.js +0 -0
  34. assets/index-SygG4YNG.js +0 -0
  35. assets/index-YTKGXYki.js +0 -0
  36. assets/index-YgwXpJdI.js +0 -0
  37. assets/index-b0CEtLKa.js +0 -0
  38. assets/index-neWit8-C.js +0 -0
  39. assets/index-sGFO8MxW.js +0 -0
  40. assets/index-x65b2my4.js +0 -0
  41. index.html +1 -1
  42. multi-harness-rl-slides.pdf +2 -2
  43. multi-harness-rl-slides.pptx +2 -2
  44. source/scripts/export-deck.mjs +69 -0
  45. source/src/components/OverflowGuard.tsx +1 -1
  46. source/src/embeds/d3-capture-proxy.html +1 -1
  47. source/src/slides/11_RLPrimer.tsx +2 -2
  48. source/src/slides/12b_WhoDrives.tsx +8 -26
  49. source/src/slides/18_Proxy.tsx +2 -2
  50. source/src/slides/23b_Tasks.tsx +2 -2
assets/{index-Bbx2oP2D.js → index-3N5LkWVC.js} RENAMED
The diff for this file is too large to render. See raw diff
 
assets/index-78cT1rtj.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-9aq7EliA.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-B3w3mWdq.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-B79OyQDv.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-BDHk57-U.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-BNmM1o-f.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-BY2oEqQ1.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-Bc6DTkhb.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-BfrUjWqB.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-Bi3QvGw1.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-BwFaVWM1.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-C8_qArG-.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-CGyAmRGA.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-CRdwQfQc.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-CZEXub1c.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-CafAjbxk.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-Cat0hfIv.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-CnLreNlK.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-Cny3hg0n.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-Cv1XSF5a.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-CzjDNvvq.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-D32RywPE.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-D5vfjkyj.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-D9crLrTR.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-DFu22CmO.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-DKT5lcVW.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-DRfgWPNb.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-Dj13ONdE.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-DtWIMazP.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-Dut9o-_5.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-Dxgi0Fr8.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-O6tcdK8e.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-SygG4YNG.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-YTKGXYki.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-YgwXpJdI.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-b0CEtLKa.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-neWit8-C.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-sGFO8MxW.js DELETED
The diff for this file is too large to render. See raw diff
 
assets/index-x65b2my4.js DELETED
The diff for this file is too large to render. See raw diff
 
index.html CHANGED
@@ -8,7 +8,7 @@
8
  name="description"
9
  content="RL Environments 101: From 'What Is an Env?' to Training Your Own — a talk by Adithya S Kolavi."
10
  />
11
- <script type="module" crossorigin src="./assets/index-Bbx2oP2D.js"></script>
12
  <link rel="stylesheet" crossorigin href="./assets/index-DlQWIdL0.css">
13
  </head>
14
  <body>
 
8
  name="description"
9
  content="RL Environments 101: From 'What Is an Env?' to Training Your Own — a talk by Adithya S Kolavi."
10
  />
11
+ <script type="module" crossorigin src="./assets/index-3N5LkWVC.js"></script>
12
  <link rel="stylesheet" crossorigin href="./assets/index-DlQWIdL0.css">
13
  </head>
14
  <body>
multi-harness-rl-slides.pdf CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:5a380ce40eefd2ad28e4215fbd3535d67939e24cca56999f54493a9e24362dcb
3
- size 6318119
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d8a176dd3c856a23907e0de6b4b3d4f239c0b24f7acbf5dd3611d0e4b998600f
3
+ size 6326516
multi-harness-rl-slides.pptx CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:8854b782a2539f8e1317ffeb399437d449b2b5c7993dc126086d2cf87789357f
3
- size 7222411
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:351415b7127815d959eabd24da2a05756c19a47b0f837e755c98672552c67239
3
+ size 7197238
source/scripts/export-deck.mjs CHANGED
@@ -78,6 +78,66 @@ const total = await page.evaluate(() => {
78
  const count = Number(process.env.SLIDES || total || 35);
79
  console.log(`exporting ${count} slides`);
80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  const pdfPages = [];
82
  const shots = [];
83
  for (let i = 0; i < count; i++) {
@@ -89,6 +149,7 @@ for (let i = 0; i < count; i++) {
89
  ? Promise.resolve()
90
  : new Promise((r) => f.addEventListener("load", r, { once: true }))));
91
  });
 
92
  pdfPages.push(await page.pdf({
93
  width: "1280px", height: "720px", printBackground: true,
94
  pageRanges: "1", margin: { top: 0, right: 0, bottom: 0, left: 0 },
@@ -105,6 +166,14 @@ for (let i = 0; i < count; i++) {
105
  await browser.close();
106
  server.close();
107
 
 
 
 
 
 
 
 
 
108
  await mkdir(OUTDIR, { recursive: true });
109
 
110
  // stitch the single-page PDFs into one deck
 
78
  const count = Number(process.env.SLIDES || total || 35);
79
  console.log(`exporting ${count} slides`);
80
 
81
+ // Layout check, run on every slide before it is captured. Two things a rendered
82
+ // deck hides well and a projector shows badly: text wider or taller than the box
83
+ // it sits in, and two pieces of text drawn on top of each other.
84
+ function findLayoutProblems() {
85
+ const visible = (e) => {
86
+ const r = e.getBoundingClientRect();
87
+ const cs = getComputedStyle(e);
88
+ return r.width > 0 && r.height > 0 && r.right > 0 && r.left < 1280 && r.top < 720
89
+ && cs.visibility !== "hidden" && Number(cs.opacity) > 0.05;
90
+ };
91
+ // only the slide on screen: the drawer and the print view hold text too
92
+ const roots = [...document.querySelectorAll("[data-slide-root]")].filter(visible);
93
+ const root = roots[roots.length - 1];
94
+ if (!root) return ["no slide root found"];
95
+ const els = [...root.querySelectorAll("*")]
96
+ .filter((e) => !e.closest("svg") && e.tagName !== "IFRAME" && visible(e));
97
+ const label = (e) => `"${(e.innerText || e.textContent || "").trim().replace(/\s+/g, " ").slice(0, 50)}"`;
98
+ const out = [];
99
+ for (const e of els) {
100
+ const cs = getComputedStyle(e);
101
+ if (cs.overflowX === "visible" && e.clientWidth > 0 && e.scrollWidth > e.clientWidth + 2 && (e.innerText || "").trim())
102
+ out.push(`spills ${e.scrollWidth - e.clientWidth}px out of its box: ${label(e)}`);
103
+ }
104
+ const leaves = els.filter((e) => [...e.childNodes].some((n) => n.nodeType === 3 && n.textContent.trim()));
105
+ // one rect per rendered line, so a phrase that wraps is not treated as the
106
+ // whole block between its first and last line
107
+ const rects = leaves.map((e) => {
108
+ const range = document.createRange();
109
+ range.selectNodeContents(e);
110
+ return [...range.getClientRects()].filter((r) => r.width > 0 && r.height > 0);
111
+ });
112
+ const hit = (a, b) =>
113
+ Math.min(a.right, b.right) - Math.max(a.left, b.left) > 3 && Math.min(a.bottom, b.bottom) - Math.max(a.top, b.top) > 3;
114
+ for (let i = 0; i < leaves.length; i++) {
115
+ for (let j = i + 1; j < leaves.length; j++) {
116
+ if (leaves[i].contains(leaves[j]) || leaves[j].contains(leaves[i])) continue;
117
+ if (rects[i].some((a) => rects[j].some((b) => hit(a, b))))
118
+ out.push(`text overlaps: ${label(leaves[i])} and ${label(leaves[j])}`);
119
+ }
120
+ }
121
+ // text drawn over a box it does not belong to (a caption running into a code
122
+ // panel, a link under a card), which the text-to-text check above misses
123
+ const boxes = els.filter((e) => {
124
+ const cs = getComputedStyle(e);
125
+ const r = e.getBoundingClientRect();
126
+ const drawn = (cs.backgroundColor !== "rgba(0, 0, 0, 0)" && cs.backgroundColor !== "transparent")
127
+ || ["Top", "Right", "Bottom", "Left"].every((side) => parseFloat(cs[`border${side}Width`]) > 0);
128
+ return drawn && r.width < 1200 && r.height < 650;
129
+ });
130
+ leaves.forEach((t, i) => {
131
+ for (const bx of boxes) {
132
+ if (bx.contains(t) || t.contains(bx)) continue;
133
+ const b = bx.getBoundingClientRect();
134
+ if (rects[i].some((a) => hit(a, b))) { out.push(`text over a box it is not in: ${label(t)} on ${label(bx)}`); break; }
135
+ }
136
+ });
137
+ return out;
138
+ }
139
+
140
+ const problems = [];
141
  const pdfPages = [];
142
  const shots = [];
143
  for (let i = 0; i < count; i++) {
 
149
  ? Promise.resolve()
150
  : new Promise((r) => f.addEventListener("load", r, { once: true }))));
151
  });
152
+ for (const p of await page.evaluate(findLayoutProblems)) problems.push(`slide ${i + 1}: ${p}`);
153
  pdfPages.push(await page.pdf({
154
  width: "1280px", height: "720px", printBackground: true,
155
  pageRanges: "1", margin: { top: 0, right: 0, bottom: 0, left: 0 },
 
166
  await browser.close();
167
  server.close();
168
 
169
+ if (problems.length) {
170
+ console.log(`\n${problems.length} layout problem(s), fix them before using the export:`);
171
+ for (const p of problems) console.log(` ${p}`);
172
+ } else {
173
+ console.log("\nlayout check: no text spills or overlaps");
174
+ }
175
+
176
+
177
  await mkdir(OUTDIR, { recursive: true });
178
 
179
  // stitch the single-page PDFs into one deck
source/src/components/OverflowGuard.tsx CHANGED
@@ -45,7 +45,7 @@ export function OverflowGuard({ id, children }: { id: string; children: ReactNod
45
  }, [id]);
46
 
47
  return (
48
- <div ref={ref} style={{ position: "absolute", inset: 0 }}>
49
  {children}
50
  {over && (
51
  <>
 
45
  }, [id]);
46
 
47
  return (
48
+ <div ref={ref} data-slide-root style={{ position: "absolute", inset: 0 }}>
49
  {children}
50
  {over && (
51
  <>
source/src/embeds/d3-capture-proxy.html CHANGED
@@ -148,7 +148,7 @@
148
  const stages = [['detect dialect','detect'],['normalise, ids on','normalise'],['record','record']];
149
  // stages sit lower in the shorter box
150
  stages.forEach((sg, k) => {
151
- const y = yP + 44 + k*15;
152
  const on = si === IDX[sg[1]];
153
  const done = after(sg[1]);
154
  s += `<circle cx="${xP+17}" cy="${y-3.5}" r="3.4" fill="${on||done ? cReq : bd}" fill-opacity="${on?1:(done?.5:1)}"/>`;
 
148
  const stages = [['detect dialect','detect'],['normalise, ids on','normalise'],['record','record']];
149
  // stages sit lower in the shorter box
150
  stages.forEach((sg, k) => {
151
+ const y = yP + 54 + k*13;
152
  const on = si === IDX[sg[1]];
153
  const done = after(sg[1]);
154
  s += `<circle cx="${xP+17}" cy="${y-3.5}" r="3.4" fill="${on||done ? cReq : bd}" fill-opacity="${on?1:(done?.5:1)}"/>`;
source/src/slides/11_RLPrimer.tsx CHANGED
@@ -20,7 +20,7 @@ export function RLPrimerSlide() {
20
  <motion.div key={n}
21
  initial={{ opacity: 0, x: -16 }} animate={{ opacity: 1, x: 0 }}
22
  transition={{ delay: 0.18 + i * 0.14, type: "spring", damping: 22 }}
23
- style={{ display: "flex", alignItems: "baseline", gap: 24, padding: "14px 0" }}
24
  >
25
  <span style={{ fontFamily: MONO, fontSize: 34, fontWeight: 800, color: T.emerald, width: 44 }}>
26
  {n}
@@ -30,7 +30,7 @@ export function RLPrimerSlide() {
30
  ))}
31
  <motion.div
32
  initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ delay: 0.85 }}
33
- style={{ marginTop: 30, padding: "24px 26px", borderRadius: 12,
34
  border: `1px solid ${T.border}`, background: T.bgRaised }}
35
  >
36
  <div style={{ fontSize: 21, color: T.textMuted, lineHeight: 1.6 }}>
 
20
  <motion.div key={n}
21
  initial={{ opacity: 0, x: -16 }} animate={{ opacity: 1, x: 0 }}
22
  transition={{ delay: 0.18 + i * 0.14, type: "spring", damping: 22 }}
23
+ style={{ display: "flex", alignItems: "baseline", gap: 24, padding: "10px 0" }}
24
  >
25
  <span style={{ fontFamily: MONO, fontSize: 34, fontWeight: 800, color: T.emerald, width: 44 }}>
26
  {n}
 
30
  ))}
31
  <motion.div
32
  initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ delay: 0.85 }}
33
+ style={{ marginTop: 22, padding: "22px 26px", borderRadius: 12,
34
  border: `1px solid ${T.border}`, background: T.bgRaised }}
35
  >
36
  <div style={{ fontSize: 21, color: T.textMuted, lineHeight: 1.6 }}>
source/src/slides/12b_WhoDrives.tsx CHANGED
@@ -12,47 +12,29 @@ import { Embed } from "../components/Embed";
12
  // which is the right order to tell it in: this is how RL normally runs, then one
13
  // click shows what a harness does to it. The title carries both halves, so the
14
  // exported PDF still makes the point without the click.
15
- const CSS = `body { zoom: 1.02; }`;
16
 
17
  export function WhoDrivesSlide() {
18
  const { T } = useTheme();
19
  return (
20
  <SlideShell
21
  kicker="The background"
22
- title="Normally the trainer drives. Here the harness does"
23
  titleSize={38}
24
  >
25
  <div style={{ position: "absolute", top: 152, left: 60, right: 60 }}>
26
- <Embed name="d3-who-drives" css={CSS} height={322} />
27
 
28
  <motion.div
29
  initial={{ opacity: 0 }}
30
  animate={{ opacity: 1 }}
31
  transition={{ delay: 0.5 }}
32
- style={{
33
- marginTop: 18,
34
- borderLeft: `3px solid ${T.lavender}`,
35
- paddingLeft: 22,
36
- fontSize: 20,
37
- color: T.text,
38
- lineHeight: 1.55,
39
- fontStyle: "italic",
40
- }}
41
  >
42
- “In traditional agentic RL, the training engine owns the environment interaction loop. In{" "}
43
- <span style={{ color: T.lavender }}>harnessed agentic RL</span>, the harness owns this loop,
44
- while the training engine observes only a sequence of LLM request-response pairs.”
45
- <div
46
- style={{
47
- fontFamily: MONO,
48
- fontSize: 14,
49
- color: T.textDim,
50
- marginTop: 10,
51
- fontStyle: "normal",
52
- }}
53
- >
54
- Agent Lightning, Microsoft 2026
55
- </div>
56
  </motion.div>
57
  </div>
58
  </SlideShell>
 
12
  // which is the right order to tell it in: this is how RL normally runs, then one
13
  // click shows what a harness does to it. The title carries both halves, so the
14
  // exported PDF still makes the point without the click.
15
+ const CSS = `body { zoom: 0.84; }`;
16
 
17
  export function WhoDrivesSlide() {
18
  const { T } = useTheme();
19
  return (
20
  <SlideShell
21
  kicker="The background"
22
+ title="Who drives the loop: the trainer or the harness"
23
  titleSize={38}
24
  >
25
  <div style={{ position: "absolute", top: 152, left: 60, right: 60 }}>
26
+ <Embed name="d3-who-drives" css={CSS} height={462} />
27
 
28
  <motion.div
29
  initial={{ opacity: 0 }}
30
  animate={{ opacity: 1 }}
31
  transition={{ delay: 0.5 }}
32
+ style={{ marginTop: 10, maxWidth: 1040, fontSize: 18, color: T.text, lineHeight: 1.5 }}
 
 
 
 
 
 
 
 
33
  >
34
+ Agent Lightning calls this{" "}
35
+ <span style={{ color: T.lavender }}>harnessed agentic RL</span>. The harness owns the loop,
36
+ and the trainer only sees the model&rsquo;s requests and responses.{" "}
37
+ <span style={{ fontFamily: MONO, fontSize: 14, color: T.textDim }}>Agent Lightning, Microsoft 2026</span>
 
 
 
 
 
 
 
 
 
 
38
  </motion.div>
39
  </div>
40
  </SlideShell>
source/src/slides/18_Proxy.tsx CHANGED
@@ -12,12 +12,12 @@ export function ProxySlide() {
12
  return (
13
  <SlideShell kicker="How it works" title="The capture proxy" titleSize={40}>
14
  <div style={{ position: "absolute", top: 146, left: 60, right: 60, bottom: 26 }}>
15
- <Embed name="d3-capture-proxy" css={CSS} height={408} />
16
  <motion.div
17
  initial={{ opacity: 0 }}
18
  animate={{ opacity: 1 }}
19
  transition={{ delay: 0.45 }}
20
- style={{ fontSize: 19, color: T.textMuted, lineHeight: 1.5, marginTop: 16 }}
21
  >
22
  The proxy probes the engine before it trusts it. An engine that will not return token ids
23
  and logprobs still serves the rollout, and the trace comes back marked evaluation only.
 
12
  return (
13
  <SlideShell kicker="How it works" title="The capture proxy" titleSize={40}>
14
  <div style={{ position: "absolute", top: 146, left: 60, right: 60, bottom: 26 }}>
15
+ <Embed name="d3-capture-proxy" css={CSS} height={448} />
16
  <motion.div
17
  initial={{ opacity: 0 }}
18
  animate={{ opacity: 1 }}
19
  transition={{ delay: 0.45 }}
20
+ style={{ fontSize: 18, color: T.textMuted, lineHeight: 1.5, marginTop: 10 }}
21
  >
22
  The proxy probes the engine before it trusts it. An engine that will not return token ids
23
  and logprobs still serves the rollout, and the trace comes back marked evaluation only.
source/src/slides/23b_Tasks.tsx CHANGED
@@ -67,13 +67,13 @@ export function TasksSlide() {
67
  </span>
68
  </motion.div>
69
 
70
- <Embed name="d3-harbor-task" css={CSS} height={408} />
71
 
72
  <motion.div
73
  initial={{ opacity: 0 }}
74
  animate={{ opacity: 1 }}
75
  transition={{ delay: 0.6 }}
76
- style={{ fontSize: 19, color: T.textMuted, lineHeight: 1.5, marginTop: 14 }}
77
  >
78
  <span style={{ color: T.white, fontWeight: 700 }}>
79
  Verified by a checker, not judged by a model.
 
67
  </span>
68
  </motion.div>
69
 
70
+ <Embed name="d3-harbor-task" css={CSS} height={392} />
71
 
72
  <motion.div
73
  initial={{ opacity: 0 }}
74
  animate={{ opacity: 1 }}
75
  transition={{ delay: 0.6 }}
76
+ style={{ fontSize: 18, color: T.textMuted, lineHeight: 1.5, marginTop: 10, maxWidth: 1060 }}
77
  >
78
  <span style={{ color: T.white, fontWeight: 700 }}>
79
  Verified by a checker, not judged by a model.