書かせた説明を読み返していて、途中で目が止まります。
誤差は $\sum_{i=1}^{n} (y_i - \hat{y}_i)^2$ で測ります。
ドルマークのまま出ています。プレビューで開いたはずなのに、文字が並んでいるだけです。
頭の中で組み直せば読めます。ただ、それは読み返しではありません。
読み返せません
文章は読み返せば確かめられます。数式は、記号の形になっていないと確かめられません。
\hat{y}_i が何を指すのかは、組まれた形で見れば一目です。文字列のままだと、頭の中で組み直すことになります。それは読み返しではなく、再計算です。
AI に書かせる量が増えると、ここが効いてきます。確かめにくいものが積み上がります。
なぜそのまま出るのか
Markdown の決まりに、数式は入っていません。
もとの Markdown は、見出し・箇条書き・強調・リンクを決めただけのものです。数式は後から各所が勝手に足したもので、$…$ という書き方も、広く使われてはいますが標準ではありません。
そのため、プレビューを作る側が明示的に対応しないと、ただの文字として通過します。対応している所としていない所が混ざるのは、このためです。
どこで組むか
対応するには、どこかで数式を組む必要があります。選べるのは2つです。
ブラウザで組む方法は、よく使われます。ページを開いたときに、ブラウザが数式を探して組み立てます。手軽ですが、組み立てる部品をブラウザに読み込ませる必要があり、表示されるまで一拍あります。
もう1つは、サーバーで組んでから送る方法です。ブラウザは組み上がった図を描くだけなので、速いです。
MulmoTerminal 10.2.0 は後者にしました。全画面のプレビューで $…$ と $$…$$ を見つけて、サーバー側で SVG に組んでから送ります。組み立ての部品は、最初に $ を含む文書が来たときに読み込まれます。
組むと穴が開きます
ここからが、やってみないと気づかない部分です。
数式を組むと、HTML の断片ができます。これをそのまま送ると、文書の中身が HTML としてページに入ることになります。Markdown を書いたのが AI であれ人であれ、そこに仕込みがあれば、そのまま効いてしまいます。
ブラウザで組む場合は、ブラウザ側の掃除の仕組みが使えます。サーバーで組む場合は、それがありません。
MulmoTerminal では、通す要素と属性を名簿にして、そこに載っているものだけを残す形にしました。
- 数式を組み立てる要素だけを通す
- 属性も、組版が書くものだけを、書く形のものだけ通す
- SVG の
<title>は落とす。ここにはエラーの文面がそのまま入るため - TeX の拡張のうち、HTML を書けるものと動作を起こせるものは外す
最後の2つが、見落としやすいところです。組版の仕組み自体は正しく動いていても、エラーのときに入力をそのまま書き出す経路が残っていると、そこが穴になります。
名簿方式にしたあと、攻撃用の入力を食わせて、HTML の解析器が何を組み立てるかを確かめる検査も入れました。
自分で用意する場合
サーバー側で組むなら、同じ順番を踏むことになります。
- Markdown を解析するときに、数式の区切りを見つける規則を足す
- 見つけた部分を組版に渡して、SVG を受け取る
- 受け取った HTML を、通す名簿で濾す
- エラーの文面が混ざる経路を潰す
3番目を飛ばすと動いてしまうので、飛ばしたことに気づきません。ここが一番危ないところです。
ブラウザで組むほうを選ぶなら、掃除は任せられます。代わりに、表示までの間と、読み込ませる部品の分だけ重くなります。
使ってみる
npx mulmoterminal@latest
枠の中でファイルを開いて、全画面のプレビューに切り替えると、数式が組まれた形で出ます。ペインに埋め込んだほうでも、別のタブで開いたほうでも同じです。
まとめ
Markdown に数式の決まりはないので、対応している所としていない所が混ざります。AI に書かせる量が増えると、確かめられない記述が積み上がります。
サーバーで組むと速くなりますが、掃除を自分でやることになります。そこを引き受けるかどうかが、どちらで組むかの分かれ目です。
- MulmoTerminal —
npx mulmoterminal@latest
