英語学習、n回目の再開。今度はAIとダンディーなオジ様に賭けてみる
必要に駆られて、切羽詰まって、追い詰められて、英語学習を再開した。
再開、というか再開(n回目)である。
特に今回は、Listening / Speaking をあと数ヶ月で「まあ何とかなる」レベルまで引き上げなければならない。なかなかに切実だ。
私はこれまで、幾度となく英語学習に失敗してきた。
3日坊主、1ヶ月で断念、3ヶ月で自然消滅。失敗パターンには枚挙にいとまがない。
直近では ELSA Speak のサブスクリプションを買ってみたものの、これも3ヶ月ほどで自然消滅した。しかも、あまり上達している実感も持てなかった。
このままだと今回も同じ結末になる。
そう思ったので、今回は少し工夫することにした。
まず AI に相談し、数ヶ月分の学習プランを立ててもらった。さらに、そのプランの各フェーズで使う具体的な練習用プロンプトも作成してもらった。
そして、そのプロンプトを ChatGPT の Voice Mode で試してみた。
Listening / Speaking の練習をやってみたところ、これが想像以上に良かった。
1. インタラクティブな学習スタイルが良い
まず、Voice Mode のインタラクティブ性がかなり効いている。
Voice Mode だと、会話形式で進むので、学習への忌避感が少し薄まる。
一方的に教材をこなすというより、「相手がいて、やり取りしながら進む」感じがある。
このインタラクティブ性が、ここまで心の障壁を下げてくれるとは思っていなかった。
考えてみれば、ちゃんとしたインタラクティブ形式なんて、高校以来かもしれない。
大学は基本的に大人数の講義形式だったし、研究室はたしかにインタラクティブだったが、あれは「学習」というより「実践」に近かった。もちろん、教授目線ではめちゃくちゃ“学習”させていたのだろうけれど。
インタラクティブな学習って、けっこう気持ち良い。
2. 問題レベルを自分用に調整できるのが良い
問題レベルをプロンプトで自由に調整できるのがとても良い。
英語学習において、問題の難易度はかなり重要だ。
簡単すぎると退屈だし、難しすぎると一瞬で心が折れる。
特に私の場合、英語学習におけるスイートスポットがかなり狭い気がしている。
小学生の頃は英会話塾に通っていた。高校生の頃は、英語でそれなりの偏差値も取っていた。瞬間最大風速で言えば、偏差値85くらい出たこともある。
一方で、大学以降はほとんど英語を使っていない。
その結果、英語力はだいぶ崩壊している。
つまり、Low レベルを丁寧に学び直すには、過去の知識とプライドが邪魔をする。
しかし、Mid / High レベルをいきなりこなせるほどの実力はまったくない。
なかなか面倒くさい状態である。
でも、この微妙なスイートスポットを、プロンプトならかなり細かく調整できそうな気がしている。
少なくとも初回の練習では、かなり心地良い難易度で進められた。
もちろん、一般的な英語学習アプリにもパーソナライズ機能はある。
ただ、AI のプロンプトを使えば、その一段上のパーソナライズができそうな感触があった。
3. ダンディーなオジ様の声が良い
そして、地味に大きいのが声である。
ChatGPT の Voice Mode では、たしか8種類か10種類くらいの音声から選べる。
その中に、ダンディーなオジ様の声がある。
これがめちゃくちゃ心地良い。
ELSA Speak も、たしか4種類くらいの声から選べた気がする。
ただ、正直どれもあまり気に入らなかった。
これまであまり意識していなかったが、気に入らない声で話しかけられると、意外と気分が乗らない。
逆に、心地良い声だと、それだけで続ける気力が少し増す。
ダンディーなオジ様の声は、本当にちょうど良い。
それだけで学習継続力が1.2倍くらいになっている気がする。
声って、めちゃくちゃ大事なのね。
そんなわけで、久しぶりに英語学習に少し希望を感じている。
もちろん、本当の勝負はここからだ。
この先数ヶ月、モチベーションと練習時間を維持できるかどうか。そこが一番難しい。
ただ、今回は少しだけ希望がある。
それは、「ダメだったらプロンプトをチューニングする」という手段が残されていることだ。
今までの英語学習では、続かなかったときに「自分の意志が弱い」で終わりがちだった。
でも今回は、自分を変えるのではなく、プロセスやルールを変えられる。
難しすぎるなら、難易度を下げる。
退屈なら、問題形式を変える。
飽きるなら、会話テーマを変える。
発話量が足りないなら、もっと喋らされるプロンプトにする。
自分を責める前に、学習環境そのものをチューニングできる。
これは、これまでの英語学習アプリではあまりできなかったことだ。
そして、AI を使った新しい学習スタイルの面白さでもある。
数ヶ月後にどうなっているかは分からない。
また自然消滅している可能性も、もちろんある。
でも今のところ、少しワクワクしている。
英語学習に対してこんな感覚を持つのは、かなり久しぶりだ。
JBoss EAP 8 のビルド
公式ドキュメント
docs.redhat.com
Legacy S2I の方法
access.redhat.com
カスタム Galleon レイヤー
github.com
EAP 8 のサンプル Helm
github.com
PgAdminにDB接続情報を環境設定的に構成する方法
あらかじめ接続情報を入れておきたいとか、構成管理したいとか、そういった状況。
設定方法はいくつかのサイトで解説が見られるが、バージョン依存で上手くいかないケースが散見される。
stackoverflow.com
最終的に上手くいったのは以下の方法となった。
stackoverflow.com
以下、Docker Compose を前提としたソースコード。
docker-compose.yaml
version: "3.9" services: postgres_db: image: postgres volumes: - ./postgres_db_data:/var/lib/postgresql/data environment: - POSTGRES_DB=postgres - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres ports: - "15432:5432" pgadmin: image: dpage/pgadmin4:7.1 restart: always environment: PGADMIN_DEFAULT_EMAIL: pgadmin@pgadmin.com PGADMIN_DEFAULT_PASSWORD: pgadmin ports: - "8080:80" volumes: - ./servers.json:/pgadmin4/servers.json - ./pgpass:/var/lib/pgadmin/pgpass depends_on: - "postgres_db"
ファイルマウントが重要なわけだが、pgpass については後述する相対パスで指定するのでたぶんどこに置いてもいける。
servers.json
{ "Servers": { "1": { "Name": "docker_postgres", "Group": "docker_postgres_group", "Host": "postgres_db", "Port": 5432, "MaintenanceDB": "postgres", "Username": "postgres", "PassFile": "../../pgpass", "SSLMode": "prefer" }, "2": { "Name": "docker_postgres_host", "Group": "docker_postgres_group", "Host": "host.docker.internal", "Port": 15432, "MaintenanceDB": "postgres", "Username": "postgres", "PassFile": "../../pgpass", "SSLMode": "prefer" } } }
"PassFile": "../../pgpass" が最重要ポイント。相対パスになっているっぽい。
pgpass
postgres_db:5432:postgres:postgres:postgres host.docker.internal:15432:postgres:postgres:postgres
パスワードは hostname:port:database:username:password の形式で書けば良い。
複数DBを1ファイルにも書ける。
微妙にハマるポイントが多く、予想に反して面倒であった。
Kubernetes リソースを Excel 表にするワンライナー
以下のようなワンライナーを実行する。
$ NAMESPACE=openshift-monitoring
$ echo -e "NAME\tKIND\tREPLICAS\tCONTAINER\tREQUEST MEMORY\tREQUEST CPU\tLIMIT MEMORY\tLIMIT CPU"; \
> oc get deployment,statefulset,daemonset -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.kind}{"\t"}{.spec.replicas}{"\t"}{range .spec.template.spec.containers[*]}{.name}{"\t"}{.resources.requests.memory}{"\t"}{.resources.requests.cpu}{"\t"}{.resources.limits.memory}{"\t"}{.resources.limits.cpu}{"\n\t\t\t"}{end}{"\n"}{end}' -n ${NAMESPACE} | sed '/^\t\t\t$/d'
実行結果。
$ NAMESPACE=openshift-monitoring
$ echo -e "NAME\tKIND\tREPLICAS\tCONTAINER\tREQUEST MEMORY\tREQUEST CPU\tLIMIT MEMORY\tLIMIT CPU"; \
> oc get deployment,statefulset,daemonset -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.kind}{"\t"}{.spec.replicas}{"\t"}{range .spec.template.spec.containers[*]}{.name}{"\t"}{.resources.requests.memory}{"\t"}{.resources.requests.cpu}{"\t"}{.resources.limits.memory}{"\t"}{.resources.limits.cpu}{"\n\t\t\t"}{end}{"\n"}{end}' -n ${NAMESPACE} | sed '/^\t\t\t$/d'
NAME KIND REPLICAS CONTAINER REQUEST MEMORY REQUEST CPU LIMIT MEMORY LIMIT CPU
cluster-monitoring-operator Deployment 1 kube-rbac-proxy 20Mi 1m
cluster-monitoring-operator 75Mi 10m
grafana Deployment 1 grafana 64Mi 4m
grafana-proxy 20Mi 1m
kube-state-metrics Deployment 1 kube-state-metrics 80Mi 2m
kube-rbac-proxy-main 15Mi 1m
kube-rbac-proxy-self 15Mi 1m
openshift-state-metrics Deployment 1 kube-rbac-proxy-main 20Mi 1m
kube-rbac-proxy-self 20Mi 1m
openshift-state-metrics 32Mi 1m
prometheus-adapter Deployment 2 prometheus-adapter 40Mi 1m
prometheus-operator Deployment 1 prometheus-operator 150Mi 5m
kube-rbac-proxy 15Mi 1m
telemeter-client Deployment 1 telemeter-client 40Mi 1m
reload 10Mi 1m
kube-rbac-proxy 20Mi 1m
thanos-querier Deployment 2 thanos-query 12Mi 10m
oauth-proxy 20Mi 1m
kube-rbac-proxy 15Mi 1m
prom-label-proxy 15Mi 1m
kube-rbac-proxy-rules 15Mi 1m
alertmanager-main StatefulSet 3 alertmanager 40Mi 4m
config-reloader 10Mi 1m
alertmanager-proxy 20Mi 1m
kube-rbac-proxy 15Mi 1m
prom-label-proxy 20Mi 1m
prometheus-k8s StatefulSet 2 prometheus 1Gi 70m
config-reloader 10Mi 1m
thanos-sidecar 25Mi 1m
prometheus-proxy 20Mi 1m
kube-rbac-proxy 15Mi 1m
prom-label-proxy 15Mi 1m
kube-rbac-proxy-thanos 10Mi 1m
node-exporter DaemonSet node-exporter 32Mi 8m
kube-rbac-proxy 15Mi 1m
結果を Excel に貼り付ける。
罫線は自前で描かないといけない。

