/home/by-natures/dev*

データ界隈で働くエンジニアとしての技術的なメモと、たまに普通の日記。

2025/06/23 ベトナム/マレーシア旅行

働く環境を変えることにし、有休消化で6月頭に1週間ほど海外旅行に行っていました。

久しぶりに一人で海外旅行しようと決めて、どこに行こうかしばらく悩んでいましたが、昔友人がお勧めしてくれたベトナムのダナンとホイアン、そして全く詳しくないマレーシアのクアラルンプールとマラッカに行ってみることにしました。一人だとあまり予定を詰め込まず、好きなものを見て食べて、疲れたらホテルに戻って昼寝したりして、自由気ままな1週間でした。

楽しくてお土産の量がすごいことに

ベトナム

ダナンのビーチ

ミシュランレストラン Bep Hen

ホイアン近郊のカフェ

ホイアンのランタン

ダナンは(ベトナムならではの交通量の多さに目をつぶれば)ホテルの目の前が綺麗なビーチでワイキキを思わせるようなリゾートでした。ベトナムらしい屋台も多いですが、少し路地に入るとおしゃれなカフェや創作料理屋も多くて歩いているだけでも楽しかったです。日夜問わず盛り上がっていて、東南アジアらしい夜の煌びやかでド派手なネオンを見たり、ビーチでただ本を読んだりしました。ベトナムは3回目なのですが10年以上ぶりで、バイクや車のクラクションも懐かしい気持ちを味わえました。

ダナンから1時間ほどにあるホイアンという港町にも行きました。ベトナムはフォーやブンと一緒に大量のハーブを食べるのですが、そのハーブを栽培している田園エリアでご飯を食べました。ハーブの味が濃くて今回の旅行で一番美味しかったです。夜は有名なランタンを見ましたが、日本で言うと都心部の夏祭りぐらいの勢いで人がおり、これが毎夜繰り返されているのかと思うと圧倒されてしまいます。お土産屋さんの店員さんと少し話しましたが、その人はホイアン生まれでホーチミンに就職したものの、交通量の多さに耐えられずにホイアンに戻ってきたそうです。私からするとホイアンも十分すごい人と交通量ですが、ベトナム人でもホーチミンの喧騒はやかましいと思っているのだと知ることができました。

マレーシア

マレーシアのニョニャ料理

クアラルンプールのブキッビンタン

ペトロナスツインタワー

マラッカ海峡モスク

マレーシアは私にとって初めてのイスラム国家でした。タイやシンガポールに隣接していますがどちらの国とも違った雰囲気で、ムスリムがいる一方で現地中国人や旅行客の白人/中国人も多く、まさに人種の坩堝だと感じました。その人種の多さゆえかあまり厳格な雰囲気はなく、旅行中も特に危ないことにも合わず、ベトナムとおなじように観光することができました。

タクシーの運転手が色々話してくれたのですが、その人は "Local Chinese" だと言っていました。クアラルンプールで生まれた中国人で、今もクアラルンプールに住んで仕事をしているようです。もちろん個人差はありますが、一般的な中国人のイメージよりは遥かにおおらかで、中国人というよりは南国の陽気なおじさんという感じでした。中国語で話しかけたらやたら褒めてくれて嬉しかったです。最近は英語だけでなく中国語もスキマ時間に Duolingo で復習しているのですが、料理を注文したり、タクシーの運転手と簡単な会話をする程度は使えたので、数年以内に中国本土にももう一度行ってみたいなと思います。

クアラルンプールからバスで2時間行くとマラッカに着きます。マラッカも港町ですが、15世紀に存在したマラッカ王国の歴史を学んだり、その後侵略してきた西欧の文化遺産が残るなど、小さな街ですが歴史の厚みを感じられる街でした。

港町/歴史

今回の旅はベトナムもマレーシアも港町が多く、中国、西欧そして大日本帝国時代の日本の史跡を感じられました。私は歴史の授業が苦手で、テストが終わった直後に頭から抜けてしまうタイプだったのですが、実際に自分で足を運んで見聞きした街や文化を歴史を通じて学ぶのは面白さが格別でした。ダナンとクアラルンプールの歴史博物館では食い入るように説明文を読み、展示品を楽しむことができました。

