Drafts

@cm3 の草稿置場 / 少々Wikiっぽく使っているので中身は適宜追記修正されます。

Alexa の スキルのプログラミングを試した

もとからやろうと思っていた ChatGPT を使うという機能と、自前の音楽を再生させるスキルと、2つ実装してみた。

1. ChatGPT を使う

k4l1sh/alexa-gpt: A tutorial on how to use ChatGPT in Alexa がセットアップのhowtoとしてわかりやすかった。唯一つまったのはchatgpt の有料プランに入ってても、APIは別途課金が必要というところ。

使ってみた感想としては、alexa の聞き取り能力に制約されるので、chatgpt の iOS app で直接聞き取ってもらう時よりかなりストレスフル。でも、簡単なことなら役立つのでそれなりに使っている。

2. 自前の音楽を再生させる

自前の mp3 をサーバにあげて、それを特定の命令で再生させるだけの機能。

あまりうまく完成していないが、Intent の JSON は以下。基本聞き取り能力がダメなので、曲の指定は t とか h とかにしている。 日本語も設定しているが、日本語で聞き取ってくれたことはない。InvocationName は日本語で聞き取ってくれているので、なんで聞き取ってくれないのかはわからない。基本、自分で作曲とか譜面化とかしない限り、著作権DRMに引っかかることが多く、あまりニーズがないんだろうなという気はする。(僕は昔から持っているmp3が大量にある)

{
    "interactionModel": {
        "languageModel": {
            "invocationName": "イヤーワーム",
            "intents": [
                {
                    "name": "ChooseSongIntent",
                    "slots": [
                        {
                            "name": "SongChoice",
                            "type": "SONG_OPTIONS"
                        }
                    ],
                    "samples": [
                        "Play {SongChoice}",
                        "I want to hear {SongChoice}",
                        "Play song {SongChoice}",
                        "Start {SongChoice}",
                        "Play the song {SongChoice}",
                        "{SongChoice} 再生",
                        "{SongChoice} で"
                    ]
                },
                {
                    "name": "AMAZON.HelpIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.StopIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.CancelIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.PauseIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.ResumeIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.LoopOffIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.LoopOnIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.NavigateHomeIntent",
                    "samples": []
                }
            ],
            "types": [
                {
                    "name": "SONG_OPTIONS",
                    "values": [
                        {
                            "name": {
                                "value": "t",
                                "synonyms": [
                                    "ティー",
                                    "トウキョー"
                                ]
                            }
                        },
                        {
                            "name": {
                                "value": "h",
                                "synonyms": [
                                    "エイチ",
                                ]
                            }
                        }
                    ]
                }
            ]
        }
    }
}

そして、node.js で作った index.js は以下。

const Alexa = require('ask-sdk-core');
const urlHead = <自分のサーバのURL>;

// Helper function to get the playback information from session attributes
function getPlaybackInfo(handlerInput) {
    const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
    if (!sessionAttributes.playbackInfo) {
        sessionAttributes.playbackInfo = {
            token: 'default-audio-token',
            offsetInMilliseconds: 0,
            inPlaybackSession: false,
            hasPreviousPlaybackSession: false,
            songUrl: ""  // Placeholder for the song URL
        };
        handlerInput.attributesManager.setSessionAttributes(sessionAttributes);
    }
    return sessionAttributes.playbackInfo;
}

// Helper function to set the playback information to session attributes
function setPlaybackInfo(handlerInput, playbackInfoObject) {
    const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
    sessionAttributes.playbackInfo = playbackInfoObject;
    handlerInput.attributesManager.setSessionAttributes(sessionAttributes);
}

// LaunchRequestHandler to handle the initial invocation of the skill
const LaunchRequestHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
    },
    handle(handlerInput) {
        const speakOutput = '準備ができました!';
        return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt('say play t or play h')
            .getResponse();
    }
};

