Implement comparative action trace table across 100, 1000, and 10000 models
Browse files- __pycache__/app.cpython-312.pyc +0 -0
- app.py +86 -13
__pycache__/app.cpython-312.pyc
CHANGED
|
Binary files a/__pycache__/app.cpython-312.pyc and b/__pycache__/app.cpython-312.pyc differ
|
|
|
app.py
CHANGED
|
@@ -99,15 +99,88 @@ def explain_features_inline(features_str: str) -> str:
|
|
| 99 |
return " Β· ".join(parts)
|
| 100 |
|
| 101 |
|
| 102 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
if not trace:
|
| 104 |
-
return "No
|
| 105 |
-
|
| 106 |
-
for
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 111 |
|
| 112 |
|
| 113 |
def build_coverage_markdown(lang_iso: str, lemma: str, features_str: str) -> str:
|
|
@@ -172,10 +245,8 @@ def run_experiment(language_label: str, lemma: str, features_str: str, gold_targ
|
|
| 172 |
status_1000 = "β
" if pred_1000 == gold_target else "β"
|
| 173 |
status_10000 = "β
" if pred_10000 == gold_target else "β"
|
| 174 |
|
| 175 |
-
trace_text = (
|
| 176 |
-
|
| 177 |
-
f"=== 1,000 Examples ===\n{format_action_trace(res_1000.action_trace)}\n\n"
|
| 178 |
-
f"=== 10,000 Examples ===\n{format_action_trace(res_10000.action_trace)}"
|
| 179 |
)
|
| 180 |
|
| 181 |
return (
|
|
@@ -453,7 +524,9 @@ with gr.Blocks(title="Morphological Inflection", theme=gr.themes.Soft(), css=CUS
|
|
| 453 |
)
|
| 454 |
|
| 455 |
with gr.Accordion("Transduction Steps", open=False):
|
| 456 |
-
trace_box = gr.
|
|
|
|
|
|
|
| 457 |
|
| 458 |
# Quick clickable examples
|
| 459 |
gr.Markdown("#### Examples")
|
|
|
|
| 99 |
return " Β· ".join(parts)
|
| 100 |
|
| 101 |
|
| 102 |
+
def _pluralize_op(op: str, count: int) -> str:
|
| 103 |
+
forms = {
|
| 104 |
+
"COPY": ("copy", "copies"),
|
| 105 |
+
"SUBST": ("substitution", "substitutions"),
|
| 106 |
+
"INSERT": ("insertion", "insertions"),
|
| 107 |
+
"DELETE": ("deletion", "deletions"),
|
| 108 |
+
}
|
| 109 |
+
sg, pl = forms.get(op, (op.lower(), op.lower() + "s"))
|
| 110 |
+
return f"{count} {sg if count == 1 else pl}"
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
def _summarize_trace(trace) -> str:
|
| 114 |
if not trace:
|
| 115 |
+
return "No actions"
|
| 116 |
+
counts = {}
|
| 117 |
+
for s in trace:
|
| 118 |
+
if s.operation == "END":
|
| 119 |
+
continue
|
| 120 |
+
op = "SUBST" if s.operation == "SUBSTITUTE" else s.operation
|
| 121 |
+
counts[op] = counts.get(op, 0) + 1
|
| 122 |
+
parts = [_pluralize_op(k, v) for k, v in counts.items()]
|
| 123 |
+
return ", ".join(parts) if parts else "no edit actions"
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
def _format_action_cell(step) -> str:
|
| 127 |
+
if not step:
|
| 128 |
+
return "β"
|
| 129 |
+
op = step.operation
|
| 130 |
+
src = step.source_char
|
| 131 |
+
emitted = step.emitted_char
|
| 132 |
+
if op == "COPY":
|
| 133 |
+
return f"COPY (`{emitted}`)"
|
| 134 |
+
elif op == "SUBSTITUTE":
|
| 135 |
+
return f"**SUBST** (`{src}` β `{emitted}`)"
|
| 136 |
+
elif op == "INSERT":
|
| 137 |
+
return f"INSERT (`{emitted}`)"
|
| 138 |
+
elif op == "DELETE":
|
| 139 |
+
return f"DELETE (`{src}`)"
|
| 140 |
+
elif op == "END":
|
| 141 |
+
return "*END*"
|
| 142 |
+
return f"{op}"
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
def format_comparative_action_trace(trace_100, trace_1000, trace_10000) -> str:
|
| 146 |
+
if not trace_100 and not trace_1000 and not trace_10000:
|
| 147 |
+
return "Generate an inflection or sample a test item to inspect transduction steps."
|
| 148 |
+
|
| 149 |
+
max_len = max(len(trace_100 or []), len(trace_1000 or []), len(trace_10000 or []))
|
| 150 |
+
|
| 151 |
+
summary_md = (
|
| 152 |
+
f"- **100 Examples:** {_summarize_trace(trace_100)}\n"
|
| 153 |
+
f"- **1,000 Examples:** {_summarize_trace(trace_1000)}\n"
|
| 154 |
+
f"- **10,000 Examples:** {_summarize_trace(trace_10000)}\n"
|
| 155 |
+
)
|
| 156 |
+
|
| 157 |
+
rows = [
|
| 158 |
+
"| Step | 100 Examples (Low) | 1,000 Examples (Medium) | 10,000 Examples (High) | Alignment |",
|
| 159 |
+
"| :---: | :--- | :--- | :--- | :--- |",
|
| 160 |
+
]
|
| 161 |
+
|
| 162 |
+
for i in range(max_len):
|
| 163 |
+
s100 = trace_100[i] if i < len(trace_100 or []) else None
|
| 164 |
+
s1000 = trace_1000[i] if i < len(trace_1000 or []) else None
|
| 165 |
+
s10000 = trace_10000[i] if i < len(trace_10000 or []) else None
|
| 166 |
+
|
| 167 |
+
c100 = _format_action_cell(s100)
|
| 168 |
+
c1000 = _format_action_cell(s1000)
|
| 169 |
+
c10000 = _format_action_cell(s10000)
|
| 170 |
+
|
| 171 |
+
# Check alignment across active steps
|
| 172 |
+
keys = set()
|
| 173 |
+
for s in (s100, s1000, s10000):
|
| 174 |
+
if s is not None:
|
| 175 |
+
keys.add((s.operation, s.source_char, s.emitted_char))
|
| 176 |
+
else:
|
| 177 |
+
keys.add(None)
|
| 178 |
+
|
| 179 |
+
alignment = "β Match" if len(keys) == 1 else "β οΈ Diverged"
|
| 180 |
+
|
| 181 |
+
rows.append(f"| {i+1} | {c100} | {c1000} | {c10000} | {alignment} |")
|
| 182 |
+
|
| 183 |
+
return f"{summary_md}\n" + "\n".join(rows)
|
| 184 |
|
| 185 |
|
| 186 |
def build_coverage_markdown(lang_iso: str, lemma: str, features_str: str) -> str:
|
|
|
|
| 245 |
status_1000 = "β
" if pred_1000 == gold_target else "β"
|
| 246 |
status_10000 = "β
" if pred_10000 == gold_target else "β"
|
| 247 |
|
| 248 |
+
trace_text = format_comparative_action_trace(
|
| 249 |
+
res_100.action_trace, res_1000.action_trace, res_10000.action_trace
|
|
|
|
|
|
|
| 250 |
)
|
| 251 |
|
| 252 |
return (
|
|
|
|
| 524 |
)
|
| 525 |
|
| 526 |
with gr.Accordion("Transduction Steps", open=False):
|
| 527 |
+
trace_box = gr.Markdown(
|
| 528 |
+
"Generate an inflection or sample a test item to inspect transduction steps."
|
| 529 |
+
)
|
| 530 |
|
| 531 |
# Quick clickable examples
|
| 532 |
gr.Markdown("#### Examples")
|