飛行機で5時間ほどでダナンにつき、そこから2時間ほどでクアラルンプールに着くのですが、大日本帝国の影響がそこまで及んでいたと考えると、当時の日本の影響力は凄まじかったのだろうと想像します。

大日本帝国による太平洋戦争中の日本軍の最大勢力範囲。大きすぎる…

ホイアンもマラッカも海上交通の要所で、ホイアンでは日本の商人が数百人規模で移住して貿易を行っていたそうです。また同じ港町マラッカでは日本の商人がフランシスコ・ザビエルと出会い、日本をぜひ訪れるべきだと進言したそうです。アジアにキリスト教を伝えた人というのはなんとなく覚えていましたが、自分の訪れた土地で数百年前にそんなやりとりがあってから実際に鹿児島に訪れたと知り、地球規模での歴史を肌身で感じることができました。

エッセンシャル思考

旅行中に一冊本を読むことが多いんですが、今回の旅行のお供は「エッセンシャル思考」でした。

現職では業務の優先度やタスク量に悩まされることが多く、Kindle に入っていたこの本が目に入って旅行中に読み耽っていました。次はこの本について記事を書きます。

2025/02/18 Flux 触ってみる(GitOps)

Flux という GitOps を実現するためのツールがあると知り、触って見たかったのでデータエンジニアもくもく会の時間を利用して触って見ました。

この辺りは前の現場までだと自分が直接触ることが無かったのでデータエンジニアリング領域とはあまり関係ないなと思っていたのですが、今の環境だと OSS 製品を安定して動かすことが求められており、データエンジニアリングが改めて総力戦だと実感しています。どうしたらデータ基盤を安定運用できるか考えており、いろんな方に聞きながら勉強していますが、GitOps も昨年知って勉強中です。

GitOps だと ArgoCD が有名だと思うのですが、データ領域で動かすにはちょっと過剰じゃないかとぼんやり思っていたので、CLIベースの軽量な Flux がもしかしたら適切かもと思っています。特に Flux は Helm のようなパッケージ化されたアプリケーションをデプロイ管理するのに適しているようで、Helm を使って Prefect, Airbyte をデプロイしている今の環境にもマッチしていそうです。まだ本格的な検証をしてはいませんが、他の GitOps 製品も比較しながら導入検討していきます。

チュートリアルをやってみる

fluxcd.io

Github アカウントに加えて Kubernetes 環境が必要です。私は colima でローカル環境で動かしています:

$ colima start --cpu 8 --memory 12 --disk 160 --kubernetes --network-address 

詳しくはこちらをどうぞ:

bynatures.hatenadiary.jp

Flux をインストール

Github トークンはこちらのページを参考にして、Github から設定できます。トークンの権限としては Codespaces, Contents, Metadata を追加しました。 個人用アクセス トークンを管理する - GitHub Docs

$ brew install fluxcd/tap/flux $ export GITHUB_TOKEN=<your-token> $ export GITHUB_USER=<your-username> 

flux check の結果、kubernetes が認識されていて Flux が動かせることが確認できました:

$ flux check --pre ► checking prerequisites ✔ Kubernetes 1.30.0+k3s1 >=1.28.0-0 ✔ prerequisites checks passed 

Github と接続

あらかじめ動作確認用のリポジトリとして fleet-infra を用意し、clone してリポジトリ配下に移動しておきます。このリポジトリに更新があれば、Flux が検知して Kubernetes 上に設定反映してくれるという仕組みです。

$ flux bootstrap github --token-auth --owner=$GITHUB_USER --repository=fleet-infra --branch=main --path=clusters/my-cluster --personal ... ► confirming components are healthy ✔ helm-controller: deployment ready ✔ kustomize-controller: deployment ready ✔ notification-controller: deployment ready ✔ source-controller: deployment ready ✔ all components are healthy 

Kuberenetes クラスタの上に、Flux の Pod がデプロイされました:

$ kubectl get pod -n flux-system NAME READY STATUS RESTARTS AGE helm-controller-6f558f6c5d-x7xxv 1/1 Running 0 27s source-controller-6d597849c8-p592g 1/1 Running 0 27s kustomize-controller-74fb56995-2mwz4 1/1 Running 0 27s notification-controller-5d794dd575-l7dnf 1/1 Running 0 27s 

アプリケーションを追加

サンプルアプリケーションを fleet-infra に追加し、Flux に起動してもらいます。まずはアプリケーションのソースを追加します:

$ mkdir -p ./clusters/my-cluster $ flux create source git podinfo \ --url=https://github.com/stefanprodan/podinfo \ --branch=master \ --interval=1m \ --export > ./clusters/my-cluster/podinfo-source.yaml 

podinfo-source.yaml というマニフェストが生成されるので、コミット&プッシュすると、ポーリングしている Flux がファイルを検知してマニフェストを適用してくれます:

$ flux get sources all NAME REVISION SUSPENDED READY MESSAGE gitrepository/podinfo master@sha1:b99bf8c2 False True stored artifact for revision 'master@sha1:b99bf8c2' gitrepository/flux-system main@sha1:2ff5f9dc False True stored artifact for revision 'main@sha1:2ff5f9dc' 

ソースの追加ができたので、アプリケーションを追加します:

$ flux create kustomization podinfo \ --target-namespace=default \ --source=podinfo \ --path="./kustomize" \ --prune=true \ --wait=true \ --interval=30m \ --retry-interval=2m \ --health-check-timeout=3m \ --export > ./clusters/my-cluster/podinfo-kustomization.yaml 

生成された podinfo-kustomization.yaml をコミット&プッシュすると、podinfo のアプリケーションが Flux によってデプロイされます:

$ kubectl -n default get deployments,services NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/dbt-sample-domain 0/1 0 0 188d deployment.apps/podinfo 2/2 2 2 32s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 230d service/podinfo ClusterIP 10.43.9.183 <none> 9898/TCP,9999/TCP 32s 

サービスがあるので 9898 に繋いでみると、アプリケーションの起動が確認できます:

$ kubectl port-forward svc/podinfo 9898:9898 -n default Forwarding from 127.0.0.1:9898 -> 9898 Forwarding from [::1]:9898 -> 9898 

Podinfo サンプルアプリケーションが Flux によってデプロイされました

2025/02/05 DataOps Night #6 で発表しました

先日、ナウキャストさん主催のデータ系のイベント、DataOps Night #6 でお話させていただきました。

finatext.connpass.com

www.youtube.com

speakerdeck.com

テーマ決めの経緯

テーマが DataOps ということで、データ品質周りの話として GreatExpectations を絡めた話をしたら面白いだろうなと思っていたのですが、私の今の業務が新基盤の構築で利用フェーズはこれからというタイミングでして、運用フェーズの話ができないと聞く方も面白くないだろうと考え直し、直前にテーマ変更させていただきました。

結果として、DataOps というよりは、ユーザの課題を解決する基盤構築をしようという私の実業務に近い話をすることにしました。2年に渡る基盤構築プロジェクトの途中から参画した立場で、社内でもプロジェクトの立場によって考え方や見えている景色が違うだろうなという中での発表だったので不安もありましたが、いちエンジニア目線でどうシステムを改善しようとしてきたかを伝えられたので、自分としてはよかったかなと思います。事前に上司の承認は得ましたが、この発表で許可出していただいて恐縮の限りです。。

内容としては以前書いたブログの肉付けという感じなので、こちらも良かったらご覧ください:

bynatures.hatenadiary.jp

今回 あまりテーマに沿ったお話ができなかったのですが、発表自体はいろいろコメントや感想いただけたので嬉しかったです。次回はデータ品質周りの話ができるように、データ活用の成熟度とともに基盤も成長させていきたいなと改めて感じました。

感想

懇親会やXのポストなどでいろんな方からコメントをいただくことが出来ましたが、Prefect や Airbyte の使い心地など個別のツールのお話や、プロジェクトの進め方についてのお話なども共感をいただくことができ、他の環境でも同様に悩んでいる方がいらっしゃるんだと知ることが出来ました。