// ChooseSongIntentHandler to handle the selection of a song
const ChooseSongIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' &&
               Alexa.getIntentName(handlerInput.requestEnvelope) === 'ChooseSongIntent';
    },
    handle(handlerInput) {
        try {
            const songChoice = handlerInput.requestEnvelope.request.intent.slots.SongChoice.value;
            let playbackInfo = getPlaybackInfo(handlerInput);
            let songUrl;

            if (songChoice === "t") {
                songUrl = "{$urlHead}tsr_alexa.mp3";
            } else if (songChoice === "h") {
                songUrl = "{$urlHead}hc_alexa.mp3";
            } else {
                return handlerInput.responseBuilder
                    .speak("すみません、その曲はわかりません。t か h で選んでください")
                    .reprompt("t か h で選んでください")
                    .getResponse();
            }

            playbackInfo.songUrl = songUrl;
            setPlaybackInfo(handlerInput, playbackInfo);

            const speakOutput = `選択された曲を再生します。`;
            return handlerInput.responseBuilder
                .speak(speakOutput)
                .addAudioPlayerPlayDirective('REPLACE_ALL', songUrl, playbackInfo.token, 0)
                .getResponse();
        } catch (error) {
            return handlerInput.responseBuilder
                .speak(`エラーが発生しました: ${error.message}`)
                .getResponse();
        }
    }
};

// Handler for stopping the audio
const CancelAndStopIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' &&
               (Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.CancelIntent' ||
                Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.StopIntent');
    },
    handle(handlerInput) {
        const speakOutput = '再生を停止します。';
        return handlerInput.responseBuilder
            .speak(speakOutput)
            .addAudioPlayerStopDirective()
            .withShouldEndSession(true)
            .getResponse();
    }
};

// Handler for pausing the audio
const PauseIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' &&
               Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.PauseIntent';
    },
    handle(handlerInput) {
        const speakOutput = '再生を一時停止します。';
        return handlerInput.responseBuilder
            .speak(speakOutput)
            .addAudioPlayerStopDirective()
            .withShouldEndSession(false)
            .getResponse();
    }
};

// Handler for resuming the audio
const ResumeIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' &&
               Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.ResumeIntent';
    },
    handle(handlerInput) {
        const playbackInfo = getPlaybackInfo(handlerInput);
        const speakOutput = '再生を再開します。';
        return handlerInput.responseBuilder
            .speak(speakOutput)
            .addAudioPlayerPlayDirective('REPLACE_ALL', playbackInfo.songUrl, playbackInfo.token, playbackInfo.offsetInMilliseconds)
            .withShouldEndSession(false)
            .getResponse();
    }
};

// Handler for the LoopOnIntent
const LoopOnIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' &&
               Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.LoopOnIntent';
    },
    handle(handlerInput) {
        let playbackInfo = getPlaybackInfo(handlerInput);
        playbackInfo.isLooping = true;
        setPlaybackInfo(handlerInput, playbackInfo);

        const speakOutput = 'ループ再生をオンにしました。';
        return handlerInput.responseBuilder
            .speak(speakOutput)
            .getResponse();
    }
};

// Handler for the LoopOffIntent
const LoopOffIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' &&
               Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.LoopOffIntent';
    },
    handle(handlerInput) {
        let playbackInfo = getPlaybackInfo(handlerInput);
        playbackInfo.isLooping = false;
        setPlaybackInfo(handlerInput, playbackInfo);

        const speakOutput = 'ループ再生をオフにしました。';
        return handlerInput.responseBuilder
            .speak(speakOutput)
            .getResponse();
    }
};

// ErrorHandler to catch any unexpected errors
const ErrorHandler = {
    canHandle() {
        return true;
    },
    handle(handlerInput, error) {
        console.error(`Error handled: ${error.message}`);
        return handlerInput.responseBuilder
            .speak('申し訳ありませんが、問題が発生しました。')
            .getResponse();
    }
};

// Skill builder configuration
exports.handler = Alexa.SkillBuilders.custom()
    .addRequestHandlers(
        LaunchRequestHandler,
        ChooseSongIntentHandler,
        CancelAndStopIntentHandler,
        PauseIntentHandler,
        ResumeIntentHandler
    )
    .addErrorHandlers(ErrorHandler)
    .lambda();

