Projects
AI projects JTPA members are building. Finished work, prototypes, and work in progress are all welcome.

使いやすい空き家探しサイトがなかったのでAIでマシなのが作れるか試してみた
by
@masayo何を作ったか 日本語で空き家情報を一括で検索できるWebアプリ(関西エリアのみ) なぜ作ったか 人口減少や高齢化の問題によって、日本には約900万戸もの空き家があると言われています。相続したもののすでに別の場所で暮らしていてその家に住む予定がなかったり、長年手付かずのままで老朽化した家は修復に多額の費用がかかることもあり、税金を払い続けるよりも手放したほうが経済的、というのが大きな理由です。そういった背景があり、無料または非常に安い価格で売り出されている空き家が日本各地で増えています。 ここ数年日本への移住に興味を持つ外国人の間でも空き家が注目されるようになっており、私の相棒もその一人です。現在、空き家の情報は2つの不動産サイト、各自治体のサイト、そして紙媒体などに分散しており、物件を探すのは意外と面倒です。外国人向けにAkiyaMartのような英語で情報を提供しているサイトもありますが、「下水」のような重要な情報が省略されていて、結局リンク先の元の掲載サイトで確認しなければならないことも多々あります。 プロジェクトのゴール 今回もGemini Antigravityを使って作ってみました。MVPは関西の4県のみ。大きな目的は2つ。 物件情報はあちこちに分散されているので表示内容やラベル名がバラバラ。これを統一して表示することができるか 町名の情報と物件の写真をGoolge Mapsのストリートビューの画像と照合して物件の住所を特定できるか 問題点と、その回避方法など スクショからすぐにピンとくるかもしれないですが、レイアウト等のデザインは某民泊プラットフォームのパクリ、ロゴは某アニメのタイトルデザインのパクリです。「具体的な例を出した時にAIはどれくらい忠実に真似できるか」というのを試してみました。結論から言うと、「かなり細かいところまで真似できる」です。 サイトのLook and Feel / Visual Design まず最初のプロンプトで、サイトの意図と見た目の詳細な指示(「AirBnBのホームページみたいな感じで」)というのを出したらかなり想像に近いものが出来てきました。こういう感じにしたい、という具体的なイメージがもしすでにあるのであれば、スクショを貼るのはすごく効果的だと思います。以下がAIが最初に生成したページです: 想像に近かったとはいえ、修正依頼はいくつか出しました。AIで生成されるデザインにはいくつか特徴があり、この「AIのクセ」のようなものを理解したうえで、デフォルトのUIでOKか修正させるかを判断するのをおすすめします。 とりあえずアイコン好き。隙あればあちこちに入れてくる。 とりあえず#タグも好き。本当に必要かどうかは構築者が判断しましょう。 Dividerも好き。必要以上にDividerを入れると画面がごちゃごちゃします。 情報をContainer/Boxに入れて整理しようとする。これも逆に情報の関連性がわかりづらくなることがあります。 サイトタイトルの前にアイコン、下にタグラインを入れる。タイトル名はたまに重複して表示。必要に応じて修正しましょう。 以下が修正後のホームページです: サイトのロゴ サイト名がまだ決まってなかったので、AntigravityとChatGPT両方でいくつかのアイデアを試しました。最終的には「空き家さがそ!」に決まりましたが、ChatGPTの方が若干元ネタのロゴに忠実なように感じました。ただ、AntigravityでもChatGPTでも、細かい修正依頼、例えば「花と葉っぱのイラストだけとって」とかは苦手で、依頼を無視して全く別のバージョンを作ってきます。結局は以下のような作業法が一番効率が良かったです。 「これのココとココを修正すれば使える」という段階までたどり着いたら画像をダウンロード そのファイルをイラレで開く 画像をトレースしてVectorに変換 手動で細かい修正をいれる 現在プロダクトデザインの現場はFigmaのいわゆる無双状態ですが、今後AIでのデザインがさらに普及すれば、もしかしたらまたアドビの時代が来るかもしれないですね。 プロジェクトのゴールの結果 プロジェクト開始前のゴールだった、「#1 物件情報を統一して表示することができるか」と「#2 物件の住所を特定できるか」について、結論は以下になりました: #1 はできるけどかなり手動の作業が必要になるんで面倒 #2 はAIでも無理 物件情報を統一して表示することができるか たとえば指示が、 であれば、「建物面積」の情報はもってこれるのに、なぜか「建物構造」はうちのサイトでは「記載なし」になっている場合が多い。元サイトには両方のラベル(まんま同じ)があるのでもってこれないはずはないのに??ちなみに物件の画像でも同じ問題がありました。スポットチェックでこういう問題を見つけたら指摘し、修正する、の繰り返しにかなりの時間を費やしました。でも400件以上の物件のチェックをいちいちできないので、結果的には「情報は間違っている可能性がある」というあまり理想的ではない結論に至りました。 物件の住所を特定できるか 結論からいうと、AIが自信満々だった割には「できなかった」。リンクされたGoogleマップに一応位置情報ピンが立っているが、その町/村の真ん中あたりに適当にピンを立てただけだと思われる。もう少し調査する必要あり。 作ったことで得られたインサイトなど サイトが不安定 前回の高校のリサーチサイトと違って、今回は400件以上のデータを扱うためかエラーが多く、1つのエラーを修正させたら他の無関係な5つの箇所が壊れる、という状況に数回陥りQAにかなりの時間を要してしまった。 データの信憑性 なぜAkiyaMartのような英語サイトが、元サイトに掲載されている物件についての全ての情報を表示できないのか理解しました。不可能に近いからです。全く同じラベル名でも探知できず見過ごすのに、ラベルが少しでも違えば(例:築年数 vs 建築時期)うちのサイトでは「記載なし」になります。ならばユーザには元サイトへ行ってもらって確認してもらうのが一番安全です。 データ構築、管理 前回作った高校リサーチのサイトでも同じことを思いましたが、プロのエンジニアのヘルプなしでは複雑なサイトを安定して稼働させるのは難しいです。デザイナーの私には裏でどうやって情報が構築、処理されているかがわからないので、エラーになった場合の根本の原因がわからずAIにどう修復すべきかの指示がだせないため、エラー修復にかなりの時間(token)を費やしました。例えばデプロイした後、ページが空白だということが何回かあったので、相棒(エンジニア)に原因を調べてもらったら、「Local DB File」「画像がキャッシュされてない」などいくつか指摘されました。 最後に感想 デザイナーがAIを駆使して、見た目がよく使いやすいプロダクトを構築することは可能です。ただ、安定性やパフォーマンスにも配慮しながらプロダクトを運営していくには、やはりエンジニアの力が不可欠です。AIの導入によって開発・プロダクトチームの作業効率が格段に上がったとはいえ、デザイナーとエンジニアが一緒にプロダクトを作っていくスタイルは、まだまだこれからも健在のようです。
Gemini
息子の高校のリサーチにまたSpreadsheetを作るのが面倒だったのでウェブアプリを作った
by
@masayo何を作ったか サンフランシスコ市内の高校をリサーチするための保護者用のツール なぜ作ったか うちには来年高校に進学する息子がいます。過去2回、小学校、中学校と学校が変わる度に学校リサーチのための情報(学校の基本情報、テストスコア、家からの距離、運転に要する時間、学校見学日、申し込み締め切り日、メモ等)をspreadsheetにいちいち細かく入力していました。しかし3回目ともなるといい加減この動作が面倒になってきたので、今回はvibe codingを試してみることにしました。Gemini Antigravityを使い、制作にかかった期間は2日程度でした。 このウェブアプリでできること SF市内の全ての高校の情報がみれる 学校のタイプ(public, private, charter, religious)や家からの距離でフィルタできる 授業料、生徒数、SATスコア等でソートできる 地図上で学校の位置が確認できる 自分の「My List」が作れる 学校をside by sideで比較できる 作ったことで得られたインサイトなど 本職はプロダクトデザイナーなので私の意見はデザイナーよりの意見になります。 とりあえず早い アイコンを右に5ピクセル動かすためだけにいちいちプロンプトを入力するのは少々面倒に感じましたが、AIを使うことで得られるメリットはそんな面倒さをはるかに上回るものでした。まるでどんなに面倒臭い要求にも文句を言わず根気強くかつ意欲的に応えてくれるデベロッパーと一緒に仕事をしているような感覚でした。そして仕事が無茶苦茶早い。知り合いのデベロッパーの方が「一度AIを使って仕事したらもう前みたいにコード書くのには戻れない」と言ってたのを、一瞬で理解しました。 生成されたデフォルトのUIはイマイチ Geminiが最初に生成したページは、そのままでも使えないことはないけどなんか使いづらい、というよく見る「AIが生成しました」という製品そのものでした。なので、「これをいかに使いやすいものにするか」というゴールに作業のほとんどの時間を費やしました。ユーザは自分なのでこの作業はとても楽しかったです。 デザイナーの役目 今後AIを使って構築された製品がどんどん増えていった場合、他のAI製品との差別化が重要な課題になってくると思います。同じ目的のための製品が2つあるとして、もし機能や値段等のもろもろの条件が同じだったらどちらの製品を選びますか?恐らく「使い勝手」がかなり重要なんじゃないでしょうか?使い勝手が悪い製品は、ストレスに感じるだけでなく、余計な時間を費やしてしまい、生産性にも影響します。でもチーム内にデザイナーが一人でもいれば、その製品が「いかにもAIで生成しました」とみえてしまうのを防ぐだけでなく、実際に製品を使うユーザの視点に立ち、使い勝手の良い、直感的な製品をつくるヘルプになります。 以下がUX改良後のページです。 デザイナーも開発チームの一員 今までの「デザイナーはUXチーム、デベロッパーは開発チームに属す」というチーム構成でなく、デザイナーもデベロッパーと同様に同じチームでAIで製品を構築するようになるかもしれません。 【従来】デザイナーがmockupをFigmaで作成 → デベロッパーがFigmaのDev modeをもとにコードを書く 【今後】デベロッパーがAIで製品を構築 → デザイナーがUI/UXをAIに改善させる そして、コードレビューと同じような、UI/UXやアクセスビリティからの観点を重視したデザインレビューはどのプロジェクトにも必須になるかもしれません。 最後に デザインと開発の境界がこれまで以上に近づいている中で、製品が本当にユーザーにとって使いやすいものになっているかを判断するには、デザイナーの視点が欠かせないことを改めて実感しました。
Gemini
I rebuilt my blog's shogi AI in a day with a fleet of AI agents — from bug hunts to WASM and NNUE distillation
by
Yudai YaguchiThe homemade shogi AI on my personal site (meetyudai.com) was, in the words of its owner (an amateur 2-dan player), "way too weak." This is the record of running up to five Claude Code subagents in parallel to see how far I could push it in a single day. It keeps not just what worked but the failed ideas that got mercilessly rejected by A/B testing — the raw diagnostic logs, the catalog of failures, the real numbers, and the lesson (learned the hard way, more than once) that polishing a proxy metric doesn't win you games. Cost: essentially nothing (electricity and LLM usage). This is the overview; the raw logs and code are in the full write-up on my blog. The gist (three lines up front) The real cause of the "nonsense moves" was neither the search nor the eval: an opening-book fallback was bypassing the search engine and answering instantly, a wiring bug. A thinking-time log was the smoking gun. Small tweaks to the handwritten engine were "no effect" 8–9 times out of 10 under production time controls. What worked was structural: a TypeScript→WebAssembly port (15× faster search) and, on top of it, NNUE distillation. The arc was 19.6% → 32.1% → 77.1% win rate vs the handwritten eval. At the end I lost to it in production, discovered a disease called sigmoid saturation, and cured it by rebuilding the data. Finally the author confirmed, in real games, that it "definitely got stronger." What I built I built a shogi AI that runs entirely inside the browser (WebAssembly), with no backend at all. Open the page and it fetches the eval weights (a 1.1 MB static file) asynchronously; from there it reads a few moves ahead and plays using only your browser's CPU. It runs on a phone browser. It has two pillars. The first is the search engine — the "read ahead" part. Shogi averages 80–100+ legal moves per position, and multiplying that across several plies gives astronomical trees. You can't read everything, so you prune obviously-bad branches early. The toolkit: negamax with alpha-beta pruning (cut branches that can't beat what you've already found, assuming the opponent replies optimally), principal-variation search, a transposition table (a cache of already-searched positions), late-move reductions (search later-ordered moves shallower), null-move and futility pruning, a quiescence search (read on until captures settle), and a dedicated mate solver. In short, a box of tools for "cutting corners intelligently so you can read deeper." The second is the evaluation function — the "eyes" that turn the leaf position of a read into a single number: who's ahead, by how much. No matter how deep the search, it's worthless if it can't score the leaves correctly. It started as a handwritten, rule-based eval; in the end I replaced it with an NNUE (neural-net eval). That's the centerpiece of the story. The "browser-only" constraint matters more than it sounds. Training uses a GPU, but running it (inference) is CPU-only — and it has to be strong under a harsh budget: a few hundred milliseconds on someone else's phone. That constraint drives every later decision: keep the model tiny, quantize it, speed it up with SIMD. Why I built it As a 2-dan player, I found the AI on my site honestly "too weak." Two symptoms. First, it lost the same way every time to the basic amateur "climbing silver" (bōgin) attack — the ▲2六歩→2五歩→3八銀→2七銀→2六銀→1五銀… march that's on page one of every beginner's book. Losing to that every time isn't a matter of counter-strategy; it means the reading itself is broken. Second, it occasionally played completely nonsensical moves — dropping a pawn uselessly in its own camp, walking its king into danger. Moves no human would ever make. The direct motivation was that leaving it broken bugged me. But there was a second one: an experiment — how far can a fleet of AI agents rebuild a piece of software in one day? Shogi AI is an ideal subject, for two clean reasons: a ground truth exists (YaneuraOu, an engine far beyond amateur-top strength), and strength is directly measurable. So you can't escape into "it feels better." Measure, and you get a verdict. How I ran the agents Before the technical details, the process itself — because it's half the point. I ran up to five subagents in parallel. Responsibilities split into "speed up search," "train the eval," "curate the opening book," "harden the code (address review findings)," and "write the article." I stayed the integrator: read each agent's result and decide what to try next, so a human bottleneck doesn't stall the independent work. The problem is that five agents editing the same repo at once will clobber each other. I solved it by giving each agent its own git worktree — multiple working copies of the same repo. Agent A can rewrite the search code while Agent B touches the training script without stepping on each other's files. Cheap isolation, no merge chaos. And — most important — every "behavior-changing" change had to pass an A/B test. I trusted no "feels stronger." Each change played N games against the previous version at production time controls, and got adopted only if it genuinely won more. Thanks to this, 8–9 out of 10 ideas I tried were rejected. That's not a failure; it's the whole point. Most plausible ideas don't survive measurement, and building the machine to reject them mechanically, up front, was the single biggest win. The other mandatory gate was bit-exact parity. Later I ported the engine to WebAssembly, and I refused to allow "faster, but the moves changed slightly." The ported version had to return the same move, same score, same node count, same leaf count as the handwritten TypeScript version — verified on thousands of positions and by exhaustive legal-move counts (perft: 25,440 nodes at depth 3 from the initial position, matching known numbers even with drops in hand). Only the version that matched 100% went to production. Different speed, identical moves — that closed the door on "optimization sneaks in a bug." Phase 1: reproduce "weak," and find the real culprit Faced with a weak AI, the temptation is to guess "the eval's bad" and start fixing. But that's a guess. I decided to get hard evidence first. I turned a losing game — the collapse to bōgin — into a reproducible script as a fixed game record. That script feeds positions, one by one, through the exact production AI path, and logs the returned move, score, material, and how long it thought. That surfaced the decisive clue: the AI was returning each move in 1–23 milliseconds. Real search of several plies takes hundreds of ms to seconds. An instant 1–23 ms reply means it isn't reading at all. Chasing it down, the truth was: an opening-book fallback was bypassing the search engine entirely. That mechanism is supposed to instantly return a recorded move for positions that are in the book. But a bug made it return a "plausible-looking" move even for positions outside the book — with no search. So even at critical endgame moments, the AI was choosing moves on vibes, reading nothing. That was the source of the nonsense. This is the biggest finding. The cause of the weakness was neither the eval nor the search algorithm — it was a wiring bug sitting in front of both. However much you polish eval or search, if the search never gets called, it all gets bypassed. Deleting that fallback eradicated the instant-nonsense class of bug. The lesson is clear. Inferring the cause (bad eval) from the symptom (bad move) usually misses. Hit it with hard evidence. Thinking time — a seemingly irrelevant number — was what cracked it. Phase 2: rebuild the search (small tricks barely helped; the structural change did) With the instant-answer bug gone, I wanted to get stronger while actually reading. I started with the search itself. I tried textbook tricks: another layer of pruning, better move ordering (searching good-looking moves first makes pruning bite), deeper mate search, tuned margin constants. In theory each should "read deeper" or "cut waste." But under rigorous A/B at production time controls, most of it was "no effect." Improvements that should deepen the read didn't move the win rate at all. This foreshadows what bit me later: a deeper read doesn't convert to wins if the eval can't correctly judge the positions you reach. What worked wasn't a trick — it was swapping the substrate. I ported the handwritten TypeScript engine to WebAssembly (WASM), a low-level format that runs at near-native speed in the browser and crunches numbers far faster than JavaScript. Moving the same algorithm to WASM alone gave: 15× faster search +3–4 ply of depth at the same time budget a 10–0 record against the old engine In shogi, "+3–4 ply deeper" is a rank's worth of strength. I didn't make the algorithm one bit smarter — just changed the runtime. Speed, not smarts, was the bottleneck — a blunt but crucial lesson. Phase 3: distill the eval (NNUE) With search fast and deep, it was time to strengthen the leaves — the "eyes," the evaluation function. Until then it was handwritten: piece values (a pawn ≈ 100, a rook ≈ 1000…) plus terms for king safety, piece activity, and so on, summed by human-written rules. Readable and decent, but capped at the range of terms a human thinks of. The subtle goodness of a shape can't be fully captured in rules. So I replaced it with machine learning, via distillation. The idea: Have the strong engine YaneuraOu score millions of positions at fixed depth. That's the teacher data. YaneuraOu is strong but heavy — it can't run in a browser. But as a "teacher who grades your answers," it's ideal. Have a small neural net imitate those scores. The net is deliberately tiny: roughly 2,268 board features → 256 → 32 → 1, with clipped-ReLU activation (a simple non-linearity that caps values that grow too large) and about 590k parameters. Tiny, because it has to produce an eval instantly on a browser CPU. This format is NNUE, and — fun fact — it was originally invented for shogi (chess's Stockfish imported it later). NNUE's strength: when the board changes by only one move, it can update the eval incrementally rather than recompute (the running state that enables this is the "accumulator"). Quantize the trained weights to 16-bit integers (round fine decimals to integers), compress to 1.1 MB, and serve them statically to the browser. The training target was — the engine's centipawn score (cp = hundredths of a pawn) squashed by a sigmoid into a win-probability-like 0–1. Remember that 600 in the denominator. It bares its teeth in the endgame. Data: three cycles of measurements NNUE didn't land in one shot. It took three rounds, each its own little story. Cycle 1 — a rout (19.6%). The first trained NNUE, in equal-time self-play against the handwritten eval, won just 19.6%. A blowout. Yet the inference was perfectly correct — bit-identical across the training framework, TypeScript, and WASM on hundreds of positions, with matching node counts at equal time (the incremental accumulator worked flawlessly). The implementation was right; the model itself lost. The post-mortem is the most important lesson here. I'd been judging model quality by "how close it is to the teacher's scores." 2–2.5× closer than the handwritten eval — so it should be stronger, right? But that metric is a bad predictor of match strength. Here's why: what alpha-beta needs is not the absolute eval value but the relative ordering of sibling moves. As long as "this move beats that one" is right, search works. The net's average error was larger than the gap between typical candidate moves (<100cp), so it scrambled the ordering. The handwritten eval, even with an off absolute scale, was self-consistent, so a uniform bias was harmless to search. "Close to the teacher but with jumbled ordering" is weaker in search than "far from the teacher but order-preserving." That lesson held to the end. Cycle 2 — the reversal (77.1%). Guessing the cause was "error too big to preserve ordering = too little data," I greatly increased the teacher data and retrained. The win rate climbed 19.6% → 32.1% → 77.1%, clearly beating the handwritten eval. More data alone flipped a rout into a comfortable win. I also shipped pondering (thinking on the opponent's clock — a "permanent brain"), lifting mean reached depth 9.00 → 9.35. This finally reached production. Cycle 3 — speed, then a defeat and its cure. Now that it could win, I made it fast. WASM SIMD (one instruction computing several numbers at once) made the eval 6.2× faster, and I added multithreading (a Lazy-SMP-style parallel search; an estimated +58 Elo, though at n=24 it didn't reach significance, so I recorded it honestly as a point estimate). So far so good. And then — at the top difficulty in production, the author (2-dan) beat the NNUE. The thing I'd just strengthened tripped over its own feet in a real game. The diagnosis revealed the culprit. The main enemy: sigmoid saturation Recall the training target was . That design hid a trap for the endgame. A sigmoid flattens and pins near 1 for large inputs, near 0 for small ones. In won or lost positions the centipawn score is huge (say +3000cp), so is essentially 1.0 — maxed out. The problem: from there, moving the eval a bit — +3000 or +3500 — barely changes the output. So moves that should differ in value all collapse to nearly the same number. In the problem position from the diagnosis, all 71 legal moves collapsed into a 15cp band. To the AI, "every move is the same." So in a position where the win (or loss) was clear, it picked essentially at random and produced nonsense. The "nonsense move" in the game the author lost came from exactly this. Ironically, making it read deeper made things worse, by reaching more of those saturated positions. The fix was in the data, not the search. The earlier training data had thinned out decisive (lopsided) positions as "boring" — and that thin region was exactly where saturation lived. So I retrained with decisive positions deliberately over-sampled — up to about half the set — on 5.24M positions (labels at depth 12), to teach it the saturated region and let it tell tiny differences apart inside a big lead. Results: Move-value spread in the problem position recovered from 20cp → 532cp (26×): "all the same" became "clearly different." Blunders in that position halved, 8 → 4. 92.2% win rate vs the old NNUE; 84.4% vs the handwritten eval (at both 1000 ms and 2000 ms). And finally, the author confirmed in real games that it "definitely got stronger." Not a proxy metric — the author playing it and admitting it. That was the only pass/fail I trusted. What I learned (failures and all) Honestly, the biggest payoff of the day was the record of failures, more than the wins. A good proxy metric doesn't mean you win. Doubling "closeness to the teacher" didn't make it stronger. The final judge is always the same: do you win the actual game — ideally against a human playing the openings you actually face? Bench numbers are only a mid-way signal. Verification itself is full of traps. Self-play statistical degeneration (self-play skews the win/loss when both sides share quirks), time-control bias (the budget you measure at changes the conclusion), and a config mismatch between old and new defaults — each nearly led me to "conclude it got stronger" by mistake. The only defense is to measure under production-equivalent conditions. Catalog of what didn't work — a memorial to the plausible ideas that died on measurement. King-piece (KP) features (a powerful method adding fine king-to-piece relations, but at 1M positions it made things worse via data dilution), check extensions (lost the A/B), drop-move late-move pruning (same), deepening the mate solver (no change). The capstone: full bitboards. Holding the board as bits of an integer and processing with bit operations is the core of a native engine's speed. I tried to copy it — but in 32-bit JavaScript the 81 squares don't fit in a single integer. Resolving sliding-piece attacks straddles words awkwardly, and a slider-list prototype came out 2× slower than the array ray-walk the JIT already optimizes well. Theoretically faster, slower here. A genuinely different arena from native C++. How I'd make it stronger from here Honestly: the browser arena has a ceiling. The search side is done for practical purposes in this environment. With SIMD, multithreading, and bit-exact speedups all in, there's no structural "depth jump" left to grab. To go further, the lever is the eval (data) side. The strongest candidate is a self-play data loop — have the current strong engine play itself to gather "positions that arise in genuinely strong play," re-label them with YaneuraOu, and retrain, closing a positive loop. Caveat: the grader is still YaneuraOu, so the ceiling is YaneuraOu's judgment (this is not true self-improvement à la AlphaZero, which learns from game outcomes themselves). The other lever is hunting concrete weaknesses the author finds in real games. The saturation discovery was exactly that: a single real game pointed at the weak spot more sharply than any proxy metric could. Cost and wrap-up Total cost: electricity and LLM usage only. Time: effectively one day. From "way too weak" to "the author admits it's definitely stronger," reached by running AI agents in parallel plus the unglamorous discipline of A/B testing and bit-exact verification. Looking back, this isn't a story of "one clever discovery." Quite the opposite: measure, discard the failures, keep only what survives — that boring repetition is what worked. 8–9 out of 10 flashy ideas died; the surviving few (the WASM port, more data, killing saturation) carried the whole thing. Reliably rejecting the changes that make it weaker mattered far more than being clever. The full version (raw logs, code, all the numbers) Everything above is a digest. The raw debugging logs, the details of every failed approach, the per-cycle measurement graphs, and the code are all in the full write-up. There's also a beginner primer explaining NNUE, distillation, backprop, and quantization from scratch. 👉 Full write-up: https://www.meetyudai.com/blog/applied-algorithms/9fpLthtYgHvnImuFR0Jf 👉 Primer (for ML beginners): https://www.meetyudai.com/blog/applied-algorithms/H9beqVVY7h5qc3hNfskR

JTPA Community Hub: A community platform for running AI meetups
by
Yudai YaguchiWhy I Built It Bay Area AI / JTPA activities can easily become scattered across many tools: event announcements, RSVPs, presenter info, slide sharing, check-in, project showcases, blog posts, Q&A, and polls. Organizers need a reliable way to manage events, while members need one place to find upcoming events, past materials, and what others are building. I built this as a unified community hub for AI meetup operations. The Showcase feature you are reading now is part of the same platform. What It Does JTPA Community Hub is a web application for running the Bay Area AI / JTPA community. It includes: Event listings, event detail pages, RSVPs, and waitlists Presenter registration, talk titles/abstracts, and slide or recording links QR-code check-in for event day attendance AI project Showcase submissions, admin review, comments, and likes Member blog posts, Q&A, guides/notes, and community polls Google sign-in, public profiles, and member dashboards Admin tools for events, reviews, attendee CSV export, and roles Japanese and English localization The goal is not just a public website. It is an operational backbone for a recurring AI meetup and a place where knowledge can accumulate over time. How It Works The app is built with Next.js 16 App Router and React 19, hosted on Firebase App Hosting. Firestore stores data, Firebase Auth handles Google OAuth, and Firebase Storage stores project images, event assets, and presentation files. A key design choice is that almost all Firestore reads and writes go through the server. Server Components load page data, and Server Actions handle RSVPs, submissions, approvals, comments, likes, and check-in. The browser does not directly write application data to Firestore. Authorization is centralized in helpers such as , , and . Large files use a different path: images and slides upload directly from the browser to Firebase Storage. After upload, a Server Action records only the metadata in Firestore, so Cloud Run does not proxy heavy file transfers. How I Used AI to Build It Most of the implementation was developed with Codex and Claude Code. I did not treat AI as a black-box "build the whole app" button. I broke the product down feature by feature and gave the AI the relevant code, constraints, expected behavior, and verification commands. The typical loop was: I defined the need, such as waitlisted RSVPs, QR check-in, or reviewed project submissions I asked AI to read the data model, Server Actions, Firestore rules, and UI patterns AI proposed a plan, and I checked authorization, data consistency, and failure cases AI implemented a small change I ran , , , and rules tests, then fed CI or review feedback back into AI AI was especially useful for expanding consistent patterns: Firestore schemas, Server Actions, admin screens, Markdown editors, i18n copy, tests, and docs. Once a pattern existed, AI helped apply it to events, projects, posts, Q&A, polls, comments, and likes. The parts that still needed strong human control were security, permissions, moderation workflow, product decisions, and UX. I treated AI-generated code as a draft, especially around who can perform an action, what happens if a write fails, and whether a pending or rejected submission can become public. What Was Hard The hardest part was balancing a simple community-facing experience with the strictness required by an operations tool. Members should see a clean site, while the system still handles RSVP counts, waitlists, presenter counts, attendance counts, approval status, ownership, roles, and file permissions correctly. QR check-in was a good example. It needed event-specific validity windows, login redirects back to the QR URL, duplicate check-in protection, admin corrections, and cumulative attendance counts. Next.js 16 also has meaningful changes compared with older versions, so it was important to make the AI read local docs and APIs instead of relying on stale assumptions. What I Learned The most important lesson was that AI coding works best when constraints are clear. Prompts like "read this file," "follow this pattern," "keep this authorization boundary," and "run these tests" were much more effective than vague requests. AI can speed up implementation dramatically, but it does not replace product judgment. Decisions such as which content requires review, whether Q&A should publish immediately, and what event attendees should provide need to come from people who understand the community. What's Next Next, I want to add AI-powered summaries for posts and Q&A, automatic event recap drafts, recommendations for relevant projects or guides, and better analytics for organizers. The long-term goal is to make community knowledge easier to find and reuse after each meetup ends. Detailed Project Case Study I also wrote a more detailed English case study about this project on my portfolio site. It summarizes the product goals, my role, key features, technical architecture, AI-assisted development workflow, challenges, and outcome from a professional project perspective. English case study: JTPA Community Hub Project Description

manabiQ: 社内のマニュアルやSOPを、AIでスマホ対応の短時間トレーニングに変換する新人教育・オンボーディング支援サービスを、バイブコーディングで作りました。
by
@kazuookumura何故作ったか AIシステム開発のビズデブ(事業開発)活動をしている中で、私を含め多くの人が、もともとの基礎知識が無いために案件化しない、ということが頻発していました。そこで当初は、AIに関する基礎知識講座を作るつもりでした。 しかし、お客様のお話を聞いているうちに、特に流通・小売の領域では、AI以前の問題として従業員の入れ替わりが激しく、同じ研修を高頻度でやり直していることを知りました。しかもベテランを現場から外して新人に教えるので、教える側のコストも大きい。「すでに手元にあるマニュアルを、初出勤前にスマホで終わる研修に変えられないか」——その繰り返し作業を肩代わりしたくて作りました。 何を作ったか ・PDF・Word・テキスト、Google Drive・OneDrive の資料をアップロードすると、AI がクイズ付きの5〜15分のコースを自動生成する SaaS です。 ・受講者はマジックリンクを開くだけ(アプリ不要)でスマホ受講でき、日本語・英語・スペイン語をワンクリックで切り替え。管理者はクイズの結果で「誰が現場に出る準備ができたか」を把握できます。 工夫したところ ・Gemini呼び出しが混雑で失敗しても少し間隔を空けて自動で再試行する仕組みを入れ、生成が途中で止まらないようにしています。 ・言語を TypeScript に統一: フロントもバックエンドも同じ TypeScript(Node)で書けるので、言語を行き来せずに済み、少人数でも開発が速い。 ・AI生成しっぱなしでは大きな誤りが出てしまうので、「元資料との整合性チェック+人の承認(HITL)」をセットにしてみました。 ・コスト最適化: 通常は軽くて速い Gemini Flash を使い、簡単な処理では Gemini の「思考モード」をOFFにしてトークン(=コスト)を節約するようにしました。 ・セキュリティ:全API を「認証→レート制限→入力検証→処理→ログ無害化」という同じ順序にしたことで、漏れが減り、あとの管理がラクになった気がします。 仕組み モデル: Google Vertex AI / Gemini 2.5 Flash 生成パイプライン(Agentic): 資料抽出 → コース構成 → 各モジュール本文 → クイズを段階生成 整合性チェック(Fidelity Check): 生成結果を元資料と突き合わせ、捏造(ハルシネーション)や抜け漏れを検出 Human-in-the-Loop: 公開前に人が確認・編集・承認 多言語対応:英、日、スペイン語 Text-to-Speech 読み上げ サポートチャットにも AI(RAG) を活用 技術スタック Next.js 16 / React 19 / TypeScript、Firebase Auth・Firestore 決済 Stripe インフラ Google Cloud Run / Cloud Build / Artifact Registry(Docker, node:20-alpine) です。 今後やりたいこと ・SMS対応(今はいちいちメールソフトを開けてリンクをクリックしないといけないのでめんどくさい。) ・Gusto、BambooHR、日本だとsmartHR、freeeなどの中小企業向けの人事・労務プラットフォームと連携し、新入社員を登録した瞬間にオンボーディング研修が自動で始まる流れを作っていきたい。
![Cover image for 株取引で予想が当たるYoutuberを見つける [株取引自動化 Part2]](/_next/image?url=https%3A%2F%2Ffirebasestorage.googleapis.com%2Fv0%2Fb%2Fjtpa-main.firebasestorage.app%2Fo%2Fprojects%252Fs20K36xPeMfgZrVuuIYKnMvxDO12%252F1781293156428-%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588_2026-06-12_12.38.36.png%3Falt%3Dmedia&w=3840&q=75)
株取引で予想が当たるYoutuberを見つける [株取引自動化 Part2]
by
@jinMarket Sentiment Explorer (2) 何故作ったか 株式市場について様々なYoutubeチャンネルが存在しているが、予想が当たるYoutuberを見つけたかった 何を作ったか 毎日指定した Youtube Channelを巡回し最新のtranscriptを取得し、Claude Codeに内容を分析させ、市場の今後のセンチメントを数値として把握できるようにする。次に実際の各セクターのその後の値動きを数値化し、両者の相関を計算することで予想の当たりやすさを数値化する。 仕組み Youtube Channelを巡回しtranscriptを取得します。こちらは別記事で詳細を解説しています。 フローチャートは下記のようになっています。この右側部分が本プロジェクトでの解説記事になります。 Claude CodeとChat GPTに手動で対話せさながらS&P500の各ティッカーをどれかのセクターに振り分ける まず、S&P500の各ティッカーシンボルとその該当セクター分けのリストを作ります。リストはClaude CodeとChat GPTでそれぞれに作らせ、2つのリストをそれぞれのエージェントに渡して検討させながら最終的に一つのリストを作成します。 基準日からの値動き率 (セクタームーブメント)を計算する Yahoo Financeで毎日のティッカーシンボルの終値を取得し、各セクターごとに各ティッカーの時価総額を用いて加重平均し、各セクターのインデクス価格を計算します。さらにはある日から2週間の各日の終値を加重平均し、基準日からその後どれだけ株価が動いていたかをセクタームーブメント指数として計算しておきます。 (ドットマーカー付きのグラフがセンチメント、実線だけのグラフがその後2週間のムーブメント) Youtuberの予想センチメントと、その後の値動きの相関を計算する その後、現在ある45日分のデータセットを使って各セクターごとにあるyoutuberが予想や所感を述べた場合に -100 100までのセンチメントが計算され、それに対して後日の値動き(ムーブメント指数)との相関を計算します。 どうやって作ったか、難しかったポイントなど 基本的に全てClaude CodeあるいはCodexに頼んでコードを書いてもらっています。 GUIはPythonでそのままコードが書けるようにStreamlitを使いました。 (これは後に後に分析されたセンチメントと実際の値動きの相関を分析するためにpythonのライブラリを使いたかったため) コツとしては、アルゴリズムを全てパラメーター化することでパラメータ探索を行い、データが溜まってきたところで随時アルゴリズムの最適化を行えるようになっています。 システム維持費用が高い Claude Code ($20/mo) システム開発、Daily Report 作成 Codex ($20/mo) システム開発、各video transcript/tweetからのセンチメント/リスク算出 Twitter API ($60/mo) Tweet 取得 (1日250件程度) 計 $100/mo 作ったことで得られたインサイトなど それなりに自分が感じていた所感と同じような結論が数値で得られた (このyoutuberは当たらないと感じていたら負の相関が示された) ただし、一部直感に異なる数値が得られているところもある 計算されたセンチメントを使って今後の株価変動を予想する場合、各セクター平均での結果の相関係数が 0.4だった。思ったよりも良い結果 予想の当たるYoutuberに高い荷重をかけてそれで予想システムの精度が上がるか検証したが、平均的な精度としては上がらなかった。 (予想が当たらないYoutuberでもオーバーフィッティングを妨げる効果がある?) 45日分程度のデータではまだまだ信頼度が低い 今後やりたいことなどがあれば とりあえずのシステムは完成したのでまずはよりデータを集めることに専念して、データが集まったところでセンチメントの予想アルゴリズムをエージェントに自動で修正させてるようにしたいです。 数千の人格がその状況でどう動くかをマルチエージェントを使ってシミュレーションする技術があるのでそれと繋げてみたいですね。 https://github.com/666ghj/MiroFish
情報取得/解析エージェントアルゴリズム最適化![Cover image for 最新のニュース/Youtube/Tweetを毎日取得してエージェントに解析させる [株取引自動化 Part1]](/_next/image?url=https%3A%2F%2Ffirebasestorage.googleapis.com%2Fv0%2Fb%2Fjtpa-main.firebasestorage.app%2Fo%2Fprojects%252Fs20K36xPeMfgZrVuuIYKnMvxDO12%252F1781246657091-sentiment.png%3Falt%3Dmedia&w=3840&q=75)
最新のニュース/Youtube/Tweetを毎日取得してエージェントに解析させる [株取引自動化 Part1]
by
@jinMarket Sentiment Explorer 何故作ったか 毎日通勤中に株式市況情報のYoutubeチャンネルを複数見てチェックしていたが、これを自動化したかった 何を作ったか 毎日指定した Youtube Channel, Website, X accoutを巡回し最新のtranscript/記事/Tweetを取得し、Claude Codeに内容を分析させ、市場のセンチメントを数値として把握できるようにし自分の代わりに毎日の分析を行わせます。 具体的にはそのセクターが上がると予想される期待の強さ(センチメント)と、現時点で不確定であるネガティブ要因(リスク)を分析します。 (一ヶ月の各セクターごとの分析された市場センチメント変化) 仕組み Youtube ChannelやXのアカウントを巡回しtranscriptや内容を取得します。一日に120件程度のyoutube チャンネル、250件程度のツィートを取得します。 現状でトータル1万件のvideo/news/tweetを取得しました。 (取得したyoutubeチャンネルのtranscriptの例) その後、それぞれに下記のようなプロンプトを使って各セクターの今後の予想やリスクを数値として取得します。 (得られたセンチメントデータの例。多数のセンチメントをあるアルゴリズムを使ってまとめあげてその日のセンチメントを算出する) 最終的に直近2週間のセンチメント変化+各youtube Channel/ツィートのサマリを全てエージェントに読ませてサマリーレポートを作成します。 ... (サマリーは長いので省略) さらに11種類の各種経済指標も毎日取得させ、それぞれの日次、週次、月次の変化も分析させてレポートを作成させます。 作成された経済指標サマリの例: こうして得られた各種情報に自分の現在のポートフォリオをAIが読める形(CSV)にしておき、Claude Codeに与えて運転中に音声で相談ができるシステムになりました。 フローチャートは下記のようになっています。(後半の"予想が当たる"YoutuberやXアカウントの算出” は別の記事で解説しています) どうやって作ったか、難しかったポイントなど 全てClaude CodeあるいはCodexに頼んでコードを書いてもらっています。 GUIはPythonでそのままコードが書けるようにStreamlitを使いました。 (これは後で分析されたセンチメントと実際の値動きの相関を分析するためにpythonのライブラリを使いたかったため) コツとしては、センチメント分析などでLLMを走らせたい場合にAPIを使うと非常に高くついてしまったため、CodexやClaude Codeをヘッドレスモードで呼び出して処理させている点です。これによって5h/1weekの復活枠を使って非常に安価に($20/mo)大量のトランスクリプト分析と日本語への翻訳を実現しています。 作ったことで得られたインサイトなど 今まで一日に3-4チャンネルのYoutubeを見るのが限界だったが、一気に120チャンネル以上網羅的にチェックできるようになった。英語のチャンネルも日本語にで読めます。 システムの設計にはソフトウェアエンジニア的なコツが必要 Youtuberは一般的にXユーザーよりも楽観的 バイアスのかからないシステムを組むことは非常に難しい 今後やりたいことなどがあれば 元々のフィーリングとして、全ての情報を数値として集約し予想を行わせる機械学習モデルでは限界があると感じていました。今回はセンチメントデータを数値としてまとめつつ、元の記事のサマリーや経済指標変化などは大量のテキストとして保存し混ぜて使うことに一定の手応えを得ることができました。 このまま企業の決算情報DBやチャート情報解析スキルと組み合わせることでより高度な資産運用エージェントの構築を目指そうと思っていますw。
情報取得/解析エージェント大量テキスト解析