一緒に発表させていただいたナウキャストさんは事業の拡大にともなってアーキテクチャの構成を見直してデータメッシュを意識した構成にされていたり、課題解決のために SELECT や OpenMetadata の導入を検討されているなど、データエンジニアとして非常に面白そうなトピックばかりでした。

estie さんからも不動産領域でのデータ品質という課題で、事業的にも名寄せが非常に重要で、名寄せのアルゴリズムに対して社内コンペが開かれているなど、技術トピックだけでなく estie さんの社風も感じられる面白い発表でした。まだご覧になっていないかたは、下のイベントページから資料は見れますし、Youtube ライブも残っているのでぜひご覧ください。

私の発表に対して感想やコメントなどあれば、ぜひいただけたら嬉しいです(XのリプやDMなど何でも構いません)。

会場をお貸しいただいたナウキャストさん、また運営の方々も皆様ありがとうございました!

2025/01/13 入社してからの話(データ基盤開発・運用)

少し遅れましたが、あけましておめでとうございます。今年もよろしくお願いいたします。

2024年は仕事も私生活も本当にいろんなことがあって非常に濃い1年でした。体感としては3年分ぐらい生きた感じがします。

現職に転職したのが2024年6月なので、まだ半年ほどしかいないのですが、メンバーからは私が「数年ぐらいいる気がする」と言ってもらえるぐらい馴染んでいるようです。出社頻度も他の方に比べると高めていたし、化粧品業界自体も興味があって製品知識は豊富なので業務も業界も楽しめています。

宣伝:データエンジニア向けのもくもく会

データエンジニア向けのもくもく会を毎週月曜日 19:00-20:00 に実施しています。 当日に私のXアカウントで告知しているので、よければ気軽にご参加ください。

もくもく会について書いた記事:

bynatures.hatenadiary.jp

入社してからの話(データ基盤開発・運用)

色々書きたいことはあるんですが、会社から許可をもらっていないので書ける範囲で書きます。2025年2月の DataOps Night での対外発表も予定していますが、似たような話をするかもしれません。

DataOps Night #6 - connpass

今開発しているデータ基盤は、私が2024年6月に入社したタイミングではすでに一部運用が始まっていたのですが、2024年後半はこの基盤の改善に尽力した半年でした。Google Cloud を触るのも久しぶりでしたし、GKE 中心の運用だったので仮想環境上でのアプリケーション構築もあまり知見がなく、入社直後はキャッチアップと技術面の習得に必死でした。

ブランチ戦略やリリースフローの見直しも数ヶ月かけて行い、手動リリースばかりだったリリースフローがほぼ全て自動リリースできるようになりました。チームビルディングにも気を配ったのでだいぶ良いチームになったと思います。チームメンバーからは「チームの雰囲気が良くなった」「見事に立て直した」とも言ってもらえました。ここまで言ってもらえると感無量です。

GKE 上のアプリケーションも冗長構成が取れるようになり、ようやく安定稼働するようになりました。メンバーから冗長構成を提案してもらい、数ヶ月かけて検証したものだったので、リリースが完了した時は大きな仕事をやり遂げた感覚でした。

夜間バッチあるあるですが、日が変わってから動き出すバッチが動くか心配で寝る前に確認したり、バグがあると修正して朝になっていたりという日も何度かありました。ただあんまり辛くはなくて、むしろ楽しいというか、責任感というか…。普段はPM業務が多いので、バグ修正だと手を動かす楽しさもあるし、今のチームは協力会社の方が多くてリリースの責任は私にあるので、私がしっかり動くようにしないといけないという気概で頑張っていました。

大きなリリースが終わった日、夜のバッチが正常に動いているのを見たときには込み上げるものがあり、涙した日もありました。肩の荷が降りた感覚だったかもしれません。(単純に深夜で疲れてたのもありますが)

伝わる人も多いんじゃないかと思うんですが、正常稼働しているシステムって美しいと思いませんか?設計通りとはいえ処理が行われたりDBに書き込まれたり、Podが立ち上がったりkillされたり…。生き物みたいだなと感じるときがたまにあります。特に今回は私が開発した部分はほとんどなくて、大まかな設計だけしてメンバーの方に実装をお願いすることが多かったので、メンバー協力のもと一つのシステムを作り上げた、という感覚を社会人人生の中で一番感じました。

