ソフトウェア開発」カテゴリーアーカイブ

Google Apps Script を Gitub Actions で簡単デプロイ

GASをさわり始めては見たものの、GAS標準で備わっているコードエディタは悪くはないんだけど、せっかくなのでローカルのVSCodeで開発をしてGithubへPush。
Github Actions を利用してデプロイまでやってしまおうかと。

GASのコードエディタだと、弄り倒してもGithubに草生えないし

Claspのインストール周り

claspという、Apps Script をローカル開発するためのコマンドラインツールをインストールします

clasp
https://github.com/google/clasp

インストールは以下のコマンドを叩くだけ

npm install -g @google/clasp

インストール完了後、claspを使ってログインを行います

clasp login

上記コマンドを打つと、Googleへのログイン情報を取得することができます。
Github Actions では、ここで取得する情報を用いて、Apps Script側へDeployすることになります。

その際、Apps Script の API を呼ぶことが出来るように、Apps Script側でAPIを有効にしておきます

GASの設定値を入手する

作成済みのGASのコードを入手するために、claspを使ってプロジェクトをcloneします

clasp clone "スクリプトID

スクリプトIDは対象とするApps Scriptのプロジェクト詳細から確認することができます

単純に、AppsScriptを表示した際に表示されるURLの一部でもあります。「https://script.google.com/d/**ID**/edit?mid=hoge&uiv=fuga」

clone をすることで、下記のファイルが取得されます

appsscript.json
.clasp.json
コード.js
.clasp.json

コード.jsはAppsScriptのエディタで編集していたJavaScriptファイルです。
HTMLファイルなどを追加している場合は同様にcloneされてくるはずです。

appsscript.json には、プロジェクトに関する設定が記載されていて、対象とするApps ScriptをWebアプリとして利用する場合にはこんな記述になっていると思います

{
  "timeZone": "Asia/Tokyo",
  "dependencies": {},
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "webapp": {
    "executeAs": "USER_DEPLOYING",
    "access": "ANYONE_ANONYMOUS"
  }
}

初回デプロイ時にWebアプリとするのか、APIとするのかなどを選択することになるので、実際にcloneする際には初回デプロイ後のほうがいいかもしれません。

また、.clasp.jsonファイルではディレクトリの指定が可能です。
Github Actions のフォルダなどを作ることを考えると、ソースファイルはsrcフォルダに移動しておいたほうがいいです。

{"scriptId":"XXXX スクリプトID XXXXX","rootDir":"./src"}

必要事項をGithub Secrets へ保存する

clasp login コマンドを実行したことで、ホームディレクトリ配下に.clasprc.jsonファイルができているはずです。
注意しないといけないのは、clasp clone で取得した.clasp.jsonファイルとは別となります。名前が似ていますが。
Windowsであれば、「C:\Users\XXX\.clasprc.json」に保存されている形です

{
    "token": {
        "access_token": "XXXXX",
        "refresh_token": "XXXXX",
        "scope": "https://www.googleapis.c...",
        "token_type": "Bearer",
        "id_token": "XXXXX",
        "expiry_date": 1662717440887
    },
    "oauth2ClientSettings": {
        "clientId": "XXXXX",
        "clientSecret": "XXXXX",
        "redirectUri": "http://localhost"
    },
    "isLocalCreds": false
}

上記の中から、Deployに必要となる下記の値をGithub Secretsへ登録します

  • access_token
  • refresh_token
  • id_token
  • clientId
  • clientSecret

さらに、デプロイを管理メニューで表示されるデプロイIDも登録します

Github Actions用の定義追加

ここまで来たらあと一息。
というわけで、workflowを定義します

name: CD

on:
  push:
    branches:
      - main
  workflow_dispatch:
