人生の目的が404なので、感情ログから「次に試すこと」を推薦するCLIを作った
人生の目的が分からない。何をして喜ぶのかも、正直よく分からない。
そこで、妙に元気な少年に相談した。彼の手段はだいたい、探すか、集めるか、強くなるか、の三択だ。
少年「人生の目的、どこだ! 探せば出てくるだろ!」
相方「出てくる話じゃない」
少年「じゃあ七つ集めればいいんだな!」
相方「集めるのはお前の妄想だ」
少年「一行書けって、それで人生わかるのかよ!?」
相方「わからない。でも一行ある方がマシだ」
meaning_of_life() を直接呼び出してはいけない
調子が悪い時ほど、でかい問いを投げてしまう。
meaning_of_life()
でもこの関数、要件定義が終わってない。返り値が大きすぎる。テストケースもない。疲れてる時に呼ぶと、いつまでも Loading... のまま固まる。
だから問いを小さくする。
what_should_i_try_next()
「何のために生まれたか」じゃなくて、何をしたあとなら、もう一回だけ試してもいいかな、と思えるかを記録する。
心理学から借りる三つの設計原則
1. 行動してから、反応を観察する
行動活性化は、活動と気分を見ながら生活の行動を少しずつ調整していく考え方。うつ病の心理療法として研究されているが、ここでは治療の代わりじゃなく、日常の小さな実験を設計するための発想だけ借りる。
少年「楽しいこと見つかってから動けばいいんだろ!」
相方「それだと今日は一生動けない」
少年「一生!? そんなバカな」
相方「腹減る前に飯は食えない。待つな。先に一口食ってみろ」
少年「一口!? そんなので強くなるのか!」
相方「強くなる話じゃない。楽だったか、見るだけだ」
2. 喜びを単一指標にしない
自己決定理論では、自律性・有能感・関係性の三つが大事だと言われる。
| 観点 | 日常語にすると |
|---|---|
| 自律性 | 自分で選んだ感じがあったか |
| 有能感 | ちょっと前に進んだ感じがあったか |
| 関係性 | 誰かや何かとつながった感じがあったか |
気分だけじゃなく、この三つもログに入れる。
少年「つまんなかった日は全部0点でいいよな」
相方「それ、お前が勝手に付けてる点数だろ」
少年「じゃあ何を見ればいい」
相方「自律、有能、関係。三つ」
少年「三つ!? めんどくせえ! 一つにまとめろ!」
相方「一つにまとめたら『楽しかったか』だけになる。それがいちばんズルい」
3. 意志を条件分岐に変える
「明日から頑張る」は、まだ実装じゃない。
実行意図は、「状況Xになったら、行動Yをする」という if-then 型の計画。
if lunch_break_started:
walk_for(minutes=5)
気合いを増やすんじゃなくて、行動が始まる条件を決める。
少年「よし、気合い入れた! 明日から本気だ!」
相方「その本気、何時に起動する」
少年「起動……? 朝だ!」
相方「朝の何時」
少年「……起きれた時」
相方「起きれた時に本気、は詐欺だ。昼休みに入ったら外を5分歩け。そこまで書け」
まずはJSONLに記録する
でかいAIはいらない。最初はCLIで十分。
from __future__ import annotations
from dataclasses import asdict, dataclass
from datetime import datetime
from pathlib import Path
import json
LOG_PATH = Path("life_events.jsonl")
@dataclass(frozen=True)
class LifeEvent:
activity: str
energy_before: int
energy_after: int
repeatability: int
autonomy: int
competence: int
connection: int
distress: bool = False
created_at: str = ""
def normalized(self) -> "LifeEvent":
return LifeEvent(
activity=self.activity.strip(),
energy_before=clamp(self.energy_before),
energy_after=clamp(self.energy_after),
repeatability=clamp(self.repeatability),
autonomy=clamp(self.autonomy),
competence=clamp(self.competence),
connection=clamp(self.connection),
distress=self.distress,
created_at=self.created_at
or datetime.now().isoformat(timespec="seconds"),
)
def clamp(value: int) -> int:
return max(0, min(10, value))
def score(event: LifeEvent) -> int:
delta = event.energy_after - event.energy_before
return (
delta * 2
+ event.repeatability
+ event.autonomy
+ event.competence
+ event.connection
)
def append_event(event: LifeEvent) -> None:
event = event.normalized()
if event.distress:
print("最適化を中断します。今は一人でログを解析する場面ではありません。")
print("身近な人、医療機関、地域の緊急窓口へ接続してください。")
print("相談先一覧: https://www.mhlw.go.jp/mamorouyokokoro/")
return
with LOG_PATH.open("a", encoding="utf-8") as file:
file.write(json.dumps(asdict(event), ensure_ascii=False) + "\n")
def load_events() -> list[LifeEvent]:
if not LOG_PATH.exists():
return []
events: list[LifeEvent] = []
with LOG_PATH.open(encoding="utf-8") as file:
for line in file:
events.append(LifeEvent(**json.loads(line)))
return events
def recommend(events: list[LifeEvent]) -> str:
if not events:
return (
"候補を三つ試してください: "
"5分歩く、何かを作る、誰かを少し手伝う"
)
best = max(events, key=score)
return (
f"次は「{best.activity}」を、"
"前回より小さく再実行してください。"
)
if __name__ == "__main__":
append_event(
LifeEvent(
activity="昼休みに5分だけ歩く",
energy_before=3,
energy_after=5,
repeatability=8,
autonomy=7,
competence=2,
connection=1,
)
)
print(recommend(load_events()))
スコアは雑でよい
ここで大事なのは精密な数理モデルじゃない。「なんか全部ダメだ」って巨大な認識を、観察できるイベントにバラすこと。
スコアが高い活動を人生の目的と呼ぶ必要もない。次は前回より小さく試すだけでいい。
少年「散歩、点数いちばん高いじゃねえか! これが答えだ!」
相方「答えって言うな。まだ早い」
少年「じゃあもっと歩けば近づくのか!」
相方「近づかない。同じところを小さく試せ」
少年「小さく!? 俺はもっと強く——」
相方「歩け。帰ってきたら一行書け」
7日間のMVP
毎日、一つだけ試す。記録する項目はこの七つで足りる。
| 項目 | 意味 |
|---|---|
activity |
何をしたか |
energy_before |
開始前の気力 |
energy_after |
終了後の気力 |
repeatability |
もう一度やってもよいか |
autonomy |
自分で選んだ感じがあったか |
competence |
ちょっと前に進んだ感じがあったか |
connection |
誰かとの接点があったか |
候補が浮かばない日は、次の三つから一つ選ぶ。
| 系統 | 例 |
|---|---|
| 体を使う | 散歩、料理、片付け、入浴 |
| 渡す | 人を手伝う、短い連絡をする、知識を共有する |
| 作る | 文章、コード、絵、植物の世話 |
フェイルセーフは必須
ログを取れないほどつらい時、自分を傷つけるかもしれない時は、アプリの推薦を止める。これは例外処理じゃなくて、主要機能。
if distress_detected:
stop_optimization()
connect_to_human_support()
この記事を読んでいる今、自分を傷つける可能性があるなら、記録や習慣化より安全を先に。日本にいる場合、差し迫った危険がある時は119。厚生労働省の「まもろうよ こころ」に電話・SNS・チャットの相談先がある。
まとめ
人生の目的を返すAPIはない。でも次の小さな実験を選ぶことはできる。
while alive:
try_something_small()
observe_response()
keep_only_weak_signals()
少年「人生の目的、まだ分かんねぇ!」
相方「昨日もそう言ってた」
少年「今日は5分歩いた! 進んでるだろ!」
相方「進んでるのは歩数だけだ」
少年「……でも腹減った。飯食う!」
相方「そこは毎日確実だな」
注意
この記事は診断や治療を目的にしたものではない。日常生活が大きく崩れている時、何週間も何にも反応しない時、消えたい気持ちが続く時は、一人で最適化を続けず、医療機関や相談窓口へ。
参考文献・相談窓口
- Ryan, R. M., & Deci, E. L. (2000). Self-Determination Theory and the Facilitation of Intrinsic Motivation, Social Development, and Well-Being.
https://selfdeterminationtheory.org/SDT/documents/2000_RyanDeci_SDT.pdf - Ekers, D. et al. (2014). Behavioural Activation for Depression; An Update of Meta-Analysis of Effectiveness and Sub Group Analysis.
https://pmc.ncbi.nlm.nih.gov/articles/PMC4061095/ - Gollwitzer, P. M., & Sheeran, P. (2006). Implementation Intentions and Goal Achievement: A Meta-analysis of Effects and Processes.
https://doi.org/10.1016/S0065-2601(06)38002-1 - Takenaka, K., Uechi, H., & Yoshida, R. (2021). Behavior change intervention on mental health promotion using if-then plans.
https://doi.org/10.11560/jhpr.200508140 - 厚生労働省「まもろうよ こころ」
https://www.mhlw.go.jp/mamorouyokokoro/ - 厚生労働省「電話相談窓口」
https://www.mhlw.go.jp/mamorouyokokoro/soudan/tel/ - 厚生労働省「SNS相談」
https://www.mhlw.go.jp/mamorouyokokoro/soudan/sns/
おもんな。