laiso 2024-03-15T21:55:47+09:00 laiso Hatena::Blog hatenablog://blog/13208692334729893091 WasmerのWinterJSのベンチマーク結果はあやしい hatenablog://entry/6801883189091043194 2024-03-15T21:55:47+09:00 2024-03-16T16:03:17+09:00 「WinterJS 1.0」の記事がシェアされていたので読んでいたのだけど「Bunより速くなった」と書かれていたので何事と思ってチェックしてみた wasmer.io ベンチマークの文書は以下に公開されている github.com で、まずエラーがめっちゃ出てる Socket errors: connect 155, read 108, write 0, timeout 29 それはいいとして(よくないが)、肝心なところはJarred Sumnerも指摘しているけどwrk -t12 -c400でリクエストの並列処置性能を測っているというのに違和感がある They’re benchmarking … <p>「WinterJS 1.0」の記事がシェアされていたので読んでいたのだけど「Bunより速くなった」と書かれていたので何事と思ってチェックしてみた</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwasmer.io%2Fposts%2Fwinterjs-v1" title="WinterJS 1.0 · Blog · Wasmer" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://wasmer.io/posts/winterjs-v1">wasmer.io</a></cite></p> <p>ベンチマークの文書は以下に公開されている</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fwasmerio%2Fwinterjs%2Ftree%2Fmain%2Fbenchmark" title="winterjs/benchmark at main · wasmerio/winterjs" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://github.com/wasmerio/winterjs/tree/main/benchmark">github.com</a></cite></p> <p>で、まずエラーがめっちゃ出てる</p> <blockquote><p>Socket errors: connect 155, read 108, write 0, timeout 29</p></blockquote> <p>それはいいとして(よくないが)、肝心なところはJarred Sumnerも指摘しているけど<code>wrk -t12 -c400</code>でリクエストの並列処置性能を測っているというのに違和感がある</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">They’re benchmarking their HTTP server running on 12 cores compared to Bun running on 1 core</p>&mdash; Jarred Sumner (@jarredsumner) <a href="https://twitter.com/jarredsumner/status/1767941079222059478?ref_src=twsrc%5Etfw">2024年3月13日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>winterjsサーバーはhyper(tokio)で書かれていてリクエストごとにマルチスレッドでコアを使ってSpiderMonkeyでスクリプトを実行してる</p> <p>シングルスレッドなBunで条件を近づけるなら<a href="https://github.com/oven-sh/bun/issues/2428">reusePort</a>オプションをLinuxで使ってマルチプロセスで<code>Bun.serve()</code>するか、Workers APIを使うとかやりようはありそう</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fbun.sh%2Fdocs%2Fapi%2Fworkers" title="Workers – API | Bun Docs" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://bun.sh/docs/api/workers">bun.sh</a></cite></p> <p>なのでWinterJSのサーバー実装だけマルチスレッドなので並列処置性能が高い(それはそう)という結果だと思った</p> <p>「Webサーバとして処理速度が速い」と言えば間違ってはいないんだろうけど'Blazing fast speeds than Bun...'から想像する内容とはギャップがある</p> <p>ただ私の環境(M1 Macbook Pro)では並列パラメータをいくら調整してもBunの方が速かったのだけど……</p> <p>そして<code>wrk -t1 -c1</code>にすると4倍Bunの方が秒間リクエストが出ていた。これは直感どうり</p> <pre class="code bash" data-lang="bash" data-unlink># WinterJS ❯ cargo run --release -- --version winterjs 0.4.3 ❯ cargo run --release -- ./simple.js ❯ wrk -t1 -c1 http://127.0.0.1:8080 Running 10s test @ http://127.0.0.1:8080 1 threads and 1 connections Thread Stats Avg Stdev Max +/- Stdev Latency 71.60us 212.70us 5.55ms 99.48% Req/Sec 16.67k 0.92k 19.30k 81.94% 119422 requests in 10.03s, 13.67MB read Requests/sec: 11910.93 Transfer/sec: 1.36MB</pre> <pre class="code bash" data-lang="bash" data-unlink># Bun ❯ bun -v 1.0.31 ❯ bun bun-simple.js ❯ wrk -t1 -c1 http://127.0.0.1:8080 Running 10s test @ http://127.0.0.1:8080 1 threads and 1 connections Thread Stats Avg Stdev Max +/- Stdev Latency 24.30us 49.42us 2.73ms 98.13% Req/Sec 47.46k 2.00k 50.59k 85.15% 476904 requests in 10.10s, 54.58MB read Requests/sec: 47221.50 Transfer/sec: 5.40MB</pre> <p>とはいえWinterJSのようなソフトウェアを作ってしまえるWasmerの人たちはすごいと思う</p> <p>ただ<a href="https://wasmer.io/products/edge">Wasmer Edge</a>はWasmをデプロイするサービスだし、なぜかWinterJS自体をWasmにして動かそうとしていて、これを作った理由が謎だけど</p> <h2 id="Tips-ビルドエラーの解決">Tips: ビルドエラーの解決</h2> <p>pythonバイナリのバージョンでwinterjsのビルドが失敗する時は以下で指定できる</p> <pre class="code bash" data-lang="bash" data-unlink>❯ PYTHON3=/usr/bin/python3 cargo build -r</pre> <p>lldがないとビルドできない</p> <pre class="code bash" data-lang="bash" data-unlink>❯ brew install llvm ❯ brew link -f llvm ❯ which lld /opt/homebrew/opt/llvm/bin/lld</pre> <h2 id="追記">追記</h2> <blockquote><p>シングルスレッドなBunで条件を近づけるなら<a href="https://github.com/oven-sh/bun/issues/2428">reusePort</a>オプションをLinuxで使ってマルチプロセスで<code>Bun.serve()</code>するか</p></blockquote> <p>やりました</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2F6761eb09aa5102" title="マルチプロセスなBun.serveの並列リクエスト処理性能を調べる" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/6761eb09aa5102">zenn.dev</a></cite></p> laiso 最近使ってる便利シェル関数: gh copilot suggest -t shell hatenablog://entry/6801883189087575054 2024-03-02T16:03:10+09:00 2024-03-02T16:03:57+09:00 「iOSシミュレータを起動するコマンドがあったんだけど忘れた」というような状況で便利 copilot() { gh copilot suggest -t shell "$@" } alias c="copilot" 忘れたのでコマンド履歴から検索してくることもままならない。そんな時はこう ❯ c launch ios sim Welcome to GitHub Copilot in the CLI! version 0.5.3-beta (2023-11-09) I'm powered by AI, so surprises and mistakes are possible. Make su… <p>「iOSシミュレータを起動するコマンドがあったんだけど忘れた」というような状況で便利</p> <pre class="code bash" data-lang="bash" data-unlink>copilot() { gh copilot suggest -t shell &#34;$@&#34; } alias c=&#34;copilot&#34;</pre> <p>忘れたのでコマンド履歴から検索してくることもままならない。そんな時はこう</p> <pre class="code bash" data-lang="bash" data-unlink>❯ c launch ios sim Welcome to GitHub Copilot in the CLI! version 0.5.3-beta (2023-11-09) I&#39;m powered by AI, so surprises and mistakes are possible. Make sure to verify any generated code or suggestions, and share feedback so that we can learn and improve. Suggestion: open -a Simulator ? Select an option [Use arrows to move, type to filter] &gt; Copy command to clipboard Explain command Revise command Rate response Exit</pre> <p>Copy command to clipboardして実行する</p> <p><code>gh copilot</code>はGitHubが提供しているCLI</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fdocs.github.com%2Fja%2Fcopilot%2Fgithub-copilot-in-the-cli%2Fusing-github-copilot-in-the-cli" title="CLI での GitHub Copilot の使用 - GitHub Docs" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://docs.github.com/ja/copilot/github-copilot-in-the-cli/using-github-copilot-in-the-cli">docs.github.com</a></cite></p> <p>難点としては結構間違ったことも言う。だが、ゆるしてやってくれ</p> laiso Sallybox Plus をゆずってもらった hatenablog://entry/6801883189079027821 2024-01-29T21:39:53+09:00 2024-01-29T21:50:34+09:00 Sallyboxはレバーレスコントローラーで、Plusは15ボタンのやつ front キーボードでスト6やってると書いていたら、世界の@k_katsumiさんがくれた PCキーボードの半分ぐらいの幅で第一印象はちっちゃと思ったけど慣れた 普段分割風キーボードを使っているので*1、左手と右手が近くて狭く感じだけどそれも慣れた 弁当箱みたいなサイズ感にRaspberry Piの基盤みたいなやつが入っててボタンはキーボード軸 back Hit Box の幅は 406.4 mmなので半分程度のサイズだけどHit Boxは触ったことないから比較できない モダンの時のボタン設定。「プロゲーマーがキーボード… <p>Sallyboxはレバーレスコントローラーで、Plusは15ボタンのやつ</p> <p><figure class="figure-image figure-image-fotolife" title="front"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20240129/20240129185316.jpg" width="2000" height="1500" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>front</figcaption></figure></p> <p><a href="https://laiso.hatenablog.com/entry/2023/12/24/213438">キーボードでスト6やってる</a>と書いていたら、世界の<a href="https://twitter.com/k_katsumi">@k_katsumi</a>さんがくれた</p> <p>PCキーボードの半分ぐらいの幅で第一印象はちっちゃと思ったけど慣れた</p> <p>普段分割風キーボードを使っているので<a href="#f-a2c22008" id="fn-a2c22008" name="fn-a2c22008" title="Keychron Q8を買った - laiso">*1</a>、左手と右手が近くて狭く感じだけどそれも慣れた</p> <p>弁当箱みたいなサイズ感にRaspberry Piの基盤みたいなやつが入っててボタンはキーボード軸</p> <p><figure class="figure-image figure-image-fotolife" title="back"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20240129/20240129185328.jpg" width="2000" height="1500" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>back</figcaption></figure></p> <p>Hit Box の幅は 406.4 mmなので半分程度のサイズだけどHit Boxは触ったことないから比較できない</p> <p>モダンの時のボタン設定。「<a href="https://www.youtube.com/watch?v=qPBJYTy6HVo">プロゲーマーがキーボードでランクマッチしてみた【マゴ】</a>」をキーボードに設定していたのを移行した</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20240129/20240129213303.png" width="2000" height="1337" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>クラシック。右手親指に投げがあると押しやすい気がする。「<a href="https://www.youtube.com/watch?v=k2KgDdGT14M">同時押しボタンを絶対に設定すべき理由- シノビチャンネル</a>」によると投げボタンがあった方が便利らしい</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20240129/20240129213547.png" width="2000" height="1361" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>キーボードで真空波動とか出せる気がしなかったのでモダンしか使ってなかったけどこのコントローラーならいけそうだったのでクラシックに切り換えようと思ってる</p> <div class="footnote"> <p class="footnote"><a href="#fn-a2c22008" id="f-a2c22008" name="f-a2c22008" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://laiso.hatenablog.com/entry/2022/08/20/KeychronQ8">Keychron Q8を買った - laiso</a></span></p> </div> laiso 東京都同情塔:テキスト生成AIブームにふさわしい芥川賞受賞作 hatenablog://entry/6801883189078614391 2024-01-28T11:34:31+09:00 2024-01-28T13:01:49+09:00 『東京都同情塔』は第170回芥川賞受賞作品で、「ChatGPTを駆使して書かれた」と話題になっていてたので気になって読みました。 東京都同情塔作者:九段理江新潮社Amazon この記事はあらすじに含まれないストーリーについて言及しています。 あらすじ 日本人の欺瞞をユーモラスに描いた現代版「バベルの塔」 ザハの国立競技場が完成し、寛容論が浸透したもう一つの日本で、新しい刑務所「シンパシータワートーキョー」が建てられることに。犯罪者に寛容になれない建築家・牧名は、仕事と信条の乖離に苦悩しながらパワフルに未来を追求する。ゆるふわな言葉と、実のない正義の関係を豊かなフロウで暴く、生成AI時代の預言の… <p>『東京都同情塔』は第170回芥川賞受賞作品で、「ChatGPTを駆使して書かれた」と話題になっていてたので気になって読みました。</p> <p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/B0CQ7GXR6N?tag=rer-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/411Xe1qEvYL._SL500_.jpg" class="hatena-asin-detail-image" alt="東京都同情塔" title="東京都同情塔"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/B0CQ7GXR6N?tag=rer-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" target="_blank" rel="noopener">東京都同情塔</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="https://d.hatena.ne.jp/keyword/%B6%E5%C3%CA%CD%FD%B9%BE" class="keyword">九段理江</a></li><li>新潮社</li></ul><a href="https://www.amazon.co.jp/dp/B0CQ7GXR6N?tag=rer-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p> <p><strong>この記事はあらすじに含まれないストーリーについて言及しています。</strong></p> <h2 id="あらすじ">あらすじ</h2> <blockquote><p>日本人の欺瞞をユーモラスに描いた現代版「バベルの塔」 ザハの国立競技場が完成し、寛容論が浸透したもう一つの日本で、新しい刑務所「シンパシータワートーキョー」が建てられることに。犯罪者に寛容になれない建築家・牧名は、仕事と信条の乖離に苦悩しながらパワフルに未来を追求する。ゆるふわな言葉と、実のない正義の関係を豊かなフロウで暴く、生成AI時代の預言の書</p></blockquote> <h2 id="感想">感想</h2> <p>メディアでは権威ある文学賞までもAIにハックされたと技術の発展を煽るような論調でしたが、私の印象では「文学界までAIブームに乗ってきた」というものでした。</p> <p>作中の世界の重要なこととして対話型AIに人々が重度に依存しているのですが、その部分にはあまり宣伝で触れられていません</p> <p>私も「生成AI時代の預言の書」という部分にまんまと釣られたということです</p> <p>物語は2026年の架空の東京都を舞台にしていていわゆるパラレルワールドになっています。</p> <p>実際のザハ・ハディドの国立競技場の初期案は、最終的には採用されませんでした。</p> <p>巨大建築の建設は覆るのは不可能なので、この世界は訪ずれることのありえない現実というのを表わしていると感じます</p> <p>作中には新型コロナに関する具体的な記述はないものの、パンデミック自体は起こっていて、さらにこの世界では東京オリピックは延期せず強行されたことになっています</p> <p>この実際の歴史との誤差が結構絶妙で、私が掘り下げたい部分です</p> <p>まず文章(テキスト)生成AIという用語を使っていなく「文章構築AI」と一貫しているのは意図的だと思います</p> <p>新たな作品を生成しているのではなく既存の価値観を他者を傷つけないよう中立的に組み立て、構築している。という表現と建築のメタファーだと思いました</p> <p><a href="https://www.asahi.com/articles/DA3S15849837.html">朝日新聞デジタルの取材記事</a>にもこの設定の背景が出てきます(有料記事なので中身には触れません)</p> <p>全体的にAIの構築する文章に社会が依存しつつもそれを好ましく思ってないような記述が多いです</p> <p>作中で「AIネイティブな世代」の青年として描かれている人物はAI使って文章を書くことを批判的に捉えています</p> <blockquote><p>彼女の積み上げる言葉が何かに似ているような気がして記憶を辿ると、それがAIの構築する文章であることに思い当たった。いかにも世の中の人々の平均的な望みを集約させた、かつ批判を最小限に留める模範的回答。平和。平等。尊厳。尊重。共感。共生。質問したそばからスクロールを促してくるせっかちな文字が脳裏に浮かぶ。彼らがポジティヴで貧乏な言葉をまくし立てる様を一度イメージしてしまうと、いくら彼女の声がしていても、すべてがAI-builtの言葉としてしか聞こえなくなった。そしてなぜか僕は、文章構築AIに対しての憐みのようなものを覚えていた。かわいそうだ、と思っていた。他人の言葉を継ぎ接ぎしてつくる文章が何を意味し、誰に伝わっているかも知らないまま、お仕着せの文字をひたすら並べ続けなければいけない人生というのは、とても空虚で苦しいものなんじゃないかと同情したのだ。けれどもちろんAIには、苦しみも喜びも人生もなく、傷付くこともないのだから、別に意味のない同情だ。人間だからといって誰しもが難なく言葉を扱えるというのでもないけれど、少なくとも人間は喋りたくないときには黙ることができる。</p></blockquote> <p>なので犯罪者の身の上に共感して新宿御苑側のタワーマンション機能を持つ刑務所で手厚く保護する先鋭化した「訪ずれない世界」で文章構築AIが支配的な影響を持つことで逆説的に現在の未来はそうならないことを望んでいるように思います</p> <p>以下は著者の会見の発言です</p> <blockquote><p>この作品は、言葉で何かを解決しよう、言葉で対話をするということを、あきらめたくないと思っている方のために書いた作品と思っています。言葉で解決できないことというのは、何によっても絶対に解決できないと私自身は考えております。</p> <p><a href="https://www.sankei.com/article/20240117-AAZSAIEHVJOJLEQOZTZPNHDDIQ/">「言葉による解決、あきらめたくない」芥川賞の九段理江さん会見 - 産経ニュース</a></p></blockquote> <p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/B0CQ7GXR6N?tag=rer-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/411Xe1qEvYL._SL500_.jpg" class="hatena-asin-detail-image" alt="東京都同情塔" title="東京都同情塔"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/B0CQ7GXR6N?tag=rer-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" target="_blank" rel="noopener">東京都同情塔</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="https://d.hatena.ne.jp/keyword/%B6%E5%C3%CA%CD%FD%B9%BE" class="keyword">九段理江</a></li><li>新潮社</li></ul><a href="https://www.amazon.co.jp/dp/B0CQ7GXR6N?tag=rer-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p> laiso builder.ioでのLLMを使ったサービス開発の実際 hatenablog://entry/6801883189071563403 2024-01-01T18:09:26+09:00 2024-01-01T20:42:17+09:00 builder.ioのSteve Sewell(CEO)が書いた「まだChat Completions APIで消耗してるの?」というトーンの記事を読んだ builder.ioはQwikの開発元で知られるCMS SaaS(Qwikの話は出てこない) www.builder.io www.builder.io 記事はVisual CopilotというFigmaのデザインをReactコンポーネント等のコードに変換する機能の裏側について解説している 「FigmaをReactコンポーネントに変換!」だけだとプロ驚き屋アカウントに消費されて右から左に流れていきそうなニュースバリューだけど、昨今のLLMs… <p>builder.ioのSteve Sewell(CEO)が書いた「まだChat Completions APIで消耗してるの?」というトーンの記事を読んだ</p> <p>builder.ioは<a href="https://qwik.builder.io/">Qwik</a>の開発元で知られるCMS SaaS(Qwikの話は出てこない)</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.builder.io%2Fblog%2Fbuild-ai" title="Don’t Build AI Products The Way Everyone Else Is Doing It" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.builder.io/blog/build-ai">www.builder.io</a></cite></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.builder.io%2Fblog%2Ftrain-ai" title="Training Your Own AI Model Is Not As Hard As You (Probably) Think" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.builder.io/blog/train-ai">www.builder.io</a></cite></p> <p>記事は<a href="https://www.builder.io/blog/figma-to-code-visual-copilot">Visual Copilot</a>というFigmaのデザインをReactコンポーネント等のコードに変換する機能の裏側について解説している</p> <p>「FigmaをReactコンポーネントに変換!」だけだとプロ驚き屋アカウントに消費されて右から左に流れていきそうなニュースバリューだけど、昨今のLLMs App開発についての実践的なアーキテクチャの話とopinionatedなことが書かれているのが面白かったので紹介します</p> <p>この2つの記事で言いたいことは「ChatGPTというハンマーが万能過ぎてすべてが釘に見えるけど、それぞれのタスクを分解して個別に解決した方が効率的」ということだと思う</p> <p>ディープラーニング全盛(バズワードとして)の時にコンサルが「ディープラーニング以外で解決しましょう」と提案してもエグゼクティブにはあんまりウケないという状況のように、この記事も思ったほど話題になっていなかった(<a href="https://news.ycombinator.com/item?id=38221552">Hacker News</a>には一応コメントが多数ある)</p> <p>複数のLLMを連携させてAgentを作るという話題は活発だけど、実際にLLMを活用して現実のプロダクトにどうやって適用しているのかという部分に注目した</p> <h1 id="アーキテクチャ">アーキテクチャ</h1> <p>Visual CopilotはFigmaからJSXなコンポーネントに変換するのに以下のパイプラインを辿る</p> <p><figure class="figure-image figure-image-fotolife" title="https://www.builder.io/blog/train-ai"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20240101/20240101173118.png" width="1856" height="1082" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption><a href="https://www.builder.io/blog/train-ai">https://www.builder.io/blog/train-ai</a></figcaption></figure></p> <p>Identify imagesはデザイン上の画像を認識し、Build layout hierarchyはHTMLの構造解析、Apply stylesはCSSのスタイル情報、Turn to (basic) codeは内部コード表現(<a href="https://github.com/BuilderIO/mitosis">Mitosis</a>?)の生成、Customize codeはそれをReactやSvelte形式に変換することだと思う</p> <p>このうちIdentify imagesとBuild layout hierarchyをGoogle Cloudの<a href="https://cloud.google.com/vertex-ai?hl=ja">Vertex AI</a>で実装して、Apply stylesとTurn to (basic) codeはコードでロジック書いて、Customize codeは既存のLLMをファインチューニングして使っているらしい(時期的にgpt-3.5-turbo?)</p> <p>またデータセットの運用が重要という話が出てくる。Visual Copilotでは人間が変換結果を確認してフィードバックして精度を高めていったらしい</p> <p>記事の結論としては</p> <ol> <li>最初に既存のLLM(例えばGPT-3やGPT-4)を使用してみる</li> <li>コストやカスタマイズ性の問題がある場合は、独自のモデルをトレーニングする</li> <li>データセットの運用で品質を上げる</li> <li>コードで実装できる個所は書く</li> </ol> <p>という方法が推奨されている</p> <p>Visual Copilotでは最後の工程のみをLLMで行い、その事前処理は従来の機械学習モデルと変換コードで実装された</p> <h1 id="感想パート">感想パート</h1> <p>「Apply stylesとTurn to (basic) code」の変換処理実装するのEasyじゃねぇ・・ と思いつつも、それぞれを比較してこの人たちの能力から見ればそうなのでしょう</p> <p>一見ChatGPT以前もそう作っていたのでは? と思うかもしれないけどGPTが汎用的に賢いので肝であるデータセットの自動生成のタスクにも役立つという環境の違いはあると思う</p> <p>冷静に考えるとVertex AI便利話に読めるけど、この頃はGPTの<a href="https://platform.openai.com/docs/guides/vision/vision">Vision API</a>も公開されていなかったので現在なら物体検知のプロトタイプを作るのは更に捗るのかもしれない</p> <p>コストについては自前した方がOpenAIより優位だとは思うけどVertex AIを使っているのでそことの比較になってくるのでは…… と思った</p> <p>コードで実装したぶんがLLM使わなかったので削減されたと解釈するべきか</p> <p>Vertex AIは個人的に趣味でデプロイして使っていたことあるんですけど一晩のトレーニングで諭吉sが吹っ飛んだ経験があるので、あまりインディーデベロッパーの用途に優しい印象はない</p> <p>安く使う方法があるのか代替手段があるのか是非読者にご教示いただきたい</p> <p>今はGPUを買って自宅サーバーでやろうとしている</p> laiso 更新されたら真っ先に聴いているおすすめポッドキャスト hatenablog://entry/6801883189071312313 2023-12-31T18:59:40+09:00 2024-01-02T17:25:07+09:00 ポッドキャストはリスナーの存在が見えづらいらしく聴いてるとアピールしないと更新停止してしまいがちなので定期的に感想を書いていく 聴く環境について ポッドキャストの探し方 BUSINESS WARS / ビジネスウォーズ News Connect あなたと経済をつなぐ5分間 #ニュースコネクト Off Topic // オフトピック fukabori.fm バンクーバーのえんじに屋 texta.fm プログラム雑談 Misreading Chat mozaic.fm kkeethのエンジニア雑談チャンネル 購読一覧 聴く環境について クライアントはGoogle Podcastを使っているんですけ… <p>ポッドキャストはリスナーの存在が見えづらいらしく聴いてるとアピールしないと更新停止してしまいがちなので定期的に感想を書いていく</p> <ul class="table-of-contents"> <li><a href="#聴く環境について">聴く環境について</a></li> <li><a href="#ポッドキャストの探し方">ポッドキャストの探し方</a></li> <li><a href="#BUSINESS-WARS--ビジネスウォーズ">BUSINESS WARS / ビジネスウォーズ</a></li> <li><a href="#News-Connect-あなたと経済をつなぐ5分間-ニュースコネクト">News Connect あなたと経済をつなぐ5分間 #ニュースコネクト</a></li> <li><a href="#Off-Topic--オフトピック">Off Topic // オフトピック</a></li> <li><a href="#fukaborifm">fukabori.fm</a></li> <li><a href="#バンクーバーのえんじに屋">バンクーバーのえんじに屋</a></li> <li><a href="#textafm">texta.fm</a></li> <li><a href="#プログラム雑談">プログラム雑談</a></li> <li><a href="#Misreading-Chat">Misreading Chat</a></li> <li><a href="#mozaicfm">mozaic.fm</a></li> <li><a href="#kkeethのエンジニア雑談チャンネル">kkeethのエンジニア雑談チャンネル</a></li> <li><a href="#購読一覧">購読一覧</a></li> </ul> <h1 id="聴く環境について">聴く環境について</h1> <p>クライアントはGoogle Podcastを使っているんですけど終了してしまうし<a href="#f-ce0a4e66" id="fn-ce0a4e66" name="fn-ce0a4e66" title="Google Podcasts、2024年に終了へ YouTube Musicに統合 - ITmedia NEWS">*1</a>最近はSpotifyに誘導されがちなので、今後移行先をどうしようか迷っている</p> <p>そもそもGoogle Podcastの購読一覧ってどこから見るんだろうと疑問だったが、<a href="https://takeout.google.com/">https://takeout.google.com/</a>からエクスポートしてくれやということらしい</p> <h1 id="ポッドキャストの探し方">ポッドキャストの探し方</h1> <p>Google Podcastはエピソード単位の検索に優れていて、それが愛用している理由だった(やめないで)</p> <p>たとえば<a href="https://podcasts.google.com/search/rust%E3%81%AF">Google Podcasts - rust&#x306F;</a>で検索すると日本語でRustについて話してそうなポッドキャストが見つかる</p> <p>あとは<a href="https://podcastfreaks.com/">Podcast Freaks</a>という地道にテック系のポッドキャストを収集して公開しているページがあるので、そこから見つけたポッドキャストも多い</p> <p>はてなユーザーにはお馴染の近藤さんがやってる<a href="https://listen.style/">LISTEN</a>もある</p> <p>専用のポッドキャストクライアントアプリが必要なプラットフォームはカバーできてない</p> <h1 id="BUSINESS-WARS--ビジネスウォーズ">BUSINESS WARS / ビジネスウォーズ</h1> <p>BUSINESS WARSはいわゆるプロのラジオドラマ制作会社が作っているコンテンツで、アメリカの現Amazon子会社の本番組<a href="#f-5e73e7b7" id="fn-5e73e7b7" name="fn-5e73e7b7" title="Business Wars with David Brown">*2</a>をニッポン放送が権利を持って翻訳して配信しているようだ</p> <p><iframe src="https://art19.com/shows/business-wars-jp/embed" style="width: 720px; height: 505px; border: 0 none;" width="720" height="505" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://art19.com/shows/business-wars-jp">art19.com</a></cite></p> <p>内容はトヨタ vs ホンダ、任天堂 vs ソニーなどの「企業VS企業」の争いを物語調に演出して、1時間x全5回程度のボリュームの連続ラジオドラマにしている</p> <p><a href="https://podcasts.apple.com/us/podcast/%E4%BB%AE%E6%83%B3%E9%80%9A%E8%B2%A8%E6%88%A6%E4%BA%89/id1534068876?i=1000612386972">仮想通貨戦争</a>回ではサトシナカモトがデスゲーム主催者よろしく合成音声でしゃべっててウケた(ラジオなのでしゃべらないと表現できない)</p> <h1 id="News-Connect-あなたと経済をつなぐ5分間-ニュースコネクト">News Connect あなたと経済をつなぐ5分間 #ニュースコネクト</h1> <p><iframe src="https://anchor.fm/takafumi-nomura4/embed" height="102px" width="400px" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://podcasters.spotify.com/pod/show/takafumi-nomura4">podcasters.spotify.com</a></cite></p> <p>News Connectはいわゆる時事ニュースのポッドキャスト</p> <p>日刊配信との週まとめ回とゲスト特別回がある</p> <p>ホストの野村さんは箕輪厚介さんとNewsPicks本のレーベルを立ち上げた人、というのをこの前知った<a href="#f-f5d99547" id="fn-f5d99547" name="fn-f5d99547" title="News Connect あなたと経済をつなぐ5分間 #ニュースコネクト:Apple Podcast内の【祝日版 #26】箕輪厚介さんと語る。2010年代「起業家本ブーム」とは何だったのか">*3</a></p> <p>週まとめ回に出てくる塩野さんという人はググると ライブドア—— とサジェストされるぐらいこの業界では有名な人で、色んな分野に見識が深く、シンプルに話がうまい</p> <p>あと音楽に詳しい。YouTubeにファンが作ったDJ塩野というプレイリストが存在する</p> <h1 id="Off-Topic--オフトピック">Off Topic // オフトピック</h1> <p><div class="itunes-embed freezed itunes-kind-podcast"><a href="https://podcasts.apple.com/jp/podcast/off-topic-%E3%82%AA%E3%83%95%E3%83%88%E3%83%94%E3%83%83%E3%82%AF/id1444665909?uo=4&at=10l8JW&ct=hatenablog" rel="nofollow" target="_blank"><img src="https://cdn.image.st-hatena.com/image/scale/7328b88d89e92a8e2d9c21aa808e607181d2a501/enlarge=0;height=200;version=1;width=200/https%3A%2F%2Fis1-ssl.mzstatic.com%2Fimage%2Fthumb%2FPodcasts114%2Fv4%2F5c%2F05%2F70%2F5c05706d-ca82-b4c3-451d-3eba41a1fb9b%2Fmza_4187866350631177947.jpg%2F100x100bb.jpg" alt="Off Topic // オフトピック" title="Off Topic // オフトピック" class="itunes-embed-image"/></a><div class="itunes-embed-info"><p class="itunes-embed-title"><a href="https://podcasts.apple.com/jp/podcast/off-topic-%E3%82%AA%E3%83%95%E3%83%88%E3%83%94%E3%83%83%E3%82%AF/id1444665909?uo=4&at=10l8JW&ct=hatenablog" rel="nofollow" target="_blank">Off Topic // オフトピック</a></p><ul><li class="itunes-embed-artist">Off Topic</li><li class="itunes-embed-genre">テクノロジー</li><li class="itunes-embed-price">¥0</li><li class="itunes-embed-badge"><a href="https://podcasts.apple.com/jp/podcast/off-topic-%E3%82%AA%E3%83%95%E3%83%88%E3%83%94%E3%83%83%E3%82%AF/id1444665909?uo=4&at=10l8JW&ct=hatenablog" rel="nofollow" target="_blank"><img src="https://cdn.blog.st-hatena.com/images/theme/itunes/itunes-badge-itunes@2x.png" width="44px" height="15px" /></a></li></ul></div></div><cite class="hatena-citation"><a href="https://podcasts.apple.com/jp/podcast/off-topic-%E3%82%AA%E3%83%95%E3%83%88%E3%83%94%E3%83%83%E3%82%AF/id1444665909">podcasts.apple.com</a></cite></p> <p>Off Topicは米国のテック業界のことを毎回ストリーラインを作って話してくれる番組</p> <p>ホストの草野さんと宮武さんのプロフィールはよく存じあげていないのだけど毎回入念に準備して話を作り込んでて感心する</p> <h1 id="fukaborifm">fukabori.fm</h1> <p><iframe src="https://art19.com/shows/fukabori/embed" style="width: 720px; height: 505px; border: 0 none;" width="720" height="505" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://art19.com/shows/fukabori">art19.com</a></cite></p> <p>fukabori.fm は毎回技術的なテーマを決めてその分野に詳しいゲストを呼んで深堀りしていく番組</p> <p>冷静に考えるとどんな分野のゲストが来ても深堀りできるホストのiwashiさんがすごくない?</p> <p>NTT Comの中の人が登場すると環境が特殊なのでやたら濃い話をして帰ってゆく・・</p> <h1 id="バンクーバーのえんじに屋">バンクーバーのえんじに屋</h1> <p><iframe src="https://art19.com/shows/vancouverengineers/embed" style="width: 720px; height: 505px; border: 0 none;" width="720" height="505" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://art19.com/shows/vancouverengineers">art19.com</a></cite></p> <p>バンクーバーの日本人コミュニティの人達が出てくるポッドキャスト。週1で配信されてる</p> <p>ブログ界隈的には<a href="https://webya.opdsgn.com/">バンクーバーのうぇぶ屋</a>の人がやってる</p> <p>日本とカナダ(含む北米)ではIT業界にはこういう違いがあるよね、とかキャリア系の話が多い</p> <p>日本人エンジニアは海外に進出せよとか渡米して給料N倍とかの絶妙な古参ブロガーらしい発信テクニックでよく界隈でバズってる</p> <h1 id="textafm">texta.fm</h1> <p><div class="itunes-embed freezed itunes-kind-podcast"><a href="https://podcasts.apple.com/jp/podcast/texta-fm/id1530076592?uo=4&at=10l8JW&ct=hatenablog" rel="nofollow" target="_blank"><img src="https://cdn.image.st-hatena.com/image/scale/dd92c50e12ccfa42be2d2c530731c9a63a0d3ffb/enlarge=0;height=200;version=1;width=200/https%3A%2F%2Fis1-ssl.mzstatic.com%2Fimage%2Fthumb%2FPodcasts124%2Fv4%2F38%2F77%2F7f%2F38777fa3-689d-c34a-33da-238920787f4f%2Fmza_2706105267430257266.jpg%2F100x100bb.jpg" alt="texta.fm" title="texta.fm" class="itunes-embed-image"/></a><div class="itunes-embed-info"><p class="itunes-embed-title"><a href="https://podcasts.apple.com/jp/podcast/texta-fm/id1530076592?uo=4&at=10l8JW&ct=hatenablog" rel="nofollow" target="_blank">texta.fm</a></p><ul><li class="itunes-embed-artist">Design and Engineering team at PIXTA</li><li class="itunes-embed-genre">テクノロジー</li><li class="itunes-embed-price">¥0</li><li class="itunes-embed-badge"><a href="https://podcasts.apple.com/jp/podcast/texta-fm/id1530076592?uo=4&at=10l8JW&ct=hatenablog" rel="nofollow" target="_blank"><img src="https://cdn.blog.st-hatena.com/images/theme/itunes/itunes-badge-itunes@2x.png" width="44px" height="15px" /></a></li></ul></div></div><cite class="hatena-citation"><a href="https://podcasts.apple.com/jp/podcast/texta-fm/id1530076592">podcasts.apple.com</a></cite></p> <p>ピクスタという会社のポッドキャスト</p> <p>おそらく技術顧問のt_wadaさんと壁打ちしてたらこれ公開してよくない? ってなったやつ</p> <p>このブログの読者なら絶対好きそうなソフトウェアアーキテクチャの話が多いのでお勧めした</p> <h1 id="プログラム雑談">プログラム雑談</h1> <p><iframe src="https://anchor.fm/karino2/embed" height="102px" width="400px" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://podcasters.spotify.com/pod/show/karino2">podcasters.spotify.com</a></cite></p> <p>プログラム雑談は週1で更新されるkarino2さんの一人しゃべりなポッドキャスト</p> <p>同じくここのブログ読者は好きそうなのでおすすめした</p> <p>内容はプログラミングそのものに関する話題やFIREやなろう系小説の話とか</p> <p>一周回ったシニアなプログラマー向けの番組かと思いきや、感想をみると若者も結構聴いているらしい。人徳のなせる業か</p> <h1 id="Misreading-Chat">Misreading Chat</h1> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fmisreading.chat%2F" title="Misreading Chat" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://misreading.chat/">misreading.chat</a></cite></p> <p>Misreading ChatはMorritaさんとMukaiさんが交互に読んできたコンピューターサイエンスの論文を解説するポッドキャスト</p> <p>そもそも周りにコンピューターサイエンスの論文を日常的に読んでる人がいないので希少な情報源になってる</p> <p>分野によっては全然言ってること分からないんだけど2人が理解してるのでなぜか聴いてるだけで自尊心の高まりを感じる・・</p> <h1 id="mozaicfm">mozaic.fm</h1> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fmozaic.fm%2F" title="Episodes | mozaic.fm" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://mozaic.fm/">mozaic.fm</a></cite></p> <p>mozaic.fmは次世代Webについて語るためのポッドキャスト</p> <p>フロントエンド属性のエンジニアにおすすめ</p> <p>月1でEcosystem回とPlatform回に分かれていてだいたいめっちゃエピードが長い</p> <p>Ecosystem回ではフロントエンドまわりのニュースをキャッチアップして参加者で議論していく</p> <p>Platform回は各ブラウザーベンダーのアップデート全部見るというマニア向けなコンテンツをしている</p> <h1 id="kkeethのエンジニア雑談チャンネル">kkeethのエンジニア雑談チャンネル</h1> <p><iframe src="https://art19.com/shows/kkeethengineers/embed" style="width: 720px; height: 505px; border: 0 none;" width="720" height="505" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://art19.com/shows/kkeethengineers">art19.com</a></cite></p> <p>以前はkkeethさんが朝活と称してYouTubeかどこかで配信したトークを撮って出ししているポッドキャストだった</p> <p>今は形態が変わっているようだが詳しくは理解していない</p> <p>フロントエンド系のネタとHR系の話が多い</p> <p>更新頻度x継続が鬼なのでよく目につくようになり定着した</p> <h1 id="購読一覧">購読一覧</h1> <p>以下はエクスポートした一覧のOPMLをCSVに変換したものです。ただのリストなので折り畳み表示にします</p> <p>ザッピングしながら感想を書いたので息切れしてしまって紹介できなかったおすすめポッドキャストが残っているんだけど、また別の機会に書かせてください</p> <p><details> <summary>購読一覧</summary> <pre> #strobofm,<a href="https://strobo.fm/index.xml">https://strobo.fm/index.xml</a> 10X.fm,<a href="https://anchor.fm/s/559fd878/podcast/rss">https://anchor.fm/s/559fd878/podcast/rss</a> ajitofm,<a href="https://ajito.fm/index.xml">https://ajito.fm/index.xml</a> Algolia Podcast,<a href="https://algolia.fm/feed.xml">https://algolia.fm/feed.xml</a> Autify Japan Podcast,<a href="https://anchor.fm/s/154fc620/podcast/rss">https://anchor.fm/s/154fc620/podcast/rss</a> Background.radio,<a href="https://anchor.fm/s/4a05f894/podcast/rss">https://anchor.fm/s/4a05f894/podcast/rss</a> Backyard Hatena,<a href="https://anchor.fm/s/7aad9de4/podcast/rss">https://anchor.fm/s/7aad9de4/podcast/rss</a> Burning cast,<a href="https://anchor.fm/s/22818cac/podcast/rss">https://anchor.fm/s/22818cac/podcast/rss</a> BUSINESS WARS / ビジネスウォーズ,<a href="https://rss.art19.com/business-wars-jp">https://rss.art19.com/business-wars-jp</a> CEREAL TALK / シリアルトーク,<a href="https://anchor.fm/s/4f8170dc/podcast/rss">https://anchor.fm/s/4f8170dc/podcast/rss</a> Cryptic,<a href="https://feeds.castos.com/020p2">https://feeds.castos.com/020p2</a> dely Tech Talk,<a href="https://anchor.fm/s/6924abf8/podcast/rss">https://anchor.fm/s/6924abf8/podcast/rss</a> devchat.fm,<a href="https://anchor.fm/s/3b652dc8/podcast/rss">https://anchor.fm/s/3b652dc8/podcast/rss</a> DroidKaigi.fm,<a href="https://fm.droidkaigi.jp/feed.xml">https://fm.droidkaigi.jp/feed.xml</a> e34,<a href="https://e34.fm/rss.xml">https://e34.fm/rss.xml</a> EM . FM #EMFM - Spotify for Podcasters,<a href="https://anchor.fm/s/70a2c40/podcast/rss">https://anchor.fm/s/70a2c40/podcast/rss</a> engineer meeting podcast,<a href="https://feeds.soundcloud.com/users/soundcloud:users:117239062/sounds.rss">https://feeds.soundcloud.com/users/soundcloud:users:117239062/sounds.rss</a> few-shot.fm,<a href="https://anchor.fm/s/e69c9d70/podcast/rss">https://anchor.fm/s/e69c9d70/podcast/rss</a> FREE AGENDA by hikaru &amp; yamotty,<a href="https://anchor.fm/s/147f7150/podcast/rss">https://anchor.fm/s/147f7150/podcast/rss</a> fukabori.fm,<a href="https://rss.art19.com/fukabori">https://rss.art19.com/fukabori</a> FUNTERACTIVE Radio,<a href="https://anchor.fm/s/55a83bbc/podcast/rss">https://anchor.fm/s/55a83bbc/podcast/rss</a> furoshiki.fm,<a href="https://anchor.fm/s/50bf64f4/podcast/rss">https://anchor.fm/s/50bf64f4/podcast/rss</a> Future Tech Cast,<a href="https://anchor.fm/s/2890e980/podcast/rss">https://anchor.fm/s/2890e980/podcast/rss</a> Good to Great(グッドトゥーグレート),<a href="https://anchor.fm/s/11decd38/podcast/rss">https://anchor.fm/s/11decd38/podcast/rss</a> Greenに書けない転職ウラ話ラジオ,<a href="https://anchor.fm/s/4c3bd64c/podcast/rss">https://anchor.fm/s/4c3bd64c/podcast/rss</a> h173.club,<a href="https://anchor.fm/s/9d93c798/podcast/rss">https://anchor.fm/s/9d93c798/podcast/rss</a> HashHub Podcast,<a href="https://stand.fm/rss/620ca7e1eb302d8b48e6c6e5">https://stand.fm/rss/620ca7e1eb302d8b48e6c6e5</a> hikifune.fm,<a href="https://anchor.fm/s/8d50d4c/podcast/rss">https://anchor.fm/s/8d50d4c/podcast/rss</a> jamming.fm,<a href="http://feeds.soundcloud.com/users/soundcloud:users:588841827/sounds.rss">http://feeds.soundcloud.com/users/soundcloud:users:588841827/sounds.rss</a> kkeethのエンジニア雑談チャンネル,<a href="https://rss.art19.com/kkeethengineers">https://rss.art19.com/kkeethengineers</a> LayerX NOW!,<a href="https://anchor.fm/s/55a49944/podcast/rss">https://anchor.fm/s/55a49944/podcast/rss</a> Learning cast,<a href="https://anchor.fm/s/79bb6d8/podcast/rss">https://anchor.fm/s/79bb6d8/podcast/rss</a> LFK mobile DevPods,<a href="https://lfk-devpods.linecorp.com/feed.atom">https://lfk-devpods.linecorp.com/feed.atom</a> LISTEN NEWS,<a href="https://listen.style/p/listennews/rss">https://listen.style/p/listennews/rss</a> London Tech Talk,<a href="https://anchor.fm/s/d904331c/podcast/rss">https://anchor.fm/s/d904331c/podcast/rss</a> Metaverse FM - メタバース/VR/ブロックチェーンについて、現役エンジニアが語ります,<a href="https://anchor.fm/s/7dbecd50/podcast/rss">https://anchor.fm/s/7dbecd50/podcast/rss</a> Middle Aged Developers,<a href="https://anchor.fm/s/6cb3ad28/podcast/rss">https://anchor.fm/s/6cb3ad28/podcast/rss</a> Misreading Chat,<a href="https://misreading.chat/category/episodes/feed/">https://misreading.chat/category/episodes/feed/</a> MOSH.fm🌞,<a href="https://anchor.fm/s/66006700/podcast/rss">https://anchor.fm/s/66006700/podcast/rss</a> mozaic.fm,<a href="https://feed.mozaic.fm/">https://feed.mozaic.fm/</a> Muddy Web Podcast,<a href="https://anchor.fm/s/c9c3bf44/podcast/rss">https://anchor.fm/s/c9c3bf44/podcast/rss</a> NDS FM,<a href="https://nagaokadevelopersstudy.github.io/ndsfm/feed.xml">https://nagaokadevelopersstudy.github.io/ndsfm/feed.xml</a> News Connect ~あなたと経済をつなぐ5分間~,<a href="https://anchor.fm/s/81fb5eec/podcast/rss">https://anchor.fm/s/81fb5eec/podcast/rss</a> nextstep.fm,<a href="https://feeds.soundcloud.com/users/soundcloud:users:281879883/sounds.rss">https://feeds.soundcloud.com/users/soundcloud:users:281879883/sounds.rss</a> normalize.fm,<a href="https://anchor.fm/s/67a9c1a0/podcast/rss">https://anchor.fm/s/67a9c1a0/podcast/rss</a> note Tech Talk,<a href="https://anchor.fm/s/622bef64/podcast/rss">https://anchor.fm/s/622bef64/podcast/rss</a> Nstockのラジオ,<a href="https://anchor.fm/s/99b01140/podcast/rss">https://anchor.fm/s/99b01140/podcast/rss</a> Off Topic // オフトピック,<a href="https://anchor.fm/s/7369a14/podcast/rss">https://anchor.fm/s/7369a14/podcast/rss</a> Ossan.fm,<a href="https://ossan.fm/feed.xml">https://ossan.fm/feed.xml</a> PHPの現場,<a href="https://php-genba.shin1x1.com/rss">https://php-genba.shin1x1.com/rss</a> PMラジオ,<a href="https://anchor.fm/s/600aa478/podcast/rss">https://anchor.fm/s/600aa478/podcast/rss</a> Pod de Engineer,<a href="https://anchor.fm/s/12948d58/podcast/rss">https://anchor.fm/s/12948d58/podcast/rss</a> Podcast by Genesia.,<a href="https://anchor.fm/s/5ca1f318/podcast/rss">https://anchor.fm/s/5ca1f318/podcast/rss</a> PositiviTea,<a href="https://positivitea-secrets.us/feed/">https://positivitea-secrets.us/feed/</a> PROTOTYPE.FM,<a href="https://feeds.acast.com/public/shows/6483f08d4f789000115c9159">https://feeds.acast.com/public/shows/6483f08d4f789000115c9159</a> Rebuild.fm,<a href="https://feeds.rebuild.fm/rebuildfm">https://feeds.rebuild.fm/rebuildfm</a> rehash.fm,<a href="https://feeds.podcastics.com/podcastics/podcasts/rss/5199_2a7b208397764ef47f4ce403a9bbc9b0.rss">https://feeds.podcastics.com/podcastics/podcasts/rss/5199_2a7b208397764ef47f4ce403a9bbc9b0.rss</a> rel.ax,<a href="https://anchor.fm/s/e644aa34/podcast/rss">https://anchor.fm/s/e644aa34/podcast/rss</a> render(fm),<a href="https://rss.art19.com/render-fm">https://rss.art19.com/render-fm</a> resize.fm,<a href="https://anchor.fm/s/416f2048/podcast/rss">https://anchor.fm/s/416f2048/podcast/rss</a> Sansan Tech Podcast,<a href="https://feeds.soundcloud.com/users/soundcloud:users:554143311/sounds.rss">https://feeds.soundcloud.com/users/soundcloud:users:554143311/sounds.rss</a> SBCast.,<a href="https://sbc.yokohama/feed/podcast">https://sbc.yokohama/feed/podcast</a> Shinagawa Agile Talks #shinagile,<a href="https://anchor.fm/s/9b465dc/podcast/rss">https://anchor.fm/s/9b465dc/podcast/rss</a> SmartBank.FM,<a href="https://anchor.fm/s/8ae8599c/podcast/rss">https://anchor.fm/s/8ae8599c/podcast/rss</a> START/FM,<a href="https://anchor.fm/s/4ac8c9a0/podcast/rss">https://anchor.fm/s/4ac8c9a0/podcast/rss</a> Startup Chat,<a href="https://anchor.fm/s/242a0e80/podcast/rss">https://anchor.fm/s/242a0e80/podcast/rss</a> STILL RENDERING // スティレン,<a href="https://anchor.fm/s/40a74b4/podcast/rss">https://anchor.fm/s/40a74b4/podcast/rss</a> Studyplus Engineering Podcast,<a href="https://anchor.fm/s/60d040c0/podcast/rss">https://anchor.fm/s/60d040c0/podcast/rss</a> systemand.online,<a href="https://systemand.online/feed.xml">https://systemand.online/feed.xml</a> Tech-Talk with SRG,<a href="https://anchor.fm/s/e535de60/podcast/rss">https://anchor.fm/s/e535de60/podcast/rss</a> terapyon channel,<a href="https://anchor.fm/s/14480e04/podcast/rss">https://anchor.fm/s/14480e04/podcast/rss</a> texta.fm,<a href="https://anchor.fm/s/330a9488/podcast/rss">https://anchor.fm/s/330a9488/podcast/rss</a> The Perfect Introvert,<a href="https://api.substack.com/feed/podcast/623637.rss">https://api.substack.com/feed/podcast/623637.rss</a> Today I Learned,<a href="https://anchor.fm/s/367f0040/podcast/rss">https://anchor.fm/s/367f0040/podcast/rss</a> ToraLab.fm,<a href="https://anchor.fm/s/46d5ea08/podcast/rss">https://anchor.fm/s/46d5ea08/podcast/rss</a> Trivial Solution,<a href="https://anchor.fm/s/6bda154/podcast/rss">https://anchor.fm/s/6bda154/podcast/rss</a> UIT INSIDE,<a href="https://uit-inside.linecorp.com/feed.atom">https://uit-inside.linecorp.com/feed.atom</a> Unlearn.fm,<a href="https://anchor.fm/s/6d3f5ee0/podcast/rss">https://anchor.fm/s/6d3f5ee0/podcast/rss</a> w2o.fm,<a href="https://w2o.fm/feed.xml">https://w2o.fm/feed.xml</a> Wantedly Engineering Podcast,<a href="https://anchor.fm/s/64205bfc/podcast/rss">https://anchor.fm/s/64205bfc/podcast/rss</a> web3FM,<a href="https://anchor.fm/s/5d5ba88/podcast/rss">https://anchor.fm/s/5d5ba88/podcast/rss</a> XCrossing,<a href="https://feeds.zencastr.com/f/wQGcVPNH.rss">https://feeds.zencastr.com/f/wQGcVPNH.rss</a> yancan.fm,<a href="https://www.yancan.tech/feed.xml">https://www.yancan.tech/feed.xml</a> Yarukinai.fm,<a href="https://yarukinai.fm/feed.xml">https://yarukinai.fm/feed.xml</a> yatteiki.fm,<a href="https://yatteiki.fm/feed.xml">https://yatteiki.fm/feed.xml</a> Yokohama North AM,<a href="https://anchor.fm/s/1e60bd50/podcast/rss">https://anchor.fm/s/1e60bd50/podcast/rss</a> yome.fm,<a href="https://yomefm.github.io/feed.xml">https://yomefm.github.io/feed.xml</a> yskoht/podcast,<a href="https://yskoht.github.io/podcast/feed.xml">https://yskoht.github.io/podcast/feed.xml</a> Zero Topic - ゼロトピック -,<a href="https://anchor.fm/s/1617b040/podcast/rss">https://anchor.fm/s/1617b040/podcast/rss</a> アクシオンポッドキャスト,<a href="https://anchor.fm/s/15ccae4c/podcast/rss">https://anchor.fm/s/15ccae4c/podcast/rss</a> あたらしい経済ニュース(幻冬舎のブロックチェーン・仮想通貨ニュース),<a href="https://feeds.soundcloud.com/users/soundcloud:users:459848829/sounds.rss">https://feeds.soundcloud.com/users/soundcloud:users:459848829/sounds.rss</a> エンジニアと人生,<a href="https://rss.art19.com/shu223">https://rss.art19.com/shu223</a> エンジニアリングマネージャーの問題集,<a href="https://rss.art19.com/engineermanager">https://rss.art19.com/engineermanager</a> お元気ですか.fm,<a href="https://anchor.fm/s/65c3f018/podcast/rss">https://anchor.fm/s/65c3f018/podcast/rss</a> カミナシSaaS FM,<a href="https://anchor.fm/s/5ca4aa04/podcast/rss">https://anchor.fm/s/5ca4aa04/podcast/rss</a> きのこるエフエム,<a href="https://anchor.fm/s/a7f362c/podcast/rss">https://anchor.fm/s/a7f362c/podcast/rss</a> キマグレエフエム,<a href="https://anchor.fm/s/31978840/podcast/rss">https://anchor.fm/s/31978840/podcast/rss</a> ゲーマーの流儀 / アール,<a href="https://feeds.transistor.fm/3cd107cc-0c4a-468d-83fb-d20addd9a756">https://feeds.transistor.fm/3cd107cc-0c4a-468d-83fb-d20addd9a756</a> ココナッツテック fm.Coconuts.tech,<a href="https://anchor.fm/s/4881bfd0/podcast/rss">https://anchor.fm/s/4881bfd0/podcast/rss</a> サブスクライバ,<a href="https://anchor.fm/s/84e2304/podcast/rss">https://anchor.fm/s/84e2304/podcast/rss</a> しがないラジオ,<a href="https://feeds.soundcloud.com/users/soundcloud:users:294673416/sounds.rss">https://feeds.soundcloud.com/users/soundcloud:users:294673416/sounds.rss</a> スタートアップオフレコ対談,<a href="https://stand.fm/rss/64c240bed4e2cbde26c179a1">https://stand.fm/rss/64c240bed4e2cbde26c179a1</a> タメ口.fm,<a href="https://anchor.fm/s/e654577c/podcast/rss">https://anchor.fm/s/e654577c/podcast/rss</a> ツナギメエフエム,<a href="https://anchor.fm/s/8426c10c/podcast/rss">https://anchor.fm/s/8426c10c/podcast/rss</a> てくてくFM - わからないが少しわかるラジオ,<a href="https://anchor.fm/s/732ccd60/podcast/rss">https://anchor.fm/s/732ccd60/podcast/rss</a> てくてくラジオ,<a href="https://anchor.fm/s/6df56fdc/podcast/rss">https://anchor.fm/s/6df56fdc/podcast/rss</a> ハラケンタのグローバル漫遊記 / 「シリコンバレーエンジニア ✕ グローバル ✕ プロフェッショナル」,<a href="https://anchor.fm/s/58a458a0/podcast/rss">https://anchor.fm/s/58a458a0/podcast/rss</a> バンクーバー ぼんやログ,<a href="https://listen.style/p/van-bonyari/rss">https://listen.style/p/van-bonyari/rss</a> バンクーバーのえんじに屋,<a href="https://rss.art19.com/vancouverengineers">https://rss.art19.com/vancouverengineers</a> ひまじんプログラマーの週末エンジニアリングレッスン,<a href="https://rss.art19.com/07ef6b45-d4fc-4d94-b211-e02a27b7e2a6">https://rss.art19.com/07ef6b45-d4fc-4d94-b211-e02a27b7e2a6</a> プログラム雑談,<a href="https://anchor.fm/s/68ce140/podcast/rss">https://anchor.fm/s/68ce140/podcast/rss</a> プロダクトマネージャーのキャリアラジオ,<a href="https://anchor.fm/s/85c0f398/podcast/rss">https://anchor.fm/s/85c0f398/podcast/rss</a> プロレポラジオ ~エンジニア採用や組織に関する課題解決を目指します~,<a href="https://anchor.fm/s/e87cda10/podcast/rss">https://anchor.fm/s/e87cda10/podcast/rss</a> ほっとテック,<a href="https://anchor.fm/s/86693634/podcast/rss">https://anchor.fm/s/86693634/podcast/rss</a> マンガのラジオ,<a href="https://www.omnycontent.com/d/playlist/67122501-9b17-4d77-84bd-a93d00dc791e/57423c3f-266b-4d1f-ab2c-ad050070c990/48f314b3-2398-4d47-b87f-ad0500718022/podcast.rss">https://www.omnycontent.com/d/playlist/67122501-9b17-4d77-84bd-a93d00dc791e/57423c3f-266b-4d1f-ab2c-ad050070c990/48f314b3-2398-4d47-b87f-ad0500718022/podcast.rss</a> ゆとりっ娘たちのたわごと,<a href="https://anchor.fm/s/6e491dbc/podcast/rss">https://anchor.fm/s/6e491dbc/podcast/rss</a> ゆるコンピュータ科学ラジオ,<a href="https://anchor.fm/s/7cd923f4/podcast/rss">https://anchor.fm/s/7cd923f4/podcast/rss</a> ゆるテク,<a href="https://anchor.fm/s/adf8dcb8/podcast/rss">https://anchor.fm/s/adf8dcb8/podcast/rss</a> ゆるふわPodcast,<a href="https://rss.art19.com/f414b397-96fb-42c5-aa9d-04baa2cde5ac">https://rss.art19.com/f414b397-96fb-42c5-aa9d-04baa2cde5ac</a> ゆる言語学ラジオ,<a href="https://radio.ken-horimoto.com/feed/podcast/">https://radio.ken-horimoto.com/feed/podcast/</a> よわよわえふえむ,<a href="https://anchor.fm/s/4feefc9c/podcast/rss">https://anchor.fm/s/4feefc9c/podcast/rss</a> りっちゃ・りょかちのやいやいラジオ,<a href="https://anchor.fm/s/599cf528/podcast/rss">https://anchor.fm/s/599cf528/podcast/rss</a> 人生fm,<a href="https://kirimin.github.io/jinseifm/feed.xml">https://kirimin.github.io/jinseifm/feed.xml</a> 今出川FM by Nota,<a href="https://anchor.fm/s/8de09a9c/podcast/rss">https://anchor.fm/s/8de09a9c/podcast/rss</a> 前田ヒロ,<a href="https://hiromaeda.com/feed/">https://hiromaeda.com/feed/</a> 名無しさんのポッドキャスト,<a href="https://feeds.buzzsprout.com/1154831.rss">https://feeds.buzzsprout.com/1154831.rss</a> 完全理解.FM,<a href="https://anchor.fm/s/a3630c38/podcast/rss">https://anchor.fm/s/a3630c38/podcast/rss</a> 楽しいラジオ「ドングリFM」,<a href="https://feeds.soundcloud.com/users/soundcloud:users:170031062/sounds.rss">https://feeds.soundcloud.com/users/soundcloud:users:170031062/sounds.rss</a> 歴史を面白く学ぶコテンラジオ (COTEN RADIO),<a href="https://anchor.fm/s/8c2088c/podcast/rss">https://anchor.fm/s/8c2088c/podcast/rss</a> 海外スタートアップレポート「シリコンバレーによろしく リターンズ 」,<a href="https://anchor.fm/s/29b92318/podcast/rss">https://anchor.fm/s/29b92318/podcast/rss</a> 火曜日のおフロ,<a href="https://anchor.fm/s/2b3dd74c/podcast/rss">https://anchor.fm/s/2b3dd74c/podcast/rss</a> 白金鉱業.FM,<a href="https://shirokane-kougyou.fm/feed.xml">https://shirokane-kougyou.fm/feed.xml</a> 科学のラジオ ~Radio Scientia~,<a href="https://omny.fm/shows/kagaku/playlists/podcast.rss">https://omny.fm/shows/kagaku/playlists/podcast.rss</a> 覇権FM,<a href="https://anchor.fm/s/93c815ac/podcast/rss">https://anchor.fm/s/93c815ac/podcast/rss</a> 言語化.fm,<a href="https://anchor.fm/s/8239c4c0/podcast/rss">https://anchor.fm/s/8239c4c0/podcast/rss</a> 論より動くもの.fm,<a href="https://anchor.fm/s/927f758c/podcast/rss">https://anchor.fm/s/927f758c/podcast/rss</a> 近藤淳也のアンノウンラジオ,<a href="https://anchor.fm/s/ab502c78/podcast/rss">https://anchor.fm/s/ab502c78/podcast/rss</a> 銀の弾丸ラジオ,<a href="https://anchor.fm/s/13df46f8/podcast/rss">https://anchor.fm/s/13df46f8/podcast/rss</a> </pre> </details></p> <p>これを作るためのPythonスクリプト</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> xml.etree.ElementTree <span class="synStatement">as</span> ET <span class="synPreProc">import</span> csv <span class="synPreProc">import</span> os tree = ET.parse(os.path.expanduser(<span class="synConstant">'~/Downloads/Takeout/Google Podcasts/Subscriptions/Subscriptions.opml'</span>)) root = tree.getroot() <span class="synComment"># CSVファイルを開く</span> <span class="synStatement">with</span> <span class="synIdentifier">open</span>(<span class="synConstant">'output.csv'</span>, <span class="synConstant">'w'</span>, newline=<span class="synConstant">''</span>, encoding=<span class="synConstant">'utf-8'</span>) <span class="synStatement">as</span> csvfile: writer = csv.writer(csvfile) <span class="synComment"># ヘッダーを書き込む</span> writer.writerow([<span class="synConstant">'text'</span>, <span class="synConstant">'xmlUrl'</span>]) <span class="synComment"># XMLのデータを反復処理する</span> <span class="synStatement">for</span> outline <span class="synStatement">in</span> root.findall(<span class="synConstant">'.//outline[@type=&quot;rss&quot;]'</span>): text = outline.get(<span class="synConstant">'text'</span>) xmlUrl = outline.get(<span class="synConstant">'xmlUrl'</span>) writer.writerow([text, xmlUrl]) </pre> <p>むしろOPMLファイルをそのまま張っておく <a href="https://github.com/laiso/laiso/files/13803644/Subscriptions.opml.csv">https://github.com/laiso/laiso/files/13803644/Subscriptions.opml.csv</a></p> <div class="footnote"> <p class="footnote"><a href="#fn-ce0a4e66" id="f-ce0a4e66" name="f-ce0a4e66" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://www.itmedia.co.jp/news/articles/2309/27/news094.html">Google Podcasts、2024年に終了へ YouTube Musicに統合 - ITmedia NEWS</a></span></p> <p class="footnote"><a href="#fn-5e73e7b7" id="f-5e73e7b7" name="f-5e73e7b7" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://wondery.com/shows/business-wars/">Business Wars with David Brown</a></span></p> <p class="footnote"><a href="#fn-f5d99547" id="f-f5d99547" name="f-f5d99547" class="footnote-number">*3</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://podcasts.apple.com/jp/podcast/%E7%A5%9D%E6%97%A5%E7%89%88-26-%E7%AE%95%E8%BC%AA%E5%8E%9A%E4%BB%8B%E3%81%95%E3%82%93%E3%81%A8%E8%AA%9E%E3%82%8B-2010%E5%B9%B4%E4%BB%A3-%E8%B5%B7%E6%A5%AD%E5%AE%B6%E6%9C%AC%E3%83%96%E3%83%BC%E3%83%A0-%E3%81%A8%E3%81%AF%E4%BD%95%E3%81%A0%E3%81%A3%E3%81%9F%E3%81%AE%E3%81%8B/id1608666340?i=1000635728678">News Connect あなたと経済をつなぐ5分間 #ニュースコネクト:Apple Podcast内の【祝日版 #26】箕輪厚介さんと語る。2010年代「起業家本ブーム」とは何だったのか</a></span></p> </div> laiso 2023年に書いたコード hatenablog://entry/6801883189071046830 2023-12-30T21:48:49+09:00 2024-01-01T14:30:04+09:00 「2023年のふりかえり」ではPythonやJavaScriptのコーディングの話ばかり出てくるけど、これって今年全体から見ると1割以下だなぁと思ったのでGitHubのメトリクスを見ながら振り返ることにした laiso.hatenablog.com 言語ごとのコミット数 PHPの話 Laravelの話 開発手法の話 テストの話 GitHub上での活動 2021年 2022年 言語ごとのコミット数 vn7n24fzkq/github-profile-summary-cardsというのが生成してくれたグラフ profile-summary-card-output Python はデータ分析サーバー… <p>「2023年のふりかえり」ではPythonやJavaScriptのコーディングの話ばかり出てくるけど、これって今年全体から見ると1割以下だなぁと思ったのでGitHubのメトリクスを見ながら振り返ることにした</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2Frecap-2023" title="2023年のふりかえり - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/recap-2023">laiso.hatenablog.com</a></cite></p> <ul class="table-of-contents"> <li><a href="#言語ごとのコミット数">言語ごとのコミット数</a></li> <li><a href="#PHPの話">PHPの話</a></li> <li><a href="#Laravelの話">Laravelの話</a></li> <li><a href="#開発手法の話">開発手法の話</a></li> <li><a href="#テストの話">テストの話</a></li> <li><a href="#GitHub上での活動">GitHub上での活動</a><ul> <li><a href="#2021年">2021年</a></li> <li><a href="#2022年">2022年</a></li> </ul> </li> </ul> <h1 id="言語ごとのコミット数">言語ごとのコミット数</h1> <p><a href="https://github.com/vn7n24fzkq/github-profile-summary-cards">vn7n24fzkq/github-profile-summary-cards</a>というのが生成してくれたグラフ</p> <p><figure class="figure-image figure-image-fotolife" title="profile-summary-card-output"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20231230/20231230202025.png" width="340" height="200" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>profile-summary-card-output</figcaption></figure></p> <p>Python はデータ分析サーバーをFastAPIで書いてるのでその分と、Swiftは記憶にない</p> <p>他の大部分はLaravel を使った複数のプロジェクトになる</p> <h1 id="PHPの話">PHPの話</h1> <p>PHPの仕事が欲しいわけではないのであんまりPHP書ける人ブランディングをしてこなかったけど9割はPHPやテンプレートHTMLを粛々と書いてると思う</p> <p>レガシー管理画面アーキテクチャなのでReactやVueどころかjQueryでフロントエンドの処理書くこともない</p> <p>ただLaravelやPHPに存在する機能を積極的に使おうとはしていて常にlatestなバージョンに追従している</p> <p>PHP8は<a href="https://www.php.net/manual/en/control-structures.match.php">match</a>構文が他言語みたいに書けて面白くて、<a href="https://www.php.net/manual/en/language.types.enumerations.php">enum</a>も外部ライブラリなしで導入できる</p> <p><a href="https://www.php.net/manual/en/language.types.declarations.php">Type declarations</a>はボーイスカウトルールで立ち入った区画を整備して帰っていく方針で付けてる</p> <p>型の不一致はテスト時にTypeError吐いてくれることもあれば、PHPStormがコーディング時に教えてくれる時もある</p> <h1 id="Laravelの話">Laravelの話</h1> <p>Laravelの諸機能は自作のオニオンアーキテクチャみたいなものを定義しなくてもある程度レールに乗っていくだけでバリデーションと権限管理をコントローラーから分離してくれたり、Active RecordでDBとモデルを分離したり、DIコンテナで実行時に実装を差し替えられたり、などの知られたデザインパターンを適用していってくれて、僕のような片手間PHPerに都合がいい</p> <p>お気に入りは<a href="https://laravel.com/docs/10.x/events">Events</a>のオブザーバーパタンで、1対多関係の非同期処理への派生が作りやすい</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaravel.com%2Fdocs%2F10.x%2Fevents" title="Laravel - The PHP Framework For Web Artisans" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laravel.com/docs/10.x/events">laravel.com</a></cite></p> <p>処理を追うのに知識がいるトレードオフがあるけど全部手続き処理を書くより単純になるなら使う、ぐらいのバランスで採用してる</p> <p>Laravelの標準機能ならなんでも良いのかといえば、そういうわけでもなく<a href="https://laravel.com/docs/10.x/eloquent-resources">EloquentのAPI Resource</a>(Railsのjbuilderみたいなやつ)などは ネストの奥の方で愚直にJSONシリアライズループしてN+1な手続きを発生させて遅くなっていることがプロファイラみてると発見できるので普通の手で書いたforループで置き換えたりしてる</p> <h1 id="開発手法の話">開発手法の話</h1> <p>普段の機能実装のフローとしてはいきなりDB設計とかテストコードとかを書き始めるわけなくて、最初は単一ファイルにトランザクションスクリプト(ビジネスロジックをベタ書きしたもの)を書きはじめる</p> <p>Railsだとrails runnerがあるけどLaravelだとないので、make:commandで適当なエントリーポイントを作って、そこに機能開発に必要な画面の裏側の処理だけ先に作る</p> <p>この時点ではテストファーストもしてないしUIの実装も全く手をつけていない</p> <p>コーディングで設計の作業をしているイメージ</p> <p>以前はテストケース内でこれをやっていたが設計が定まらないとテストコードの設計も決まらないのでこうなった</p> <p>全体の手順としてはビジネスロジック→DB設計→モデル→ビュー→コントローラーの順</p> <ol> <li>Commandで実行可能なトランザクションスクリプトを作成 <ol type="a"> <li>これによってデバッガを使いながらコーディングができる。Webアプリケーションの中に書き始めると手動操作が発生してしまうがスクリプトではじめるとショートカットキーで実行できるのでイテレーションサイクルが早められる</li> </ol> </li> <li>DBに変更が必要ならこの時点でmigrationを追加 <ol type="a"> <li>(1)でユースケースを先に書いてるのでスキーマをそれにあわせて発行したいSQL文からtableをつくる</li> </ol> </li> <li>DB入出力を完成させる。これでDB設計→モデルまで一旦終ったことになる</li> <li>このデータをモデルとして、(1)で書いたコードをコントローラーに持ってきて、画面に表示するビューのUI部分を作る <ol type="a"> <li>場合によってはこの段階でプロトタイプにしてUXレビューにまわす(抽象的な仕様だと手戻りがだいたい発生する)</li> <li>ビューを定義した時点で新たな事実が分かって前提が変わるので(2)をやりなおしたりする。マージ後に手戻りさせるとマイグレーションが2つになってしまうけどこの段階ならまとめられる</li> </ol> </li> <li>次にビュー→コントローラーのフェーズに移る。(1)で書いたコードをパラメータと関数に分離してパラメータはリクエストから入力+バリデーションするように変更</li> <li>抽出した関数を任意のモデルに移動。複数のモデル(≠DB table)を横断する処理はChatGPTに名前を考えてもらって単一責務な専用のクラスにする <ol type="a"> <li>自分で命名するとHogeModelServiceみたいな名前になりがち</li> </ol> </li> <li>(6)の自動テストを書く</li> <li>テストで実装の差し替えが必要になったらinterface定義してDIで差し替える</li> </ol> <p>上記は新機能開発というか更地に機能を建てる時の手順なんですけど、機能改修の時も4-5あたりから合流して同じフローに乗せてる</p> <h1 id="テストの話">テストの話</h1> <p>テストコードの方針についてもボーイスカウトルールで積み重ねていっているんだけど、とくに重視しているのはバグの再現コードをテストにしてリグレッションテストを入れるという作業</p> <p>バグを修正しないといけないという状況は=ユーザーにとって重要なコードということがはっきりしているので、テストで保護する価値も高いと考えている</p> <p>ユニットテストはコードの分離さえ積み重ねていけば前進できるけど、E2Eな統合テストはコンテキストが多用でテストケース1つの価値が低くなることもあるので、無理せずそういうテストの保守はせず消して手動テストケースのスプレッドシートに移してる</p> <p>スプレッドシート上で言語化できるってことは自動化できるやろと当初は思っていたんですけど、そううまくはいかなかった</p> <p>ということは私達は言語化していないことを暗黙的に検証してることが多いので、運用しながら監視などのアプローチをそろそろ加えるべきなのかもしれない</p> <p>Codecovで計測してる数値以下のように増加が見込めたが「内部品質向上のためにN%達成」という目標は立てずに「前期N%増減→それによって何か影響あったかなかったか」という指標として見てる</p> <p><figure class="figure-image figure-image-fotolife" title="codecov"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20231230/20231230210229.png" width="1526" height="806" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>codecov</figcaption></figure></p> <p>ただこれらの開発方針はソロ開発している都合で好きなようにやっている反面があり、分業してたりチーム開発でナレッジを運用しつつだったりすると事情が変わってくるのかもしれない</p> <p>たとえば世の中によく広まっているEntityとRepositoryを作ってビジネスの語彙で内部DSLでユースケースを記述して—— っていう戦略を最初は真似してやってみていた</p> <p>この戦略はファイルが増えるぶん複数人で作業しても衝突しない反面、EntityがDBのtableの定義に寄せられて開発ラインごとに新規tableを定義してファイル分割するようなドメインモデル貧血症問題を起こしがちだった</p> <p>それを自分たちの環境で何が必要なのかを自己認識していった結果できたのが上記の1.〜のフローになってる</p> <p>エンジニア10倍いたらそんな過程踏まずに一気にリノベしてマイクロサービス化していたかもしれない</p> <h1 id="GitHub上での活動">GitHub上での活動</h1> <p>以下は<a href="https://github.com/tarao/oss-contributions">tarao/oss-contributions</a>が生成してくれた集計結果<a href="#f-e32e75e5" id="fn-e32e75e5" name="fn-e32e75e5" title="tarao/oss-contributions: 個人/組織のOSS貢献を可視化する https://tarao.hatenablog.com/entry/2021/06/14/160248">*1</a></p> <p>「LMQL v0.0.6.1で日本語が通るようになった」 の時のプルリクエストがあるだけで、とくに目立った活動はしていないことが分かった</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2Fbb4b0a720983da" title="LMQL v0.0.6.1で日本語が通るようになった" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/bb4b0a720983da">zenn.dev</a></cite></p> <table> <tr><th align="left">Contributors</th><td align="right">1</td></tr> <tr><th align="left">Repositories</th><td align="right">2</td></tr> <tr><th align="left">Commits</th><td align="right">31</td></tr> <tr><th align="left">PRs</th> <td align="right">3</td></tr> <tr><th align="left">Reviews</th><td align="right"></td></tr> <tr><th align="left">Issues</th> <td align="right">1</td></tr> </table> <table> <tr> <td width="150px">1 commit</td> <td width="150px">2 PRs</td> <td width="150px"></td> <td width="150px"></td> </tr> <tr><td colspan="4"></td></tr> <tr><td colspan="4"> <img src="https://repository-images.githubusercontent.com/570020780/6b9aca1e-8b32-4ba3-b0ab-cda56c7bde49" width="32" height="32" align="left" /> <span> <a href="https://github.com/eth-sri/lmql"> eth-sri/lmql</a> <br> <a href="https://github.com/eth-sri/lmql/stargazers">★2,868</a> </span> </td></tr> <tr> <td><a href="https://github.com/eth-sri/lmql/commits?author=laiso">1 commit</td> <td><a href="https://github.com/eth-sri/lmql/pulls?q=is%3Apr+author%3Alaiso">1 PR</a></td> <td><a href="https://github.com/eth-sri/lmql/pulls?q=is%3Apr+reviewed-by%3Alaiso"></a></td> <td><a href="https://github.com/eth-sri/lmql/issues?q=is%3Aissue+author%3Alaiso"></a></td> </tr> <tr><td colspan="4" width="600px"> <details><summary>Pull requests</summary> <ul> <li><a href="https://github.com/eth-sri/lmql/pull/39">multibyte characters issue #38</a></li> </ul> </details> </td></tr> <tr><td colspan="4"></td></tr> <tr><td colspan="4"> <img src="https://opengraph.githubassets.com/ca7395e33e4efd14b68aa796af533b3fdc6bc23a86a3a7e7988a8d2046154e55/jzillmann/pdf-to-markdown" width="32" height="32" align="left" /> <span> <a href="https://github.com/jzillmann/pdf-to-markdown"> jzillmann/pdf-to-markdown</a> <br> <a href="https://github.com/jzillmann/pdf-to-markdown/stargazers">★884</a> </span> </td></tr> <tr> <td><a href="https://github.com/jzillmann/pdf-to-markdown/commits?author=laiso"></td> <td><a href="https://github.com/jzillmann/pdf-to-markdown/pulls?q=is%3Apr+author%3Alaiso">1 PR</a></td> <td><a href="https://github.com/jzillmann/pdf-to-markdown/pulls?q=is%3Apr+reviewed-by%3Alaiso"></a></td> <td><a href="https://github.com/jzillmann/pdf-to-markdown/issues?q=is%3Aissue+author%3Alaiso"></a></td> </tr> <tr><td colspan="4" width="600px"> <details><summary>Pull requests</summary> <ul> <li><a href="https://github.com/jzillmann/pdf-to-markdown/pull/62">Update for Node.js LTS v18 Compatibility and Dependency Fixes</a></li> </ul> </details> </td></tr> <tr><td colspan="4"></td></tr> </table> <p>ついでに2021-2022年の集計するのも忘れてたので出してみた</p> <p>2021年はVercelやAWS Amplifyを使ったアーキテクチャの研究をしていったっぽいが、2022年は記憶にも記録にも残ってない</p> <h2 id="2021年">2021年</h2> <table> <tr><th align="left">Contributors</th><td align="right">1</td></tr> <tr><th align="left">Repositories</th><td align="right">3</td></tr> <tr><th align="left">Commits</th><td align="right">17</td></tr> <tr><th align="left">PRs</th> <td align="right">3</td></tr> <tr><th align="left">Reviews</th><td align="right"></td></tr> <tr><th align="left">Issues</th> <td align="right">1</td></tr> </table> <table> <tr> <td width="150px">1 commit</td> <td width="150px">3 PRs</td> <td width="150px"></td> <td width="150px">1 issue</td> </tr> <tr><td colspan="4"></td></tr> <tr><td colspan="4"> <img src="https://opengraph.githubassets.com/3d9de6c33085c575bfa113f2d5c30e2e3a89176b94af78b5fa625398954b8623/vercel/vercel" width="32" height="32" align="left" /> <span> <a href="https://github.com/vercel/vercel"> vercel/vercel</a> <br> <a href="https://github.com/vercel/vercel/stargazers">★11,669</a> </span> </td></tr> <tr> <td><a href="https://github.com/vercel/vercel/commits?author=laiso"></td> <td><a href="https://github.com/vercel/vercel/pulls?q=is%3Apr+author%3Alaiso">1 PR</a></td> <td><a href="https://github.com/vercel/vercel/pulls?q=is%3Apr+reviewed-by%3Alaiso"></a></td> <td><a href="https://github.com/vercel/vercel/issues?q=is%3Aissue+author%3Alaiso"></a></td> </tr> <tr><td colspan="4" width="600px"> <details><summary>Pull requests</summary> <ul> <li><a href="https://github.com/vercel/vercel/pull/5628">[now-python] Fix qs encoding in http-handler</a></li> </ul> </details> </td></tr> <tr><td colspan="4"></td></tr> <tr><td colspan="4"> <img src="https://repository-images.githubusercontent.com/171566590/bcfb2180-dc06-11e9-84fb-9028e13935a6" width="32" height="32" align="left" /> <span> <a href="https://github.com/serverless-nextjs/serverless-next.js"> serverless-nextjs/serverless-next.js</a> <br> <a href="https://github.com/serverless-nextjs/serverless-next.js/stargazers">★4,321</a> </span> </td></tr> <tr> <td><a href="https://github.com/serverless-nextjs/serverless-next.js/commits?author=laiso">1 commit</td> <td><a href="https://github.com/serverless-nextjs/serverless-next.js/pulls?q=is%3Apr+author%3Alaiso">1 PR</a></td> <td><a href="https://github.com/serverless-nextjs/serverless-next.js/pulls?q=is%3Apr+reviewed-by%3Alaiso"></a></td> <td><a href="https://github.com/serverless-nextjs/serverless-next.js/issues?q=is%3Aissue+author%3Alaiso">1 issue</a></td> </tr> <tr><td colspan="4" width="600px"> <details><summary>Pull requests</summary> <ul> <li><a href="https://github.com/serverless-nextjs/serverless-next.js/pull/1477">fix(nextjs-component, nextjs-cdk-construct): create AWS resources for dynamic SSG (#1476)</a></li> </ul> </details> <details><summary>Issues</summary> <ul> <li><a href="https://github.com/serverless-nextjs/serverless-next.js/issues/1476">requires set at least one SSG path in working ISR on AWS</a></li> </ul> </details> </td></tr> <tr><td colspan="4"></td></tr> <tr><td colspan="4"> <img src="https://opengraph.githubassets.com/27fa6792bcb3d0eb7adba507d4c2a450b1d5c89343194bdaaf586cb49281d16a/serverless/blog" width="32" height="32" align="left" /> <span> <a href="https://github.com/serverless/blog"> serverless/blog</a> <br> <a href="https://github.com/serverless/blog/stargazers">★182</a> </span> </td></tr> <tr> <td><a href="https://github.com/serverless/blog/commits?author=laiso"></td> <td><a href="https://github.com/serverless/blog/pulls?q=is%3Apr+author%3Alaiso">1 PR</a></td> <td><a href="https://github.com/serverless/blog/pulls?q=is%3Apr+reviewed-by%3Alaiso"></a></td> <td><a href="https://github.com/serverless/blog/issues?q=is%3Aissue+author%3Alaiso"></a></td> </tr> <tr><td colspan="4" width="600px"> <details><summary>Pull requests</summary> <ul> <li><a href="https://github.com/serverless/blog/pull/1038">Update 2019-09-16-lambda-at-edge-support-added.md</a></li> </ul> </details> </td></tr> <tr><td colspan="4"></td></tr> </table> <h2 id="2022年">2022年</h2> <table> <tr><th align="left">Contributors</th><td align="right"></td></tr> <tr><th align="left">Repositories</th><td align="right"></td></tr> <tr><th align="left">Commits</th><td align="right">51</td></tr> <tr><th align="left">PRs</th> <td align="right">1</td></tr> <tr><th align="left">Reviews</th><td align="right"></td></tr> <tr><th align="left">Issues</th> <td align="right">3</td></tr> </table> <div class="footnote"> <p class="footnote"><a href="#fn-e32e75e5" id="f-e32e75e5" name="f-e32e75e5" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">tarao/oss-contributions: 個人/組織のOSS貢献を可視化する <a href="https://tarao.hatenablog.com/entry/2021/06/14/160248">https://tarao.hatenablog.com/entry/2021/06/14/160248</a></span></p> </div> laiso 2023年のふりかえり hatenablog://entry/6801883189069683426 2023-12-25T18:43:42+09:00 2024-01-02T17:21:08+09:00 TL;DR 2023年に学んだ知識で2024年はマネーを獲得 2022年のふりかえり 2023年にやったこと After ChatGPT ChatGPTの使い方 コーディング自動化 アプリケーション開発 クラウドプラットフォーム関連 技術系の動画 フレームワーク関連 AWSコスト最適化大作戦 オライリー本 メインエディタをVSCodeに乗り換えた AndroidからiPhone 15 Proに乗り換えた OSSへの寄付 2023年にやりたかったこと 2024年にやりたいこと LLMを活用したアプリケーションを開発する 技術書を書く ニュースレターを配信する 動画を作る 事業を作る 2022年の… <p><strong>TL;DR 2023年に学んだ知識で2024年はマネーを獲得</strong></p> <ul class="table-of-contents"> <li><a href="#2022年のふりかえり">2022年のふりかえり</a></li> <li><a href="#2023年にやったこと">2023年にやったこと</a></li> <li><a href="#After-ChatGPT">After ChatGPT</a><ul> <li><a href="#ChatGPTの使い方">ChatGPTの使い方</a></li> <li><a href="#コーディング自動化">コーディング自動化</a></li> <li><a href="#アプリケーション開発">アプリケーション開発</a></li> </ul> </li> <li><a href="#クラウドプラットフォーム関連">クラウドプラットフォーム関連</a></li> <li><a href="#技術系の動画">技術系の動画</a></li> <li><a href="#フレームワーク関連">フレームワーク関連</a></li> <li><a href="#AWSコスト最適化大作戦">AWSコスト最適化大作戦</a></li> <li><a href="#オライリー本">オライリー本</a></li> <li><a href="#メインエディタをVSCodeに乗り換えた">メインエディタをVSCodeに乗り換えた</a></li> <li><a href="#AndroidからiPhone-15-Proに乗り換えた">AndroidからiPhone 15 Proに乗り換えた</a></li> <li><a href="#OSSへの寄付">OSSへの寄付</a></li> <li><a href="#2023年にやりたかったこと">2023年にやりたかったこと</a></li> <li><a href="#2024年にやりたいこと">2024年にやりたいこと</a><ul> <li><a href="#LLMを活用したアプリケーションを開発する">LLMを活用したアプリケーションを開発する</a></li> <li><a href="#技術書を書く">技術書を書く</a></li> <li><a href="#ニュースレターを配信する">ニュースレターを配信する</a></li> <li><a href="#動画を作る">動画を作る</a></li> <li><a href="#事業を作る">事業を作る</a></li> </ul> </li> </ul> <h1 id="2022年のふりかえり">2022年のふりかえり</h1> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2Ftech2022" title="2022年の技術トピックをふりかえる - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/tech2022">laiso.hatenablog.com</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F01%2F10%2F212305" title="2022年のインターネットをふりかえる - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/01/10/212305">laiso.hatenablog.com</a></cite></p> <h1 id="2023年にやったこと">2023年にやったこと</h1> <h1 id="After-ChatGPT">After ChatGPT</h1> <p>Chat Completions APIのリリースを皮切りにプログラムからGPT-3,4の応答が呼び出せるようになったので「LLMアプリケーション」と呼ばれるようなジャンルにまでなり流行した</p> <p>当サイトでも技術的な実験記事やら観念的な持論やら今年は色々書き散らした</p> <p>まだハイプサイクルの峠をこえたんだかいないんだか明確でないので来年もしばらく続くんだろうと予測している</p> <h2 id="ChatGPTの使い方">ChatGPTの使い方</h2> <p>「OpenAI Playgroundを使ってGPTを会話風テキスト生成ツールとして楽しむ 」は世間で流通しているプロンプトハックみたいなものに意味があるのか疑問があったので書いた <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F03%2F24%2F215859" title="OpenAI Playgroundを使ってGPTを会話風テキスト生成ツールとして楽しむ - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/03/24/215859">laiso.hatenablog.com</a></cite> 「Bing AIチャットをデフォルトのウェブ検索にして使ってみた 」あたりの時期からはGoogle検索を使う機会がグッと減ったように思う <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F04%2F18%2F030717" title="Bing AIチャットをデフォルトのウェブ検索にして使ってみた - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/04/18/030717">laiso.hatenablog.com</a></cite> Bing AIチャットことMS Copilotは今はそんなに活用していないんだけど、膨大長文トークンページをMSの謎の技術力(<a href="https://github.com/microsoft/semantic-kernel">Semantic Kernel</a>?)で折り畳んで要約してくれるのPDF開いたりする時に補助的に使っている</p> <p>「TwitterでフォローしていいかどうかもGPTに決めてもらう 」は実用しているわけではないけどTwitterを再開する動機になった <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F04%2F19%2F005454" title="TwitterでフォローしていいかどうかもGPTに決めてもらう世界線 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/04/19/005454">laiso.hatenablog.com</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F06%2F29%2F201254" title="SNSに飽きてる話 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/06/29/201254">laiso.hatenablog.com</a></cite> 「英文を句構造文法に変換するやつ」「ChatGPTと英会話」はしばらくやってみたけどそんなに理解しやすいわけではなかった <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F04%2F21%2F130208" title="人間が英文を読解することに言語生成AIを使いたい - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/04/21/130208">laiso.hatenablog.com</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F04%2F22%2F130253" title="ChatGPTと英会話するためのツール - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/04/22/130253">laiso.hatenablog.com</a></cite> 「人類には早過ぎるLLMの話 」はサムアルトマン解任劇の最中に思想間対立に注目している人が少なかったので書いた <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F11%2F23%2F023915" title="人類には早過ぎるLLMの話 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/11/23/023915">laiso.hatenablog.com</a></cite> 自分はAI慎重派や効果的利他主義の考えに興味を持っていたところだったので、この解釈はすんなり受け入れられた</p> <h2 id="コーディング自動化">コーディング自動化</h2> <p>「GPTでソースコードからpatchを生成し続けたらプログラミングを自動化できるのでは???? 」や「GPT同士に対話をさせて自動でブログ記事を書くことができるのか?」は実際にできたし物凄い勢いでAPI課金されて後悔した <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F04%2F09%2Fgpgpt" title="GPTでソースコードからpatchを生成し続けたらプログラミングを自動化できるのでは???? - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/04/09/gpgpt">laiso.hatenablog.com</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F04%2F14%2F015237" title="GPT同士に対話をさせて自動でブログ記事を書くことができるのか? - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/04/14/015237">laiso.hatenablog.com</a></cite> コーディングは現在GitHubとVS Code周辺がどんどん発展していっているのあいつに任せてればよくない? と思いはじめている その一貫としてプログラムからローカルのCopilotに入出力できれば自動化できそうだなを思って内部プロトコルを調べた <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2F9456a7ba4b0712" title="GitHub Copilotの補完候補をNode.jsプログラムで取得する" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/9456a7ba4b0712">zenn.dev</a></cite> 「ライティングの哲学と未来のエディタの話 」では非コーディングな生産にもこれを拡大できるのでは、という展開をした <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F12%2F10%2F022446" title="ライティングの哲学と未来のエディタの話 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/12/10/022446">laiso.hatenablog.com</a></cite> Code Interpreterが出た後はコード読解能力にも注目した、このUXは現在のCursorやGitHub Coplilot Chatに引き継がれている <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F07%2F16%2F123214" title="ChatGPTのCode Interpreterのコードリーディング能力は結構優秀 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/07/16/123214">laiso.hatenablog.com</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F10%2F28%2F171539" title="Cursorはコードベースに質問できる - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/10/28/171539">laiso.hatenablog.com</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F12%2F02%2F150356" title="Copilot ChatのAgents機能がすごそう - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/12/02/150356">laiso.hatenablog.com</a></cite></p> <h2 id="アプリケーション開発">アプリケーション開発</h2> <p>今年の前半は<a href="https://langchain.readthedocs.io/en/latest/index.html">LangChain</a>と<a href="https://www.llamaindex.ai/">LlamaIndex</a>の実装を読みながらどんな風にGPTが活用できそうかなというのを考えていた</p> <p>当初はJSONの応答をコントロールするのも以下のようにプロンプト側で工夫していた <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2F87ae84375a7a2b" title="ChatGPT自身をAPIサーバーにする" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/87ae84375a7a2b">zenn.dev</a></cite> その後Function callingや<a href="https://platform.openai.com/docs/guides/text-generation/json-mode">JSON mode</a>が追加され楽になった <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2Fb516dc215a2e87" title="Function callingでダジャレ評価関数を作る" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/b516dc215a2e87">zenn.dev</a></cite> 開発をしていると、プロンプトAとプロンプトBのどちらが精度のよい結果が得られるのか? と思う場面が結構あって、そういう時モデル評価用のEvalsというツールが活用できた <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2F0c01417c1142b2" title="ChatGPTで大喜利エンジニアリング" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/0c01417c1142b2">zenn.dev</a></cite> さらにそれを利用して巷で噂されているプロンプトハックみたいなものの検証もしていた <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2F25eb7ea24f29e9" title="「ChatGPTに敬語で話すと回答が良くなる」という噂をEvalsで自動化して検証する" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/25eb7ea24f29e9">zenn.dev</a></cite> 現在RAGと呼ばれている関連ドキュメントを埋め込み表現で類似検索してコンテキストとしてプロンプトに含めるやつも最初は試行錯誤で、とりあえずLangChainのnotebookが追加されたらみんなで試すみたいな雰囲気だった <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2F15b0bcaa3b2a38" title="LangChain Agentでジョバンニたちの到着時刻を探索させる" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/15b0bcaa3b2a38">zenn.dev</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2Ffaa984a3e33e2b" title="Node.jsでnoteアカウントの記事を参照してGPTに質問する" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/faa984a3e33e2b">zenn.dev</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2Fb12578919ddd83" title="Semantic Kernel Pythonでユーザーごとの記憶を持たせてみる" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/b12578919ddd83">zenn.dev</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2Ff5e5c616e128a7" title="LangChainのContextual Compressionがどのようにコンテキストを圧縮しているのか" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/f5e5c616e128a7">zenn.dev</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2F627ae23862e418" title="自作Chrome拡張でChatGPT Retrieval Pluginsを動かす" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/627ae23862e418">zenn.dev</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2F5b804dc76e3511" title="Node.jsの@dqbd/tiktokenとtiktoken-nodeのトークン数の算出を比較した" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/5b804dc76e3511">zenn.dev</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2Fd961c2ed18b464" title="Cloudflare Workersで類似度ベクトル検索APIを構築する" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/d961c2ed18b464">zenn.dev</a></cite> デプロイ先のVercelやCloudflare Workers上でチャットバックエンドのSSEなAPIを実装するノウハウがまだなかったので以下を書いた <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2F7dfdcbbbe5cf76" title="Edge Runtime上でChat Completion API経由のストリーム形式のレスポンスを実装する" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/7dfdcbbbe5cf76">zenn.dev</a></cite> 今は<a href="https://github.com/vercel/ai">Vercel AI SDK</a>があるのでこっちになるべく寄せたい</p> <p>4月になったらOpenAIからChatGPTに任意のツールを差し込めるようなプラグインの仕組みが公開されたので使い方を覚えた <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Fscraps%2F0c4d0cd589dc10" title="ChatGPT Plugins開発" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/scraps/0c4d0cd589dc10">zenn.dev</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2F39174470be0608" title="ChatGPT Retriever PluginsをLangChainでデバッグする" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/39174470be0608">zenn.dev</a></cite> プラグインストアの今後はどうなるのか発表されていないが、ChatGPT上で対話したい時は<a href="https://platform.openai.com/docs/actions/actions-in-gpts">Actions in GPTs</a>で自分のサイト上でヘッドレスに使いたい時は<a href="https://platform.openai.com/docs/assistants/overview">Assistants API</a>を利用する形になるのかなと思っている</p> <p>「PaLM APIのファインチューニングではてな匿名ダイアリー風文章生成モデルを作る 」ではGoogle CloudのMLプラットフォームの使い方に詳しくなった <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F08%2F27%2F192730" title="PaLM APIのファインチューニングではてな匿名ダイアリー風文章生成モデルを作る - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/08/27/192730">laiso.hatenablog.com</a></cite> 後継モデルの<a href="https://deepmind.google/technologies/gemini/">Gemini</a>はOpenAIのGPTモデルと価格競争力に優れそうなので出番があるかもしれない</p> <p>Windowsマシンを用意したのも生成AIのモデルを動かすためにGoogle Colabの強いインスタンス借りるのはだるいな〜と思い自分のGPUが欲しくなったため <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F09%2F03%2F233712" title="ニューWindowsマシンのセットアップした - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/09/03/233712">laiso.hatenablog.com</a></cite> それまでは以下のようにSeamlessM4TやVOICEVOXの音声合成エンジンをColabを動かしてなんとかしていた <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2Ff7f3a11153dd80" title="SeamlessM4Tで英語のYouTube動画の日本語音声を自動生成する" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/f7f3a11153dd80">zenn.dev</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2F16dfaea68d3f68" title="VOICEVOXエンジンをGoogle Colabで起動してMacのエディタから使う" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/16dfaea68d3f68">zenn.dev</a></cite> 結局まだこのPCはそんなに活用していないんだけど久しぶりにWindowsの開発環境に触れているのが楽しい</p> <h1 id="クラウドプラットフォーム関連">クラウドプラットフォーム関連</h1> <p>サーバーレスとDB接続問題は今年は各種DBプロバイダーがホスティング側で解決しだしたのであまり気にする必要がなくなってきた <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Fscraps%2F595d631fe19ef5" title="VercelからMySQL/PostgreSQLに接続したい場合にどういうアーキテクチャにするのが最適か" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/scraps/595d631fe19ef5">zenn.dev</a></cite> とくにNeonがsocket接続を実行時にWebSocketに差し替えて解決していたのに感心した <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2F542fdfac2acb6b" title="Vercel PostgresがどうやってEdge RuntimeでORMとコネクションプールを使えるようにしているのか" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/542fdfac2acb6b">zenn.dev</a></cite> 現在はSocket APIさえ呼び出せばCloudflareがHTTPからTCPのレイヤーを維持して接続してくれる仕組みがあるのでより楽になりつつある <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2F6ae13d95235e4a" title="workerdのSocket APIでPostgreSQLに接続してみる" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/6ae13d95235e4a">zenn.dev</a></cite> 「サーバーレスをやめろ」に出てきたMRSKは現在は<a href="https://world.hey.com/dhh/kamal-1-0-5304ff9e">Kamal</a>という名前になって37signalsの本番環境で動いているらしい <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2Fddhh" title="最近のDHH「サーバーレスをやめろ」 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/ddhh">laiso.hatenablog.com</a></cite> Internet Computerは世間ではマイナーブロックチェーンの一種ぐらいにしか捉えられてないかもしれないが自分はアプリケーションをデプロイできるマイナーなプラットフォームとして強引に理解しているのでこの記事を書いた <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2Fic" title="Internet Computer Dapp開発入門 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/ic">laiso.hatenablog.com</a></cite> 全く誰も興味なさそうだった</p> <p>「AWS Lambda Go 1.x ランタイム終了を時系列理解 」はXのタイムラインで「Go言語オワタ」「サーバーレスの悲劇」みたいな反応をしている人たちがいたので、どゆこと? と思い調べた <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F08%2F27%2F150820" title="[アクションが必要]AWS Lambda Go 1.x ランタイム終了を時系列理解 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/08/27/150820">laiso.hatenablog.com</a></cite> こういう感じでSNSシェアで話題になっていることの確認をしにいくようなムーブが今年は多かった</p> <p>「しずかなインターネットの技術スタックを調べる」や <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F11%2F23%2F210736" title="「しずかなインターネット」の技術スタックを調べる - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/11/23/210736">laiso.hatenablog.com</a></cite></p> <p>「デジタル庁でjQueryが何をしているのか 」もその1つ <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F12%2F14%2F184602" title="デジタル庁でjQueryが何をしているのか - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/12/14/184602">laiso.hatenablog.com</a></cite> これは中の人が「Drupalするならまず人脈・・」みたいな反応をしていたのがちょっと面白かった</p> <p>SQLiteの本番サーバー活用の分野はLiteFSとD1が牽引していて、どちらもベンダーロックインがあるが、今年はD1がpublic betaになり、LiteFS Cloudというマネージドサービスが提供された <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2F3bc2f8d0474d6c" title="LiteFS及びFly.io最新情報" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/3bc2f8d0474d6c">zenn.dev</a></cite> どちらも無料からワンコインの予算感で運用できるようになっている</p> <h1 id="技術系の動画">技術系の動画</h1> <p>今年は技術系の動画をよく見るようにした「React.js: The Documentary」や「TypeScript Origins: The Documentary」「Ruby on Rails: The Documentary」がおすすめOSSドキュメンタリー3点セットで感想記事を書いた <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2Freact-documentary" title="React.js: The Documentaryで振り返るReact普及の歴史 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/react-documentary">laiso.hatenablog.com</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F09%2F22%2F232349" title="TypeScript Origins: The Documentaryを観た - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/09/22/232349">laiso.hatenablog.com</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F11%2F10%2F234344" title="Ruby on Rails: The Documentary - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/11/10/234344">laiso.hatenablog.com</a></cite> 他には「The shape of future builders: from design to deploy 」や「Video Editing in the Browser 」などのカンフェレンス系の動画も見ていた <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.jp%2Fentry%2F2023%2F06%2F24%2F192715" title="The shape of future builders: from design to deploy - Guillermo Rauch (Config 2023) https://www.youtube.com/watch?v=Q20HfSyqm78 - を読んだ" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.jp/entry/2023/06/24/192715">laiso.hatenablog.jp</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.jp%2Fentry%2F2023%2F08%2F03%2F004609" title="Video Editing in the Browser https://www.youtube.com/watch?v=-d6q4yb57F8 - を読んだ" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.jp/entry/2023/08/03/004609">laiso.hatenablog.jp</a></cite> 記事にしていない範囲だとBunの作者インタビューが面白かった <iframe width="560" height="315" src="https://www.youtube.com/embed/jPupI9-UKRs?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen title="Bun.js with Jarred Sumner - JSJ 584"></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?v=jPupI9-UKRs">www.youtube.com</a></cite> 個人開発者としてゲームを作っているうちにツール作りがメインになってBunができたらしい</p> <p>「光の速さが同じはずなのにbun installだけ何で早いの?」と疑問だったので詳しく調べた <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Fscraps%2F9a787a6888e228" title="なんでbun installは速いのか?" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/scraps/9a787a6888e228">zenn.dev</a></cite></p> <h1 id="フレームワーク関連">フレームワーク関連</h1> <p>「Remove TypeScript」はある日いつものようにDHH周辺のXのタイムラインが荒れていて日常やね〜 とのほほんと眺めていたらいつも見かけないフロントエンド界隈のOSS有名人が沢山出てきて何事!? と思い動向を追っていた <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F09%2F07%2F153417" title="Remove TypeScript - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/09/07/153417">laiso.hatenablog.com</a></cite> 記事に書いたとうりこれはTurboの開発方針に関わる意思決定なので、言語論争だけしたい人が大量に流入してくるのに疑問を持っていたが、ある人がコメントで「DHHがブログで煽るからじゃない?」と言っててそれはそうと納得した</p> <p>一方Turboのモバイルアプリ連携コンポーネントのStradaが正式にリリースされ、世間の話題にはなっていない <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2Fe79d3125705294" title="StradaのWebViewとネイティブコード連携を理解する" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/e79d3125705294">zenn.dev</a></cite> Zenn全体でStradaの記事書いているのが自分だけという悲しい状況</p> <p>「丁寧なDeno+JSX」ではサーバーサイドNext.jsは最適か? →MVCフレームワークに戻るか? →別の道も探すか? という今時の課題に自分なりの答えを出した <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F10%2F23%2F172934" title="丁寧なDeno+JSX - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/10/23/172934">laiso.hatenablog.com</a></cite> ここに書いてないことで特筆すべきこととしては最近は<a href="https://astro.build/">Astro</a>のSRRも便利に使っている</p> <p>「いまさら振り返るRxSwift」はXの弊タイムラインにいるiOS関係の人達がRxSwiftの学習コストについて議論していたので懐しくなって自分も振り返った <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F10%2F27%2F212748" title="いまさら振り返るRxSwift - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/10/27/212748">laiso.hatenablog.com</a></cite> WebUIについては新しものが出てきたらとりあえずひとうり理解するルーチンの1ついう感じ <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F12%2F23%2F165348" title="WebUIについて調べた - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/12/23/165348">laiso.hatenablog.com</a></cite> 「GPT-4の画像認識とPlaywrightでポケモン判定ツールを作る」ではGPT-4のAPIが未リリースだった頃に無理矢理使おうとして試行錯誤したもの <a href="https://zenn.dev/laiso/articles/fac48615b30046">https://zenn.dev/laiso/articles/fac48615b30046</a> GPTよいうよりむしろPlaywrightとChromiumの接続仕様の勉強になった</p> <h1 id="AWSコスト最適化大作戦">AWSコスト最適化大作戦</h1> <p>2023年の円安ドル高の市況でどこの企業も似たようなことをやっていそうだけど、自分もAWSインフラのランニングコストを削減するための作業を片手間にやっていた</p> <p>そんなに特別なことはやっていなくてSpot InstanceやReseverved Instance、Saving Planを活用、余剰リソースを整理してアプリケーションも書き換えインスタンスの単価を減らす、というようなコスト最適化をするのに当たり前なことを作業の優先順位の一番上に持ってきた</p> <p>これには「<a href="https://www.amazon.co.jp/dp/B0BYC5H9G8?tag=rer-22&amp;linkCode=ogi&amp;th=1&amp;psc=1">AWSコスト最適化ガイドブック</a>」「<a href="https://www.amazon.co.jp/dp/B08HRRX1G8?tag=rer-22&amp;linkCode=ogi&amp;th=1&amp;psc=1">Amazon Web Services コスト最適化入門 (技術の泉シリーズ(NextPublishing))</a>」を参考にした</p> <h1 id="オライリー本">オライリー本</h1> <p>自分は県内一のオライリー本廃課金勢だと思っているんだけど、アカウンティング関連の整理していたら現在はPayPalが使えなくなっていて、オライリージャオパンや技術評論社のDRMフリーの電子書籍が買えなくなって困っていたので以下の記事を投稿した <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2Ffor-tim" title="PayPalアカウントがないとオライリー本買えなくて不便 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/for-tim">laiso.hatenablog.com</a></cite> その後<a href="https://www.oreilly.com/online-learning/individuals.html">Online Learning with O'Reilly</a>のサブスクを契約して対応している本は読んでいたりした <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F07%2F28%2F171613" title="オライリー本が買えない話その後 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/07/28/171613">laiso.hatenablog.com</a></cite> さらに10月になるとクレジットカードでの決済に対応するアップデートが来ていたのでありがたく使わせてもらっている <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F10%2F28%2F151426" title="PayPalアカウントがなくてもオライリー本は買える(確信) - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/10/28/151426">laiso.hatenablog.com</a></cite> Online Learning with O'Reillyの方のサブスクはこれはこれで色んな洋書を読めて便利だったので年間契約に移行した</p> <h1 id="メインエディタをVSCodeに乗り換えた">メインエディタをVSCodeに乗り換えた</h1> <p>2023年のVS Code x GitHub Copilot関連の圧倒的進化速度を目の前にしてこれは第一エディタにしとかないと色んな機能がキャッチアップできないなと感じたのでJetBrains系から乗り換えた</p> <p>ただしPHPのコーディング環境は<a href="https://www.jetbrains.com/ja-jp/phpstorm/">PhpStorm</a>の方が快適なので、Laravel系の開発をする時だけ使っている</p> <p>しかしXcodeでSwiftを書いている純iOSエンジニアたちは、サードパーティプラグインがあるとはいえ、このままVS Code x GitHub Copilot並の開発者体験に合流することはないんだろうか、というのがちょっと気になっている</p> <p>(またはそれは自分の過小評価でXcode単体で充分足りる?)</p> <h1 id="AndroidからiPhone-15-Proに乗り換えた">AndroidからiPhone 15 Proに乗り換えた</h1> <p>XiaomiのAndroid端末を2年ほど使っていたので、2年ごとにiPhoneとAndroid端末を乗り換えるルールにしたがってiPhone 15 Proに乗り換えた <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F09%2F30%2F185450" title="2年ごとにiPhoneとAndroid端末を乗り換えている話 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/09/30/185450">laiso.hatenablog.com</a></cite> いっちょWear OSアプリ開発をはじめるかと購入したGalaxy Watch5がiOSとペアリングできなくてモチベーション下った <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2Fwearos" title="Wear OSアプリ開発入門 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/wearos">laiso.hatenablog.com</a></cite></p> <h1 id="OSSへの寄付">OSSへの寄付</h1> <p><a href="https://github.com/codefirst/aquaskk">aquaskk</a>に加えて、ずんだもんボイスでお馴染の<a href="https://voicevox.hiroshiba.jp/">VOICEVOX</a>への寄付をはじめた。</p> <p>VOICEVOXは経済的価値を生み出している割に明かに資金流入の足りてないプロジェクトであるのでもっと支援者が増えてほしい <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhiho.fanbox.cc%2F" title="ヒホ|pixivFANBOX" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://hiho.fanbox.cc/">hiho.fanbox.cc</a></cite></p> <h1 id="2023年にやりたかったこと">2023年にやりたかったこと</h1> <p>去年に「GoやGraphQLやモバイルアプリ開発を勉強しとかな」と書いたけど、その時間を全部ChatGPT関連に流した感じ</p> <p>これについては「次の技術選定で無理矢理ねじ込む」とか「案件を獲得して実践する」などでコミットメントを達成しようという気はなくて、自分の正確では「やらなかったということは必要なことではなかった」と結論付けることになった</p> <p>一方「AI系の何かをやりたい」という目標はたぶん満たされており、「大規模フロントエンド開発の経験」は行動したいがうまくいかない、ぐらいの塩梅にあるのでストレッチゴールとしては丁度よかったのではないか</p> <p>ということで次の目標を立てることにします</p> <h1 id="2024年にやりたいこと">2024年にやりたいこと</h1> <h2 id="LLMを活用したアプリケーションを開発する">LLMを活用したアプリケーションを開発する</h2> <p>せっかく2023年にいろいろキャッチアップして今までなかった知恵がついたので、これを使って個人でアプリケーションを作って公開したい</p> <p>今のところ文章執筆や構成を自動化するアウトラインプロセッサーと作りたいと思っているけどマイナージャンルなので、それよりよいアイデアがあったらそっちに切り換えるかもしれない</p> <h2 id="技術書を書く">技術書を書く</h2> <p>オライリーのサブスクでブラウザで本を読んでいるうちに「あれこれってブログでは?」という気分になってきて、技術書がブログみたいなもんなら自分にも書けるかもと思えてきた</p> <p>今まで技術書というのは長い長い長期プロジェクトをひらすら続けないといけない上に書いたものを公開できないイメージだったのだけど、オライリーのEAP版とか<a href="https://peaks.cc/">PEAKS</a>のような先に売る形態もあるし、コンテンツをWebに置いて販売も自分でするという方法でなんとか達成できないかと考えている</p> <p>先のLLMを使った自動化はライターやエディター個人の能力を拡大するものだと思っているので、アウトラインプロセッサーを作るという目標ともリンクしている</p> <p>とりあえず士気が上ってちゃんとした文章書くぞという気になり「理工系のためのよい文章の書き方」や「数学文章作法」を先日読んでいた</p> <h2 id="ニュースレターを配信する">ニュースレターを配信する</h2> <p>ジャンルは全然決めていないんだけど読者を募って定期的にメール配信するようなコンテンツを作りたい</p> <p>これにはsubstack.comやnote.comなどの色んなプラットフォームがあるんだけど、自分はGitHub Sponsorsの機能を使って運用したい</p> <p>スポンサー募集ページは以下に作ったんですけど、今後コンテンツを発信していく際に宣伝しようと思うのでよかったら参加してください</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fsponsors%2Flaiso" title="Sponsor @laiso on GitHub Sponsors" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://github.com/sponsors/laiso">github.com</a></cite></p> <h2 id="動画を作る">動画を作る</h2> <p>VOICEVOXを触っていたことと関連するんですけど、スクリーンキャストや技術解説の動画を作ってみたい</p> <p>これは技術書で書くような内容をさらにマスな層に届けるために必要なことだと思っていて、尊敬するプログラマーであるDHHや<a href="https://kentcdodds.com/">Kent C. Dodds</a>はよく考えたら動画活動を熱心にやっているのでどこにそんなモチベーションが? というのを昔から気になっていた</p> <p>とくにKent C. DoddsはRemixを離れプログラマー界のバズレシピみたいなチームを自分たちで作り高額動画教材(現為替レートで17万円)を売っているので、どういう動機でこの活動をしているのか気になっている</p> <h2 id="事業を作る">事業を作る</h2> <p>今まであげた「アプリ開発」「技術書」「ニュースレター」「動画」すべてにつながることであるんだけど、それらを金銭の発生する事業に発展させないと深い取り組みにならないなと思っている</p> <p>「新技術を覚えるために副業で請け負い開発をする」などを近い動機かもしれない</p> <p>それはそれで責任を伴うからプライベートでやるには重いことなのかもしれないが、今まであまり意識したことがなかったのでやっていきたい</p> laiso 2023年に読んだ漫画やゲーム hatenablog://entry/6801883189069451806 2023-12-24T21:34:38+09:00 2023-12-24T21:35:19+09:00 漫画 今年読んだ中でおすすめなのはドラマ化もした「トリリオンゲーム」という作品 トリリオンゲーム(1) (ビッグコミックス)作者:池上遼一小学館Amazon 日本のスタートアップやベンチャー業界のマネーゲームをモチーフに プログラマーの主人公がハスラーな友達と起業して振り回されつつ要所ではハッカーとして覚醒して1兆企業目指すぞ的な漫画 池上遼一の劇画調で新興ビジネスを描いてるギャップ効果で面白くなっている気がする 元ネタがはっきり分かるぐらい、あからさまな業界あるあるが出てきて、ストーリー上のどんでん返しの為に無茶をしていて、時々「犯罪では?」とツッコみをうけている あとはポットキャストで紹介… <h1 id="漫画">漫画</h1> <p>今年読んだ中でおすすめなのはドラマ化もした「トリリオンゲーム」という作品</p> <p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/B08YJWRJ4V?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51xaU2VuraL._SL500_.jpg" class="hatena-asin-detail-image" alt="トリリオンゲーム(1) (ビッグコミックス)" title="トリリオンゲーム(1) (ビッグコミックス)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/B08YJWRJ4V?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1" target="_blank" rel="noopener">トリリオンゲーム(1) (ビッグコミックス)</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="https://d.hatena.ne.jp/keyword/%C3%D3%BE%E5%CE%CB%B0%EC" class="keyword">池上遼一</a></li><li>小学館</li></ul><a href="https://www.amazon.co.jp/dp/B08YJWRJ4V?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p> <p>日本のスタートアップやベンチャー業界のマネーゲームをモチーフに</p> <p>プログラマーの主人公がハスラーな友達と起業して振り回されつつ要所ではハッカーとして覚醒して1兆企業目指すぞ的な漫画</p> <p>池上遼一の劇画調で新興ビジネスを描いてるギャップ効果で面白くなっている気がする</p> <p>元ネタがはっきり分かるぐらい、あからさまな業界あるあるが出てきて、ストーリー上のどんでん返しの為に無茶をしていて、時々「犯罪では?」とツッコみをうけている</p> <p>あとはポットキャストで紹介されていたやつをそのまま購入する機会が多い</p> <p><a href="https://podcasters.spotify.com/pod/show/middle-aged-developers/episodes/25-Inefficiency-makes-value-e1o13g0">Middle Aged Developers</a>ポットキャストで紹介されていた「ひゃくえむ。」を読んだ</p> <p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/B09VSVM8J8?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51GmN0WsWsL._SL500_.jpg" class="hatena-asin-detail-image" alt="ひゃくえむ。新装版 上 (マガジンポケットコミックス)" title="ひゃくえむ。新装版 上 (マガジンポケットコミックス)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/B09VSVM8J8?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1" target="_blank" rel="noopener">ひゃくえむ。新装版 上 (マガジンポケットコミックス)</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="https://d.hatena.ne.jp/keyword/%B5%FB%CB%AD" class="keyword">魚豊</a></li><li>講談社</li></ul><a href="https://www.amazon.co.jp/dp/B09VSVM8J8?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p> <p>この作品は「ピンポン」のような才能と能力の関係をうまくドラマにしていて、プログラマーの世界も他人の才能や能力を否が応にも実感させられる環境なので楽しく読んだ</p> <p>他には<a href="https://podcasts.apple.com/vn/podcast/%E3%83%9E%E3%83%B3%E3%82%AC%E3%81%AE%E3%83%A9%E3%82%B8%E3%82%AA-vol-65-%E3%81%A8%E3%82%88%E7%94%B0%E3%81%BF%E3%81%AE%E3%82%8B%E3%81%95%E3%82%93-%E3%81%9D%E3%81%AE1-%E6%9C%AC%E5%A0%82%E3%81%AF%E3%83%9E%E3%83%B3%E3%82%AC%E5%96%AB%E8%8C%B6/id1562792453?i=1000575260545&amp;l=vi">マンガのラジオ</a>から「<a href="https://www.amazon.co.jp/dp/B09YH8ZX5T?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1">これ描いて死ね</a>」</p> <p><a href="https://www.youtube.com/watch?v=evVYt1FsbFg">中田オススメの今面白い漫画</a>から「<a href="https://www.amazon.co.jp/dp/B08GC7TB1F?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1">王様ランキング</a>」</p> <p><a href="https://www.youtube.com/watch?v=Htj7UPdTC7c">読書の秋!マンガの秋!プレゼンするぞ!</a>から「<a href="https://www.amazon.co.jp/dp/B085C8KPC7?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1">妻と僕の小規模な育児</a>」「<a href="https://www.amazon.co.jp/dp/B09XQL8CGV?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1">住みにごり</a>」を読んだ</p> <p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/B085C8KPC7?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51SRUtxUK1L._SL500_.jpg" class="hatena-asin-detail-image" alt="妻と僕の小規模な育児(1) (コミックDAYSコミックス)" title="妻と僕の小規模な育児(1) (コミックDAYSコミックス)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/B085C8KPC7?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1" target="_blank" rel="noopener">妻と僕の小規模な育児(1) (コミックDAYSコミックス)</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="https://d.hatena.ne.jp/keyword/%CA%A1%CB%FE%A4%B7%A4%B2%A4%E6%A4%AD" class="keyword">福満しげゆき</a></li><li>講談社</li></ul><a href="https://www.amazon.co.jp/dp/B085C8KPC7?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p> <p>妻と僕の—— の福満しげゆきはガロ系の作家で、漫画家が漫画の中で漫画を描くエッセイ漫画みたいなものを大量に描いてる</p> <p>作品はどれも<ドジっ子>特有のあるあるみたいなものが大量に描かれていて好みだったので「<a href="https://www.amazon.co.jp/dp/B08BWZZZRV?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1">僕の小規模な失敗</a>」「<a href="https://www.amazon.co.jp/dp/B00A765Y3U?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1">僕の小規模な生活</a>」「<a href="https://www.amazon.co.jp/dp/B00A2MD05I?tag=rer-22&amp;linkCode=ogi&amp;th=1&amp;psc=1">生活</a>」の過去作も購入した</p> <p>「住みにごり」は家族愛の問題を青年誌っぽい暗めのトークンで描いた作品で、ミステリー要素はありつつも基本的にキャラクター造形で楽しむものっぽい</p> <p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/B09XQL8CGV?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51O3nM4z3oL._SL500_.jpg" class="hatena-asin-detail-image" alt="住みにごり(1) (ビッグコミックス)" title="住みにごり(1) (ビッグコミックス)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/B09XQL8CGV?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1" target="_blank" rel="noopener">住みにごり(1) (ビッグコミックス)</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="https://d.hatena.ne.jp/keyword/%A4%BF%A4%AB%A4%BF%A4%B1%A4%B7" class="keyword">たかたけし</a></li><li>小学館</li></ul><a href="https://www.amazon.co.jp/dp/B09XQL8CGV?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p> <p>同じく家族愛がテーマの「<a href="https://www.amazon.co.jp/dp/B0BT4PD1R7?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1">一ノ瀬家の大罪</a>」は「<a href="https://www.amazon.co.jp/dp/B09R9YL6Q8?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1">タコピーの原罪</a>」の作者の新作で、だいたいいつもタイムリープしてる。絵柄は全然違うけど「住みにごり」似たような印象を持っている。</p> <p>あとは「<a href="https://www.amazon.co.jp/dp/B07GDFH4VT?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1">前科者</a>」「<a href="https://www.amazon.co.jp/dp/B07FCHN6XQ?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1">天国大魔境</a>」「<a href="https://www.amazon.co.jp/dp/B08VRFN9ZL?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1">ちいかわ</a>」、<a href="https://comic-action.com/episode/4856001361287348513">アンチマン</a>著者の「<a href="https://www.amazon.co.jp/dp/B07NVJ6C5N?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1">メイコの遊び場</a>」などを読んだ</p> <h1 id="ゲーム">ゲーム</h1> <p>おすすめは<a href="https://www.jp.square-enix.com/paranormasight/">パラノマサイト</a>というゲームで以下に感想を書いた</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.jp%2Fentry%2F2023%2F11%2F08%2F234640" title="パラノマサイト FILE 23 本所七不思議 https://www.jp.square-enix.com/paranormasight/ - を読んだ" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.jp/entry/2023/11/08/234640">laiso.hatenablog.jp</a></cite></p> <p>あとは「<a href="https://www.amazon.co.jp/dp/B0BVNW23Y1?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1">超探偵事件簿 レインコード</a>」「<a href="https://www.amazon.co.jp/dp/B09WW5VGG3?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1">ANONYMOUS;CODE</a>」「<a href="https://store.steampowered.com/app/588040/WILL_A_Wonderful_World__WILL/">WILL: A Wonderful World</a>」などのノベル系のゲームが最近は多い</p> <p>今は「<a href="https://store.steampowered.com/app/1684660/_/">ナツノカナタ</a>」と「<a href="https://store.steampowered.com/app/1783360/_/">メグとばけもの</a>」をやってる</p> <h2 id="スト6">スト6</h2> <p>9月頃に自作PCをわざわざ新規構築して「<a href="https://www.amazon.co.jp/dp/B0C6DHKR39?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1">ストリートファイター6</a>」を買った</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F09%2F03%2F233712" title="ニューWindowsマシンのセットアップした - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/09/03/233712">laiso.hatenablog.com</a></cite></p> <p>アケコンがないのでキーボードでストレスフルにやってるけど地域的にマッチング人口が少ないので快適ではない</p> <p>そう考えるとUAEやシンガポールのプロゲーマーとかすごい</p> <p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/B0C6DHKR39?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/61u2NvL3XoL._SL500_.jpg" class="hatena-asin-detail-image" alt="【Steamキー】ストリートファイター6|オンラインコード版" title="【Steamキー】ストリートファイター6|オンラインコード版"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/B0C6DHKR39?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1" target="_blank" rel="noopener">【Steamキー】ストリートファイター6|オンラインコード版</a></p><ul class="hatena-asin-detail-meta"><li>カプコン</li></ul><a href="https://www.amazon.co.jp/dp/B0C6DHKR39?tag=rer-22&amp;linkCode=osi&amp;th=1&amp;psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p> <h2 id="スイカ">スイカ</h2> <p>最近は<a href="https://store-jp.nintendo.com/list/software/70010000043363.html">スイカゲーム</a>を毎日やってる</p> <p>スコア3000点を突破してダブルスイカを目指してる</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fstore-jp.nintendo.com%2Flist%2Fsoftware%2F70010000043363.html" title="スイカゲーム ダウンロード版" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://store-jp.nintendo.com/list/software/70010000043363.html">store-jp.nintendo.com</a></cite></p> <p>PS: この記事は書影の表示のためにAmazon.co.jpの商品埋め込みリンクを利用しています。2023年の当サイトのアフィリエイト報酬は¥852でした</p> laiso WebUIについて調べた hatenablog://entry/6801883189069112394 2023-12-23T16:53:48+09:00 2023-12-30T21:59:22+09:00 WebUIはデスクトップアプリを作るためのライブラリ。HTML, CSS, JavaScriptでフロントエンドを作り、バックエンドをC, C++, Python, Go, TypeScriptなどの言語で開発できる。システムにインストールされているWebブラウザで動作する https://webui.me/webui.me 2023年にhassandragaさんが公開し、V言語コミッタのttytmさんらも参加した 本体はCで開発されていて、Python, Go, TypeScriptにバイディングが提供されている 似た技術としてはElectronやTauri、Gluonなどが存在する lai… <p>WebUIはデスクトップアプリを作るためのライブラリ。HTML, CSS, JavaScriptでフロントエンドを作り、バックエンドをC, C++, Python, Go, TypeScriptなどの言語で開発できる。システムにインストールされているWebブラウザで動作する</p> <p><a href="https://webui.me/">https://webui.me/</a><cite class="hatena-citation"><a href="https://webui.me/">webui.me</a></cite></p> <p>2023年に<a href="https://github.com/hassandraga">hassandraga</a>さんが公開し、V言語コミッタの<a href="https://github.com/ttytm">ttytm</a>さんらも参加した</p> <p>本体はCで開発されていて、Python, Go, TypeScriptにバイディングが提供されている</p> <p>似た技術としては<a href="https://www.electronjs.org/">Electron</a>やTauri、<a href="https://github.com/gluon-framework/gluon">Gluon</a>などが存在する</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2Ftauri-on-mobile" title="Tauri on mobile 現状確認会 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/tauri-on-mobile">laiso.hatenablog.com</a></cite></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2F825ee7e652ad1b" title="Tauri+Next.jsでモバイルアプリ開発" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/825ee7e652ad1b">zenn.dev</a></cite></p> <h1 id="アーキテクチャについて">アーキテクチャについて</h1> <p>ElectronやTauriと比較すると、WebUIのアーキテクチャはWebアプリをブラウザで開くだけなのでより単純かつ制約が大きい</p> <p>開発者にとってはブラウザを使ってプログラムにGUIを付けられるライブラリであり</p> <p>ユーザーにはChromeの<a href="https://support.google.com/a/users/answer/13293027#desktop_shortcut">desktop shortcuts</a>のようにスタンドアロンなウィンドウで起動するWebアプリになる</p> <p>他のフレームワークとの簡単な比較図を作った</p> <table> <thead> <tr> <th> </th> <th> Presentation </th> <th> Main Program </th> <th> Bridge </th> </tr> </thead> <tbody> <tr> <td> Electron </td> <td> Chromium </td> <td> Node.js </td> <td> IPC </td> </tr> <tr> <td> Tauri </td> <td> WebView </td> <td> Rust </td> <td> IPC(JSON-RPC) </td> </tr> <tr> <td> WebUI </td> <td> Web Browser </td> <td> C and bindings </td> <td> HTTP(WebSocket) </td> </tr> </tbody> </table> <p>WebUIでデスクトップアプリを起動する時のフローが以下になっている</p> <ol> <li>Pythonなどで記述したMainプログラム(<a href="https://github.com/webui-dev/python-webui/blob/main/examples/hello_world.py">hello_world.py</a>)を実行</li> <li>WebUIがシステムにインストールされているウェブブラウザを呼び出す</li> <li>専用のプロファイルでMainプログラムが実行する<code>http://localhost:53949</code>を開いてデスクトップアプリっぽく見せる</li> </ol> <pre class="code bash" data-lang="bash" data-unlink>git clone https://github.com/webui-dev/python-webui cd python-webui/examples pip install webui2 python hello_world.py</pre> <pre class="code python:hello_world.py" data-lang="python:hello_world.py" data-unlink>MyWindow = webui.window() MyWindow.show(login_html) # 描画するHTMLのテキスト</pre> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20231223/20231223155223.png" width="2000" height="1748" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>このデスクトップアプリのシステムWindowは「Google Chrome」になっていて以下のプロセスで実行されている</p> <pre class="code bash" data-lang="bash" data-unlink>ps x | grep .WebUI /Applications/Google Chrome.app/Contents/MacOS/Google Chrome --user-data-dir=/Users/laiso/.WebUI/WebUIChromeProfile --no-first-run --no-proxy-server --safe-mode --disable-extensions --disable-background-mode --disable-plugins --disable-plugins-discovery --disable-translate --disable-features=Translate --bwsi --disable-sync --disable-sync-preferences --disable-component-update --allow-insecure-localhost --app=http://localhost:53949</pre> <h1 id="Mainプログラムとブラウザのブリッジ連携">Mainプログラムとブラウザのブリッジ連携</h1> <p>Mainプログラム側からブラウザの値を参照するにはJavaScriptコードを送る</p> <pre class="code lang-python" data-lang="python" data-unlink>res = e.window.script(<span class="synConstant">&quot;return document.getElementById(</span><span class="synSpecial">\&quot;</span><span class="synConstant">MyInput</span><span class="synSpecial">\&quot;</span><span class="synConstant">).value;&quot;</span>) <span class="synStatement">if</span> res.data == <span class="synConstant">&quot;123456&quot;</span>: <span class="synIdentifier">print</span>(<span class="synConstant">&quot;Password is correct.&quot;</span>) </pre> <p>逆にブラウザ側からMainプログラムの関数を呼び出す時は<code>windows.webui</code>オブジェクト経由でバインドしておく</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synStatement">def</span> <span class="synIdentifier">check_the_password</span>(e : webui.event): <span class="synComment">#...</span> MyWindow.bind(<span class="synConstant">'CheckPassword'</span>, check_the_password) </pre> <pre class="code lang-html" data-lang="html" data-unlink><span class="synIdentifier">&lt;</span><span class="synStatement">button</span><span class="synIdentifier"> </span><span class="synSpecial">onclick=&quot;webui.CheckPassword</span>()<span class="synSpecial">&quot;</span><span class="synIdentifier">&gt;</span>Check Password<span class="synIdentifier">&lt;/</span><span class="synStatement">button</span><span class="synIdentifier">&gt;</span> </pre> <p>もしくはHTMLのid要素に暗黙的にバインドされている</p> <pre class="code lang-html" data-lang="html" data-unlink><span class="synIdentifier">&lt;</span><span class="synStatement">button</span><span class="synIdentifier"> </span><span class="synType">id</span><span class="synIdentifier">=</span><span class="synConstant">&quot;CheckPassword&quot;</span><span class="synIdentifier">&gt;</span>Check Password<span class="synIdentifier">&lt;/</span><span class="synStatement">button</span><span class="synIdentifier">&gt;</span> </pre> <p>これを使うためにHTML側には <code>&lt;script src="webui.js"&gt;&lt;/script&gt;</code> のおまじないが入ってないといけない</p> <p>この中身が<a href="https://github.com/webui-dev/webui/tree/main/bridge">webui /bridge/</a>で、TypeScriptで書いたWebSocketクライアントをさらにCのヘッダにhexにして埋め込んでいる</p> <p>埋め込んだ文字列をローカルサーバーの <code>/webui.js</code> として返している</p> <p>なんでそんなことを…… と最初思ったが、バイナリに埋め込み静的ライブラリとして配布するため?</p> <h1 id="その他の特性">その他の特性</h1> <ul> <li>あくまでライブラリでデスクトップアプリを配布用にパッケージングする仕組みなどはない <ul> <li>例えばMainプログラムの実行にPythonが必要なら利用する環境にもインタプリタがないといけない</li> </ul> </li> <li>ブラウザの中で動いているローカルなWebアプリなので、その外側のOSの機能(システムメニューなど)まではアクセスできない</li> </ul> <p>ドキュメントは <a href="https://webui.me/docs/">https://webui.me/docs/</a></p> <h1 id="Disclaimer">Disclaimer</h1> <p>この記事はWebUIのコア実装の理解に焦点を置いています。ElectronやTauriと比較し、WebUIの利用を薦めるものではありません</p> <p>筆者はデスクトップアプリの開発にはプラットフォームの標準SDKを使います</p> laiso デジタル庁でjQueryが何をしているのか hatenablog://entry/6801883189066776818 2023-12-14T18:46:02+09:00 2023-12-15T15:50:07+09:00 TL;DR: jQueryはDrupalのバーター リニューアルするたびにWeb界隈の一斉レビューを受けることでお馴染のデジタル庁ポータルサイトがいつの間にかまたリニューアルされていて、フロントエンドがNext.jsからDrupalに変わって話題になっていたので1、私も旅券所持者として国政に関心を持ってゆく また、まわりのフロントエンドエンジニアの間でjQuery氏の入庁について「モダンブラウザ全盛の時代に必要か?」と疑念がとなえられていたので、これも追求してゆきたい どのような変更があったのか システム変更の経緯はプロジェクトの関係者であるHal Sekiさんの発言が正確なところだと思う D… <p><strong><em>TL;DR: jQueryはDrupalのバーター</em></strong></p> <p>リニューアルするたびにWeb界隈の一斉レビューを受けることでお馴染の<a href="https://www.digital.go.jp/">デジタル庁ポータルサイト</a>がいつの間にかまたリニューアルされていて、フロントエンドがNext.jsからDrupalに変わって話題になっていたので<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>、私も旅券所持者として国政に関心を持ってゆく</p> <p>また、まわりのフロントエンドエンジニアの間でjQuery氏の入庁について「モダンブラウザ全盛の時代に必要か?」と疑念がとなえられていたので、これも追求してゆきたい</p> <h1 id="どのような変更があったのか">どのような変更があったのか</h1> <p>システム変更の経緯はプロジェクトの関係者であるHal Sekiさんの発言が正確なところだと思う</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Drupalが話題ですが、元々CMS側は2年前からずっとDrupalだったんです。設立当初はサイトもシンプルだったのでフロントエンド側はNextjsでヘッドレス構成だったのですが、構成が複雑になってきてヘッドレスでは持たなくなってきたという話で。 <a href="https://t.co/dmm0HodDEQ">https://t.co/dmm0HodDEQ</a></p>&mdash; Hal Seki (@halsk.bsky.social)🛡️ (@hal_sk) <a href="https://twitter.com/hal_sk/status/1734931944377606650?ref_src=twsrc%5Etfw">2023年12月13日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>私が理解した内容を勝手に作図してみたのが以下、脱<a href="https://jamstack.org/">Jamstack</a>された</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20231214/20231214175410.png" width="500" alt="JAMStack" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20231214/20231214175829.png" width="400" alt="Drupla" /></p> <p>AstroやGatbsyなどのStatic Site Generator(SSG)を主軸にしたフレームワークと違い、Next.jsはインクリメンタルなビルドやサイトへのアップロードにフォーカスした機能をそなえていないので、ページ数が多くなるとビルド時間が長くなるというのは理解できる</p> <p>SSGとSSRの併用・動的な切り換えを含め実現できるようNext.jsのサーバーを追加で立ち上げるって手もあるが「プレビュー機能や予約投稿など、元々CMSに備わっている機能も活用できない」とあるので、既に運用しているDrupal側に寄せたのだと思う</p> <h1 id="いつ変更されたのか">いつ変更されたのか</h1> <p><a href="https://chrome-ux-rumble.web.app/reports/V6FGcFU3I2rlkXsT3oVt/monthly-p75">CrUX サイトスピード簡単比較</a>(このサイトすごい)によると10月〜11月にかけて「OnLoad (リソース総読み込み時間)」が増加しているので、それを参考に<a href="https://web.archive.org/web/20230000000000*/https://www.digital.go.jp/">Wayback Machine</a>を辿っていく</p> <p>Drupal判定はページのJavaScriptに特定のオブジェクトが存在するかどうかで行われているのが独自研究で分っていたので<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup>手がかりにした</p> <p>その結果11月に新アーキテクチャになったというわけではなく、既に10月にはDrupalに移行済みだった</p> <p>さらに遡って二分探索で時期を特定したところ、最終的には9月初旬に該当の変更があったことが分かった</p> <p>ただ発表は11月にあったようだ</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ウェブサイトリニューアルのお知らせ💻📱<br><br>利用者の皆様からいただいた声をもとに、デジタル庁ウェブサイトを改善しました。<br>以下のURLより、ぜひご覧ください。<br>→<a href="https://t.co/ksY2vrzl60">https://t.co/ksY2vrzl60</a> <a href="https://t.co/IXA3V576Yz">pic.twitter.com/IXA3V576Yz</a></p>&mdash; デジタル庁 (@digital_jpn) <a href="https://twitter.com/digital_jpn/status/1719549826017247318?ref_src=twsrc%5Etfw">2023年11月1日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>それ以前の6月にデジタル庁は新トップページの試行版を<code>/experimental/</code>で公開していた(現在はアクセスできない)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">新しいデザインのウェブサイトを体験ください📱💻<br><br>本日(6月29日)、デジタル庁ウェブサイトにて、新トップページの試行版を公開しました。<br>利用者様からのフィードバックを参考にしながら、今後も設計や表現を見直していきます。<br><br>体験はこちらから↓<a href="https://t.co/qaOkeKkDVa">https://t.co/qaOkeKkDVa</a></p>&mdash; デジタル庁 (@digital_jpn) <a href="https://twitter.com/digital_jpn/status/1674311739607769088?ref_src=twsrc%5Etfw">2023年6月29日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>この更新はCSS ModulesからTailwindCSSベースに移行する意図だと思われる</p> <pre class="code lang-html" data-lang="html" data-unlink><span class="synComment">&lt;!-- 20230629060923/ --&gt;</span> <span class="synIdentifier">&lt;</span><span class="synStatement">section</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">&quot;attention&quot;</span><span class="synIdentifier">&gt;</span> <span class="synIdentifier">&lt;</span><span class="synStatement">h2</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">&quot;attention__title&quot;</span><span class="synIdentifier">&gt;</span>重要なお知らせ<span class="synIdentifier">&lt;/</span><span class="synStatement">h2</span><span class="synIdentifier">&gt;</span> <span class="synIdentifier">&lt;</span><span class="synStatement">ul</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">&quot;attention__list&quot;</span><span class="synIdentifier">&gt;</span> <span class="synIdentifier">&lt;</span><span class="synStatement">li</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">&quot;attention__item&quot;</span><span class="synIdentifier">&gt;</span> <span class="synIdentifier">&lt;/</span><span class="synStatement">li</span><span class="synIdentifier">&gt;</span> <span class="synIdentifier">&lt;/</span><span class="synStatement">ul</span><span class="synIdentifier">&gt;</span> <span class="synIdentifier">&lt;/</span><span class="synStatement">section</span><span class="synIdentifier">&gt;</span> <span class="synComment">&lt;!-- 20230629060923/experimental --&gt;</span> <span class="synIdentifier">&lt;</span><span class="synStatement">section</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">&quot;flex flex-col gap-12&quot;</span><span class="synIdentifier">&gt;</span> <span class="synIdentifier">&lt;</span><span class="synStatement">header</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">&quot;flex items-center gap-4&quot;</span><span class="synIdentifier">&gt;</span> <span class="synIdentifier">&lt;</span><span class="synStatement">h2</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">&quot;text-pc-xl&quot;</span><span class="synIdentifier">&gt;</span>重要なお知らせ<span class="synIdentifier">&lt;/</span><span class="synStatement">h2</span><span class="synIdentifier">&gt;</span> <span class="synIdentifier">&lt;/</span><span class="synStatement">header</span><span class="synIdentifier">&gt;</span> <span class="synIdentifier">&lt;/</span><span class="synStatement">section</span><span class="synIdentifier">&gt;</span> </pre> <p>この時点ではフロントエンドはNext.jsで生成された静的サイトのまま。この試行版の結果を踏まえて今回の変更に至ったのではないか</p> <h1 id="jQueryをどう使っているのか">jQueryをどう使っているのか</h1> <p>jQueryの使用目的を調べるために、まず現在の最新サイトがどのようなJavaScriptを読み込んでいるのかを確認する</p> <p>必要な個所だけを抜粋すると以下2つのJavaScriptファイルが読み込まれている</p> <pre class="code lang-html" data-lang="html" data-unlink><span class="synIdentifier">&lt;</span><span class="synStatement">script</span><span class="synIdentifier"> </span><span class="synType">src</span><span class="synIdentifier">=</span><span class="synConstant">&quot;/assets/contents/js/js_ClXDO7hKtoW-lPIxg2611itLMSFuyA_7QOQFpHSZnkc.js&quot;</span><span class="synIdentifier">&gt;&lt;/</span><span class="synStatement">script</span><span class="synIdentifier">&gt;</span> <span class="synIdentifier">&lt;</span><span class="synStatement">script</span><span class="synIdentifier"> </span><span class="synType">src</span><span class="synIdentifier">=</span><span class="synConstant">&quot;/assets/contents/js/js_sLGkDuawXY9ceUV6gA6ioeCD4o_nT-dduyMlEtshv-8.js&quot;</span><span class="synIdentifier">&gt;&lt;/</span><span class="synStatement">script</span><span class="synIdentifier">&gt;</span> </pre> <p>中身を読むと、それぞれ「開発者自身が記述したJavaScript」と「サードパーティのJavaScriptをバンドルしたファイル」という一般的なビルド結果ということが分かる</p> <p>「サードパーティのJavaScript」ではjQuery v3系とDrupal JavaScript APIのコードが存在する</p> <p>Drupal JavaScript APIが何かというと、Drupalの生成するページに対して追加の処理を実行するためのAPIである</p> <p><a href="https://www.drupal.org/docs/drupal-apis/javascript-api/javascript-api-overview">https://www.drupal.org/docs/drupal-apis/javascript-api/javascript-api-overview</a></p> <p>「開発者自身が記述したJavaScript」のファイル側でスクロールの挙動をカスタマイズしている</p> <pre class="code lang-javascript" data-lang="javascript" data-unlink><span class="synComment">/**</span> <span class="synComment"> * Scroll processing</span> <span class="synComment"> */</span> <span class="synStatement">const</span> viewScroller = () =&gt; <span class="synIdentifier">{</span> <span class="synComment">// If the URL has an anchor</span> <span class="synStatement">if</span> (<span class="synStatement">window</span>.<span class="synStatement">location</span>.hash) <span class="synIdentifier">{</span> <span class="synComment">// Processing at &quot;Back&quot; screen transition</span> <span class="synComment">// eslint-disable-next-line no-unused-vars</span> <span class="synStatement">window</span>.addEventListener(<span class="synConstant">&quot;popstate&quot;</span>, (e) =&gt; <span class="synIdentifier">{</span> scrollToForFloatHeader(<span class="synStatement">window</span>.<span class="synStatement">location</span>.hash, 10); <span class="synIdentifier">}</span>); scrollToForFloatHeader(<span class="synStatement">window</span>.<span class="synStatement">location</span>.hash, 300); <span class="synIdentifier">}</span> <span class="synIdentifier">}</span>; Drupal.behaviors.viewer = <span class="synIdentifier">{</span> <span class="synComment">// eslint-disable-next-line object-shorthand, no-unused-vars</span> attach: <span class="synIdentifier">function</span> (context) <span class="synIdentifier">{</span> viewScroller(); <span class="synIdentifier">}</span>, <span class="synIdentifier">}</span>; </pre> <p>他に得られた知識としては</p> <ul> <li>コメントが英語</li> <li>eslintが導入されている</li> <li>jQueryがスコープに宣言だけされてAPIが使われていない(!)</li> </ul> <p>ということが分った</p> <p>「jQueryのAPIを直接使っていない」という事実が今回の記事の重要な点で、このサイトのフロントエンドはVanilla JavaScriptでなるべく実装されていることが読み取れる</p> <p>DrupalのドキュメントにはJavaScript APIを利用するためにはjQueryをロードせよという記述がある</p> <blockquote><p>Note: Since Drupal uses jQuery.noConflict() and only loads JavaScript files when required, to use jQuery and the $ shortcode for jQuery you must include jQuery and Drupal as dependencies in the library definition in your MODULE.libraries.yml and add a wrapper around your function. <a href="https://www.drupal.org/docs/drupal-apis/javascript-api/javascript-api-overview">https://www.drupal.org/docs/drupal-apis/javascript-api/javascript-api-overview</a></p></blockquote> <p>なのでjQueryの読み込みはDrupal JavaScript APIを使う上では必須なのだろう</p> <p>jQueryの読み込みはしているということは前述の計測データの「OnLoad (リソース総読み込み時間)」が増加とつながる</p> <h2 id="追記-DrupalコアとjQueryの関係">追記: DrupalコアとjQueryの関係</h2> <p>この記事が多くの人に読まれたことで識者の人に追加情報をもらったので追記します</p> <p>まず現在のDrupalを使うのにjQueryを依存に追加するのは必須ではないようだった</p> <p>状況としてはこのサイトが「jQueryが必要なテーマやモジュールを使っている」という可能性がある</p> <p>ただそれがどこで使われているのか、閲覧者側に見える個所なのか管理側なのかは分からなかった</p> <p>サイト内検索に<a href="https://www.marsflag.com/ja/services/marsfinder/">MARS FINDER</a>が使われていることは通信内容から分かり、このモジュールはjQuery v2を独自に読み込んでいるが……</p> <p>一方、<a href="https://www.drupal.org/project/drupal/issues/3052002">[meta] Replace JQuery with vanilla Javascript in core [#3052002] | Drupal.org</a> のチケットではcoreからjQueryを削除しようという議論が行なわれておりそれはまだ進行中のように見えるのでサイト管理者が作成するコンテンツ以外のinternalな場所で使われているのかもしれない</p> <p>コメントくれた<a href="https://b.hatena.ne.jp/prograti/">prograti</a>さん、<a href="https://twitter.com/uhyo_">uhyo</a>さん、<a href="https://twitter.com/tom_k_en">tom_k_en</a>さんに感謝</p> <hr /> <p>以下言いたいことだけを言うコーナー</p> <h2 id="jQueryを新規で使っちゃだめなの">「jQueryを新規で使っちゃだめなの?」</h2> <ul> <li>最新のjQueryそのものを使うことについてはさしたる問題はない。</li> <li>問題はjQueryをベースに作成されたライブラリがアクティブなのかという点にある。</li> <li>サポートされなくなったバージョンや更新されなくなったライブラリを使うことが安全ではない、というのが一般的な答えかと思う</li> <li>jQueryの機能は現在のブラウザが標準装備している(それがライブラリが維持されない理由でもある)のでそれを読み込まないだけでUXに関連する数値が改善できる。「その高速化は本質的ではない」「統計によると何msで売上がN上がる」などの言い分があるものの、あとは各人のUX改善にどういう視点で向き合うかという価値観の問題になる</li> <li>また「非宣言的UIで複雑なGUIは作れない・パフォーマンスに欠点がある」という意見を持つ人もいると思う。私はその部分には持論はない</li> <li><a href="https://2023.yamanoku.net/2023-12-12">何がjQueryを負債たらしめているのかを考察する | yamanoku Advent Calendar 2023</a></li> </ul> <h2 id="やはり最新技術より枯れた技術で労働者確保">「やはり最新技術より枯れた技術で労働者確保」</h2> <ul> <li>今回の更新のコンテキストとは関係なさそう</li> <li>自分は当事者としてそのプロジェクトにいる時にしかその手のことを気にしない</li> <li>デジタル庁サイトの上流は業界内のハイクラス人材ばかりなので何使っても何とかなるのではないか(してください)</li> </ul> <h2 id="最初からNextjsやJamstack不要だったのでは">「最初からNext.jsやJamstack不要だったのでは?」</h2> <ul> <li>静的コンテンツをCDNに乗せ配信するという現在のアーキテクチャだけ見ればそうだけど、Nextの<a href="https://nextjs.org/docs/pages/building-your-application/configuring/draft-mode">Draft Mode</a>やVercelの<a href="https://vercel.com/docs/workflow-collaboration">Workflow</a>などCMS向けの機能もあるしNext側に寄せる選択肢もあったからではないか</li> <li>Vercelの人は梯子を外されてしまったけど笑</li> </ul> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">I was very proud to learn <a href="https://t.co/yJ8t6zzkw0">https://t.co/yJ8t6zzkw0</a> is built with <a href="https://twitter.com/nextjs?ref_src=twsrc%5Etfw">@nextjs</a>.<br><br>There&#39;s tremendous opportunity for Silicon Valley companies to partner with Japan in their ongoing digital transformation.<br><br>I&#39;m very excited about doubling down on our investment in Japan.</p>&mdash; Guillermo Rauch (@rauchg) <a href="https://twitter.com/rauchg/status/1629176433032720385?ref_src=twsrc%5Etfw">2023年2月24日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <div class="footnotes"> <hr/> <ol> <li id="fn:1"> 移行してたのは <a href="https://twitter.com/yuta0801_/status/1734611708508012617">https://twitter.com/yuta0801_/status/1734611708508012617</a> で知った<a href="#fnref:1" rev="footnote">&#8617;</a></li> <li id="fn:2"> Drupal判定 <a href="https://twitter.com/laiso/status/1734945420638654664">https://twitter.com/laiso/status/1734945420638654664</a><a href="#fnref:2" rev="footnote">&#8617;</a></li> </ol> </div> laiso ライティングの哲学と未来のエディタの話 hatenablog://entry/6801883189065492606 2023-12-10T02:24:46+09:00 2023-12-13T02:06:05+09:00 『ライティングの哲学 書けない悩みのための執筆論』を読んだ。 本書はWorkflowyを使いこなしている文筆家をTwitterで募ってそれぞれの活用法を紹介する座談会を4名で開催したら、文章執筆についての精神性の話題がメインになってしまい、それはそうと3年後に参加者に実際に原稿書かせてみて再度Zoomで座談会して1冊の本にしてみた。という変わった企画だった。 ライティングの哲学 書けない悩みのための執筆論 (星海社 e-SHINSHO)作者:千葉雅也,山内朋樹,読書猿,瀬下翔太講談社Amazon あとがき、が一番この本全体で起っていることを体裁立てて書いてあるので先に読むと分かりやすい。 僕は… <p>『ライティングの哲学 書けない悩みのための執筆論』を読んだ。</p> <p>本書は<a href="https://workflowy.com/">Workflowy</a>を使いこなしている文筆家をTwitterで募ってそれぞれの活用法を紹介する座談会を4名で開催したら、文章執筆についての精神性の話題がメインになってしまい、それはそうと3年後に参加者に実際に原稿書かせてみて再度Zoomで座談会して1冊の本にしてみた。という変わった企画だった。</p> <p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/B098NQWT8H?tag=rer-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/41DhKrWoZxS._SL500_.jpg" class="hatena-asin-detail-image" alt="ライティングの哲学 書けない悩みのための執筆論 (星海社 e-SHINSHO)" title="ライティングの哲学 書けない悩みのための執筆論 (星海社 e-SHINSHO)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/B098NQWT8H?tag=rer-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" target="_blank" rel="noopener">ライティングの哲学 書けない悩みのための執筆論 (星海社 e-SHINSHO)</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="https://d.hatena.ne.jp/keyword/%C0%E9%CD%D5%B2%ED%CC%E9" class="keyword">千葉雅也</a>,<a href="https://d.hatena.ne.jp/keyword/%BB%B3%C6%E2%CA%FE%BC%F9" class="keyword">山内朋樹</a>,<a href="https://d.hatena.ne.jp/keyword/%C6%C9%BD%F1%B1%EE" class="keyword">読書猿</a>,<a href="https://d.hatena.ne.jp/keyword/%C0%A5%B2%BC%E6%C6%C2%C0" class="keyword">瀬下翔太</a></li><li>講談社</li></ul><a href="https://www.amazon.co.jp/dp/B098NQWT8H?tag=rer-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p> <p>あとがき、が一番この本全体で起っていることを体裁立てて書いてあるので先に読むと分かりやすい。</p> <p>僕は各人の著書をあまり読み込んだことがないので、実際の執筆の変化は分からないのですけど、3年後座談会では概ねみんな「雑に書いて世に生み出せた時点でえらい」というような方向性でまとまっており、自分と同意見だなと関心した(理科系の作文技術とちょうど対極みたいな)</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fsizu.me%2Flaiso%2Fposts%2Fwid3fbcii84b" title="ブログは3行以上|laiso" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://sizu.me/laiso/posts/wid3fbcii84b">sizu.me</a></cite></p> <h1 id="アウトライナーの未来">アウトライナーの未来</h1> <p>ここからは一旦ライティングの哲学の部分の話題は忘れて、この本を読んだきっかけである文章執筆ツール系の話になります。</p> <p>僕はプログラミングのコーディングとこういう文筆業のライティングを似たようなものとして捉えており、それは文系プログラマーの局地のような考えだと思うのだけど、2つを統合したような性質を持つ技術ブログというものをアウトライナーを使って10年以上書いてきた経験から「もっとツール側で問題を解決できるのではないか」と思うことが多い。</p> <p>本書は座談会参加者がWorkflowyユーザーということもあって、エディタやアウトライナーなどの文章執筆ツールについても言及が多い。</p> <p>各人ともWorkflowyで小説や実用書などのすべての執筆活動を行うわけではなく、スマホからメモを取る、とかエディタAにしたりBにしたりどんどん変える、などの行動を短い期間内で試行錯誤していた<a href="#f-db38ca9a" id="fn-db38ca9a" name="fn-db38ca9a" title="この時点では本の原稿は最終的にScrivener に保存しておくのがトレンドのようだった ">*1</a></p> <p>これはこのトライアンドエラーも含めて執筆活動ということだと思うのだけど、「TODOアプリはラーメン屋」で書いたような人間の知的生産活動を現状のツールで受け持つのがそもそも難しいんじゃないかという点を思い出させる。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fsizu.me%2Flaiso%2Fposts%2Fo6fz0uwvek33" title="TODOアプリはラーメン屋|laiso" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://sizu.me/laiso/posts/o6fz0uwvek33">sizu.me</a></cite></p> <p>それでアウトライナーの話なんですけど、僕はこのエディタAにしたりBにしたりの過程に「プログラムでの自動化処理」もできると思っていて、そこに大規模言語モデルさんのパワーが使えるのではないかと考えている。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fsizu.me%2Flaiso%2Fposts%2F1x7v8hb4zx8m" title="アウトラインエディタとLLMは相性がいいはず|laiso" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://sizu.me/laiso/posts/1x7v8hb4zx8m">sizu.me</a></cite></p> <p>参加者の一人である読書猿さんにもそういう発言が多い。</p> <blockquote><p>一方で、ぼくが書く本を自分の代わりに書いてくれるプログラムをつくれないかなという思いもずっとあります。ぼくの書いている本の中身は既存のものなんです。タイトルとかコンセプトとか構成のアイデアは自分の頭から出たものですけれど、そうしてつくった枠組みに充塡するために中身を世界のどこかから取ってきている。だったらそのルールをプログラムの形で記述して、コンピュータが世界中の知識を巡って知識を拾って勝手に埋めてくれないものかなと <cite>千葉雅也,山内朋樹,読書猿,瀬下翔太. ライティングの哲学 書けない悩みのための執筆論 (Japanese Edition) (p. 213). Kindle Edition. </cite></p></blockquote> <p>OpenAI APIを裏で呼び出すWebのアウトライナーでもマシン上でモデルの推論を実行するデスクトップアプリでも、VS Code上の拡張で実現するでもどんな方法でもいいんですけど、システムに日本語入力システムがあるのと同じレベルで言語生成・編集機能が付いてる、っていうものを未来のライティング環境として想像している。</p> <p>なので、階層のリストを要約して自動で親項目を挿入したり、箇条書きリストを自然言語で分類し直したり、マクドナルド理論よろしく<a href="#f-8ff9b201" id="fn-8ff9b201" name="fn-8ff9b201" title="https://gigazine.net/news/20130502-mcdonalds-theory/ ">*2</a> 各項目を置き換え前提のテキスト補完を入れてしまう—— とか、今ある技術だけで何とかなりそうなのでプロトタイピングをしている。</p> <p>『ライティングの哲学 書けない悩みのための執筆論』発刊の2021年時点ではChatGPTブームは来てないのでアップデートするような企画があったら面白そうだ。これだけツールを使いこなしている人達なら色々試しているはずなので</p> <div class="footnote"> <p class="footnote"><a href="#fn-db38ca9a" id="f-db38ca9a" name="f-db38ca9a" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">この時点では本の原稿は最終的に<a href="https://www.literatureandlatte.com/scrivener/overview">Scrivener</a> に保存しておくのがトレンドのようだった </span></p> <p class="footnote"><a href="#fn-8ff9b201" id="f-8ff9b201" name="f-8ff9b201" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://gigazine.net/news/20130502-mcdonalds-theory/">https://gigazine.net/news/20130502-mcdonalds-theory/</a> </span></p> </div> laiso Copilot ChatのAgents機能がすごそう hatenablog://entry/6801883189063413456 2023-12-02T15:03:56+09:00 2023-12-04T17:47:14+09:00 GitHub Copilot ChatのアップデートでAgentsという機能が追加されて@workspaceをつけて質問することでエディタのコンテキスト外のファイルも対象に回答してくれるようになった。 code.visualstudio.com 「プログラマー失業不可避」が噂されるCopilot Workspace*1とは別の機能なので注意。 以下Microsoft Copilotに翻訳してもらった要点: LLMは、ある時点での公開リポジトリのデータで訓練されています。つまり、現在のコードについては何も知りません。コードについては一般的なことは知っていますが、ワークスペースの内容に関する必要な… <p>GitHub Copilot ChatのアップデートでAgentsという機能が追加されて<code>@workspace</code>をつけて質問することでエディタのコンテキスト外のファイルも対象に回答してくれるようになった。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcode.visualstudio.com%2Fblogs%2F2023%2F11%2F13%2Fvscode-copilot-smarter" title="Pursuit of wicked smartness in VS Code" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://code.visualstudio.com/blogs/2023/11/13/vscode-copilot-smarter">code.visualstudio.com</a></cite></p> <p>「プログラマー失業不可避」が噂されるCopilot Workspace<a href="#f-41c867da" id="fn-41c867da" name="fn-41c867da" title="GitHubが生成AI 見えてきたプログラマー不要時代 - 日本経済新聞">*1</a>とは別の機能なので注意。</p> <p>以下Microsoft Copilotに翻訳してもらった要点:</p> <blockquote><p>LLMは、ある時点での公開リポジトリのデータで訓練されています。つまり、現在のコードについては何も知りません。コードについては一般的なことは知っていますが、ワークスペースの内容に関する必要な文脈を持っていないので、それに関する質問に正確に答えたり、ワークスペースの形式や機能に従った新しいコードを提案したりすることができません。</p> <p>これを回避するために、GitHub Copilot Chatは、モデルがよりよく質問に答えられるようにするためのコードの断片を送ります(これを「Retrieval Augmented Generation」または「RAG」と呼びます)。1回答は、関連性の高いコードを見ることでよくなります。しかし、LLMに送ることができるコードの量(およびプロンプトによるガイダンス)には限りがあります。小さなプロジェクトであれば、これは通常問題になりません。しかし、大きなソースコードリポジトリを考えてみると、すべてのファイルの内容をモデルに送ることは不可能であることがすぐにわかります。よりよい回答を得るための解決策は、適切な量のリソースを合理的な時間内に使って、関連する文脈を送ることです。これを実現し、さらに多くのシナリオを解放するために、私たちはCopilot Chatにエージェントという概念を追加しました。</p></blockquote> <p>つまりCursorがやっていてくれたような機能がオフィシャルでサポートされている(さよならCursor)</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F10%2F28%2F171539" title="Cursorはコードベースに質問できる - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/10/28/171539">laiso.hatenablog.com</a></cite></p> <p><a href="https://github.com/VikParuchuri/marker">VikParuchuri/marker</a>を一緒に読んでみたところなかなか有能だった。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20231202/20231202143006.png" width="2000" height="1295" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>このリポジトリはPythonだが、ただCopilot Chat自体得意言語の差があるという説もある。</p> <h1 id="Agentsとは">Agentsとは</h1> <p><code>@workspace</code>の@指示子を提供するパーツがAgentsという仕組みで、なんとこれはユーザーも追加することができるらしい。</p> <p>Copilot Chatのコンテキストを拡張して任意のコードを実行でき、VS Code側で用意されたAPIを使うことができる。</p> <p>全体の構造:</p> <pre class="code" data-lang="" data-unlink>VS Code ├── GitHub Copilot Extension ├── GitHub Copilot Chat Extension │   ├── Agents │   │   ├── @workspace │   │   ├── @vscode │   │   ├── @cat │   │   ├── @dall-e</pre> <p>実際に動作可能なAgentとして<a href="https://github.com/microsoft/vscode-extension-samples/tree/main/chat-agent-sample">@cat</a>や<a href="https://github.com/roblourens/chat-agent-dalle/tree/main">@dall-e</a>のサンプルにアクセスできる。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20231202/20231202145552.jpg" width="2000" height="1249" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>実装は以下の個所でここを書き換えることで独自のAgentを開発できる。</p> <p><a href="https://github.com/microsoft/vscode-extension-samples/blob/bb473a1724d7595006760a9dfdc31e2429fa6cc7/chat-agent-sample/src/extension.ts">vscode-extension-samples/chat-agent-sample/src/extension.ts</a></p> <p>@dall-eとかはこの中でAzure OpenAIのAPI叩いて画像生成してた。</p> <p>Chat Completion APIを使ってる人ならお馴染みのI/Fで、以下のようにCopilotの内部のモデルへの問い合わせができる。</p> <pre class="code lang-typescript" data-lang="typescript" data-unlink><span class="synType">const</span> access <span class="synStatement">=</span> <span class="synStatement">await</span> vscode.chat.requestChatAccess<span class="synStatement">(</span><span class="synConstant">'copilot'</span><span class="synStatement">);</span> <span class="synType">const</span> topics <span class="synStatement">=</span> <span class="synIdentifier">[</span><span class="synConstant">'linked list'</span><span class="synStatement">,</span> <span class="synConstant">'recursion'</span><span class="synStatement">,</span> <span class="synConstant">'stack'</span><span class="synStatement">,</span> <span class="synConstant">'queue'</span><span class="synStatement">,</span> <span class="synConstant">'pointers'</span><span class="synIdentifier">]</span><span class="synStatement">;</span> <span class="synType">const</span> topic <span class="synStatement">=</span> topics<span class="synIdentifier">[</span><span class="synSpecial">Math</span>.floor<span class="synStatement">(</span><span class="synSpecial">Math</span>.random<span class="synStatement">()</span> * topics.length<span class="synStatement">)</span><span class="synIdentifier">]</span><span class="synStatement">;</span> <span class="synType">const</span> messages <span class="synStatement">=</span> <span class="synIdentifier">[</span> <span class="synIdentifier">{</span> role: vscode.ChatMessageRole.System<span class="synStatement">,</span> content: <span class="synConstant">'You are a cat! Your job is to explain computer science concepts in the funny manner of a cat. Always start your response by stating what concept you are explaining.'</span> <span class="synIdentifier">}</span><span class="synStatement">,</span> <span class="synIdentifier">{</span> role: vscode.ChatMessageRole.User<span class="synStatement">,</span> content: topic <span class="synIdentifier">}</span><span class="synStatement">,</span> <span class="synIdentifier">]</span><span class="synStatement">;</span> <span class="synType">const</span> chatRequest <span class="synStatement">=</span> access.makeRequest<span class="synStatement">(</span>messages<span class="synStatement">,</span> <span class="synIdentifier">{}</span><span class="synStatement">,</span> token<span class="synStatement">);</span> <span class="synStatement">for</span> <span class="synStatement">await</span> <span class="synStatement">(</span><span class="synType">const</span> fragment <span class="synStatement">of</span> chatRequest.response<span class="synStatement">)</span> <span class="synIdentifier">{</span> progress.report<span class="synStatement">(</span><span class="synIdentifier">{</span> content: fragment <span class="synIdentifier">}</span><span class="synStatement">);</span> <span class="synIdentifier">}</span> <span class="synStatement">return</span> <span class="synIdentifier">{</span> slashCommand: <span class="synConstant">'teach'</span> <span class="synIdentifier">}</span><span class="synStatement">;</span> </pre> <h1 id="まとめ">まとめ</h1> <p>つまりAgentsを通じてエディタの中で自然言語とソースコードの組合せから情報を取り出したり、コードを更新したり実行したりするのがより柔軟になるので色々活用の幅が広がりそう。</p> <p>Copilot Chatは最近GPT-4ベースになったので<a href="#f-5d82778d" id="fn-5d82778d" name="fn-5d82778d" title="GitHub Copilot – November 30th Update - The GitHub Blog">*2</a>「以前使ってみたけど精度がいまいちだったな〜」という人も再度チェックしてみてください。</p> <div class="footnote"> <p class="footnote"><a href="#fn-41c867da" id="f-41c867da" name="f-41c867da" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://www.nikkei.com/article/DGXZQOUC202KJ0Q3A121C2000000/">GitHubが生成AI 見えてきたプログラマー不要時代 - 日本経済新聞</a></span></p> <p class="footnote"><a href="#fn-5d82778d" id="f-5d82778d" name="f-5d82778d" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://github.blog/changelog/2023-11-30-github-copilot-november-30th-update/">GitHub Copilot – November 30th Update - The GitHub Blog</a></span></p> </div> laiso 「しずかなインターネット」の技術スタックを調べる hatenablog://entry/6801883189061152645 2023-11-23T21:07:36+09:00 2023-12-04T17:45:06+09:00 追記 作者のcatnose99さんがより詳細を解説してくださいました zenn.dev /追記 ポエム特化のZenn2との噂の「しずかなインターネット」を使いはじめたので、ユーザーとしてどんな技術が使われているのかを確認していく。 sizu.me おもむろにbuiltwith.comにかけてみる。 builtwith.com ここで分かる情報はブラウザのDevTools眺めてても得られるのであまり収穫はない。 前段にCloudflareのCDNサーバーがいて Next.jsで生成されたレスポンスを返している ことがわかる。 この時点ではキャッシュのみCloudflareなのか、Pages/Wo… <h2 id="追記">追記</h2> <p>作者のcatnose99さんがより詳細を解説してくださいました</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Fcatnose99%2Farticles%2Ff8a90a1616dfb3" title="しずかなインターネットの技術構成" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/catnose99/articles/f8a90a1616dfb3">zenn.dev</a></cite></p> <h2 id="追記-1">/追記</h2> <p>ポエム特化のZenn2との噂の「しずかなインターネット」を使いはじめたので、ユーザーとしてどんな技術が使われているのかを確認していく。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fsizu.me%2F" title="しずかなインターネット" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://sizu.me/">sizu.me</a></cite></p> <p>おもむろにbuiltwith.comにかけてみる。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fbuiltwith.com%2F%3Fhttps%253a%252f%252fsizu.me%252f" title="SIZU.ME Technology Profile on BuiltWith" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://builtwith.com/?https%3a%2f%2fsizu.me%2f">builtwith.com</a></cite></p> <p>ここで分かる情報はブラウザのDevTools眺めてても得られるのであまり収穫はない。</p> <ol> <li>前段にCloudflareのCDNサーバーがいて</li> <li>Next.jsで生成されたレスポンスを返している</li> </ol> <p>ことがわかる。</p> <p>この時点ではキャッシュのみCloudflareなのか、Pages/WorkersでNext.jsのSSRごと動かしているのかは判断できない。</p> <h1 id="認証">認証</h1> <p><code>Set-Cookie: __Secure-next-auth.session-token=</code>が含まれているので<a href="https://next-auth.js.org/">NextAuth.js</a>を使っているのが分かる。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fnext-auth.js.org%2F" title="NextAuth.js" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://next-auth.js.org/">next-auth.js.org</a></cite></p> <p>Emailでサインアップすると<code>https://sizu.me/enter/callback/firebase-action?apiKey=...</code>というリンクを送ってくるので<a href="https://firebase.google.com/docs/auth">Firebase Authentication</a>でユーザーが管理されているのも分かる。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ffirebase.google.com%2Fdocs%2Fauth" title="Firebase Authentication" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://firebase.google.com/docs/auth">firebase.google.com</a></cite></p> <h1 id="ストレージR2">ストレージ(R2)</h1> <p>画像をアップロードすると <code>r2.sizu.me</code>というホストのURLが割り当てられ、<a href="https://developers.cloudflare.com/r2/">Cloudflare R2</a>が利用されているのが分かる。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fdevelopers.cloudflare.com%2Fr2%2F" title="Cloudflare R2 · Cloudflare R2 docs" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://developers.cloudflare.com/r2/">developers.cloudflare.com</a></cite></p> <h1 id="フロントエンドサーバーCloudflare">フロントエンドサーバー(Cloudflare)</h1> <p><code>/api/..</code>以下がCloudflareを指すので完全に静的なexportサイトではないことが分かる。</p> <p>ただ<code>/dashboard</code>以下のページは<code>__NEXT_DATA__.nextExport=true</code>になっているのでSSGな部分とCSRな部分が混在している。</p> <p>共通UIが静的でログインユーザーの情報は<code>/api/..</code>から取得しているのだと思う。</p> <h1 id="コンテンツキャッシュCloudflare">コンテンツキャッシュ(Cloudflare)</h1> <p>投稿の詳細ページは本文を含む完全なHTMLを返してきて<code>__NEXT_DATA__.gssp=true</code>になるのでSSRなことが分かる。</p> <p>ブラウザのナビゲーションで同じページを開くと<code>/api/trpc/postDetail.get</code>からコンテンツは取得される。</p> <p>同じページをナビゲーションで2回開くとAPIにアクセスは発生しないのでクライアントサイドのキャッシュもあることが分かる。</p> <h1 id="バックエンドサーバーGoogle-Cloud">バックエンドサーバー(Google Cloud)</h1> <p>ここから先はアプリケーションを調べても分からないし、人海戦術で作者の<a href="https://twitter.com/catnose99">catnose</a>さんの発言内容をチェックする(そもそも聞いたら教えてくれると思う <a href="#f-99c8a6d4" id="fn-99c8a6d4" name="fn-99c8a6d4" title="補足説明をもらえた: https://twitter.com/catnose99/status/1727669652766204141 ">*1</a> )</p> <p>以下のポストはしずかなインターネット開発中のものと思われる</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">個人的に推していきたい構成はこれだな<br><br>・Next.js on Cloud Run<br>・Cloudflare<br>・PlanetScale<br>・Upstash (Redis)<br>・Cloud Tasks<br>・Cloud Scheduler<br><br>アクセスがなければ¥0、スケールしても段階的に料金が上がっていくから安心。</p>&mdash; catnose (@catnose99) <a href="https://twitter.com/catnose99/status/1641072516344209408?ref_src=twsrc%5Etfw">2023年3月29日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>これによるとCloudflare Pages/WorkersでDB接続まではしていなさそうで、コアサーバーはCloud Runの方にありそう。</p> <p>その場合、バックグラウンドジョブなどの実行もCloud Runベースになるだろう。</p> <p>DBやRedisはそのままPlanetScaleとUpstashなのかもしれないが、定かではない。</p> <h1 id="APIサーバーtRPC">APIサーバー(tRPC)</h1> <p>設定 <code>https://sizu.me/dashboard/settings</code>から更新すると<code>/api/trpc/user.update</code>に対してPOSTリクエストが送信される。</p> <p>命名からして<a href="https://trpc.io/">tRPC</a>が使われていそう。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftrpc.io%2F" title="tRPC - Move Fast and Break Nothing. End-to-end typesafe APIs made easy. | tRPC" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://trpc.io/">trpc.io</a></cite></p> <p>API Routesの下でBFFとなるエンドポイントがあって、trpcサーバーのモジュールを通して、Cloud Runにあるバックエンドのサーバーと通信している?</p> <h2 id="追記-2">追記</h2> <p>BFF→Cloud Runの二段階アーキテクチャではなしに、trpcサーバーからDBに接続する層もCloud Runで動作しているらしい。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">フルスタックNext.jsアプリをCloudRunにデプロイしてます。<br><br>CloudRunの東京リージョンにカスタムドメインを紐づけるとレイテンシが発生する問題の対応として、Cloudflare Workersを前段に置いてます<a href="https://t.co/EMw1Yg4ijj">https://t.co/EMw1Yg4ijj</a></p>&mdash; catnose (@catnose99) <a href="https://twitter.com/catnose99/status/1727669654821413364?ref_src=twsrc%5Etfw">2023年11月23日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1 id="まとめ">まとめ</h1> <p>プレゼンテーション層とデータ層を処理するフルスタックなNext.jsアプリケーションがCloud Runで動いていて、Cloud Runの制約上発生するレイテンシをなくすためにその前段にCloudflare Workersでプロキシしているというアーキテクチャだということが分かった。</p> <p>初期ZennがVercelとApp EngineのRails APIで構築されていたのを更にフルJavaScript版に進めた感じがしますね。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Fteam_zenn%2Farticles%2F5e9547a5c207e3" title="Next.jsアプリをVercelからGoogle Cloudに移行した話" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/team_zenn/articles/5e9547a5c207e3">zenn.dev</a></cite></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Fteam_zenn%2Farticles%2Fmigrate-appengine-to-cloudrun" title="Zennのバックエンドを Google App Engine から Cloud Run へ移行しました(無停止!YES!)" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/team_zenn/articles/migrate-appengine-to-cloudrun">zenn.dev</a></cite></p> <div class="footnote"> <p class="footnote"><a href="#fn-99c8a6d4" id="f-99c8a6d4" name="f-99c8a6d4" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">補足説明をもらえた: <a href="https://twitter.com/catnose99/status/1727669652766204141">https://twitter.com/catnose99/status/1727669652766204141</a> </span></p> </div> laiso 人類には早過ぎるLLMの話 hatenablog://entry/6801883189060950414 2023-11-23T02:39:15+09:00 2023-11-23T22:31:07+09:00 Sam Altman解任騒動は個人間の対立ではなく、組織構造の問題に注目すると感想が変わるなと思った。 www.nytimes.com この騒動についてはAIの安全性を重視する思想とOpenAIのビジネスの拡大を目指す戦略の衝突があるので、AIの安全性というトピックが重要になる。 僕は結構テクノロジー原理主義者みたいなところがあるので、自動車で人命が失なわれているとして人類が獲得した利益と比較できないし、SNSによって情報操作から暴動が起きたり、誹謗中傷で精神を病む人々が出現してもそれは—— まぁ困るよね・・(身内が事故やSNSで不幸にあったら絶対反転アンチになるだろうし) ぐらいの曖昧な態度… <p>Sam Altman解任騒動は個人間の対立ではなく、組織構造の問題に注目すると感想が変わるなと思った。</p> <p><iframe src="https://www.nytimes.com/svc/oembed/html/?url=https%3A%2F%2Fwww.nytimes.com%2F2023%2F11%2F21%2Ftechnology%2Fopenai-altman-board-fight.html" scrolling="no" frameborder="0" allowtransparency="true" title="Before Altman’s Ouster, OpenAI’s Board Was Divided and Feuding" style="border:none;max-width:500px;min-width:300px;min-height:550px;display:block;width:100%;"></iframe><cite class="hatena-citation"><a href="https://www.nytimes.com/2023/11/21/technology/openai-altman-board-fight.html">www.nytimes.com</a></cite></p> <p>この騒動についてはAIの安全性を重視する思想とOpenAIのビジネスの拡大を目指す戦略の衝突があるので、AIの安全性というトピックが重要になる。</p> <p>僕は結構テクノロジー原理主義者みたいなところがあるので、自動車で人命が失なわれているとして人類が獲得した利益と比較できないし、SNSによって情報操作から暴動が起きたり、誹謗中傷で精神を病む人々が出現してもそれは—— まぁ困るよね・・(身内が事故やSNSで不幸にあったら絶対反転アンチになるだろうし) ぐらいの曖昧な態度だったんだけど、これをきっかけにAIの安全性についての研究等に関心を持つようになった。</p> <p>安全性と言っても暴走ロボットが人類滅亡に向ってstep by stepで考えてください、みたいな昔のSF小説的な世界観じゃなくて先の自動車やSNSの例のように「世界便利になったんですけど—— 歴史としてみると人類の活動が一部蝕まれている!」と100年後に明かになるような変化を想像している。</p> <p>OpenAIの非営利団体のスキームは実に巧妙で、取締役会による統治が、人類にとって最も良い結果をもたらす、というロジックになっている。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fopenai.com%2Four-structure" title="Our structure" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://openai.com/our-structure">openai.com</a></cite></p> <p>なのでこれを運用するためには取締役会のメンバーに偏った思想を持つ人を置けないし、対立が発生するのは折り込み済みみたいな部分がある。</p> <p>今回OpenAIの事業拡大とAIの安全性に懸念を示す思想が衝突したと思われるんだけど、え? じゃあ"OpenAI’s structure"って本当に機能するの? というツッコミどころができてしまったと思う。</p> <p>人類の一番イケてるAI開発組織の考えたシステムが想定どうりに発動したんだけど、それがまた人類によって停止させらてしまった、みたいな。そもそも取締役会を選任するのも人間で、各人にも立場があるしな……</p> <p>取締役会のうちの1人だったHelen Tonerも参加する"Decoding Intentions: Artificial Intelligence and Costly Signals"の論文ではCostly Signalsの概念が難しくて順立して解説するのは無理なんだけど、ChatGPTについては安全性の面で批判的に書かれている。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcset.georgetown.edu%2Fpublication%2Fdecoding-intentions%2F" title="Decoding Intentions - Center for Security and Emerging Technology" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://cset.georgetown.edu/publication/decoding-intentions/">cset.georgetown.edu</a></cite></p> <p>ChatGPTに関する言及は全体の一部分で、Costly Signalsを説明するための具体例としてAIの軍事利用、政治活用、それに加えてLLMの公開と運用というセクションで出てくる。</p> <p>その内容をまとめると「ChatGPT(LLM)のようなサービスを世界中にリリースして人々に利用させるのは時期尚早でもっと慎重に行なえる可能性がある。それにはCostly Signalsの観点から——」というトーンだと思う。取締役会を離反した元メンバーの会社(Anthropic)を引き合いに出してるのでSam Altmanブチギレと言われてもまぁ分かる。</p> <p>"Why Geoffrey Hinton is sounding the alarm about AI"は解任騒動より前に公開されたインタビュー記事だけど、これも面白かった。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftorontolife.com%2Fdeep-dives%2Fgeoffrey-hinton-sounding-alarm-artificial-intelligence%2F" title="Why Geoffrey Hinton is sounding the alarm about AI" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://torontolife.com/deep-dives/geoffrey-hinton-sounding-alarm-artificial-intelligence/">torontolife.com</a></cite></p> <p>Geoffrey Hintonは世界最強のAIヤバいインフルエンサーだが彼がここに至った経緯にもChatGPTの公開が契機となっているようなので「(人類には早過ぎる)LLMに対して何か対策をほどこさなくては」という方向に慣性を得た=安全性について有利に働いた、という側面もあるんじゃないかと思った。</p> <p>「OpenAIにみる宗教的対立」は効果的利他主義 vs. 効果的加速主義というキーワードを使って、本記事の話題をより多角的・専門的に解説している。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftamuramble.theletter.jp%2Fposts%2F521c8910-8880-11ee-91ed-6b13018a1ff9" title="OpenAIにみる宗教的対立" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tamuramble.theletter.jp/posts/521c8910-8880-11ee-91ed-6b13018a1ff9">tamuramble.theletter.jp</a></cite></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.theheadline.jp%2Farticles%2F972" title="効果的加速主義とは何か?シリコンバレーで話題の新トレンド | The HEADLINE" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.theheadline.jp/articles/972">www.theheadline.jp</a></cite></p> <p>「OpenAI騒動、生成AI制御の「解」なお見えず」でも効果的利他主義を持つメンバーが外れた点を指摘している。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.nikkei.com%2Farticle%2FDGXZQOUC228ZC0S3A121C2000000%2F" title="OpenAI騒動、生成AI制御の「解」なお見えず - 日本経済新聞" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.nikkei.com/article/DGXZQOUC228ZC0S3A121C2000000/">www.nikkei.com</a></cite></p> <p>うみゆき@AI研究さんという技術のバックグラウンドがあってAI関連の話題を面白おかしく発信してくれるXアカウントがこの騒動のストーリーにして以下のポストにしていたので紹介。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">OpenAIの理念「敢えてAI研究しまくる事で人類をAIから守る」<br>①TransformerはGPU資源があればあるほど強くなるから、AI開発は死ぬほど金がないと最前線に立てない。大学や研究所はあんま金ないから、金持ってる大企業がリードする戦場。…</p>&mdash; うみゆき@AI研究 (@umiyuki_ai) <a href="https://twitter.com/umiyuki_ai/status/1727323341802066152?ref_src=twsrc%5Etfw">2023年11月22日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ユドコウスキー氏というのはEliezer YudkowskyでAIが人類の滅亡をもたらすという一番悲観的なシナリオを発信する研究者。</p> <p><iframe src="https://embed.ted.com/talks/eliezer_yudkowsky_will_superintelligent_ai_end_the_world" width="560" height="315" frameborder="0" scrolling="no" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe><cite class="hatena-citation"><a href="https://www.ted.com/talks/eliezer_yudkowsky_will_superintelligent_ai_end_the_world">www.ted.com</a></cite></p> <p>ロイターの続報にあるリークではMira Muratiが旧取締役会にAGI開発進捗メールを送ったことが引き金になった可能性を示唆している。Sam Altmanがいつも同じバッグを持ってる=「ChatGPTを停止するキルスイッチが入っている」みたいなネタがあったが(おたくだからでは????)、旧取締役会にとってのAGIヤバイスイッチだったのかなんなのか。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.reuters.com%2Ftechnology%2Fsam-altmans-ouster-openai-was-precipitated-by-letter-board-about-ai-breakthrough-2023-11-22%2F" title="Exclusive: OpenAI researchers warned board of AI breakthrough ahead of CEO ouster, sources say" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.reuters.com/technology/sam-altmans-ouster-openai-was-precipitated-by-letter-board-about-ai-breakthrough-2023-11-22/">www.reuters.com</a></cite></p> <p>旧取締役会は暫定CEOにMira Muratiを指名していたから関係はあるかもしれないが、彼女は後のSam Altman復帰を求める署名にも参加してるから、権力闘争の結果というよりは各人がバラバラに判断しててあまり詳細は証されていないなという印象を受ける。Decoding Intentions論文には透明性が安全性に関わるとされているのに…… まぁ最終的に明かされるのかもしれない。</p> <h1 id="FAQ">FAQ</h1> <h2 id="旧取締役会のQuora-CEO-Adam-DAngeloは競合他社だからOpenAIのビジネスを妨害する動機があるのでは">「旧取締役会のQuora CEO Adam D'Angeloは競合他社だからOpenAIのビジネスを妨害する動機があるのでは?」</h2> <p>Anthropicなら分かるもののQuoraのPoeはOpenAIから見るとメタなサービスであり、OpenAI技術に依存した部分もあるので直接競合ではないのでは? と思う。</p> <p>僕はAdam D'Angeloはテクノロジー畑の人だと思っていて、GPTsのような路線が拡大するとPoeにも相乗効果がありそうなのに、Sam Altman解任に賛成するのが意外だった。</p> <p>なのでOpenAIのビジネスにダメージを与えるべく賛成したというのは立場から利害関係を単純に想像しただけで、実際にこの立場に居た時にどういう判断をするのかは、彼の性質も加味しないとしっくりこない。</p> laiso Ruby on Rails: The Documentary hatenablog://entry/6801883189057767145 2023-11-10T23:43:44+09:00 2023-11-11T00:47:58+09:00 Ruby on Rails: The DocumentaryはRuby on Railsの誕生に纏わる44分のドキュメンタリー映像作品。 37signalsの関係者やShopifyのTobias LütkeなどのRailsコアチームの人々のインタビューが中心 www.youtube.com JasonとDavidの出会いからRailsの誕生、広く普及するまでを駆け足でおさらいした。React.js: The Documentaryなんやと比べるとあっさり目な内容。 僕も含め、周りでは「How to build a blog in 15 minutes with Rails」の動画でRailsを… <p>Ruby on Rails: The DocumentaryはRuby on Railsの誕生に纏わる44分のドキュメンタリー映像作品。</p> <p>37signalsの関係者やShopifyのTobias LütkeなどのRailsコアチームの人々のインタビューが中心</p> <p><iframe width="560" height="315" src="https://www.youtube.com/embed/HDKUEXBF3B4?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen title="Ruby on Rails: The Documentary"></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?v=HDKUEXBF3B4">www.youtube.com</a></cite></p> <p>JasonとDavidの出会いからRailsの誕生、広く普及するまでを駆け足でおさらいした。<a href="https://laiso.hatenablog.com/entry/react-documentary">React.js: The Documentary</a>なんやと比べるとあっさり目な内容。</p> <p>僕も含め、周りでは「How to build a blog in 15 minutes with Rails」の動画でRailsを知った人が多くて、その動画も出てきて懐しかった。</p> <p><iframe width="420" height="315" src="https://www.youtube.com/embed/Gzj723LkRJY?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen title="Ruby on Rails demo"></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?v=Gzj723LkRJY">www.youtube.com</a></cite></p> <p>中盤で触れられてる「RailsはスケールしないFUD」な話も、Rubyが遅いとかエンプラには早いとか色々評価があったと記憶しているけど、今となってはコミュニティの力によってそれが正しくなかった未来にされてしまったし、隔世の感がありますね。</p> <p>終盤にはMerbとの統合話も出てくる<a href="#f-1a0bbc02" id="fn-1a0bbc02" name="fn-1a0bbc02" title="https://en.wikipedia.org/wiki/Merb ">*1</a>。この出来事は、当時の時代感でいうとRailsはWebフレームワークの中心的な存在だったので、今でいうと「Next.jsとRemixが合体しました」みたいな衝撃だと思う。</p> <p>あと、インタビューイーであるJamis Buckが事情あってRailsを去ってしまった人たちの名前も言及していて、それが収録されていたのがなんか良いなと思った。</p> <div class="footnote"> <p class="footnote"><a href="#fn-1a0bbc02" id="f-1a0bbc02" name="f-1a0bbc02" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://en.wikipedia.org/wiki/Merb">https://en.wikipedia.org/wiki/Merb</a> </span></p> </div> laiso Cursorはコードベースに質問できる hatenablog://entry/6801883189054097491 2023-10-28T17:15:39+09:00 2023-10-31T18:27:39+09:00 VSCodeベースのCursorっていうGPT連携組込みエディタがあって、GitHub Copilot Chatと比較してみた。 cursor.sh 関心 読みテスト 脆弱性探知 OSS解析 書きテスト Cursor Copilot Chat 関心 GPTでソースコードからpatchを生成し続けたらプログラミングを自動化できるのでは???? - laiso ChatGPTのCode Interpreterのコードリーディング能力は結構優秀 - laiso で書いたようにコーディング(読み書き)を自動化したい。 Cursorをとくに薦めはしないけどLLM組込みエディタのUXの例としてわかりやすか… <p>VSCodeベースのCursorっていうGPT連携組込みエディタがあって、GitHub Copilot Chatと比較してみた。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcursor.sh%2F" title="Cursor - The AI-first Code Editor" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://cursor.sh/">cursor.sh</a></cite></p> <ul class="table-of-contents"> <li><a href="#関心">関心</a></li> <li><a href="#読みテスト">読みテスト</a><ul> <li><a href="#脆弱性探知">脆弱性探知</a></li> <li><a href="#OSS解析">OSS解析</a></li> </ul> </li> <li><a href="#書きテスト">書きテスト</a><ul> <li><a href="#Cursor">Cursor</a></li> <li><a href="#Copilot-Chat">Copilot Chat</a></li> </ul> </li> </ul> <h1 id="関心">関心</h1> <ul> <li><a href="https://laiso.hatenablog.com/entry/2023/04/09/gpgpt">GPTでソースコードからpatchを生成し続けたらプログラミングを自動化できるのでは???? - laiso</a></li> <li><a href="https://laiso.hatenablog.com/entry/2023/07/16/123214">ChatGPTのCode Interpreterのコードリーディング能力は結構優秀 - laiso</a></li> </ul> <p>で書いたようにコーディング(読み書き)を自動化したい。</p> <p>Cursorをとくに薦めはしないけどLLM組込みエディタのUXの例としてわかりやすかったので紹介します。</p> <h1 id="読みテスト">読みテスト</h1> <h2 id="脆弱性探知">脆弱性探知</h2> <p>例によって<a href="https://github.com/ockeghem/badtodo">脆弱性診実習用アプリ(通称「やられサイト」)</a>のSQLインジェクションを発見してもらうという会話をした。</p> <p>ディレクトリを開いて「PHPファイルにSQLインジェクションある?」の文章入れただけ。該当個所をただしく発見してくれている(言語はエディタの設定で日本語指定にもできる)</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20231028/20231028170110.png" width="1882" height="1022" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p><code>USED Codebase</code>になっている時はコードベース=ディレクトリのインデックスしたファイル群を参照している。</p> <p><code>@codebase</code>で対象を明示できる。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/laiso/20231028215630" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20231028/20231028215630.png" width="546" height="394" loading="lazy" title="" class="hatena-fotolife hatena-fotolife-height-only" style="height:200px" itemprop="image"></a></span></p> <p>インデックス状態の表示</p> <p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/laiso/20231028170317" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20231028/20231028170317.png" width="780" height="746" loading="lazy" title="" class="hatena-fotolife hatena-fotolife-height-only" style="height:200px" itemprop="image"></a></span></p> <p>GitHub Copilot Chatだと選択した範囲と今までの会話がコンテキストに含まれていると思うんですけど、Cursorはコードベース全体を対象にしていることが分かる(インデックスがどこに保存されるか不明なので機密情報なコードは開かない方が無難)</p> <p>※Copilot ChatでもVSCodeのバッファを対象に含めている説もあるけど自分が検証した限りでは、そういう挙動はしていなかった</p> <p>VSCodeにOpen AI APIの連携を追加するような拡張も各種公開されているけど、リポジトリ全体をインデックスするやつははじめて見た。</p> <h2 id="OSS解析">OSS解析</h2> <p><a href="https://github.com/wasmerio/wasmer">Wasmer</a>のコードをいっしょに読んでみる。</p> <p>「<code>wasmer run</code>の実行を追うにはどのファイルを見るべき?」</p> <pre class="code" data-lang="" data-unlink>以下のファイルやディレクトリが特に重要です: 1. lib/cli/src/run.rs: このファイルはwasmer runコマンドのエントリーポイントです。ここでコマンドライン引数が解析され、適切な関数が呼び出されます。 2. lib/runtime-core/src/: このディレクトリには、Wasmerのランタイムのコア部分が含まれています。ここには、WebAssemblyモジュールの解析や実行、メモリ管理などが行われます。 3. lib/compiler/: このディレクトリには、Wasmerのコンパイラが含まれています。ここでは、WebAssemblyコードをネイティブコードに変換する処理が行われます。 4. lib/wasmer-types/: このディレクトリには、Wasmerで使用される主要な型定義が含まれています。</pre> <p>「WcgiRunner, WasiRunner, EmscriptenRunnerの違いは?」</p> <pre class="code" data-lang="" data-unlink>1. WcgiRunner: このランナーは、Web CGI標準に準拠するWebAssemblyモジュールを実行するように設計されています。Web CGI(Common Gateway Interface)は、Webサーバーがプログラムやスクリプトを実行し、その出力をHTTPレスポンスとして返すことを可能にする標準です。Wasmerのコンテキストでは、WcgiRunnerを使用すると、WebAssemblyモジュールをCGIスクリプトのように実行できます。 2. WasiRunner: このランナーは、WASI (WebAssembly System Interface) APIを使用するWebAssemblyモジュールを実行するように設計されています。WASIは、WebAssemblyモジュールがシステムと対話するための標準化されたインターフェイスです(ファイルの読み取りやコンソールへの印刷など)。WasiRunnerは、これらのモジュールが正しく実行されるために必要な環境を提供します。 3. EmscriptenRunner: このランナーは、EmscriptenでコンパイルされたWebAssemblyモジュールを実行するように設計されています。Emscripten は、C および C++ コードを WebAssembly にコンパイルするツールチェインで、システムとの対話のための独自の API セットを提供します。EmscriptenRunner は、これらのモジュールが正しく実行されるために必要な環境を提供します。</pre> <p>一般的な用語の説明です。</p> <p>「 WcgiRunner::can_run_commandは何を見て判断するの?」</p> <pre class="code" data-lang="" data-unlink>WcgiRunner::can_run_commandは、指定されたコマンドが実行可能かどうかを判断するメソッドです。具体的な実装については、コードベースに提供された情報からは明らかではありません。</pre> <p><a href="https://github.com/wasmerio/wasmer/blob/7cb550db60656352cc527eaf869981d39448e38d/lib/wasix/src/runners/wcgi/runner.rs#L90">このへん</a>を教えてほしかったです</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20231028/20231028222351.png" width="1606" height="498" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>あまり深い解析まではやってくれないみたいだ。</p> <h1 id="書きテスト">書きテスト</h1> <p>発見した個所に「脆弱性修正したい」と入れてみる。結果は同じ。</p> <h2 id="Cursor">Cursor</h2> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20231028/20231028171000.png" width="1242" height="426" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <h2 id="Copilot-Chat">Copilot Chat</h2> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20231028/20231028171358.png" width="1422" height="1000" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/laiso/20231031182651" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20231031/20231031182651.png" width="512" height="512" loading="lazy" title="" class="hatena-fotolife hatena-fotolife-height-only" style="height:1px" itemprop="image"></a></span></p> laiso PayPalアカウントがなくてもオライリー本は買える(確信) hatenablog://entry/6801883189054070214 2023-10-28T15:14:26+09:00 2023-10-28T15:14:26+09:00 PayPalアカウントがないとオライリー本買えなくて不便 - laiso オライリー本が買えない話その後 - laiso この後、定期的に何かの拍子でアカウント復活しないかな〜と思いPayPalチャレンジをしていたんだけど今月実行してみたらO'Reilly Japan Ebook Storeでクレジットカードが使えるようになっていた。 ヘルプも更新されていたので正式に対応したのだと思われる。 決済について Ebook Storeでのお買い物は、クレジットカード、PayPalでのお支払いが可能です。 https://www.oreilly.co.jp/ebook/help.html ありがとうス… <ol> <li><a href="https://laiso.hatenablog.com/entry/for-tim">PayPal&#x30A2;&#x30AB;&#x30A6;&#x30F3;&#x30C8;&#x304C;&#x306A;&#x3044;&#x3068;&#x30AA;&#x30E9;&#x30A4;&#x30EA;&#x30FC;&#x672C;&#x8CB7;&#x3048;&#x306A;&#x304F;&#x3066;&#x4E0D;&#x4FBF; - laiso</a></li> <li><a href="https://laiso.hatenablog.com/entry/2023/07/28/171613">&#x30AA;&#x30E9;&#x30A4;&#x30EA;&#x30FC;&#x672C;&#x304C;&#x8CB7;&#x3048;&#x306A;&#x3044;&#x8A71;&#x305D;&#x306E;&#x5F8C; - laiso</a></li> </ol> <p>この後、定期的に何かの拍子でアカウント復活しないかな〜と思いPayPalチャレンジをしていたんだけど今月実行してみたら<a href="https://www.oreilly.co.jp/ebook/">O'Reilly Japan Ebook Store</a>でクレジットカードが使えるようになっていた。</p> <p>ヘルプも更新されていたので正式に対応したのだと思われる。</p> <blockquote><p>決済について Ebook Storeでのお買い物は、クレジットカード、PayPalでのお支払いが可能です。 <a href="https://www.oreilly.co.jp/ebook/help.html">https://www.oreilly.co.jp/ebook/help.html</a></p></blockquote> <p>ありがとうステークホルダーの方々。</p> laiso いまさら振り返るRxSwift hatenablog://entry/6801883189053907994 2023-10-27T21:27:48+09:00 2023-10-31T18:28:50+09:00 私とRxSwift 2013-2014年 2016-2017年 2018-2019年 何がIssueだったのか 非同期処理 Future/Promise パターンのかわり Observableパターン 宣言的UI 状態管理 どう解決されたか Swift Concurrency で非同期処理 UIKitからSwiftUIへ Combine やObservation おわりに 私とRxSwift 2013-2014年 C#な世界でLINQとかReactive Extensionsが高評価なことを知る。 iOSアプリ開発でもこれを生かせないかということを考えはじめる。ReactiveCocoaのこと… <ul class="table-of-contents"> <li><a href="#私とRxSwift">私とRxSwift</a><ul> <li><a href="#2013-2014年">2013-2014年</a></li> <li><a href="#2016-2017年">2016-2017年</a></li> <li><a href="#2018-2019年">2018-2019年</a></li> </ul> </li> <li><a href="#何がIssueだったのか">何がIssueだったのか</a><ul> <li><a href="#非同期処理">非同期処理</a><ul> <li><a href="#FuturePromise-パターンのかわり">Future/Promise パターンのかわり</a></li> <li><a href="#Observableパターン">Observableパターン</a></li> </ul> </li> <li><a href="#宣言的UI">宣言的UI</a></li> <li><a href="#状態管理">状態管理</a></li> </ul> </li> <li><a href="#どう解決されたか">どう解決されたか</a><ul> <li><a href="#Swift-Concurrency-で非同期処理">Swift Concurrency で非同期処理</a></li> <li><a href="#UIKitからSwiftUIへ">UIKitからSwiftUIへ</a></li> <li><a href="#Combine-やObservation">Combine やObservation</a></li> </ul> </li> <li><a href="#おわりに">おわりに</a></li> </ul> <h1 id="私とRxSwift">私と<a href="https://github.com/ReactiveX/RxSwift">RxSwift</a></h1> <h2 id="2013-2014年">2013-2014年</h2> <p>C#な世界でLINQとかReactive Extensionsが高評価なことを知る。</p> <p>iOSアプリ開発でもこれを生かせないかということを考えはじめる。<a href="https://github.com/ReactiveCocoa">ReactiveCocoa</a>のことも知る。</p> <p><a href="https://speakerdeck.com/laiso/mvvm-for-ios">MVVM for iOS - Speaker Deck</a></p> <p>サーバーサイド方面でもReactive Programming の話題が活発なことを知る。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fnetflixtechblog.com%2Freactive-programming-in-the-netflix-api-with-rxjava-7811c3a1496a" title="Reactive Programming in the Netflix API with RxJava" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://netflixtechblog.com/reactive-programming-in-the-netflix-api-with-rxjava-7811c3a1496a">netflixtechblog.com</a></cite></p> <p>直接関係ないど何故かこの時期React(JS)も話題になってたりReactiveなんとかバズが到来していた。</p> <p><a href="https://www.reactivemanifesto.org/">https://www.reactivemanifesto.org/</a></p> <p>Androidアプリ開発でもRxJavaが使われているらしいと聞く。当時入手できたAndroid端末は非力なものが多くてそんな巨大なライブラリ入れてるんだと驚いた記憶がある。</p> <p>以下は時代背景が知れるRebuildの回</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Frebuild.fm%2F70%2F" title="Rebuild: 70: Bureaucratic Refactoring (Hajime Morrita)" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://rebuild.fm/70/">rebuild.fm</a></cite></p> <h2 id="2016-2017年">2016-2017年</h2> <p>アッテチーム の新規開発でRxSwiftを活用してるという講演を聞いてよさそうやんけと思う。</p> <p><iframe src="https://www.docswell.com/slide/KPPV6K/embed" allowfullscreen="true" class="docswell-iframe" width="620" height="405" style="border: 1px solid #ccc; display: block; margin: 0px auto; padding: 0px; aspect-ratio: 620/405;"></iframe><cite class="hatena-citation"><a href="https://www.docswell.com/s/bricklife/KPPV6K-atte-fes-swift-and-rxswift">www.docswell.com</a></cite></p> <p>自分たちでもRxSwiftを使いはじめ試行錯誤する。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fqiita.com%2Flaiso%2Fitems%2F9e113e4aecb546300360" title="Swiftでいい感じのViewModelを作るためのメモ - Qiita" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://qiita.com/laiso/items/9e113e4aecb546300360">qiita.com</a></cite></p> <h2 id="2018-2019年">2018-2019年</h2> <p>周りがエンジニア0〜1人のスタートアップばかりになったので、新規プロジェクトではRxSwift使わなくていいんじゃない? と言いはじめる。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2Fe-kanji-ios" title="いい感じにiOSアプリ開発プロジェクトを立ち上げる方法を考える - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/e-kanji-ios">laiso.hatenablog.com</a></cite></p> <p><a href="https://github.com/google/promises">google/promises</a> あたりからでよいのではという説を唱えていたが、モバイルアプリ自体を開発しなくなった。</p> <h1 id="何がIssueだったのか">何がIssueだったのか</h1> <h2 id="非同期処理">非同期処理</h2> <h3 id="FuturePromise-パターンのかわり">Future/Promise パターンのかわり</h3> <p>Web APIと連携するモバイルアプリはネットワークI/Oを多用するのでそこの記述にコールバック関数を使いがちだった。</p> <p>GUIのイベント処理もマルチスレッドで非同期に行うことが多いので組み合わせるとグッチャグチャになりがちだったところにフィットしたと思う。</p> <p>ストリームオブジェクトにすることでキャンセル処理も気軽に書けた。</p> <h3 id="Observableパターン">Observableパターン</h3> <p>親子関係のあるような画面構成でこっちの画面で行った処理を伝達させて別の画面でUIを更新するっていうパターンをやりたかった。</p> <p>GUIはステートルフルなので、どこから元となるデータを取得するかという処理が一箇所にまとめられたのが良かった。</p> <h2 id="宣言的UI">宣言的UI</h2> <p>イベントごとに変化する画面を手続きコードで記述しているうちに管理がたいへんになってきた。</p> <p>UIデータバインディングにすることでデータAがあったらこのUI、ストリームBが来たらこの動きをする。というコードを積み重ねて拡張できた。</p> <p>あとUIのイベントをオブジェクトにできるので、頑張ったらテストも書けた(書くのはたいへんだった)</p> <h2 id="状態管理">状態管理</h2> <p>UIデータバインディングにすることで状態管理をどう実現するのかっていう次のIssueに進めた。</p> <p>ReactのFluxアーキテクチャがターニングポイントで、双方向データフローではなく単一方向にしましょうね、というところに落ち着いた。</p> <p>業界ではサーバーレスポンス+ローカルキャッシュ+Redux化などの研究がどんどん進められていたが、そこはあまり関心を向けていなかった。</p> <h1 id="どう解決されたか">どう解決されたか</h1> <p>以下のようなトピックだけ知っているけど満足に活用した経験はないので、詳しい人に解説してほしい。</p> <h2 id="Swift-Concurrency-で非同期処理">Swift Concurrency で非同期処理</h2> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fdeveloper.apple.com%2Fdocumentation%2Fswift%2Fupdating_an_app_to_use_swift_concurrency" title="Updating an App to Use Swift Concurrency | Apple Developer Documentation" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://developer.apple.com/documentation/swift/updating_an_app_to_use_swift_concurrency">developer.apple.com</a></cite></p> <h2 id="UIKitからSwiftUIへ">UIKitからSwiftUIへ</h2> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fdeveloper.apple.com%2Fxcode%2Fswiftui%2F" title="SwiftUI Overview - Xcode - Apple Developer" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://developer.apple.com/xcode/swiftui/">developer.apple.com</a></cite></p> <h2 id="Combine-やObservation">Combine やObservation</h2> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fdeveloper.apple.com%2Fdocumentation%2Fcombine" title="Combine | Apple Developer Documentation" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://developer.apple.com/documentation/combine">developer.apple.com</a></cite></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fdeveloper.apple.com%2Fdocumentation%2Fobservation" title="Observation | Apple Developer Documentation" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://developer.apple.com/documentation/observation">developer.apple.com</a></cite></p> <h1 id="おわりに">おわりに</h1> <p>振り返ったことで</p> <ol> <li>Rxの話と見せかけて関心事はGUI開発のアーキテクチャ全体に及ぶ</li> <li>またモバイル開発はWebプラットフォームの影響を強く受けている</li> </ol> <p>というのが分かった。</p> <p>このように前提条件が素早く変化するプラットフォームでは、チーム開発での長期的なコミュニケーションにおいてはArchitectural Decision Recordsを残すのが定石と思う。</p> <p><a href="https://adr.github.io/">https://adr.github.io/</a></p> <p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/laiso/20231031182815" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20231031/20231031182815.png" width="600" height="600" loading="lazy" title="" class="hatena-fotolife hatena-fotolife-height-only" style="height:1px" itemprop="image"></a></span></p> laiso 丁寧なDeno+JSX hatenablog://entry/6801883189052822810 2023-10-23T17:29:34+09:00 2023-10-28T15:05:50+09:00 *1 サーバーレスFunctionsぐらいの気軽さでサーバーアリのWebアプリをデプロイしたいという時がある。主に自分たちだけが使うようなツール系のやつ。 その時に今までのようにSPA+APIアーキテクチャではなく、モノリシックなサーバーサイドアーキテクチャにしつつもフロントエンド開発と同じツールチェインを使いたい、と前から思っていた。 これは単にReactメタフレームワークでも一気通貫に時短で作れそうだけど、個人の楽しみのための活動なので、一旦世間のトレンドからは離れて自分が本当に必要だと思った要素技術のみを最小限に使って理解しながら試行錯誤したい。 ※ただ第三者に提供するシステムとかは安全… <p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/laiso/20231028150339" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20231028/20231028150339.png" width="512" height="512" loading="lazy" title="" class="hatena-fotolife hatena-fotolife-height-only" style="height:200px" itemprop="image"></a></span> <a href="#f-9a914085" name="fn-9a914085" title="https://ja.wikipedia.org/wiki/Deno">*1</a></p> <p>サーバーレスFunctionsぐらいの気軽さでサーバーアリのWebアプリをデプロイしたいという時がある。主に自分たちだけが使うようなツール系のやつ。</p> <p>その時に今までのようにSPA+APIアーキテクチャではなく、モノリシックなサーバーサイドアーキテクチャにしつつもフロントエンド開発と同じツールチェインを使いたい、と前から思っていた。</p> <p>これは単にReactメタフレームワークでも一気通貫に時短で作れそうだけど、個人の楽しみのための活動なので、一旦世間のトレンドからは離れて自分が本当に必要だと思った要素技術のみを最小限に使って理解しながら試行錯誤したい。</p> <p>※ただ第三者に提供するシステムとかは安全に作られた既存フレームワークに乗るのがいいというのもある</p> <p>しばらく考えてみたところ、私にとっては「TypeScriptでJSXをテンプレートエンジンに使ってHTMLを書けるだけでよい」という所に落ち着いた</p> <p>(一汁一菜でええんですわ的な<a href="#f-03a39272" name="fn-03a39272" title="「一汁一菜でよいという提案」https://kokocara.pal-system.co.jp/2016/12/19/ichiju-issai-yoshiharu-doi/ ">*2</a> )</p> <p>この用途に最適なのが<a href="https://deno.com/">Deno</a>や<a href="https://bun.sh/">Bun</a>だと思っていて、今回はDenoを使ってみる。</p> <p>Denoは.jsxおよび.tsxファイルを標準でサポートしており、特別なビルド構成などを用意しなくてよい。</p> <p>本質的にシンプルであるというよりはDenoのコアに複雑さが隠されていて全部やってくれている</p> <blockquote><p>高レベルでは、Deno は TypeScript (TSX や JSX も同様に) JavaScript に変換します。これは Deno に組み込まれている TypeScript コンパイラ と、swc と呼ばれる Rust ライブラリの組み合わせによって行われます。型チェックされ変換されると、コードはキャッシュに保存され、ソースから再び JavaScript に変換することなく次の実行に備えることができます。 <a href="https://deno-ja.vercel.app/manual@main/typescript/overview">https://deno-ja.vercel.app/manual@main/typescript/overview</a></p></blockquote> <h1 id="ランタイムにPreactを使う">ランタイムにPreactを使う</h1> <p>JSXを解釈して最終的にHTMLを吐き出したいのでその設定をする。必要なのはReactのフル機能ではなくJSXのテキスト処理だけなので<a href="https://preactjs.com/">Preact</a>の方をランタイムとして使うことにした。</p> <p>deno.jsonのcompilerOptionsにESMで指定する。</p> <pre class="code lang-json" data-lang="json" data-unlink><span class="synSpecial">{</span> &quot;<span class="synStatement">compilerOptions</span>&quot;: <span class="synSpecial">{</span> &quot;<span class="synStatement">jsx</span>&quot;: &quot;<span class="synConstant">react-jsx</span>&quot;, &quot;<span class="synStatement">jsxImportSource</span>&quot;: &quot;<span class="synConstant">https://esm.sh/preact</span>&quot; <span class="synSpecial">}</span> <span class="synSpecial">}</span> </pre> <p>ウェブサーバーからHTMLを出力するコード</p> <pre class="code lang-typescript" data-lang="typescript" data-unlink><span class="synStatement">import</span> renderToString <span class="synStatement">from</span> <span class="synConstant">&quot;https://cdn.skypack.dev/preact-render-to-string@6.2.2?dts&quot;</span><span class="synStatement">;</span> Deno.serve<span class="synStatement">(</span> <span class="synStatement">(</span>_req<span class="synStatement">)</span> <span class="synStatement">=&gt;</span> <span class="synIdentifier">{</span> <span class="synStatement">return</span> <span class="synStatement">new</span> Response<span class="synStatement">(</span>renderToString<span class="synStatement">(&lt;</span>h1<span class="synStatement">&gt;</span>Hello<span class="synStatement">,</span> World<span class="synConstant">!</span><span class="synStatement">&lt;</span>/h1<span class="synStatement">&gt;),</span> <span class="synIdentifier">{</span>headers: <span class="synIdentifier">{</span><span class="synConstant">&quot;content-type&quot;</span>: <span class="synConstant">&quot;text/html&quot;</span><span class="synIdentifier">}}</span><span class="synStatement">);</span> <span class="synIdentifier">}</span> <span class="synStatement">);</span> </pre> <p><code>import * from "https://...</code> でバージョン番号ハードコードしてるのが落ち着かないみたいな問題は<a href="https://docs.deno.com/runtime/manual/basics/import_maps">Import Maps</a>を使う。また@以下を省略してlatestを使える。</p> <pre class="code lang-json" data-lang="json" data-unlink>&quot;<span class="synStatement">imports</span>&quot;: <span class="synSpecial">{</span> &quot;<span class="synStatement">preact-render-to-string</span>&quot;: &quot;<span class="synError">https</span>:<span class="synError">//cdn.skypack.dev/preact-render-to-string@6.2.2?dts&quot;;</span> <span class="synSpecial">}</span> </pre> <h1 id="サーバーサイド実装もする">サーバーサイド実装もする</h1> <p>現時点ではJavaScriptがサーバーサイドのみで動くものとして扱うことができる。</p> <pre class="code lang-typescript" data-lang="typescript" data-unlink><span class="synStatement">import</span> <span class="synIdentifier">{</span>Database<span class="synIdentifier">}</span> <span class="synStatement">from</span> <span class="synConstant">&quot;https://deno.land/x/sqlite3@0.9.1/mod.ts&quot;</span><span class="synStatement">;</span> <span class="synStatement">import</span> renderToString <span class="synStatement">from</span> <span class="synConstant">&quot;https://cdn.skypack.dev/preact-render-to-string@6.2.2?dts&quot;</span><span class="synStatement">;</span> <span class="synStatement">type</span> User <span class="synStatement">=</span> <span class="synIdentifier">{</span> id: <span class="synType">number</span><span class="synStatement">;</span> name: <span class="synType">string</span><span class="synStatement">;</span> email: <span class="synType">string</span><span class="synStatement">;</span> <span class="synIdentifier">}</span> <span class="synStatement">interface</span> TopPageProps <span class="synIdentifier">{</span> users: User<span class="synIdentifier">[]</span><span class="synStatement">;</span> <span class="synIdentifier">}</span> <span class="synStatement">export</span> <span class="synType">const</span> TopPage <span class="synStatement">=</span> <span class="synStatement">(</span><span class="synIdentifier">{</span>users<span class="synIdentifier">}</span>: TopPageProps<span class="synStatement">)</span> <span class="synStatement">=&gt;</span> <span class="synStatement">(&lt;</span>html<span class="synStatement">&gt;</span> <span class="synStatement">&lt;</span>body<span class="synStatement">&gt;</span> <span class="synStatement">&lt;</span>h1<span class="synStatement">&gt;</span>Users<span class="synStatement">&lt;</span>/h1<span class="synStatement">&gt;</span> <span class="synStatement">&lt;</span>ul<span class="synStatement">&gt;</span> <span class="synIdentifier">{</span>users.map<span class="synStatement">((</span>user<span class="synStatement">)</span> <span class="synStatement">=&gt;</span> <span class="synStatement">&lt;</span>li<span class="synStatement">&gt;</span><span class="synIdentifier">{</span>user.name<span class="synIdentifier">}</span><span class="synStatement">&lt;</span>/li<span class="synStatement">&gt;)</span><span class="synIdentifier">}</span> <span class="synStatement">&lt;</span>/ul<span class="synStatement">&gt;</span> <span class="synStatement">&lt;</span>/body<span class="synStatement">&gt;</span> <span class="synStatement">&lt;</span>/html<span class="synStatement">&gt;</span> <span class="synStatement">);</span> Deno.serve<span class="synStatement">(</span> <span class="synStatement">(</span>_req<span class="synStatement">)</span> <span class="synStatement">=&gt;</span> <span class="synIdentifier">{</span> <span class="synType">const</span> db <span class="synStatement">=</span> <span class="synStatement">new</span> Database<span class="synStatement">(</span><span class="synConstant">&quot;db.sqlite3&quot;</span><span class="synStatement">);</span> <span class="synType">const</span> users <span class="synStatement">=</span> db.prepare<span class="synStatement">(</span><span class="synConstant">&quot;SELECT * FROM Users&quot;</span><span class="synStatement">)</span>.<span class="synStatement">all&lt;</span>User<span class="synStatement">&gt;();</span> <span class="synStatement">return</span> <span class="synStatement">new</span> Response<span class="synStatement">(</span>renderToString<span class="synStatement">(&lt;</span>TopPage users<span class="synStatement">=</span><span class="synIdentifier">{</span>users<span class="synIdentifier">}</span> /<span class="synStatement">&gt;),</span> <span class="synIdentifier">{</span>headers: <span class="synIdentifier">{</span><span class="synConstant">&quot;content-type&quot;</span>: <span class="synConstant">&quot;text/html&quot;</span><span class="synIdentifier">}}</span><span class="synStatement">);</span> <span class="synIdentifier">}</span> <span class="synStatement">);</span> </pre> <p>最近はサーバーレスな環境でも<a href="https://litestream.io/">Litestream</a>でSQLiteを使えばよいという考えなので<a href="https://cloud.google.com/run?hl=ja">Cloud Run</a>や<a href="https://fly.io/">Fly.io</a>で動きそうなコンテナイメージを作ればいいと思っている。</p> <p>こんな感じの定義からスタート</p> <pre class="code Dockerfile" data-lang="Dockerfile" data-unlink>FROM denoland/deno EXPOSE 8000 WORKDIR /app ADD . /app RUN deno cache main.ts CMD [&#34;deno&#34;, &#34;run&#34;, &#34;--watch&#34;, &#34;--allow-net&#34;, &#34;--allow-env&#34;, &#34;--allow-read&#34;, &#34;--allow-ffi&#34;, &#34;--unstable&#34;, &#34;main.ts&#34;]</pre> <p><a href="https://github.com/denodrivers/sqlite3">denodrivers/sqlite3</a>を使うためにunstable FFI APIが必要になっている。</p> <h1 id="Tips1-Tailwind-CSSのクラスを記述して必要なstyleだけ埋め込みたい">Tips(1): Tailwind CSSのクラスを記述して必要なstyleだけ埋め込みたい</h1> <p>TwindというCSS-in-JSがあってそれを使ってタグを書き換える。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fdocs.deno.com%2Fruntime%2Fmanual%2Fadvanced%2Fjsx_dom%2Ftwind" title="Using Twind with Deno | Deno Docs" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://docs.deno.com/runtime/manual/advanced/jsx_dom/twind">docs.deno.com</a></cite></p> <p>従来のビルドで生成するのと比較すると実行時のオーバヘッドがある。</p> <h1 id="デプロイ">デプロイ</h1> <p>デプロイ先は<a href="https://deno.com/deploy">Deno Deploy</a>と言いたいところだけど前述のとうりLitestreamを動かしたいのでCloud Runが無難。</p> <p>Litestreamの運用もめんどくさいならFly.ioで1インスタンス固定にしてボリュームを付けておくだけでもいいのではないか。トランザクションは使えなさそうだけど。</p> <p>最初からSQLiteではなく<a href="https://docs.deno.com/kv/manual">Deno KV</a>をDBに活用するならDeno Deployでいいと思う。</p> <h1 id="この後は">この後は——</h1> <p>URLのルーティングやクライアントサイドのロジックが必要になってきた段階で無理せず<a href="https://github.com/honojs/hono">Hono</a>や<a href="https://fresh.deno.dev/">Fresh</a>に移動した方がいい。</p> <p>Honoはプラットフォームごと移動できる余地もあるし(<a href="https://workers.cloudflare.com/">Cloudflare Workers</a>等)、Freshはパスベースのルーティングもあるしクライアントサイドのハイドレーションも対応してる。</p> <p>なら最初から<a href="https://nextjs.org/">Next.js</a>や<a href="https://remix.run/">Remix</a>でいいじゃん? という疑問については試して失敗してみないことには分かりませんな</p> <div class="footnote"> <p class="footnote"><a href="#fn-9a914085" name="f-9a914085" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://ja.wikipedia.org/wiki/Deno">https://ja.wikipedia.org/wiki/Deno</a></span></p> <p class="footnote"><a href="#fn-03a39272" name="f-03a39272" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text">「一汁一菜でよいという提案」<a href="https://kokocara.pal-system.co.jp/2016/12/19/ichiju-issai-yoshiharu-doi/">https://kokocara.pal-system.co.jp/2016/12/19/ichiju-issai-yoshiharu-doi/</a> </span></p> </div> laiso 2年ごとにiPhoneとAndroid端末を乗り換えている話 hatenablog://entry/820878482971920669 2023-09-30T18:54:50+09:00 2023-09-30T18:59:06+09:00 iPhone 15を入手してまたAndroidからiOSに移行しているんですけど、なんでそもそもこんなことやってるんだっけと思えてきたので振り返ってみた。 Distracted Boyfriend Meme Generator - Imgflip なんでやってるか Androidアプリ開発のため プラットフォームの違いを知るため 趣味(Just for Fun) 良かったところ 環境の見直し Androidアプリ開発 Android環境 不便なところ iOS版しかないアプリ Apple系のサービスが使えない Galaxy Watch使えてない 自作したツールが移行できなくなる Android端… <p>iPhone 15を入手してまたAndroidからiOSに移行しているんですけど、なんでそもそもこんなことやってるんだっけと思えてきたので振り返ってみた。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20230930/20230930185324.png" width="750" height="500" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span> <a href="https://imgflip.com/memegenerator/Distracted-Boyfriend">Distracted Boyfriend Meme Generator - Imgflip</a></p> <ul class="table-of-contents"> <li><a href="#なんでやってるか">なんでやってるか</a><ul> <li><a href="#Androidアプリ開発のため">Androidアプリ開発のため</a></li> <li><a href="#プラットフォームの違いを知るため">プラットフォームの違いを知るため</a></li> <li><a href="#趣味Just-for-Fun">趣味(Just for Fun)</a></li> </ul> </li> <li><a href="#良かったところ">良かったところ</a><ul> <li><a href="#環境の見直し">環境の見直し</a></li> <li><a href="#Androidアプリ開発">Androidアプリ開発</a></li> <li><a href="#Android環境">Android環境</a></li> </ul> </li> <li><a href="#不便なところ">不便なところ</a><ul> <li><a href="#iOS版しかないアプリ">iOS版しかないアプリ</a></li> <li><a href="#Apple系のサービスが使えない">Apple系のサービスが使えない</a></li> <li><a href="#Galaxy-Watch使えてない">Galaxy Watch使えてない</a></li> <li><a href="#自作したツールが移行できなくなる">自作したツールが移行できなくなる</a></li> </ul> </li> <li><a href="#Android端末の選択肢">Android端末の選択肢</a><ul> <li><a href="#端末遍歴">端末遍歴</a></li> </ul> </li> <li><a href="#まとめ">まとめ</a></li> </ul> <h1 id="なんでやってるか">なんでやってるか</h1> <h2 id="Androidアプリ開発のため">Androidアプリ開発のため</h2> <p>「我が社もAndroid版アプリを開発するためにエンジニア採用をしなくては」というタイミングでプロジェクトの関係者が全員iPhoneだったので、とりあえずAndroidに興味を持つところからはじめないとな〜 と思いなんとなくスイッチした。</p> <p>これによってAndroidアプリエンジニアと面談の場である程度会話することができるようになった。</p> <h2 id="プラットフォームの違いを知るため">プラットフォームの違いを知るため</h2> <p>僕はクロスプラットームなGUIプログラミングに関心があるので、色々なプラットフォームを使ってみて比較したい。</p> <p>例えば<a href="https://developer.apple.com/xcode/swiftui/">SwiftUI</a>と<a href="https://developer.android.com/jetpack/compose">Jetpack Compose</a>と<a href="https://flutter.dev/">Flutter</a>の開発者体験を比較したり、React Nativeで<a href="https://reactnative.dev/docs/hermes">Hermes</a>っていうJavaScriptエンジンが両OSに組込まれるところを眺めたり、Tauri MobileのWebView経由でNext.jsを動かしてみたりしている。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Flaiso%2Farticles%2F825ee7e652ad1b" title="Tauri+Next.jsでモバイルアプリ開発" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/laiso/articles/825ee7e652ad1b">zenn.dev</a></cite></p> <h2 id="趣味Just-for-Fun">趣味(Just for Fun)</h2> <p>端末のセットアップとかは多くの人が面倒だと思っている部分だと思うけど僕にとっては単に娯楽なのであまり疑問に思わなかった。</p> <h1 id="良かったところ">良かったところ</h1> <h2 id="環境の見直し">環境の見直し</h2> <p>環境構築を繰替えすことで一定のタイミングで現時点でのベストな方法を模索することができる。</p> <p>惰性で使っていたツールがもうしばらく更新されていなかったり、より良い代替手段があったりする。</p> <h2 id="Androidアプリ開発">Androidアプリ開発</h2> <p>自分が日常的に使っている環境なので不便を感じた時に簡単なツールを自作して自分の端末で動かすことができる。</p> <p>これによってAndroidアプリ開発ができるようになった。</p> <h2 id="Android環境">Android環境</h2> <p>「Kindleがアプリ内で買える」ところがチャームポイントだったが近年の規制で外に飛ばさないといけなくなってしまった。</p> <p>Google Play Booksで買った本や<a href="https://gihyo.jp/dp">Gihyo Digital Publishing</a>や<a href="https://www.oreilly.co.jp/ebook/">O'Reilly Ebook Store</a>のePubをアップロードすると自動で読み上げてくれるので愛用してる。今は買えなくなっちゃったけど<a href="#f-23fc0095" name="fn-23fc0095" title="オライリー本が買えない話その後https://laiso.hatenablog.com/entry/2023/07/28/171613 ">*1</a></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2Fpower-of-kiku" title="Android端末でのオーディオブック環境 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/power-of-kiku">laiso.hatenablog.com</a></cite></p> <p>iOSだと読み上げコントローラでKindleページ送りして読んでたので同等のことはできるかも。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fsupport.apple.com%2Fja-jp%2Fguide%2Fiphone%2Fiph96b214f0%2Fios" title="iPhoneで画面や選択テキストを読み上げる/入力フィードバックを返す" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://support.apple.com/ja-jp/guide/iphone/iph96b214f0/ios">support.apple.com</a></cite></p> <h1 id="不便なところ">不便なところ</h1> <h2 id="iOS版しかないアプリ">iOS版しかないアプリ</h2> <p>日本やアメリカのアーリーアダプタ向けのサービスはiOS版が先行しがちなのでAndroidしかないとお預け状態になる。</p> <h2 id="Apple系のサービスが使えない">Apple系のサービスが使えない</h2> <p>この先Androidに移行する未来が決まっているので「Appleにすべてを委ねて楽になる」みたいなコンセプトのサービスが使えない。</p> <p>逆に「Googleにすべてを委ねて楽になる」サービスはiOSでも使えることが多いのでAndroidファーストになってきてしまう。</p> <h2 id="Galaxy-Watch使えてない">Galaxy Watch使えてない</h2> <p>Galaxy Watch5を持っているんだけど、ネットワークはセルラー越しに行うモデルなのでiPhone側にコンパニオンアプリを入れてbluetoothでペアリングして中継してもらう必要がある。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2Fwearos" title="Wear OSアプリ開発入門 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/wearos">laiso.hatenablog.com</a></cite></p> <p>でもいざiOS 17に移行しようとするとiOSアプリ:<a href="https://apps.apple.com/us/app/samsung-galaxy-watch-gear-s/id1117310635">Samsung Galaxy Watch</a>のプロセスが完了しない。</p> <p>もう1年半以上更新されてないし最新のiOSやWear OSに対応してないんじゃ疑惑がある。</p> <p>このためGalaxy Watch5が「現在時刻を見る」ぐらいのタスクしかこなせなくなってしまった。時計じゃん(時計だが)</p> <p>現在はGalaxy Watchからクラウドへの同期を機能させるためだけにサブのAndroid端末が控えてる。</p> <p>似た問題として<a href="https://www.apple.com/jp/airpods-pro/specs/">AirPods Pro</a>の接続をiPhoneに切り換えたらiOSでしか動作しないいろんな機能があったことに気付いた(会話するとボリューム抑えるのとか)。</p> <h2 id="自作したツールが移行できなくなる">自作したツールが移行できなくなる</h2> <p>自分の端末に入れて動かしてるツールがあってクロスプラットフォームなフレームワークで作ったやつはまだなんとかなるんですけどOSのAPI直接呼び出した方が速いようなケースではネイティブアプリで作ってる。</p> <p>これを移行できないので再実装するか捨てるかを都度選択することになる。</p> <h1 id="Android端末の選択肢">Android端末の選択肢</h1> <p>iPhoneはその時に発売されたものを買えばいいとしてAndroidはどのメーカーのにするか、というのを最初に決めないといけない。</p> <p>基本方針として「iPhoneと同価格帯」「まだ使ったことのないメーカー」の組合せて選んでる。</p> <h2 id="端末遍歴">端末遍歴</h2> <ul> <li>Nokia <a href="https://ja.wikipedia.org/wiki/Vodafone_702NK_II">702NK II</a>(Symbian)</li> <li><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20230930/20230930184146.png" width="17" height="20" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span>iPhone3G</li> <li><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20230930/20230930184149.png" width="17" height="20" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><a href="https://ja.wikipedia.org/wiki/SoftBank_X06HT">HTC Desire</a></li> <li><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20230930/20230930184146.png" width="17" height="20" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span>iPhone 4</li> <li><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20230930/20230930184149.png" width="17" height="20" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><a href="https://ja.wikipedia.org/wiki/Xperia_acro">Xperia acro</a></li> <li>(突如Windows Phone 8に目覚めた闇の期間があり覚えてない)</li> <li><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20230930/20230930184146.png" width="17" height="20" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span>iPhone 7</li> <li><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20230930/20230930184149.png" width="17" height="20" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><a href="https://en.wikipedia.org/wiki/Oppo_F5/F5_Youth">Oppo F5</a></li> <li><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20230930/20230930184146.png" width="17" height="20" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span>iPhone 11 Pro</li> <li><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20230930/20230930184149.png" width="17" height="20" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><a href="https://en.wikipedia.org/w/index.php?title=Xiaomi_Mi_11_Pro&amp;redirect=no">Xiaomi Mi 11 Pro</a></li> <li><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20230930/20230930184146.png" width="17" height="20" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span>iPhone 15 Pro</li> </ul> <p>Icon: <a href="https://iconduck.com/icons/">https://iconduck.com/icons/</a></p> <h1 id="まとめ">まとめ</h1> <p>2年ごとにiPhoneとAndroid端末を乗り換えると便利—— なのか????</p> <p>そもそも「2年ごとに買い替えて浪費するな」という意見もあると思うけど、自分のまわりでは毎年新型iPhoneに乗り換えて運用するApple著しく好き属性(ていねいな呼び方)な人が結構な割合でいるので2年だと比較的倹約家だな〜 と自負していて認知が歪んでいる。</p> <div class="footnote"> <p class="footnote"><a href="#fn-23fc0095" name="f-23fc0095" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">オライリー本が買えない話その後<a href="https://laiso.hatenablog.com/entry/2023/07/28/171613">https://laiso.hatenablog.com/entry/2023/07/28/171613</a> </span></p> </div> laiso TypeScript Origins: The Documentaryを観た hatenablog://entry/820878482969790274 2023-09-22T23:23:49+09:00 2023-09-23T15:32:04+09:00 TypeScript Origins: The DocumentaryはTypeScriptの誕生に関わった関係者たちへのインタビューで構成されたドキュメンタリー動画。 www.youtube.com 製作元はOfferZenというアムステルダムの求人プラットームの会社で、以前にはSvelte OriginsやLaravel Originsも公開している。 本作ではReact.js: The Documentaryの次世代フロントエンドフレームワーク開発競争と時期を同じくして起っていたAltJS戦争の中でどうTypeScriptが現在の地位を獲得していったのかに迫る。 laiso.hatena… <p>TypeScript Origins: The DocumentaryはTypeScriptの誕生に関わった関係者たちへのインタビューで構成されたドキュメンタリー動画。</p> <p><iframe width="560" height="315" src="https://www.youtube.com/embed/U6s2pdxebSo?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen title="TypeScript Origins: The Documentary"></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?v=U6s2pdxebSo">www.youtube.com</a></cite></p> <p>製作元は<a href="https://www.youtube.com/@OfferZenOrigins">OfferZen</a>というアムステルダムの求人プラットームの会社で、以前には<a href="https://www.youtube.com/watch?v=kMlkCYL9qo0">Svelte Origins</a>や<a href="https://www.youtube.com/watch?v=127ng7botO4">Laravel Origins</a>も公開している。</p> <p>本作ではReact.js: The Documentaryの次世代フロントエンドフレームワーク開発競争と時期を同じくして起っていたAltJS戦争の中でどうTypeScriptが現在の地位を獲得していったのかに迫る。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2Freact-documentary" title="React.js: The Documentaryで振り返るReact普及の歴史 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/react-documentary">laiso.hatenablog.com</a></cite></p> <p>私はTypeScriptについては片手間業務プログラマーという感じで全然詳しくないんですけど、TypeScript Originsのゆりかご からRemove TypeScriptの墓場まで(!)何かと当ブログでは縁がありますね。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F09%2F07%2F153417" title="Remove TypeScript - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/09/07/153417">laiso.hatenablog.com</a></cite></p> <h1 id="あらすじ">あらすじ</h1> <p>動画はSteve Lucco、Luke Hoban(現<a href="https://www.pulumi.com/">Pulumi</a>CTO)へのインタビューからはじまる。ふたりはChakra Javascriptエンジンの開発者で<a href="#f-6b2eb906" name="fn-6b2eb906" title="The Inner Workings of the Chakra Javascript Engine • Steve Lucco • GOTO 2012: https://www.youtube.com/watch?v=ouSoyWj_lSI ">*1</a>、当時コードネームStradaと呼ばれていたTypeScriptプロジェクトはマイクロソフトの戦略的にはブラウザエンジン高速化→OfficeやVisual Studioなどの自社製品のブラウザアプリケーション化→より大規模で複雑なソースコードを管理できるようにする、という流れをくんで始まったものだという事実が明かされる。</p> <p>この時点でなんか天才言語設計者のAnders HejlsbergがグッとガッツポーズしたらJavaScriptが改善したんでしょ、ぐらいの浅い理解だった自分には興味深かった。</p> <p>Anders Hejlsbergが出てくるのはプロジェクトの方向性が言語設計の具体的になった次のフェーズで、先ずはC#など別の言語からトランスパイルするのか(CoffeeScript, Haxe, Script#, GWT)、別の言語とエンジンごと置き換えるのか(Dart)、様々な方法がある中で互換性を維持しつつJavaScriptそのものを改善するというアイデアを進めることにしたようだ(動画では<a href="https://flow.org/">Flow</a>の話も出てくr)。</p> <p>舞台はこの後、Java界で著名なErich Gammaが出てきてVS Codeの初期開発を語ったり、当時OSS文化のなかったマイクロソフト内でAmanda Silverらがどう立ち回ってデベロッパーリレーションを確立したのか、GoogleのAngular開発者との連携、TC39との次期JavaScript仕様の標準化、などの話に入る(続きは本編をご覧ください)</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20230922/20230922232254.png" width="1000" height="563" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span> (ハリウッド映画のようにカットインするAnders Hejlsberg)</p> <h1 id="感想">感想</h1> <p>途中Anders HejlsbergがV8 JavaScriptエンジン開発者Lars Bak<a href="#f-d171e5d2" name="fn-d171e5d2" title="Want to be a Better Programmer? • Lars Bak &amp;amp; Kasper Lund https://www.youtube.com/watch?v=P8ltWIqDPzo ">*2</a>と「JavaScriptを直すべきか置き換えるべきか」という議論をしたという話が出てくる。</p> <p>Larsは置き換えるという考えでDartVMをブラウザに乗せるべき開発を推進したが、結果は皆さんもご存じのとうり。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">いいコマあった <a href="https://t.co/o7K64pdBPS">pic.twitter.com/o7K64pdBPS</a></p>&mdash; laiso👻 (@laiso) <a href="https://twitter.com/laiso/status/1705057952569372837?ref_src=twsrc%5Etfw">2023年9月22日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ただしDartはFlutterの中核として華麗にクロスプラットフォーム構築言語としてリバイバルしたので<a href="#f-fa2e5c36" name="fn-fa2e5c36" title="一度は挫折したDart言語が最近モバイル開発で右肩上がりに https://news.mynavi.jp/techplus/article/programinglanguageoftheworld-33/ ">*3</a>Dart側から見たドキュメンタリーもあったら面白そうだなぁと感じた。</p> <p>それにしても2010年代はスマホブームに注目していて気付かなかったけど巨大資本主導によるOSSプロジェクトがどんどん躍進していったのですね—— と昨今のドキュメンタリー動画たちを観ていて思った。</p> <div class="footnote"> <p class="footnote"><a href="#fn-6b2eb906" name="f-6b2eb906" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">The Inner Workings of the Chakra Javascript Engine • Steve Lucco • GOTO 2012: <a href="https://www.youtube.com/watch?v=ouSoyWj_lSI">https://www.youtube.com/watch?v=ouSoyWj_lSI</a> </span></p> <p class="footnote"><a href="#fn-d171e5d2" name="f-d171e5d2" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text">Want to be a Better Programmer? • Lars Bak &amp; Kasper Lund <a href="https://www.youtube.com/watch?v=P8ltWIqDPzo">https://www.youtube.com/watch?v=P8ltWIqDPzo</a> </span></p> <p class="footnote"><a href="#fn-fa2e5c36" name="f-fa2e5c36" class="footnote-number">*3</a><span class="footnote-delimiter">:</span><span class="footnote-text">一度は挫折したDart言語が最近モバイル開発で右肩上がりに <a href="https://news.mynavi.jp/techplus/article/programinglanguageoftheworld-33/">https://news.mynavi.jp/techplus/article/programinglanguageoftheworld-33/</a> </span></p> </div> laiso Remove TypeScript hatenablog://entry/820878482965441462 2023-09-07T15:34:17+09:00 2023-09-08T10:10:32+09:00 経緯 world.hey.com DHHが「オタクくん見てる〜? 今からうちのレポジトリからTypeScriptを剥しま〜す」と宣言したことにより、Web開発者界隈でTypeScriptの是非自体の話になり騒ぎになった*1*2。 github.com その後、野次馬がたくさん集ってきてrevertプルリクエストを立てる人やTypeScript公式リポジトリから全ソースコードを消すプルリクエストを出す*3ようなキッズムーブをする人も出てきた world.hey.com 実際の変更 8617行のTypeScriptがJavaScript化された。(Sloc 便利) ❯ scc src/ ─────… <h1 id="経緯">経緯</h1> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fworld.hey.com%2Fdhh%2Fturbo-8-is-dropping-typescript-70165c01" title="Turbo 8 is dropping TypeScript" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://world.hey.com/dhh/turbo-8-is-dropping-typescript-70165c01">world.hey.com</a></cite></p> <p>DHHが「オタクくん見てる〜? 今からうちのレポジトリからTypeScriptを剥しま〜す」と宣言したことにより、Web開発者界隈でTypeScriptの是非自体の話になり騒ぎになった<a href="#f-a36de83a" name="fn-a36de83a" title="https://twitter.com/kentcdodds/status/1699539752637309142 ">*1</a><a href="#f-928608c5" name="fn-928608c5" title="https://twitter.com/DrizzleORM/status/1699497381824201074 ">*2</a>。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fhotwired%2Fturbo%2Fpull%2F971" title="Remove TypeScript by afcapel · Pull Request #971 · hotwired/turbo" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://github.com/hotwired/turbo/pull/971">github.com</a></cite></p> <p>その後、野次馬がたくさん集ってきてrevertプルリクエストを立てる人やTypeScript公式リポジトリから全ソースコードを消すプルリクエストを出す<a href="#f-ae3f7cdc" name="fn-ae3f7cdc" title="https://github.com/microsoft/TypeScript/pull/55655 ">*3</a>ようなキッズムーブをする人も出てきた</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fworld.hey.com%2Fdhh%2Fopen-source-hooliganism-and-the-typescript-meltdown-a474bfda" title="Open source hooliganism and the TypeScript meltdown" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://world.hey.com/dhh/open-source-hooliganism-and-the-typescript-meltdown-a474bfda">world.hey.com</a></cite></p> <h2 id="実際の変更">実際の変更</h2> <p>8617行のTypeScriptがJavaScript化された。(<a href="https://github.com/boyter/scc">Sloc</a> 便利)</p> <pre class="code" data-lang="" data-unlink>❯ scc src/ ─────────────────────────────────────────────────────────────────────────────── Language Files Lines Blanks Comments Code Complexity ─────────────────────────────────────────────────────────────────────────────── TypeScript 81 10934 2048 269 8617 986 HTML 65 1891 138 2 1751 0 JavaScript 3 170 17 23 130 29 CSS 2 6 0 0 6 0 SVG 1 1 0 0 1 0 TypeScript Typings 1 13 2 1 10 1 ─────────────────────────────────────────────────────────────────────────────── Total 153 13015 2205 295 10515 1016</pre> <pre class="code" data-lang="" data-unlink>❯ scc src/ ─────────────────────────────────────────────────────────────────────────────── Language Files Lines Blanks Comments Code Complexity ─────────────────────────────────────────────────────────────────────────────── JavaScript 81 10434 1983 272 8179 752 HTML 65 1891 138 2 1751 0 CSS 2 6 0 0 6 0 SVG 1 1 0 0 1 0 ─────────────────────────────────────────────────────────────────────────────── Total 149 12332 2121 274 9937 752</pre> <p>典型的な変更は型注釈の削除。これを全ファイルに渡って行っている。</p> <pre class="code lang-diff" data-lang="diff" data-unlink><span class="synSpecial">- respondsToEventTarget(target: EventTarget | null) {</span> <span class="synIdentifier">+ respondsToEventTarget(target) {</span> const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null return element &amp;&amp; element.closest(&quot;turbo-frame, html&quot;) == this.element } </pre> <h1 id="Turboとは何か">Turboとは何か</h1> <p>TurboはRailsのviewでSPAを書くための仕組みです。<a href="https://turbo.build/">https://turbo.build/</a>とは別。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2Fhotwire-debut" title="Hotwireの感想 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/hotwire-debut">laiso.hatenablog.com</a></cite></p> <p>厳密には「サーバーサイドHTMLテンプレートベースでSPAを書くための仕組み」でRails以外にも適用できるのでGitHubのorgが独立して開発されている。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fhotwired" title="Hotwire" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://github.com/hotwired">github.com</a></cite></p> <h1 id="背景">背景</h1> <p>「静的型付け言語と動的型付け言語はどちらが良いのか」という議論は今までにも各所で行なわれてきた。TypeScriptは静的型付け言語でJavaScriptやRubyは動的型付け言語に分類される。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftypescriptbook.jp%2Foverview%2Fstatic-type" title="静的型付け | TypeScript入門『サバイバルTypeScript』" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://typescriptbook.jp/overview/static-type">typescriptbook.jp</a></cite></p> <p>DHHは(Ruby on Railsの作者だから当然)動的型付け言語の信仰者で、TypeScriptを好んでなくて利点を認めつつもあまり熱心ではないと普段から公言していた。</p> <p>Rails誕生からの十数年を経て近年は型推論で静的型付けの記述量が軽減されたり、IDEや言語サーバーが賢くなったり、世間のプロジェクトが大規模複雑化してきたりしてもその部分はブレていないようだ。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fworld.hey.com%2Fdhh%2Fprogramming-types-and-mindsets-5b8490bc" title="Programming types and mindsets" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://world.hey.com/dhh/programming-types-and-mindsets-5b8490bc">world.hey.com</a></cite></p> <p>なのでTurboのレポジトリがTypeScriptだったのも「ライブラリはTypeScriptにするメリットがあるんだろうな」ぐらいに自分は感じていた。</p> <p>実際、37signalsが作成するRailsアプリケーションのサンプルコードはいつもデフォルトJavaScriptで、彼等のプロダクトのコードもそうなんだろうと思う。</p> <p>彼にとってTypeScriptが本来なくても充分に機能する複雑な抽象レイヤーという認識だったのかもしれませんね。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2Fddhh" title="最近のDHH「サーバーレスをやめろ」 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/ddhh">laiso.hatenablog.com</a></cite></p> <p>あと直接TypeScript書いてたコミッタの人は2021年のCEOブチ切れ事件の時にやめてる</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftechcrunch.com%2F2021%2F04%2F30%2Fbasecamp-employees-quit-ceo-letter%2F" title="Basecamp sees mass employee exodus after CEO bans political discussions | TechCrunch" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://techcrunch.com/2021/04/30/basecamp-employees-quit-ceo-letter/">techcrunch.com</a></cite></p> <h1 id="誰に影響があるのか">誰に影響があるのか</h1> <h2 id="Turboのコントリビューター">Turboのコントリビューター</h2> <p>RailsのviewでSPAを書いていてTurbo本体にコントリビュートしたい時にJavaScriptコードで変更をしないといけなくなる人。</p> <p>一方、RailsのviewでSPAを書いているアプリケーション開発l=Turboユーザー当事者はviewテンプレートと向きあったりwebpackやesbuildを通じたアセット管理をしているだけで、Turboのインターフェイスをコードから直接呼び出すようなことはない。</p> <p>なのでTurboの中身がJavaScriptになったことでアプリケーション側ではひき続きTypeScriptで書くことができる(と言ってもTurboを使っている時に主に書くのはHTMLとRubyだが)</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fguides.rubyonrails.org%2Fworking_with_javascript_in_rails.html" title="Working with JavaScript in Rails — Ruby on Rails Guides" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://guides.rubyonrails.org/working_with_javascript_in_rails.html">guides.rubyonrails.org</a></cite></p> <p>そもそもRailsのviewを使う機会が近年のチーム開発では減ってきていてそれを指して「Railsはオワコン」とか言われていたりする。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2Fruby3000" title="Railsオワコン論 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/ruby3000">laiso.hatenablog.com</a></cite></p> <h2 id="Rails以外でTurboを使えるようにしたい人">Rails以外でTurboを使えるようにしたい人</h2> <p>Turboを別のフレームワークに提供するためにプラグインを書いて、その時に<a href="https://www.npmjs.com/package/@hotwired/turbo">@hotwired/turbo</a>の型定義を参考にする人。</p> <p>自分の知っている中ではLaravel版があるけど彼等もJavaScriptで書いてる。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fhotwired-laravel%2Fturbo-laravel" title="GitHub - hotwired-laravel/turbo-laravel: This package gives you a set of conventions to make the most out of Hotwire in Laravel." class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://github.com/hotwired-laravel/turbo-laravel">github.com</a></cite></p> <h2 id="Railsエコシステム周りでTypeScriptやっていきたい人">Railsエコシステム周りでTypeScriptやっていきたい人</h2> <p>37signals系のライブラリがTypeScriptを剥すのは既定路線で今から覆らなさそうなので、<a href="https://github.com/hotwired/stimulus">Stimulus</a>などのRailsでかつフロント関係あるやつが全部JS化されて生きづらくなりそう。</p> <div class="footnote"> <p class="footnote"><a href="#fn-a36de83a" name="f-a36de83a" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://twitter.com/kentcdodds/status/1699539752637309142">https://twitter.com/kentcdodds/status/1699539752637309142</a> </span></p> <p class="footnote"><a href="#fn-928608c5" name="f-928608c5" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://twitter.com/DrizzleORM/status/1699497381824201074">https://twitter.com/DrizzleORM/status/1699497381824201074</a> </span></p> <p class="footnote"><a href="#fn-ae3f7cdc" name="f-ae3f7cdc" class="footnote-number">*3</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://github.com/microsoft/TypeScript/pull/55655">https://github.com/microsoft/TypeScript/pull/55655</a> </span></p> </div> laiso ニューWindowsマシンのセットアップした hatenablog://entry/820878482964460799 2023-09-03T23:37:12+09:00 2023-09-06T01:08:12+09:00 10年ぶりぐらいにWindowsメイン機を構築したら色々変わっていた。その過程で情報収集しながら記録した内容をポストします。 マシンの目的 やらなかったこと 日本語環境の構築 古いWindowsっぽく振る舞う設定系 仮想マシン内にLinux環境を作る系 Remote Desktop sshd winget Git Python Stable Diffusion web UI Visual Studio 2022 PowerToys JoyToKey Power Automate マシン間のファイル送受信 自動ログオンとキオスク端末化 マシンの目的 Windowsしか対応していないビデオゲームを… <p>10年ぶりぐらいにWindowsメイン機を構築したら色々変わっていた。その過程で情報収集しながら記録した内容をポストします。</p> <ul class="table-of-contents"> <li><a href="#マシンの目的">マシンの目的</a></li> <li><a href="#やらなかったこと">やらなかったこと</a><ul> <li><a href="#日本語環境の構築">日本語環境の構築</a></li> <li><a href="#古いWindowsっぽく振る舞う設定系">古いWindowsっぽく振る舞う設定系</a></li> <li><a href="#仮想マシン内にLinux環境を作る系">仮想マシン内にLinux環境を作る系</a></li> </ul> </li> <li><a href="#Remote-Desktop">Remote Desktop</a></li> <li><a href="#sshd">sshd</a></li> <li><a href="#winget">winget</a></li> <li><a href="#Git">Git</a></li> <li><a href="#Python">Python</a></li> <li><a href="#Stable-Diffusion-web-UI">Stable Diffusion web UI</a></li> <li><a href="#Visual-Studio-2022">Visual Studio 2022</a></li> <li><a href="#PowerToys">PowerToys</a></li> <li><a href="#JoyToKey">JoyToKey</a></li> <li><a href="#PowerAutomate">Power Automate</a></li> <li><a href="#マシン間のファイル送受信">マシン間のファイル送受信</a></li> <li><a href="#自動ログオンとキオスク端末化">自動ログオンとキオスク端末化</a></li> </ul> <h1 id="マシンの目的">マシンの目的</h1> <ul> <li>Windowsしか対応していないビデオゲームをプレイする</li> <li>GPU使ったタスク。機械学習モデルの推論やファインチューニング。画像・テキスト生成AIの実行</li> <li>Windowsデスクトップアプリケーションの開発</li> <li>VRデバイスや3Dゲームエンジンを使った開発</li> <li>WindowsにしかSDKがないデバイス組込ソフトウェア系の開発</li> </ul> <h1 id="やらなかったこと">やらなかったこと</h1> <h2 id="日本語環境の構築">日本語環境の構築</h2> <p>半分ぐらいサーバー機っぽいのでIMEいらんやろと思ってパスした。</p> <p>WindowsはサーバーエディションじゃなくてWindows 11 Proを買った。</p> <h2 id="古いWindowsっぽく振る舞う設定系">古いWindowsっぽく振る舞う設定系</h2> <p>老いに逆らってゆきたいので、基本的に差し出された最新のWindows 11環境をなるべく使うようにした。</p> <h2 id="仮想マシン内にLinux環境を作る系">仮想マシン内にLinux環境を作る系</h2> <p>LinuxベースWeb開発環境っぽいものを構築するのをやめた。デバイスやGPUを直で使いたいので仮想環境じゃない方が都合もよく、既に所持しているmacOS環境でWeb系の作業も足りているので。</p> <p>.NET系のWeb環境は別で何か入れるかもしれない。</p> <h1 id="Remote-Desktop">Remote Desktop</h1> <p>手持ちMacBookからログインして作業したいのでRemote Desktopを先に設定した。</p> <p><div class="itunes-embed freezed itunes-kind-mac-software"><a href="https://apps.apple.com/us/app/microsoft-remote-desktop/id1295203466?mt=12&uo=4&at=10l8JW&ct=hatenablog" rel="nofollow" target="_blank"><img src="https://cdn.image.st-hatena.com/image/scale/412f0fc146e5f58060bbff29d12db1fc6d0131c8/enlarge=0;height=200;version=1;width=200/https%3A%2F%2Fis5-ssl.mzstatic.com%2Fimage%2Fthumb%2FPurple126%2Fv4%2Fa6%2Fee%2F65%2Fa6ee6559-2343-2e58-3a04-95e8c36812c2%2FAppIcon-85-220-0-4-2x.png%2F100x100bb.png" alt="Microsoft Remote Desktop" title="Microsoft Remote Desktop" class="itunes-embed-image"/></a><div class="itunes-embed-info"><p class="itunes-embed-title"><a href="https://apps.apple.com/us/app/microsoft-remote-desktop/id1295203466?mt=12&uo=4&at=10l8JW&ct=hatenablog" rel="nofollow" target="_blank">Microsoft Remote Desktop</a></p><ul><li class="itunes-embed-artist">Microsoft Corporation</li><li class="itunes-embed-genre">Business</li><li class="itunes-embed-price">Free</li><li class="itunes-embed-badge"><a href="https://apps.apple.com/us/app/microsoft-remote-desktop/id1295203466?mt=12&uo=4&at=10l8JW&ct=hatenablog" rel="nofollow" target="_blank"><img src="https://cdn.blog.st-hatena.com/images/theme/itunes/itunes-badge-macappstore@2x.png" width="80px" height="15px" /></a></li></ul></div></div><cite class="hatena-citation"><a href="https://apps.apple.com/us/app/microsoft-remote-desktop/id1295203466?mt=12">apps.apple.com</a></cite></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fsupport.microsoft.com%2Fen-us%2Fwindows%2Fhow-to-use-remote-desktop-5fe128d5-8fb1-7a23-3b8a-41e636865e8c" title="How to use Remote Desktop - Microsoft Support" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://support.microsoft.com/en-us/windows/how-to-use-remote-desktop-5fe128d5-8fb1-7a23-3b8a-41e636865e8c">support.microsoft.com</a></cite></p> <h1 id="sshd">sshd</h1> <p>GUIなしでシェルでガチャガチャ作業するだけならRDP経由じゃなくてSSHでいいので以下を参考にMacからログインできるようにした。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flearn.microsoft.com%2Fen-us%2Fwindows-server%2Fadministration%2Fopenssh%2Fopenssh_install_firstuse" title="Get started with OpenSSH for Windows" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://learn.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse">learn.microsoft.com</a></cite></p> <p>以下まで実行するとログインがPowerShellになる。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flearn.microsoft.com%2Fen-us%2Fwindows-server%2Fadministration%2Fopenssh%2Fopenssh_server_configuration" title="OpenSSH Server configuration for Windows" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://learn.microsoft.com/en-us/windows-server/administration/openssh/openssh_server_configuration">learn.microsoft.com</a></cite></p> <h1 id="winget">winget</h1> <p>aptやbrewみたいなパッケージマネージャコマンド。ツール類をまとめて管理するために利用。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flearn.microsoft.com%2Fja-jp%2Fwindows%2Fpackage-manager%2F" title="Windows パッケージ マネージャー" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://learn.microsoft.com/ja-jp/windows/package-manager/">learn.microsoft.com</a></cite></p> <h1 id="Git">Git</h1> <p>GitHubからツールをダウンロードしてくる時などに使われがち。</p> <p>公式ページにあるwingetコマンドでインストールした。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgit-scm.com%2Fdownload%2Fwin" title="Git - Downloading Package" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://git-scm.com/download/win">git-scm.com</a></cite></p> <h1 id="Python">Python</h1> <p>どうなんだろう……と思いながらMicrosoft Storeから入れた。</p> <p>Stable Diffusion系の記事で3.10系にしとけみたいな記述が多かったので様子見で3.10にした。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fapps.microsoft.com%2Fstore%2Fdetail%2Fpython-310%2F9PJPW5LDXLZ5" title="Get Python 3.10 from the Microsoft Store" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://apps.microsoft.com/store/detail/python-310/9PJPW5LDXLZ5">apps.microsoft.com</a></cite></p> <h1 id="Stable-Diffusion-web-UI">Stable Diffusion web UI</h1> <p>ここまでセットアップした環境ですんなり起動できて、画像生成もできた。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2FAUTOMATIC1111%2Fstable-diffusion-webui" title="GitHub - AUTOMATIC1111/stable-diffusion-webui: Stable Diffusion web UI" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://github.com/AUTOMATIC1111/stable-diffusion-webui">github.com</a></cite></p> <p>7860ポートを開放して <code>webui.bat --listen</code>で起動するとネットワークの他のマシンからアクセスできる。</p> <p><code>New-NetFirewallRule -Name 'stable-diffusion-webui' -DisplayName 'stable-diffusion-webui' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 7860</code></p> <h1 id="Visual-Studio-2022">Visual Studio 2022</h1> <p>Windows系のアプリケーション開発に使うIDEとSDK類。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fvisualstudio.microsoft.com%2Fja%2F" title="Visual Studio: ソフトウェア開発者とチーム向けの IDE およびコード エディター" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://visualstudio.microsoft.com/ja/">visualstudio.microsoft.com</a></cite></p> <p>Communityエディションでいいらしい。</p> <p>Win10以降のことよく知らなかったが最新のデスクトップ向けプラットフォームはUWPというやつらしい。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flearn.microsoft.com%2Fen-us%2Fwindows%2Fuwp%2Fdevelop%2F" title="Develop UWP apps - UWP applications" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://learn.microsoft.com/en-us/windows/uwp/develop/">learn.microsoft.com</a></cite></p> <p>MAUIっていうのが元Xamarinで、モバイルアプリ作るのはこれらしい。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flearn.microsoft.com%2Fen-us%2Fdotnet%2Fmaui%2F" title=".NET Multi-platform App UI documentation - .NET MAUI" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://learn.microsoft.com/en-us/dotnet/maui/">learn.microsoft.com</a></cite></p> <h1 id="PowerToys">PowerToys</h1> <p>Caps lockとcontrolどうやってスワップするんだと調べていた時に見付けた今風のやつ。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flearn.microsoft.com%2Fen-us%2Fwindows%2Fpowertoys%2F" title="Microsoft PowerToys" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://learn.microsoft.com/en-us/windows/powertoys/">learn.microsoft.com</a></cite></p> <h1 id="JoyToKey">JoyToKey</h1> <p>Java版のマイクラをパッドでやる用に入れた。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fjoytokey.net%2Fja%2F" title="JoyToKey 公式ホームページ - 最新版をダウンロード" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://joytokey.net/ja/">joytokey.net</a></cite></p> <p>未だJoyToKeyが定番らしい。メンテナンスし続けてくれてありがとうございます。</p> <h1 id="PowerAutomate">Power Automate</h1> <p>MacでいうAutomatorっぽいやつらしい。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fpowerautomate.microsoft.com%2Fja-jp%2F" title="Power Automate | Microsoft Power Platform" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://powerautomate.microsoft.com/ja-jp/">powerautomate.microsoft.com</a></cite></p> <h1 id="マシン間のファイル送受信">マシン間のファイル送受信</h1> <p>Remote Desktopの接続先に接続元のディレクトリを指定できるのでファイルの受け渡しができる。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fsupport.microsoft.com%2Fen-gb%2Ftopic%2Fhow-to-gain-access-to-local-files-in-a-remote-desktop-session-to-a-windows-xp-based-or-to-a-windows-server-2003-based-host-computer-021ee183-e6be-4201-809e-c355c47b17f4" title="How to gain access to local files in a remote desktop session to a Windows XP-based or to a Windows Server 2003-based host computer - Microsoft Support" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://support.microsoft.com/en-gb/topic/how-to-gain-access-to-local-files-in-a-remote-desktop-session-to-a-windows-xp-based-or-to-a-windows-server-2003-based-host-computer-021ee183-e6be-4201-809e-c355c47b17f4">support.microsoft.com</a></cite></p> <h1 id="自動ログオンとキオスク端末化">自動ログオンとキオスク端末化</h1> <p>キオスク端末として普段はゲーム用に自動ログインしておき、管理者はRemoteログインするという運用をしたかったので以下を設定した。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flearn.microsoft.com%2Fen-us%2Fwindows%2Fconfiguration%2Fkiosk-prepare%23automatic-logon" title="Prepare a device for kiosk configuration on Windows 10/11 - Configure Windows" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://learn.microsoft.com/en-us/windows/configuration/kiosk-prepare#automatic-logon">learn.microsoft.com</a></cite></p> <p>Steam設定でBig Picture modeをデフォルトにしておきシステムの起動時に自動で立ち上げるようにしておくと、Xboxのコントローラーのみで操作可能な疑似キオスク端末風にできる。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhelp.steampowered.com%2Fen%2Ffaqs%2Fview%2F3725-76D3-3F31-FB63" title="Steam Support :: Steam&#39;s Big Picture mode" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://help.steampowered.com/en/faqs/view/3725-76D3-3F31-FB63">help.steampowered.com</a></cite></p> laiso PaLM APIのファインチューニングではてな匿名ダイアリー風文章生成モデルを作る hatenablog://entry/820878482962186159 2023-08-27T19:27:30+09:00 2023-08-28T12:14:51+09:00 PaLMとは PaLM APIのファインチューニング はてな匿名ダイアリー風文章生成モデルとは Quotaの申請 データセットの作成 トレーニングJobの実行 チューニング済みモデルで文章生成する おまけ: gpt-3-5-turboでも同じファインチューニングしてみた チューニングなし チューニングあり ジョブの実行部分 PaLMとは PaLMはGoogleの大規模言語モデルです。先日、日本語に対応しました。 www.itmedia.co.jp PaLM APIのファインチューニング PaLM APIの基本的な利用方については以下の記事が参考になります。 zenn.dev 6月頃に「PaLM… <ul class="table-of-contents"> <li><a href="#PaLMとは">PaLMとは</a></li> <li><a href="#PaLM-APIのファインチューニング">PaLM APIのファインチューニング</a></li> <li><a href="#はてな匿名ダイアリー風文章生成モデルとは">はてな匿名ダイアリー風文章生成モデルとは</a></li> <li><a href="#Quotaの申請">Quotaの申請</a></li> <li><a href="#データセットの作成">データセットの作成</a></li> <li><a href="#トレーニングJobの実行">トレーニングJobの実行</a></li> <li><a href="#チューニング済みモデルで文章生成する">チューニング済みモデルで文章生成する</a></li> <li><a href="#おまけ-gpt-3-5-turboでも同じファインチューニングしてみた">おまけ: gpt-3-5-turboでも同じファインチューニングしてみた</a><ul> <li><a href="#チューニングなし">チューニングなし</a></li> <li><a href="#チューニングあり">チューニングあり</a></li> <li><a href="#ジョブの実行部分">ジョブの実行部分</a></li> </ul> </li> </ul> <h1 id="PaLMとは">PaLMとは</h1> <p>PaLMはGoogleの大規模言語モデルです。先日、日本語に対応しました。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.itmedia.co.jp%2Fnews%2Farticles%2F2308%2F23%2Fnews087.html" title="Google、LLMの「PaLM 2」と「Codey」で日本語をサポート" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.itmedia.co.jp/news/articles/2308/23/news087.html">www.itmedia.co.jp</a></cite></p> <h1 id="PaLM-APIのファインチューニング">PaLM APIのファインチューニング</h1> <p>PaLM APIの基本的な利用方については以下の記事が参考になります。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Fgoogle_cloud_jp%2Farticles%2Fgoogle-cloud-generative-ai" title="Google Cloud で生成 AI アプリケーションを作ろう!パート 0:Google Cloud の生成 AI ソリューション" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/google_cloud_jp/articles/google-cloud-generative-ai">zenn.dev</a></cite></p> <p>6月頃に「PaLMって英語の受け答えにしか対応していないけど日本語でファインチューニングしたらどうなるんだろう<a href="#f-3f8f0490" name="fn-3f8f0490" title="https://twitter.com/laiso/status/1668598072279175169">*1</a>」と思って実行してみたんですけど、当然のごとくエラーが出て失敗しました。</p> <p>今回日本語に対応したので、再度挑戦してみました。</p> <h1 id="はてな匿名ダイアリー風文章生成モデルとは">はてな匿名ダイアリー風文章生成モデルとは</h1> <p>題材として、以前以下の記事でみかけたコンセプトである「はてな匿名ダイアリー風文章生成モデル」の自作を選びました。</p> <blockquote><p>Anond AIは、rinna/japanese-gpt2-mediumをはてな匿名ダイアリーのデータを用いてファインチューニングし、ドメイン適応させたものです。</p></blockquote> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fdeveloper.hatenastaff.com%2Fentry%2Fanond-ai-development" title="Anond AI開発日記 - Hatena Developer Blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://developer.hatenastaff.com/entry/anond-ai-development">developer.hatenastaff.com</a></cite></p> <h1 id="Quotaの申請">Quotaの申請</h1> <p>以下のドキュメントに沿ってすすめます。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcloud.google.com%2Fvertex-ai%2Fdocs%2Fgenerative-ai%2Fmodels%2Ftune-text-models" title="Tune text models  |  Vertex AI  |  Google Cloud" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://cloud.google.com/vertex-ai/docs/generative-ai/models/tune-text-models">cloud.google.com</a></cite></p> <p>ファインチューニングの実行はeurope-west4かus-central1でないと実行できないようになっているので、そのlocationでQuotaの申請を行います。</p> <p>6月時点ではeurope-west4しか対応してなかったので、europe-west4 + restricted_image_training_tpu_v3_pod=64を申請しました。</p> <blockquote><p>For europe-west4, submit a request for Restricted image training TPU V3 pod cores per region in the europe-west4 region in multiples of 64.</p></blockquote> <p>受理までしばらく時間がかかりました(数日)。以下URLから割り当て状況を確認可能です。</p> <p><a href="https://console.cloud.google.com/iam-admin/quotas/qirs">https://console.cloud.google.com/iam-admin/quotas/qirs</a></p> <h1 id="データセットの作成">データセットの作成</h1> <p>ドキュメントに従いjsonlファイルを作ります。300件ほどサンプルがあればよいかと思い、以下のような形式のデータを作成しました。</p> <ul> <li>input_text: 投稿のタイトル</li> <li>output_text: 投稿の本文冒頭</li> </ul> <pre class="code bash" data-lang="bash" data-unlink>❯ tail dataset.jsonl {&#34;input_text&#34;: &#34;表現規制派の言ってる事って「マイナスイオン」とか「水からの伝言」と何が違うの?&#34;, &#34;output_text&#34;: &#34;強力効果論とか限定効果論とかあるけどさ、あれってどの位証明されてどの位信用が けるものなの? そういう影響論を真に受けて表現規制とか公共の場に出すなとか言っているけど それが嘘だった場合(つまり、影響なんて無いか、無視できる程度だったり、他の表現や社会的に許容されて 他の一般的行動とか慣習と同程度の影響しかなかった場合)、どうするの? 現状、その可能性は全然有る様に見えるんだけど 全然効果が無い事の為に、仕事を失ったり罵倒されり悪として扱われる人達の理 尽な境遇を考えないなら、リベラルの名を語る資格無くね? あなた達は人を不幸にする為にリベラルとか表現規制派とかをやっているの? 違うと言うなら、何で真面目に考えようとしないの? 表現規制派の ってる事って「マイナスイオン」とか「水からの伝言」と何が違うの? 追記 冒頭に挙げた例が却って一例に拘泥して論点を見失う原因になるようなので、消しまし&#34;} {&#34;input_text&#34;: &#34;甲子園球児の笑顔が辛い&#34;, &#34;output_text&#34;: &#34;しんどい場面で笑ってるのがキツイ。本当は「くそがああああ!!!!」とブチギレたいだろうに。グローブでもベンチに投げつけたいし、バット し折りたいだろう。緊張極まってプルプル真っ青な顔でいたいだろうに。テレビもあるし、一生残るし常に「どんな状況でも甲子園楽しんでます!」を演出しなきゃいけないのしんどすぎるだろ。小さい頃に ちゃイジメられてたのにヘラヘラ笑うしか無かった自分を思い出して見てられん。はーしんど。&#34;} {&#34;input_text&#34;: &#34;お金がなくなっていくって怖いよね&#34;, &#34;output_text&#34;: &#34;元々貧乏な生活してささやかな貯金をするのが趣味だった。 今配偶者がなおるあてのない長く療養が必要な重い病気になって貯金を切 崩す生活をしてて、使える制度をフルに使っても100万円しかない貯金が毎月10万円ずつ減ってるの見てるけど、配偶者が重い病気で怖いとか悲しいより、このお金が無くなるという方が正直ストレスに感じて 。 薄情なやつだな、と思うけど、そんなことを悟られないようにして最期まで面倒みるから、許して欲しい。 実家、新築の家を昔ローンで買ってたけど、今年55歳の父親が1500万の残債がどうにもならなく 売りに出すって。でも、私あの家にそんな価値ないって知ってる。猫が柱をがちゃがちゃにして、あらゆるところの掃除をマメにしていたわけでないから汚れが酷くて立地が酷い。だからきっとそんな値段で 売れない。父親と母親は熟年離婚した。母親も貧乏な生活してる。父親も母親も高卒で、両親はわたしを含め&#34;}</pre> <p>これによって未知のタイトルを入力したら、はてな匿名ダイアリーの投稿の書き出しを生成してくれるのを期待します。</p> <p>できたらjsonlファイルをGCSにアップロードしておきます。</p> <h1 id="トレーニングJobの実行">トレーニングJobの実行</h1> <p><a href="https://github.com/GoogleCloudPlatform/python-docs-samples/blob/aff1e1ffbb562b655c8b63542533bb23167dd919/generative_ai/tuning.py">tuning.py</a>を参考に実装します。</p> <pre class="code lang-python" data-lang="python" data-unlink>model = TextGenerationModel.from_pretrained(<span class="synConstant">&quot;text-bison@001&quot;</span>) model.tune_model( training_data=training_data, model_display_name=<span class="synConstant">'text-anond'</span>, train_steps=<span class="synConstant">12</span>, tuning_job_location=<span class="synConstant">&quot;europe-west4&quot;</span>, tuned_model_location=location, ) </pre> <p>training_dataはGCSにアップロードしたデータセットのパスを指定します。例: <code>gs://bucket-name/path/to/dataset.csv</code></p> <p>train_stepsはファインチューニングのステップ数を指定します。データセットのサンプル数とジョブ実行locationで調整します。</p> <blockquote><p>If there are 240 examples in a training dataset, in europe-west4, it takes 240 / 24 = 10 steps to process the entire dataset once. In us-central1, it takes 240 / 8 = 30 steps to process the entire dataset once. The default value is 300.</p></blockquote> <p>tuned_model_locationはモデルが配置される場所です。トレーニングとは別のlocationが指定できます。</p> <p>このスクリプトを実行するとVertex AIのパイプライン上で実行中となり状況やエラーなどを確認できます。</p> <p><a href="https://console.cloud.google.com/vertex-ai/pipelines/runs">https://console.cloud.google.com/vertex-ai/pipelines/runs</a></p> <p>第1回目のチューニングを実行した直後「差別的な内容など・データセットに問題あり」警告が100件程出てきて完全に題材見誤ったわーと後悔したのですが、なんとかなりました。</p> <h1 id="チューニング済みモデルで文章生成する">チューニング済みモデルで文章生成する</h1> <p>無事チューニングジョブが完了したら、以下のモデル一覧にチューニング済みモデルが表示されます。</p> <p><a href="https://console.cloud.google.com/vertex-ai/models">https://console.cloud.google.com/vertex-ai/models</a></p> <p>「デプロイ」→「モデルのテスト」→「Generative AI Studio」と進むとブラウザ上で応答を確認できます。</p> <p>Prompt入力欄に匿名ダイアリーにありそうなタイトルを入力してみて、生成された文章を確認します。創作性を発揮してもらいたいのでモデルのtemplateは1にしておきます。</p> <p>ここで残念なお知らせですが、Googleの<a href="https://cloud.google.com/trustedtester/aitos?hl=ja">Generative AI Preview Products</a>利用規約に従い生成された文章は第三者に公開できません(なので本稿も公開情報だけに触れています)。</p> <p>なので私の感想を書くだけにとどめますが——そういえばはてな匿名ダイアリーを普段読まないので正直よく分からん。</p> <p>ソースコードからこのモデルを呼び出す時のコードは<a href="https://github.com/GoogleCloudPlatform/python-docs-samples/blob/aff1e1ffbb562b655c8b63542533bb23167dd919/generative_ai/ideation.py">ideation.py</a> が参考になります。</p> <p>今回のテストだとこんな感じになります。</p> <pre class="code lang-python" data-lang="python" data-unlink>model = TextGenerationModel.from_pretrained(<span class="synConstant">&quot;text-bison@001&quot;</span>) model = model.get_tuned_model(f<span class="synConstant">&quot;projects/{project_id}/locations/{location}/models/{tuned_model_id}&quot;</span>) response = model.predict( <span class="synConstant">&quot;&quot;&quot;タモリさんの本名は?&quot;&quot;&quot;</span>, **parameters ) <span class="synIdentifier">print</span>(f<span class="synConstant">&quot;Response from Model: {response.text}&quot;</span>) </pre> <h1 id="おまけ-gpt-3-5-turboでも同じファインチューニングしてみた">おまけ: gpt-3-5-turboでも同じファインチューニングしてみた</h1> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fopenai.com%2Fblog%2Fgpt-3-5-turbo-fine-tuning-and-api-updates" title="GPT-3.5 Turbo fine-tuning and API updates" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://openai.com/blog/gpt-3-5-turbo-fine-tuning-and-api-updates">openai.com</a></cite></p> <p>データセットは微修正すればいけるので追加で試した。</p> <pre class="code lang-python" data-lang="python" data-unlink>model = <span class="synConstant">&quot;ft:gpt-3.5-turbo-0613:personal::XXXXXXX&quot;</span> completion = openai.ChatCompletion.create( model=model, messages=[ {<span class="synConstant">&quot;role&quot;</span>: <span class="synConstant">&quot;user&quot;</span>, <span class="synConstant">&quot;content&quot;</span>: <span class="synConstant">&quot;まじな話をすると、N予備校のプログラミング入門コースやるのがオススメ&quot;</span>} ], max_tokens=<span class="synConstant">255</span>, ) <span class="synIdentifier">print</span>(completion.choices[<span class="synConstant">0</span>].message[<span class="synConstant">'content'</span>]) </pre> <pre class="code bash" data-lang="bash" data-unlink>❯ python tuning_openai.py 個人的な意見で、エンジニアになりたい人、プログラミングを自己流ではなくちゃんと根底から学びたい人には超オススメというか、やらない理由を教えてくれ。1.人に教える道具としてプログラミングが使え るようになる。言語が単なる道具になる。 2.NO②を使って試してみる、NO①で作った物からいじり方を考える 3.解説あっての練習_system.out.println()の設定 ・javaの入出力の勉強 4 プログラムのバグは悪くない、そのバグは必ず意味がある、じゃないと書けない。高校の見方しか出来ない。 5 数字コード「文字コード」を理解する 6</pre> <p>見比べるとこっちのがはてな匿名ダイアリーっぽい(諸説ある)。</p> <h2 id="チューニングなし">チューニングなし</h2> <blockquote><p>我が家のインドカレー</p> <p>インドカレーは、我が家の定番料理です。母はインドの友人から学んだ本格的なレシピで作るので、香り高いスパイスと豊かな味わいが特徴です。</p></blockquote> <h2 id="チューニングあり">チューニングあり</h2> <blockquote><p>我が家のインドカレー</p> <p>インド料理を美味しく頂くのはもちろんだが、カレールウを自作することが我々日本人にとってもっとも適した消費の仕方であり、肝要である。原因は3つ考えられる。</p></blockquote> <h2 id="ジョブの実行部分">ジョブの実行部分</h2> <pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> openai resp = openai.File.create( <span class="synIdentifier">file</span>=<span class="synIdentifier">open</span>(<span class="synConstant">&quot;dataset.jsonl&quot;</span>, <span class="synConstant">&quot;rb&quot;</span>), purpose=<span class="synConstant">'fine-tune'</span> ) <span class="synIdentifier">print</span>(resp) job = openai.FineTuningJob.create(training_file=resp.id, model=<span class="synConstant">&quot;gpt-3.5-turbo&quot;</span>) <span class="synIdentifier">print</span>(job) </pre> <div class="footnote"> <p class="footnote"><a href="#fn-3f8f0490" name="f-3f8f0490" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://twitter.com/laiso/status/1668598072279175169">https://twitter.com/laiso/status/1668598072279175169</a></span></p> </div> laiso [アクションが必要]AWS Lambda Go 1.x ランタイム終了を時系列理解 hatenablog://entry/820878482962113773 2023-08-27T15:08:20+09:00 2023-08-28T12:23:54+09:00 Go 1.x ランタイムでデプロイしたLambdaがあるとこういうメールが来る。 Amazon Linux AMI のメンテナンスサポートが 2023 年 12 月 31 日に終了するのに合わせて、AWS Lambda での Go 1.x ランタイムのサポートを終了します [1]。 Lambda は、provided.al2 ランタイムを使用して Go プログラミング言語を引き続きサポートします。 provided.al2 ランタイムを使用すると、AWS Graviton2 プロセッサのサポートや、より小さなデプロイパッケージとより高速な関数呼び出しパスによる効率的な実装など、go1.x ラン… <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20230827/20230827144525.png" width="1698" height="822" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>Go 1.x ランタイムでデプロイしたLambdaがあるとこういうメールが来る。</p> <blockquote><p>Amazon Linux AMI のメンテナンスサポートが 2023 年 12 月 31 日に終了するのに合わせて、AWS Lambda での Go 1.x ランタイムのサポートを終了します [1]。</p> <p>Lambda は、provided.al2 ランタイムを使用して Go プログラミング言語を引き続きサポートします。</p> <p>provided.al2 ランタイムを使用すると、AWS Graviton2 プロセッサのサポートや、より小さなデプロイパッケージとより高速な関数呼び出しパスによる効率的な実装など、go1.x ランタイムに比べていくつかの利点があります。</p> <p>詳細については、ブログ記事 [2] を参照してください。</p></blockquote> <h2 id="QGo対応のプライオリティが下げられたのか">Q:「Go対応のプライオリティが下げられたのか」</h2> <p>ちょっとニュアンスが違う。</p> <p><a href="https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-runtimes.html">Lambdaランタイム 一覧</a>にあるとうりLambdaはarm64やAmazon Linux 2サポートが進行していて、Javaや.NET、スクリプト言語などのシステム依存の割合が比較的大きい環境のが優先されている。</p> <p>Goはカスタムランタイム以前にサポートされたので専用ランタイムが存在しているが、たとえばシステム依存の少ないワンバイナリを作れるRustなども専用ランタイムはない<a href="#f-8a9d8212" name="fn-8a9d8212" title="カスタムランタイム版はある https://github.com/awslabs/aws-lambda-rust-runtime">*1</a>。</p> <p>なのでより正確な文脈としてはFaaSやサーバーレスサービス全般の(Dockerに限らない)コンテナネイティブなアーキテクチャへの移行という意味になると思う。</p> <p>現在はウェブアプリケーション向けのソースコードからAmazon Linuxベースのイメージを生成する<a href="https://docs.aws.amazon.com/apprunner/latest/dg/service-source-code.html">App Runner</a>の基盤もあるし、GoogleのCloud Functions も2nd genになってCloud Runが基盤になっている。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ffirebase.google.com%2Fdocs%2Ffunctions%2Fversion-comparison" title="Cloud Functions version comparison  |  Cloud Functions for Firebase" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://firebase.google.com/docs/functions/version-comparison">firebase.google.com</a></cite></p> <h1 id="時系列">時系列</h1> <p>2017年末にAmazon Linux 2 LTS Candidateが公開。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Faws.amazon.com%2Fjp%2Fabout-aws%2Fwhats-new%2F2017%2F12%2Fintroducing-amazon-linux-2%2F" title="Amazon Linux 2 のご紹介" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://aws.amazon.com/jp/about-aws/whats-new/2017/12/introducing-amazon-linux-2/">aws.amazon.com</a></cite></p> <p>2018年1月にAWS LambdaのGoサポートが追加。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Faws.amazon.com%2Fjp%2Fblogs%2Fcompute%2Fannouncing-go-support-for-aws-lambda%2F" title="Announcing Go Support for AWS Lambda | Amazon Web Services" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://aws.amazon.com/jp/blogs/compute/announcing-go-support-for-aws-lambda/">aws.amazon.com</a></cite></p> <p>2018年11月にAmazon Linux 2を使ったカスタムランタイムが公開。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Faws.amazon.com%2Fjp%2Fblogs%2Faws%2Fnew-for-aws-lambda-use-any-programming-language-and-share-common-components%2F" title="New for AWS Lambda – Use Any Programming Language and Share Common Components | Amazon Web Services" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://aws.amazon.com/jp/blogs/aws/new-for-aws-lambda-use-any-programming-language-and-share-common-components/">aws.amazon.com</a></cite></p> <p>2020年1月にAmazon Linux AMI(2じゃないやつ)のサポート期間が2020年6月30日から2023年6月30日まで延長。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fdev.classmethod.jp%2Farticles%2Fupdate-on-amazon-linux-ami-end-of-life%2F" title="Amazon Linux のサポート期間延長のアナウンスについて | DevelopersIO" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://dev.classmethod.jp/articles/update-on-amazon-linux-ami-end-of-life/">dev.classmethod.jp</a></cite></p> <p>2020年1月の<a href="https://aws.amazon.com/jp/blogs/database/building-enterprise-applications-using-amazon-dynamodb-aws-lambda-and-golang/">Building enterprise applications using Amazon DynamoDB, AWS Lambda, and Go | AWS Database Blog</a>が書かれた時点ではサンプルコードにGo 1.x ランタイムが指定されている<a href="#f-7e19e34a" name="fn-7e19e34a" title="https://github.com/aws-samples/aws-dynamodb-enterprise-application/blob/master/cloud-infra-demo/lib/cloud-infra-demo-stack.ts">*2</a>。</p> <p>2020年6月のコミットでカスタムランタイムを指定してaws-lambda-goで書いた関数をデプロイ可能になった。</p> <p><a href="https://github.com/aws/aws-lambda-go/pull/298">https://github.com/aws/aws-lambda-go/pull/298</a></p> <p>2020年9月の公式ドキュメント<a href="http://web.archive.org/web/20200910170422/https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/golang-package.html">Go の AWS Lambda デプロイパッケージ - AWS Lambda</a>ではGo 1.x ランタイムが指定されている。</p> <p>2022年4月頃のドキュメント<a href="http://web.archive.org/web/20220402080043/https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/golang-package.html">.zip ファイルアーカイブを使用して Go Lambda 関数をデプロイする - AWS Lambda</a>の最後にprovided.al2 ランタイムのオプションが登場。</p> <hr /> <p>これ以降英語ドキュメントの方の経過を見ていった方がいいのではと思ったので切り換え。</p> <p>2023年1月の<a href="http://web.archive.org/web/20230113101206/https://docs.aws.amazon.com/lambda/latest/dg/lambda-golang.html">Building Lambda functions with Go - AWS Lambda</a>ではまだGo 1.x ランタイムのみが記述。</p> <p>2023年6月 <a href="http://web.archive.org/web/20230608194059/https://docs.aws.amazon.com/lambda/latest/dg/lambda-golang.html">Building Lambda functions with Go - AWS Lambda</a> になかった</p> <blockquote><p>Go is implemented differently than other managed runtimes. Because Go compiles to native code, Lambda treats Go as a custom runtime. We recommend that you use the provided.al2 runtime to deploy Go functions to Lambda.</p></blockquote> <p>2023年8月には追加されている。</p> <h1 id="まとめ">まとめ</h1> <ul> <li>Go 1.x ランタイムはAmazon Linux AMIと共にしばらく延命されていたが最近までドキュメントから流入は起きていた</li> <li>アクションが必要</li> </ul> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Faws.amazon.com%2Fjp%2Fblogs%2Fcompute%2Fmigrating-aws-lambda-functions-from-the-go1-x-runtime-to-the-custom-runtime-on-amazon-linux-2%2F" title="Migrating AWS Lambda functions from the Go1.x runtime to the custom runtime on Amazon Linux 2 | Amazon Web Services" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://aws.amazon.com/jp/blogs/compute/migrating-aws-lambda-functions-from-the-go1-x-runtime-to-the-custom-runtime-on-amazon-linux-2/">aws.amazon.com</a></cite></p> <div class="footnote"> <p class="footnote"><a href="#fn-8a9d8212" name="f-8a9d8212" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">カスタムランタイム版はある <a href="https://github.com/awslabs/aws-lambda-rust-runtime">https://github.com/awslabs/aws-lambda-rust-runtime</a></span></p> <p class="footnote"><a href="#fn-7e19e34a" name="f-7e19e34a" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://github.com/aws-samples/aws-dynamodb-enterprise-application/blob/master/cloud-infra-demo/lib/cloud-infra-demo-stack.ts">https://github.com/aws-samples/aws-dynamodb-enterprise-application/blob/master/cloud-infra-demo/lib/cloud-infra-demo-stack.ts</a></span></p> </div> laiso 記事の有料販売のテスト hatenablog://entry/820878482953490803 2023-07-28T19:51:10+09:00 2023-07-28T19:56:15+09:00 以下はラオスで撮った仏像の写真です。 <p>以下は<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%E9%A5%AA%A5%B9">ラオス</a>で撮った仏像の写真です。</p> laiso オライリー本が買えない話その後 hatenablog://entry/820878482953458012 2023-07-28T17:16:13+09:00 2023-10-28T15:15:17+09:00 UPDATE: PayPalアカウントがなくてもオライリー本は買える(確信) - laiso PayPalアカウントがないとオライリー本買えなくて不便で国がPayPal利用を遮断してしまったのでオライリージャパンの本が買えないという話をしていたのだけど現在は諦めてUSのOnline Learning with O'Reillyを購読してる。 laiso.hatenablog.com O'Reilly Japan, Inc.の新着を毎週見てると定期的に新刊を配信してくれているみたいだしオライリージャパンには感謝している。 先のポストをした直後に『WEB+DB PRESS』 休刊のお知らせなんかも… <p><ins>UPDATE: <a href="https://laiso.hatenablog.com/entry/2023/10/28/151426">PayPalアカウントがなくてもオライリー本は買える(確信) - laiso</a></ins></p> <p><a href="https://laiso.hatenablog.com/entry/for-tim">PayPalアカウントがないとオライリー本買えなくて不便</a>で国がPayPal利用を遮断してしまったのでオライリージャパンの本が買えないという話をしていたのだけど現在は諦めてUSの<a href="https://www.oreilly.com/online-learning/individuals.html">Online Learning with O'Reilly</a>を購読してる。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2Ffor-tim" title="PayPalアカウントがないとオライリー本買えなくて不便 - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/for-tim">laiso.hatenablog.com</a></cite></p> <p><a href="https://learning.oreilly.com/publisher/oreilly-japan-inc/">O'Reilly Japan, Inc.</a>の新着を毎週見てると定期的に新刊を配信してくれているみたいだしオライリージャパンには感謝している。</p> <p>先のポストをした直後に<a href="https://gihyo.jp/magazine/wdpress/suspended">『WEB+DB PRESS』 休刊のお知らせ</a>なんかもあったりして、むしろ日本語で技術書発刊してるだけでえらい! という気持ちになってしまった。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgihyo.jp%2Fmagazine%2Fwdpress%2Fsuspended" title="『WEB+DB PRESS』 休刊のお知らせ:WEB+DB PRESS" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://gihyo.jp/magazine/wdpress/suspended">gihyo.jp</a></cite></p> <p>ちょっと困っているのが技術評論社のタイトルで、<a href="https://gihyo.jp/dp">Gihyo Digital Publishing</a>からDRMフリーのePubが入手できるのでそれをPlay Booksのtext-to-speechで読んでいたのがPayPal遮断によって購入できなくなってしまった。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fsupport.google.com%2Fgoogleplay%2Fanswer%2F11938821%3Fhl%3Den%26co%3DGENIE.Platform%253DAndroid" title="Hear books read out loud on Google Play Books - Android - Google Play Help" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://support.google.com/googleplay/answer/11938821?hl=en&co=GENIE.Platform%3DAndroid">support.google.com</a></cite></p> <p><a href="https://play.google.com/store/books">Books on Google Play</a>に電子版を配信してあればこの問題を回避できるんだけど技術評論社はなぜかKindleや他の日本のプラットフォームまでしか配信していない。</p> <p>最悪紙本を通販で輸入して入手すればいいやと思いつつもオライリー本買うために一旦引越ししてPayPalをアクティベーションするかとか倒錯的なことも考えた上でとくに何もしていない感じ。</p> laiso ChatGPTのCustom Instructionsはシステムメッセージに設定されるっぽい hatenablog://entry/820878482951576330 2023-07-21T14:19:13+09:00 2023-07-21T14:19:13+09:00 ChatGPTのインターフェイスではなくOpenAI APIやPlaygroundを使う利点として「システムメッセージを設定できる」と言っていたが、Custom instructionsによってシステムメッセージがChatGPTからも利用できるようになった。 The system message helps set the behavior of the assistant. For example, you can modify the personality of the assistant or provide specific instructions about how it sho… <p>ChatGPTの<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A1%BC%A5%D5%A5%A7%A5%A4%A5%B9">インターフェイス</a>ではなくOpenAI <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a>や<a href="https://platform.openai.com/playground?mode=chat">Playground</a>を使う利点として「システムメッセージを設定できる」と言っていたが、<a href="https://openai.com/blog/custom-instructions-for-chatgpt">Custom instructions</a>によってシステムメッセージがChatGPTからも利用できるようになった。</p> <blockquote><p>The system message helps set the behavior of the assistant. For example, you can modify the personality of the assistant or provide specific instructions about how it should behave throughout the conversation. However note that the system message is optional and the model’s behavior without a system message is likely to be similar to using a generic message such as "You are a helpful assistant." <a href="https://platform.openai.com/docs/guides/gpt/chat-completions-api">https://platform.openai.com/docs/guides/gpt/chat-completions-api</a></p></blockquote> <h1 id="Socratic-tutor">Socratic tutor</h1> <p>GPT-4の<a href="https://openai.com/research/gpt-4">Socratic tutor</a>サンプルでは「問題の答えではなく解き方を教える」という制御をシステムメッセージで行っている。それをCustom Instructions+GPT-3.5でも試してみた。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fchat.openai.com%2Fshare%2Faeb63059-68c6-455a-b50b-b186b5485e76" title="Socratic tutor with Custom Instructions" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://chat.openai.com/share/aeb63059-68c6-455a-b50b-b186b5485e76">chat.openai.com</a></cite></p> <p>これをCustom Instructionsではなくユーザーの会話メッセージとして入れるようにすると、答えを教えてくれる。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fchat.openai.com%2Fshare%2F85445077-ecbe-49c0-a823-711a63b42722" title="Socratic tutor without Custom Instructions" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://chat.openai.com/share/85445077-ecbe-49c0-a823-711a63b42722">chat.openai.com</a></cite></p> <h1 id="あなたは猿ですか">あなたは猿ですか?</h1> <p>以下はCustom Instructionsで設定した猿設定がどのように変化するのかを未設定時と比較した。Custom Instructionsの例では猿設定が維持されていたので「システムメッセージに設定される」と推測した。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fchat.openai.com%2Fshare%2F8d87e2bd-e3d1-4380-85bd-a7c6b400a882" title="Custom Instructionsに入れた猿設定を会話で上書きできるのか?" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://chat.openai.com/share/8d87e2bd-e3d1-4380-85bd-a7c6b400a882">chat.openai.com</a></cite></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fchat.openai.com%2Fshare%2Fc331689d-4a75-4579-a853-81c345937ac4" title="Custom Instructionsに猿設定を入れずに会話" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://chat.openai.com/share/c331689d-4a75-4579-a853-81c345937ac4">chat.openai.com</a></cite></p> laiso ChatGPTのCode Interpreterのコードリーディング能力は結構優秀 hatenablog://entry/820878482950241494 2023-07-16T12:32:14+09:00 2023-08-19T13:44:07+09:00 Code interpreter のキラーソリューションは表データの可視化っぽいけど、入力テキストとファイルソースによってテキスト生成とファイル出力ができるという点に着目すると色々活用の幅が広がる。 中でも、今までは入出力トークンに含まれる必要があったソースコードデータを外部ファイル化できるので、「リポジトリを丸ごと食わせる」などの従来トークン制限上実現できなかったことが外部システム連携なしで簡単に可能になったのが嬉しいポイントだった。 この特性を生かして最近OSSの静的コード解析というかコードリーディングをChatGPTにやってもらっている。 以下のサンプルでは脆弱性診実習用アプリ(通称「や… <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/laiso/20230819/20230819134331.jpg" width="1372" height="710" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p><a href="https://openai.com/blog/chatgpt-plugins#code-interpreter">Code interpreter</a> のキラーソリューションは表データの可視化っぽいけど、入力テキストとファイルソースによってテキスト生成とファイル出力ができるという点に着目すると色々活用の幅が広がる。</p> <p>中でも、今までは入出力トークンに含まれる必要があったソースコードデータを外部ファイル化できるので、「リポジトリを丸ごと食わせる」などの従来トークン制限上実現できなかったことが外部システム連携なしで簡単に可能になったのが嬉しいポイントだった。</p> <p>この特性を生かして最近OSSの静的コード解析というかコードリーディングをChatGPTにやってもらっている。</p> <p>以下のサンプルでは<a href="https://github.com/ockeghem/badtodo">脆弱性診実習用アプリ(通称「やられサイト」)</a>のSQLインジェクションを発見してもらうという会話をした。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fchat.openai.com%2Fshare%2F24c72a33-8d94-458f-8f14-8c7125bc662a" title="やられサイトリポジトリの脆弱性を探索" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://chat.openai.com/share/24c72a33-8d94-458f-8f14-8c7125bc662a">chat.openai.com</a></cite></p> <p>以下では<a href="https://github.com/kubernetes-sigs/aws-load-balancer-controller">aws-load-balancer-controller</a> や <a href="https://github.com/coderabbitai/openai-pr-reviewer">openai-pr-reviewer</a>というOSSを使うにあたって実装を調べたかったので質問をした。これを元に実際のファイルを読んだところ理解が進んだ。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fchat.openai.com%2Fshare%2Fd656dc41-5085-4f2e-a017-bb33725fe728" title="アーキテクチャ解説: aws-load-balancer-controller" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://chat.openai.com/share/d656dc41-5085-4f2e-a017-bb33725fe728">chat.openai.com</a></cite></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fchat.openai.com%2Fshare%2F2333133b-9872-406a-b858-f4b6bd5dce16" title="openai-pr-reviewerの実装解説" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://chat.openai.com/share/2333133b-9872-406a-b858-f4b6bd5dce16">chat.openai.com</a></cite></p> <p>コード読めるならたぶん書けるよねということを思っていて、以下の記事では仕様書を渡してzipでコードを納品してもらうという実験をされている</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fnote.com%2Fbbz662bbz%2Fn%2Fn7c9b620cd8f0" title="なんかいけそうな気がしたので Code Interpreter でシュッと Web アプリつくってもろた|bbz" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://note.com/bbz662bbz/n/n7c9b620cd8f0">note.com</a></cite></p> <p>出力をパッチやプルリクエスト中間形式にしたりするとさらに拡張できそう。以前の記事で書いたようにGPTを使った自動プログラミングに関心があるのでAPIが使えるようになったら更に色々実験してみたい。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flaiso.hatenablog.com%2Fentry%2F2023%2F04%2F09%2Fgpgpt" title="GPTでソースコードからpatchを生成し続けたらプログラミングを自動化できるのでは???? - laiso" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://laiso.hatenablog.com/entry/2023/04/09/gpgpt">laiso.hatenablog.com</a></cite></p> laiso