今作っている基盤は新しい基盤なので、これからデータを増やし、ユーザに使ってもらえるよう案内しないといけません。ここは開発チーム以外の協力が不可欠なので、また働き方が大きく変わりそうです。基盤自体も元々私が設計したものではないので、これからさらに機能拡張させていく場合も意識を変えないといけません。どちらにしても、2025年もまだまだ試行錯誤が必要になりそうです。

2024/12/03 データエンジニアもくもく会を1年続けた学び

datatech-jp Advent Calendar 2024 3日目の記事を書きます!

毎週月曜日にデータエンジニア向けのもくもく会をXで(以前は datatech-jp で)実施しており、約1年続けてみてどのような学びがあったかをまとめたいと思います。

データエンジニア向けのもくもく会を始めたきっかけ

下のブログ記事でもくもく会を始めたきっかけを簡単に書いたのですが、今日は当時の気持ちをもう少し深掘りしたいと思います。

bynatures.hatenadiary.jp

エンジニア全般だと思うのですが、学び続けないとトレンドに置いて行かれてしまうという危機感はみなさんお持ちだと思います。私もそのような一人なのですが、ここ数年はどうも夢中になれる技術というのがなくて、漠然とした焦りのようなものがありました。

新卒社員として働き始めた頃は、分散処理技術の Hadoop というのがあるらしいと知り、先輩たちと一緒に勉強したり論文を読んだり、未知の世界で本当に楽しかったです。2社目でHadoopを使ってデータ基盤を構築・運用している会社に雇ってもらいましたが、そこでも論文の輪読会が盛んでした。難解なものも多かったですし、データ基盤というプロダクトの性質から難しい立ち回りが求められることも多かったですが、同僚や先輩と議論を重ねてシステム開発していくのは、十数年の社会人生活で一番大切な経験として記憶に残っています。

その後、技術トレンドも変化してクラウドDWHが主流になり、一般ユーザにとって Hadoop, Sparkのような分散技術は裏で利用される意識しなくて良いレイヤーになりました。技術自体というよりは、さまざまなツールやサービスを組み合わせてどう課題解決に使うか、という本来エンジニアが課されるべき領域にやっとデータ基盤の技術が追いついたというべきでしょうか。喜ばしいことだと思います。

もくもく会を立ち上げた当初、私はテック系コンサルで勤めており、議論というよりは目の前の課題やタスクをどうこなすかが問われていました。データエンジニアとしては一人でプロジェクトにアサインされることもあり、ダイレクトに技術力と課題解決が求められる環境で緊張感がありました。これはこれで技術研鑽にはよい環境でしたが、私はエンジニア同士が議論し合って良いシステムを作り上げていくのが好きなんだと再確認できました。

他のデータエンジニアとの交流を増やし、学習時間も継続性のある形で確保できないかと思って立ち上げたのが、データエンジニア向けのもくもく会でした。システムを議論しながら作り上げていくというのは転職で事業会社に戻る形で追い求める形となりましたが、これはまた別の機会に話します。

もくもく会の目的

参加者に自己学習していただきながら、副次的に他のデータエンジニアと交流することを目的としました。

もくもく会の運営は、以下の点に気をつけて実施しています:

  • テーマをデータエンジニアリングに限定して、ディスカッションしやすくする
  • 継続的に実施する
    • 数回やるだけなんて誰でもできる、なんでもいいから続けなさいと最初の会社で先輩に教えてもらったことを実践しています。
  • 作業集中する時間と、交流する時間を分ける
    • Zoomなどで繋ぎながらもくもく会されている方もいましたが、私はどうしても他の方の挙動が気になってしまうので、作業時間・共有時間を明確に分けました。

約1年続けてみて

2024年1月から続けて約1年ほどになりました。時間にして大体50時間ぐらいでしょうか。どのような気付き、学びがあったかを書き出してみます。

積ん読消化ができた