くだらないけど意外に使いどころがあるかもしれない。
OpenShift Cluster Monitoring の Prometheus のデータを Export/Import する
これが実現できると一番スマートそうだなと思った。
visibilityspots.org
だが、Cluster Monitoring の Prometheus では admin API が無効化されていた。まぁ想定はしていた。
$ oc exec -it -n openshift-monitoring prometheus-k8s-0 -- sh
sh-4.4$ curl -X POST http://localhost:9090/api/v1/admin/tsdb/snapshot
{"status":"error","errorType":"unavailable","error":"admin APIs disabled"}仕方がないので Prometheus のデータを tar.gz で固めて持ってくることにした。固めるのにかなり時間が掛かる。
$ oc exec -it -n openshift-monitoring prometheus-k8s-0 -- sh sh-4.4$ tar -zcvf /tmp/prometheus.tar.gz /prometheus tar: Removing leading `/' from member names /prometheus/ /prometheus/01FK3XJ471YNVXFRT1PV5VHPTP/ /prometheus/01FK3XJ471YNVXFRT1PV5VHPTP/chunks/ ・・・ ・・・ ・・・ sh-4.4$ ls /tmp/ ks-script-rgpe088e ks-script-zgupbl05 prometheus.tar.gz
Prometheus のバージョンも調べておく。
sh-4.4$ /bin/prometheus --version prometheus, version 2.26.1 (branch: rhaos-4.8-rhel-8, revision: 5e146b2e4b9d96a952b9412dc20ce3fabfa2bd5e) build user: root@d43b8d11b98a build date: 20210813-03:01:55 go version: go1.16.6 platform: linux/amd64
oc cp でローカルに tar.gz で固めたものを持ってくる。持ってくるのにかなり時間が掛かる。
$ oc cp prometheus-k8s-0:/tmp/prometheus.tar.gz /my/local/pc/prometheus.tar.gz Defaulting container name to prometheus. tar: Removing leading `/' from member names
ローカルで同一バージョンの Prometheus をデータをコピーした領域をマウントする形で起動する。
$ docker run -d --name prometheus -v /my/local/pc/prometheus:/prometheus -p 9090:9090 prom/prometheus:v2.26.1 002bc4b65116d370f9998455e38c55d88d28d2bb26b1ebddacba38abfbcb10b4
一応ちゃんとデータを見られる。そこそこ使い所ありそう。