Skip to content

Commit b246ac1

Browse files
committed
feat: add eval
1 parent fa59f1a commit b246ac1

5 files changed

Lines changed: 142 additions & 17 deletions

File tree

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
Live: [https://tape.systems](https://tape.systems)
44

5-
A minimal site describing a tape-based fact model, practiced in [bub.build](https://bub.build).
5+
A minimal site about constructing context from tape, practiced in [bub.build](https://bub.build).
66

7-
The site covers both the core context model and two natural extensions: observability and model training.
7+
The site covers both the core context model and three natural extensions: observability, evaluation, and model training.
88

99
References:
1010

@@ -19,6 +19,7 @@ References:
1919
- Advanced Collaboration: memory, teams
2020
- Appendix:
2121
- observability via replayable tape timelines
22+
- evaluation via anchor-bounded views, judges, and derived annotations
2223
- training via anchor-segmented trajectory export
2324

2425
## Tech Stack

components/appendix.tsx

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ export function Appendix() {
2929

3030
<AppendixCard
3131
label="B"
32+
title={t("appendix.eval.title")}
33+
description={t("appendix.eval.desc")}
34+
note={t("appendix.eval.note")}
35+
referenceLabel={t("appendix.eval.ref")}
36+
referenceHref="https://arize.com/docs/phoenix"
37+
diagram={<EvaluationDiagram />}
38+
/>
39+
40+
<AppendixCard
41+
label="C"
3242
title={t("appendix.training.title")}
3343
description={
3444
<>
@@ -200,6 +210,108 @@ function ObservabilityDiagram() {
200210
)
201211
}
202212

213+
function EvaluationDiagram() {
214+
const { locale } = useI18n()
215+
216+
return (
217+
<svg viewBox="0 0 700 220" className="w-full" fill="none">
218+
<defs>
219+
<marker id="eval-arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto">
220+
<path d="M0 1L9 5L0 9" className="fill-none stroke-foreground" strokeWidth="1.5" />
221+
</marker>
222+
<marker id="eval-arr-a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto">
223+
<path d="M0 1L9 5L0 9" className="fill-none stroke-accent" strokeWidth="1.5" />
224+
</marker>
225+
</defs>
226+
227+
<rect x="28" y="18" width="132" height="34" rx="7" className="fill-foreground" />
228+
<text x="94" y="40" textAnchor="middle" className="fill-primary-foreground text-[12px] font-mono font-semibold">
229+
Tape Slice
230+
</text>
231+
232+
<rect x="246" y="18" width="146" height="34" rx="7" className="fill-secondary" />
233+
<text x="319" y="40" textAnchor="middle" className="fill-foreground text-[12px] font-mono font-semibold">
234+
{locale === "zh" ? "Human Review" : "Human Review"}
235+
</text>
236+
237+
<rect x="528" y="18" width="144" height="34" rx="7" className="fill-accent" />
238+
<text x="600" y="40" textAnchor="middle" className="fill-accent-foreground text-[12px] font-mono font-semibold">
239+
{locale === "zh" ? "Derived Facts" : "Derived Facts"}
240+
</text>
241+
242+
<line x1="160" y1="35" x2="236" y2="35" className="stroke-foreground" strokeWidth="1.2" markerEnd="url(#eval-arr)" />
243+
<line x1="392" y1="35" x2="518" y2="35" className="stroke-accent" strokeWidth="1.2" markerEnd="url(#eval-arr-a)" />
244+
245+
<rect x="44" y="82" width="100" height="24" rx="6" className="fill-card stroke-border" strokeWidth="1" />
246+
<text x="94" y="98" textAnchor="middle" className="fill-foreground text-[9px] font-mono">
247+
anchor A12
248+
</text>
249+
250+
<rect x="44" y="116" width="100" height="22" rx="5" className="fill-card stroke-border" strokeWidth="1" />
251+
<text x="94" y="131" textAnchor="middle" className="fill-muted-foreground text-[8px] font-mono">
252+
tool / event / msg
253+
</text>
254+
255+
<rect x="44" y="148" width="100" height="24" rx="6" className="fill-accent/12 stroke-accent" strokeWidth="1" />
256+
<text x="94" y="164" textAnchor="middle" className="fill-accent text-[9px] font-mono">
257+
anchor A13
258+
</text>
259+
260+
<text x="94" y="190" textAnchor="middle" className="fill-muted-foreground/40 text-[8px] font-mono">
261+
{locale === "zh" ? "bounded by anchors" : "bounded by anchors"}
262+
</text>
263+
264+
{[
265+
{ x: 262, y: 84, label: locale === "zh" ? "history replay" : "history replay" },
266+
{ x: 262, y: 118, label: locale === "zh" ? "decision check" : "decision check" },
267+
{ x: 262, y: 152, label: locale === "zh" ? "notes" : "notes" },
268+
].map((item) => (
269+
<g key={item.label}>
270+
<rect x={item.x} y={item.y} width="114" height="22" rx="5" className="fill-card stroke-border" strokeWidth="1" />
271+
<text x={item.x + 57} y={item.y + 14} textAnchor="middle" className="fill-foreground text-[8px] font-mono">
272+
{item.label}
273+
</text>
274+
</g>
275+
))}
276+
277+
<rect x="422" y="90" width="78" height="76" rx="10" className="fill-secondary/35 stroke-border" strokeWidth="1" />
278+
<text x="461" y="111" textAnchor="middle" className="fill-muted-foreground text-[9px] font-mono font-semibold">
279+
{locale === "zh" ? "append" : "append"}
280+
</text>
281+
<text x="461" y="128" textAnchor="middle" className="fill-muted-foreground/70 text-[7px] font-mono">
282+
score
283+
</text>
284+
<text x="461" y="141" textAnchor="middle" className="fill-muted-foreground/70 text-[7px] font-mono">
285+
label
286+
</text>
287+
<text x="461" y="154" textAnchor="middle" className="fill-muted-foreground/70 text-[7px] font-mono">
288+
rationale
289+
</text>
290+
291+
<line x1="144" y1="160" x2="262" y2="160" className="stroke-muted-foreground/35" strokeWidth="1" strokeDasharray="4 3" markerEnd="url(#eval-arr)" />
292+
<line x1="376" y1="95" x2="422" y2="114" className="stroke-accent/55" strokeWidth="1" markerEnd="url(#eval-arr-a)" />
293+
<line x1="376" y1="129" x2="422" y2="129" className="stroke-accent/55" strokeWidth="1" markerEnd="url(#eval-arr-a)" />
294+
<line x1="376" y1="163" x2="422" y2="144" className="stroke-accent/55" strokeWidth="1" markerEnd="url(#eval-arr-a)" />
295+
296+
{[
297+
{ y: 84, title: locale === "zh" ? "Replay" : "Replay", detail: locale === "zh" ? "history stays visible" : "history stays visible" },
298+
{ y: 122, title: locale === "zh" ? "Check" : "Check", detail: locale === "zh" ? "decisions stay inspectable" : "decisions stay inspectable" },
299+
{ y: 160, title: locale === "zh" ? "Recall" : "Recall", detail: locale === "zh" ? "labels stay linked" : "labels stay linked" },
300+
].map((block) => (
301+
<g key={block.title}>
302+
<rect x="536" y={block.y} width="128" height="28" rx="6" className="fill-accent/10 stroke-accent" strokeWidth="1" />
303+
<text x="548" y={block.y + 12} className="fill-accent text-[9px] font-mono font-semibold">
304+
{block.title}
305+
</text>
306+
<text x="548" y={block.y + 21} className="fill-accent/60 text-[7px] font-mono">
307+
{block.detail}
308+
</text>
309+
</g>
310+
))}
311+
</svg>
312+
)
313+
}
314+
203315
function TrainingDiagram() {
204316
const { locale } = useI18n()
205317

components/conclusion.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,14 @@ export function Conclusion() {
2828
</div>
2929
<div className="flex flex-col gap-3">
3030
{[
31-
{ key: "ref.1", slug: "carpenter-hammer-nail" },
32-
{ key: "ref.2", slug: "prometheus-bound" },
33-
{ key: "ref.3", slug: "reinvent-the-punch-tape" },
31+
{ key: "ref.1", href: `${refBase}/carpenter-hammer-nail/` },
32+
{ key: "ref.2", href: `${refBase}/prometheus-bound/` },
33+
{ key: "ref.3", href: `${refBase}/reinvent-the-punch-tape/` },
34+
{ key: "ref.4", href: `${refBase}/im-and-socialized-evaluation/` },
3435
].map((ref, i) => (
3536
<a
3637
key={ref.key}
37-
href={`${refBase}/${ref.slug}/`}
38+
href={ref.href}
3839
target="_blank"
3940
rel="noopener noreferrer"
4041
className="group flex items-center gap-3 text-sm text-background/60 hover:text-background transition-colors"
@@ -80,7 +81,7 @@ function ConclusionDiagram() {
8081
{
8182
num: "05",
8283
label: locale === "zh" ? "附录" : "Appendix",
83-
detail: "observe / train",
84+
detail: "observe / eval / train",
8485
},
8586
]
8687

components/reading-path.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ function ReadingDirectory() {
100100
num: "07",
101101
href: "#appendix",
102102
title: locale === "zh" ? "附录" : "Appendix",
103-
detail: "observability / training",
103+
detail: "observability / eval / training",
104104
group: locale === "zh" ? "附加" : "Applied",
105105
},
106106
]

lib/i18n.tsx

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ const translations: Translations = {
1818

1919
// Hero
2020
"hero.tagline": {
21-
zh: "Tape 即上下文",
22-
en: "Tape as Context",
21+
zh: "Tape 构造上下文",
22+
en: "Context from Tape",
2323
},
2424
"hero.subtitle.line1": {
25-
zh: "同一个模型,也可以外延到可观测性与模型训练。",
26-
en: "The same structure extends into observability and training.",
25+
zh: "同一个结构,也可以外延到可观测性、Eval 与训练。",
26+
en: "It also extends to observability, eval, and training.",
2727
},
2828
"hero.subtitle.line2": {
2929
zh: "一个面向长周期、多团队协作的统一事实模型。",
@@ -278,27 +278,37 @@ const translations: Translations = {
278278
// Appendix
279279
"appendix.title": { zh: "附录", en: "Appendix" },
280280
"appendix.subtitle": {
281-
zh: "两个外延:把 tape 作为可观测层,以及把 tape 作为训练轨迹底座。",
282-
en: "Two extensions: tape as an observability layer and tape as a substrate for training trajectories.",
281+
zh: "三个外延:把 tape 作为可观测层、评估层,以及训练轨迹底座。",
282+
en: "Three extensions: observability, eval, and training.",
283283
},
284284
"appendix.observability.title": { zh: "可观测性", en: "Observability" },
285285
"appendix.observability.desc": {
286286
zh: "tape 不只服务上下文装配,也可以保留 session、tool call 和运行事件,再由 web UI 组装成可检索、可回放的时间线。",
287-
en: "Tape can serve more than context assembly: it can retain sessions, tool calls, and runtime events, then feed a searchable, replayable web timeline.",
287+
en: "Tape can retain sessions, tool calls, and events for a replayable web timeline.",
288288
},
289289
"appendix.observability.note": {
290290
zh: "UI 是派生视图;原始事实仍留在 append-only tape 中。",
291291
en: "The UI is a derived view; raw facts remain in the append-only tape.",
292292
},
293293
"appendix.observability.ref": { zh: "bub", en: "bub" },
294+
"appendix.eval.title": { zh: "Eval", en: "Eval" },
295+
"appendix.eval.desc": {
296+
zh: "按 anchor 取片段,回放历史,检查决策;评分与标签作为派生事实写回。",
297+
en: "Slice by anchor, replay history, inspect decisions, then write scores and labels back as derived facts.",
298+
},
299+
"appendix.eval.note": {
300+
zh: "先给人看清路径与决策,再沉淀派生标注。",
301+
en: "Show the path and decisions to people first, then append derived annotations.",
302+
},
303+
"appendix.eval.ref": { zh: "Phoenix", en: "Phoenix" },
294304
"appendix.training.title": { zh: "训练 / 强化学习", en: "Training / RL" },
295305
"appendix.training.desc.before": {
296306
zh: "tape 可以无缝与",
297-
en: "Tape can work seamlessly with frameworks such as",
307+
en: "Tape works with frameworks such as",
298308
},
299309
"appendix.training.desc.after": {
300310
zh: "这样的框架协作:按 anchor 切段、附 reward、导出 trajectory,再交给异步 trainer 更新模型。",
301-
en: ": segment by anchor, attach rewards, export trajectories, and hand them to an async trainer.",
311+
en: ": slice by anchor, attach rewards, and export trajectories.",
302312
},
303313
"appendix.training.note": {
304314
zh: "训练层应消费 tape 的导出物,而不是替换 tape 作为原始记录。",
@@ -318,6 +328,7 @@ const translations: Translations = {
318328
"ref.1": { zh: "木匠,锤子,钉子", en: "Carpenter, Hammer, Nail" },
319329
"ref.2": { zh: "被缚的普罗米修斯", en: "Prometheus Bound" },
320330
"ref.3": { zh: "重新发明打孔纸带", en: "Reinventing the Punch Tape" },
331+
"ref.4": { zh: "即时通讯与社会化评估", en: "Instant Messaging and Socialized Evaluation" },
321332

322333
// Footer
323334
"footer.desc": {

0 commit comments

Comments
 (0)