分かりやすいところでは積ん読が何冊か消化ができました。

私は技術書を読み始めるまでが腰が重いタイプなので、もくもく会でとりあえず読み始めることができたのはとても良かったです。本の雰囲気が分かれば読むペースが上がったり、気になるところだけつまみ読みするなど、本に適した読み方ができました。

もくもく会中に読んだ本です。どれももくもく会中に全て読んだわけではなく、読み始めるきっかけにしたり、輪読会の準備のために読んだりしていました:

技術検証ができた

転職してからは扱うツールがガラッと変わったので、キャッチアップも兼ねてもくもく会でツールの検証をしたりしていました:

  • Great Expectations
  • Prefect, ControlFlow
  • Airbyte
  • Dify
  • OpenMetadata
  • dbt

書き出してみると業務で使っているツールがほとんどなので、今後は業務で触れていないツールなども触ってみる時間にしたいですが、業務中に間に合わなかった検証作業もできたりしたので有意義な時間でした。

社外の方とコミュニケーションができる

もくもく会を始める前はどんな方が来るのか、私が会を取り仕切ることは出来るのかと少し不安はありましたが、杞憂でした。

参加いただいている方はみなさん親切で、もくもく会で取り上げられたトピックに対して質問したり教えあったりすることができました。読まれている本の共有や技術検証の内容、社内でどういったデータに関する取り組みをされているのかなど、毎回いろんな話が交わされていました。

基本的には私含めて3人程度(多くて4人ぐらい)の日が多く、この程度であれば一人一人が話したり質問する時間も十分取れたかなと思います。もくもく会という形なので各自が取り組んだことをベースに話す形式も気後れせずに話せるので良かったです。

結果的に分かったことですが、「同じ職種の人でもくもく会をする」というのがよいアイデアだったように思えます。じぶんの作業だけでなく、他の人の取り組みも身近なテーマに感じられ、30分の共有時間がディスカッションに発展することも多かったです。仕事上の悩みなども話したりして、ゆるく繋がっている感覚が私は好きでした。

謝辞

立ち上げ当初は datatech-jp で syou6162 さんにも相談し、アドバイスをいただきました。いつもありがとうございます!

よく来てくれる方もいらっしゃって、私自身も勉強の励みになっています。いつも本当にありがとうございます!

来年も同じペースで続けてみようかと思っています。だいたい毎週月曜日19:00からXで行っていますので、もしご興味ある方は気軽にご参加ください。私の Xアカウントhttps://x.com/tendon0 か、ハッシュタグ #de_mokumoku_study を確認してください。

2024/09/11 colima で nodePort に繋ぐには、--network-address オプションをつける

会社の方にお勧めされて「つくって、壊して、直して学ぶ Kubernetes 入門」という本を読んでいます:

実際にコマンドを打ちながら不具合を探ったりして実践的に Kubernetes が学べる本で、概念もコマンドも覚えられるのでとても役立っています。

書籍では Docker Desktop をベースに話が進みますが、私は普段 Colima で Docker 環境を利用しているので、この本でも Colima を使いながら学んでいました。

Chapter6 で Kubernetes Service のタイプとして NodePort が紹介されていますが、Colima では --network-address オプションをつけて Colima を起動させないといけません。

Reachable IP address is not enabled by default due to root privilege and slower startup time.

colima/docs/FAQ.md at main · abiosoft/colima · GitHub

確かに --network-address をつけて colima start すると root 権限が求められ、起動自体にも非常に時間がかかりました(私の環境で15分程度)。

# Kubernetes の環境につなげない $ curl localhost:30599 curl: (52) Empty reply from server $ colima stop # --network-address オプションをつけ、ホストから繋がるようにする $ colima start --cpu 8 --memory 12 --disk 160 --kubernetes --network-address $ kubectl config get-contexts # P.155 kind によって作ったクラスタの設定を利用 $ kubectl apply --filename chapter-06/deployment-hello-server.yaml $ kubectl config use-context kind-kind-nodeport $ kubectl apply --filename chapter-06/service-nodeport.yaml # Service の NodePort に接続成功 $ curl localhost:30599 Hello, world! 