jobs:
  deploy:
    runs-on: ubuntu-20.04
    timeout-minutes: 15
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Setup Node.js 16.x
        uses: actions/setup-node@v2
        with:
          node-version: '16.x'
      - name: Install Clasp
        run: |
          npm init -y
          npm install clasp -g
      - name: Create claspc.json
        run: |
          echo \{\"token\":\{\"access_token\":\"${{ secrets.ACCESS_TOKEN}}\",\"scope\":\"https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/script.projects https://www.googleapis.com/auth/script.webapp.deploy https://www.googleapis.com/auth/logging.read openid https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/script.deployments https://www.googleapis.com/auth/service.management https://www.googleapis.com/auth/cloud-platform\",\"token_type\":\"Bearer\",\"id_token\":\"${{ secrets.ID_TOKEN }}\",\"expiry_date\":1620870307822,\"refresh_token\":\"${{ secrets.REFRESH_TOKEN }}\"\},\"oauth2ClientSettings\":\{\"clientId\":\"${{ secrets.CLIENTID }}\",\"clientSecret\":\"${{ secrets.CLIENTSECRET }}\",\"redirectUri\":\"http://localhost\"\},\"isLocalCreds\":false\} > ~/.clasprc.json
      - name: Push
        run: |
          clasp push
      - name: DEPLOY
        run: |
          clasp deploy --deploymentId ${{secrets.PROD_DEPLOYMENT_ID}}

mainブランチに対してのpushで起動するようになっています。

将来的に、デプロイ先を分けられるように、DEPLOYMENT_IDはPRODをつけて定義しています。
上記yamlファイルを

.github/workflows

フォルダに配備します。
最終的なディレクトリ構成としては下記の様に私はしてみました

PROJECT_FOLDER
  └── .github
       └── workflows
              └── cd.yaml
 └── src
       └── .appsscript.json
           コード.js
  .clasp.json
  README.md

これで動いていることを確認できます。

うまくいかなかった時

Github ActionsのFlowが成功したからと言って、実際にAppsScriptがちゃんとデプロイされるとは限らないです。

Run clasp push
  clasp push
  shell: /usr/bin/bash -e {0}
? Manifest file has been updated. Do you want to push and overwrite? (y/N) 

上記の様なログがclasp push 時に発生していました。

原因としては、clasp clone 後にAppsScriptのコンソール上から、AppsScriptを初デプロイした際にWebアプリの選択を行いました。

デプロイ後にclasp clone していれば問題なかったのですが、Webアプリを選択したことで、appsscript.jsonの中身が更新されたのです。

clasp push 時にその差分が検知されてしまい、上書きするのかどうかを問われて、返答なしでそのまま終わってしまったのですね。。。

現状の不満

なんとか目論見通り、ローカルでの開発とPushすることでのDeployまで持っていくことができました。

一方で、ローカルで作ったものを動かすことができていません。。。
そのため、毎回デプロイして本番確認。デプロイして本番確認を行っています。。。

Githubに無駄に草がわんさか生えることになっているんだけど、実際のところ、ただのタイプミスだったりすることも多くて、少し悲しい。
できれば、動作確認してからcommitしたい。。

というのも、フロントエンドが不得手な私はサンプルを探してきて使ってみているんですが、なかなかこれがうまく動かない。
そして、恐ろしくエラーの原因調査・デバッグが難しい。。。

Vue.jsで書かれたサンプルを改造しようとしていますが、正直心が折れそうで、見た目とか気にせずにものすごく単純なHTMLにしてしまおうか迷っているところです。
とは言え、なんかこのまま引き下がるのも悔しいんですよね~。

というわけで、Vue.jsに関して少し勉強してみようかな・・・?

参考

Google Apps Script (GAS) をさわり始めた

ちょっとしたきっかけで、妻から「こんなの作れたりする?」として見せられたサイトがGASでできていた。

GAS。。。一時期結構話題に登ることはあって、結構便利という話ではあったんだけど、結局のところ必要となる場面もなかったので触ったことないんだよな、ということで簡単に調べてみた。

GASの用途

Googleサービスと連携させることが比較的ラクなので、データを保存する場所としては基本的にはSpredsheetもしくはDriveへの保存になると思う。

軽く検索してみた限りでは、GASの利用用途としては

  • 簡易的なWeb API
  • スクレイピングしてSpredSheetへ保存
  • 簡易Webアプリ

みたいなところだろうか。
スクリプトを走らせることが出来る以上、やろうと思えばある程度のことはできそうだけど、あまり凝ったことをしようとすると、できなくはないが面倒なことになるかもしれない。

確か、以前LINE公式アカウントに関して調べた際も、GASで作ったAPIを呼び出すような例もあった気がする。
それを考えると、API設計なんかを含めて考えて作ることができれば、スピードとかを気にしなければ用途の幅は広がりそうだ

簡易Webアプリ

今回、できないか?と言われたのはWebアプリに分類されるもの。
端的に言えば、スプレッドシートの情報を公開するのと、その情報を使って計算し、結果を表示させるようなものだ。

それだけであれば、すぐにできそう

基本的なGASで作るWebアプリのコンセプトとしては簡易的なもので、ページとしてもHTML一つ。
色々と調べてみるとReactやVueなどでつくってWebpackなどでまとめることでGAS上で動かすことも出来るようだが、あまり凝ったことを今回やってもなぁ、と思ってしまう。

今回のオーダーとしては、最終的には妻の職場で使ってみたいということなので、ある程度自分たちでメンテナンスができないといけないのだ。

というわけで、簡単なWebのフォームを使った計算結果の表示と、データ入力。
また、スプレッドシートの表示みたいなことができればいいのかな?と思っている。

実際のところ、もう少しやりたい事を聞いてまとめて、最終的な完成形というか、業務フローというか。そういったものを考えた上でアプリをどう使っていくのかの動線を考えたいところ。

ReactにしろVueにしろ、凝ったことは出来るんだろうけど、そもそも自分がその領域に関して明るくないわけだし、今回の要求からはオーバースペックなわけだ。
まずは、簡単なところで試してみつつ、これまで手でやっていた自分の作業をGASを使って、より良い方向に向かわせることができれば面白いかな、と思っている。

続・画像生成AIを触ってみた

Docker Composeが途中で止まってしまった原因は不明だが、まずは動かしてみたいというところでDevContainer使ってVSCode上のターミナルから試行錯誤してみようとと。

参考はこちら
Stable Diffusionをローカルマシンで実行する(VSCodeとDevcontainerを使用)
https://zenn.dev/hayatok/articles/6141a9a46e4f48

DevContainer準備

VSCodeで適当なフォルダを開き、Dockerfileを作成します

FROM nvcr.io/nvidia/cuda:11.7.1-cudnn8-runtime-ubuntu20.04

ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=Asia/Tokyo

RUN apt-get update && apt-get install -y wget git git-lfs libglib2.0-0 libsm6 libxrender1 libxext-dev

RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh && \
    sh Miniconda3-latest-Linux-x86_64.sh -b -p /opt/miniconda3 && \
    rm -r Miniconda3-latest-Linux-x86_64.sh

ENV PATH /opt/miniconda3/bin:$PATH

RUN git clone https://github.com/CompVis/stable-diffusion && \
    cd stable-diffusion && \
    conda init bash && \
    conda env create -f environment.yaml && \
    echo "conda activate ldm" >> ~/.bashrc

VSCode のコマンドパレットから「Remote-Containers: Add Development Container Configuration Files…」を選択し、作成したDockerfileを指定します。

devcontainer.jsonが作成されるので、編集します

// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.245.0/containers/docker-existing-dockerfile
{
	"name": "Existing Dockerfile",

	// Sets the run context to one level up instead of the .devcontainer folder.
	"context": "..",

	// Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename.
	"dockerFile": "../Dockerfile",

	// 追記ここから。GPU利用可のコンテナ起動オプション
	"runArgs":[
		"--gpus",
		"all"
	],
	// 追記ここまで。
	"customizations": {
		"vscode": {
			"extensions": [
				"ms-python.python"
			]
		}
	}

	// Use 'forwardPorts' to make a list of ports inside the container available locally.
	// "forwardPorts": [],

	// Uncomment the next line to run commands after the container is created - for example installing curl.
	// "postCreateCommand": "apt-get update && apt-get install -y curl",

	// Uncomment when using a ptrace-based debugger like C++, Go, and Rust
	// "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],

	// Uncomment to use the Docker CLI from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker.
	// "mounts": [ "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind" ],

	// Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root.
	// "remoteUser": "vscode"
}

コマンドパレットから「Remote-Containers: Rebuild and Reopen in Container」を選択することで、コンテナ内でVSCodeが起動する形となります。
VSCode の左下がこの状態ですね

Modelの配置

前回取得した Hugging Face のモデルを、Stable Diffusionがモデルのデフォルトパスとして指定している”models/ldm/stable-diffusion-v1/model.ckpt”に配備します。
このあたりは、”txt2image.py”を読んでいくとなんのパラメータ指定が出来るのかがわ借ります。
別のパスを指定する場合は —ckpt オプションで指定可能となっています

実行!

参考にさせていただいたページに従って、test.pyを用意し、実行します

(ldm) root@21feb17171f4:/workspaces/StableDiffusion2/stable-diffusion# python test.py
Traceback (most recent call last):
  File "test.py", line 6, in <module>
    pipe = StableDiffusionPipeline.from_pretrained(
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/diffusers/pipeline_utils.py", line 154, in from_pretrained
    cached_folder = snapshot_download(
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/huggingface_hub/utils/_deprecation.py", line 93, in inner_f
    return f(*args, **kwargs)
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/huggingface_hub/_snapshot_download.py", line 168, in snapshot_download
    repo_info = _api.repo_info(
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/huggingface_hub/hf_api.py", line 1454, in repo_info
    return self.model_info(
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/huggingface_hub/hf_api.py", line 1276, in model_info
    _raise_for_status(r)
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/huggingface_hub/utils/_errors.py", line 169, in _raise_for_status
    raise e
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/huggingface_hub/utils/_errors.py", line 131, in _raise_for_status
    response.raise_for_status()
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/requests/models.py", line 1021, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://huggingface.co/api/models/CompVis/stable-diffusion-v1-4/revision/fp16 (Request ID: PQ6M8N2Lators-j6XdN6V)

Access to model CompVis/stable-diffusion-v1-4 is restricted and you are not in the authorized list. Visit https://huggingface.co/CompVis/stable-diffusion-v1-4 to ask for access.
(ldm) root@21feb17171f4:/workspaces/StableDiffusion2/stable-diffusion# python test.py
Downloading: 100%|████████████████████████████████████████████████████| 1.34k/1.34k [00:00<00:00, 1.13MB/s]
Downloading: 100%|████████████████████████████████████████████████████| 12.5k/12.5k [00:00<00:00, 11.2MB/s]
Downloading: 100%|█████████████████████████████████████████████████████████| 342/342 [00:00<00:00, 337kB/s]
Downloading: 100%|█████████████████████████████████████████████████████████| 543/543 [00:00<00:00, 557kB/s]
Downloading: 100%|████████████████████████████████████████████████████| 4.63k/4.63k [00:00<00:00, 4.02MB/s]
Downloading: 100%|██████████████████████████████████████████████████████| 608M/608M [00:20<00:00, 29.6MB/s]
Downloading: 100%|█████████████████████████████████████████████████████████| 209/209 [00:00<00:00, 208kB/s]
Downloading: 100%|█████████████████████████████████████████████████████████| 209/209 [00:00<00:00, 185kB/s]
Downloading: 100%|█████████████████████████████████████████████████████████| 572/572 [00:00<00:00, 545kB/s]
Downloading: 100%|██████████████████████████████████████████████████████| 246M/246M [00:08<00:00, 29.6MB/s]
Downloading: 100%|███████████████████████████████████████████████████████| 525k/525k [00:00<00:00, 583kB/s]
Downloading: 100%|█████████████████████████████████████████████████████████| 472/472 [00:00<00:00, 476kB/s]
Downloading: 100%|█████████████████████████████████████████████████████████| 788/788 [00:00<00:00, 864kB/s]
Downloading: 100%|█████████████████████████████████████████████████████| 1.06M/1.06M [00:01<00:00, 936kB/s]
Downloading: 100%|█████████████████████████████████████████████████████████| 772/772 [00:00<00:00, 780kB/s]
Downloading: 100%|████████████████████████████████████████████████████| 1.72G/1.72G [00:54<00:00, 31.7MB/s]
Downloading: 100%|█████████████████████████████████████████████████████| 71.2k/71.2k [00:00<00:00, 188kB/s]
Downloading: 100%|█████████████████████████████████████████████████████████| 550/550 [00:00<00:00, 532kB/s]
Downloading: 100%|██████████████████████████████████████████████████████| 167M/167M [00:05<00:00, 28.5MB/s]
0it [00:01, ?it/s]
Traceback (most recent call last):
  File "test.py", line 15, in <module>
    image = pipe(prompt)["sample"][0]  
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/torch/autograd/grad_mode.py", line 27, in decorate_context
    return func(*args, **kwargs)
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/diffusers/pipelines/stable_diffusion/pipeline_stable_diffusion.py", line 137, in __call__
    noise_pred = self.unet(latent_model_input, t, encoder_hidden_states=text_embeddings)["sample"]
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/torch/nn/modules/module.py", line 1110, in _call_impl
    return forward_call(*input, **kwargs)
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/diffusers/models/unet_2d_condition.py", line 150, in forward
    sample, res_samples = downsample_block(
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/torch/nn/modules/module.py", line 1110, in _call_impl
    return forward_call(*input, **kwargs)
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/diffusers/models/unet_blocks.py", line 505, in forward
    hidden_states = attn(hidden_states, context=encoder_hidden_states)
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/torch/nn/modules/module.py", line 1110, in _call_impl
    return forward_call(*input, **kwargs)
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/diffusers/models/attention.py", line 168, in forward
    x = block(x, context=context)
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/torch/nn/modules/module.py", line 1110, in _call_impl
    return forward_call(*input, **kwargs)
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/diffusers/models/attention.py", line 196, in forward
    x = self.attn1(self.norm1(x)) + x
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/torch/nn/modules/module.py", line 1110, in _call_impl
    return forward_call(*input, **kwargs)
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/diffusers/models/attention.py", line 245, in forward
    sim = torch.einsum("b i d, b j d -> b i j", q, k) * self.scale
RuntimeError: CUDA out of memory. Tried to allocate 512.00 MiB (GPU 0; 4.00 GiB total capacity; 3.13 GiB already allocated; 0 bytes free; 3.13 GiB reserved in total by PyTorch) If reserved memory is >> allocated memory try setting max_split_size_mb to avoid fragmentation.  See documentation for Memory Management and PYTORCH_CUDA_ALLOC_CONF

エラーになってしまった。要するにメモリが足りないんだと。
そこでメモリの状態を調べるコマンドを打ってみる

(ldm) root@21feb17171f4:/workspaces/StableDiffusion2/stable-diffusion# nvidia-smi
Tue Sep  6 14:52:34 2022       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 515.65.01    Driver Version: 516.94       CUDA Version: 11.7     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA GeForce ...  On   | 00000000:01:00.0 Off |                  N/A |
| N/A   56C    P3    13W /  N/A |      0MiB /  4096MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

むぅ。そもそもいくつあればOKなのかがいまいちわからん。
エラーメッセージに出てきた「PYTORCH_CUDA_ALLOC_CONF」あたりを見ていくと何とかパラメータ指定でうまく行けないかな?という気もするけど、多くの人がStable Diffusionをそのまま使うのではなく、メモリ消費を抑えたバージョンを使っているという事を見聞きしているので、そちらを使うことにする

(ldm) root@21feb17171f4:/workspaces/StableDiffusion2# mkdir basujindal
(ldm) root@21feb17171f4:/workspaces/StableDiffusion2# ls
Dockerfile  basujindal  stable-diffusion
(ldm) root@21feb17171f4:/workspaces/StableDiffusion2# cd basujindal/
(ldm) root@21feb17171f4:/workspaces/StableDiffusion2/basujindal# git clone https://github.com/basujindal/stable-diffusion.git

適当なフォルダを作って、リポジトリからclone

(ldm) root@21feb17171f4:/workspaces/StableDiffusion2/basujindal# cd stable-diffusion/
(ldm) root@21feb17171f4:/workspaces/StableDiffusion2/basujindal/stable-diffusion# python optimizedSD/optimized_txt2img.py --prompt "a photograph of an astronaut riding a horse" --H 512 --W 512 --seed 27 --n_iter 2 --n_samples 10 --ddim_steps 50
Global seed set to 27
Loading model from models/ldm/stable-diffusion-v1/model.ckpt
Traceback (most recent call last):
  File "optimizedSD/optimized_txt2img.py", line 184, in <module>
    sd = load_model_from_config(f"{ckpt}")
  File "optimizedSD/optimized_txt2img.py", line 29, in load_model_from_config
    pl_sd = torch.load(ckpt, map_location="cpu")
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/torch/serialization.py", line 699, in load
    with _open_file_like(f, 'rb') as opened_file:
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/torch/serialization.py", line 231, in _open_file_like
    return _open_file(name_or_buffer, mode)
  File "/opt/miniconda3/envs/ldm/lib/python3.8/site-packages/torch/serialization.py", line 212, in __init__
    super(_open_file, self).__init__(open(name, mode))
FileNotFoundError: [Errno 2] No such file or directory: 'models/ldm/stable-diffusion-v1/model.ckpt'

おっと、モデルを新たに置き直さないと行けない。
サクッとコピーして、再度実行する

(ldm) root@21feb17171f4:/workspaces/StableDiffusion2/basujindal/stable-diffusion# python optimizedSD/optimized_txt2img.py --prompt "a photograph of an astronaut riding a horse" --H 512 --W 512 --seed 27 --n_iter 2 --n_samples 10 --ddim_steps 50
Global seed set to 27
Loading model from models/ldm/stable-diffusion-v1/model.ckpt
Global Step: 470000
Traceback (most recent call last):
  File "optimizedSD/optimized_txt2img.py", line 204, in <module>
    model = instantiate_from_config(config.modelUNet)
  File "/stable-diffusion/ldm/util.py", line 85, in instantiate_from_config
    return get_obj_from_str(config["target"])(**config.get("params", dict()))
  File "/stable-diffusion/ldm/util.py", line 93, in get_obj_from_str
    return getattr(importlib.import_module(module, package=None), cls)
  File "/opt/miniconda3/envs/ldm/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 961, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 973, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'optimizedSD'

あれ、何だ?optimizedSDがない?

調べてみると、新しくディレクトリ作って作業しているので、PythonのEnvを作り直す必要があるそうだ

(ldm) root@21feb17171f4:/workspaces/StableDiffusion2/basujindal/stable-diffusion# conda deactivate       
(base) root@21feb17171f4:/workspaces/StableDiffusion2/basujindal/stable-diffusion# conda remove -n ldm --all
(base) root@21feb17171f4:/workspaces/StableDiffusion2/basujindal/stable-diffusion# conda env create -f environment.yaml 
(base) root@21feb17171f4:/workspaces/StableDiffusion2/basujindal/stable-diffusion# conda activate ldm

よし、気を取り直して実行だ

(ldm) root@21feb17171f4:/workspaces/StableDiffusion2/basujindal/stable-diffusion# python optimizedSD/optimized_txt2img.py --prompt "a photograph of an astronaut riding a horse" --H 512 --W 512 --seed 27 --n_iter 2 --n_samples 10 --ddim_steps 50
Global seed set to 27
Loading model from models/ldm/stable-diffusion-v1/model.ckpt
Global Step: 470000
UNet: Running in eps-prediction mode
CondStage: Running in eps-prediction mode
Downloading: "https://github.com/DagnyT/hardnet/raw/master/pretrained/train_liberty_with_aug/checkpoint_liberty_with_aug.pth" to /root/.cache/torch/hub/checkpoints/checkpoint_liberty_with_aug.pth
100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 5.10M/5.10M [00:00<00:00, 21.2MB/s]
Downloading: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████| 939k/939k [00:01<00:00, 854kB/s]
Downloading: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████| 512k/512k [00:00<00:00, 567kB/s]
Downloading: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 389/389 [00:00<00:00, 366kB/s]
Downloading: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 905/905 [00:00<00:00, 804kB/s]
Downloading: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████| 4.31k/4.31k [00:00<00:00, 3.92MB/s]
Downloading: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████| 1.59G/1.59G [00:59<00:00, 28.5MB/s]
Killed

いきなり殺された。。。

stable_diffusion.openvino を WSL2 で実行したけど”Killed” されちゃった人へ
https://zenn.dev/suzuki5080/articles/1438d52377b9df

調べてみると、これも結局はメモリが不足しているために発生しているという可能性が高い。
そして、WSL2に対する割当メモリを変えることで、この問題は解消する可能性が!

[wsl2]
memory=12GB

.wslconfigファイルを配備して、再起動。
そして再チャレンジ

(ldm) root@21feb17171f4:/workspaces/StableDiffusion2/basujindal/stable-diffusion# python optimizedSD/optimized_txt2img.py --prompt "a photograph of an astronaut riding a horse" --H 512 --W 512 --seed 27 --n_iter 2 --n_samples 10 --ddim_steps 50
Global seed set to 27
Loading model from models/ldm/stable-diffusion-v1/model.ckpt
Global Step: 470000
UNet: Running in eps-prediction mode
CondStage: Running in eps-prediction mode
FirstStage: Running in eps-prediction mode
making attention of type 'vanilla' with 512 in_channels
Working with z of shape (1, 4, 32, 32) = 4096 dimensions.
making attention of type 'vanilla' with 512 in_channels
Sampling:   0%|                                                                                                                             | 0/2 [00:00<?, ?it/sseeds used =  [27, 28, 29, 30, 31, 32, 33, 34, 35, 36]                                                                                       | 0/1 [00:00<?, ?it/s]
Data shape for PLMS sampling is [10, 4, 64, 64]
Running PLMS Sampling with 50 timesteps
PLMS Sampler: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████| 50/50 [06:46<00:00,  8.13s/it]
torch.Size([10, 4, 64, 64])
saving images 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████| 50/50 [06:46<00:00,  8.38s/it]
memory_final =  7.72352
data: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [07:04<00:00, 424.21s/it]
Sampling:  50%|██████████████████████████████████████████████████████████                                                          | 1/2 [07:04<07:04, 424.21s/itseeds used =  [37, 38, 39, 40, 41, 42, 43, 44, 45, 46]                                                                                       | 0/1 [00:00<?, ?it/s]
Data shape for PLMS sampling is [10, 4, 64, 64]
Running PLMS Sampling with 50 timesteps
PLMS Sampler: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████| 50/50 [07:19<00:00,  8.79s/it]
torch.Size([10, 4, 64, 64])
saving images 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████| 50/50 [07:19<00:00,  8.62s/it]
memory_final =  6.833664
data: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [07:27<00:00, 447.21s/it]
Sampling: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [14:31<00:00, 435.71s/it]
Samples finished in 15.12 minutes and exported to outputs/txt2img-samples/a_photograph_of_an_astronaut_riding_a_horse
 Seeds used = 27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46

できた!できたよ、ママン!

ようやく、なんとかStable Diffusionを動かすことが出来る環境を作ることができました。
Pythonに関する知識不足もさることながら、メモリ周りで苦労しますね。

せっかく環境を作ることができたので、もう少し触って遊んでみようと思っています

画像生成AIを触ってみた(未完)

少し前から結構色々な、画像生成AIが話題になっている。
LINEでテキストメッセージを送ると画像を返してくれるような、簡単に使えるようなものを作ってくれる人もいて、早速フレンドになったはいいものの、すぐに制限に引っかかってしまい、面白くない。

というわけで、公開されている内容なので自前で用意してみようと考えた

Stable Diffusion

公開されている画像生成AIで、一番メジャーそうなのはこの「Stable Diffusion」のようなので、まずはそちらを使ってみることにした。
使うにはNVIDIAのボードを積んでいる必要があるようだ。ちなみに私のラップトップのスペックはこんな感じだ

CPU:AMD Ryzen 9 5900HS with Radeon Graphics 3.30 GHz
Memory:16G
GPU0:NVIDIA GeForce RTX 3050 Ti Laptop GPU
GPU1:AMD Radeon(TM) Graphics

前準備

Docker Desktopは入っているものとします。
また、NVIDIAのCUDA Toolkitを入れる必要があるそうです
https://developer.nvidia.com/cuda-downloads

Hugging Faceから学習済みモデルを取得

Hugging Faceという、学習済みのモデルやデータセットなどを公開してくれているサイトがあるので、そちらで公開されているStable Diffusion用のモデルを使用します

HuggingFace
https://huggingface.co/


右上の「Sign Up」からアカウントを作成します。
必要事項を入力し、最終的にメールによるアクティベートを行った後に、モデルの利用申請を行います

公開されているモデルはいくつかありますが、今回は一番新しいv1-4を使いますので、こちらのページに行きます

CompVis/stable-diffusion-v1-4
https://huggingface.co/CompVis/stable-diffusion-v1-4

ライセンス条項を確認して、チェックを行い、リポジトリへのアクセス許可を得ます。

その後、ローカルにて下記コマンドでモデルをダウンロードします

>git clone https://huggingface.co/CompVis/stable-diffusion-v-1-4-original
Cloning into 'stable-diffusion-v-1-4-original'...
remote: Enumerating objects: 54, done.
remote: Counting objects: 100% (54/54), done.
remote: Compressing objects: 100% (53/53), done.
remote: Total 54 (delta 22), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (54/54), 71.74 KiB | 282.00 KiB/s, done.
Updating files: 100% (5/5), done.
Filtering content: 100% (2/2), 7.14 GiB | 14.32 MiB/s, done.

>dir
stable-diffusion-v-1-4-original のディレクトリ

2022/09/04  22:31    <DIR>          .
2022/09/04  22:23    <DIR>          ..
2022/09/04  22:23             1,478 .gitattributes
2022/09/04  22:23            11,891 README.md
2022/09/04  22:32     7,703,807,346 sd-v1-4-full-ema.ckpt
2022/09/04  22:29     4,265,380,512 sd-v1-4.ckpt
2022/09/04  22:23            71,237 v1-variants-scores.jpg
               5 個のファイル      11,969,272,464 バイト

clone すると、ユーザ・パスワードを聞かれるので HuggingFace のユーザ名/パスワードを入力します。
clone結果としては上記のような形で、11GBほどファイルがありますね。。。

sd-v1-4.ckptmodel.ckptにリネームしておきます。

Dockerでの環境構築

Dockerのベースイメージに関してはNVIDIA Cloudのものを利用すると良さそうと偉い人が言っているので素直に真似る

FROM nvcr.io/nvidia/cuda:11.7.1-cudnn8-runtime-ubuntu20.04

ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=Asia/Tokyo

RUN apt-get update && apt-get install -y wget git git-lfs libglib2.0-0 libsm6 libxrender1 libxext-dev

RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh && \
    sh Miniconda3-latest-Linux-x86_64.sh -b -p /opt/miniconda3 && \
    rm -r Miniconda3-latest-Linux-x86_64.sh

ENV PATH /opt/miniconda3/bin:$PATH

RUN git clone https://github.com/CompVis/stable-diffusion && \
    cd stable-diffusion && \
    conda init bash && \
    conda env create -f environment.yaml && \
    echo "conda activate ldm" >> ~/.bashrc

さらに、DockerComposeを用意する

version: '3'
services:
  app:
    build: .
    working_dir: /stable-diffusion
    tty: true
    volumes:
      - ./stable-diffusion-v-1-4-original/:/stable-diffusion/models/ldm/stable-diffusion-v1/
      - ./outputs:/stable-diffusion/outputs
    deploy:
      resources:
        reservations:
          devices:
            - capabilities: [gpu]
    environment: 
      - NVIDIA_VISIBLE_DEVICES=all
      - NVIDIA_DRIVER_CAPABILITIES=all

さて、動かすぞ

>docker-compose up --build
[+] Building 2.1s (8/8) FINISHED
 => [internal] load build definition from Dockerfile                                                               0.0s
 => => transferring dockerfile: 717B                                                                               0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [internal] load metadata for nvcr.io/nvidia/cuda:11.7.1-cudnn8-runtime-ubuntu20.04                             2.0s
 => [1/4] FROM nvcr.io/nvidia/cuda:11.7.1-cudnn8-runtime-ubuntu20.04@sha256:4ee00dd83e88e75739870df5ac67ec38bea09  0.0s
 => CACHED [2/4] RUN apt-get update && apt-get install -y wget git git-lfs libglib2.0-0 libsm6 libxrender1 libxex  0.0s
 => CACHED [3/4] RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh &&     sh Minicon  0.0s
 => CACHED [4/4] RUN git clone https://github.com/CompVis/stable-diffusion &&     cd stable-diffusion &&     cond  0.0s
 => exporting to image                                                                                             0.0s
 => => exporting layers                                                                                            0.0s
 => => writing image sha256:5d2c7f98241a55c1f2b608d865bfb22e09b1f91dc425d86db7a55d8e2b4d7b07                       0.0s
 => => naming to docker.io/library/stablediffusion-app                                                             0.0s

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
[+] Running 1/0
 - Container stablediffusion_app_1  Recreated                                                                      0.1s
Attaching to stablediffusion-app-1

シーン。。。。

ここから、うんともすんとも言わなくなってしまった。
せめてエラーでも出してくれればいいのだが、いくら待っても何度やり直しても結果が変わらないので、きっと何かが足りないのであろう。。。
げせぬ

というわけで、一旦Docker Composeは諦めて、DevContainerで試行錯誤してみることにした。
続きは明日。。

参考: Stable DiffusionをDockerで動かすhttps://zenn.dev/choshicure/scraps/14bca2492bf49f

SmartMirror妄想

先日、AWS のオンラインセミナーシリーズであるBlack Beltを見ていたら、こんなものが

見る限りでは、まだまだ改良の余地がありそうな顧客体験に感じるけれど、ちょっと未来的ですよね、SmartMirror。

そこで、SmartMirrorに関してちょっと調べてみた

SmartMirrorの仕組み

そもそもの話、鏡とは?ということに関してもちゃんと知らないことに気がつく。
そもそも鏡とガラスってどう作られるのか?ガラスはなんか砂を溶かしてやるって漫画で見たぞ?

こちらのサイトを見る限りでは、鏡=ガラス+銀 or アルミニウム背面のようだ。

SmartMirrorでは、背面としてディスプレイを使うし、鏡自体もマジックミラーを使うらしい。

ラズパイを用いる

作り上げるにはRaspberryPiを使うと、すでに世の中にはノウハウが溜まっていて楽そうだ。特にOSSでMagicMirrorを作るためのプラットフォームが用意されている

MagicMirror²
https://magicmirror.builders/

調べてみるとYouTubeにもDIY動画などが上がっていて、意外と簡単に作ることができそうだ。

何に使うのか

実装そのものは、技術的には別に問題なくできそうだ。
とは言え、作ったとして何にどう使うのか?を考えてみたい。

事例としてよく挙げられている内容としては、鏡に天気予報やニュース、メッセージなどを出すということなんだけど・・・

スマホでいいよね?

という結論に至ってしまう。もしくはスマートウォッチ。

鏡に文字が浮かび上がるのは、未来感もあるし、言ってしまうとSF的な感じもする。
ロマンだ

だけどせっかくなら有用な利用用途を考え出したい。

スマホなどと違って、鏡であること。
それであって、RaspberryPiで出来るレベルの表現

思いつかないな。。。

とりあえず、いつの日かロマンを追い求めて作り出すかもしれないので、見つけたサイトを備忘録に載せておくことにする

Denoの今後に関して

先日、Denoの記事を書いたが、ちょうど公開されたmozaic.fmで話題に上がっていた

ep102 Monthly Ecosystem 202208
https://mozaic.fm/episodes/102/monthly-ecosystem-202208.html

Big Changes Ahead for Deno
https://deno.com/blog/changes

Denoの記事が投稿されたのが8/15。
mozaic.fmの公開が8/20ということで、いま時点から考えてもなかなか早い話題だ。

正直言って私はこのあたりの知見がないと言っても過言ではないレベル感なので、評価的なコメントは難しいし、誰も望んでいないだろうからしない。

ただ、いつも思うのはJavaScriptやTypeScript周りのフレームワークやエコシステムの数の多さというか、流行り廃れのスピード感はすごいな、と思わずにはいられない。

mozaic.fmの中でも話題にはなっていたが、それぞれの仕組みが何を目指して、それを使うモチベーションやメリットがどこに有るのか?というのだけでもちゃんと抑えていきたいところ。

話の中で出てきた、ViteやBunに関しても恥ずかしながら知らなかった。。。
うーん、追っかけるの実際問題難しいよなー

Bun
https://bun.sh/

Vite
https://vitejs.dev/

データモデリングで頭の体操

今まで、定期購読はしているものの、なかなか有効活用できていなかったWEB+DBプレスですが、今月号は結構読むことができています。
これも通勤の効果でしょうか?

特集の一番目は「実践データモデリング」

私自身、前職では基幹系の業務システムパッケージの開発に従事していたこともあって、題材として登場する「発注」や「出荷」といった業務のデータ構造や業務知識に関しては知らないわけではない。むしろ、一般的に考えると詳しい方なのでは?と思わなくもない。
というわけで、読みながら勉強になるな、と思う反面、やっぱりこのあたりは難しい問題だよな、と思ってしまうんですよね。

ソフトウェアを作る上での複雑さへの挑戦

現在は基本的に大きいプログラムを作るのではなく、責務を適切に分割し、シンプルな単位でのプログラムを組み合わせてシステムを作るのが良いとされている。

これに関して異を唱えるつもりはあまりない

前職でも、パッケージを作ったとしてもバージョンアップを考える必要があり、バージョンアップの際には過去との仕様互換性を保ちながら巨大なプログラムを新しい言語なりで作り直すとか、デスマーチ確定な感じだった。

パッケージのバージョンアップには多大な工数と期間を要し、既存顧客からは仕様の互換性に関して文句を言われ、新規の顧客からは不具合を指摘される。
もうちょっとうまいことできないものなのか。毎回スクラップ&ビルドはもうやりたくないと。

そうではなく小さいプログラムにする。更には責務の分割、モジュールの分割を進めることで、サービスを切り出す。
そしてサービス単位でバージョンアップすることを可能にしていくというのが今の流れで、その最たるものがマイクロサービスなんだと理解している。

本書でのデータモデリングも、単一テーブルにあれこれ詰め込むのではなくて責務を分割統治していくのが基本だ。

システムとして何を優先させるべきなのか

一方で、この方法だとそもそも取り扱う業務数が多い基幹系システムだと、テーブル数がかなりの数になるのでパフォーマンスの懸念は生じてしまう。
テーブル数が多くなることで、一つ一つはシンプルなんだけど、数が多すぎてひよるということもある。

特にパフォーマンスに関してはこだわりが強い人達が多いのも基幹系システムのユーザ特徴だ。
メインフレームCUI画面とWebブラウザを比較して、おそすぎると言われるの辛いよね。

データモデルをシンプルにするということは、基本的には機能もシンプルになっていくものだと理解している。
一方で、一目ですべての情報を把握したい。より多くの情報を画面に詰め込みたい。しかも早く。みたいな要求も当然のようにやってくる。

なぜなら、今がそうだから、みたいな理由で。

SoRである基幹システムのユーザは、システムを使って入力することが業務なのではなく、価値を生み出す業務は別にあるという認識は強い。
画面遷移なく、ショートカットキー盛りだくさんで何分でどれだけデータを入れられるかや判断できるかの選手権が行われている。

あれもこれも表示させる画面を超スピードで表示させるには、できるだけテーブルJOINを少なくするような、言ってしまうと下手くそなデータモデルだなぁと言われるようなテーブルになりそう。

それもこれも、個別最適化されたような過去のカスタマイズ遺産みたいなものがだめなんだ!って言うのは簡単なんだけど、ソフトウェアかくあるべきみたいな喧嘩をしてもしょうがないしね。

実際のところ、現代においてもパフォーマンス上やっぱり問題なのだろうか?みたいなところに関してはわからないのだが、こうやって頭の中で考えると言うのは結構楽しいものである。現実は厳しいけれど。

そんなことを思った2022年の夏。皆様はいかがお過ごしでしょうか。

私は元気です

Deno Fresh環境の構築とチュートリアル

少し前になるが、DenoにおけるフロントエンドWeb開発フレームワークとしてFreshがリリースされている

https://fresh.deno.dev/

今月のWEB+DB Press の裏表紙を見たら、Denoが広告を打っていて超びっくりした

せっかくなのでさわりとして、いくつかの情報をまとめた

Denoとは

Node.js の作者であるライアン・ダール氏によって作成された、Node.jsにおける反省点を踏まえて作られたJavaScript 及び TypeScript のランタイム環境

Node.js環境下では、TypeScriptはトランスパイラを通したりビルドしたりする必要があるがDenoはTypeScriptをそのまま実行することができるようになります。

特にNode.jsと比較して強化されているのはセキュリティ周りです。
Denoはデフォルトでサンドボックス内で動作する形を取っているため、明示的にアクセスを許可してあげないとファイルシステムなどへのアクセスの確認が頻発したりします。

Fresh

TypeScriptのランタイム環境としてのDenoは、それはそれでTypeScript使いに取ってはいいものに見えましたが、Webフロントエンド開発は別に用意する必要がありました。

ところが、今年の7月にDeno用のフルスタックWebフレームワークとしてFreshをリリースしました

ちなみに、8/16現在でバージョンは1.0.2
できたてホヤホヤですな

Freshの特徴としては Islands Architecture を採用しており極力SSRで処理を行う形でクライアント側でのJavaScript配信を行わないような思想のようです

Islands Architecture
https://www.patterns.dev/posts/islands-architecture/

環境構築とチュートリアル

せっかくなので環境はDockerを使ってやろうと。
このあたりは、あちこち参考にさせていただきながらやっているのでツッコミどころは満載かも知れないが、誰かの役に立てればと思いDockerFileを公開する

FROM debian:stable-slim

WORKDIR /var/www/html

RUN apt-get -qq update \
  && apt-get -qq -y install curl zip unzip \
  && curl -fsSL https://deno.land/x/install/install.sh | sh \
  && apt-get -qq remove curl zip unzip \
  && apt-get -qq remove --purge -y curl zip unzip \
  && apt-get -qq -y autoremove \
  && apt-get -qq clean \
  && echo 'export DENO_INSTALL="/root/.deno"' >> ~/.bash_profile \
  && echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> ~/.bash_profile

CMD ["/bin/bash", "-c", "source ~/.bash_profile && bash"]

チュートリアルに関しては公式を参照

Getting Started
https://fresh.deno.dev/docs/getting-started

Denoでは、Deploy先としてDeno Deployというエッジ環境を提供してくれているので、Githubと連携させたりしてPush=Deployの環境の構築も簡単にできた。

チュートリアルがうまくいかない?

Deno の Web フレームワーク Fresh チュートリアル
https://zenn.dev/azukiazusa/articles/fresh-tutorial

チュートリアルを用意してくれている人もいたので、こちらもやってみた。
ただ、スタイルの適用が何故かうまく行ってくれずに困っている

https://krote–ample-resh.deno.dev/blog

このあたり、フロントエンド開発はからっきしなので、ちょっと詰まってしまったなぁ。
開発者ツールで見る限りでは、想定した通りのclassが割り当てられているようにみえるんだけど。。。

まだまだですねぇ
教えて、偉い人。

Gartner先進技術ハイプ・サイクルと社内タレントマーケットプレイス

Gartnerが出しているハイプ・サイクル。
これの先進技術に関するものが公開されていました

Gartner Identifies Key Emerging Technologies Expanding Immersive Experiences, Accelerating AI Automation and Optimizing Technologist Delivery
https://www.gartner.com/en/newsroom/press-releases/2022-08-10-gartner-identifies-key-emerging-technologies-expanding-immersive-experiences-accelerating-ai-automation-and-optimizing-technologist-delivery

先進技術ということもあって、そのどれもが黎明期~過度な期待のピーク期という扱い。これら技術が幻滅期やそれ以降のフェーズへの生き残りをかけた戦いがこれから始まるわけですね。

先陣を切っているものが「Cloud Data Ecosystems」ということで、若干他のラインナップからするとここに並ぶのかな?という気がしないでもないです。
NFTに関しては、あと2~5年で安定期に入るとGartnerは予想しているんですね。

どの技術が実際に今後のキーとなるのか、ハイプ・サイクルからそれを導き出すというのはあまり現実的ではないかもしれないけれど、少なくともここに載っている内容に関しては、ある程度何を指し示しているのか、ということに関しては知っておくに越したことはないと考えている。

そういう意味で、ちょっと気になったものとしては「Internal Talent Marketplaces」というキーワードだ。

Internal Talent Marketplaces

正直あまり聞き慣れていない言葉ではあった。
デロイトのページがよく書かれているので読んでみた

社内に労働マーケットの考え方や手法を持ち込み、人材のキャリアやスキルを可視化・拡張し、柔軟に配置転換をしながら育成、活用するマネジメント・プラットフォームのあり方

https://www2.deloitte.com/jp/ja/pages/human-capital/articles/hcm/internal-talent-marketplace.html

タレントマネジメントは、ここ数年で随分といろいろな企業で話を聞くようになった。私が所属している会社でも、タレントマネジメントツールを導入している。
一方で、タレントマネジメントがちゃんとできているのか?という点や、そもそもなんでタレントマネジメントが必要なのか?ということに対して有効な動きを取ることができていないのが実情でもあるように感じる。

実際のところ、社内マーケットプレイスというものはどこまで有効なのだろうか?

プロジェクト単位にメンバーを公募。つまり社内のタレントマーケットから探し出して~というと、連続性のないプロジェクトであればいいかもしれないが、連続性のあるプロジェクト・業務の場合、どうしてもこれまでの業務知識なり経験というものがあると嬉しい状態になる。

もちろん、メンバーを固定化させたほうがいいというわけではなく、門出は開いておき流動性は持たせたい。
ただ、流動性をもたせ過ぎるとオンボーディングが大変になる。

また、全部のプロジェクトが同じ期間で区切りがあるなんてことはないだろうから、タイミングにも左右されるようになるんだろう。

一方で、新しいことへ挑戦するという風土みたいなものは培われるだろう。
また、そういった高いメンタリティでプロジェクトへJOINするのであれば、実際のところそこまで大きな問題にはならないのかもしれない。

つまりは、それだけ成熟した。レベルの高い組織であれば成り立つということなのかな?とも思った。全員売れ残りみたいな社内マーケットになり、有用なメンバーは全部外部調達(外注)なんてシャレにならないよ。

タレントマネジメント

社内マーケットプレイスに到達するのは一足飛びには難しいかもしれないけど、タレントマネジメントとして、自分が培った技術や知識を可視化して、それを自分が従事したいプロジェクトへアピールしていくという考え方はとても大事だとは思う。

日々の業務におわれていると、なかなか今この業務が自分のなんのスキルアップにつながる可能性があるだろうか?ということに関しては埋もれていってしまう。

また、それらを意識して仕事をするのとしないのとでは、明確にスキルアップ速度が異なると考えている。
そういう意味でも、もう少ししっかりとタレントマネジメントに関しては実施していく必要があるだろうな、と考えた。

iPhone13 Pro をゲット

iPhoneのタッチディスプレイが不調という報告をした直後ではありますが、iPhoneの13Proを購入しました。

今回、初めてProモデルを購入。
このところの自分のiPhoneの利用目的を考えてみたところ、コミュニケーションやゲームはもちろんのところ、性能に関していえばやはりカメラが占める割合はかなり高いのではないかと考えたのです。

以前は一眼レフのようなものに手を出してみたことはあるものの、やはり取り扱いが非常に繊細なのと、常に持ち運ぶのは難しいということから、スマホのカメラがよくなるというのであればそれにお金をかけることは問題ないという判断ですね。
(無事に復活したiPhoneXsは妻におさがりという形で渡す形で有効利用)

まだ、新機能であるシネマティックモードとかは使いこなしていませんが、あれこれとこれから試していってみようと思います。
でも実際にどうなんでしょうね。ぱっとシネマティックモードが自分の中で使えるタイミングというものがよくわかっていません。

よくわかっていないからこそ使ってみてというところでしょうか。
これを機に、今まで全く手を出してこなかった映像編集みたいなものもちょっと触ってみるのはありなのかもしれません。
そういうの出来たら、ちょっとかっこいい感じがするし