本当はループとか再生のいろんな操作をしたかったのだが、今更ながらAlexaのAudio Playerをきちんと理解してみる③ 〜複数の曲を扱ってみる〜 - kun432's blog のようにしてみようとしたら、AudioPlayer.PlaybackNearlyFinished が受け取れずに諦めました。テスト機能でそもそもそのイベントが発生していなかったようなので、諦めました。

m3u も対応しているということでしたが、単純に曲のmp3を並べただけの m3u は対応してませんでした。MyVideo をいうサービスに関わっての情報ですが、Each .m3u8 file should contain only a single stream link. という制限がかかっているのだと思うので、ストリーミングのためのサーバーを建てる必要があるのではという感じです。

単に短い(4分以内)の曲を一度再生させるだけなら SSML だけでもいけます。そっちの方が実装は楽です。(参考:Alexa上で音源(MP3)を制御するための知見 [SSML, AudioPlayer] #AlexaSkillsKit - Qiita

総評

さて、Alexa のスキルストアをみても正直ろくな機能が公開されていません。それは、m3u の件のように仕様の詳細がわかりにくいのと、console.log のような単純なデバッグができない(やりかたがわからない)のと、すでに公開されているアプリのコメントでも書かれていますがそもそもの聞き取り能力が低過ぎて色々なアプリが実現できない状況であることが原因だと思います。

基本機能としてタイマーや時計は便利ですし、単に、おはよう、いってきます、ただいま、を言う相手としては悪くないです。Prime の無料期間には頼んだ曲も一曲目に演奏してくれたのでミュージックプレイヤーとしても優秀でした。しかし、無料期間が終わるとだんだん演奏してくれなくなりました。ストリーミングサービスに慣れた人たちは良いのでしょうが、ポップスにしろクラシックにしろ「今この曲が聞きたい!」という僕のようなタイプは Amazon Music Unlimited に入らざるを得ないのですが、基本的にPCの前に居るので、Alexa を bruetooth スピーカーとして使って音楽を流した方がいいのです。

Amazonのデバイス事業が少なくとも約4兆円の損失を出していたことが判明、Alexaから収益を上げる計画は崩壊 - GIGAZINEということで、上に挙げた聞き取り能力の低さについては Alexa Plus というサブスクサービスでLLMベースのアップデートをするらしく、それは値段と性能次第では契約するかもしれない。スマートホーム家電を買うのは面倒でいろいろ制約が強くなるので、とりあえずインタフェースだけ便利に対応してほしくはある。ラズパイ+赤外線みたいな方法でね。ADHD用のハックのように「行ってらっしゃい」のついでに戸締りなどの確認をアナウンスで僕にさせるというのがいまのところ良い使い道で、そこで消灯の確認などが自動化できるといい、くらいの意味なので、やはり、ここも現在の機能で十分なのかもしれないけど。

組織論学びたい、というメモ

そのうち Coursera か何かで学んでみようと思っている。学部前期の教養で1コマ取っていて、意思決定モデルなどは楽しかった覚えがある→ゴミ箱モデル(ゴミばこモデル)とは? 意味や使い方 - コトバンク。レポートでは課題の論題そのものの枠組みに対する稚拙な反論から始めてしまったような記憶が朧げながらあり、先生には申し訳ないことをしたなぁと薄らと思っている。

さて、その程度の知識しかないのに、組織論についての興味が増し、ここにメモらねばと思っているのは、新しい職場における色々な危機感からである。別に今の職場が嫌いなわけではない。でも、国家公務員でもないのに国家公務員を対象とした法に基づいて仕事をしようとしたり、口にされる「ガバナンス」が単にトップダウンな支配系統しか意味してなかったり、組織論が未熟なまま組織化の力が肥大した組織で、それは、所属各機関やそこの研究者を対象とした情報システムを設計する僕にとって非常に怖いことなのだ。システムというものは、不可避に個と対立する。情報システムはその暗黙さや設計の自由さ、知能的処理と結びついた能力などの特性のおかげでそれを非常に強力に発揮しうる。しかし、今挙げたような"情報"システムの特性は、必ずしも、「不可避に個と対立するシステム」の「対立」と直接結びついた要素ではない。たとえばデータを標準化することによって、相互利用や長期保存が見込めるが、ゆるい標準化とそこからの抽出が知能的処理で可能な状態ならば、個々の研究者のデータの自由度は上がるので、むしろ「対立」を弱めるようにその特性は機能する。ちなみに、システムが個と対立するのが不可避だと思っているのは、システムは人間以外も含めて複数のアクターと機能の有機的な結びつき(=全体)と、それ自体が機能的に自律して持つ大局的な方向づけ(=全体のバイアス)を不可避に持つから、という一般システム理論から派生したような認識だ。

そんな環境で、機構の指示を所属する機関が聞かずに文句をいって意思決定が遅れることをガバナンスの不在として糾弾するような認識があればどうなるか。それでなくとも、会計監査の説明責任を自ら持つことを一定さけるために国に準じて仕事し、文科省から飛んできた的外れな調査に唯々諾々と対応する官僚的な組織において、ミッションが意識されず(ミッションは 人間文化研究機構とは | 大学共同利用機関法人 人間文化研究機構 に書かれているとおりだが、大枠として 「大学共同利用機関法人・大学共同利用機関の在り方」主な論点及び関連する主な意見(案):文部科学省 が他の組織と相関的に見たミッションを把握するのに重要だと思っている)細かい手続きに手続き自体を目的化した形でこだわることで(「凡俗」も含め)パーキンソンの法則で指摘されるような無駄を抱え、「保守的」になることでミッションに反する状況にある。幸い、機構長も理事も研究者であるので、その問題がどうしようもないレベルではないが、逆に言うと、この問題を解決するために必要な組織論的な知見は実務的にも知識的にも乏しい。ちなみに「ガバナンス」という言葉に噛み付いているのは、コーポレート・ガバナンスは「会社が、株主をはじめ顧客・従業員・地域社会等の立場を踏まえた上で、透明・公正かつ迅速・果断な意思決定を行うための仕組み」を指すので、トップダウンに言うことを聞かせる組織はこれがむしろ「できていない」ことが多い。わざわざカタカナ語を用いていることからもわかるようにアメリカからの輸入概念だが、なぜアメリカでコーポレートガバナンスが叫ばれるようになったのか彼らは答えられるのだろうか。インテグリティについても同様で、カタカナ語にすること自体に問題なくとも、原義を損なって今の日本の雑な権力を強化するためにカタカナが用いられているの、カタカナが可哀想だ。

既存の現場のやり方や概念は、積極的に学んで「使えば」いい。どの組織は総務課が、どの組織は人事課がこの情報を扱うので、そこに根回しを、みたいなのもかなり身についてきた。別にそういうのは、研究者としては無駄な能力だろうが、僕は教育職を避けることによって省けている無駄は色々あるので、その分、このくらい仕事のために身につければいいと思っている。「ライン」という言葉もこの職場にきて始めて頻繁に聞くようになったジャーゴンで、レポートラインラインマネージャといった用語でいうラインで、「明日山陽子 (2023): 国際比較から見える日本のジョブの特徴」(https://www.jil.go.jp/institute/zassi/backnumber/2023/06/pdf/058-067.pdf) で指摘されている「日本企業が内向きの調整ばかりを重視し,過剰ともいえる和を求める傾向(沼上ほか 2007)が更に,人間関係や仕事の社会的意義を押し下げる要因となっている可能性もある」と指摘されている問題を強化するようにも脱するようにも使いうるもので、脱するようにつかえばいい(部署全員の総意を取ろうと、会議を増やさなくて良い)。

出所不明のネタ画像にあるように、ツリー状の組織だけが組織ではない。別に組織を変えることが目的ではないが、mission oriented な仕事ができるようにしたい。そのために組織論を学びたい。

地面師たち、みた

話題になってるから見た、程度。レビューを漁っていたら「総じて楽しかったですが、楽しかったという印象しか残らなかったというエンタメです。」という酷評が見つかったが、結構同意かな。まあ、あとは詐欺に遭いやすい心理の一つや二つを解像度高く知っておくというのは意味があるかなとは思った。

  • 冒頭のクマのシーンから映像の作りは少し荒いと思った(「サンクチュアリ」と比較)
  • 青年誌の無駄なセックスシーンっぽいノリが気になるというのがあって、別に僕はこれはこれで存在していいとは思うが、確かにジャンクエロっぽくて「美味しく」なかった。裏社会ノリで別様のエロといえば思い出すのは お嬢さん - 映画情報・レビュー・評価・あらすじ・動画配信 | Filmarks映画 がなかなかよかったのだが、あまり安易にジャンクなエロを描かないで欲しいというのは、皆のエロリテラシーを上げるためにそう思う。
  • なんかうまいこといったみたいに、土地の奪い合いというのは戦争と変わらないという話をしていたが、地面師は別に土地を奪ってないし、デベロッパーも付加価値つけて切り売りしかしていないので、土地への執着というコンテクストで一貫性を持たせるのは無理がある気がしました。
  • ここまで酷評しときながら一気見しているので、どんな内容でも「面白くしちゃう」技術というのはもう少し身につけたいなと思いました。
  • 対してエロくないのに、なんでnetflixしかできないと言われているんだろう?と思ったら殺しのシーンが多いからか。殺しのシーンもグロ控えめだったと思う。グロ苦手なのでそこはありがたかった。
  • 積水ハウス地面師詐欺事件 - Wikipedia まあ普通に史実が面白い。
  • イッキ見する人続出!「地面師たち」何が面白い?|シネマトゥデイ 演技は良かったし、典型的ピカレスク、ハリウッドより韓国ドラマ寄り、ってあたりすべて同意っす。

やっしーが出演しているので、「また、科学者扱いされているのか」と憤っている人が多いようだが、「そこまで言って委員会NP」に出ているということは学者としては不適かキワモノであると扱われているということなので、むしろ「そういうお墨付きを得ちゃったのね」と扱えばいいのである。そういうリテラシーが無い人たちが恰も科学のリテラシーがあるかのように振る舞っていること自体怪しいなと思ってしまう。

そもそもに、だ。「アカデミアを検証する番組の出演者がまったくアカデミックでない」ことは別に問題では無い。ひやっしーについては学界を知っている風に振る舞っていて、ぜんぜん的外れだったりで、共感性羞恥が発動しまくっていたが、竹中平蔵は学者として振る舞ってはいなかったし、山口真由もどちらかというとアナウンサーのような振る舞いでゲスト学者に質問を振っていた(一応全部見たのです、TVer で、1.75倍速で。みんなは見なくていいよ)。学問というのは、化学博士だからといって社会学のことについて専門性を持てないように、ある分野の専門性というのは一定以上汎化できないわけなので、「アカデミアを検証する」ことをアカデミックにできるとしたら、Science of Science、科学社会学、科学政策などの専門家が必要なわけであって、単に学者が必要なのではない。化学博士ができるのは単に当事者としてのローカル知を以て何か言えるというくらいである。そして、この番組の構成は、学界の爪弾き者やイロモノ、学問になんらか関わっているが嫌われている者、などが極論を「そこまで言うか」と言われそうな毒を伴って言うことに「意味がある」ので、アカデミアからまともに認められた人たちによる構成、先ほどあげた科学社会学や科学政策の専門家による構成はそもそも目指していないのである。

そういう意味では意外とまともに構成していると思ったのだ。竹中平蔵ネオリベ一つ覚えだし、ひやっしーは居なくてよかったし、途中に挟まれる京大生インタビューは「君たち、こういうのに簡単に顔ださんほうがいいよ」と思ったけれども、まあ、意外と議論として噛み合っていたのだ(才媛枠でヨシヨシされてた初出演の上田さんが「視聴者側で見ていたいつもより暖かい雰囲気だった」的なことをおっしゃってたので、珍しい回だったのかもしれない)。コロナの総括、原子力発電の是非、地震予知、について、宮沢孝幸、多田将、ロバートゲラーをゲストにしていて(後ろ二人はよく知らないが宮沢さんと並べられていいんかとか?とは心配になったけど)まあよくある論点をバラエティ的に話していて、極論を出すことで議論が盛り上がるという構成自体は悪くなかった。極論にそのまま呑まれるような視聴者だと見てはいけないけれども。多田さんの、学者ももっと社会への説明責任を果たすべきって話とかはめっちゃ真っ当だったし(僕はこの点については、少々極端?な立場で、国民の1%が分かるように説明すればいい、下位50%についてはメタ専門知( ハリー コリンズ (著), 鈴木 俊洋 (翻訳) 「我々みんなが科学の専門家なのか」での用語)的な判断に資する説明としても無視するべきと思っている=多数決的な意思決定と訣別すべしと思っているので多田さんとは意見は相違するが)、一度は東大に入れるくらいの知性?だったりする方々が、科学に関すること政治的な意思決定について科学政策の素人として話すと言うことを下位50%に見せる番組としては全然悪くないんじゃないかな。別に結論を出したりする方向性にはもっていっていなかったし。

「極論を出すことで議論が盛り上がるという構成自体は悪くなかった」とは言ったものの、この点について、パブリックな討論のあり方自体について課題を感じた。やしきたかじんが良かったとは思わないが、田原さんも、もともとはもう少しマシだったし、ある程度、日本におけるパブリックな討論の伝統として、「歯に衣着せぬ物言いをする知識人」に物を言わせるということ自体は行われてきた。「そこまで言って委員会NP」の雛壇が知識人かといわれたらふざけんなと思うし、この番組は安倍を呼んでヨイショしていたくらいなので、政治権力に「歯に衣着せぬ」のではなく、リベラル的規範に「歯に衣着せぬ」のを是としている。そこまで言って委員会NP - WikipediaWikipedia 記事にバラエティだから政治発言が許されているとあるが、単に政権に親和的だから許されてるだけでしょう。そこは見る側も「だっせー」くらいの感覚は持っておいてほしい。そして、番組冒頭単なる東大理三を持ち上げていることからわかるように「知識人」の想定レベルが低すぎる。じゃあ、ネットメディアで真の知識人が全方面に歯に衣着せずに討論する番組が可能かというと、なかなか難しい。ReHacQ はちょっとそういう志向と良さを感じる(がひろゆきは切れ味的にもダメじゃないか…?)。ゲンロンは東京都知事選の後の開票雑談みてて、暇空を評価してる宇佐美典也を呼んでまともに相手しちゃってオジさん3人並べて話しているあたりからホモソ臭が耐えられなかった(こういう形でオジさん属性が否定されることに対して東さんは異議申し立てをしていて、まあわかる。今でも「弱者男性」でさえ救うべきだし無駄に攻撃する必要はないとは僕も思っているし(cf .

)、自分の"弱者性"を盾に攻撃しているツイフェミはガシガシブロックしているけれど、ま、相手することや表に出すことが必要じゃないわな、「治療」が必要なのであって。暇空やその支持者は完全そういう対象でしょう)。

オープンさをこの国で実現するのに「歯に衣着せぬ」の必要性はわかるけど、もう少し違う形で、「オープンでパブリックな討論のあり方」を発明していきたいと思う。前職・現職で少しそういうことに取り組む機会は得てきているし、最近、LLMの発展を活かす形で、人工知能学会の友人も2ちゃん研究で盛り上がった頃の心を思い出して、そういうテーマに取り組んでいるのを見たので、俺もやるぞーってね。

「二合半」の読みと意味

Androidスマホでホーム画面左に「Google Discover」というニュースフィードのようなものがあって、そこでたまにくだらない記事を読んでしまう。

「二合半」はなんと読むでしょう?

QuizKnock 見てる勢なので答えは知ってるが、そういや用例について色々疑問があったなと思って読んでみる。『現代ビジネス』のサイトだったのだ。『grape』のようなメディアなら「どーせ回答と「なんでこう読むの!?」みたいな市井の反応を紹介するだけで、その理由も書かずに終わるだろう」という期待値なのだが、もうすこしマシだと期待して、大量の広告をかいくぐって読んだら、

正解は「こなから」でした!わかりましたか?

で終わり。本当にクズすぎてリンクも貼りたくない。


代わりに解説すると、一升の半分を「半」で「なから」と呼び、さらに半分を「小半」で「こなから」と呼んだ。…というところまでは知っている。そういう意味で、référent は同じ二合半 = 二合五勺という量である。しかし、「二合半」という文字列を「こなから」と読んだかについては個人的に甚だ疑わしいと思っているのだ。まず国会図書館の次世代デジタルライブラリーで全文検索してもろくに出てこない。逆に二合半をそのまま「にごうはん」と読む例はあり、

家庭の栞 : 教育実話

これは、デジタル大辞泉(from コトバンク)に

2 《1日5合の扶持米(ふちまい)を朝夕二度に分けて食べたところから》武家の下級の奉公人。また、身分の低い奴やっこなどを卑しめていう語。

と書かれているようにこの書籍に限らず言及されている用法である。「五合」で「なから」と読ませる例は全然見かけないし、「二合半」で「こなから」も同様に怪しいのだ。「春夏冬」で「あきない」、「一斗二升五合」で「しょうばいますますはんじょう」(なぜかは各々考えよ)と読ませる遊びと同様の読みだと言われれば、なるほどと思う。そういった、トンチ的面白さも相俟って読みとされているのだろう。もう、現代にはクイズ以外で出てくることはない読みといっても過言ではない。

ちなみに、référent の同一性から生じる難読語は他にも色々あるが、先日帰省した時に「安口」で「はだかす」という地名に出会った。その地域にオオサンショウウオがいたのだけれど、

落合重信氏著の「ひょうごの地名再考」には、「江戸時代、丹波地方では、山椒魚のことをハダカスともアンコウとも言っていたのである。アンコウから『安口』の文字をあてていたが、方言としてアンコウよりハダカスが一般的になってきて、安口(アンコウ)が山椒魚だと知っている人たちが、いつしかこれをハダカスと呼ぶようになったのであろうか」と記載している。

from 「安口」なんて読む? 正解は「大山椒魚」に由来 かつては井戸で飼う風習も - 丹波新聞 孫引きになってすまないが、この丹波新聞の記事は本当によく調べられている。そして砂防ダムで姿を消したというところで、地名から今はみかけない生物が元々多くいたことに思いを馳せることができるという点が明示的にされているのも良い。

さて、二合半が多いのか少ないのかという点については、「少量の酒。こなからざけ。」という語義が辞書に載せられているように「少ない」わけだが、酒に弱い僕からすると、450mlの日本酒なんてとんでもなく多い。傷む前に飲みきることすらかなわない。飲酒量が多かった江戸時代、酒はいくらだったか 日本酒が作られるようになった時代の飲酒事情 (東洋経済オンライン)わが国の飲酒パターンとアルコール関連問題の推移(厚生労働省) を見合わせてみると、そんなに現代と変わらない飲酒量だったようで、ただ、酒の種類の大半が日本酒だった(日本酒というのはだから、レトロニムだよね)とはいえ、やはり二合半の日本酒を「すくない」の代名詞として使える気はしない。水割り日本酒のルーツは江戸時代!その理由と蘇った江戸酒を紹介 (日本酒ラボ) 当時のアルコール度数はもっと低かったとなって合点がいった。徳利は一升が基本で五合が最低ラインだった(現在は1〜2合 貧乏徳利・牡丹徳利【うまか陶】)というのも、人間の耐性がそう簡単に変わるわけはないので、度数の説を後押しする。「最近の若者は酒が飲めないじゃないか。昔はもっと飲んでたんだよ」って?前掲の厚労省のデータを見るといい。

同じ物理的な二合半を指していても、そこに乗った気持ちは異なる。あとは小吉は吉より下なのは小江戸より江戸が江戸なんだから当然だし、算術の教科書に二合半がたくさん出てくるのは Quarter 貨幣があるように二合半というのは身近な単位だったというのとか、「二号はん」とかけてお妾さんを指す用法があったとか(これマジ?)、諸々含めての二合半なのである。

「明けの明星」と「宵の明星」。これらは「同じ」なのか。ゴットロープ・フレーゲは言う。それらの「意味」(Bedeutung)は同じであると。しかし、それは意味が同じというだけである。彼は明確に、それらの「意義」(Sinn)は違うという。

from 「意義と意味の哲学」日本哲学会


「二合半」を「こなから」と読む、それだけでは、二つの signifiant の繋がりを知識化しただけにすぎない。「中国語の部屋」みたいな時代遅れな例えを出さずとも、文脈を encode してなければ、文脈を decode できないよねという話。実は、表層的に確認できる意味理解なんてものは、その程度でしかなくて、その元データとしての現実世界との繋がりを作れるのは現実と情報のインタフェースとしての身体を持った存在だけだけど、それも別にロボットでもできること。

ちなみにこの記事のタイトルについてのAI推薦は以下の通り↓ソーシャルメディアはバカの言い換えか。

LLMと暮らしたい

いま、村を作るとして、世の中からランダムに100人集めるのと、LLMを内蔵したロボット100台と暮らすのとどちらがいいか?1年前なら確実に「そりゃ人間に決まってるじゃん」と言っていたと思う。そもそもロボット100体と暮らしても孤独だ。でも、この1年、人間社会への失望を深めた結果、「どっちも嫌だな。人間40人とロボット60台という選択肢は無いかい?」と聞きたくなってきている。もちろんLLMの進化も一因。相対的に、世の中の平均より、社会構成員として望ましいものが作れるようになるだろうと思えるようになった、のだ。これまで多くのフィクションがロボットが人間社会の一員になることを描いてきた。そこにはロボットの邪悪さを取り除けるかやロボットに心はあるかといった問題を取り扱ってきたが…「邪悪で心が無い」人間に溢れている社会の中で、その問いは相対的に意味を為さなくなってきた。もちろん、僕は、人工知能を使って人間を適切に再教育することの方が、人間を排除するよりは望ましいと思っているけれども、もう、少なくとも、身分階層化された社会、次善的な平等に扱われた生身の人間の社会、どちらも終わりにしようって思ってる。諸事情でアメリカのTwitterアカウントを観察しつづけたこともそういう失望の一因になってるんだから、日本ならマシではあるのかもしれない。人工知能学会に行った後とは思えない(?)人工知能の雑な礼賛に聞こえるかもしれない。でも、まあ、メタに共同認識された社会問題を解くために適切に社会の舵取りに人工知能が組み込まれることは必須で、日本はそれが受け入れられやすい素地があると思う。たとえば、フランスなんかよりずっとずっと。2024年5月末日、とりあえずそういう方向に向けてさまざまを考えることにした。このメモの題名をAIに考えてもらったら「ディストピアへの旅」だってさ、上手だね。

ブラウザのデベロッパーコンソールで use strict した場合の振る舞いについてのメモ

基本的に、1回のコマンドでスコープが区切られているので、

"use strict"

a = 3

を別々にやると特にエラーが出ずに、

"use strict"; a = 3

でエラーがでるようになります。


また、以下3つではWindowオブジェクトが返りますが

(function() { console.log(this)} )()

'use strict'; console.log(this);

console.log(this)

以下だけ undefined が返ります。

'use strict'; (function() { console.log(this)} )()

これは

(function() { console.log(this)} )()

を理解するのが肝ですね、strict じゃなければ勝手に外側の this を引き継いじゃっている。