2024/09/10 Prefect の新サービス ControlFlow を触ってみた  

オーケストレーションツール Prefect を開発している Prefect Technologies 社の新サービス、 Control Flow が2024年6月に公開されました:

www.prefect.io

Prefect Server に繋いでチュートリアルは行えましたが、チュートリアル手順だけではつまずく点が多かったので手順を共有します。しかしまだ絶賛開発中なので数ヶ月後にはまた状況が変わっているかもしれません。その場合は参考程度にご覧ください。

インストール手順&チュートリアル

今回はこの手順に沿って、詰まった点を紹介しながら進めます。

Installation & Setup - ControlFlow

インストール

チュートリアルでは pip install -U controflow を実行することになっていますが、今回は不具合の再現性確保のため、2024年9月時点での最新版 0.8.2 をインストールします。仮想環境などは個人の好みもあるので適当に読み替えてください。

$ python -m venv .venv # Python の仮想環境を作る $ source .venv/bin/activate # 仮想環境をアクティベート $ pip install controlflow==0.8.2 # 最新版を入れるだけなら pip install -U controflow で良い 

OpenAI のキー取得&エクスポート

ControlFlow から ChatGPT につなぐため、OpenAI のキー取得とエクスポートを行います。

2024年9月時点で、OpenAI には User API Key(レガシー)と Project API Key が存在しますが、Project API Key では上手くつながらなかったため、User API Key を取得しました。

OpenAI のユーザAPIキー設定画面

また API を使うためには予め予算を登録しておく必要があり、私は $10 程度入れて動かしました。ただチュートリアルをいくつか動かしていますが、少し遊ぶ程度なら $1 でも十分そうです。

Prefect のローカルサーバを起動

ControlFlow は単独で動くものではなく、Prefectにフローを登録する Prefect のラッパーのようなものなので、Prefect Server を起動します(Prefect Cloudでも大丈夫です)

別ウィンドウで Prefect サーバを起動させます:

prefect server start 

Control Flow がフローを登録するための API を環境変数にセットします:

export PREFECT_API_URL=http://127.0.0.1:4200/api 

サンプルを実行するとエラー

ここでサンプルのサイコロを振るプログラムを実行すると、以下のエラーが発生します:

$ python roll_dice.py Traceback (most recent call last): File "/path/to/control_flow/roll_dice.py", line 1, in <module> import controlflow as cf File "/path/to/control_flow/.venv2/lib/python3.12/site-packages/controlflow/__init__.py", line 5, in <module> from .agents import Agent File "/path/to/control_flow/.venv2/lib/python3.12/site-packages/controlflow/agents/__init__.py", line 1, in <module> from . import memory File "/path/to/control_flow/.venv2/lib/python3.12/site-packages/controlflow/agents/memory.py", line 7, in <module> from controlflow.tools import Tool File "/path/to/control_flow/.venv2/lib/python3.12/site-packages/controlflow/tools/__init__.py", line 1, in <module> from controlflow.llm.tools import tool, Tool, as_tools File "/path/to/control_flow/.venv2/lib/python3.12/site-packages/controlflow/llm/__init__.py", line 1, in <module> from controlflow.llm import models, messages, tools, handlers, completions, rules File "/path/to/control_flow/.venv2/lib/python3.12/site-packages/controlflow/llm/tools.py", line 16, in <module> from controlflow.utilities.prefect import create_markdown_artifact, prefect_task File "/path/to/control_flow/.venv2/lib/python3.12/site-packages/controlflow/utilities/prefect.py", line 22, in <module> from prefect.results import ResultFactory ImportError: cannot import name 'ResultFactory' from 'prefect.results' (/path/to/control_flow/.venv2/lib/python3.12/site-packages/prefect/results.py). Did you mean: 'ResultRecord'? 

from prefect.results import ResultFactory というライブラリインポートの構文で、ResultFactory というオブジェクトがないとエラーを出しています。

この ResultFactory ですが、最新の Prefect のソースコードを見ると確かに存在しません。しかし以下のコミットにより ResultStore というオブジェクト名に変更されていることを見つけました。ControlFlow から Prefect は 3.0.0 を指定していますが、このコミットが 3.0.0 の RC の途中 に取り込まれたため、正しく動いていた時期があるのが検知が難しいポイントだったかもしれません…

