太陽がまぶしかったから

C'etait a cause du soleil.

SlackでLLMを取り扱うには Markdown Blocks が便利

SlackでLLMを取り扱うときのつらみが解消

かつてSlackでMarkdownを取り扱おうとすると独自記法である mrkdwn 形式で書く必要があり、2023年ごろの gpt-3.5-turbo に mrkdwn を教えても出力が安定しないので、LLMからは標準的な出力である Markdown で出力させて、それに独自の変換スクリプトかますのが定石であった。

そもそもMarkdownをパースして mrkdwn にするのは面倒だったし、Blocks には3000文字しか入らず、階層箇条書きをスペースで表現したりリンクが途中で切れないようにするといったバッドノウハウヒューリスティックに対応してきたのだけど、最近になって公式から Markdown Blocks が出ていることを知った。Slack Boltであればこんな感じで、最大文字数制限の12000文字ごとに Blocks を生成してリストに加えてやるだけで良い。

def chunk_markdown(text: str, size: int = 12000):
    for i in range(0, len(text), size):
        yield text[i:i+size]

@app.event("app_mention")
def handle_app_mention(event, say):
    prompt = event["text"].replace(f"<@{event['user']}>", "").strip()
    markdown_text = get_llm_contents(prompt)

    blocks = []
    for chunk in chunk_markdown(markdown_text):
        blocks.append({
            "type": "markdown",
            "text": chunk
        })

    say(blocks=blocks)

階層箇条書きやリンクなどもいい感じ。見出しについては # で修飾した方が読みやすいので意図的に few shot でプロンプトエンジニアリングをしている。

## \\# 主要リンク

- [記事タイトル1](リンク1)
    - 説明文や価格などがある時は要旨を140文字以内でまとめてリンクの後ろにつける 
    - 説明文や価格などがある時は要旨を140文字以内でまとめてリンクの後ろにつける 

 表組はやってくれないので、箇条書きでうまく表現させるように指示したり、画像化にチャレンジするなどの余地がある。リンクが切れないようにする処理を作っても良いが、そもそも12,000文字以上も取り扱うことのが稀だろう。

黎明期だからこそのしなくてもよかった苦労と楽しさ

これまでの苦労はなんだったんだと思うぐらいあっさりとできてしまったが、逆に言えば最初から対応してたり、統一的な記法であれば悩む必要のない問題であった。

Displays formatted markdown.
This block can be used with AI apps when you expect a markdown response from an LLM that can get lost in translation rendering in Slack. Providing it in a markdown block leaves the translating to Slack to ensure your message appears as intended. Note that passing a single block may result in multiple blocks after translation.

説明文にも "このブロックは、LLMからの出力がMarkdown形式で返されることを想定するAIアプリにおいて、Slack上でのレンダリングで意図がずれるリスクを防ぐために使用できます。" とある通り、SlackでLLMを取り扱う時に発生するつらみは自分以外にも共通のペインだったので、公式対応されてありがたい以外にはないのだけど、妙な寂寥感への既視感もある。

パンくずリストは、当時は新しかった方法が古くなったという経緯であって、最初から古い方法を選択していた訳ではない。他にもはてなブログhttps 可能になったのも2018年のことで、2014年時点の記事を持ってきて https に対応していないと言われて困ったりもする。

それを思い起こすと、はてなブログ初期にパンくずリストGoogleに認識させたり、記事レコメンドをインジェクションするハックをしていた頃の感覚に思い至る。その時は楽しかったし、ちょっとした優越感もあったけれども公式が機能を提供すれば野良ハックは陳腐化するし、レガシーなカスタマイズが足を引っ張るリスクのが大きい。これもまた期間限定の思想というものなのだろう。

最近でも同じような話が Notion でリトルネロをしているけれども、あんまりノレていないのは、そういうハックは若い衆に任せようって気分なのかもしれない。