2025-05-07
人とAIの関係性を設計しよう Embedding / Copilot / Agent の三類型
自分が作るプロダクトの中で、人間とAIはどのような関係性を築くのか?
壮大なテーマに聞こえるかもしれないが、実はプロダクト開発における実務的な問いだと思っている。もう少し現場的にいえば、「人間に対して、AIをどのような位置に立たせて仕事をさせるか」ともいえるかもしれない。ユーザー体験やプロダクトの意味合いは、この設計次第で大きく変わってくる。
この問いに向き合うためのフレームとして、僕が最近出会って腑に落ちたものを紹介したい。中国のあるデザイン系メディアで紹介されていた「人間とAIの協働における三類型」という整理だ。以下の図は、そこで紹介されていたものを僕が翻訳し、わかりやすくするために少しだけ改変したものである。
この図では、人とAIが協働する際の関係性をEmbedding(裏方)、Copilot(共同作業者)、Agent(代理人)という三つの型で捉えている。タスクの進行プロセスを縦に示し、それぞれの協働スタイルを横に並べた形だ。
Embedding(裏方):AIが部分的に人間のタスクを補助するモード
作業の大部分はユーザーが主導し、AIはその中の一部の工程、情報検索や判断材料の提示といった領域で、さりげなく手を貸す。ゴールの設計や意思決定、最終的な実行はあくまでユーザーが担っており、AIはタスクの断片にだけ「埋め込まれて」いる。たとえば、フォームの自動補完、スマートな並び替えの提案、画像の自動補正、検索時のキーワード補強などがその例だ。大抵の場合、ユーザーはAIを「操作している」という感覚すら持たないことも多く、なんとなく便利、くらいの感覚で使われている。
Copilot(共同作業者):AIが人間と並走し、随時サポートや提案を行うモード
作業の主導権はユーザーが持ちつつ、AIはその過程で「一緒に考える相手」として振る舞う。タスクの中で特定の処理を代わりに行うこともあるが、その成果物はユーザーの確認・修正を経て進められる。GitHub CopilotやNotion AIのように、ユーザーが言語化した意図を受け取り、それに応じたアシストをしてくれる例がこれにあたる。
Agent(代理人):ユーザーが目的を設定したあと、AIがその達成に向けてタスクを分解し、適切なリソースや手段を選びながら自律的に進めていくモード
ユーザーは起点のアクションと最終確認を担うが、途中の過程ではAIが代理人として意思決定し、進行する。AutoGPTのようなツールがこの例にあたり、ユーザーは「何をしたいか」を伝えるだけで、AIがステップを設計し実行していく。頼もしいけれど、ちょっと怖いと感じる人もいるかもしれない。SF映画ではだいたい人類を滅ぼしにかかってくる。
この三類型の整理がよいのは、AIの能力の高さや技術的な洗練度ではなく、「協働の構造」にフォーカスしているところだ。僕は、プロダクトの本質はこの協働の構造にあって、AI自体の技術力はその上に乗っかってくるパワーのようなものだと思っている。パワーでの戦いは、資本力の高いところに勝つのは難しい。しかし協働の構造を工夫するところには、ベンチャーにも戦える余地があると思う。
プロダクトにAI機能を実装するときには、この図を参考にして、ユーザーとAIの間にどんな関係性を築いていくのかを十分に議論するようにしていきたい。この図は、その議論をふわふわとした抽象論に留めず、図面的設計的に捉えてチームで共有するための叩き台になるはずだ。
そうした議論の延長として「関係性のフェーズ移行を設計する」ということも考えられるだろう。新しい機能は最初Copilot型でユーザーと一緒に試行錯誤しながら信頼を得ていき、一定の慣れが生まれたタイミングでAgent的な動きを提案していく、というような段階的な設計の可能性だ。協働のあり方を、固定された型ではなく、関係性の成熟に応じてシフトするものとして捉えてみると、より実用的な設計ができる気がする。
また、「関係性を構築する」というのは、「継続的な視点を持つ」ということでもある。人間同士がそうであるように、関係性はある程度の時間の中で育っていくものだからだ。実際の関係構築というのは、ドラマの脚本のように設定を与えれば完了するわけではない。このことは、自分の身の回りの関係が、「最初の印象」なんかよりも「どう付き合い続けてきたか」の方が強く影響していることからも分かるだろう。特に、ある関係のあり方を意図的に目指すのであれば、より計画的な取り組みと、適時の調整作業が必要だ。
関係性は持続され、反復されることによってのみ成立する。「関係性」とは一定の距離感と進入角度のことを指すのではなく、二者の接触によってその都度、距離感と進入角度が共創的に試行錯誤し続けられる「状態」のことを指すのだ。
(宇野常寛、2022『砂漠と異人たち』朝日新聞出版)
美涼は、それはそんなに難しくないという顔で、
「わかったってところから、また愛し直すんじゃないですか? 一回、愛したら終わりじゃなくて、長い時間の間に、何度も愛し直すでしょう? 色んなことが起きるから。」と言った。
(平野啓一郎、2018『ある男』文藝春秋)
まだまだAI機能のデザインは始まったばかりなので、これからいろいろとAI搭載のプロダクトを作っていけば、より詳細な類型化もできるかもしれない。もとより人と他者の関係のあり方は一様ではないし、型通りのもので終わる話でもないだろう。AI機能を観察するときに「この機能は、人とAIをどのように協働させるものなのか」という問いを持つことで、僕たちはより実務的なデザイナーの目を養うことができると思う。
どうすればAIとの関係が、日々の営みに溶け込んで、自然にそこにあるものとして続いていくのか。使えば使うほど馴染んでいくような関係性は、どうしたら作ることができるのか。そんなことを話し合って設計された機能こそが、ユーザーに利便性以上のものをもたらし、プロダクトの価値を高めていくはずだ。
2025-05-09
今日のハイライト: 2025/05/10
台湾といえば、やっぱり肉粽(ちまき)だと思う。
あの笹の香りともち米のずっしり感が、土地の空気と結びついている感じがする。台北だったら王記府城の肉粽が最高だ。
そして今日、初めて気づいたのだが……
肉粽、コンビニでふつうに売っていた。
さすが台湾すぎる……!
台湾のコンビニ飯でいうと、僕がめっちゃ好きなのが麻油鶏(マーヨージー)のおにぎりだ。
麻油鶏とは、台湾のスープ料理である。それがおにぎりの具材になっている。どうだ、混乱するだろう。
でも食べてみると、ちゃんと米の食感の中から麻油鶏の味がしてくる。いったい何が起きているのか分からない。戸惑いと感動が同時に襲ってくる。
稲田俊輔が、日本料理で「旨味」が重宝されるように、南インド料理では「マズ味」(酸味やエグ味)がうまく使われている、と言っていたが、僕は台湾で暮らして初めて「苦味っておいしいんだな」と感じるようになった。
そのことを強く実感した料理が二つある。その一つが麻油鶏だ。このおにぎりがおいしいのも、麻油鶏特有の薬膳の苦味が味わえるからだと思う。もう一つは忘れた。思い出したらまた書こう。
冬に食べる麻油鶏は最高だが(この冬、僕は抑えきれず週三ペースで麻油鶏を食べ、露骨に太った)今日くらいの暑さだとちょっと厳しい。そういうとき、お手軽に麻油鶏の味を楽しむためのものとして、このおにぎりは本当に大発明だと思う。マジで痩せる暇がない。
2025-05-17
今日のハイライト: 2025/05/17
岩首で、大石さんの田植えを手伝ってきた。
僕は農作業や庭仕事の類が昔からあまり好きじゃない。が、坐骨神経痛とヘルニアを同時にキメた高齢の友人のために、腹を括って鉛のように重たい腰を持ち上げて行ってきた。
台湾から帰国してまだ数日、じんわり疲労感が残る身体は、田んぼの泥に優しく沈み込む。
夜、浅井と海野と三人で麻雀を打った。日本で打つのは今年初めてだ。
台湾麻雀の癖が抜けず、なんだか随分とガサツな打ち回しになってしまった気がするが、三麻という懐の広いルールに甘えてなんとかプラスで終えることができた。
それにしても、卓についてるのは自分なのに、どこか他人が打っているのを後ろから眺めているような、ふわっとした感覚が終始あった。
浅井とは、年に一、二度、佐渡でしか会わない。たったそれだけの付き合いだが、わざわざ佐渡の山奥に来る同世代というだけで、妙なシンパシーがある。ニッチな推しが被ってるような感じだ。
去年の秋、僕は佐渡に向かう理由の半分くらいを「浅井に会うこと」に置いていた。中秋の島の静けさの中で、言葉を少しずつ渡し合いながら、何かしら確かめたかったんだと思う。浅井との対話にはそういう力がある。
ところが、いざ会ってみると彼は終始酒に酔っていて会話が成立せず、挙句、酒を飲まない僕に「人生の半分は損してる」と、テンプレのような泥酔口撃を繰り出してきた。最悪である。
正直かなりがっかりしてしまったので、今回一緒に佐渡で過ごそうという話になったとき、ついその件についてきつめの物言いをしてしまった。
浅井は酒量をぐっと控えてくれて、結果として穏やかでいい時間を過ごせた気がするのだけど、でもその裏に、彼なりの「抑え」があったのだとしたら、僕たちの関係性は少し無理のあるかたちになっていたのかもしれない。
田舎で酒飲みと過ごすときのいいやり方を、もう少し考えたい。
2025-05-17
今日のハイライト: 2025/05/18
昨日に引き続き、今日も朝から農作業。
早起きして張り切った甲斐もあり、昼過ぎには予定の工程を終えることができた。これで大石さんの田んぼは一通り完了、あとは補植を残すのみ。ひとまず助っ人としてのミッションは達成である。
午後は、佐渡島で音楽ライブができそうな場所を探して、いくつかの候補地を回った。Chooningで検討中の企画だ。
なかでも良かったのが、椎崎諏訪神社の能舞台。
その名の通り能を演じる場所だが、ステージとしての風格もあるし、観客席もちゃんと取れそうなスペースがある。実際に音楽イベントで使われた実績もあるとのこと。両津港からも近くて、周囲の宿泊施設も充実している。
加茂湖を見下ろす高台にあって、奥の方からは夕日が湖面に沈むところも見える。うまくいけば、夕暮れと音楽とが重なる瞬間がつくれるかもしれない。
しかし、ちょうど視察を終えたあと、イベント実施のためにアテにしていた資金の話が立ち消えになったという報せが入った。
\(^o^)/
2025-05-18
今日のハイライト: 2025/05/19
佐渡汽船の売店で、なんとなく手に取った笹団子がめちゃくちゃうまかった。
冷凍されたものを持ち歩いていたら自然解凍されたんだけど、それがよかったのかもしれない。
2025-05-22
インクトラップ(Inktrap)
「インクトラップ(Inktrap)」というタイポグラフィの技術に関するメモ。
作成する際のコツ
インクトラップを効かせる箇所は、細くて、鋭くて、潰れやすいところ。要するに「詰まりそうなポイント」に余白を仕込むとそれっぽく見える。
- 内側の鋭角コーナー:ストローク同士がぐっと狭くなる部分。たとえば、セリフと縦線が交わる接合点など。
- 終筆(ターミナル)の先端:細い線がふっと途切れる箇所(細ければ細いほど印刷時に潰れやすい)。ここにほんの少し切り欠きを入れると、線が残ることになる。
- セリフの付け根:水平のセリフと縦のストロークがぶつかる部分。細くなればなるほどインクのにじみで潰れやすくなるので、ここも空間を残しておく。
- ストロークの交差点:「×」とか「+」のような、線が中央でクロスするところ。見た目が黒く濁りがちなので、中心にわずかに隙間を入れる。
- 細いハネやカーブの端:筆記体っぽい書体で、カーブが直線に移る細いところ。
メモ
インクトラップとは、文字の角の部分や接合部などにあらかじめ「へこみ」を設けておくことで、印刷時にインクがにじんでも、視覚的なバランスが保たれるようにするデザイン技法。とくに小さいサイズや粗い紙に印刷することを想定したフォントでは、文字が潰れてしまわないよう、あらかじめ余白を確保しておく必要があった。その発想から生まれたのがインクトラップである。
現代の高解像度ディスプレイではこのような工夫は不要だが、逆に「意図的にインクトラップを残す/見せる」というデザインが登場している。かつての「印刷のための工夫」が、いまは「造形的な魅力」として再解釈されている点がおもしろい。
デザインにおいて、「かつての制約が生んだ造形」が「いまの美意識」に読み替えられる、というのはよくあることで、同じようにフォントでいえば、セリフ(もともとは金属活字の筋の弱い細線を補強するための「足」だったが、いまはクラシックさや安定感を象徴する装飾要素になっている)や、和文フォントのウロコ(筆で書く際の運筆の名残だが、いまでは和風の空気感を醸す装飾要素になっている)がそうだし、Webやアプリのデザインでよく採用されるグリッドレイアウトも、かつての組版や紙面整理の都合から生まれた構造が現在になって「モダンデザインの骨格美」として愛され、再活用されているものだ。
近過去を採用したものでいえば、Y2K(1990年代後半〜2000年代前半の限られた3D表現やCG技術、Webの表示制限が生んだチープな未来感が、いまでは懐かしさとフィクショナルな未来像のミックスとして再評価されている)やピクセルアート、チップチューンなども挙げられる。
https://www.youtube.com/watch?v=SiTazCUPBGM
エンジニアのスキルというのは、一度身につけた技術が数年後もそのまま使えるとは限らず、むしろ過去の知識が通用しなくなることのほうが多い。だからこそ、常に学び直しが求められるし、若い世代がベテランを凌駕するチャンスがあったり、その延長線上にベンチャーの勝機があったりもする。
つまり、不要になった技術的な工夫(iモード向けのサイト構築とか、Flash制作、IEへの個別対応とか……うっ、頭が……)というのはどんどん積み重なっていくわけだが、でも、そうした過去の制約下で生まれた工夫をあらためて掘り起こし、技術的な意味は失われても装飾的な意味で再利用する、ということができるのはデザイナーなんじゃないかと思う。
いったん役目を終えた技術を、意匠としてもう一度連れてきて、再解釈の文脈に乗せる。むしろ、技術が意味を失ってからのほうが、デザインとしては面白くなることもあるかもしれない。こういうところはまさにデザイナーの腕の見せどころだろう。
技術にもある程度詳しいデザイナーとして中年に差しかかるいま、こういう視点はこれからずっと使えるんじゃないか……と、思ったりしている。
参考
2025-05-22
Mattermostをセルフホスティングする
Mattermostとは
Mattermostは、Slackに似たUIを持つ、オープンソースのコラボレーションツールだ。
自分たちでサーバーを用意して運用する「セルフホスティング」に対応しており、ユーザー数や機能に応じて課金されることなく自由に使うことができる。すごい。これでSlack重税ともおさらばや!!
https://mattermost.com/
Mattermost(セルフホスティング)でできること
- 基本的なチャンネルベースのチャット(Slackと同様のUI)
- ダイレクトメッセージ
- チャンネルの公開設定(オープンチャンネル or プライベートチャンネル)
- スレッド形式での返信
- メンション @here, @channel, @username など
- 画像・PDFなどの添付&プレビュー
- iOS / Androidアプリあり(Mattermost公式)
- 投稿内でのMarkdown記法対応
- Bot / Webhook: Incoming / Outgoing webhookあり
- Plugin / Integration: Trello、GitLab、Jiraなどの連携プラグインあり
Mattermost(セルフホスティング)でできないこと
- 音声通話: Slackのハドルのようなものは標準では非搭載(プラグインが必要)
- 画面共有: 上記のプラグインを使っても画面共有はできない
- SAML / LDAP: Enterprise Editionならできるっぽい
- 監査ログ / EMM連携: Enterprise Editionならできるっぽい
Slackの利用料を払うのが難しい規模のプロジェクトでは、Discordが使われることが多いと思う。
ただ、個人的にはDiscordのスレッド返信がどうにも使いづらく、結果としてテキストでのやり取りが整然と進められないのがずっと気になっていた。Mattermostではその点がしっかり解消されており、チャンネル内での会話の整理がしやすそうという印象。一方で、Discordのような「ゆるくつながる」音声通話のスタイルを大事にしたい場合には、Mattermostは少し堅すぎるというか、そういう用途にはあまり向いていない。
「本当はSlackのようなスタイルのコミュニケーションをしたいのだけど、仕方なくDiscordを使っている」というようなプロジェクトには、Mattermostはちょうどよい選択肢になると思う。
早速環境を用意してみたので、以下作業メモ。
1. サーバーを用意する
さくらのVPSで 4Gプランを契約(記事執筆時で月額3,960円。年払いだともう少し安くなる)。
OSはUbuntu 22.04を選択。IPアドレスが払い出される。
https://vps.sakura.ad.jp/
契約後、コントロールパネルにアクセスしてサーバーを起動
https://secure.sakura.ad.jp/vps/servers
2. SSHでログインしてセットアップ開始
ssh root@<VPSのIPアドレス>
最初に自動生成されたパスワードを使ってログイン
3. 初期設定&Dockerの導入
sudo apt update && sudo apt upgrade -y
sudo apt install -y docker.io docker-compose
sudo systemctl enable docker
4. Mattermost用ディレクトリの作成
sudo mkdir -p /opt/mattermost
cd /opt/mattermost
5. docker-compose.yml の作成
sudo nano docker-compose.yml
version: "3"
services:
db:
image: postgres:13
restart: always
environment:
POSTGRES_USER: mmuser
POSTGRES_PASSWORD: mmuser_password
POSTGRES_DB: mattermost
volumes:
- ./volumes/db:/var/lib/postgresql/data
app:
image: mattermost/mattermost-team-edition
restart: always
ports:
- "8065:8065"
environment:
MM_SQLSETTINGS_DRIVERNAME: postgres
MM_SQLSETTINGS_DATASOURCE: postgres://mmuser:mmuser_password@db:5432/mattermost?sslmode=disable
MM_SERVICESETTINGS_SITEURL: http://<VPSのIPアドレス>:8065
volumes:
- ./volumes/app/mattermost:/mattermost/data
depends_on:
- db
nanoの保存コマンド: Ctrl + O → Enter → Ctrl + X
6. コンテナの起動
sudo docker-compose up -d
7. サーバーのパケットフィルターを設定
ポート 8065 でアクセスしたいので、パケットフィルターを設定する。ついでにこのあと必要なポートも登録しておく。
8. 動作確認
ブラウザからVPSのIPアドレスを直叩きしてアクセス!
http://160.16.197.152:8065
9. サブドメインの割り当て
ドメイン管理サービスでDNS設定
host: chat
type: A
data: 160.16.197.152
Google Domains亡きあと、惰性でSquarespaceを使い続けているけれど、ずっとCloudflare Registrarに移行したいと思っている。(こういう地味な作業に腰が上がらなくなるの、確実に加齢の兆候だと思う。)
10. Nginxでリバースプロキシを設定
Mattermostのポート8065番を、標準の80番/443番(HTTPS)に乗せかえる必要がある。
Let’s Encryptは、ポート80(HTTP)を使って認証するため、Mattermost が直接 8065番で動いてると認証できない。そこで、Nginxで80番を受付けてMattermostに中継(proxy)する形を取る。
sudo apt install nginx
sudo nano /etc/nginx/sites-available/mattermost
server {
listen 80;
server_name chat.chooning.app;
location / {
proxy_pass http://localhost:8065;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
有効化
sudo ln -s /etc/nginx/sites-available/mattermost /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
SSL化(HTTPS対応)
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d chat.chooning.app
メールアドレス入力、利用規約に同意、リダイレクト(HTTP→HTTPS)を Yes に。
11. 動作確認
割り当てたドメインにブラウザでアクセスして確認
http://chat.chooning.app
2025-05-23
今日のハイライト: 2025/05/24
赤レンガ倉庫のテラス席で、Greenroomの音漏れを聞きながら作業していた。海風に乗って届くベース音がちょうどよくて、結構な特等席だ。
このGreenroomに参加するため、京都からふみちゃんがやってきたのだが、昨夜、駅からうちに来るまでの間につまずいて顔面を強打し、なんと前歯が折れてしまった。「欠けた」のではなく、まさにバキリと「折れた」のである。痛すぎる。
合流したときには顔面血まみれで、思わず2メートルほどのけぞってしまった。「駅まで迎えに行くよ」と僕が言っていたのに手が離せず、一人で来てもらったタイミングでの出来事だったので申し訳なさがすごい。
それでもふみちゃんは今朝から歯医者及び外科の治療を受け、アンパンマンの絆創膏を顔に貼って音に合わせて踊っていた。愛と勇気の健気なミュージック・ラバーである。ジャムおじさんに新しい顔を投げてもらいたい
2025-05-24
Hugo v0.125以降で _index.md を使ったセクションページが表示されなくなった件
Hugoでは、content/about/_index.md のようなファイルを配置することで、「about」というセクションのトップページを作ることができる。WordPressでいえばカスタム投稿タイプのアーカイブページ(一覧ページ)に近い仕組みだ。セクション全体の紹介や記事一覧に使われるページで、Hugoの用語では「セクションページ(Section Page)」または「ブランチページ(Branch Page)」と呼ばれている。
例えば、僕のサイトでは、
ezeroms.com/about/about/ezeroms.com/about/work/ ezeroms.com/about/diary/ ezeroms.com/about/shoulders-of-giants/
といったURLで表示されるページがそれにあたる。
で。今日このサイトを更新していたら、それらのセクションページが突如表示されなくなった。この記事では、その原因と解決方法を記録しておく。
問題の背景
Hugoでは、contentディレクトリ以下にあるMarkdownファイルが、layouts以下にあるテンプレートによってHTMLに変換(=レンダリング)される。
具体的には、以下のような構成だ。
content/
about/
_index.md
diary
_index.md
shoulders-of-giants
_index.md
work
_index.md
layouts/
about/
index.html
diary
index.html
shoulders-of-giants
index.html
work
index.html
content/about/_index.md
---
title: "About"
layout: "index"
---
ここにコンテンツを書く
layouts/about/index.html
<section>
<article>
{{ .Content }}
</article>
</section>
このように、Markdown側では layout: "index" を指定し、Hugoはそのレイアウトに従ってHTMLを生成してくれる。つまり、コンテンツは.mdファイルに書き、構造や見た目は.htmlテンプレートに記述することで、Markdownさえ書ければWebサイトが更新できるようになる。
この仕組みによって、例えばDecapCMSのようなヘッドレスCMSを使えば、mdファイルの編集だけでサイトの更新が可能になる。出力されるのはあくまで静的な html ファイルだが、裏側では動的にCMSを運用しているような体験が得られるのだ。
しかし今回localでbuildしたところ、buildは正常に完了したものの、該当するセクションページのHTMLが生成されない(「意図したファイルが public/ 以下に出てこない」)という問題が発生した。
原因:Hugoのアップデートでテンプレート解決が厳密化
今回の原因は、Hugoの仕様変更(v0.125以降)によりテンプレートの解決ルールがより厳密になったことだった。最近Macを新しくした際にHugoも最新バージョン(v0.134.1)でインストールし直したため、この問題が表面化したのだろう。
以前のHugoでは、_index.md に対して layout: "index" を指定していても、なんとなく layouts/about/index.html が使われていたのだが、最新のHugoではそのような曖昧な解決が効かなくなり、テンプレートは適切な名称でなければならなくなった。というか、そもそも僕は index.html が適切な型名でないことを今回調べて初めて知った( ^ω^)
index.md file rendering correctly then overwritten by default single.html | Hugo Forums
解決策:テンプレートファイル名とレイアウト指定の変更
以下のように修正したらセクションページが表示されるようになったよ\(^o^)/
テンプレートファイルのファイル名を変更
# 修正前
layouts/
about/
index.html
diary/
index.html
shoulders-of-giants/
index.html
work/
index.html
# 修正後
layouts/
about/
list.html
diary/
list.html
shoulders-of-giants/
list.html
work/
list.html
Markdownファイル内のレイアウト指定を変更
layout: "index"
layout: "list"
2025-05-25
今日のハイライト: 2025/05/26
KJと、鶴屋町に新しくできたスシローに行ってきた。
台湾から帰ってきて以来、回転寿司ばかり行っている。カウンターの向こうから次々に流れてくる小皿を思考停止で迎え撃ちたくなる日々が続いているのだ。
どうでもいい話だが、僕は大学生になるまで回転寿司に行ったことがなかった。
僕の両親は、回転寿司を寿司と認めていなかった。「こんなものを子どもに食べさせるなんてありえない」という、かなり強めのポリシーがあったように思う。ちなみにファミレスの類もNGだった。(そのため、僕が中学生で初めてひとり旅をしたとき、まず最初にしたことは「ファミレスに入って巨大なパフェを注文すること」だった。)
両親の頭の中では、「回転寿司 = 本物の寿司の廉価版」みたいな構図があったのだと思う。でも、実際のところ(多くの人が体験的に知っているように)回転寿司は寿司の下位互換なんかではなく、まったく別の料理であり、別の体験であり、「外食エンタメ」として独自の進化を遂げた産業でさえある。
回転寿司で回っているのは寿司ではない。寿司に擬態した何かである。これは「本物の寿司に味が劣る」という話ではなく、位相の違いだ。
江戸前寿司が食文化としての伝統を継承する場だとすれば、回転寿司は外食エンタメの革新と最適化の場である。そこに求められているのは固定化された「寿司」の質を高めることではなく、「楽しくて、ついもう一皿取りたくなる工夫」なのだ。
たとえば、回転寿司のサーモンにはチーズが当然のような顔で乗っている。軍艦にはコーンマヨやツナマヨが詰められている。タルタルソースが惜しみなく盛られたえび天や、イベリコ豚、ローストビーフ、ハンバーグ寿司なんてのも回ってくる。逆輸入されたカルフォルニアロールや、韓国料理のキンパなど、他国の料理のエッセンスが無邪気に紛れ込んでいる。メニューには唐揚げやフライドポテト、ラーメン、ハンバーガー、たこ焼きなんてのもある。祭りの屋台を眺めているような気分だ。
プリン、コーヒーゼリー、ガトーショコラ、みたらし団子、フレッシュパインなど、甘味の世界も広がっている。突如パチンコ的演出が発動し、オモチャが転がり落ちてくる。飯を食っていたらカプセルトイがもらえるのである。もはや食事という行為が拡張されている。注文はタブレット、配達は非接触の専用レーンで高速到着するなど、衛生面やユーザー体験に配慮された技術のアプリケーションとしてもかなり成熟している。これはもう近代日本の食と遊びと技術が交差した、総合アミューズメント施設といったほうがいい。そこにあるのは格式ではない。発明なのだ。
したがって、僕の両親が回転寿司を「寿司の代用品」として拒んでいたのは、たぶん的外れだった。ただ、決して頭が固い方ではなく、こうした面白さが伝わる感性はあると思うので、いつか油断しているときに回転寿司に連れ込んでやりたいと思っている。
さて、寿司をつまみながら、KJからTikTokの「#founderstory」というハッシュタグの話を聞いた。
#founderstory とは、スタートアップを立ち上げた人が「ハーイ! 私の名前はイヴァンカ。先週Googleを辞めて新しいプロダクトを立ち上げたの」「身の回りにあるこんなf**kingな課題をどうしても解決したくなったからね」「今日から100日でこの課題を解決するサービスを育てていくから、その様子をみんなにシェアしていくね〜!」みたいなノリで投稿する、マーケティングを目的とした動画コンテンツに付けられるハッシュタグのことらしい。
まだ自分でちゃんと確認したわけではないのであまり分かったフリをしないようにはしておきたいが、とりあえず僕はこれを「物語消費的なものの一形態だな」と理解した。ナラティブのスナック化だなあ、などと思う。
「AIが台頭してくる中で、『人(ニン)を売る』ことがますます重要になってくる」
「プロダクトにおける『人(ニン)の含有量』をどう増やすかなんだよ」
KJの持論には頷けるところが多い。たしかにその通りだろう。AIが機能を量産する時代には、つくった人間の顔つきや手触りが、判断材料としていっそう重要になるのだと思う。
僕はこの手の起業家の試行錯誤的ジャイアントキリング物語が大好きなので、それがたとえマーケティング用に巧妙に編集されたものであったとしても、けっこう好んで見てしまうと思う。もしKJのような友人がやっていたら、応援がてらフォローして、日々の進捗を楽しくウォッチするだろう。
ただ、それを自分がやるか(たとえばChooningのプロジェクトについて「100日間でやってみる」的な発信をするか)と問われると、たぶんやらない気がする。
僕も情報発信に無関心なわけではないし、言葉を届けようとする意志は持っているつもりだが、自分の主戦場はやはりこういうブログのような、ある程度まとまった文字量を使って、自分の考えや感覚を丁寧に差し出せる場所でやっていきたいと思っている。
これはリアルなコミュニケーションにも通じるのだけど、SNSにおける「いいね!」ボタン的な賛意や同調、それから服屋の「こちらお似合いですね!」のような、言っている内容そのものよりも会話を円滑に進めるためだけに存在している言葉をどれだけもらっても、僕はあまり心が動かない。できればもう少し時間をかけて、相手がこちらの言葉を受け取り、それを自分の思考や感覚のなかに通した上で返してくれるようなやり取りのほうが、僕にとってはずっと心地いい。
思うに、僕が大事にしたいのは、情報の交換というよりも思考の共有なのだろう。その人自身の文脈を通じて構築された返答を受け取ったとき、ようやくそこに対話が生まれている気がする。お互いの価値観や語彙、ものの見方を一時的に借り合うような、相手の頭を通してもう一度自分の言葉に出会い直す、そういうコミュニケーションのあり方が好きだ。
もちろん、反射的なリアクションが悪いわけではないし、そこにはそこにしかない温度や励ましがある。けれど、自分の感受性のあり方として、そういったもので満たされる領域はあまり多くないのだと思う。
できることなら、「僕の言葉をどう受け取ったか」を、相手の論理や感情の構造ごと見せてもらえるような、そういうやり取りの中に身を置いていたい。
2025-05-28
Suchmos is back!!!!!!
2025-05-29
MattermostのWebSocket接続エラーを解決した
MattermostにBoards(旧・Focalboard)のプラグインを入れる作業をする過程で発生したエラーに関する備忘録。
プラグインをインストールしてBoardsのUIが表示されたまではよかったのだが、その画面上部に次のようなエラーが表示された。
WebSocket connection closed, connection interrupted.
If this persists, check your server or web proxy configuration.
チャンネル(プロジェクト)やタスクをクリックしても何も起きない。タスクの新規作成はできるが編集はできないなど、部分的にできることできないことがあり、明らかに壊れている様子でもある。いろいろと検証した結果、これは「Boardsのインターフェースは立ち上がっているが、WebSocket通信が失敗していて機能していない状態」だろうということが分かった。以下に対処方法を記録しておく。
原因その1:NGINXの設定ミス
まず、リバースプロキシとして動作しているNginxの設定がどのようになっているかを確認する。
※ Mattermostはデフォルトではポート8065番で動作しているが、それを https://chat.chooning.app のような独自ドメインで扱うには、外部からのリクエストをNginxで受け取り、Mattermost本体に転送する必要がある(=リバースプロキシ)。
その設定が有効になっているかを確認するため、有効なサイト設定ファイルの一覧を表示。
ls -l /etc/nginx/sites-enabled/
/etc/nginx/sites-enabled/ は、Nginxが読み込むサイト設定ファイルへのシンボリックリンクが置かれている場所。 /etc/nginx/sites-available/ にある設定ファイルのうち、実際に有効にしたいものをシンボリックリンクとして /etc/nginx/sites-enabled/ に格納することで、設定が反映されるようになる。
/etc/nginx/sites-available/ : すべてのNginx用の設定ファイルの本体を置いておく場所。まだ有効にはなっていない。/etc/nginx/sites-enabled/ :実際にNginxが読み込んで使う設定ファイルのシンボリックリンクを置く場所。ここにあるファイルだけが、Nginx起動時に読み込まれて反映される。
実行結果。mattermost という名前の設定ファイルが /etc/nginx/sites-available/mattermost からリンクされていることから、Mattermost用のNginx設定が有効になっていることが確認できる。
default -> /etc/nginx/sites-available/default
mattermost -> /etc/nginx/sites-available/mattermost
本体の設定ファイルの中身を確認。
cat /etc/nginx/sites-available/mattermost
server {
server_name chat.chooning.app;
location / {
proxy_pass http:
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/chat.chooning.app/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/chat.chooning.app/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
設定ファイルの中に、HTTPからWebSocketへプロトコルをアップグレードする際に必要なヘッダー項目が抜けていることが分かる。これがないとWebSocket接続が確立できない。
修正
server {
server_name chat.chooning.app;
location / {
proxy_pass http://localhost:8065;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/chat.chooning.app/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/chat.chooning.app/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
Nginxを再読み込み
sudo nginx -t
sudo systemctl reload nginx
原因その2:config.jsonの設定ミス
Nginxの設定を修正したことで「WebSocket connection closed, connection interrupted.」のエラーは解消されたものの、BoardsのUIが動かない現象は解決しなかった。
Dockerコンテナ内に入って、config.json(Mattermost本体の設定ファイル)の内容を確認する。
sudo docker exec -it mattermost_app_1 /bin/bash
cat /mattermost/config/config.json | grep -A 10 ServiceSettings
その結果、SiteURLとWebsocketURLが空であることが判明。この2つの値はMattermostが自身のURLやWebSocket接続先を認識するために必要なもので、ここが空だと接続が正しく行えない。
"SiteURL": "",
"WebsocketURL": "",
修正
sed -i 's|"SiteURL": ""|"SiteURL": "https://chat.chooning.app"|' /mattermost/config/config.json
sed -i 's|"WebsocketURL": ""|"WebsocketURL": "wss://chat.chooning.app"|' /mattermost/config/config.json
コンテナから出て、コンテナ再起動
exit
sudo docker restart mattermost_app_1
上記2つの修正を行ったことで、Boardが正常に使えるようになった\(^o^)/
副作用的に他のエラー(「The server is not reachable.」)も解決した
実はずっとネイティブアプリに「The server is not reachable.」というエラーが表示されていたのだが、WebSocket接続エラーを解決したことで偶然これも解決した。
この通知、初期セットアップ時からずっと表示されていたのだが、Mattermost自体は普通に使えており、フォーラムにも同様の報告が上がっていたので、まあネイティブアプリのバグかなと思って放置していた。しかし実際にはWebSocket接続が失敗していたために表示されていたっぽい/(^o^)\
アプリがある程度は動いていたのは、WebSocketを使わない基本的なAPI通信が問題なく通っていたからではないかと思う。(通知やBoardsなどのリアルタイムUIは動かないが、通常の投稿やチャンネル閲覧などはHTTP通信だけで動作していた、ということなんじゃないかと思う。たぶん……)
何はともあれ、これでBoardsが使えるようになった。Slack的なコミュニケーションとNotion的なやつが同一アプリ内で使えるの快適すぐる!!!!!
Boardのセットアップに関する記事はこの土日に書く。この一週間ですっかりMattermostの虜や〜〜〜