Rename `ResultFactory` to `ResultStore` (#15184) · PrefectHQ/prefect@128e12d · GitHub

以下のIssueでもこの問題は指摘されていました:

Prefect's latest release seems to have broken controlflow · Issue #288 · PrefectHQ/ControlFlow · GitHub

とりあえず ControlFlow を動かすだけであれば、取り急ぎ以下のRCバージョンも指定した pip で Prefect を再インストールします:

pip install prefect==3.0.0rc20 

サンプル再実行(サイコロを振る)

改めてサンプルを実行します:

$ python roll_dice.py ╭─ Agent: Marvin ──────────────────────────────────────────────────────────────────────────────────╮ │ │ │ ⠼ Tool call: "talk_to_user" │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────── 12:33:50 AM ─╯ 🤖 Agent: How many dice would you like to roll? Type your response: 10 ╭─ Agent: Marvin ──────────────────────────────────────────────────────────────────────────────────╮ │ │ │ ✅ Tool call: "mark_task_d3dca_successful" │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────── 12:33:52 AM ─╯ ╭─ Agent: Marvin ──────────────────────────────────────────────────────────────────────────────────╮ │ │ │ ✅ Tool call: "roll_dice" │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────── 12:33:54 AM ─╯ ╭─ Agent: Marvin ──────────────────────────────────────────────────────────────────────────────────╮ │ │ │ ✅ Tool call: "mark_task_facb0_successful" │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────── 12:33:55 AM ─╯ The result is: [4, 2, 1, 2, 1, 3, 6, 2, 1, 3] 

詳しくはチュートリアル内の解説を見ていただきたいのですが、このプログラムではサイコロを何回振るかをユーザに入力させ(上では10回)、その後の処理を ChatGPT に任せています。

Prefect のローカルサーバに繋ぐと、以下のようにフローとタスクが構築され、LLMによる処理がされていることが分かります:

Prefect による LLM フローの実行

サンプル実行(AIとじゃんけん)

ユーザがどの手を選ぶかを入力し、AIの入力とじゃんけんする例です。

じゃんけんのロジック(パーはグーに勝つ、など)は一切記述していない点が不思議に感じます。プログラムの組み方も手続的というより宣言的に感じますし、使いこなすには慣れが必要だなと感じます。

$ python rps.py ╭─ Agent: RPS-Helper ──────────────────────────────────────────────────────────────────────────────╮ │ │ │ ⠏ Tool call: "talk_to_user" │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────── 12:19:40 PM ─╯ 🤖 Agent: Please choose one: rock, paper, or scissors. I won\'t share your choice with the AI opponent. Type your response: rock ╭─ Agent: RPS-Helper ──────────────────────────────────────────────────────────────────────────────╮ │ │ │ ✅ Tool call: "mark_task_02a14_successful" │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────── 12:19:46 PM ─╯ ╭─ Agent: Marvin ──────────────────────────────────────────────────────────────────────────────────╮ │ │ │ ✅ Tool call: "mark_task_5d441_successful" │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────── 12:19:47 PM ─╯ ╭─ Agent: Marvin ──────────────────────────────────────────────────────────────────────────────────╮ │ │ │ ⠋ Tool call: "talk_to_user" │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────── 12:19:49 PM ─╯ 🤖 Agent: It\'s a tie! Both chose rock. Would you like to play again? (yes/no) Type your response: yes ... 

まとめ

以上、チュートリアルを走破するまでの手順と気をつけるポイントでした。LLM に実際の挙動は任せるという新しいプログラムの書き方を感じられて面白かったです。

ただ、今はまだ開発段階ということもあってドキュメントのまま進めても躓くことが多かったです。Prefect 本体も開発がどんどん進んでいるので、本番投入はもう少し様子を見た方が良いかもしれませんが、ChatGPT への入出力を型指定できる能力を簡単に手に入れられると考えると、手元でちょっと動かすだけでも十分業務支援につながりそうです。