Podcast - Backyard Hatena
TechTalk - Google Cloud Born Digital Summit
ぽ靴な缶
この記事は はてなエンジニアアドベントカレンダー 2024 5 日目の記事です。 昨日は id:susisu さんの Data types à la carte in TypeScript でした。 本人が「アクセス増えたと思ったら別の記事で、全然読まれてない...」と言っていたので「いきなりフランス語で難しそうやからね」と伝えました。本文は日本語なので、みなさんも読んで下さい。 今日は最近見て面白かったコードの紹介です。 ChatGPT が流行って以来、アプリでストリームのレスポンスをよく見るようになりました。 LLM によるテキスト生成はわりと時間がかかる処理で、もしすべて生成し終えてからレスポンスするとユーザーを待たせてしまうからでしょう。テキストがちょっとずつ表示される UI は昔からあるものですが、LLM を使ったアプリケーションが出てきて以来、演出としてではなく実用としてよく見られるようになったと思います。 各社が提供している LLM の API を利用する場合も、大抵ストリームでレスポンスを受け取る方法も提供されています。また自然文の生成だけでなく、指定したスキーマを埋めて JSON で構造化されたデータを返してくれる機能があります。アプリケーションに組み込みやすくて重宝しますね。 では LangChain で JSON のレスポンスストリームを読んでいる様子を見てください これは Gemini API のレスポンスを JsonOutputParser に渡していて、チャンクを受信するたびにパース結果を出力しています。 JsonOutputParser え!?!? 今みた!?!? もっとわかりやすく1文字ずつバッファに書き込んでいってパースさせてみましょう。 1文字ずつ おわかりいただけだろうか... まだリテラルが終わっていない段階でパースされた値が得られているのを... stream: {"name": "p parsed: {"name": "p" ↑ この段階で name の値が p としてパースされてる!! stream: {"name": "pokutuna", "age": 1 parsed: {"name": "pokutuna", "age": 1} ↑ age: 1 の瞬間がある!! JSON ストリームの読み込みは、いろいろなライブラリで実装されています。 例えば、NDJSON に対して行ごとにオブジェクトを受け取れるものや、JSON Path で値をひっかけるもの、SAX-like な特定のトークンが来たらコールバックを受け取るもの (もう SAX という響きが懐かしいぞ)など。 でも LangChain のこのパターンを見るのは始めてで、なにそれ!? と思ってコードを見に行きました。 この動作はこの parse_partial_json で実装されています。 github.com 文字列の開始のダブルクオートや、Object や Array の開きカッコなど、開始トークンが来るたびに、対応する閉じトークンを積んでいって、最後に reverse してくっつけて補完して json.loads しています。なかなか勢いのある実装。 内容を正確にパースをするという観点からは許されるか怪しい、レスポンスを途中までしか受け取ってないからといって、お小遣い3円の瞬間があっていいのか? しかし { "message": "長いテキスト長いテキスト長いテキスト長いテキスト... のような文字列の終わりを待ってずっと値を使えないなら、レスポンスをストリームすることで本来得たいユーザを待たせない体験が得られません。 実装も富豪的で、全体のパースを試して失敗したら1文字ずつ読んでカッコ等を積んでいく、ダメなら末尾を捨てていって試す、と何回 json.loads するつもりなのか。 これは JsonOutputParser 全体で、自然文中に JSON が含まれるレスポンス はい、指示に従って JSON で回答します。 ```json {"hoge": "fuga", ... みたいな出力もパースできるようにするためですね。 大抵「ストリームで JSON を処理したい」というと、超巨大なログを扱うとか、一度にメモリに読み込みたくないとか、実行時のリソースに意識があります。しかし LangChain のこの実装はユーザを待たせないため、途中でもいいから値を返す、Object や Array だけでなく、文字列や数値すら途中で返してしまう、AI との会話文ストリームからも取り出す、というのが面白いですね。そんなちょっとした観光名所でした。 途中の stream.py はこれ stream.py · GitHub この記事は はてなエンジニアアドベントカレンダー 2024 5 日目の記事です。 id:miki_bene さんです!! { entries.forEach(entry => { if (entry.isIntersecting) { typeText(); } else { clearTimeout(animationId); } }); }); observer.observe(element);
ぽ靴な缶
はてな 生成AI×新規事業 の挑戦 〜生成AIを学びながら技術とチームを磨いた事業立ち上げの道のり〜 - connpass speakerdeck.com 何の因果か新規事業立ち上げ & AI 担当みたいな仕事をしております。 話題で分類するとなるとトピックモデルか? と思うけど、Vertex AI の Embedding API に task_type="CLUSTERING" を見つけ、クラスタリングでそこそこのものが出たのでそれで行くことに。改善の余地は様々ありますがとにかく HDBSCAN の性質に助けられた機能だったなと思います。 密度ベースのクラスタリング 異なる密度レベルのクラスタ得られる クラスタ形状の変化に柔軟 階層構造得られる ハイパラ調整がほぼ要らない 都合が良すぎる。 メイン図 手法の図
ぽ靴な缶
去年の9月末に買いました。 Series 9 41mm シルバー GPS 発表を見るたびに欲しいなと思うものの、冷静に考えると要らないよな、という結論に行き着くので買ってなかった。常にスマホ持ってるでしょ。欲しい → 要らん → 欲しい というのを年1でやりつつ、ついに買ってしまった。 買ってからは便利で、風呂と充電以外は常に着けている。 生活をシャキッとさせたい フルリモートなので家から出る頻度が減って、体力も落ちだんだん太ってきた。運動習慣を付けたいけど、無策では続けられないので記録を付けるおもちゃが欲しい。他にも睡眠や心拍など Watch で体をモニタリングして遊びたい。自転車に乗っていた頃は記録に楽しさがあった。サイコンつけるし心拍計も胸に巻いてた。変化が分かると成長が見えるし満足できる。 TODO リストをもっと生活に密着させる狙いもある。Things を愛用していたけど、ここ何年も活用できてなかった。今は仕事のタスクは仕事で管理するし、生活系は記憶に頼ってもなんとかなる。なんとかなるけど、サプリ飲むとか本読むとか買い物とか、それなりに忘れているので確実に遂行しつつ習慣を作りたい。 バンド選び 買う前にずっと迷っていたのはバンド。 結局バンドはデフォルトのスポーツバンドにした。シリコン的なプニャっとしたやつ。 スポーツバンド スポーツバンド Apple Watchのバンドを購入 - Apple(日本) Watch を持ってる同僚の話を聞いて、 ブレイデッドソロループ > スポーツループ > スポーツバンド ぐらいの感じで、実物見て決めようと思っていた。しかし欲しさが最高潮の加速を使ってヨドバシで買ったので選ぶ余地が スポーツバンド or スポーツループ しかなかった。個別にバンドを選べるのは Apple Store か通販だけである。 ソロループ系は伸びるのを想定してサイズチャートより1サイズや2サイズ下が良いという真偽不明情報に惑わされて踏み切れないし、スポーツループの実物は思ったよりペラペラで、軽くて柔らかいのは分かるけど、タイトめに締めないと Watch の重さに対して慣性やズレが不快そうだなと見送った。 結果的にスポーツバンドで満足している。 4 運動などタイトにしたいとき 5 普段使い 6 洗い物したり干渉するとき むしろ締め付けず使い分けれるのが良い。通気性はないので汗をかくと多少気になるけど、そのまま時計ごとじゃぶじゃぶ洗える。冬場は手袋やパーカーの袖口のリブなんかが干渉するのでやや鬱陶しい。 腕 使ってみて いろんなものが腕で済む 時間が分かって便利、とよく言うけど、たしかに常に時計とカレンダーが腕にあるのは素朴な便利さがある。 常に次の予定がぱっと見れる。特に出社した時など、ミーティングあるのは分かっているけど会議室どこやねん、と調べるのに何かを開かなくて良い。 MFA も腕で見れる。トークン入力画面が出るやいなや端末探したり席を立つ必要がないのが良い。MFA には Authy を使っていて iPhone アプリ側のがそのまま見れる。パスワード自体も 1Password から選択的に Watch へ送っておくことができる。 腕から Nature Remo により家電が操作できる。常に腕に付いてるので、布団の中で携帯探さなくて良い。 ズボラな用途だと、布団に入ったけど、何かが PC のスリープを止めているな...まぶしい...って時に時計から pmset sleepnow している。Shortcut.app で ssh するショートカットを用意しておくとよい。 地図が腕にあるのも悪くない。 スマホ出してロック解除して地図見て、という動作をかなり頻繁にやっていることに気づく。今まで Apple Map を使っていなかったけど、Watch との連携の良さから使うようになった。Google Map の Watch アプリは地図は出ないが、スマホ側で検索したルート(主に乗り換え)を Watch で見れるので使い分けている。カレンダーの予定に場所を入れる機能も Watch でルートをシュッと表示できるので入れると便利。 母艦との連携 iPhone・Mac とのシームレスな連携がすごい。 iPhone 側のアラームは Watch も鳴って、Watch 側で止めれる、iPhone 操作している時に鳴った場合は時計は鳴らない、とかも大変良いです。外やマスク付けている時は Watch が FaceID より速く反応してロック解除できるのも良い。Mac のロックも解除できる。 通知も同期している。 iPhone にバンバン来る通知に対し、一覧を眺めて読み飛ばす運用をしていた。でもそのノリで時計で受けるのは鬱陶しすぎた。 最終的に id:cockscomb に教えてもらった時間指定要約を使って、いらねと思ったものを要約送りにしていくと必要なものだけ Watch に届くようになるし、iPhone 側は雑に受けつつ興味あるやつだけざっと見る運用ができた。 ただ iPhone 側の時間指定要約は、おしゃれなレイアウトで表示されるので、エッチな画像のレコメンドや YouTube のサムネがロックスクリーンに表示されうる。ロック中は通知を出さないようにしているが、携帯と一瞬目が合うと解除される。たまに気まずい。 Watch を買うと通知を整理する動機が生まれるし、Watch ユーザのほうが世のアプリのエンゲージメントが下がっているみたいなことが起きているんじゃないか。LINE の企業アカウントの通知とかも止めまくったし。 端末を超えて集中・睡眠モードが同期して動くのも良い。 あとここ数年ぐらいの iOS のアップデートの意図みたいなのがしっくりきた。ロック画面のカスタマイズがなんでこんな感じなの...と微妙に思っていたけど Watch と体験が共通になっているし納得感はある。 あと通知の持ち上げたとき周りの挙動がいいよね。 かわいい通知 電池の持ち 自分の使い方だと、常時点灯で1日使って 40~50% ぐらい残る。100% から 40 時間ぐらい持つ。 丸2日は持たないが、充電せず寝てしまっても十分バッファがある。 カタログスペックでは 18 時間という不安になる数字だけど、かなり時計使いまくってる状態での試験やね。バッテリなんて得てしてカタログを下回る体験だけど、倍以上保つのは意外だった。 意外と持つ 充電面倒かなと思っていたけど、意外とそうでもない。 45分で 0% → 80% のようで、実際そのぐらい。風呂の時間だけで 100% になれば最高なのだが...ちょっとは待つ必要がある。 充電自体より、ケーブルの管理が面倒。出張や外泊に持っていくものが1個増える。 サードパーティのケーブルはレモン市場感が激しく、急速充電言ってるだけだったり 5W 出てないものだったりする。そしてまともなものは MFi 取っていて高い。 Apple Watch 磁気充電ケーブル(1m) Apple(アップル) Amazon Anker 3-in-1 Cube with MagSafe: マグネット式 3-in-1 ワイヤレス充電ステーション/USB急速充電器付属/ワイヤレス出力/Apple Watchホルダー付/MFi認証/iPhone15 Apple Watch対応 Anker Amazon 睡眠の記録 睡眠トラッカーの AutoSleep が良い。 睡眠には、気絶睡眠モデルを採用しており、寝ようと思って眠ることはあまりなく、いつのまにか気絶している。十分寝たら意識を取り戻す。そういう暮らしを送っています。支障がないようウィンドウを広く取っていて、夕食後(20時) ~ 愛する妻が起きる(7時)まで、任意気絶する。 そういう感じなので、自然と10時間寝て元気なこともあれば、3時間しか寝てないこともある。記録が残っていれば眠かったり疲れてたりするのが睡眠不足かどうか切り分けられる。仕事の忙しさやストレスが睡眠に反映されているのも読み取れたりする。 夕食後に寝てない時期 気絶睡眠法の欠点として寝る前の準備というものができない。昔から Sleep Sycle を使っていたけど、iPhone に充電ケーブルを挿しつつアプリを起動して枕元に置く作業は難しすぎる。いびきを録音して聞けたりは大変楽しいのだが、意図して入眠する日だけ使える状態だった。 Apple Watch を使った睡眠記録には AutoSleep が良くて、いつ寝ても睡眠検出して記録してくれるし、起きたタイミングも勝手に残る。判定が間違ってると思うことはそんなにない。 特に「人間が寝るのは1日1回である」という非現実的な仮定を置いてないのがいい。複数回寝れるし記録が残る。 晩飯食べたあと床で30分気絶して、ベッドに這って移動してまた寝るとか、昼休みに30分寝るとか、朝飯食べたあとに二度寝するとか、現実には1日に何回も寝る。1回なわけねーだろ。 現実の睡眠活動 アプリの作りも、常にセンシングして頑張っている感じでなくヘルスケアのデータを複数突き合わせて活用している感じなのも好ましい。母機の iPhone いじってたらそれは起きてる時間だよね、とか。 リングやゲージの UI は特に分かりやすくはないです。 入力 意外とキーボード入力できる。 込み入った返事はやる気起きないが、ack 程度の内容や、TODO を 1 行だけ入力など時など普通に時計でやっている。音声入力も割と使う。 意外と入力できるキーボード Series 9 なら使えるダブルタップは良いけどタイト目につけていないと反応がわるい。今のところ通知閉じるのと、料理中に手が汚れたままタイマー止めるのが主な用途である。 アクセシビリティの Assistive Touch を使うと、色々ジェスチャで操作できてなかなかすごい体験。一度やったほうがいい。それなりには大変だけど片腕でも一通りの操作ができる。手を2回握りしめる、とかにアクションが割り当てられている。 Apple Watch で AssistiveTouch を使う - Apple サポート (日本) ダブルタップはプライマリのボタン1個押す程度のアクションしかできないので、普段もクレンチ(手を握りしめる)でセカンダリの動作ができるようになってほしいな。 運動 買ってから週に 2 ~ 3 回運動していて、意外と続いている。近所の坂の上の神社まで行って帰ってくる、約 40 分。 これ読んでインターバル速歩をやっている。 ウォーキングの科学 10歳若返る、本当に効果的な歩き方 (ブルーバックス) 作者:能勢 博 講談社 Amazon 要は (ワーク:心拍ゾーン2以上を3分 → レスト:心拍ゾーン1を3分) * 5 をやれという話だけど、運動生理学の話がおもしろい。mol から消費酸素の体積計算したりした。知らない分野の教科書みたいな読後感。 世にアプリも色々出ているが、Apple のフィットネスで独自のワークアウトを作れて、心拍ゾーン外れたら通知したりできる。これ Apple Watch からしか編集できないようで、チマチマした作業が発生して面白い。 時計でワークアウトを編集する 作ったワークアウトは共有もできる。iOS で開くと Watch に追加できる。 https://storage.googleapis.com/pokutuna-public/interval-walking.workout 本で紹介されている運動は老人向けで、だんだんと心肺機能がマシになってきたのもあり、平地の早歩きでは心拍が上がらないので、普通に走り始めた。傾斜がきついところは歩いている。するとゾーン5も使う羽目になる。 それにしても VO2max が低すぎる、35 て。 痩せにくいと思っていたけどショボすぎないか、45 ぐらいには持っていきたい。一方心拍回復は 30 まで戻ってきた。 Watch アプリのつくり アプリが全体的に割り切った作りものが多い。 Apple Map のルート検索の出発地点は現在地からのみ。出発地点や経由地を設定したければ iPhone からしろという割り切りは良いのだが、電車3路線アクセス可能な立地に住んでおり、なかなか狙ったルートで検索できないので時計から電車の時間調べるのは諦めてる。 アラームやリマインダーなど、リストに追加する系 UI の追加ボタンが一番下にありがちなのもツラい。「ヘイシリ n 分後に起こして」という指示を日々やっているので、アラームのリストはスクロールが苦痛なほど長くなっている。時計でも右上に "+" ボタン置いてくれよ。 ピークタイム スマホ経由で通信する都合上、ネットワークエラーやタイムアウトに出くわしやすい気がする。やたらローディングのままだったり、タイムアウトした時にアプリをキルしないと何もできなかったり。 微妙なアプリの作りの悪さもありがち。 Watch の Siri のサジェスト押した時の動作定義してないのか、最低限アプリが起動すればいいのだが謎のウィンドウが開いてくるくるするだけとか。 母機の iPhone を経由する遅延やリトライがそこそこある上に、状態を iPhone 側に保存していたら通信して読まないといけないだろうし、考えることが多く画面も小さくフィードバックも難しそうではある、その上ユーザは限られてるとなると力も入らない気持ちは分かる。 価値 収支 図にするとこんな感じ。 腕に時計を着け続けるのは明らかに邪魔なのだが、様々な便利さにより総合的には良い。 追記 あたりまえすぎてタッチ決済に言及していなかった。 まじめにやってくれ天気.app
ぽ靴な缶
これは はてなエンジニアアドベントカレンダー2023 2日目の記事です。 はてなエンジニア Advent Calendar 2023 - Hatena Developer Blog はてなエンジニアのカレンダー | Advent Calendar 2023 - Qiita トップバッターは緊張するけど、順番が回ってくるまで長い間ソワソワするのも嫌、という理由で例年2日目を狙うようにしている id:pokutuna です。今年も成功しました。 観光名所とは 目を閉じれば思い出す、あのコード... あの Issue... あなたが Web 系のエンジニアであれ、趣味で開発している方であれ、必要に応じてライブラリやフレームワークのコードを読むのはよくあることでしょう。公開の場で開発されているソフトウェアは、ソースコードだけでなく、開発コミュニティでの議論やバグ報告なども見ることができます。 リポジトリを覗き見していると、思いもよらない実装や、記憶に残るディスカッション、バグレポートまでいろいろな営みが見つかります。 私はそういったものを「観光名所」と呼んでコレクションしています。 今日はよく知られているソフトウェアの GitHub 上にある観光名所をピックアップして紹介します。 観光名所たち __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED (facebook/react) facebook/react@60ad369 - packages/react/src/React.js#L128 export { ... ReactSharedInternals as __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, これはちょっと有名かも、ReactSharedInternals が export される際の物騒な名前。React の内部状態が入っています。 まあ必要があって export しているわけで、テストや react-dom など他の packages/ 以下からちょいちょい参照されている。package として公開しているが、これに依存した機能なんて作るなよというメッセージが明確に表現されています。まあドキュメントやコメントで言っても読まれませんからね。 Node.js の HTTP ヘッダの小文字化 (nodejs/node) nodejs/node@60ffa9f - lib/_http_incoming.js#L279 function matchKnownFields(field, lowercased) { switch (field.length) { case 3: if (field === 'Age' || field === 'age') return 'age'; break; case 4: if (field === 'Host' || field === 'host') return 'host'; if (field === 'From' || field === 'from') return 'from'; if (field === 'ETag' || field === 'etag') return 'etag'; if (field === 'Date' || field === 'date') return '\u0000date'; if (field === 'Vary' || field === 'vary') return '\u0000vary'; break; case 6: if (field === 'Server' || field === 'server') return 'server'; if (field === 'Cookie' || field === 'cookie') return '\u0002cookie'; if (field === 'Origin' || field === 'origin') return '\u0000origin'; if (field === 'Expect' || field === 'expect') return '\u0000expect'; if (field === 'Accept' || field === 'accept') return '\u0000accept'; break; case 7: if (field === 'Referer' || field === 'referer') return 'referer'; if (field === 'Expires' || field === 'expires') return 'expires'; ... Node で HTTP ヘッダを扱う際、ヘッダ名を小文字で扱っていることに気づきます。RFC2616 → RFC7230 → RFC9112 の歴史ある仕様にあるように、ヘッダ名は大文字小文字を区別しないので、すべて小文字に寄せているようですね。 何度も実行されるところなので、パフォーマンス優先のためになかなか激しい実装になっています。toLowerCase を呼ぶ回数を減らすため、一般的なヘッダはハードコードされており、文字列比較の回数を減らすため前段で文字列長で分岐しています。 返す文字列の1文字目がフラグになっている、というのもなかなかです。同じヘッダが複数回出現する場合の区切り文字や、Cookie & Set-Cookie の扱いを制御しています。 VSCode のコマンドがローカライズされる (microsoft/vscode) Don't localize command names on the command palette · Issue #4679 · microsoft/vscode VSCode の開発版である Insiders Build にリリースされた変更。 コマンド名が翻訳されて、git pull ではなく git プル と入力する必要がでてくる。やめてくれという意見で CJK 圏の気持ちが一つになった事件。 Issue を立てるだけでなく、繰り返し問題を説明する @espresso3389 さんの活躍が光る Issue です。これが安定版に降ってこなくて本当に良かったですね。ソフトウェアをローカライズする際の難しさも垣間見えます。 A picture of a cute animal (moby/moby ほか) moby/moby@75546e1 - .github/PULL_REQUEST_TEMPLATE.md Please provide the following information: ... **- A picture of a cute animal (not mandatory but encouraged)** moby は、以前モノリシックな構造だった Docker リポジトリをコンポーネント化していったもので以前は docker/docker でした。今も Docker の実装に使われています。その moby の Pull Request テンプレートには、かわいい動物の画像を貼るコーナーがあります。 例 https://github.com/docker/compose/pull/11213 (moby じゃなかった) https://github.com/moby/moby/pull/32061 (アスキーアート) https://github.com/moby/moby/pull/27455 (どういう状況?) https://github.com/moby/moby/pull/34895 (🐼で済ませる) でも最近の Pull Requests を見るに、そんなに貼られてはいなさそう。 その他 docker 関連リポジトリにおいても動物画像コーナーがしばしば見られます。 docker/compose@c582470 - .github/PULL_REQUEST_TEMPLATE.md docker/cli@c1455b6 - .github/PULL_REQUEST_TEMPLATE.md Steve Wozniak is not boring (moby/moby) moby/moby@75546e1 - pkg/namesgenerator/names-generator.go#L852 if name == "boring_wozniak" /* Steve Wozniak is not boring */ { goto begin } こちらも moby から、Docker コンテナの自動命名にある唯一の例外。 docker run でコンテナを起動した際、ランダムな名前が割り当てられるのはこの names-generator.go の実装によるものです。"形容詞" と "科学者やハッカーの名前" の2つのテーブルから選んで結合したものになる。 形容詞のテーブルに boring、人名のテーブルに wozniak が含まれていますが、boring_wozniak という名前がコンテナに割り当てられることだけはありません。なぜなら Apple 創業者の Steve Wozniak は退屈ではないので。 goto で戻ってやり直しているのも普段あまり見ないので面白いですね。 そういえば Elasticsearch の node 名は Marvel キャラクターから選ばれるんだっけ、と見に行ったら 5.0 からなくなっていた。めっちゃ前じゃん elastic/elasticsearch@v2.4.6 - core/src/main/resources/config/names.txt Trick and AttributeError 事件 (pypa/pipenv) Halloween easter egg breaks · Issue #786 · pypa/pipenv pipenv は Python のインタプリタと依存ライブラリのバージョンを管理する bundler ツール。 普段のプログレスバーは 🐍 の絵文字で表示されるところ、ハロウィンだけ 🎃 になるというイースターエッグが仕込まれていました。しかしそこにバグがあり、ハロウィンだけ例外が出て依存をインストールできなくなる事態に。 ちょうどこれでデプロイ不能になってハマったのでよく覚えている。ここがいきなり壊れると思わないだろ。 累計100万DLを突破したダイエットアプリ(無料)の『もぐたん』! (google/zetasql) google/zetasql@589026c - zetasql/compliance/testdata/strings.test#L911 -- ARRAY<STRUCT< STRING, formatted_description STRING >> [ { "累計100万DLを突破したダイエットアプリ(無料)の『もぐたん』!\nおかげさまで、ヘルスケア/フィットネス 無料カテゴリで1位獲得!\n\n◆かんたんスタンプ入力 \n文字で書かなくても食べ物スタンプで簡単に記録出来ちゃう!\n\n◆『もぐたん』がみんなを応援\n入力する度にもぐたんがゆるくて可愛いコメントをくれるよ!\n毎日体重を入力して『もぐたん』の「きせかえ」をGETしよう!\n\n◆ダイエットの成果はグラフでチェック\n体重を入力するとグラフに反映されるから変化がまるわかり!\n摂取カロリーの推移もグラフでチェック出来ちゃう!\n\n◆体重と一緒に運動スタンプを入力\n運動もスタンプでかんたん入力!\n毎日どのくらいダイエットしたかがひと目でわかるよ!\n\n◆ 自動カロリー計算機能\nプロフィールを入力すると、あなたに合った摂取カロリーの目安がわかるよ!\n\nhttps://itunes.apple.com/jp/app/daietto-ji-lumogutan-ke-aiisutanpude/id882365789", '"累計100万DLを突破したダイエットアプリ(無料)の『もぐたん』!\\nおかげさまで、ヘルスケア/フィットネス 無料カテゴリで1位獲得!\\n\\n◆かんたんスタンプ入力 \\n文字で書かなくても食べ物スタンプで簡単に記録出来ちゃう!\\n\\n◆『もぐたん』がみんなを応援\\n入力する度にもぐたんがゆるくて可愛いコメントをくれるよ!\\n毎日体重を入力して『もぐたん』の「きせかえ」をGETしよう!\\n\\n◆ダイエットの成果はグラフでチェック\\n体重を入力するとグラフに反映されるから変化がまるわかり!\\n摂取カロリーの推移もグラフでチェック出来ちゃう!\\n\\n◆体重と一緒に運動スタンプを入力\\n運動もスタンプでかんたん入力!\\n毎日どのくらいダイエットしたかがひと目でわかるよ!\\n\\n◆ 自動カロリー計算機能\\nプロフィールを入力すると、あなたに合った摂取カロリーの目安がわかるよ!\\n\\nhttps://itunes.apple.com/jp/app/daietto-ji-lumogutan-ke-aiisutanpude/id882365789"' } ] zetasql は BigQuery や Cloud Spanner 内で利用されている Google の SQL Parser & Analyzer です。 その utf8 文字列のテストデータとして「もぐたん」という iOSアプリの App Store 説明文らしきものが使われています。そこは Play Store じゃないんかい。 zetasql は、BigQuery 大好きパーソンが中を知りたい時に当たれる数少ない公開コンポーネントです。謎に満ちており、OSS ではあるもののコミュニティ主導ではなく ZetaSQL Team ユーザが数週間に1回変更をまとめて push する、人の侵入を望まない霊峰のような風情。 もぐたんは現在サービス終了していますが、かわいいクマチャンが出てくるアプリです。zetasql との温度差で交互浴の気分になります。 ダイエット・カロリー・体重記録アプリもぐたん(applion より引用) 参考 Google の SQL parser/analyzer の ZetaSQL とは何であるか | by apstndb | google-cloud-jp | Medium 公開論文から学ぶ Google のテクノロジー : パート 3:データベース技術編 | Google Cloud 公式ブログ Promise.race で DNS & IP 両方にリクエストを投げる (googleapis/gcp-metadata) googleapis/gcp-metadata@27f0a12 - src/index.ts#L186-L187 let responded = false; const r1: Promise<GaxiosResponse> = request<T>(options) .then(res => { // ... }) const r2: Promise<GaxiosResponse> = request<T>(secondaryOptions) .then(res => { // ... }); return Promise.race([r1, r2]); これは Google Cloud のメタデータサーバーにリクエストする実装です。 メタデータサーバーは GCP 内のネットワーク内から到達でき、実行環境に応じた情報取得や認証を行うため、ほとんどのクライアントライブラリが内部的に叩いています。 ここではメタデータサーバーの metadata.google.internal. と、それを解決したリンクローカルアドレスの 169.254.169.254 に並行にリクエストを投げて先に成功した方を使うという実装になっています。 そんなことしていいの、と驚くけど、GCP 内の名前解決が遅い環境では 169.254.169.254 が先に結果を返すでしょうし、GCP 外のユーザのローカル環境などでタイムアウト待ちになったとしても metadata.google.internal. が解決できないので名前解決程度の短時間で失敗できる、という感じでしょうか。合理的ではあります。こんなコアっぽいところでリクエストを倍にしちゃうんだ。 関連: GCP の Application Default Credentials を使った認証 - ぽ靴な缶 命名に関する議論 命名に関する議論は紛糾しがちです。 GitHub は 2020 年 10 月にデフォルトブランチ名を master から main に変更しました。日本語圏だけでもいろいろな意見が飛び交いましたね。 The default branch for newly-created repositories is now main - The GitHub Blog 先程の Docker コンテナ命名の実装についても、議論の末に変更を凍結する判断がされています。 Freeze the namesgenerator package against new additions by tianon · Pull Request #43210 · moby/moby このコメントの一部を機械翻訳し、調整したものを引用します 私たちはこの変更についてメンテナ会議で議論し、私たち全員がこのパッケージの最初の アイデアを気に入っていたにもかかわらず、何年もかけてこのパッケージは 望ましい以上のメンテナンスが必要になり始めたという結論に達しました。 いくつかの例を挙げますと、何年もの間、名前の組み合わせが不幸な組み合わせになったり、形容詞がすべての状況に適していなかったり、否定的な意味を持つようになったり、リストの人々が物議を醸すようになったりしたため、私たちはリストの変更を余儀なくされてきました。さらに、技術的な制限(姓が一意でないこと、名前の長さ、名前がアスキーに限定されているため、暗黙のうちに多くの地域の名前が除外されていること)もあり、事態を複雑にしています。 リンクされているコミットでは、形容詞の cocky は人に付けるのは適切でなかったり、kickass, insane など俗語的にはポジティブな意味(ヤバすぎ、のような)でも、フォーマルな文脈では厳しいので消したり置き換えられたりしています。 この "物議" が指すのは、エプスタイン事件において疑惑のある Marvin Minsky や、それへの言及が問題となった Richard Matthew Stallman についての話で、人名テーブルから除く変更が行われています。 リチャード・ストールマン氏、MITの役職とFSF総裁を辞任 エプスタイン関連コメントへの批判で - ITmedia NEWS かつてはおもしろ機能だったものが、社会的な価値観の変化やより広い人々を包摂するにつれて、不適切とみなされるようになっていく、ということが起きています。 他に命名に関する議論で思い出されるのは、FactoryGirl や Tsunami でしょうか。観光名所というと面白がっているニュアンスで聞こえるかもしれませんが、fun ではなく controversial な、記憶に残るものとして紹介します。 FactoryGirl が FactoryBot に変更 (thoughtbot/factory_bot) Repository Name · Issue #921 · thoughtbot/factory_bot こちらは Ruby のテストデータのファクトリライブラリである FactoryGirl が、FactoryBot にリネームした際の議論。 FactoryGirl は、Factory パターンと Rolling Stones の曲に由来する名前ですが、「名前の由来はなんなの?」という質問に端を発し、女性差別的ではないか、男性多数なソフトウェア業界のバイアスがあるのではないか、という議論から FactoryBot にリネームされました。 リネーム反対意見に同意する emoji の数や、女性による変えなくて良いというコメントが繰り返し言及される中(「当の女性が問題にしていないじゃないか」的な)、冷静にリネームの判断を下していてすごいですね。6 年前の話ですが、今やると emoji の傾向も大分変わるんじゃないでしょうか。不快だと思っていてもこの荒れた Issue では表明するのも難しいでしょう。 一方 FactoryGirl の Python 版といえる FactoryBoy はそのまま行くという判断をしています。 factory_girl --> factory_bot by alexgleason · Pull Request #442 · FactoryBoy/factory_boy Consider renaming to FactoryPy or the like · Issue #912 · FactoryBoy/factory_boy · GitHub Tsunami の命名に関する議論 (google/tsunami-security-scanner) I'm not sure if "Tsunami" is a good name. But I need your opinion. · Issue #5 · google/tsunami-security-scanner 津波のような攻撃から身を守るセキュリティスキャナーという命名ですが、Tsunami って命名はどうなの? 東日本大震災の津波を思い出す人もいるんじゃない? という Issue です。master/slave や whitelist/blacklist は、どこか外の話のように感じる人も多いと思いますが、これは日本人が当事者になったトピック。 当時はてなブックマークでも話題になっていました。 Googleのセキュリティスキャナー「Tsunami」、名称がGitHubで議論呼ぶ 関係者が参加し釈明 - ITmedia NEWS 性別の話に比べ、かなり抑制的に議論が行われていると思います。津波という名前だから破壊する方のツールかと思った、という尤もな指摘もあります。 ...それはそれとして、この議論の数ヶ月後に、google/tsunami が push されています。TSUNAMI (TypeScript Untar Multiple Reads) の略だそうです。偶然でしょうが、変なオチがついた気持ちになりました。 XML は暴力ではない (sparklemotion/nokogiri) Removing reference to violence. · sparklemotion/nokogiri@ddd8e1d - XML is like violence - if it doesn’t solve your problems, you are not - using enough of it. - ポリティカルコレクトネス的な変更で思い出すのは Nokogiri です。Ruby の XML パーサーですが、README から以下の行が暴力を賛美しているということで削除されました。 XML is like violence - if it doesn’t solve your problems, you are not using enough of it. XML は暴力のようなもので、それで問題が解決しないのであれば、使い方が足りないのだ。) まあ明らかにジョークだし、このぐらいいいんじゃないの...と思うものの、暴力に怯える状況で XML をパースする際には複雑な気持ちになるかもしれません。 自分がどの立場になるか、という問題は常にあります。 Facebook にクビになった人は、React の __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED を面白がれるでしょうか。いやしかし、他者の痛みを想像しつつも、勝手な想像で他人の喧嘩をしないほうがいい、というのが私の気持ちです。 もはや GitHub デフォルトブランチが main なのが当たり前になり、むしろ master を見ると古臭く感じるようになりました。そんな心情の変化に時代の流れを感じますね、とここまでを締めることにする。 その他小粒なもの 特に説明しても面白さに資さないけど、記憶に残るもの 猫がキーボードの上を歩いた結果立った Redis の Issue ///33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333-g=-[=. · Issue #3909 · redis/redis if enabled then "Disabled" まあ稀にこういうことをする羽目に陥る hashicorp/terraform-provider-azurerm@v2.67.0 - azurerm/internal/services/network/subnet_resource.go#L524-L533 Google Analytics の dimesion1 ~ dimension200 までの型定義、metrics1 ~ metrics200 もある DefinitelyTyped/DefinitelyTyped@ad1ea50 - types/google.analytics/index.d.ts#L84-L283 OSS 以外 タイトルの引き欲しさに OSS と書いたので、ここまでオープンソースライセンスと言えるものを挙げてきました。それ以外で記憶に残っているものをちょっと紹介します。 "You are not expected to understand this" (Version 6 Unix) 超有名な一節。コードが分かる人に比して圧倒的にコメントが流行っている。僕もわかりません。 BSD で配布されているようですが原典的にはこの枠で。 2230 /* 2231 * If the new process paused because it was 2232 * swapped out, set the stack level to the last call 3333 * to savu(u_ssav). This means that the return 2235 * actually returns from the last routine which did 2236 * the savu. 2237 * 2238 * You are not expected to understand this. 2239 */ 2240 if(rp->p_flag&SSWAP) { 2241 rp->p_flag =& ~SSWAP; 2242 aretu(u.u_ssav); 2243 } 解説の翻訳 あなたが見た中で最も有用なコードコメントは何ですか? - Quora SQLITE_TEMP_FILE_PREFIX "etilqs_" (mackyle/sqlite) mackyle/sqlite@18cf471 - src/os.h#L65-L79 #ifndef SQLITE_TEMP_FILE_PREFIX # define SQLITE_TEMP_FILE_PREFIX "etilqs_" #endif SQLite は軽量でファイルベースのデータベースです。著作権を放棄した Public Domain で公開されています。 身近なモバイルアプリやブラウザのローカルなデータベースとして組み込まれていたりします。Chromium の履歴やブックマークでも使われているようですね。SQLite abstraction layer そんな SQLite の一時ファイルは、sqlite を逆さに読んだ etilqs_ が prefix になっています。 理由はこちらの @EzoeRyo 氏のツイートでどうぞ。 マカーフィーがSQLiteを使っていて、C:\tempに一時ファイルを作ったため、ファイルを見て疑問に思った馬鹿なユーザーがsqliteを検索し、出てきた開発者の電話番号に「テメェ責任者かコラ、ファイル消しやがれゴルァ」という迷惑電話をかけまくったため、逆さ読みのetilqs_に変更された。 — 江添亮 (@EzoeRyou) 2023年6月13日 おわりに コレクションしていた観光名所を一通り放出しました。 みなさんの知る観光名所はどんなものがあるでしょうか? コメントやはてなブックマークコメントでぜひ教えてください!! チャンネル購読と、高評スターもお願いします。 また、労働をしていると社内の開発リポジトリに観光名所を見つけることもあります。きっと皆様の会社にもあることでしょう。 様々なしがらみで修正できずそのままになっている typo 議論が白熱しすぎてもはや喧嘩している Issue デカい障害を引き起こした名コミット 狂った命名 遺言に見えるコメント Revert を Revert した回数最高記録 いちばん長い SHA1 のゾロ目を探して遊ぶ などなど、興味がある方はこちらから入社してください。日本全国フルリモートOK!! hatena.co.jp 実用的な情報 ちなみに GitHub のソースコード表示中に y を押すと、URL が main などブランチ名から コミットID が含まれるものに変わります。こういう記事や、ドキュメントを書くときに便利ですね。ファイルへのパーマリンクを取得する - GitHub Docs また、cocopy でリンクテキストを生成するとさらに便利ですよ。 blog.pokutuna.com こんな関数で、デフォルトは Markdown、Shift キーを押している時は Scrapbox 記法でコピーしています。 ({title, url, modifier}) => { const pattern = /https?:\/\/(.+)\/(?<user>.+)\/(?<repo>.+)\/blob\/(?<rev>[^/]+)\/(?<file>[^#]+)(?<hash>#.+)?/; const g = pattern.exec(url).groups; title = `${g.user}/${g.repo}@${g.rev.substr(0,7)} - ${g.file}${g.hash || ''}` return modifier.shift ? `[${title} ${url}]` : `[${title}](${url})`; } この記事は はてなエンジニア Advent Calendar 2023 2日目の記事でした。 明日の担当は id:mechairoi さんです。楽しみですね。 blog.chairoi.me 追記 ブックマークありがとうございます。 挙げてもらった観光名所にリンクしておきます。 ちょっと小粒よりだけど Sidekiq にある❤という名前のメソッドはおもしろ命名なので観光名所としてオススメですhttps://t.co/FkHiOH6amS OSS 観光名所を貼るスレ - ぽ靴な缶 https://t.co/Js9w9VQlZI — 藤秋 (@f_subal) 2023年12月2日 「デカい障害を引き起こした名コミット」の例だとaxiosでXSSを防ぐために"on〇〇"を含むクエリパラメータを全部エラーにしたやつが思い出されるかなhttps://t.co/z20FtZkLzx — 藤秋 (@f_subal) 2023年12月2日 TypeScript が急に 3.3.3333 ってバージョンを作って怒られる回 https://t.co/nnqwJrUGBG とか、Jest が10000個目の PR で馬鹿になっちゃった回 https://t.co/KTNhPWDLQx とか好き OSS 観光名所を貼るスレ - ぽ靴な缶 https://t.co/ScIsJyGC0e — ksakahieki@恋垢 (@ksakahieki) 2023年12月2日 GitHub のRails リポジトリがハックされたやつも載せてほしい https://t.co/4KqXswesMX / “OSS 観光名所を貼るスレ - ぽ靴な缶” https://t.co/vbd1Nx698o — suginoy (@suginoy) 2023年12月2日 OSS 観光名所を貼るスレ - ぽ靴な缶 これも <a href="https://tech.a-listers.jp/2011/06/17/epic-fail-on-github/" target="_blank" rel="noopener nofollow">https://tech.a-listers.jp/2011/06/17/epic-fail-on-github/</a> 2023/12/03 00:33 OSS 観光名所を貼るスレ - ぽ靴な缶 個人的にはこれ→<a href="https://github.com/cocoa-mhlw/cocoa/issues/95" target="_blank" rel="noopener nofollow">https://github.com/cocoa-mhlw/cocoa/issues/95</a>「OSのプロキシ設定を無視したHTTP接続を行っている」 2023/12/03 01:34 おもしろかった。個人的にはUI LibraryのAnt Designで、クリスマスになると勝手にデザインが変わる時限爆弾を思い出した。https://t.co/QC92u9sa0L / “OSS 観光名所を貼るスレ - ぽ靴な缶” https://t.co/a3kEb8CzE3 — snagasawa (@snagasawa_) 2023年12月2日 弊社のリポジトリでは変数の横に*が10個付いたCのコード(ポインタのポインタの…って10回分)が発見されて話題になったことがあるhttps://t.co/PMdgMEqy3c — ぞりお (@__zorio__) 2023年12月3日 これは楽しいw/命名関係は色々意見があるよねぇ…/個人的には古いけど「membarrier()システムコール」の話が大好きw https://t.co/yBJF2NuIkL / 他39件のコメント https://t.co/1EtRLNGIF8 “OSS 観光名所を貼るスレ - ぽ靴な缶” (331 users) https://t.co/FJZlUX0fAO — wisboot (@wisboot) 2023年12月3日
Checked other resources I added a very descriptive title to this issue. I searched the LangChain.js documentation with the integrated search. I used the GitHub search to find a similar question and didn't find it. I am sure that this is a bug in LangChain.js rather than my code. The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package). Example Code Make the model output long texts containing multibyte characters as a stream. import { VertexAI } from "@langchain/google-vertexai"; // Set your project ID and pass the credentials according to the doc. // https://js.langchain.com/docs/integrations/llms/google_vertex_ai const project = "YOUR_PROJECT_ID"; const langchainModel = new VertexAI({ model: "gemini-1.5-pro-preview-0409", location: "us-central1", authOptions: { projectId: project }, }); // EN: List as many Japanese proverbs as possible. const prompt = "日本のことわざをできるだけたくさん挙げて"; for await (const chunk of await langchainModel.stream(prompt)) { process.stdout.write(chunk); } Error Message and Stack Trace (if applicable) (No errors or stack traces occur) Output Example: Includes Replacement Characters (�) ## ������������:知恵の宝庫 日本のことわざは、長い歴史の中で培われた知恵や教訓が詰まった、短い言葉の宝庫で������いくつかご紹介しますね。 **人生・教訓** * **井の中の蛙大海を知らず** (I no naka no kawazu taikai wo shirazu): 狭い世界しか知らない者のたとえ。 * **石の上にも三年** (Ishi no ue ni mo san nen): ������強く努力すれば成功する。 * **案ずるより産むが易し** (Anzuru yori umu ga yasushi): 心配するよりも行動した方が良い。 * **転�������������** (Korobanu saki no tsue): 前もって準備をすることの大切さ。 * **失敗は成功のもと** (Shippai wa seikou no moto): 失敗から学ぶことで成功�������る。 **人���関係** * **類は友を呼ぶ** (Rui wa tomo wo yobu): 似た者同士が仲良くなる。 * **情けは人の為ならず** (Nasake wa hito no tame narazu): 人に親切にすることは巡り巡��て自分に良いことが返ってくる。 * **人の振り見て我が振り直せ** (Hito no furi mite waga furi naose): 他人の行動を見て自分の行動を反省する。 * **出る杭は打たれる** (Deru kui wa utareru): 他人より目���つ��叩かれる。 * **三人寄れば文殊の知恵** (Sannin yoreba monju no chie): みんなで知恵を出し合えば良い考えが浮かぶ。 ... Description This issue occurs when requesting outputs from the model in languages that include multibyte characters, such as Japanese, Chinese, Russian, Greek, and various other languages, or in texts that include emojis 😎. This issue occurs due to the handling of streams containing multibyte characters and the behavior of buffer.toString() method in Node. langchainjs/libs/langchain-google-gauth/src/auth.ts Line 15 in a1ed4fe data.on("data", (data) => this.appendBuffer(data.toString())); When receiving a stream containing multibyte characters, the point at which a chunk (readable.on('data', ...) is executed) is may be in the middle of a character’s byte sequence. For instance, the emoji "👋" is represented in UTF-8 as 0xF0 0x9F 0x91 0x8B. The callback might be executed after only 0xF0 0x9F has been received. buffer.toString() attempts to decode byte sequences assuming UTF-8 encoding. If the bytes are invalid, it does not throw an error, instead silently outputs a REPLACEMENT CHARACTER (�). https://nodejs.org/api/buffer.html#buffers-and-character-encodings To resolve this, use TextDecoder with the stream option. https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder/decode Related Issues The issue has been reported below, but it persists even in the latest version. #4113 The same issue occurred when using Google Cloud's client libraries instead of LangChain, but it has been fixed. googleapis/nodejs-vertexai#78 googleapis/nodejs-vertexai#86 I will send a Pull Request later, but I am not familiar with this codebase, and there are many google-related packages under libs/ which I have not grasped enough. Any advice would be appreciated. System Info macOS node v20.12.2 langchain versions $ npm list --depth=1 | grep langchain ├─┬ @langchain/community@0.0.54 │ ├── @langchain/core@0.1.61 │ ├── @langchain/openai@0.0.28 ├─┬ @langchain/google-vertexai@0.0.12 │ ├── @langchain/core@0.1.61 deduped │ └── @langchain/google-gauth@0.0.12 ├─┬ langchain@0.1.36 │ ├── @langchain/community@0.0.54 deduped │ ├── @langchain/core@0.1.61 deduped │ ├── @langchain/openai@0.0.28 deduped │ ├── @langchain/textsplitters@0.0.0 │ ├── langchainhub@0.0.8
Fixes #6501 I have fixed this issue similarly to #5286. The approach is the same, but we need to use components that work in the Browser environment instead of Node. I previously fixed the same issue for @langchain/google-vertexai in #5285. Although I don't use @langchain/google-vertexai-web myself, I've also fixed this package as it was requested in the issue.
Checked other resources I added a very descriptive title to this issue. I searched the LangChain.js documentation with the integrated search. I used the GitHub search to find a similar question and didn't find it. I am sure that this is a bug in LangChain.js rather than my code. The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package). Example Code Make the model output long texts containing multibyte characters as a stream. import { VertexAI } from "@langchain/google-vertexai-web"; const langchainModel = new VertexAI({ model: "gemini-1.5-pro-001", location: "us-central1", }); // EN: List as many Japanese proverbs as possible. const prompt = "日本のことわざをできるだけたくさん挙げて"; const stream = await langchainModel.stream(prompt); const reader = stream.getReader(); let buf = ""; while (true) { const { done, value } = await reader.read(); if (done) break; buf += value; } console.log(buf); This code can be executed by creating a service account key from the Google Cloud Console and running it with the following command: $ GOOGLE_WEB_CREDENTIALS=$(cat ./key.json) npx tsx sample.ts Error Message and Stack Trace (if applicable) (No errors or stack traces occur) Output Example: Includes Replacement Characters (�) ## ���本の諺 (ことわざ) - できるだけたくさん! **一般的な知������������** * 石の上にも三年 (いしのうえにもさんねん) - Perseverance will pay off. * 七転び八起き (ななころびやおき) - Fall seven times, stand up eight. * 継続は力なり (けいぞくはちからなり) - Persistence is power. * 急がば回れ (い��がばまわれ) - Haste makes waste. * 井の中の蛙大海を知らず (いのなかのかわずたいかいをしらず) - A frog in a well knows nothing of the great ocean. * 良���は���に苦し (りょうやくはくちにくい) - Good medicine tastes bitter. * 猿も木から落ちる (さるもきからおちる) - Even monkeys fall from trees. * 転石苔を生ぜず (てんせきこけをしょうぜず) - A rolling stone gathers no moss. * 覆水盆に返らず (ふくすいぼんにかえらず) - Spilled water will not return to the tray. * 後生の祭り (ごしょうの�����り) - Too late for regrets. * 習うより慣れろ (ならうよりなれろ) - Experience is the best teacher. * 鉄は熱いうちに打て (てつはあついうちにうて) - Strike while the iron is hot. ... Description This is the same issue as #5285. While #5285 is about @langchain/google-vertexai, this issue also occurs in @langchain/google-vertexai-web. The problem occurs when a stream chunk is cut in the middle of a multibyte character. For detailed reasons, please refer to #5285. I will submit a Pull Request with the fix shortly. System Info macOS node v20.12.2 langchain versions $ npm list --depth=1 | grep langchain ├─┬ @langchain/google-vertexai-web@0.0.25 │ ├── @langchain/core@0.2.23 │ └── @langchain/google-webauth@0.0.25 ├─┬ @langchain/google-vertexai@0.0.25 │ ├── @langchain/core@0.2.23 deduped │ └── @langchain/google-gauth@0.0.25 ├─┬ langchain@0.2.15 │ ├── UNMET OPTIONAL DEPENDENCY @langchain/anthropic@* │ ├── UNMET OPTIONAL DEPENDENCY @langchain/aws@* │ ├── UNMET OPTIONAL DEPENDENCY @langchain/cohere@* │ ├── UNMET OPTIONAL DEPENDENCY @langchain/community@* │ ├── @langchain/core@0.2.23 deduped │ ├── UNMET OPTIONAL DEPENDENCY @langchain/google-genai@* │ ├── @langchain/google-vertexai@0.0.25 deduped │ ├── UNMET OPTIONAL DEPENDENCY @langchain/groq@* │ ├── UNMET OPTIONAL DEPENDENCY @langchain/mistralai@* │ ├── UNMET OPTIONAL DEPENDENCY @langchain/ollama@* │ ├── @langchain/openai@0.2.6 │ ├── @langchain/textsplitters@0.0.3
Environment KFP SDK version: kfp==2.0.0b16 All dependencies version: kfp==2.0.0b16 kfp-pipeline-spec==0.2.2 kfp-server-api==2.0.0b1 Steps to reproduce When running the code snippet below the following error is raised: kfp.components.types.type_utils.InconsistentTypeException: Incompatible argument passed to the input 'val_a' of component 'add': Argument type 'STRING' is incompatible with the input type 'NUMBER_INTEGER' @dsl.component() def add(val_a: int, val_b: int) -> int: return val_a + val_b @dsl.pipeline() def model_training_pipeline() -> None: with dsl.ParallelFor( items=[{"a": 1, "b": 10}, {"a": 2, "b": 20}], parallelism=1 ) as item: task = add(val_a=item.a, val_b=item.b) compiler.Compiler().compile( pipeline_func=model_training_pipeline, package_path="/app/pipeline.yaml" ) Expected result According to the ParallelFor documentation, the code sample above should compile without errors. The add component should receive the values of the dictionaries as integer arguments. Materials and Reference The code snippet below is a modification of the code snippet above, changing the add component to accept string arguments. @dsl.component() def add(val_a: str, val_b: str) -> int: return int(val_a) + int(val_b) @dsl.pipeline() def model_training_pipeline() -> None: with dsl.ParallelFor( items=[{"a": 1, "b": 10}, {"a": 2, "b": 20}], parallelism=1 ) as item: task = add(val_a=item.a, val_b=item.b) compiler.Compiler().compile( pipeline_func=model_training_pipeline, package_path="/app/pipeline.yaml" ) The pipeline compiles without errors with this modification, however it fails to run in Google Vertex Pipelines. The add component doesn't even run and throws the following error in the UI: Failed to evaluate the expression with error: INVALID_ARGUMENT: Failed to parseJson from string.; Failed to evaluate the parameter_expression_selector. As the component's code is not even executed, it seems that the problem occurs when executing the DAG. Here is the content of the pipeline.yaml that was compiled. # PIPELINE DEFINITION # Name: model-training-pipeline components: comp-add: executorLabel: exec-add inputDefinitions: parameters: val_a: parameterType: STRING val_b: parameterType: STRING outputDefinitions: parameters: Output: parameterType: NUMBER_INTEGER comp-for-loop-2: dag: tasks: add: cachingOptions: enableCache: true componentRef: name: comp-add inputs: parameters: val_a: componentInputParameter: pipelinechannel--loop-item-param-1 parameterExpressionSelector: parseJson(string_value)["a"] val_b: componentInputParameter: pipelinechannel--loop-item-param-1 parameterExpressionSelector: parseJson(string_value)["b"] taskInfo: name: add inputDefinitions: parameters: pipelinechannel--loop-item-param-1: parameterType: STRUCT deploymentSpec: executors: exec-add: container: args: - --executor_input - '{{$}}' - --function_to_execute - add command: - sh - -c - "\nif ! [ -x \"$(command -v pip)\" ]; then\n python3 -m ensurepip ||\ \ python3 -m ensurepip --user || apt-get install python3-pip\nfi\n\nPIP_DISABLE_PIP_VERSION_CHECK=1\ \ python3 -m pip install --quiet --no-warn-script-location 'kfp==2.0.0-beta.16'\ \ && \"$0\" \"$@\"\n" - sh - -ec - 'program_path=$(mktemp -d) printf "%s" "$0" > "$program_path/ephemeral_component.py" python3 -m kfp.components.executor_main --component_module_path "$program_path/ephemeral_component.py" "$@" ' - "\nimport kfp\nfrom kfp import dsl\nfrom kfp.dsl import *\nfrom typing import\ \ *\n\ndef add(val_a: str, val_b: str) -> int:\n return int(val_a) +\ \ int(val_b)\n\n" image: python:3.7 pipelineInfo: name: model-training-pipeline root: dag: tasks: for-loop-2: componentRef: name: comp-for-loop-2 iteratorPolicy: parallelismLimit: 1 parameterIterator: itemInput: pipelinechannel--loop-item-param-1 items: raw: '[{"a": 1, "b": 10}, {"a": 2, "b": 20}]' taskInfo: name: for-loop-2 schemaVersion: 2.1.0 sdkVersion: kfp-2.0.0-beta.16 Impacted by this bug? Give it a 👍.