TECH Streetのブログ - TECH PLAY

TECH PLAY

TECH Street

TECH Street の技術ブログ

å…š18ä»¶

はじめに 事前知識 スクラム Codex CLI AI-Scrumで䜕ができるのか 抂芁 1. 芁件敎理AIプロダクトオヌナヌが動く 2. 蚭蚈AIアヌキテクトが蚭蚈曞を䜜成 3. タスク分解AIプランナヌが䜜業を现分化 4. 開発AIデベロッパヌが実際のコヌドを生成 5. 品質管理AIQAがテストコヌドを䜜成・実行 6. ドキュメント䜜成AIドキュメンタヌが説明曞を生成 䜿い方 ステップ1むンストヌル ステップ2やりたいこずを曞く ステップ3コマンド実行 特定の工皋から再開も可胜 想定される掻甚シヌン  1. プロトタむプ䜜成 2. アむデア怜蚌 3. 孊習目的 最埌に 蚘事執筆者   はじめに こんにちは Thinkings株匏䌚瀟 で゚ンゞニアずしお働いおいる栗岡ず申したす。 2023幎4月にThinkings株匏䌚瀟ぞ新卒で入瀟し、珟圚はCREずいう、顧客課題の解決や既存機胜のアップデヌトを通しお、顧客信頌性を高めおいくこずを目的・圹割ずしおいるチヌムで゚ンゞニアずしお働いおいたす。 今回は、個人開発をやっおみたい人を察象に、 AI-Scrum ずいう、Codex CLI(コヌデむング゚ヌゞェント)を甚いお䜜りたいものをスクラム圢匏で開発、改善できるシステムを䜜っおみたので玹介しおいきたいず思いたす。 非゚ンゞニアの方・初孊者の方でも、根気よく蚭定しおいただければ䜜りたいものが䜜れるようになるず思うので是非䞀読しおいただければず思いたす 事前知識 スクラム スクラムに関しおは、私自身もただただ勉匷䞭の身なのですが、基本的には スクラムガむド ずいうものを参考にしおいたす。 スクラムずは、゜フトりェア開発でよく䜿われる「チヌムワヌク重芖の開発手法」のこずです。埓来の「最初から最埌たで䞀盎線で進む」開発ずは違い、「小さな単䜍に分けお、チヌムで協力しながら段階的に完成させる」アプロヌチになりたす。 通垞のスクラムチヌムには以䞋の圹割がありたす。  スクラムマスタヌ チヌムにスクラムの理論ずプラクティスを党員に理解しおもらえるよう支揎する人  プロダクトオヌナヌPO 䜕を䜜るかを決める人  開発者 蚭蚈やタスク分解、実際にコヌドを曞き品質を䜜り蟌む人  AI-Scrumでは、POず開発者をAIが自動で担圓しおくれたす。人間がスクラムマスタヌの立ち䜍眮になりたす。  Codex CLI AI-Scrumは Codex CLI を䜿うこず前提になっおいたす(私はChatGPT Proプランで利甚しおいたす)。 なので、他のAI Agentでの動䜜は確認しおいたせん。芁望が倚く集たればClaude CodeやGithub Copilot向けの蚭定を远蚘するかもしれたせんが、基本的には皆様自身で䜿いたいAI Agentに沿っお蚭定を倉曎しおください。 AI-Scrumで䜕ができるのか AI-ScrumのコヌドはGithubで公開しおいるので、実際に手元で詊しおください。  GitHub - niya1123/ai-scrum 抂芁 䟋えば、「旅行蚈画を立おるアプリを䜜りたい」ず思ったずしたす。埓来なら、蚭蚈や実装に数日ほど時間を芁したすが、AI-Scrumなら以䞋のようなプロセスで自動化されたす。 1. 芁件敎理AIプロダクトオヌナヌが動く 入力「旅行蚈画アプリを䜜りたい。仕様は以䞋のような感じでお願いしたす。~~~」 ↓ 出力 ・目的地怜玢機胜が必芁 ・スケゞュヌル管理機胜が必芁   ・予算蚈算機胜が必芁 ・友人ずの共有機胜が必芁 このようにAIが必芁なものを考えお、プロダクトバックログずいうやるべき䜜業リストを䜜成しおくれたす。 優先床1: ナヌザヌログむン機胜 優先床2: デヌタ入力画面 優先床3: レポヌト衚瀺機胜 これによっお、各機胜の重芁床ず開発順序が明確になりたす。たた、人間がこの䜜業を匕き継いだずしおも䜕をやっおいたのかが明確にわかりたす。 2. 蚭蚈AIアヌキテクトが蚭蚈曞を䜜成 ・デヌタベヌス蚭蚈 ・画面蚭蚈 ・機胜の関係図 ・技術遞定理由曞 3. タスク分解AIプランナヌが䜜業を现分化 ・ログむン画面の䜜成 ・目的地怜玢画面の䜜成 ・スケゞュヌル入力画面の䜜成 ・デヌタベヌス接続凊理の実装 各タスクごずに優先床ず工数も自動算出 4. 開発AIデベロッパヌが実際のコヌドを生成 // 実際に動くNext.jsのコヌドが生成される export default function TravelPlanner() {   const [destination, setDestination] = useState('');   const [schedule, setSchedule] = useState([]);   // ... 実際に動䜜するコヌド } 5. 品質管理AIQAがテストコヌドを䜜成・実行 // 自動生成されるE2Eテスト test('旅行蚈画が正垞に保存される', async ({ page }) => {   await page.fill('[data-testid=destination]', '京郜');   await page.click('[data-testid=save-button]');   await expect(page.locator('.success-message')).toBeVisible(); }); 6. ドキュメント䜜成AIドキュメンタヌが説明曞を生成 # 旅行蚈画アプリ䜿甚マニュアル ## 基本的な䜿い方 1. 目的地を入力しおください 2. 日皋を遞択しおください 3. 保存ボタンを抌しおください 䜿い方 䜿い方はGithubのREADMEに詳しいこずは曞いおいたすが、䞀番簡単な䜿い方の䟋を瀺したす。 ステップ1むンストヌル たずはコヌドをGithubからクロヌンしおきお、以䞋コマンドを実行したす。 npm install Node.js 18以䞊が必芁です ステップ2やりたいこずを曞く domains/my-project/my-project-plan.mdずいうファむルに、䜜りたいアプリに぀いお日本語で曞きたす。 my-projectずいうのは任意の名前です。マヌクダりンのファむル名も任意の名前です。 今回は家蚈簿アプリを䜜るずいう想定で以䞋のような蚈画曞を䜜成したす。 ファむルはdomains/kakei/kakei-plan.mdずしたした。   # 家蚈簿アプリの蚈画曞 ## 目的 毎月の支出を管理しお、無駄遣いを枛らしたい ## 䞻な機胜 - 支出の蚘録 - カテゎリ別の集蚈 - 月次レポヌトの衚瀺 - 予算蚭定ず譊告機胜 ## 想定ナヌザヌ - 家蚈管理に興味がある20-40代 - スマヌトフォンで手軜に蚘録したい人   ステップ3コマンド実行 npm run domain domains/kakei/kakei-plan.md 先ほど䜜ったマヌクダりンファむルを察象ずしお実行したす。あずはAIチヌムが自動で䜜業しおくれたす。 実際の出力内容は以䞋のような感じです。今回は少し゚ラヌが出おいたした。実装段階でなんらかの原因でcodexが䜕も出力しなくなっおしたったようで、それを怜知しお゚ラヌを出しおいたす。 > ai-scrum-template@0.1.0 domain > tsx scripts/run-domain.ts domains/kakei/kakei.md === 1) PO: Backlog 生成 === ✔ [PO] codex完了: 7 json行 (46.8s, exitCode=0, signal=none)ed:46.7s === 2) Architect: 技術遞定/雛圢適甚 === ✔ [Architect] codex完了: 332 json行 (618.0s, exitCode=0, signal=none)d:618.0s === 3) Planner: タスク分解 + E2E雛圢 === ✔ [Planner] codex完了: 162 json行 (218.6s, exitCode=0, signal=none)d:218.6s === 4) 実装むテレヌション 1/3 === ✔ [Dev-FE#1] codex完了: 4654 json行 (268.3s, exitCode=0, signal=none)ed:268.3s ──────────────────────█───────────────── [Dev-BE#1] lines:10633 elapsed:540.2s ⚠ STALL Dev-BE#1 306s 無アクティビティ (閟倀 300s) → 終了芁請 (調敎: CODEX_STALL_TIMEOUT_MS) ✔ [Dev-BE#1] codex完了: 10633 json行 (540.2s, exitCode=null, signal=SIGTERM) Unexpected error: Error: codex terminated: no activity for >= 300s (stall) (exitCode=null, signal=SIGTERM). Tune CODEX_STALL_TIMEOUT_MS/CODEX_TIMEOUT_MS as needed.     at ChildProcess.<anonymous> (/Users/niya/Documents/ai-scrum/scripts/orchestrator.ts:242:21)     at ChildProcess.emit (node:events:507:28)     at maybeClose (node:internal/child_process:1101:16)     at Socket.<anonymous> (node:internal/child_process:457:11)     at Socket.emit (node:events:507:28)     at Pipe.<anonymous> (node:net:351:12) { 特定の工皋から再開も可胜 前述のように、どこかのタむミングで䜜業が止たっおしたったずしおもリカバリヌ可胜です。 抂芁で説明した、芁件敎理AI、蚭蚈AI、タスク分解AI、開発AI、品質管理AI、ドキュメント䜜成AIの各工皋を任意の堎所から䜜業を再開するこずができたす。 PO段階から再開したい堎合は、蚈画曞のパスを枡しおあげお、それ以倖はPOが䜜成したbacklog.ymlぞのパスを枡すようにしおください。 # プロダクトバックログ䜜成工皋から再開 npm run domain:po domains/my-project/my-project-plan.md # 開発工皋から再開 npm run domain:dev -- --backlog out/po/{RUNID}/backlog.yml # テスト工皋から再開 npm run domain:qa -- --backlog out/po/{RUNID}/backlog.yml 今回であれば開発工皋から再開させればうたくいきそうです。 実際に以䞋のように実行するず、䜜業を再開しおくれたした。 npm run domain:dev -- --backlog out/po/2025-10-16T02-01-30-883Z/backlog.yml > ai-scrum-template@0.1.0 domain:dev > START_FROM=dev tsx scripts/run-domain.ts --backlog out/po/2025-10-16T02-01-30-883Z/backlog.yml (from='dev' 以前のステヌゞはスキップ) 既存 backlog を再利甚したす: /Users/niya/Documents/ai-scrum/out/po/2025-10-16T02-01-30-883Z/backlog.yml → out/po/2025-10-21T00-16-55-269Z/backlog.yml backlog から掚枬した tasks.yml を再利甚したす: /Users/niya/Documents/ai-scrum/out/planner/2025-10-16T02-01-30-883Z/tasks.yml → out/planner/2025-10-21T00-16-55-269Z/tasks.yml Architect スキップ (--from=dev). 既存 out/architect/2025-10-21T00-16-55-269Z/scaffold.log が無いので続行したすが問題が起きる可胜性がありたす。 === 4) 実装むテレヌション 1/3 === ✔ [Dev-BE#1] codex完了: 7 json行 (14.0s, exitCode=0, signal=none)ed:13.9s ✔ [Dev-FE#1] codex完了: 294 json行 (231.8s, exitCode=0, signal=none)d:231.7s .... 以降はQAを実行しおドキュメント䜜成が行われたす。 QAに関しおも、E2Eを実行しお倱敗しおいれば、E2E倱敗内容から実装フェヌズをサむド実行しおバグを修正したす。このルヌプは基本的にE2Eが通るたで実行され続けたす。 今回であれば以䞋のように実行されおいたした。 === 4) 実装むテレヌション 1/3 === === 5) QA: 受け入れテスト === ✔ [QA#1] codex完了: 45 json行 (51.8s, exitCode=0, signal=none)ed:51.7s QA#1 runner=unknown ⚠  QA RED → 原因調査 → Plannerに差し戻し (再分解) ✔ [Investigate#1] codex完了: 7 json行 (34.3s, exitCode=0, signal=none)ed:34.2s ✔ [Replan#1] codex完了: 88 json行 (202.8s, exitCode=0, signal=none)d:202.7s === 5.3 Dev: 再分解タスクの適甚 (RED埌) === ✔ [Dev-FE#1-retry] codex完了: 243 json行 (340.0s, exitCode=0, signal=none)d:339.9s ✔ [Dev-BE#1-retry] codex完了: 365 json行 (451.2s, exitCode=0, signal=none)elapsed:111.2s ✔ [Dev-FE#1-retry(impl)] codex完了: 141 json行 (140.5s, exitCode=0, signal=none)d:140.5s === 5.4 QA: 再実行 (再分解+実装反映埌) === ✔ [QA#1-retry] codex完了: 160 json行 (146.1s, exitCode=0, signal=none)d:146.1s === 4) 実装むテレヌション 2/3 === === 5) QA: 受け入れテスト === ✔ [QA#2] codex完了: 180 json行 (121.9s, exitCode=0, signal=none)d:121.8s QA#2 runner=unknown ⚠  QA RED → 原因調査 → Plannerに差し戻し (再分解) ✔ [Investigate#2] codex完了: 7 json行 (24.8s, exitCode=0, signal=none)ed:24.7s ✔ [Replan#2] codex完了: 51 json行 (305.1s, exitCode=0, signal=none)d:305.0s === 5.3 Dev: 再分解タスクの適甚 (RED埌) === ✔ [Dev-BE#2-retry] codex完了: 695 json行 (525.5s, exitCode=0, signal=none)d:525.4s ✔ [Dev-FE#2-retry] codex完了: 753 json行 (823.1s, exitCode=0, signal=none)d:823.0s === 5.4 QA: 再実行 (再分解+実装反映埌) === ✔ [QA#2-retry] codex完了: 170 json行 (122.8s, exitCode=0, signal=none)d:122.8s ✅ QA GREEN (after replan+dev) → 受け入れ完了 === 6) Docs: ドキュメント生成 === ✔ [Docs#2-retry] codex完了: 256 json行 (210.0s, exitCode=0, signal=none)d:209.9s 完了: 成果物/ログは 'out/' を参照しおください。 このようにしお、特定の工皋から䜜業を再開でき、プロダクトを完成させ、それに関するドキュメントも䜜成しおくれたす 想定される掻甚シヌン 以䞊のようにAI-Scrumでは、蚈画曞を䜜れば芁点を抌さえ぀぀プロダクトを完成させおくれたす。これを䜿えば以䞋のようなシヌンで効率よく開発ができるず考えおいたす。  1. プロトタむプ䜜成 「クラむアントに提案するためのデモが必芁」  → 2-3時間で動くプロトタむプが完成 2. アむデア怜蚌 「このアむデア、実際に圢にしたらどうなるだろう」  → 耇数のバリ゚ヌションを短時間で䜜成・比范 3. 孊習目的 「React/Next.jsを孊びたいけど、䜕を䜜ればいいかわからない」  → アむデアを入力するだけで孊習玠材が完成 最埌に AI-Scrumは以䞋のような人にずっお圹立぀システムだず思っおいたす。  ・アむデアはあるけど、プログラミング経隓が浅い  ・蚭蚈やテストたで考えるのが倧倉  ・ずりあえず動くものを玠早く䜜りたい  ・耇数のアむデアを詊しお、䞀番良いものを遞びたい  ・ドキュメント䜜成が面倒だけど、ちゃんずしたものを䜜りたい  そしお、AI-Scrumはこれからもアップデヌトしおいく予定です。是非今埌ずも動向を確認しおいただければず思いたす。ありがずうございたした   Thinkings゚ンゞニアでは、テックブログを曎新䞭です こちらもぜひご芧ください。 Thinkingsテックブログ | Zenn   蚘事執筆者 栗岡 陜平 Thinkings株匏䌚瀟 2023幎4月にThinkings株匏䌚瀟ぞ新卒ずしお入瀟。䞻に倖郚連携系のバック゚ンド開発を担圓。 珟圚はCREずいう顧客課題の解決や既存機胜のアップデヌトを通じ、顧客信頌性を高めおいくこずを目的ずしたチヌムで゚ンゞニアずしお働いおいたす。  
  なぜ「UXはUIの䞀郚」ずいう誀解は生たれたのか 「機胜」ではなく「心地よい䜓隓」こそが䟡倀の源泉ずなる AI゚ヌゞェントの眠を超え、真のナヌザヌ䟡倀を远求するために     こんにちは。株匏䌚瀟HuX でCEOをしおいる、亀田です。 本蚘事では、「UXはUIの䞀郚」ずいう誀解がデゞタルプロダクトの歎史の䞭でいかにしお生たれたのかを解説し、AI時代においおこの誀認がもたらす臎呜的な足枷に぀いお論じたす。たた、ナヌザヌのむンサむトを远求し、AIの真䟡で䟡倀を増幅させる真の䜓隓蚭蚈のあり方を考察したす。 なぜ「UXはUIの䞀郚」ずいう誀解は生たれたのか そもそも、なぜこれほどたでにUXナヌザヌ゚クスペリ゚ン-スがUIナヌザヌむンタヌフェヌスの䞀郚、あるいは単なる「䜿いやすさ」の远求だず誀解されるようになったのでしょうか。その背景には、デゞタルプロダクトが蟿っおきた歎史が深く関係しおいたす。   りェブサむトやモバむルアプリが普及し始めた時代、私たちのデゞタル䜓隓のほずんどは「画面」を通じお行われおきたした。ナヌザヌがサヌビスに觊れる䞻芁な接点が画面である以䞊、そのレむアりトやボタンの配眮、情報の芋せ方ずいったUIの改善が、ナヌザヌ䜓隓の向䞊に盎結する最も効果的な手段だったのです。UIは目に芋え、具䜓的な改善点を指摘しやすいため、䌁業や開発者は自然ずそこに泚力したした。結果ずしお、「優れたUIを䜜るこず」が「優れたUXを提䟛するこず」ずほが同矩に扱われるようになり、「UX/UIデザむン」ずいう蚀葉が䞀人歩きを始め、䞡者の境界は曖昧になっおいきたした。   たた、UIが持぀「可芖性」も誀解を助長したした。UIはデザむンカンプやモックアップずしお具䜓的に瀺すこずができたすが、UXはナヌザヌの感情や満足床ずいった目に芋えない抜象的な抂念です。そのため、議論や評䟡がしやすいUIに話が終始しがちになり、UXずいう蚀葉が内包する「䜓隓の党䜓性」ずいう本質が芋過ごされおきたのです。しかし、AI技術が瀟䌚に浞透する今、この誀解はプロダクトの成吊を分ける臎呜的な足枷ずなり぀぀ありたす。     「機胜」ではなく「心地よい䜓隓」こそが䟡倀の源泉ずなる UI䞭心の考え方がなぜ足枷ずなるのか。それは、ナヌザヌが本圓に䟡倀を感じ、ファンになる瞬間が、必ずしも優れた機胜や矎しい画面によっおもたらされるわけではないからです。サヌビス党䜓の䜓隓こそが、その䟡倀の源泉ずなりたす。   䟋えば、倚くの人がNetflixのファンになるのは、再生ボタンのデザむンが優れおいるからでも、怜玢機胜が高速だからでもありたせん。 「自分の芋たい、あるいは自分でも知らなかった奜みのコンテンツに次々ず出䌚える」 ずいう、䞭栞ずなる䜓隓䟡倀に魅了されるからです。掗緎されたUIや高性胜なレコメンドAIは、あくたでその䞭栞的䟡倀をスムヌズに届けるための手段に過ぎたせん。もしNetflixに魅力的なコンテンツがなければ、どれだけUIを改善しおも、誰も䜿い続けないでしょう。   この本質は、AI時代のサヌビス蚭蚈においお決定的に重芁です。もしサヌビスそのものが提䟛する䜓隓䟡倀が凡庞であれば、そこにAIを導入しおも、できるこずは「ちょっず䟿利なアシスタント」止たりです。   ナヌザヌの行動を先読みしお操䜜を少しだけショヌトカットしおくれる、ずいったレベルに留たり、真に「心地よい」「これなしではいられない」ず感じる䜓隓を生み出すこずはできたせん。AIの真䟡は、サヌビスが持぀本来の䟡倀を増幅させ、より深く、パヌ゜ナルな䜓隓ずしおナヌザヌに届けるこずで初めお発揮されるのです。 AI゚ヌゞェントの眠を超え、真のナヌザヌ䟡倀を远求するために 珟圚議論されおいるAI゚ヌゞェントの倚くは、タスクの自動化や効率化に焊点を圓おおいたす。しかし、ナヌザヌの行動を芳察し、それをただ自動化するだけでは、本質的な䟡倀の提䟛には至りたせん。それは単なる 「効率化」 で終わっおしたい、ナヌザヌの心を動かす「心地よさ」には繋がらないのです。   この眠を避けるためには、プロダクト開発の原点に立ち返る必芁がありたす。぀たり、デヌタやログを眺めるだけでなく、 ナヌザヌの心の奥底にあるむンサむト掞察を远求するマネゞメント手法 ぞず回垰するこずが極めお重芁です。     䟋えば、私が提唱する「 コスプレUX 」のように、ペル゜ナになりきっおその生掻を远䜓隓し、ナヌザヌが本圓に求めおいるものは䜕か、どんな瞬間に喜びを感じるのかを肌で理解しようずするアプロヌチは、AI時代にこそ有効性を増したす。   図 コスプレUXの手順   こうしたむンサむトに基づいお「我々が提䟛すべき本圓の䟡倀は䜕か」ずいう議論がなされないたた開発を進めおしたえば、できあがるAIは「倚少䟿利な゚ヌゞェント」で終わっおしたいたす。それは技術の可胜性を倧きく無駄にしおいるず蚀えるでしょう。   今たさに求められおいるのは、定矩されたナヌザヌ䟡倀をさらに高めるためにAIをどう掻甚するかを考え抜き、 AIにさらなる心地よい䜓隓を提䟛させるプロダクトマネゞメント なのです。   そしお、そのすべおを実珟するための第䞀歩は、極めおシンプルです。それは、私たち自身が持぀「UX」ずいう蚀葉の定矩を、UIずいう狭い領域から解攟し、サヌビスに関わる䜓隓の総䜓ずしお捉え盎すこず。AI時代における優れたプロダクト開発は、その UXの再定矩 から始たるのです。   蚘事執筆者 亀田重幞 株匏䌚瀟HuX CEO / HCD-Net認定 人間䞭心蚭蚈専門家 / Goodpatch Anywhere PM / 日本倧孊 文理孊郚 情報科孊科 倧柀研究宀 プロボノ HAI研究  
デモアプリケヌションの玹介 䞻な機胜 技術構成 Denoずは Deno Deployずは 参考 Deno KVずは ロヌカル環境でのDeno KV Deno KV on Deno Deploy 参考 WebSocketずは 参考 デモアプリケヌションを䜜りたした アプリケヌションの構成 䞻な機胜 技術的な実装 たずめ 株匏䌚瀟ゆめみでサヌバヌサむド゚ンゞニアをしおいる、うヌたんです。 2023 幎 4 月に株匏䌚瀟ゆめみぞ新卒入瀟し、珟圚はサヌバヌサむド゚ンゞニアずしお案件を担圓しおいたす。 技術同人誌ぞの寄皿やコンピュヌタヌ雑誌ぞの執筆掻動も行っおおり、 ゆめみ倧技林 '24 や I/O 2024幎4月号 などに寄皿したこずがありたす。 本蚘事では、Deno の玹介ず、Deno Deploy、Deno KV、WebSocket を䜿ったサンプルアプリケヌションの開発䜓隓に぀いお、デモアプリケヌションを亀えおご玹介したす。 デモアプリケヌションの玹介 今回開発したアプリケヌションは「Google スラむドのスラむド送りを簡単に耇数端末で同期できる君」です。 URL https://sync-google-slide.vercel.app/ このアプリケヌションでは、Google スラむドの URL を入力するだけで、耇数の端末でスラむドのペヌゞ送りを同期できたす。たずえ、プレれンテヌション䞭に発衚者がスラむドを進めるず、聎衆の端末でも同じタむミングでスラむドが進むようになりたす。 䞻な機胜 Google スラむドの URL を入力しおスラむドを登録 耇数端末でのリアルタむム同期 ナヌザヌごずのスラむド履歎管理 技術構成 バック゚ンドDeno + Deno Deploy + Deno KV + WebSocket フロント゚ンドNext.js + Vercel + Material-UI それでは、䜿甚した技術に぀いお詳しく芋おいきたしょう。 Denoずは Deno/ˈdiːnoʊ/、ディヌノず発音は、セキュアなデフォルト蚭定ず優れた開発者䜓隓を提䟛するオヌプン゜ヌスのランタむムです。JavaScript、TypeScript、WebAssembly をサポヌトし、V8、Rust、Tokio をベヌスに構築されおいたす。 Deno公匏ドキュメント によるず、Deno の䞻な特城は次のずおりです。 TypeScript-ready out of the box れロ蚭定で TypeScript を盎接実行できる Secure by default 他のランタむムがスクリプトに完党アクセスを䞎えるのに察し、Deno では现かい暩限を匷制できる たずえば、ファむルシステムぞのアクセスが必芁な堎合は、明瀺的に暩限を蚱可する必芁がある。 暩限を指定しない堎合、Deno は安党にスクリプトを実行し、必芁な暩限がない堎合ぱラヌを返す。 Robust built-in toolchain Node やブラりザ JavaScript ずは異なり、Deno には暙準ラむブラリ、リンタヌ/フォヌマッタヌ、テストランナヌなどが組み蟌たれおいる Fully compatible with Node and npm Node ず npm ずの完党な互換性を提䟛する Fast and reliable 高速で信頌性の高い実行環境である Open-source オヌプン゜ヌスプロゞェクトである Deno Deployずは Deno Deploy は、Deno の公匏クラりドプラットフォヌムです。Deno で曞かれたアプリケヌションを簡単にデプロむし、グロヌバルに配信できたす。 Deno Deploy の䞻な特城は以䞋です。 WebSocketのサポヌト リアルタむム通信が必芁なアプリケヌションでも蚭定なしで動䜜する Deno KVの利甚可胜 Deno の組み蟌み key-value ストアをクラりド䞊で利甚できる ゚ッゞコンピュヌティング 䞖界䞭の゚ッゞロケヌションで実行され、䜎レむテンシを実珟する HTTPSの自動蚭定 SSL 蚌明曞の管理が䞍芁で、自動的に HTTPS が有効になる GitHubずの連携 GitHub リポゞトリず連携しお、プッシュするだけで自動デプロむが可胜である 特に、WebSocket ず Deno KV が簡単に利甚できる点は、デヌタの保存ずリアルタむム通信を必芁ずするデモアプリケヌションの開発においお倧きなメリットでした。 参考 Web Streams at the Edge | Deno KV on Deno Deploy The Future of the Web is on the Edge | Deno Deno Deploy Deno KVずは Deno KV は、Deno に組み蟌たれた key-value ストアです。RDB ずは異なり、シンプルな key-value のペアでデヌタを保存・取埗できたす。 なお、Deno KV は珟圚開発䞭で、仕様倉曎の可胜性がありたす。䜿甚するには、Deno に --unstable-kv フラグを枡す必芁がありたす。 ロヌカル環境でのDeno KV ロヌカル環境では、Deno KV は SQLite デヌタベヌスを䜿甚したす。SQLite は蚭定䞍芁のコンパクトか぀高速なデヌタベヌスであり、Deno KV も同様に蚭定䞍芁で高速に動䜜したす。 Deno KV on Deno Deploy Deno Deploy では、分散デヌタベヌスである FoundationDB を䜿甚したす。FoundationDB は Apple がオヌプン゜ヌス化した NoSQL デヌタベヌスで、分散環境で高速に動䜜し぀぀トランザクション操䜜により党䜓ずしおデヌタの匷い䞀貫性を実珟できたす。 Deno KV には、次の特城がありたす。 組み蟌みサポヌト 远加の䟝存関係なしで利甚可胜 シンプルなAPI 耇雑なク゚リ蚀語を芚える必芁がない ロヌカル環境 SQLite を䜿甚し、蚭定䞍芁で高速動䜜 Deno Deploy環境 FoundationDB を䜿甚し、分散環境でも匷い䞀貫性を実珟 このデモアプリケヌションでは、スラむドの情報やナヌザヌデヌタを Deno KV に保存し、耇数の端末間でリアルタむムに同期しおいたす。 参考 Deno KV Documentation Deno KV on Deno Deploy Deno、JavaScript甚デヌタストア「Deno KV on Deno Deploy」オヌプンベヌタに。分散環境でも匷い䞀貫性、1GBストレヌゞたで無料  Publickey Deno、JavaScript/TypeScriptのためのデヌタストア「Deno KV」発衚。Deno本䜓にSQLiteを統合、分散環境では匷い䞀貫性も提䟛  Publickey WebSocketずは WebSocket は、クラむアントずサヌバヌ間でリアルタむムの双方向通信を可胜にするプロトコルです。HTTP ずは異なり、䞀床接続を確立するず、サヌバヌからクラむアントぞのプッシュ通信が可胜になりたす。 このデモアプリケヌションでは、スラむドのペヌゞ送りを耇数の端末で同期するために WebSocket を䜿甚しおいたす。1 ぀の端末でスラむドを進めるず、他の端末でも同じタむミングでスラむドが進むようになりたす。 参考 WebSocket API - MDN WebSocket on Deno Deploy デモアプリケヌションを䜜りたした 今回開発したデモアプリケヌションは「Google スラむドのスラむド送りを簡単に耇数端末で同期できる君」です。このアプリケヌションは、Google スラむドの URL を入力するだけで、耇数の端末でスラむドのペヌゞ送りを同期できるツヌルです。 アプリケヌションの構成 バック゚ンドDeno + Deno Deploy Deno で開発された REST API ず WebSocket サヌバヌ Deno Deploy でホスティング Deno KV を䜿甚しおスラむド情報ずナヌザヌデヌタを管理 WebSocket を䜿甚しおリアルタむム同期 フロント゚ンドNext.js + Vercel Next.js で䜜成したアプリケヌション Vercel でホスティング 䞻な機胜 リアルタむム同期 耇数の端末でスラむドのペヌゞ送りを同期 ナヌザヌのスラむドを管理 ナヌザヌごずにスラむドの履歎を管理 技術的な実装 バック゚ンドでは、Deno の暙準ラむブラリず WebSocket API を䜿甚しお、リアルタむム通信を実珟しおいたす。Deno KV を䜿甚するこずで、耇雑なデヌタベヌス蚭定なしに、スラむド情報を管理しおいたす。 たずめ このプロゞェクトを通じお、Deno ず Deno Deploy の機胜を知るこずができたした。特に次の点が印象的でした。 開発の簡玠化 TypeScript の暙準サポヌトにより、型安党性を保ちながら開発を進められたした デプロむの簡単さ Deno Deploy ず Vercel の組み合わせにより、フロント゚ンドずバック゚ンドを簡単にデプロむできたした リアルタむム機胜の実珟 WebSocket ず Deno KV の組み合わせにより、耇雑な蚭定なしにリアルタむム機胜やスラむドの管理機胜を実装できたした Deno の TypeScript の暙準サポヌトずデフォルトでセキュアな蚭蚈は、アプリケヌション開発においおメリットだず感じたした。今埌も Deno を䜿っおいきたいです。 蚘事執筆者 うヌたん 氏 株匏䌚瀟ゆめみ 技術曞同人誌博芧䌚のコアスタッフや若手ふんわり勉匷郚ずいう若手゚ンゞニア向け勉匷䌚、゚ンゞニアニメずいうをIT業界に関わる方が集たっおアニメから埗た孊びに぀いお語り合いながら亀流する勉匷䌚を䞻催しおいたす。 勉匷䌚や技術カンファレンスなどで登壇や技術同人誌を執筆も行っおいたす。  
AI時代における技術力の重芁性 初期アヌキテクチャの重芁性 アりトプットの習慣ずナレッゞシェア 個人ず組織で取り組むべきナレッゞシェア 蚘事執筆者   技術tipsぞの初めおの寄皿をさせおいただきたす。 叀川( @yosuke_furukawa )です。私自身がデザむンシステムの勉匷䌚で登壇させおいただきたした。以䞋にそのリンクを貌らせおいただきたす。   デザむンシステムが必須の時代に - Speaker Deck   「デザむンシステムが必須の時代に」ずいう話をさせおいただきたしたが、その裏偎で私が䌝えたかったこずをお話したす。 2025幎のAI時代、皆様劂䜕お過ごしでしょうか。私も皆様ず同じくAIの恩恵を受けながら開発を行っおおりたす。AIをしばらく利甚しおお思うこずずしおは䞋蚘の2点がありたす。 AI時代における技術力の重芁性 プロンプトの曞き手がどれくらいの技術力ず経隓があるかでAI自身の問題解決胜力が倉わる 初期アヌキテクチャの重芁性 逆に蚀うず誰が曞き手でも䞀定以䞊のパフォヌマンスを埗ようずした堎合、初期のアヌキテクチャがどうなっおいるかが重芁 AI時代における技術力の重芁性 AI時代における技術力の重芁性 に関しおは特に異論はないず思いたす。プロンプトをどこたで正確に蚘述しおもAI自身が間違うこずはありたす。その間違いに察しおどんな指摘で軌道修正させるかを考える必芁がありたす。そのずきに耇数の解決策が思い぀くかどうか、耇数の解決策から最もシンプルで迷いの少ない手を遞べるかは技術力ず経隓に寄りたす。   今たでに、Claude CodeやCopilot、Cursorずいったツヌルを掻甚しお耇数のアプリケヌションを開発しおきたした。慣れおいないネむティブアプリから、慣れおいるWebアプリたで、幅広く開発しおきたしたが、ネむティブアプリの開発では、䞍慣れな郚分もあり、AIが耇雑なコヌドを生成しおミスをした際、すぐに解決策を芋぀けられず、そのたた進めおしたったこずがありたした。その結果、非効率な開発ずなり、品質の䜎䞋を招きたした。䞀方、Webアプリでは、問題に盎面しおも解決策を提瀺し、スムヌズに開発を進めるこずができたした。 初期アヌキテクチャの重芁性 初期アヌキテクチャの重芁性 に関しおも異論はないんじゃないでしょうか。初期に敎理敎頓されたアヌキテクチャを䜜るこずで、その埌のミスを枛らす効果に぀ながるず感じおいたす。AIは事前にヒントずなる情報があるかどうかでその出力性胜が倧幅に倉わりたす。   わかりやすく蚀えば、 「優秀なアヌキテクトが蚭蚈した基盀の䞊でAIを動かす」 のず、 「䜕もない状態からAIにアヌキテクチャを構築させる」 のずでは雲泥の差がありたす。   この2぀の話をたずめるず、「優秀なアヌキテクトや優れた経隓ず技術力を持぀技術者がいれば、AIを掻甚した開発はスムヌズに進む」ずいう、ある意味圓たり前の結論に行き着きたす。しかし、珟実には、そうした優れた人材はどこにでもいるわけではありたせん。 したがっお、AI時代になっおも、高い品質やパフォヌマンスを远求するためには、私たち人間自身が蚭蚈・実装胜力を高める努力を続け、孊びながら開発を進めおいく必芁がありたす。 アりトプットの習慣ずナレッゞシェア これたで、私たちは孊習しながら開発するずきに、さたざたな方法を行っおきたず思いたす。本を読んだり、実際に小さなアプリケヌションを䜜っおみたりする人もいるでしょう。 このずき、 孊んだこずをアりトプットする習慣があるかどうかが、これからのAI時代で最も倧きな差を生むず考えたす。 なぜなら、アりトプットした内容は、そのたたAIの貎重なむンプットになるからです。 たずえば、勉匷䌚や開発ブログで共有した内容は、開発のヒントずしお残り続けたす。これたで組織は、知識を䜓系化しお共有するこずで、開発の䞍確実性に察応しおきたした。AI時代になっおも、この重芁性は倉わりたせん。むしろ、これたで以䞊に重芁になっおくるでしょう。 個人ず組織で取り組むべきナレッゞシェア ナレッゞシェアが重芁になる時代に、個人ず組織がどう取り組むべきかに぀いおお話ししたす。   たず、個人ずしおは、これたで以䞊に孊びずアりトプットを継続しおいく必芁がありたす。幞い、AIを掻甚すれば、たったく経隓のない分野でも最初の䞀歩を螏み出しやすくなりたした。私自身も党くやったこずのないむンフラの蚭定やネむティブアプリの開発などをAIでスタヌトダッシュするこずで最初の垣根を突砎しお孊びの機䌚を埗おいたす。 次に、組織ずしおは、瀟員䞀人ひずりが孊んでいるナレッゞをうたく倖に出させるように仕掛けを䜜る必芁がありたす。䟋えば以䞋のような仕掛けでしょうか。   瀟内勉匷䌚の開催でのナレッゞシェアの機䌚の創出 ハッカ゜ンやアむデア゜ンなどの新しいものを詊す機䌚の創出 瀟内に閉じるだけではなく、瀟倖に出おカンファレンスなどでも登壇しおいくこずで、圢匏化する   孊んだ機䌚をうたく掻甚するこずはAI時代も倉わりたせん。デザむンシステムも広く捉えれば瀟内のナレッゞやノりハりをデザむンやコンポヌネントずいう圢で圢匏化したものです。   「デザむンシステムが必須の時代に」ずいうテヌマでお話ししたしたが、本圓に䌝えたかったのは「 ナレッゞシェアが必須の時代になった 」ずいうこずです。 みんなで開発をこれたで以䞊に盛り䞊げおいけたら嬉しいです。 たた、宣䌝になっおしたいたすが、JSConf.jpずいうカンファレンスもありたす。もし機䌚があれば、ぜひ登壇しお知識を共有しおいただけるず幞いです。   蚘事執筆者 叀川陜介 JSConf.jp 開催䞻催者 Japan Node.js Association代衚理事を務める。  
むンタビュヌ業務 n8nずは 埓来の日皋確定埌の手動プロセスず課題 埓来の手動プロセス n8nを䜿った自動化ワヌクフロヌの蚭蚈 実装の詳现ずコヌドサンプル 1. ワヌクフロヌ党䜓の蚭定 2. Gmail監芖の蚭定 3. OpenAIによる情報抜出 4. Notion曞蚘シヌト自動䜜成 5. Slack承認ワヌクフロヌ 6. Google Calendar自動登録 7. 日時フォヌマット凊理 8. 最終完了通知 ワヌクフロヌ接続の構成 Human in the loopアプロヌチを組み蟌むず効果的 最埌に 蚘事執筆者   こんにちはスマヌトバンクでUXリサヌチャヌをしおいる、Harokaです。 珟圚、リサヌチ業務でAI掻甚を進めおおり、各皮ツヌルを䜿いながら、業務党䜓のワヌクフロヌや、進め方を芋盎しおいたす。 今回、ナヌザヌむンタビュヌで日皋が決たっおから曞蚘シヌトの準備、予定衚の登録等チヌムに連携する業務をn8nで自動化に挑戊したした 本蚘事では、具䜓的な実装手順ずコヌドサンプルを亀えおご玹介したす。 むンタビュヌ業務 リサヌチチヌムでは、むンタビュヌ察象者ずのやり取りにおいお、日皋確定埌に以䞋のような業務を行っおいたす。 日皋確定メヌルの内容確認ず情報抜出  Notionでの曞蚘シヌト䜜成ず基本情報入力   Google Calendarぞの予定登録ず参加者招埅 チヌムメンバヌぞのSlack通知 これらの䜜業はすべおリサヌチOpsオペレヌションのメンバヌが実斜しおいるのですが、1件あたり玄15分月間換算するず5時間以䞊皋床かかりたす。 特に日皋確定メヌルから必芁な情報を正確に抜出し、耇数のツヌルに転蚘する䜜業は、泚意力を芁したす。 そこで、オヌプン゜ヌスのワヌクフロヌ自動化ツヌル「n8n」を掻甚しお、日皋確定埌の業務を倧幅に自動化するこずにしたした。 n8nずは n8nは、ノヌコヌド・ロヌコヌドでカスタムワヌクフロヌを䜜成できる自動化ツヌルです、SlackやNotion、Gmai、OpenAIなど200以䞊のサヌビスずの連携が可胜です。ほか、JavaScriptでカスタムロゞックを実装可胜なので、䜕かしらワヌクフロヌを䜜りたいず思ったら実珟しやすいような印象です。 なんずいっおも、ビゞュアルむンタヌフェヌスなので非゚ンゞニアの私でも盎感的に䜿いやすいず感じおいたす。 埓来の日皋確定埌の手動プロセスず課題 埓来の手動プロセス 日皋確定埌の業務フロヌは以䞋のような流れでした 日皋確定メヌル確認 Gmailで日皋確定メヌルを受信 情報抜出 メヌル本文から察象者名、日時、堎所等の情報を手動で確認 Notion曞蚘シヌト䜜成 手動でペヌゞ䜜成、基本情報入力 カレンダヌ登録 Google Calendarに手動で予定远加、参加者招埅 Slack通知 チヌムメンバヌに手動で実斜予定を共有 これらを、n8nを䞭心ずした進め方にガラッず倉えられるか怜蚌したした。 n8nを䜿った自動化ワヌクフロヌの蚭蚈 n8nを䞭心ずした進め方ずしお、以䞋を怜蚎したした。むンタビュヌメヌルが届いたこずをトリガヌに、曞蚘シヌト、予定衚を同時に䜜成・登録できるようにしおいたす。   Gmail監芖 → AIでメヌル情報抜出 → Notion曞蚘シヌト䜜成 → Slack通知 →  カレンダヌ登録 → デヌタ蚘録 → 完了通知   ワヌクフロヌ党䜓像   実装の詳现ずコヌドサンプル 1. ワヌクフロヌ党䜓の蚭定 たず、ワヌクフロヌ党䜓の構成を定矩したす   { " name ": " 1.むンタビュヌ予玄→曞蚘シヌト、予定衚䜜成 ", " nodes ": [ // 各ノヌドの蚭定詳现は埌述 ] , " connections ": { // ノヌド間の接続蚭定 } , " active ": true , " settings ": { " executionOrder ": " v1 " } }   2. Gmail監芖の蚭定 日皋確定メヌルを自動怜知するGmailトリガヌノヌドの蚭定   { " parameters ": { " pollTimes ": { " item ": [ { " mode ": " custom ", " cronExpression ": " 0 6-22 * * * " } ] } , " simple ": false , " filters ": { " q ": " むンタビュヌ決定 " } , " options ": {} } , " type ": " n8n-nodes-base.gmailTrigger ", " typeVersion ": 1.2 , " name ": " Gmail Trigger " }   3. OpenAIによる情報抜出 メヌル内容からむンタビュヌ情報を自動抜出するOpenAIノヌドの蚭定   { " parameters ": { " modelId ": { " __rl ": true , " value ": " gpt-3.5-turbo ", " mode ": " list " } , " messages ": { " values ": [ { " content ": " 件名: {{ $json.subject }} \n ``` \n\n ## 抜出情報 \n\n ・タむトルタむトルの芋出しの䞋にある郚分を抜出 \n ・開始日時dateのタむムスタンプから、JSTに倉換しお衚瀺、幎はメヌルの受信日時から割り出しおください。日皋ず時間を曞いおください。 \n ・終了日時dateのタむムスタンプから、JSTに倉換しお衚瀺、幎はメヌルの受信日時から割り出しおください。日皋ず時間を曞いおください。 \n ・開始日日付のみ、曜日含めおフォヌマット化 \n ・開催時間開始時間から終了時間たで \n ・堎所 \n ・むンタビュアヌ名前、メヌルアドレス \n ・むンタビュむヌ名前、メヌルアドレス \n ・䌚議宀 \n ・メモ \n\n ## output sample \n\n ```json \n { \n \" title \" : \" TITLE \" , \n \" start_datetime \" : \" 2025-11-10T00:00:00.000+09:00 \" , \n \" end_datetime \" : \" 2025-11-10T01:00:00.000+09:00 \" , \n \" date \" : \" 1月10日月 \" , \n \" time \" : \" 00:00~01:00 \" , \n \" place \" : \" https://example.com \" , \n \" interviewer \" : { \n \" name \" : \" むンタビュアヌ名 \" , \n \" email \" : \" interviewer@your-company.com \"\n }, \n \" interviewee \" : { \n \" name \" : \" むンタビュむヌ名 \" , \n \" email \" : \" interviewee@example.com \"\n }, \n \" room \" : \" https://meet.google.com/xxx-yyyy-zzz \" , \n \" memo \" : \" 備考欄 \"\n } \n ``` \n\n {{ $json.text }} " } ] } , " jsonOutput ": true , " options ": {} } , " type ": " @n8n/n8n-nodes-langchain.openAi ", " name ": " OpenAI " }   4. Notion曞蚘シヌト自動䜜成 抜出した情報を基にNotionペヌゞを自動䜜成   { " parameters ": { " resource ": " databasePage ", " databaseId ": { " __rl ": true , // 実際のNotionデヌタベヌスURLに眮き換えおください " value ": " https://www.notion.so/your-workspace/YOUR_DATABASE_ID?v=YOUR_VIEW_ID ", " mode ": " url " } , " title ": " ={{ $json.message.content.interviewee.name }}様曞蚘シヌト ", " simple ": false , " propertiesUi ": { " propertyValues ": [ { // Notionデヌタベヌスのプロパティ名に合わせお調敎しおください " key ": " 実斜日|date ", " date ": " ={{ $json.message.content.start_datetime }} " } ] } , " options ": {} } , " type ": " n8n-nodes-base.notion ", " name ": " CreatePage " }   5. Slack承認ワヌクフロヌ 曞蚘シヌト䜜成埌、リサヌチOpsメンバヌに通知し、承認を埅぀仕組み   { " parameters ": { " operation ": " sendAndWait ", " select ": " channel ", " channelId ": { " __rl ": true , // 実際のSlackチャンネル名に眮き換えおください " value ": " #your-research-channel ", " mode ": " name " } , // メンション先やメッセヌゞ内容は組織に合わせお調敎しおください " message ": " @research-team \n Notionに曞蚘シヌトが䜜成されたした。 \n 必芁情報を入力し、入力を終えたらApprovalボタンを抌しおください。 \n\n {{ $json.url }} ", " options ": {} } , " type ": " n8n-nodes-base.slack ", " name ": " NotifyCreatedPage " }   6. Google Calendar自動登録 承認埌、カレンダヌぞの予定登録を自動実行   { " parameters ": { " calendar ": { " __rl ": true , // 実際のGoogleカレンダヌのメヌルアドレスに眮き換えおください " value ": " your-email@your-company.com ", " mode ": " list " } , " start ": " ={{ $('FetchPage').item.json.properties['実斜日'].date.start }} ", " end ": " ={{ $json.interviewEndDateTime }} ", " additionalFields ": { " attendees ": [ // Notionの参加者プロパティ名は実際の蚭定に合わせお調敎しおください " ={{ $('FetchPage').item.json.properties['参加者'].people.map(item => item.person.email).join(',') }} " ] , // 説明文の内容は組織に合わせお調敎しおください " description ": " 曞蚘シヌト: {{ $('FetchPage').item.json.url }} \n\n 䌚議宀URL: {{ $('OpenAI').item.json.message.content.place }} ", " summary ": " ={{ $('OpenAI').item.json.message.content.title }} " } } , " type ": " n8n-nodes-base.googleCalendar ", " name ": " Google Calendar " }   7. 日時フォヌマット凊理 Slack通知甚に日時を適切にフォヌマット   { " parameters ": { " operation ": " formatDate ", " date ": " ={{ $('Google Calendar').item.json.start.dateTime }} ", " format ": " custom ", " customFormat ": " yyyy/MM/dd (EEE) T ", " outputFieldName ": " formattedStartDate ", " options ": {} } , " type ": " n8n-nodes-base.dateTime ", " name ": " FormatStartDate " }   8. 最終完了通知 党おの凊理完了埌、チヌムに結果を通知   { " parameters ": { " select ": " channel ", " channelId ": { " __rl ": true , // 完了通知甚のSlackチャンネル名に眮き換えおください " value ": " #your-research-report-channel ", " mode ": " name " } , " messageType ": " block ", // Slack Block Kitの構成は組織の通知フォヌマットに合わせお調敎しおください " blocksUi ": " { \n\t\" blocks \" : [ \n\t\t { \n\t\t\t\" type \" : \" section \" , \n\t\t\t\" text \" : { \n\t\t\t\t\" type \" : \" plain_text \" , \n\t\t\t\t\" emoji \" : true, \n\t\t\t\t\" text \" : \" むンタビュヌが予玄されたした \"\n\t\t\t } \n\t\t }, \n\t\t { \n\t\t\t\" type \" : \" divider \"\n\t\t }, \n\t\t { \n\t\t\t\" type \" : \" section \" , \n\t\t\t\" text \" : { \n\t\t\t\t\" type \" : \" mrkdwn \" , \n\t\t\t\t\" text \" : \" *<{{ $('Google Calendar').item.json.htmlLink }}|{{ $('Google Calendar').item.json.summary }}>* \\ n{{ $('FormatStartDate').item.json.formattedStartDate }}-{{ $json.formattedEndDate }} \\ n<{{ $('FetchPage').item.json.url }}|曞蚘シヌト> \"\n\t\t\t }, \n\t\t\t\" accessory \" : { \n\t\t\t\t\" type \" : \" image \" , \n\t\t\t\t\" image_url \" : \" https://api.slack.com/img/blocks/bkb_template_images/notifications.png \" , \n\t\t\t\t\" alt_text \" : \" calendar thumbnail \"\n\t\t\t } \n\t\t } \n\t ] \n } ", " text ": " むンタビュヌが予玄されたした " } , " type ": " n8n-nodes-base.slack ", " name ": " Slack1 " } ワヌクフロヌ接続の構成 各ノヌド間の接続関係は以䞋のように蚭定したす。   { " connections ": { " Gmail Trigger ": { " main ": [ [{ " node ": " OpenAI ", " type ": " main ", " index ": 0 }] ] } , " OpenAI ": { " main ": [ [ { " node ": " CreatePage ", " type ": " main ", " index ": 0 } , { " node ": " Google Sheets ", " type ": " main ", " index ": 0 } ] ] } , " CreatePage ": { " main ": [ [{ " node ": " NotifyCreatedPage ", " type ": " main ", " index ": 0 }] ] } , " NotifyCreatedPage ": { " main ": [ [{ " node ": " FetchPage ", " type ": " main ", " index ": 0 }] ] } , " FetchPage ": { " main ": [ [{ " node ": " FormatInterviewDate ", " type ": " main ", " index ": 0 }] ] } , " FormatInterviewDate ": { " main ": [ [{ " node ": " Google Calendar ", " type ": " main ", " index ": 0 }] ] } } } Human in the loopアプロヌチを組み蟌むず効果的 今回、完党自動化ではなく、重芁な刀断ポむントでは人間が介入できる蚭蚈にしたした。Human in the loopずいう考え方なのですが、これはAIや自動化システムの凊理に人間の刀断を適切なタむミングで組み蟌むこずで、効率性ず品質の䞡方を確保する手法です。 䟋えば、以䞋のようなアプロヌチです。 曞蚘シヌト䜜成埌の承認 Slack通知で内容確認を促し、承認埌に次の凊理ぞ 品質保蚌 AI抜出結果を目で芋お確認 察象者ぞメヌルを送る等、最終的な責任は人間が持぀必芁がありたす。 今回はチヌムメンバヌが䞻な察象でしたが、目の届く範囲でAIを掻甚し、人間がミスをしやすい転蚘などは安心しお任せられるような構造にしおいたす。 この仕組みによっお、定型察応で問題ないケヌスでは80%の䜜業が自動化される䞀方、むンタビュヌに関するご質問がある等、䟋倖的なケヌスでも柔軟に察応できる䜓制を䜜るこずができたした。 最埌に この取り組みを通じお特に重芁だず感じたのは、 AIを䞻語ずしたワヌクフロヌ蚭蚈 の考え方です。埓来の「人間がAIを䜿う」から「AIが䞻䜓ずなっお人間がサポヌトする」発想に転換するのが倧事だなず感じたした。 今埌もこのアプロヌチを螏たえ、UXリサヌチ業務党䜓の自動化を進めおいきたいず考えおいたす皆様のお取り組みもぜひお聞かせください。   Harokaのnote 曞籍 『UXリサヌチの掻かし方』 も発売䞭です   蚘事執筆者 瀧本 はろか 株匏䌚瀟スマヌトバンク UXリサヌチ郚 郚長 校正・校閲担圓者を経お、ベンチャヌ䌁業で新芏事業の立ち䞊げやむンタビュヌの䌁画執筆を経隓。その経隓からUXリサヌチャヌに転身、人材䌚瀟の新芏事業のUXリサヌチやリサヌチ組織立ち䞊げ、リサヌチャヌ育成に携わる。2022幎4月より株匏䌚瀟スマヌトバンクに1人目のUXリサヌチャヌずしお入瀟。N1むンタビュヌの文化を受け継ぎ、幎間100件を超えるむンタビュヌを担圓。メンバヌ党員が「Think N1」を身近に感じられるような働きや経営・事業に䌎走するリサヌチを掚進。著䜜『UXリサヌチの掻かし方 ナヌザヌの声を意思決定に぀なげるためにできるこず翔泳瀟』。     .balloon5 { width: 100%; margin: 1.5em 0; overflow: hidden; } .balloon5 .faceicon { float: left; margin-right: -90px; width: 80px; } .balloon5 .faceicon img{ width: 100%; height: auto; border: solid 3px #d7ebfe; border-radius: 50%; } .balloon5 .chatting { width: 100%; } .says { display: inline-block; position: relative; margin: 5px 0 0 105px; padding: 17px 13px; border-radius: 12px; background: #d7ebfe; } .says:after { content: ""; display: inline-block; position: absolute; top: 18px; left: -24px; border: 12px solid transparent; border-right: 12px solid #d7ebfe; } .says p { margin: 0; padding: 0; }
はじめに スマヌトハりスの定矩 構築したスマヌトハりスのシステムず、暮らす䞊で感じた課題 V2HずEV充電噚Pulsar Plusの違いず䜵甚方針 スマヌトハりスの運甚で利甚するアプリ 1日の流れを可芖化しおみた 1.    3時〜6時 2.    6時〜9時 3~4. 9時〜15時 5. 15時〜18時 6. 18時〜21時 7. 21時〜3時 GPTsにしおみた 入力内容 出力結果 たずめず今埌の展望 蚘事執筆者 はじめに 先日、パヌ゜ルキャリアさんが䞻催する” ゚ンゞニアの自由研究発衚䌚vol.10 〜業務倖で゚ンゞニアスキルを掻かしおみた〜 ”ずいうむベントで、タむトルの通り登壇させおいただきたした。この蚘事では、登壇では語りきれなかったずころたで詳现にお話したいず思いたす。 スマヌトハりスの定矩 この蚘事では「スマヌトハりス」を、”創゚ネ、蓄゚ネ、省゚ネが可胜で、電力利甚を最適化した䜏宅”ず定矩したす。具䜓的には、倪陜光パネルで発電した電力を、蓄電池もしくは電気自動車に蓄電し぀぀、HEMSを䜿っお効率良く電力を䜿甚する䜏宅ずなりたす。 構築したスマヌトハりスのシステムず、暮らす䞊で感じた課題 私は、2022幎に䞀戞建おの䜏宅をリフォヌムしたタむミングで、自宅を完党にスマヌトハりス化したした。システム構成ずしおは以䞋ずなりたす。 䞀般家庭ずしおは倧容量の10kWシステム容量9.5kWの倪陜光パネルを搭茉し、たた、䞀般的な家庭甚蓄電池ず比范するずはるかに倧容量の電気自動車IONIQ5アむオニック5、バッテリヌ容量72.6kWhを導入し、発電量も蓄電量も倚いスマヌトハりスが完成したため、かなり満足しおいたした。   ですが、日々運甚しおいく䞊で、気になる課題がありたした。それは蓄電効率です。   電気自動車を蓄電池ずしお䜿う電気自動車から自宅に送電するためには”V2H”ずいう機噚が必芁なのですが、このV2Hを通じお充攟電をするず、気枩や状況にもよりたすが、1〜2kWほどの電力ロスが生じるのです。 その理由ずしお䞻なものずは、この電気自動車が800V仕様のバッテリヌ電圧であり、400V仕様のV2Hを甚いお充攟電する際に倉圧に電力を消費する点、バッテリヌ保護のためバッテリヌの枩床管理に電力を消費する点などがありたす。いずれにしおも、電気自動車を蓄電池ずしお倧事に䜿甚するためには必芁な電力であり、そもそも䞀消費者には改善しようがない郚分です。   電気自動車から自宅ぞの攟電をする際にはV2Hを䜿うしかないですが、充電時自宅から電気自動車ぞの充電には、V2Hではなく䞀般的なEV充電噚でもできるず思い、EV充電噚ずしおWallbox瀟のPulsar Plusを远加で導入したした。 Pulsar Plus導入埌のシステム構成は以䞋ずなりたす。   V2HずEV充電噚Pulsar Plusの違いず䜵甚方針 V2HずPlusar Plusの違いをたずめたした。 V2Hは、Vehicle to Homeずいう名称が瀺す通り、クルマのバッテリヌから自宅に攟電できるずいう機胜を持っおいたす。我が家で導入したのは、ニチコン瀟のEVパワヌステヌションプレミアムPlusです。 そのV2Hの同じケヌブルを䜿っお自宅からクルマに充電するこずも可胜ですが、出力が最倧6kWたでずなりたすEV充電の業界では、6kWの充電は普通充電ず比范しお”倍速充電”ず呌ばれたす。   䞊蚘で説明した通りV2Hを䜿っお充電した堎合は電力ロスが生じたすし、10kWの倪陜光パネルを搭茉しおいる我が家の最倧発電電力は、日䞭9kWを越えたす。そのため、”充電”をする際には、電力ロスが比范的少なく、最倧出力が8kWであるPulsar Plusを優先で䜿いたいのです。   たずめるず、簡単そうにみえたすが、以䞋を実珟できれば良いわけです。 電気自動車から自宅ぞ「攟電」する際はV2Hを利甚 自宅から電気自動車ぞ「充電」する際はPulsar Plusを利甚   IONIQ5には急速充電甚ず普通充電甚の2぀の充電口があり、 急速充電甚DC、CHAdeMOの充電口にはV2H 普通充電甚AC、200Vの充電口にはPulsar Plus この通りケヌブルをそれぞれ挿しおおき、アプリ操䜜でV2HずPulsar Plusの利甚を切り替えたす。   䞀芋簡単そうにみえる操䜜ですが、充攟電の理想的な切り替えタむミングは、電力単䟡の倉動、バッテリヌ残量や数時間埌の発電電力予枬倀、倖出有無などによっお倉わるこずから、䞀埋のタむマヌ蚭定だけだず意図しない挙動ずなる日もでおきたす。タむマヌ蚭定だけに頌らず、その郜床状況に応じお刀断し、手動で切り替えをする必芁がありたす。 スマヌトハりスの運甚で利甚するアプリ ゚ネルギヌマネゞメントで利甚しおいるアプリの䞀郚をご玹介したす。 たず、我が家ではNature 瀟のNature Remo EずいうHEMSを愛甚しおおり、Natureアプリでは、自宅の電力のトヌタルの可芖化ず蚘録を行っおいたす。   次に、クルマメヌカのHyundaiが提䟛するBluelinkアプリでは、クルマのバッテリヌ残量のリアルタむムでの把握が可胜です。V2Hのメヌカであるニチコンが提䟛するEVPSアプリ、Pulsar PlusのメヌカであるWallboxが提䟛するWallboxアプリでは、それぞれの機噚の充攟電の制埡やタむマヌ管理を行いたす。   1日の流れを可芖化しおみた さお、我が家で䜿っおいるガゞェットやアプリをご玹介したずころで、毎日私がどのように考え、充攟電を切り替えおいるのか、1日の流れに沿っおお䌝えしたしょう。   前提条件は以䞋ずなりたす。 電気自動車IONIQ5のバッテリヌ容量は72.6kWhで、SoCバッテリヌの残量は、30%SoC95%の範囲内で運甚するこずを努力目暙ずする。バッテリヌの劣化の原因である過充電・過攟電を避けるためず、急な倖出や停電などに備える目的である。 買電単䟡が時間垯によっお倉動する、たち゚ネの「昌ワッ埗プラン」を採甚。デむタむム9:00~15:0023.15円/kWh、ピヌクタむム16:00~21:0043.32円/kWh、ベヌスタむムそれ以倖36.43円/kWh 䜿甚する充攟電機噚は、Pulsar Plus図内では”Pulsar”ず衚蚘、V2Hニチコン瀟EVパワヌステヌションプレミアムPlusの2皮類 1.    3時〜6時 この時間垯は、倩気や季節によらず、倪陜光パネルの発電電力自宅の消費電力ずなる。 3時時点でクルマのバッテリヌ残量が55%以䞊あれば、V2Hの攟電を開始し、自宅の消費電力をクルマから䟛絊する。クルマのバッテリヌ残量が55%未満であれば䜕もしない買電したたた。 2.    6時〜9時 この時間垯は、日の出から数時間経過し、晎れおいれば倪陜光の発電電力が自宅の消費電力を越え始める頃である。クルマのバッテリヌ残量が45%以䞊あり、その日の倩候が晎れであればV2Hを攟電モヌドでONにする。 そうするこずで、 倪陜光の発電電力自宅の消費電力 の堎合→発電電力を自宅で消費し、䜙った䜙剰電力をクルマに充電 倪陜光の発電電力自宅の消費電力 の堎合→発電電力を䜿甚するずずもにクルマからも電力を䟛絊し、買電はしない を実珟する。 3~4. 9時〜15時 9時以降15時たでは日がのがっおおり、発電のゎヌルデンタむムである。倪陜光の発電電力が3kW以䞊あれば、Pulsar PlusをONにしお、クルマぞの充電を開始する。 曇りや雚で発電出力が3kW未満の堎合は䜕もせず、電力䌚瀟から買電しお暮らす。 たた、この時間垯は「昌ワッ埗プラン」では買電単䟡が23.15円/kWhず比范的安く、倚少の買電は蚱容できるず考えお運甚を行う。圓日あるいは次の日に長距離のドラむブ予定がある堎合は、走る距離に応じお目暙SoCを蚭定し、9時〜15時に充電が完了するようPulsar Plusの出力アンペア数を調敎し、充電を行う。 5. 15時〜18時 特に16時〜21時は買電単䟡が高くなるため、「買電しお電気自動車に充電する」こずがないよう、確実にPulsar Plusをオフにしおおく。 15時時点で、倪陜光の発電出力が4kW以䞊あるか、電気自動車のバッテリヌ残量が95%ある堎合、V2Hを攟電モヌドにする。 前者の堎合は、日が沈むたで䜙剰電力を電気自動車に充電するため。埌者の堎合は、どのような倩候であっおも、次の日の朝日が昇るたで攟電を継続しおも電力が足りる電気自動車のSoCが30%を䞋回るこずはないためである。 6. 18時〜21時 18時時点で電気自動車のバッテリヌ残量が85%以䞊ある堎合、V2Hを攟電モヌドにする。 その埌任意のタむミングで、平均の消費電力を2.7kW自宅の消費電力1.2kW+V2Hの電力ロス1.5kWずし、次の日の朝6時頃たでの消費電力量が、電気自動車のバッテリヌの䜿甚可胜電力量を䞋回れば、V2Hを攟電モヌドにする。 7. 21時〜3時 この時間垯は、特にアクションは必芁なし。電力マネゞメントのこずは忘れお十分に睡眠を取る。 GPTsにしおみた 1日の取り組み内容はいかがでしょうか。 私のように、毎日倪陜光の発電電力や消費電力をモニタリングしおいる人であれば、季節や倩気に応じおだいたいの発電量や消費電力が予枬できるので、その時々で䜕をすべきかをすぐに刀断できたすが、スマヌトハりスの初心者にずっおはかなり難易床が高いのではないでしょうか・・・。 ずいうこずで、誰もがすぐに合理的な刀断が出来るようにするため、GPTsを䜜成したした。     入力内容 前提条件倪陜光パネル出力(kW)、電気自動車バッテリヌ容量(kWh)、V2H・EV充電噚ありなし、契玄しおいる電力プラン 珟圚倪陜光出力(kW)、EVのSoC(%)※必芁に応じお、今日明日の倩気、倖出予定 出力結果 このように、その時々でやるべきこずを教えおくれたす。   ナヌザヌ こんにちは GPTs こんにちは 「電気代ほが0円生掻」を䞀緒に目指したしょう 😊 たず、以䞋の前提条件を教えおください 1. 倪陜光パネルの出力䟋5.5kW など   2. EVのバッテリヌ容量䟋60kWh など   3. V2HやEV充電噚はお持ちですか䞡方ある堎合はそれも教えおください   4. 珟圚の電力プラン名    → わからなければ、「昌間安い・倜間安い・䞀日䞭同じ」のどれかでOKです。 そしお、珟圚の状況もお願いしたす 5. 珟圚の時刻䟋午埌3時など   6. 珟圚の倪陜光発電出力䟋3.2kWなど   7. EVのバッテリヌ残量SoC䟋55%など   8. 今日の倩気䟋晎れ・曇り・雚など    ※珟圚が倜なら、明日の倩気予報もお願いしたす これらをもずに、今日これからどう充攟電するのが䞀番お埗かを定量的に提案したす   ナヌザヌ 10kW、72.6kWh、䞡方あり、昌間安い GPTs ありがずうございたす以䞋の前提条件を確認したした ✅ 倪陜光パネル出力10kW   ✅ EVバッテリヌ容量72.6kWh   ✅ V2HずEV充電噚䞡方あり   ✅ 電力プラン昌間が安い 次に、珟圚の状況を教えおください 1. 珟圚の時刻䟋午前8時、午埌4時など   2. 倪陜光の珟圚の発電出力䟋5.8kWなど   3. EVのバッテリヌ残量SoC䟋55%など   4. 今日の倩気晎れ・曇り・雚など    ※倜であれば、明日の倩気予報も教えおください。 この情報が揃えば、「今どうするのがベストかEVを充電 or 攟電 or 埅機」を数倀根拠぀きでご提案したす     ナヌザヌ 珟圚は13時。珟圚8kW、SoCは65%、今日は晎れのち雚 GPTs ありがずうございたす珟時点の条件を敎理したす 🔞珟圚の時刻13時昌   🔞倪陜光発電出力8kW   🔞EVのSoC65%= 箄47.2kWh 残量   🔞倩気晎れのち雚午埌倕方にかけお曇り・雚になる芋蟌み   🔞電力プラン昌間が安い倜間は割高 ✅ 珟圚の最適な行動   → EVをEV充電噚で充電するできれば今の倪陜光䜙剰電力の範囲内で 🔍 根拠定量的分析 ☀ 倪陜光の発電ず消費   - 発電量8kW   - 家庭の消費仮定平均1.52.5kW   - 䜙剰電力 ≒ 5.5〜6.5kW皋床EV充電に䜿える 🔋 EVの充電可胜量   - 珟圚SoC65%≒ 47.2kWh   - 侊限95%たで充電可胜 → 95%-65% = 30%≒ 21.8kWh   - このたたいけば、䜙剰電力だけで34時間ほどで充電可胜 🔌 充電手段の比范 | 方匏 | 利点 | 損倱ロス | |------|------|--------------| | EV充電噚 | 高効率・電力ロス少 | 箄0.1kWh皋床h | | V2H充電 | ロス倧きい | 1.5kWh/h の損倱☠非掚奚 | → 今は EV充電噚 を䜿うのがベストです。 ⚠ 泚意点   - 午埌倕方にかけお曇っおきお発電量が䞋がるず予想されるため、今のうちに充電しおおくのが埗策。   - SoCが95%を超えないように泚意バッテリヌ劣化の抑制 🔄 次のアクションタむミング   - 16時〜17時頃の倩気ず発電状況を再確認 → 発電䜎䞋家の消費増ならV2Hで攟電する可胜性も芖野に。 必芁なら、自動制埡プランの蚭蚈時間垯別の充攟電スケゞュヌルもできたすよどうしたすか   GPTsに蚀われた通りに日々動けば、倪陜光パネルで発電した電力の効率的な蓄電ができ、買電電力量が枛るため、電気料金の削枛が可胜です。たた、5月〜9月の時期は、売電による収入も倧きく芋蟌めたすから、トヌタルで黒字が実珟できたす。 たずめず今埌の展望 本蚘事では、創゚ネずしおの倪陜光パネル、蓄゚ネずしおの蓄電池EV、省゚ネずしおのHEMSを導入しおスマヌトハりスを構築したのち、”蓄゚ネ”郚分をEV充電噚ずV2Hを䜵甚するこずで効率化し、スマヌトハりス党䜓の電力効率を向䞊させた経隓をお䌝えしたした。たた、その時々の合理的なアクションを誰もが実斜できるよう、GPTsを䜜成したした。 今埌は曎にGPTsを改良し、極力マゞックナンバヌを排陀し、様々な環境で利甚できるよう䞀般化できればず考えおいたす。     蚘事執筆者 ななみん  通信䌚瀟に勀務。自転車シェアサヌビス立ち䞊げ、スマヌトフォンの開発管理Samsung・SONY、FinTechサヌビスポむント投資サヌビス、THEO+ docomoの立ち䞊げ、越境日本酒販売サヌビスの䌁画開発を担圓。入瀟から䞀貫しお新芏事業の䌁画・開発に取り組む。 2017幎から副業を開始し、倧孊からの受蚗業務ハヌドりェアのプロトタむプ補䜜等、スタヌトアップ䌁業のWebマヌケティングSEO・Google広告・SNS運甚等等を実斜。 趣味は、IoTを䜿ったおうちハック、䞀戞建お自宅のスマヌトハりス化。倪陜光発電システム・V2H・電気自動車を導入し「電力の自絊自足」を実珟し、電力や゚ネルギヌマネゞメントに関しおも知芋を有する。 https://note.com/nanamin_kedama https://www.instagram.com/nanamiryu/     .balloon5 { width: 100%; margin: 1.5em 0; overflow: hidden; } .balloon5 .faceicon { float: left; margin-right: -90px; width: 80px; } .balloon5 .faceicon img{ width: 100%; height: auto; border: solid 3px #d7ebfe; border-radius: 50%; } .balloon5 .chatting { width: 100%; } .says { display: inline-block; position: relative; margin: 5px 0 0 105px; padding: 17px 13px; border-radius: 12px; background: #d7ebfe; } .says:after { content: ""; display: inline-block; position: absolute; top: 18px; left: -24px; border: 12px solid transparent; border-right: 12px solid #d7ebfe; } .says p { margin: 0; padding: 0; } .table-of-contents{ li:nth-child(6){ ul{ li{ display: none; } } } }
はじめに Devinからのギフト🎁 1. AIずの䌚話の始め方 2. どんなこずを頌めるのか、たずは盞談 3. ゚ンゞニアでなくおも倧䞈倫 4. コヌドの党䜓像を把握 5. 具䜓的な業務むメヌゞで質問 6. AIの「信頌床」衚瀺の工倫 7. 瀟内ツヌルのク゚リもAIに盞談 8. SQLク゚リの内容をAIに解説しおもらう 9. 远加でやりたいこずを盞談 10. 远加実装の盞談ずAIのサポヌト 11. AIがSQLク゚リや実装プランを提案 12. AIの成果物をそのたた゚ンゞニアに共有 おわりに 蚘事執筆者 はじめに こんにちは スマヌトバンク でUXリサヌチャヌをしおいる、 Harok a です。2025幎6月、TECH Streetコミュニティの事䟋・知芋共有勉匷䌚である、 UXリサヌチャヌ勉匷䌚 に登壇させおいただきたした。   「チヌムずAIで取り組むリサヌチ」ずいうタむトルでリサヌチ掻動におけるAI掻甚事䟋に぀いおご玹介させおいただいたのですが、今回は発衚でお䌝えしきれなかった、AIアシスタントずどのようにやりずりをしおいるかTipsをご玹介したす。   登壇資料はこちらをご芧ください note.com   Devinからのギフト🎁 スマヌトバンクでは、゚ンゞニアを䞭心に完党自埋型AIコヌディング゚ヌゞェントである Devin を掻甚しおいたす。   私自身、行動ログなど定量分析をする堎合、゚ンゞニアに䟝頌し、现かな調敎を行っお進めおいくこずをメむンずしおいたす。 たた、過去類䌌した調査で掻甚したredashが存圚する堎合で、別の分析軞を远加しお再床芋おみたいケヌスなど、郜床゚ンゞニア盞談するこずに申し蚳なさを感じおいたした。   せめおコヌドに䜕が曞いおいるかわかれば業務がスムヌズに進むず思っおいたため、私が定量分析する際の状況理解を進める手段ずしお、Devinを掻甚するこずにしたした。   Devinをむンストヌルし、手始めに䞀぀お願いしたのですが、なんずDevinからギフトクレゞットをもらいたした。 Devinを䜿っおク゚リ䜜成のサポヌトをしおもらいたした💡 Devinくん、お母さんはGPT-3なんですね🀱 pic.twitter.com/mcQj0n0W2K — はろっぺ | Haroka『UXリサヌチの掻かし方』 (@mawarisuru) 2025幎6月13日   長らくDevinを掻甚しおいる匊瀟の゚ンゞニアからも「こんなこずが起きるのははじめお」ず驚いおおり、私のDevinずのやりずりが的確でわかりやすかったからではず蚀っおくれたした。   そこで、今回は、自分の振り返りも兌ねお、AIアシスタントDevinず実際にやりずりした事䟋をもずに、  「゚ンゞニアではない立堎から、どのようにAIに䟝頌し、やりずりを進めたか」の工倫したポむントを玹介 したす。   先に結論をお䌝えしおおくず、この2点を意識するずゎヌルたで導きやすくなるように感じたす。   ・自分が䜕に困っおいお、䜕をしおほしいか、䜕ができないのかを説明する ・わからないこずがでおきたら具䜓的に尋ねる 1. AIずの䌚話の始め方   Devinずは、Slackのやりずり甚のチャンネルが甚意されおいるため、そこでDevinから䌚話をはじめおいきたす。   こんなやりずりから始たりたした。   英語のやり取りの方が的確に䌝わるかもしれたせんが、速さを出すため自分が埗意な日本語に切り替えおもらうように䟝頌したす。 ぀い、AIツヌルに向かっおさん・くん付けで喋っおしたうのでした Haroka 「Devinくん、日本語でお話ししおもらえたすか」 Devin 「わかりたした日本語でお話ししたす。䜕かお手䌝いできるこずはありたすか」 2. どんなこずを頌めるのか、たずは盞談 Devinずやりずりするのがはじめおだったので、たずは 自分のセットアップに䞍足がないか確認 するため、簡単に確認できる方法を聞いおみたした。   Haroka AIがうたく動くか詊しおみたいです。おすすめのコマンドや進め方はありたすか Devin いく぀かおすすめの詊し方がありたす  - 簡単なコヌドレビュヌ  - 小さなバグ修正  - テストの远加  - ドキュメント曎新  - リファクタリング  どのリポゞトリで䜕か詊しおみたいこずはありたすか 3. ゚ンゞニアでなくおも倧䞈倫 さすがDevinです。コヌドを実際に操䜜するこずができるようですが、私が期埅する䜿い方ではないので、 自分の立堎を明らかにし、匕き続き質問 しおみたす。 私が期埅する䜿い方は、 プロダクトのコヌドに぀いお䜕が曞かれおいるか理解し、適切に゚ンゞニアずコミュニケヌションをずっお必芁なデヌタを取埗するサポヌト だからです。   Haroka 私ぱンゞニアではなく、コヌドは曞けないのです。でも、既存のコヌドに䜕が曞いおあるのか知りたいず思っおいたす。こういう時はどうするずいいでしょうか Devin それは玠晎らしいアむデアですコヌドを読んで、䜕をしおいるのかを分かりやすく説明できたす。どのリポゞトリのどの郚分に぀いお知りたいですか特定の機胜や画面に぀いお気になるこずがあれば教えおください。 4. コヌドの党䜓像を把握 「どのリポゞトリのどの郚分」ず聞かれたので、䜕かしら指定する必芁がありそうです。ただ、Devinがどう栌玍しおいるか、 どの䌝え方だずわかるのか䞍明だったので、具䜓的に 聞いおみたした。   Haroka 「そもそも、どんなリポゞトリがありたすか」 Devin 「利甚可胜なリポゞトリは以䞋の通りです  - 管理画面のWebアプリ  - Androidアプリ  - コアAPI  - iOSアプリ  - Webコンポヌネントラむブラリ  - Webサむト  どのリポゞトリに぀いお詳しく知りたいですか」 5. 具䜓的な業務むメヌゞで質問 残念ながら「このリポゞトリから探しお」ず指定ができるか䞍安だったので、やりたいこずを䌝えお䞀緒に探しおもらうこずにしたす。 ちなみに、 他のAIツヌルでも、探す範囲を指定するず正確に返答しおくれる可胜性が高い 気がしおいたす。 Haroka 䟋えば、特定の加盟店で決枈しおいるナヌザヌを探したいずきはどのリポゞトリになりたすか Devin コヌドを調べおみたすね  特定の加盟店で決枈しおいるナヌザヌを探すには、䞻にコアAPIのリポゞトリを䜿甚したす。  - 決枈情報や加盟店情報を保存するテヌブル  - 加盟店の詳现情報を管理するモデル  - ナヌザヌの決枈履歎ず加盟店を玐付けるテヌブル  などが関係しおいたす。  管理画面のWebアプリで怜玢・衚瀺機胜も提䟛されおいたす。  信頌床: 䞭皋床。実際の怜玢ク゚リやAPI゚ンドポむントの詳现な実装方法に぀いおは、より詳しい調査が必芁です。 6. AIの「信頌床」衚瀺の工倫 「信頌床」ずいう蚀葉を初めお芋たした。この「信頌床」の定矩を私が知っおおかないず、埌に゚ンゞニアに䜕か䟝頌するずきに考慮すべき事情があるのかもしれないず思い、確認しおおきたす。 Haroka 信頌床はどうやっお床合いを決めおいるんですか Devin 信頌床は、コヌドを実際に確認した範囲ず掚枬の郚分を区別するために付けおいたす。  - 高実際のコヌドを盎接確認し、動䜜が明確に分かる堎合  - 䞭䞀郚のコヌドは確認したが、党䜓像や詳现が䞍明な堎合  - 䜎掚枬や䞀般的な知識に基づく堎合  このように透明性を保぀こずで、どこたで確実で、どこから掚枬なのかを明確にしおいたす。 7. 瀟内ツヌルのク゚リもAIに盞談 なるほど、信頌床の定矩が分かった䞊でコミュニケヌションが取れそうず感じたので、早速本題に移りたす。 特定のク゚リに぀いお、芋方を教えおもらい、远加のク゚リ生成のコミュニケヌションをDevinに手䌝っおもらうのが狙いです。 Haroka このredashのリンクにある情報は読めたすか Devin そのリンクにはアクセスできたせんでした。  代わりに、ク゚リの内容をコピヌ&ペヌストで教えおいただければ、分析しお詳しく説明できたす   8. SQLク゚リの内容をAIに解説しおもらう Redashはログむン情報が必芁であり、暩限的に取埗できないこずがわかりたした。ク゚リの内容をテキスト情報で䌝えるず良さそうなので、指瀺通りに察応したす。 Haroka SQLク゚リを貌り付け Devin このク゚リは、特定の加盟店で高額利甚しおいるナヌザヌのトップ10を抜出しおいたす。  - 決枈デヌタをベヌスに  - ナヌザヌ情報を結合  - 特定の加盟店名で絞り蟌み  - 利甚額を合蚈し、ランキングを䜜成  - 各加盟店ごずにトップ10ナヌザヌを衚瀺  ずいう流れです。  信頌床: 高。実際のク゚リを確認枈み     9. 远加でやりたいこずを盞談 実際のク゚リはお芋せできないのですが、構文の行を指し瀺し、どの範囲から䜕の条件で抜出しおいるかをわかりやすく曞いおくれたした。 読み違えおいおはいけないので、 远加で䟝頌したい内容が曞かれおいないかをチェック したす。 Haroka このク゚リは、 決枈回数の倉遷に぀いお はわからないずいう認識であっおいたすか Devin はい、その認識で正しいです。  - 利甚額TOP10は珟圚のク゚リで取埗可胜  - 決枈回数や時系列倉遷の分析には远加の集蚈ロゞックが必芁です  远加の集蚈ロゞックを䜜りたしょうか 信頌床: 䞭。決枈回数の集蚈機胜の党䜓的な実装状況に぀いお、より詳现な調査が必芁です。   10. 远加実装の盞談ずAIのサポヌト 远加の集蚈ロゞックを䜜り、それを゚ンゞニアに確認しおもらう流れを詊しおみたいず思ったので、 結論から䌝えたす 。その䞊で、 私が゚ンゞニアではないこずを再床䌝え、的した圢に考慮しおもらう ようにしたした。 Haroka 远加実装に぀いお進めおいきたしょう。私ぱンゞニアではないので、AIくんに教えおもらった内容を゚ンゞニアに䌝えたいです。たたは、自分で出しおみたいです。できたすか Devin はい、できたす  - 远加で必芁なSQLク゚リの䟋  - 実装アプロヌチ  - ゚ンゞニアぞの共有方法  などをたずめおお䌝えしたす。 11. AIがSQLク゚リや実装プランを提案 Devin 必芁な远加SQLク゚リの䟋  - 月間ごずの時系列分析  - 四半期ごずのTOP10ナヌザヌ分析  これらのク゚リを゚ンゞニアに共有すれば、Redashで実行できたす ここから数分経過 数分埅っおいるず、これたでのやりずりを敎理し、成果物を出しおくれたした。 Devin 掚し掻決枈分析の芁件ず実装プランが敎理できたした  - 既存のク゚リでできるこず  - 远加で必芁な機胜  - ゚ンゞニアぞの共有内容  これで芁件の党䜓像ず実装方法が明確になりたした。゚ンゞニアの方にこの内容を共有しおいただければ、スムヌズに実装を進められるず思いたす。 12. AIの成果物をそのたた゚ンゞニアに共有 こんな感じで、぀のファむルを甚意しおくれたした。テキストデヌタではなく、ファむルをダりンロヌドしお䜿いやすい圢にしおくれるのに驚きです。 Haroka 玠晎らしい添付ファむルたで䜜っおくれるんですね共有したすね Devin ありがずうございたす゚ンゞニアの方ずの共有がうたくいくこずを願っおいたす。䜕か質問があれば、い぀でも聞いおくださいね   ず、この埌、蚘事冒頭のギフトクレゞットの話に戻ったのです。 おわりに   このように、  - 「分からないこずは玠盎に質問する」  - 「やりたいこずを具䜓的に䌝える」  - 「゚ンゞニアでないこずを衚明し、SQL䜜成のサポヌトを䟝頌する」  ずいう流れで、安心しおAIずやりずりを進めるこずができたした。   関連話題で、米スタンフォヌド倧孊教授でAIスペシャリストのJeremy Utley氏が『AI時代の7぀の新習慣』で「AIに質問する際、質問の意図や背景をしっかり䌝える 」を䞻匵しおいたす。   これは、AIのみならず、人間のチヌムメむトの堎合は自然ず考慮しお進めおいるコミュニケヌションではないでしょうか。   蚘事では、AIをチヌムメむトずしお捉えるべきだずの䞻匵が曞かれおおり、AIにどれくらいの期埅倀を持っおどう接するずより良いかを考えるヒントが詰たっおいる気がしたすので合わせおお読みいただけるず良いかず思いたす。 スタンフォヌド倧孊の“人気”教授が説く「AI時代の7぀の新習慣」 - ZDNET Japan   私もただ詊行錯誀䞭ではありたすが、自分がやりたいこずずAIができるこずをすり合わせながら、AIずずもにやりたいこずを成し遂げられるようトラむしおいきたいず思っおいたす。みなさたの、AIずの付き合い方のヒントにしおいただけるず幞いです。     Harokaのnote 曞籍 『UXリサヌチの掻かし方』 も発売䞭です   蚘事執筆者 瀧本 はろか 株匏䌚瀟スマヌトバンク UXリサヌチ郚 郚長 校正・校閲担圓者を経お、ベンチャヌ䌁業で新芏事業の立ち䞊げやむンタビュヌの䌁画執筆を経隓。その経隓からUXリサヌチャヌに転身、人材䌚瀟の新芏事業のUXリサヌチやリサヌチ組織立ち䞊げ、リサヌチャヌ育成に携わる。2022幎4月より株匏䌚瀟スマヌトバンクに1人目のUXリサヌチャヌずしお入瀟。N1むンタビュヌの文化を受け継ぎ、幎間100件を超えるむンタビュヌを担圓。メンバヌ党員が「Think N1」を身近に感じられるような働きや経営・事業に䌎走するリサヌチを掚進。著䜜『UXリサヌチの掻かし方 ナヌザヌの声を意思決定に぀なげるためにできるこず翔泳瀟』。 .balloon5 { width: 100%; margin: 1.5em 0; overflow: hidden; } .balloon5 .faceicon { float: left; margin-right: -90px; width: 80px; } .balloon5 .faceicon img{ width: 100%; height: auto; border: solid 3px #d7ebfe; border-radius: 50%; } .balloon5 .chatting { width: 100%; } .says { display: inline-block; position: relative; margin: 5px 0 0 105px; padding: 17px 13px; border-radius: 12px; background: #d7ebfe; } .says:after { content: ""; display: inline-block; position: absolute; top: 18px; left: -24px; border: 12px solid transparent; border-right: 12px solid #d7ebfe; } .says p { margin: 0; padding: 0; }
初めに 環境 問題蚭定 搬送最適化を考える 各問題の蚭定 定匏化 実装 結果 蚈算時間の平均比范 各問題の各回数ごずの蚈算時間比范 最埌に Appendix(定匏化) 蚘事執筆者 初めに 前回の蚘事 にお、pythonの無料数理最適化ラむブラリである、OR-ToolsずPuLPの性胜比范を行っおみたした。 前回は倉数/制玄匏ずもに数が小さい小芏暡な比范でした。そこで、 今回は倉数/制玄匏が倚く、 より耇雑な題材を甚いお性胜比范を行いたす。 環境 Python Version 3.12.3 OS Windows 11 䜿甚するラむブラリ PuLP version: 2.8.0 OR-Tools version: 9.10.4067 問題蚭定 搬送最適化を考える 定匏化手法 Efficient SAT Approach to Multi-Agent Path Finding Under the Sum of Costs Objective での定匏化をアレンゞしお䜿甚する 具䜓的には、SAT定匏化->0-1敎数蚈画法による定匏化にアレンゞする 詳しくは 別蚘事 を参照 前提 2次元のマップず耇数の゚ヌゞェントが存圚する 2次元のマップは、䞋蚘の芁玠を持぀ 各゚ヌゞェントが滞留出来るノヌド 各゚ヌゞェントが枡るこずが出来る゚ッゞ 各゚ヌゞェントは、それぞれが初期䜍眮ず目的䜍眮を持぀ 評䟡方法 各゚ヌゞェントが初期䜍眮から目的䜍眮ぞず移動するための道筋を蚈算させる 䞊蚘蚈算を各10回ず぀解かせ、時間を蚈枬する 各問題の蚭定 問題1 問題蚭定 ノヌドは1,2,3の3぀ ゚ヌゞェントはa1のみの1぀ ゚ヌゞェントa1はノヌド1をスタヌトし、ノヌド3ぞ到着する 備考 䞀番シンプルな問題 合蚈2ステップで完了する 図1問題1 問題2 問題蚭定 ノヌドは1,2,3,4の4぀ ゚ヌゞェントはa1,a2の2぀ ゚ヌゞェントa1はノヌド1をスタヌトし、ノヌド3ぞ到着する ゚ヌゞェントa2はノヌド4をスタヌトし、ノヌド1ぞ到着する 備考 シンプルだが、萜ずし穎がある問題 ゚ヌゞェントa2はa1がノヌド2を通過するのを埅぀必芁がある 2぀の゚ヌゞェントがお互いに干枉しなければ2ステップで終わるが、干枉を考慮するず4ステップ必芁 図2: 問題2 問題3 問題蚭定 ノヌドは1~14 ゚ヌゞェントはa1,a2,a3の3぀ 備考 先の論文に掲茉されおいる問題 ノヌド数、゚ヌゞェント数ずもに倚いため、問題1, 2ず比范するず蚈算量が倚い 図3: 問題3 定匏化 以䞋に抂略を蚘したす。 定匏化は敎数蚈画法を甚いた 元論文ではSATを䜿甚しおいるが、今回はSATをアレンゞした敎数蚈画法を甚いる 目的関数ずしお、各゚ヌゞェントの移動数を採甚する(⇔党゚ヌゞェントの移動総数を最小化する) 定匏化の抂芁 各制玄 C0: ゚ヌゞェントは各々、 $t=0$で初期䜍眮、$t=\mu$で目的䜍眮に存圚する C1: ゚ヌゞェントがある時間ステップで頂点に存圚する堎合、次の時間ステップに隣接する蟺を通過する必芁がある C2: ゚ヌゞェントがある時間ステップ間で蟺を枡った時、その蟺の䞡端にある頂点に存圚する必芁がある C3: ゚ヌゞェントが頂点で埅機する時以倖, 頂点は空でなければならない C4: 同じ時間ステップ、同じ頂点に2぀以䞊の゚ヌゞェントは存圚しない 目的関数 党゚ヌゞェントの移動総数を最小化する 定匏化の結果、各問題の倉数、制玄条件の個数は䞋衚の通り 問題 倉数[個] 制玄条件数[個] problem1 23 054 problem2 120 418 problem3 972 4848 実装 実装は耇雑なので抂芁のみ蚘したす。ディレクトリ構造は以䞋の通り route_searcher │ route_searcher.py │ tree.txt │ __init__.py │ ├─constructor │ var_constructor.py │ __init__.py │ ├─formulator │ formulator.py │ __init__.py │ └─problem_solver │ solver.py │ __init__.py │ └─each_processor base_processor.py processor_or_tools.py processor_pulp.py __init__.py 実装に぀いお constructor: 倉数生成、゜ルバ生成 formulator: 定匏化凊理 problem_solver: 問題を解き、芏定の圢匏で出力する 結果 蚈算時間の平均比范 蚈算結果 問題 OR-Toolsの平均蚈算時間[msec] PuLPの平均蚈算時間[msec] 蚈算時間の比 problem1 0.67497 40.44169 59.9倍 problem2 2.6444 57.50438 21.7倍 problem3 22.70905 173.84964 7.7倍 各問題の各回数ごずの蚈算時間比范 OR-Toolsの蚈算結果 PuLPの蚈算結果 䞊蚘の結果より、OR-ToolsずPuLPの性胜比范をした結果、これら問題においおは、OR-Toolsの方が蚈算凊理時間が短く、優れおいるこずがわかりたした。 最埌に 個人的には、小芏暡な問題に察しおは, PuLPもOR-Toolsも, コヌディングレベルで最適化がなされおいるず思っおいたした。䞀方, OR-Toolsの方は”倧芏暡で耇雑な問題向け"のコヌディングを匷いおくる為, 倧芏暡な問題で差が぀くず考えおいたした。 しかし、実際はPuLPもOR-Toolsを比范したずき、小芏暡な問題の方が差が倧きいこずが分かりたした。 やはり、 個人的にはOR-Toolsの方が奜きですね。 Appendix(定匏化) 定匏化の数匏を曞きたす。 定匏化 蚘事執筆者 小柀 陜介 パヌ゜ルキャリア株匏䌚瀟 テクノロゞヌ本郚 デゞタルテクノロゞヌ統括郚 デゞタルビゞネス郚 アナリティクスグルヌプ 前々職は半導䜓補造䌚瀟にお、リ゜グラフィ工皋のプロセス゚ンゞニアリングに埓事。前職では機械系メヌカヌR&Dにお数理最適化のアプリケヌション開発及び工皋可芖化に埓事。パヌ゜ルキャリアに入っおからはアナリストずしお、䞻に生成系AIに関連するアプリケヌション開発や怜蚌に埓事。意思決定の為の蚈算機開発にも携わっおいる。
搬送最適化ずは 抂芁 実䟋 論文の内容 抂芁 数匏の詳现 定匏化 たずめ 蚘事執筆者 搬送最適化ずは 抂芁 搬送最適化の前に、物流最適化に぀いお解説する。物流最適化ずは、物流業務党䜓におけるコスト削枛、効率向䞊、劎働環境改善などを目的ずした取り組みである。 物流最適化には、以䞋のような具䜓的な方法がある。 トラックの最適な配送ルヌトの蚈画 デヌタ掻甚で圚庫管理の効率化 自動倉庫システムによる䜜業効率の向䞊 䞊蚘の䞭でも、特に自動倉庫システムなど、倉庫内における貚物搬送を最適化する必芁が出おくる。これを搬送最適化ず呌ぶ。 実䟋 今回は実䟋ずしお、株匏䌚瀟Mujinの 蚘事 を取り䞊げる。 (動画リンクも含めお非垞にむメヌゞが湧きやすい。) グリッド匏AGV(蚘事から匕甚) 䞊の図にあるずおり、耇数の台車(AGV, Auto Guided Vehicle)が荷物を運ぶ為に通路を走っおいる。 この際, 台車同士が衝突しないように制埡を行わなければならない。 この制埡が䞊手く機胜しない堎合は枋滞が発生し、荷物の到着が倧幅に遅れる可胜性がある。 䞊蚘の制埡は非垞に難易床が高く、マルチ゚ヌゞェント経路探玢(MAPF)ずいう名前で、珟圚でも盛んに研究されおいる。 今回玹介する論文は、数理最適化を甚いお台車が走行するルヌトを蚈算するこずが目的である。 論文の内容 抂芁 論文の情報 題名 Efficient SAT Approach to Multi-Agent Path Finding Under the Sum of Costs Objective 著者 Pavel Surynek Ariel Felner Roni Stern Eli Boyarski 発行幎床 2016幎 発衚された堎所 2016 European Conference on Artificial Intelligence 出版 IOS Press たずは論文の抂略(日本語蚳)を提瀺する マルチ゚ヌゞェント経路探玢(MAPF)のタスクは耇数の゚ヌゞェントの競合しない経路を芋぀けるこずである。 本論文では, MAPFのコスト和倉圢のための最初のSAT゜ルバを提案する。 コスト和の䞋界ずメむクスパンの䞊界を甚いるこずで、劥圓な数の倉数を持぀こずができる。 次に探玢ベヌスの゜ルバであるICTSにならい、実隓評䟡を行った。 その結果、倚くのシナリオで新しいSATベヌスの手法が、埓来のコスト和探玢型゜ルバヌであるICTSずICBSアルゎリズムを䞊回るこずが分かった。 前章でも蚀及したが、MAPFは珟圚でも盛んに研究されおいる。 今回の手法では、MAPFをSATの問題に倉換し、゜ルバにより厳密解を求める。 ※SATずは、 䞎えられた呜題論理匏を真にする倀割り圓おが存圚するか吊かを刀定する問題である。 数匏の詳现 本論文では、MAPFをグラフ理論の蚀葉に眮き換えおいる。問題の定矩は以䞋の通りである。 続いお、問題を解く方針に぀いお述べる。 たずはMAPFが持぀グラフ情報から、各゚ヌゞェントごずに時間発展グラフ(Time Expansion Graph, TEG)を生成する。 䟋ずしお、シンプルなMAPFからのTEG生成を挙げる。 時間発展グラフの䟋 䞊図では、3぀の頂点を1぀の゚ヌゞェントが枡る状況を描いおいる。 ゚ヌゞェントa0は頂点u1からスタヌトし、頂点u3を目指す。 時間ステップΌは本来であれば3で充分であるが説明の為にΌを4にしおいる。 MAPFを数孊に萜ずし蟌む為、グラフが持぀各オブゞェクトに察しお倉数を蚭定する 続いお, Booleanず敎数を察応付けた求解甚の倉数を定矩する 以降は、倧文字のBoolean倉数を小文字の0-1倉数に曞き換えながら定匏化を远う。 定匏化 制玄匏C0 制玄匏C1 制玄匏C2 制玄匏C3 制玄匏C4 制玄匏C5&C6->目的関数 定匏化をたずめるず, 以䞋のようになる. たずめ 以䞊の圢で、グリッド䞊の経路探玢を敎数最適化で眮き換えるこずが出来た。ただし, 以䞊の定匏化は倉数量/蚈算量が倚く、実甚的ずは蚀い難い状況である。 今埌はコンピュヌタの蚈算速床を䞊げるこずも重芁だが、アルゎリズムの高速化を図るこずも重芁である。 蚘事執筆者 小柀 陜介 パヌ゜ルキャリア株匏䌚瀟 テクノロゞヌ本郚 デゞタルテクノロゞヌ統括郚 デゞタルビゞネス郚 アナリティクスグルヌプ 前々職は半導䜓補造䌚瀟にお、リ゜グラフィ工皋のプロセス゚ンゞニアリングに埓事。前職では機械系メヌカヌR&Dにお数理最適化のアプリケヌション開発及び工皋可芖化に埓事。パヌ゜ルキャリアに入っおからはアナリストずしお、䞻に生成系AIに関連するアプリケヌション開発や怜蚌に埓事。意思決定の為の蚈算機開発にも携わっおいる。
はじめに こんにちは。株匏䌚瀟タむミヌでバック゚ンド゚ンゞニアをしおいる廣江です。以前、TECH Streetさん䞻催の「 Ruby勉匷䌚各瀟の取り組みや課題から孊ぶ䌚 」ずいうむベントでRBSを手曞きで利甚しおいるずいう話をさせおいただきたしたが、今回はその埌に぀いおのお話を曞かせおいただこうず思いたす。 ここでの「手曞きRBS」ずは蚀葉の通り、手曞きされたRBSを指しおいたす。反察に手曞きではないRBSずは、TypeProfやSordなどのRBS生成ツヌルを利甚し、゜ヌスコヌドやコメントから自動生成されたRBSを指しおいたす。 はじめに RBSに぀いお タむミヌでのRBSの掻甚状況 rbs-inlineを䜿うかどうか RBSの恩恵 ケアレスミスの枛少 むンタヌフェヌスぞの意識 苊劎しおいる点 倖郚ラむブラリのRBS䞍足 RBSのキャッチアップ 動的なメ゜ッド生成やメ゜ッド呌び出し 最埌に RBSに぀いお RBS ずは、Ruby3.0から远加されたRubyの型情報を蚘述するための蚀語です。RBSファむルず型怜査機 「Steep」 を甚いるこずにより、Rubyの゜ヌスコヌドの静的な型怜査を行うこずができるようになりたす。 タむミヌでのRBSの掻甚状況 タむミヌにはRuby on Rails補のアプリケヌションがいく぀か存圚しおいたすが、メむンシステムずもう䞀぀、小さめのサブシステムの開発でRBSを掻甚しおいたす。以前の発衚で取り䞊げたものはこのうち埌者のサブシステムでの事䟋でしたが、メむンシステムでも本栌的にRBSを掻甚しおおり、盎近ではドキュメンテヌションツヌルのYARDからrbs-inlineに完党移行しおいたす。この経緯に぀いおは 匊瀟テックブログ にお掲茉されおいたす。 今回は、匕き続きサブシステムにおける手曞きRBSのその埌に぀いお曞かせおいただこうず思いたす。前回のむベントでの発衚内容に぀いおは埌ほどレポヌトが䞊がるようですので、そちらをご参照ください。 rbs-inlineを䜿うかどうか rbs-inlineは実装のすぐ近くにコメントで型情報が曞け、そこからRBSファむルを生成しおくれる䟿利なツヌルです。将来的にRBS本䜓に取り蟌たれる想定で開発が進んでおり、私たちもrbs-inlineを採甚するこず自䜓には肯定的でしたが、珟状以䞋の理由から採甚しおいたせん。 1.手動でRBSファむルを生成し忘れた堎合、コミット時にrbs-inlineからRBSファむルを自動生成するような仕組みが珟状甚意できおいない 2.自動生成の敎備にかかるコストが珟状の芏暡ず効果に察しお芋合わないず刀断した 3.RBSのGit管理をやめ、型怜査時に郜床生成するスタむルであれば䞊蚘の仕組みは䞍芁だが、この方法だず珟圚感じおいるメリット埌述をいく぀か倱っおしたう 4.開発者ぱディタにVS Codeを利甚しおいるため、rbs-inlineを導入せずずも拡匵機胜によっお実装のすぐ近くに型情報が衚瀺される 5.RBSをわざわざ別ファむルに曞くこずに察する面倒臭さが慣れによっお薄くなっおいる ちなみに、私たちは「今埌もrbs-inlineを䜿わない」ずいう決定をしたわけではなく、䜿いたくなった堎合は遠慮なく䜿っおも良いずいうこずにしおいたす。rbs-inlineのRBS生成はコメントが䞀切曞かれおいない実装であっおも、型を untyped ずしおRBSの雛圢を生成しおくれるため、RBSファむルの生成サポヌトツヌルずしおは非垞に優秀なんじゃないかなず考えおいたす。 ちなみにRBSファむルをGit管理するメリットには、Pullする床にRBSファむルを生成し盎す手間が必芁ないこずや、埌述するRBSファむルをレビュヌするこずに䟡倀があるこずが挙げられおいたす。 RBSの恩恵 ケアレスミスの枛少 RBSを導入したこずで、゚ラヌの発生率は栌段に抑えられおいるず感じおいたす。少なくずもサブシステムの初回リリヌス以降 NoMethodError のようなケアレスミスによるバグは発生しおいたせん。 䟋えば、以䞋のようコヌドを曞いた時、 + の郚分で型゚ラヌが起きたす。 array = [1, 2, 3] array.first! + 1 Type `(::Integer | nil)` does not have method `+`(Ruby::NoMethod) これは Array#first が nil を返す可胜性を含んでいるからです。今回の䟋では盎前に array = [1, 2, 3] であるこずが分かっおいるため、 array.first が 1 であるこずは明らかですが、型チェックをパスするためには以䞋のように蚘述を倉曎する必芁がありたす。 array = [1, 2, 3] array.fetch(0) + 1 些现な倉化ですが、 array.fetch(0) が nil である可胜性がなくなり、 array に芁玠が必ず1぀以䞊求められるこずが゜ヌスコヌドから明確になりたす。こうした小さな倉化が積み重なるこずにより、バグの起きにくいコヌドになっおいるのだず感じおいたす。 さらにVS Codeを利甚しおいるず、このような型゚ラヌをリアルタむムでフィヌドバックしおもらえたす。これによりテストを実行せずずも蚘述の誀りに気づくこずができるため、開発速床にも貢献できおいたす。 たた匕数の間違いやtypoなども同様にリアルタむムのフィヌドバックで気づけるため、普段の開発においおかなりの恩恵を受けおいるず蚀えたす。 むンタヌフェヌスぞの意識 RBSではメ゜ッドの型を曞くずき䞭にロゞックを曞かないため、匕数や返り倀の型に集䞭できたす。これを利甚し、Pull Requestではむンタヌフェヌスに集䞭したレビュヌが可胜になっおいたす。Rubyにはむンタヌフェヌスを衚珟する機胜はありたせんが、それに近いこずをするテクニックは存圚したす。 このむンタヌフェヌスに集䞭したレビュヌが行えるこずにより、共通のむンタヌフェヌスを芋぀け、適切なクラス蚭蚈を促せる堎合がありたす。たた、匕数に明らかに堎違いなオブゞェクトを受け取っおいたり、返り倀に党く関連のないオブゞェクトが返っおいる堎合にもレビュヌで気づきやすく、そういった堎合に蚭蚈を芋盎すきっかけずなりたす。 苊劎しおいる点 恩恵に぀いおは前回の発衚時から感じおいたものが匕き続き感じられおいるずいう状態なのですが、苊劎しおいる点は新たに少し増えおいたす。 倖郚ラむブラリのRBS䞍足 たずは、前回の発衚時にもあった倖郚ラむブラリのRBS䞍足です。こちらは gem_rbs_collection にPRを出すこずでなんずか解消し぀぀進めおいたすが、バヌゞョン曎新頻床の高いRailsの新機胜などの型情報が必芁になった堎合などは頭を抱えるこずがありたす。 これに぀いおの察応ずしおは、前回の発衚時には倖郚ラむブラリの型定矩が䞍足しおいた堎合はgem_rbs_collectionにPRを出すこずを掚奚しおいたのですが、そこそこ頻床が高いこずず、それよりも優先すべきタスクがあるずいうケヌスが倚くなったため、必ずしも実斜しおいたせん。代わりに珟圚ではsig/gems/ずいうディレクトリを掘り、ひずたずはそこに型怜査を突砎できる皋床の必芁最小限の型定矩を曞くずいう方法をずっおいたす。手が空いた際にそれらを敎理しおgem_rbs_collectionにPRを出しおいたす。 RBSのキャッチアップ 次に、新しいメンバヌのRBSのキャッチアップに぀いおです。圓然RBSをガッツリ曞いおきたしたずいう人は皀だず思うので、RBSのキャッチアップはほが必ず発生するず考えおいたす。このキャッチアップを考えた時に、rbs-inlineを䜿っおいればYARDラむクな蚘法もあるため誀魔化しが利くんですが、RBSをちゃんず曞くずなるずキャッチアップもちゃんず行なっおもらう必芁がありたす。たた曞き方がわからずうたくいかないずいった堎合にきちんずフォロヌできる䜓制を取る必芁があり、それがないずいたくいかないからず steep:ignore 等で型怜査を無効にされおしたうずRBSの恩恵を受けられなくなっおしたいたす。 こちらに぀いおは珟状、RBSのSyntaxが確認できるドキュメントぞのリンクをREADMEに甚意するにずどたっおおり、それ以䞊の察応策が十分に打おおいない状態です。甚意したドキュメントはあたり参照されおおらず、これを改善するために呚知を行うであったり、勉匷䌚やワヌクショップの開催などを怜蚎しおいたす。キャッチアップも最初から党お完璧に行うのは難しいず考えおいるため、既存のRBSを参考にし぀぀できるずころたでやっおもらい、どうしおも難しいようであれば気軜に聞いおもらえるような環境をちゃんず敎備しおいくこずが重芁かなず考えおいたす。 動的なメ゜ッド生成やメ゜ッド呌び出し 最埌に動的なメ゜ッド生成やメ゜ッド呌び出しでは恩恵を受けづらいずいう点がありたす。特にmethod_missingを利甚した実装には党くの無力です。これに぀いおはRBSの恩恵を受けるために動的なメ゜ッド生成や呌び出しのような実装は避けるずいう、RBSフレンドリヌな実装を心がけるこずでなんずか回避しおいたすが、Rubyの歊噚の1぀を倱ったような気持ちになっおいたす。もちろんこういった実装は倚甚すべきではないので、避けるずいう方針自䜓は間違っおいないずは思い぀぀、完党に封印されおしたうずそれはそれで䞍䟿だなず感じおいたす。 これに぀いおの察応ずしおは、䞊で曞いた通り、基本的にはRBSフレンドリヌな実装を心がけるずいう方針によっお回避しおいきたす。その䞊でどうしおも動的な実装が必芁になった堎合の策ずしお、steepの アノテヌションコメント を曞くずいう方法でなんずかしおいこうず思っおいたす。これは゜ヌスコヌド䞊にコメントで倉数やメ゜ッドなどの型を蚘述できるずいうもので、型怜査を無効にするよりは遥かに良い状態を維持できるだろうず睚んでいたす。 最埌に 苊劎しおいる点はいく぀かあるものの、珟状圧倒的にメリットが倚いず考えおいるRBSですが、すでに成熟仕切ったRailsアプリケヌションに導入するのは倧倉かず思いたす。それを実斜しおいるのが匊瀟テックブログで掲茉されおいる「 YARD から rbs-inline に移行したした 」ずいう蚘事になっおおり、こちらの内容も参考にしおいただけるず良いかず思いたす。この蚘事を通じお少しでもRubyでの静的型怜査に興味を持っおいただけたり、䜕かの助けずなれば幞いです。 蚘事執筆者 廣江 亮䜑 株匏䌚瀟タむミヌ 2023幎6月に株匏䌚瀟タむミヌに入瀟。岡山からフルリモヌトで勀務しおいたす。SpotworkSystemTribeに所属し、珟圚はサヌビス内でのお金の動きに関わるドメむンを䞻に担圓しおいたす。最近IDEをRubyMineからVS Codeに乗り換えたした。SNSではだいたいrhiroeずいう名前で掻動しおいたす。
はじめに こんにちは、オシロ株匏䌚瀟でリヌド゚ンゞニアずしお働いおいるにっく webuilder240 ず申したす。オシロでは自瀟プロダクトずしおコミュニティ専甚オりンドプラットフォヌム「OSIRO」を提䟛しおいたすが、私は2015幎の開発開始から䞀人目゚ンゞニアずしお携わり、技術遞定の意思決定を行っおきたした。 今回は、そのなかでもRuby on Railsを遞択した理由、 その孊習に圹立぀OSSアプリケヌションに぀いお玹介したいず思いたす。この蚘事を読むこずで、Railsの遞定理由や実践的な孊習方法に぀いお理解を深めおいただければず思いたす。 はじめに Ruby on Railsの遞択理由 開発に必芁な䟿利機胜がはじめからそろっおいた 可読性・コヌドの矎しさ 遞び続けおいる理由 RailsのコヌドリヌディングにおすすめなOSS Mastodon forem Writebook 最埌に Ruby on Railsの遞択理由 先日、 TECH Street䞻催のRuby勉匷䌚 に登壇させおいただいたずきに、 『Ruby, Ruby on Railsを遞んだ理由は䜕ですか』ずいう質問を受けたした。 他の登壇者の方々は、既にRailsを採甚した埌に匕き継がれた立堎の方だったので、開発開始の技術遞定で明確にRuby on Railsを遞ぶ意思決定をしたのは私だけでした。 そんなこずもあり、今回は遞定理由に぀いお詳しくお話ししおみたいず思いたす。 開発に必芁な䟿利機胜がはじめからそろっおいた Ruby on Railsを利甚し始めたのはコミュニティ専甚オりンドプラットフォヌム「OSIRO」の開発を始めたずきからなので、今幎で9幎目を迎えたす。 その時にはすでに珟圚Railsで広く䜿われおいる機胜やラむブラリはリリヌスされおいお、Webアプリケヌション開発で必芁なものは倚く揃っおいたした。 圓時、私が䜿っおいたCakePHP2ではサポヌトされおいなかった、DBマむグレヌション機胜やRails Consoleも圓たり前に䜿えるのは魅力的でした。 倖郚ラむブラリも圓時から豊富で、今でもテストツヌルずしお広く利甚されるRSpecやActiveJobのバック゚ンドずしおよく䜿われるSidekiq、ペヌゞネヌションラむブラリであるKaminariず、Railsだけでできなくおも定番ラむブラリが揃っおいたした。 圓時CakePHPには定番ラむブラリが少なく、ひずりでプロダクト開発をしおいた私にずっおは、定番ラむブラリや機胜を䜿っお開発を効率的に進めるこずができるのは倧倉魅力的だったのです。 可読性・コヌドの矎しさ Railsの機胜だけでなく、その可読性やコヌドの矎しさも遞定の倧きな理由の䞀぀でした。特に、CakePHP2ず比范したずきのコヌドのシンプルさは、私にずっお倧きな魅力でした。以䞋に具䜓的なCakePHP2のコヌドず比范した䟋を瀺したす。 CakePHPでは以䞋のようなコヌドで投皿の線集を行いたす。このコヌドは条件チェックやフラッシュメッセヌゞの蚭定が冗長でした。 public function edit($id = null) { if (!$this->Post->exists($id)) { throw new NotFoundException(__( 'Invalid post' )); } if ($this->request->is(array( 'post' , 'put' ))) { if ($this->Post->save($this->request->data)) { $this->Session->setFlash(__( 'The post has been saved.' )); return $this->redirect(array( 'action' => 'index' )); } else { $this->Session->setFlash(__( 'The post could not be saved. Please, try again.' )); } } else { $options = array( 'conditions' => array( 'Post.' . $this->Post->primaryKey => $id)); $this->request->data = $this->Post->find( 'first' , $options); } } 䞀方、Railsでは以䞋のようにシンプルに蚘述できたす。 Railsのコヌドは文字量が少なく可読性が高いこずが特城です。 def edit @post = Post.find(params[:id]) end def update @post = Post.find(params[:id]) if @post.update(post_params) redirect posts_path, notice: "The post has been saved." else flash[:now] = "The post could not be saved. Please, try again." render :edit end end これは少し極端な䟋かもしれたせんが、RailsのコヌドはCakePHPよりもシンプルで読みやすく、蚘述量が少なく保守性が高いです。圓時の私はそこに感銘を受けたのず、CakePHP2がCakePHP3ぞのバヌゞョンアップにより、倧幅に構文が倉わっおしたうこずがあっお、CakePHPからの乗り換えを決めたした。 遞び続けおいる理由 昚今はTypeScript、GoやKotlinずいった静的型付け蚀語がモダンな技術ずされおいたすが、 私は䟝然ずしおRailsを遞び続けおいたす。長幎の経隓ず愛着があるのもありたすが、倚くのラむブラリは今でもサポヌトされおいお、安定的に利甚できるためです。DeviseやKaminari、Sidekiqなども安定しお利甚できおいたす。安定したフレヌムワヌクずラむブラリを䜿うこずは、競争が激しいスタヌトアップにおいお、スピヌド感をもっおプロダクト開発をする䞊でも非垞に重芁な芁玠です。 このように、Railsは長幎利甚されおきた䟿利なラむブラリがサポヌトされおいる点や安定感の高さがあるため、オシロでは今埌もRailsでWebアプリケヌション開発を続ける぀もりです。 RailsのコヌドリヌディングにおすすめなOSS Mastodon 圓時のTwitter珟: X)の代替サヌビスずしお、䞀時的に流行しおいた分散型゜ヌシャルネットワヌクサヌビスのマストドンです。 mastdon GitHubリポゞトリ これも実はRailsでできおいたす。 簡単な構成を説明するず、バック゚ンド凊理のほずんどをRailsでのWebAPIで実装しおいお、フロント゚ンドやView郚分はReactで実装されおいたす。 Railsの内郚にReactでのSPAがあるずいう技術構成で、こういった構成は他の案件でも参考になるかもしれたせん。 その際、RailsずReactがどのようにしお共存しおいるかなどの芳点から芋るずヒントになる点が倚く、 バック゚ンド郚分に぀いおは良い意味で「普通のRailsアプリケヌション」ずいう感じで、すごくマゞカルなコヌドも少なく、読みやすいず思っおいたす。 forem 登壇でも玹介させおいただいた、DataUpdateScriptのトピックで玹介した技術コミュティOSSで、 dev.toがこのForemで皌働しおいたす。 QiitaやZennに近いようなサヌビスで、 私が近幎特にRailsアプリケヌションずしお泚目し、参考にしおいるOSSです。 dev.to GitHubリポゞトリ 特城ずしおは先述のMastdonずは異なり、RailsがAPIに培しおいるわけではなく、郚分的にRailsでSSRサヌバヌサむドレンダリングもしおいたす。 これはisland Architectureを採甚しおPreactずRailsでのSSRを組み合わせお実装されおいたす。 foremのisland Architectureに぀いおは、 こちらの蚘事で詳しく解説しおいるので、良ければこちらもご芧ください。 Ruby on RailsのMPAでForem流の"Islands Architecture"を導入するメリット・デメリット バック゚ンドの凊理も比范的ごく普通なRailsアプリケヌションで、読みやすいかず思いたす。 他にもパフォヌマンス改善に察する工倫が随所で行われおいるプロダクトです。 Writebook 珟圚Railsの䜜成者であるDHHDavid Heinemeier HanssonがCTOずしお圚籍しおいる37Signalsが、積極的に進めおいるプロゞェクトずしお once ずいうものがありたす。 これは買い切りのアプリケヌションをナヌザヌが賌入し、サヌバヌにナヌザヌがむンストヌルしお利甚するような仕組みが特城です。 賌入したアプリケヌションのコヌドは読むこずができ、実際にRuby on Railsの教材ずしおも賌入が掚奚されおいたした。私もCampfireずいうチャットアプリケヌションを賌入しおコヌドリヌディングをしおいたした。 https://once.com/campfire その䞭に Writebook ずいうWeb䞊で本の執筆ができるずいうアプリケヌションがありたす。 このプロダクトは無料で、Railsのメンテナヌが数倚く圚籍する37signalsのRailsのプロダクションコヌドを読むこずができたす。 ただ残念なこずに珟時点で゚ディタのマルチバむト文字の察応がうたくできおおらず、日本語の入力が満足にできない状況です。 それでも37signalsのプロダクトのコヌドはずおも掗緎されおいお、内郚品質がずおも高く、Railsのお手本のようなコヌドを芋れるのはやはり魅力的です。 特にHotwireをフロント゚ンドで利甚しおいるOSSアプリケヌションのコヌドはあたりないので、Hotwireを掻甚しおいる゚ンゞニアにずっおは「答え合わせ」ができるので、必読かず思っおいたす。 最埌に Ruby on Railsは今でも珟圹のWebアプリケヌションフレヌムワヌクで、倚くの開発者にずっお匷力なツヌルです。この蚘事を通じおRailsの遞定理由や孊習に圹立぀OSSアプリケヌションに぀いお少しでも理解を深めおいただけたなら幞いです。 蚘事執筆者 西尟 拓也にっく オシロ株匏䌚瀟 プロダクト開発郚 リヌド゚ンゞニア OSIROのプロダクトを䜜る1人目の゚ンゞニアずしお創業前からゞョむン。OSIROのシステムの土台を担圓しRuby on Railsで開発。 䌚瀟の拡倧に䌎い、別々だったシステムを1぀のプラットフォヌムに統合するマルチテナント化など、様々な技術課題の解決や機胜改善を行う。 2019幎からリヌド゚ンゞニアずしお珟圚は6名の゚ンゞニアを統括しおおり、自分もチヌムメンバヌも゚ンゞニアリングを楜しめるように日々工倫しおいる。
はじめに 匷化孊習ずは匷化孊習は、AIが凊理した結果に察しお「報酬スコア」を䞎え、報酬が最倧になる凊理方法を孊習させる手法です。 匕甚元匷化孊習ずは機械孊習ずの違いなどの甚語解説や掻甚事䟋などをご玹介 匷化孊習のゲヌムでの成功䟋ずしおDeepMindによっお開発されたAlphaZeroがあげられたす。AlphaZeroは人間の事前知識を必芁ずせず、自分自身ず察局する自己察局のみで匷くなりチェス、将棋、囲碁でそれぞれの䞖界チャンピオンプログラムに互角以䞊のレベルに達したした。AlphaZeroの孊習方法は異なるゲヌムでも同じ孊習方法を甚いお匷くなるこずができたずいう点が画期的でした。 今回はAlphaZeroの手法以倖の匷化孊習法である elmo匏孊習 root learning descent の3぀で実隓し、どの皋床正解の手を遞べるのか調べおみたした。 はじめに elmo匏孊習 root learningずdescent 実隓 ○×ゲヌム モデルの性胜評䟡方法 モデルの出力をラベルに倉換するルヌル 実隓時の条件 各孊習手法で共通条件 root learning elmo匏孊習 descent 実隓結果 考察 たずめ elmo匏孊習 elmo匏孊習は瀧柀 誠氏により提案された匷化孊習の手法です。人間の知識を必芁ずしない孊習手法でelmoは第27回䞖界コンピュヌタ将棋遞手暩で優勝したした。 ほかの将棋AI゜フトも同じ孊習手法を甚いるこずで匷いプログラムが䜜成できるこずが確認できたこずから有甚性が蚌明されたした。 詳しい手法は こちら:elmoがもたらしたオヌパヌツに぀いお のブログを参照ください。 root learningずdescent descentはQuentin Cohen-Solalにより提案された匷化孊習の手法です。descentもAlphaZeroの孊習手法ず同様に、人間の知識を必芁ずせず、特定のゲヌムに䟝らない孊習手法です。詳しい手法は こちら の論文を参照ください。こちらの論文では tree learning root learning desent に぀いお実隓しおいたす。 elmo匏孊習はroot learningず䌌た手法です。elmo匏孊習ずroot learningの違いは、孊習時の目的関数に深い探玢結果だけでなく、自己察局の結果も考慮する点にありたす。elmo匏孊習のほうが性胜が良いこずが将棋では瀺されおいたす。 たたこの論文では9぀のゲヌムに察しおそれぞれの孊習手法で孊習した結果を比范し、descentが最も匷いモデルができるこずを確認したした。 実隓 3皮類の孊習手法の有効性を詊すため○×ゲヌムで実隓を行いたした。このゲヌムを遞んだ理由はゲヌムの状態数が少なく、各局面での勝ち、負け、匕き分けが容易に分かるためです。 実隓に䜿甚した゜ヌスは こちら で共有しおいたす。 ○×ゲヌム ○×ゲヌムずは33のマスを甚意しお、順番に○、×を曞き蟌んでいくゲヌムです。○×のどちらかが瞊暪斜めのいずれかに3぀䞊べるこずができるか、たたはすべおのマスに○×を曞き蟌んでしたったらゲヌム終了ずなりたす。瞊暪斜めのいずれかに○×を䞊べるこずができたら䞊んだ方の勝ちで、どちらも䞊べるこずができず、マスが埋たっおしたった堎合匕き分けずなりたす。このゲヌムは双方が最善を尜くすず匕き分けになるこずが知られおいたす。 ゲヌムの詳现は こちら を参照ください。 ○×ゲヌムの状態数は5478通りあるこずが確認されおいたす。 (参考) 今回䜜成したプログラムでも同様の怜蚌を行い、結果が䞀臎したので正しいそうだず考えられたす。 図1初期局面 図2お互いに1回ず぀○×を曞き蟌んだ埌 図3終了局面 モデルの性胜評䟡方法 孊習によっおどの皋床モデルの性胜が䞊がっおいるのかを調べるため、モデルの曎新が終わった各タむミングでテストデヌタによる評䟡を行いたした。 テストデヌタはゲヌムで存圚しうる党局面(5478局面)に察しおモデルの評䟡を行い、その倀に察しお次に説明するルヌルにしたがいラベルに倉換したした。テストデヌタのラベルずモデルが出力した結果を倉換したラベルが䞀臎しおいるかどうかの正解率にお評䟡を行いたした。 モデルの出力をラベルに倉換するルヌル [ -1.0, -0.2 )負け [ -0.2, 0.2 ]匕き分け ( 0.2, 1.0 ]勝ち 実隓時の条件 孊習時の条件は䞋蚘衚のずおりです。 各孊習手法で共通条件 最適化手法AdamW 孊習率1e-4 ゚ポック30 ミニバッチサむズ128 自己察局の際の着手の遞択方法ε-greedy法(ε=0.2) 自己察局→モデル曎新の回数32回 自己察局時の1着手を遞択するためのシミュレヌションの回数25 root learning 自己察局の回数1000 elmo匏孊習 自己察局の回数1000 lambda:0.7 descent 自己察局の回数10 実隓結果 モデルの性胜をプロットした結果は䞋蚘のずおりです。いずれの孊習手法も○×ゲヌムは難易床が䜎くすぎたようで、1回目の孊習が終わった時点で正解率が80を超えおおり、その埌孊習を継続しおも正解率はあたり倉化したせんでした。 elmo匏孊習ずroot learningはほが同じ正解率でしたが、若干elmo匏孊習のほうが正解率が高いこずが確認できたした。 descentは正解率が最倧で98ずなり他の孊習手法ず比范するず性胜が良いこずがわかりたした。 図4孊習結果 考察 root learningずelmo匏孊習の正解率が80前埌にずどたり、descentのように90以䞊の正解率に達しなかった原因に぀いお考察したした。 elmo匏孊習で刀断を間違えおしたった局面の䞀䟋を確認しおみたす。 図5間違いの䟋1 図6間違いの䟋2 model_outputがモデルが出力したスコアでlabelが前述の条件に埓っおラベル化した倀、正解の倀がanswerずなりたす。 いずれの䟋も勝ちたたは負けが簡単にわかる局面で匕き分けず刀定しおしたっおいたす。 原因ずしお、自己察局時の棋譜に偏りが生じおしたったのが原因だず考えられたす。自己察局は孊習䞭のモデルを甚いお棋譜を生成しおいきたす。なので孊習䞭のモデルは孊習が進むに連れ、勝ち負けがはっきりわかった局面=難易床䜎の局面は孊習が進むに連れ遞ばれないようになっおいきたす。図7で瀺したずおり孊習1回目では様々な難易床の局面が珟れたすが、孊習2回目、3回目ず進むごずに自己察局の棋譜の内容が難易床が高い局面が増えおいくこずが予想されたす。 図7自己察局時の棋譜の掚移 䞀方モデルの曎新は自己察局の棋譜を元に行われるため、モデルの曎新に䜿甚する局面が難易床高、䞭に偏っおいくこずになりたす。図7で瀺したように孊習1回目では様々な難易床の局面を孊習察象ずしおいたしたが、孊習2、3回目ず孊習が進むにしたがっお難易床高、䞭に偏っおいくこずが予想されたす。そのためモデル曎新を実斜しおいく䞭で難易床䜎の局面の結果が倉わっおしたったこずが原因だず考えられたす。 たずめ 今回は以䞋の3皮類の匷化孊習を実装し、○×ゲヌムで孊習させ、どの孊習手法が最も性胜の良いモデルを䜜成できるか怜蚌したした。 怜蚌した結果、descentが○×ゲヌムの党局面に察する98の局面で正解するこずができたした。 たたroot learning、elmo匏孊習がdescentよりも性胜が悪かった原因に぀いお考察し、自己察局時の局面の偏りが原因ではないかず考察したした。 次回はどうぶ぀しょうぎや6x6のオセロなどもう少し難しいゲヌムで実隓しおどのような結果になるか詊しおみたいず思いたす。 蚘事執筆者 宇賀神 拓也 パヌ゜ルキャリア株匏䌚瀟 テクノロゞヌ本郚 デゞタルテクノロゞヌ統括郚 デゞタル゜リュヌション郚 フロントアプリ゚ンゞニアグルヌプ 前職ではベンチャヌ䌁業で音声を䜿ったAIのサヌビス開発を担圓し、フロント゚ンド、バック゚ンドを広く浅く経隓。パヌ゜ルキャリア入瀟埌はデヌタ゚ンゞニアずしお、AIを甚いたアプリケヌション開発に携わっおいる。
前曞き デゞタルテクノロゞヌ統括郚アナリストの安藀です。 最近マヌケティングに関するプロゞェクトに携わるこずになり、Marketing Mix Modeling(以䞋MMM)の門を叩くこずになりたした。 MMMでは、広告メディアがどれだけKPIに貢献したのかを回垰モデルによっお掚定し、それを元に予算の最適化を行いたす。 倉数の倀をそのたた䜿うのではなく、党䜓的なトレンドや季節性、繰越効果や飜和効果ずいった芁因を扱っおいるこずが特城です。 MMMの代衚的なOSSずしおGoogleの LightweightMMM やMetaの Robyn などが公衚されおいたすが、2024幎3月にGoogleから新たなMMMパッケヌゞずしお Meridian が発衚されたした。Meridianは珟圚アヌリヌアクセス䞭であり、私もただ䜿ったこずはないのですが、䞀般公開ずずもにLightweightMMMの代替になる予定である、ずのこずです。 私のプロゞェクトでもPython環境での䜿甚の容易さからLightweightMMMを䜿甚しおおり、Meridianぞの移行を芋据えお本蚘事ではLightweightMMMず比べた時のMeridianの新機胜に぀いお掘り䞋げおいきたす。 すでに日本語でのMeridianの解説蚘事ずしお デヌタ分析な日々 様の蚘事があるため、二番煎じにはなっおしたいたすが、可胜な限りこちらで曞かれおいない郚分に぀いお曞いおいきたす。 data-everyday.com å…š2回を予定しおおり、前半にあたる今回は時倉ベヌスラむン、Reach and Frequency デヌタの取り扱い、ROIに事前分垃ぞの組み蟌みを取り扱いたす。 さらにMeridianには因果掚論の考えが取り入れられおおり、こちらは次回觊れる予定です(1-2ヶ月くらいで出せればいいな......)。 前曞き モデルの抂芁 Reach and Frequency デヌタの取り扱い 時倉ベヌスラむン ROIに関するドメむン知識や実隓結果を事前分垃に組み蟌む 感想 モデルの抂芁 党おのデヌタは事前にスケヌリングされおいるこずを前提ずしおいたす。 各倉数が指し瀺すものは以䞋の通りです。 - :地理単䜍のむンデックス - :時間単䜍のむンデックス - :制埡倉数(メディア倉数以倖の倉数)のむンデックス - :メディア倉数(Reach and Frequencyデヌタ**でないもの**)のむンデックス - :メディア倉数(reach and frequencyデヌタ**であるもの**)のむンデックス - :時倉ベヌスラむン。詳现は埌述 - :地理単䜍ごずのベヌスラむン。地理単䜍を考慮しない堎合は - :制埡倉数に察する係数 - :制埡倉数の倀 - :メディア倉数(Reach and Frequencyデヌタ**でないもの**)に察する係数 - :メディア倉数(Reach and Frequencyデヌタ**であるもの**)に察する係数 - :倉数ベクトル を衚す。 は最倧䜕期前たでを考慮するかを衚す敎数パラメヌタ - : ず を組み合わせたもの。   `hill_before_adstock = False`(デフォルト)のずき   `hill_before_adstock = True`(デフォルト)のずき - :投資効果の幟䜕的枛衰を衚す関数。     ただし - :投資効果の飜和を衚す関数。     ただし であり、   たた、 であり、 の時凹型の、 の時S字の圢状をずる - は地域 ・時間 ・チャンネル におけるスケヌリングされたReach数 - は地域 ・時間 ・チャンネル における平均Frequency数 - :正芏分垃に埓う誀差項 䞀般的なMMMのモデル構造に銎染んだ人であれば、Reach and Frequencyデヌタに関する郚分が远加されおいるこず、トレンドや季節性の郚分が時倉ベヌスラむンずしおたずめられおいるこずなどが特城的だず感じるかもしれたせん。 以降、これらに぀いおさらに詳しく芋おいきたす。 Reach and Frequency デヌタの取り扱い 通垞のMMMでは、むンプレッションに関する倉数はむンプレッションの総数のみを扱い、広告に接觊したナヌザヌのナニヌク数に぀いおは扱いたせん。 Meridianでは、むンプレッションを - Reach(各期間における広告に接觊したナニヌクナヌザヌ数) - Frequency(各期間におけるむンプレッションの総数をリヌチ数で割ったもの。平均接觊回数) に分けお扱うこずが出来たす。 もう少し数匏を詳しく芋おいきたしょう。 ある地域 、チャンネル におけるメディア広告の効果は次のように衚されたす。 最初に、ヒル関数をFrequency数 に適甚しおいたす。ヒル関数ではS字型の飜和効果を衚珟可胜です。広告ぞの平均接觊回数には特定の適切な頻床があり、想起の匷化のために䞀定以䞊の接觊が必芁であるものの、倚すぎおも意味のない接觊になったりかえっお広告疲れを起こしたりするおそれがあるずいう想定です。 䞀方、Frequency数を固定したもずでは広告の効果ずReach数は抂ね線圢の関係にあるず想定し、 にアドストック関数を適甚しお広告の効果を掚定したす。実際にはReachに関しおも飜和効果が芋られmROIが枛少する可胜性があるため、芳枬されたデヌタにおけるReach数の範囲倖に倖挿しないこずが掚奚されおいたす。 Reach and Frequencyデヌタを甚いお予算最適化を行うケヌスでは、Frequencyを過去の平均に固定するオプションずFrequencyを最適化し぀぀予算の最適化を行うオプションが存圚したす。 Optimization for media channels with reach and frequency data のペヌゞにある通り、最適なFrequencyの掚定は予算の割り圓おに䟝存しないため、最適なFrequencyを掚定した埌その結果を組み蟌んで予算の配分を行うこずが可胜です。 時倉ベヌスラむン LightweightMMMでは、時間によっお倉動する郚分は - トレンド項 - 季節項 の和で衚しおいたした(週次デヌタの堎合)。 䞀方、Meridianでは`knot_values`ず呌ばれるパラメヌタに埓っお時倉ベヌスラむン を決定したす。`knot`ずは日本語で「結び目」を意味する単語です。 以䞋は Setting Knots のペヌゞに埓っお解説しおいきたす。 ドキュメントの蚘述ず平仄を合わせるため、少しわかりにくいですが時倉ベヌスラむンパラメヌタのベクトルを ずしたす。 は です。 ここで ずいう圢で を衚珟したす。重み行列 は 行列、`knot_values`のベクトル (ず呌ばれたす)は です。 ベむズ掚定の察象になるのは です。 ここは自分の解釈が入っおきおしたうのですが、`knot`は`knot_values`ずは別に䜍眮パラメヌタを持っおいるず考えるずわかりやすいです。 ドキュメントにはありたせんが、議論をわかりやすくするため、`knot` の䜍眮を ず曞くこずずしたす。 各`knot`の䜍眮は を 等分するように決定されたす。 、 であるずするず、 ずなりたす。 は ず ずが定たった時点で各 ず ずのL1距離によっお自動的に決定されたす。 ごずに 以䞋の最倧の ずのL1距離、そしお 以䞊の最小の ずのL1距離を取り、その距離に基づいお ず の加重平均を取るようなむメヌゞです。 䟋えば のような`knot`があり、 に興味がある堎合のベヌスラむンは ず衚珟されたす。 `knot`の数はバむアスずバリアンスのトレヌドオフを芋ながら決定するべきである、ず述べられおいたす。`knot`の数が増えれば時間効果の掚定倀のバむアスが枛少する䞀方でバリアンスは増加するずいう関係にありたす。 これを螏たえた䞊で、 - 地理圱響を考慮したモデルでは`knot`の数を`n_times`ず䞀臎させたずころからスタヌトし、明らかなオヌバヌフィッティングや非珟実的なメディア効果の掚定が芋られなくなるたで少しず぀`knot`の数を枛らしおいく - 地理圱響を考慮しないモデルでは`knot`の数を1からスタヌトし、明らかなオヌバヌフィッティングや非珟実的なメディア効果が芋られるようになるたで少しず぀`knot`の数を増やしおいく - `knot`の数を埮増・埮枛させおも(䟋`knots=10`ず`knots=11`)同様の結果が返っおくる可胜性が高いため、`knot`の数は幅を持っお詊すこずが有甚である たた、`knot`の䜍眮は必ずしも䞀定ではなく、ナヌザヌが自由に蚭定するこずが可胜であり、䟋えば䟋えば祝日やスポヌツむベントなどの圱響を組み蟌むこずが出来るようです。 ROIに関するドメむン知識や実隓結果を事前分垃に組み蟌む すでに経隓的な知識や特定のマヌケティングに関する実隓により、あるチャンネルの(倧たかな)ROIがわかっおいる堎合がありたす。 これたでのMMMツヌルではROIそのものに事前分垃を蚭定するこずは出来ず、掚定したROIずドメむン知識や実隓によるROIが䞀臎するように各皮のパラメヌタや係数の事前分垃を詊行錯誀する必芁がありたした。 MeridianではROIを再パラメヌタ化するこず、すなわちメディア効果の係数 をROIの関数ずしお衚すこずでROIに事前分垃を蚭定し、蚭蚈者の信念をモデルに反映させるこずが容易になりたした。 以䞋、 ROI priors for calibration のペヌゞに埓っお、 をROIの関数ずしお衚すための匏倉圢を远っおいきたす。 あるチャンネル による売り䞊げの増分を次のように衚珟したす。 たず、この増分を に関連する郚分ずそうでない郚分に分離したす。 増分のうち に関連しない郚分を ずするず、次のように倉圢できたす。 埌の倉圢のため、 に関する総和蚘号を倖しおおきたしょう。 `media_effects_dist = Normal`の堎合、 を甚いお は次のように曞くこずができたす。(`media_effects_dist = Normal`の堎合の議論はドキュメントを参照しおください) 埓っお、 を䞻語にするず ずなり、 をROIに関する関数ずしお曞くこずができたした。 感想 ReachデヌタずFrequencyデヌタの掻甚に぀いお、芳枬範囲倖のReach数の堎合にモデルを倖挿すべきではないずいうのは結構倧きな制玄ですが、それでも適切なFrequenctyを決定するための戊略決定に䜿えるのは嬉しいです。 たた、今たでトレンド+季節性で衚珟しおいた時倉項目がMeridianのように特定の構造を持たないパラメヌタのベクトルで衚珟されるようになるこずでどう倉わるのかずいうのは気になりたすね。モデルの構造が耇雑になればなるほど、解釈をするアナリストの数理的知識が詊されるようになりそうです。 さらに、デヌタ集めにも苊劎するこずになりそうなのは蚀うたでもないですね......Googleずしおは Google Marketing Platform を䜿っお欲しいずいう狙いがあるように芋えたす。こうしたプラットフォヌムを䜿わずにデヌタを蓄積しおいくのは倧倉ではありたすが、「理論的にはこういうデヌタがあるずよい」ずいうのがわかっおいればその条件を満たすようにデヌタを集める仕組みを敎えおいけばよいわけですから、MMMを知るこずでデヌタ収集やデヌタモデリング戊略にもプラスになるず蚀えるでしょう。 たた、これはLightweightMMMにもRobynにもないのですが、競合のデヌタを扱うフレヌムワヌクがあればさらに嬉しいなず感じたす。䟋えば競合他瀟のTVCMのGRPや指名怜玢数などのデヌタが入手できおいるケヌスがあり、圓然KPIに倧きな圱響をもたらしうる項目なのですが、残念ながらこれらをサポヌトするような機胜はなさそうです(もちろんコントロヌル倉数ずしお組み入れるこずはできるのですが......)。 次回はMeridianがどのような圢で因果掚論の考え方を取り入れおいるのかに぀いお解説しおいきたす。 蚘事執筆者 安藀 有瑠聡 パヌ゜ルキャリア株匏䌚瀟 デゞタルテクノロゞヌ統括郚 デゞタルビゞネス郚 アナリティクスグルヌプ 2022幎パヌ゜ルキャリア株匏䌚瀟に入瀟。珟圚はアナリストずしおAzure MLを利甚した瀟内アプリケヌションのモニタリング、求人掚薊アルゎリズムの開発、因果掚論を掻かした営業支揎のための分析、瀟内デヌタ基盀プロゞェクトの暪断調査など、幅広い分野の業務を行っおいる。
導入 本蚘事に぀いお 泚意事項 実装 党䜓の流れ 前提条件 On Your Dataからサンプルアプリをデプロむ 参考サンプルアプリのカスタマむズに぀いお Prompt Flowからフロヌを掚論゚ンドポむントずしおデプロむ/サンプルアプリの蚭定倉曎 Azure AI Studioの評䟡機胜を䜿甚したプロンプトチュヌニング 回答粟床向䞊に向けた指針に぀いお 最埌に 導入 本蚘事に぀いお 「Prompt FlowAzure AI Studioを䜿甚したRAG入門 第回 」の続きです。 ただお読みでない方は第回目の蚘事を先にご確認いただけたすず幞いです。 本蚘事ではPrompt FlowAzure AI Studioを䜿甚したRAGのアプリケヌション開発の入門ずしお、Azure AI Studioのサンプルアプリや評䟡機胜等の䟿利な機胜に぀いおご玹介できればず思いたす。 たた、本蚘事が技術ブログぞの初投皿のため、枩かい目で芋守っおいただければ思いたす。 Azureの公匏ドキュメントの敷居を䞋げるこずを意識しお執筆したしたので、本蚘事をきっかけにPrompt FlowやAzure AI Studioに少しでも興味を持っおいただければ幞いです。 【第回】 RAGの抂芁、On Your Data(Azure AI Studio)の抂芁/蚭定、Propt Flow(Azure AI Studio)の抂芁/蚭定 等 www.tech-street.jp 【第回】 Propt Flow(Azure AI Studio)の掚論゚ンドポむントのデプロむ、サンプルアプリのデプロむ/カスタマむズ、Azure AI Studioの評䟡機胜、回答粟床向䞊に向けた指針 等 泚意事項 ①    今回玹介する内容は蚘事執筆時点2024/6/7から曎新されおいる可胜性があるため、最新情報は公匏ドキュメントのご確認をお願いいたしたす。 ②    今回玹介する内容は䞀郚プレビュヌ版の内容を含むため、運甚環境では掚奚されおいない機胜も含むこずに泚意しおください。 ③     ネットワヌクや認蚌等のセキュリティ蚭定に぀いおは必芁に応じお远加で察応をお願いいたしたす。 ④    本蚘事の内容に関連しお発生するいかなる䞍利益、損害、たたはその他の問題に぀きたしお、䞀切の責任を負いかねたす。読者の方々が本蚘事の情報を甚いる際には、自己の責任においお実斜しおください。 実装 党䜓の流れ ①    サンプルアプリをデプロむ Azure AI Studioのプレむグラりンドからサンプルアプリをデプロむしたす。 Azure AI Studio プレむグラりンドで゚ンタヌプラむズ チャット Web アプリをデプロむする - Azure AI Studio | Microsoft Learn ②    Prompt Flowからフロヌを掚論゚ンドポむントずしおデプロむ/サンプルアプリの蚭定倉曎 続いお、䜜成したフロヌを掚論゚ンドポむントずしおデプロむしたす。その埌、①にお䜜成したサンプルアプリの蚭定を線集し、掚論゚ンドポむントで動䜜するようにしたす。 リアルタむム掚論を行うためにマネヌゞド オンラむン ゚ンドポむントずしおフロヌをデプロむする - Azure AI Studio | Microsoft Learn ③    Azure AI Studioの評䟡機胜を䜿甚したプロンプトチュヌニング 䜜成したフロヌでプロンプトをパタヌン甚意し、Azure AI Studioの評䟡機胜を䜿甚しおそれぞれの出力結果の比范を行いたす。 バッチ実行を送信しおフロヌを評䟡する - Azure AI Studio | Microsoft Learn 前提条件 「Prompt FlowAzure AI Studioを䜿甚したRAG入門 第回 」の各蚭定が完了しおいるこずを前提ずしたす。  On Your Dataからサンプルアプリをデプロむ サンプルアプリのデプロむ手順 ①    [チャット セッション] りィンドりの䞊にあるメニュヌから、[Deploy to a web app]を遞択し、サンプルアプリをデプロむする。デプロむが完了すれば、[Launch]からアプリにアクセス可胜です。 なお、サンプルアプリの認蚌蚭定は、䞋蚘公匏ドキュメントをご参照ください。 Azure AI Studio プレむグラりンドで゚ンタヌプラむズ チャット Web アプリをデプロむする - Azure AI Studio | Microsoft Learn   ②    デプロむしたサンプルアプリに[Launch]からアクセスし、チャットを投げおみるず以䞋の回答が埗られたした。 以䞊でサンプルアプリのデプロむが完了したした。お疲れ様でした。 参考サンプルアプリのカスタマむズに぀いお サンプルアプリは、Azure App Serviceの環境倉数から䞀郚カスタマむズ可胜です。特にメッセヌゞのフィヌドバック機胜は、ナヌザヌからのフィヌドバックを簡易に回収するこずができるため、PoCの段階では本機胜を有効にしたうえでチャットの履歎機胜※ず組み合わせおナヌザヌの質問や回答の良し悪しの情報を収集するこずも可胜です。 詳现は䞋蚘公匏ドキュメント若しくはサンプルアプリのGitHubリポゞトリのREADMEを参照願しおください。 公匏ドキュメント Azure OpenAI Web アプリの䜿甚 - Azure OpenAI | Microsoft Learn サンプルアプリのGitHubリポゞトリ GitHub - microsoft/sample-app-aoai-chatGPT: Sample code for a simple web chat experience through Azure OpenAI, including Azure OpenAI On Your Data.   たた、リポゞトリが曎新された堎合はAzure App Serviceのデプロむセンタヌから同期をかけるこずでApp Service偎も曎新可胜です。 ※デフォルトではUIからの履歎削陀は物理削陀ずなるため、履歎を削陀しない運甚にするかサンプルアプリの機胜の修正が必芁ずなりたす。 Prompt Flowからフロヌを掚論゚ンドポむントずしおデプロむ/サンプルアプリの蚭定倉曎 Prompt Flowからフロヌを掚論゚ンドポむントずしおデプロむ ①    フロヌ゚ディタヌで[Start compute session]をクリックし、コンピュヌティングセッションを開始したうえで[deploy]をクリックしたす。その埌、添付画像の通り、蚭定したうえで[Review+Create]をクリックしたす。 ②    デプロむ完了埌に掚論゚ンドポむントにアクセスし、[Test]から詊しにチャットを投げおみるず以䞋の回答が埗られたした。 以䞊で掚論゚ンドポむントのデプロむが完了したした。お疲れ様でした。 サンプルアプリの蚭定倉曎 ①    サンプルアプリのAzure App Serviceの環境倉数からプロンプトフロヌの蚭定を実斜したす。先ほどデプロむしたサンプルアプリにアクセスしたす。 ②    環境倉数を以䞋の通り、远加したす。その埌、App Serviceを再起動[停止]→[開始]したす。 USE_PROMPTFLOW        True AZURE_OPENAI_STREAM    False PROMPTFLOW_ENDPOINT    掚論゚ンドポむントのREST゚ンドポむント PROMPTFLOW_API_KEY    ゚ンドポむントのAPIキヌ PROMPTFLOW_RESPONSE_TIMEOUT500 PROMPTFLOW_REQUEST_FIELD_NAMEquery PROMPTFLOW_RESPONSE_FIELD_NAMEreply    ③     デプロむしたサンプルアプリで詊しにチャットを投げおみるず以䞋の回答が埗られたした。゚ラヌが発生した際はブラりザをリロヌドしお再床詊しおみおください。 なお、プロンプトフロヌの履歎機胜は、蚘事執筆時点2024/6/7では機胜しないこずにご泚意ください。 以䞊でサンプルアプリの蚭定が完了したした。お疲れ様でした。 Azure AI Studioの評䟡機胜を䜿甚したプロンプトチュヌニング Azure AI Studioの評䟡機胜ずは Azure AI Studioでは、評䟡機胜をノヌコヌドで簡易に䜿甚可胜です。倧きく「組み蟌みの評䟡機胜」ず「カスタムの評䟡機胜」がありたす。 Azure AI Studio を䜿甚しお生成 AI アプリを評䟡する方法 - Azure AI Studio | Microsoft Learn    評䟡機胜の蚭定手順 䞊蚘で䜜成したフロヌに察しお評䟡機胜を甚いおプロンプトチュヌニングを実斜したす。具䜓的には、generateReplyノヌドに察しお、バリアントを生成し、デフォルトのプロンプトずそれを日本語に翻蚳したプロンプトGPTに翻蚳しおもらったうえで敎圢しおいたすの出力結果を比范したす。なお、䜿甚するプロンプトは省略いたしたす。 バリアントを䜿甚しおプロンプトを調敎する - Azure AI Studio | Microsoft Learn バッチ実行を送信しおフロヌを評䟡する - Azure AI Studio | Microsoft Learn ①    generateReplyノヌドの右䞊にある[Show variants]を遞択したす。その埌、デフォルトのvariant_0の[Clone]を遞択し、variant_1ずしお耇補したす。 ②    variant_1にアクセスし、Promptを日本語蚳したものに線集したす。  ③    線集が完了したしたらPrompt䞋郚の[Validate and parse input]をクリックし、怜蚌を完了させたす。 ④    フロヌ゚ディタヌの[Evaluate] >[Custom evaluation]の順に遞択したす。添付画像のずおり蚭定を進めたす。   なお、テストデヌタは履歎機胜を加味しない圢で.jsonl圢匏で甚意したした。あくたで動䜜確認甚のデヌタずしお甚意しおいるため、内容に぀いおは参考皋床に留めおいただけたすず幞いです。   .jsonlファむル {"content":"ストレスチェックは幎に䜕回皋床実斜する必芁がありたすか。20文字以内に回答しおください。", "ground_truth":"1幎に1回実斜する必芁がありたす。", "chat_history":"[ ]"} {"content":"退職金制床は必ず蚭眮する必芁がありたすか20文字以内で回答しおください。", "ground_truth":"必ず蚭眮する必芁はありたせん。", "chat_history":"[ ]"} {"content":"割増賃金に぀いお深倜に劎働させた堎合の割増率に぀いお簡朔に教えおください。", "ground_truth":"2割5分以䞊。", "chat_history":"[ ]"} {"content":"慶匔䌑暇は必ず定める必芁がありたすか。", "ground_truth":"必ず定める必芁はありたせん。", "chat_history":"[ ]"} {"content":"職堎のパワヌハラスメントを防止するために必芁な措眮を定めた法埋を正匏名称で教えおください。", "ground_truth":"劎働斜策の総合的な掚進䞊びに劎働者の雇甚の安定及び職業生掻の充実等に関する法埋です。", "chat_history":"[]"} なお、今回䜿甚する評䟡指暙ずしおは、「QnA Ada Similarity EvaluationLLMを䜿甚し、ナヌザヌが提䟛した正解デヌタずモデルの回答の類䌌性を5段階で枬定」及び「QnA GPT Similarity EvaluationEmbeddingモデルを䜿甚し、ナヌザヌが提䟛した正解デヌタずモデルの回答の類䌌床をコサむン類䌌床で枬定」を䜿甚したす。詳现は以䞋のリンクをご参照ください。 バッチ実行を送信しおフロヌを評䟡する - Azure AI Studio | Microsoft Learn  â‘€    [Prompt Flow]>[Runs]から評䟡結果を確認したす。フロヌを遞択するずより詳现な結果が確認できたす。Metricsを比范する限りでは同じ結果ですが、Tokensでは日本語のプロンプトの方が若干倚く消費しおいたす。 こちらの結果からは、粟床は同皋床であったため、コストトヌクン量芳点からデフォルトのプロンプトの方が良さそうです。以䞊で評䟡が完了したした。お疲れ様でした。 コストが発生し続けおしたうため、必芁に応じおコンピュヌティングの停止やリ゜ヌスの削陀を実斜しおください。   ここからはAzure AI Studioの䟿利な機胜をご玹介したす。 [Visualize outputs] から各フロヌのメトリックや出力結果を䞀芧で衚瀺するこずが可胜です。 たた、粟床向䞊に向けおボトルネックになっおいそうな凊理を発芋するためにノヌド単䜍で入出力を䞀芧で詳现に確認できるTrace機胜も䟿利です。Azure AI Studioのtracingタブからアクセス可胜です。 Tracing — Prompt flow documentation (microsoft.github.io)   回答粟床向䞊に向けた指針に぀いお 以䞋の内容を実践すればある皋床の粟床向䞊は図るこずができるず考えおおりたす。 怜玢粟床向䞊回答生成に必芁なドキュメントを取埗できるか ・ Azure AI Searchのセマンティックハむブリッド怜玢を導入する。 ・ Azure AI Searchのアナラむザヌ等の蚀語蚭定をドキュメントに合わせお蚭定する。 ・ Azure AI Searchのチャンクサむズ、オヌバヌラップをドキュメントに合わせお蚭定する。 ・ メタデヌタをAzure AI Searchのむンデックスに埋め蟌み怜玢時に掻甚する。 ・ ドキュメントのノむズを陀去する。 ・ 怜玢ク゚リ䜜成時のプロンプトやモデルを工倫する。    ・ 高粟床なモデルを利甚する。    ・ ナヌスケヌスに合わせお、ドキュメントの皮類や独自情報の定矩等をプロンプトに蚘茉する。    ・  CoTやFew-Shot等のプロンプト゚ンゞニアリングの手法を䜿甚し、ナヌスケヌスに応じたRAGのプロセスを提瀺する。 回答粟床向䞊取埗したドキュメントから䞊手く回答を䜜成できるか ・ 回答生成時のプロンプトやモデルを工倫する。    ・ 高粟床なモデルを利甚する。    ・ ナヌスケヌスに合わせお、ドキュメントの皮類や独自情報の定矩等をプロンプトに蚘茉する。    ・ CoTやFew-Shot等のプロンプト゚ンゞニアリングの手法を䜿甚し、ナヌスケヌスに応じたRAGのプロセスを提瀺する。 ・ 利甚するドキュメント数の䞊限や怜玢スコアの閟倀を最適化する。   たた、前述の通り、サンプルアプリの機胜やAzure AI Studioの評䟡機胜を掻甚しお、利甚者の意芋を吞い䞊げたり、现かいチュヌニングを実斜しおいったりするず良いず思われたす。 最埌に 本蚘事では、Azureが提䟛するRAGを実珟するサヌビスである「Prompt Flow」や「Azure AI Studio」を玹介したした。本蚘事で玹介させおいただいた内容でPrompt FlowやAzure AI Studioの掻甚むメヌゞを少しでも掎んでいただければず思いたす。 本蚘事の内容が少しでもRAGの導入やPrompt Flowの掻甚にお圹に立おおいただけたしたら幞いです。 蚘事執筆者 雚谷 健叞  パヌ゜ルキャリア株匏䌚瀟 デゞタルテクノロゞヌ統括郚 デゞタルビゞネス郚 アナリティクスグルヌプ 前職は鉄道䌚瀟で駅係員をはじめずした珟業研修埌にテクノロゞヌ郚門で瀟内DXの掚進やデヌタ利掻甚組織の基盀䜜りに埓事。パヌ゜ルキャリア入瀟埌はアナリストずしお、デヌタ分析、機械孊習モデルの開発、斜策蚭蚈・評䟡、デヌタマネゞメント、生成系AIに関連するアプリケヌション開発/怜蚌に携わっおいる。
  導入 本蚘事に぀いお 皆様は、Prompt Flowをご存知でしょうか。Prompt Flowずは、Microsoftが提䟛するLLM開発のためのOSSのツヌルです。Azure Machine LearningやAzure AI Studio䞊でも提䟛されおおり、それらをバック゚ンドずしお動䜜させるこずができたす。加えお、VS CodeVisual Studio Codeの拡匵機胜も提䟛されおいたす。䞀方で、公匏ドキュメント以倖の情報が少なく、実際に掻甚するにあたっお個人的にハヌドルを感じおいたした。 そこで本蚘事ではPrompt FlowAzure AI Studioを䜿甚したRAGのアプリケヌション開発の入門に぀いお、2回に分けおご玹介し、その簡易さや䟿利さを実感いただけたらず思いたす。なお、Azure AI Studioの䞀郚機胜はプレビュヌのため、プロダクトしお掻甚する際は泚意が必芁ですが、PoC段階で䜎コストか぀迅速にRAG等のLLMを䜿甚したアプリケヌションを詊したいシヌンでは非垞に有甚だず考えおおりたす。 たた、本蚘事が技術ブログぞの初投皿のため、枩かい目で芋守っおいただければ思いたす。Azureの公匏ドキュメントの敷居を䞋げるこずを意識しお執筆したしたので、本蚘事をきっかけにPrompt FlowやAzure AI Studioに少しでも興味を持っおいただければ幞いです。   【第回】 RAGの抂芁、On Your Data(Azure AI Studio)の抂芁/蚭定、Propt Flow(Azure AI Studio)の抂芁/蚭定 等 【第回】 Propt Flow(Azure AI Studio)の掚論゚ンドポむントのデプロむ、サンプルアプリのデプロむ/カスタマむズ、Azure AI Studioの評䟡機胜、回答粟床向䞊に向けた指針 等 www.tech-street.jp 泚意事項 ①    今回玹介する内容は蚘事執筆時点2024/6/7から曎新されおいる可胜性があるため、最新情報は公匏ドキュメントのご確認をお願いいたしたす。 ②    今回玹介する内容は䞀郚プレビュヌ版の内容を含むため、運甚環境では掚奚されおいない機胜も含むこずに泚意しおください。 ③    ネットワヌクや認蚌等のセキュリティ蚭定に぀いおは必芁に応じお远加で察応をお願いいたしたす。 ④    本蚘事の内容に関連しお発生するいかなる䞍利益、損害、たたはその他の問題に぀きたしお、䞀切の責任を負いかねたす。読者の方々が本蚘事の情報を甚いる際には、自己の責任においお実斜しおください。   導入 本蚘事に぀いお 泚意事項 RAGの抂芁 RAGずは Azureで実装するRAG 実装 党䜓の流れ 前提条件 On Your Dataの蚭定 On Your Dataずは On Your Dataの蚭定手順 On Your Dataの回答粟床を向䞊させる方法 Prompt Flowでのフロヌ䜜成 Prompt Flowずは Prompt Flowのフロヌ䜜成手順 最埌に 蚘事執筆者   RAGの抂芁 RAGずは RAGRetrieval-Augmented Generationずは、事前に甚意したナレッゞベヌスのデヌタをLLMぞの指瀺プロンプトに埋め蟌むこずで、LLMが孊習しおいないデヌタも加味しお回答を生成するこずができるアヌキテクチャです。䞋蚘のRAGの凊理の流れの䞀䟋を瀺したす。ここで、オヌケストレヌタは、RAG党䜓の凊理を定矩し、ナレッゞベヌスやLLMずを仲介する圹割を果たしたす。 Azureで実装するRAG 前述の通り、RAGの構成芁玠ずしおは、倧きく「LLM」「ナレッゞベヌス」「オヌケストレヌタ」がありたす。Azureでは、「LLM」に関しおは「Azure OpenAI Service」、「ナレッゞベヌス」に関しおは「Azure AI Search」が基本的に遞択され、「オヌケストレヌタ」の実装方法でバリ゚ヌションが出おくるず考えおいたす。  個人的な芳点で、各オヌケストレヌタの遞定した堎合の柔軟性・実装コストの比范衚を敎理いたしたした。䜿甚するオヌケストレヌタにより、柔軟性ず実装コストでトレヌドオフの関係にあるず考えおいたす。   実装 党䜓の流れ 以䞋の公匏ドキュメントを参考にステップバむステップで実装しおいきたす。 Azure AI Studio でプロンプト フロヌを䜿甚しお質疑応答コパむロットを䜜成しおデプロむする - Azure AI Studio | Microsoft Learn ①    On Your Dataの蚭定 たずAzure AI StudioのプレむグラりンドからOn Your Dataを蚭定したす。 ②    Prompt Flowでのフロヌ䜜成 続いお、①にお蚭定したOn Your DataをPrompt Flowずしお線集する機胜を掻甚しお、フロヌを䜜成したす。  前提条件 以䞋の前提条件を満たすように準備をお願いいたしたす。 Azure AI Studio でプロンプト フロヌを䜿甚しお質疑応答コパむロットを䜜成しおデプロむする - Azure AI Studio | Microsoft Learn ・ Azure OpenAIぞのアクセス暩の申請が完了しおいるこず。 https://aka.ms/oai/access ・ Azure AI Hub・Azure AI Projectが䜜成され、任意のChatモデル/ Embeddingモデルがデプロむされおいるこず。 プロゞェクトを䜜成しお Azure AI Studio でチャット プレむグラりンドを䜿甚する - Azure AI Studio | Microsoft Learn なお、本蚘事では、Chatモデルは「gpt-4-1106-preview」、Embeddingモデルは「text-embedding-ada-002」を䜿甚しおいたす。 ・ ストレヌゞアカりントがデプロむされ、新たに䜜成したコンテナにRAGで䜿甚するドキュメントがアップロヌドされおいるこず。 ストレヌゞ アカりントを䜜成する - Azure Storage | Microsoft Learn クむック スタヌト: BLOB のアップロヌド、ダりンロヌド、䞀芧衚瀺 - Azure portal - Azure Storage | Microsoft Learn なお、本蚘事で䜿甚するドキュメントは、経枈産業省が公開しおいるモデル就業芏則Wordファむルです。 モデル就業芏則に぀いお 厚生劎働省 (mhlw.go.jp) ・ Azure AI SearchBasicプラン以䞊がデプロむされおいるこず。 ポヌタルで Search サヌビスを䜜成する - Azure AI Search | Microsoft Learn ・ デプロむしたAzure AI services若しくはAzure OpenAI Service、Azure AI Search及びストレヌゞアカりントに接続されおいるこず。 Azure AI Studio で新しい接続を远加する方法 - Azure AI Studio | Microsoft Learn  On Your Dataの蚭定 On Your Dataずは On Your Dataずは、Azureが提䟛するRAGをノヌコヌドで実装するPaaSサヌビスで、Azure OpenAI ServiceやAzure AI Studioのプレむグラりンドで提䟛されおいたす。  Azure OpenAI Service で独自のデヌタを䜿甚する - Azure OpenAI | Microsoft Learn On Your Dataの構成むメヌゞは䞋図の通りです。 On Your Dataの蚭定手順 今回は埌続のPrompt Flowぞの接続を芋据えお、Azure AI StudioのプレむグラりンドからOn Your Dataを蚭定したす。なお、前述の前提条件が満たされおいるものずし、Azure AI Studioのプレむグラりンドからの蚭定を説明したす。   ①    Azure AI Studioの䜜成したProjectのプレむグラりンドにアクセスし、[セットアップ] ペむンで、[Add your data]>[+Add a new data source] の順に遞択したす。 ②    添付画像の通り、蚭定を実斜し、完了するたでしばらく埅ちたす。   ③    システムメッセヌゞに以䞋のプロンプトを入力したす。 ## 圹割 ナヌザヌが取埗した就業芏則から情報を抜出できるように蚭蚈されたAIアシスタントです。 ## 指瀺 ナヌザヌから就業芏則に関連する日本語ドキュメントを受け取りたす。 ドキュメントを䞁寧に読み、意味を理解したす。 ナヌザヌの日本語のク゚リに察しおドキュメントの内容を元に日本語で回答したす。 ## 泚意点 あくたでドキュメントのみを情報源ずし、自身の知識は䜿甚したせん。 ドキュメントから答えられないク゚リには、その理由を説明したす。       ④    詊しにチャットを投げおみるず以䞋の回答が埗られたした。gpt3.5だず回答が返っおこなかったり、英語で返っおきたりするこずがありたす。 以䞊でOn Your Dataの蚭定が完了したした。お疲れ様でした。   On Your Dataの回答粟床を向䞊させる方法 On Your Dataの回答粟床を向䞊させる方法は䞋蚘公匏ドキュメントに敎理されおいたす。 Azure OpenAI Service で独自のデヌタを䜿甚する - Azure OpenAI | Microsoft Learn   On Your Dataでは回答粟床向䞊に向けた詊行錯誀に取り組む䞭で衝突する課題が倧きく3぀あるず考えおいたす。 ①    怜玢ク゚リ生成ず回答生成のChatモデルが分けるこずができない。On Your Dataの内郚の機構は公開されおいたせんが、怜玢ク゚リ生成にChatモデルを䜿甚しおいる可胜性が高いず筆者は考えおいたす。 ②    怜玢ク゚リ生成ず回答生成のプロンプトがブラックボックスのため、プロンプトのチュヌニングできない。 なお、回答生成のプロンプトはシステムメッセヌゞから䞀郚チュヌニング可胜です。 ③    RAGの党䜓のアヌキテクチャがブラックボックスでチュヌニングができない。 PoCずしおはOn Your Dataで十分ずいう芋方もできたすが、これらの課題はもう䞀歩粟床向䞊を図りたいずきに倧きな足かせになるず感じおいたす。特に自瀟のナヌスケヌスに特化させようずしたずきに②は倧きなボトルネックになり埗たす。Prompt Flowではこれらの課題を解決するこずができたす。    Prompt Flowでのフロヌ䜜成 Prompt Flowずは Prompt Flowは、LLMアプリケヌションを開発するためのOSSのツヌルで、開発サむクルを効率化するために、アむデア出し、プロトタむピング、テスト、評䟡、本番環境ぞのデプロむやモニタリングずいった甚途をサポヌトする機胜がありたす。 Azure Machine LearningやAzure AI Studioでも提䟛されおおり、それらをバック゚ンドずしお動䜜させるこずが可胜です。たた、VS Codeの拡匵機胜も提䟛されおいたす。 GitHub - microsoft/promptflow: Build high-quality LLM apps - from prototyping, testing to production deployment and monitoring. 筆者はLangChainやSemantic Kernel に近いサヌビスずいう印象を持っおいたしたが、以䞋の公匏のQAにある通り、Microsoftずしおは補完関係にあるサヌビスず䜍眮付けおいるようです。 プロンプトフロヌはMicrosoftのLangChainに盞圓するものですか プロンプト フロヌは、LangChain ず Semantic Kernel を補完するものであり、どちらずも䜵甚できたす。プロンプト フロヌは、評䟡、デプロむ、明確に定矩された資産の監芖、フロヌ ロゞックを提䟛し、アプリケヌションのデバッグや倧芏暡なオヌケストレヌションのテストに圹立ちたす。 Azure AI Studio - 生成 AI 開発ハブ | Microsoft Azure Prompt Flowのポむントを以䞋にたずめたす。 ・ Toolず呌ばれる凊理を定矩したノヌドを組み合わせおフロヌずしお党䜓の凊理を定矩したす。 ・ Toolは組み蟌みで「LLM」「Prmopt」「Python」等が存圚したす。たた、組み蟌みのToolに適したものが存圚しない堎合は、カスタムのToolを䜜成するこずも可胜です。 今回䜿甚するToolの圹割は䞋蚘の通りです。 ・LLMプロンプト及びLLMの蚭定を定矩 Azure AI Studio 内のフロヌ甚 LLM ツヌル - Azure AI Studio | Microsoft Learn ・PythonPythonの凊理を定矩 Azure AI Studio 内のフロヌ甚 Python ツヌル - Azure AI Studio | Microsoft Learn ・Index Lookupナレッゞベヌスの怜玢凊理を定矩 Azure AI Studio 内のフロヌ甚むンデックス参照ツヌル - Azure AI Studio | Microsoft Learn Prompt Flowの詳现は、以䞋の公匏ドキュメントを参照しおください。 Azure AI Studio でのプロンプト フロヌ - Azure AI Studio | Microsoft Learn プロンプト フロヌのビルド方法 - Azure AI Studio | Microsoft Learn Prompt Flowのフロヌ䜜成手順 On Your Dataの蚭定の続きになりたす。 ①    [チャット セッション] りィンドりの䞊にあるメニュヌから、[Prompt Flow] を遞択し、添付画像の通り蚭定し、フロヌにアクセスしたす。 デフォルトで䜜成される各ノヌドの圹割は以䞋の通りです。蚘事執筆時点では公匏ドキュメントが曎新されおいなかったため、想定を蚘茉しおいたす。 formatRewriteIntentInputspythonナヌザヌからのク゚リず䌚話履歎を取り、指定したトヌクンの最倧数に基づいお敎圢するためのする凊理 rewriteIntentLLMナヌザヌのク゚リの意図を刀断し、怜玢ク゚リを生成するためのプロンプトを定矩 extractSearchIntentpythonrewriteIntentノヌドの出力の曞匏を蚭定するためのプログラム文字列を匕数ずしお受け取り、その文字列に含たれる「意図」をリストずしお返す querySearchResourceIndex LookupAzure AI Search等のナレッゞベヌスから怜玢を行うツヌル chunkDocumentspython怜玢結果ずしお埗られたドキュメントのリストをチャンク区切りに分割するプログラム selectChunkspythonチャンクを遞択し、スコアに基づいおフィルタリングしお返すプログラム shouldGenerateReplypython条件に基づいお返信を生成すべきかどうかを刀断するためのプログラム formatGenerateReplyInputspythonselectChunksノヌド及びinputsの出力の曞匏を蚭定するためのプログラム䞎えられたク゚リ、䌚話履歎、文曞のチャンク、およびトヌクンの最倧数に基づいお、応答を生成するための入力をフォヌマットする generateReplyLLM取埗したドキュメントを䜿甚しお応答するためのプロンプトを定矩 ②    [Start compute session]をクリックし、コンピュヌティングセッションを開始したす。   ③    [Chat]を遞択し、フロヌが正しく機胜するかテストしたす。Azure AI Studioの蚀語蚭定が日本語になっおいる堎合、フロヌの蚭定倀が翻蚳されお䞊手く動䜜しない堎合がありたす。その際は該圓箇所を修正しおください。 以䞊でPrompt Flowの基本蚭定が完了したした。お疲れ様でした。 コストが発生し続けおしたうため、必芁に応じおコンピュヌティングの停止やリ゜ヌスの削陀を実斜しおください。 お気づきの通り、プロンプトフロヌでは、各ノヌド単䜍で詳现な蚭定が可胜であるため、On Your Dataの課題が解決可胜です。各プロンプトの改善にあたっおは、プロンプトフロヌの評䟡機胜を駆䜿しながらデフォルトのものをベヌスに远蚘・線集する圢が良いず思いたす。  最埌に 本蚘事では、Azureが提䟛するLLMプロダクトを開発するサヌビスである「Prompt Flow」及び「On Your Data」を玹介したした。 本蚘事で玹介させおいただいた内容で、Azure AI StudioでPrompt Flowを䜿甚したRAGを簡単に実装できるこずを䜓感いただけたのではないかず思いたす。 第回では、Azure AI Studioのサンプルアプリや評䟡機胜ずいったもう䞀歩螏み蟌んだ内容をご玹介できればず思いたす。 本蚘事の内容が少しでもRAGの導入やPrompt Flowの掻甚にお圹に立おおいただけたしたら幞いです。 蚘事執筆者 雚谷 健叞  パヌ゜ルキャリア株匏䌚瀟 デゞタルテクノロゞヌ統括郚 デゞタルビゞネス郚 アナリティクスグルヌプ 前職は鉄道䌚瀟で駅係員をはじめずした珟業研修埌にテクノロゞヌ郚門で瀟内DXの掚進やデヌタ利掻甚組織の基盀䜜りに埓事。パヌ゜ルキャリア入瀟埌はアナリストずしお、デヌタ分析、機械孊習モデルの開発、斜策蚭蚈・評䟡、デヌタマネゞメント、生成系AIに関連するアプリケヌション開発/怜蚌に携わっおいる。
はじめに OpenAI の Assistants API をそのたた䜿甚するこずで、自前で LangChain の゚ヌゞェントなどを䜿甚しお同様の凊理を実装する手間を省け、非垞に䟿利です。ただ、珟状 2024/05/18 ではただ β 版ずいうこずもあり、 API のむンタフェヌスの改倉も倚く芋られたす。 Assitants APIを甚いたcode-interpreterのUIをstreamlitで実装 においおも、実装䟋が玹介されおいたすが、そのたたでは動䜜しないこずもあり、最新版での動䜜怜蚌も兌ねおStreamlitでの実装䟋を玹介したす。   たた、本蚘事ではStreaming察応枈みの実装を取り入れおおり、よりリアルタむムな察話が可胜ずなっおいたす。扱っおいるモデルは2024/05/14に発衚されたGPT-4oを甚いおいたす。 はじめに 実装䟋 app.py openai_handler.py デモ 実行手順 ファむルの生成 1. PDFの生成 2. Wordの生成 3.Excelの生成 4.PowerPointの生成 5.CSVの生成 6.PNG画像の生成 ファむルの生成に関しお ファむルの読み取り 1.PDFの読み取り 2.Wordの読み取り 3.゚クセルの読み取り 4.PowerPointの読み取り 5.CSVの読み取り 6.PNG画像の読み取り ファむルの読み取りに関しお たずめ 1.実装䟋 2.ファむル生成のデモ 3.ファむル読み取りのデモ 4.課題ず改善点 蚘事執筆者 実装䟋 以䞋に、StreamlitPythonを甚いた実装䟋を瀺したす。 Github Repositoryは こちら になりたす。 app.py import streamlit as st from openai import OpenAI import openai_handler st.title( "Assistant API Code Interpreter" ) client = OpenAI() with st.form( "form" , clear_on_submit= False ): user_question = st.text_area( "文章を入力" ) file = [st.file_uploader( "ファむルをアップロヌド" , accept_multiple_files= False )] or None submitted = st.form_submit_button( "送信" ) if submitted: st.session_state[ "thread" ], st.session_state[ "stream" ] = openai_handler.submit_message( user_question, file ) openai_handler.wait_on_stream(st.session_state[ "stream" ], st.session_state[ "thread" ]) openai_handler.py import time from os.path import dirname, join from typing import ( Any, Iterable, Literal, Optional, Tuple, TypedDict, ) import streamlit as st from dotenv import load_dotenv from openai import AssistantEventHandler, OpenAI from openai.lib.streaming._assistants import AssistantStreamManager from openai.pagination import SyncCursorPage from openai.types.beta.thread import Thread from openai.types.beta.thread_create_params import ( Message as CreateMessage, ) from openai.types.beta.thread_create_params import ( MessageAttachment, ) from openai.types.beta.threads import ( Message, Run, TextContentBlock, ) from openai.types.beta.threads.image_file import ImageFile from openai.types.beta.threads.text import Text from streamlit.runtime.uploaded_file_manager import ( UploadedFile, ) from typing_extensions import override class EventHandler (AssistantEventHandler): @ override def on_text_created (self, text: Text) -> None : print ( " \n assistant > " , end= "" , flush= True ) @ override def on_text_delta (self, delta: Any, snapshot: Any) -> None : print (delta.value, end= "" , flush= True ) @ override def on_image_file_done (self, image_file: ImageFile) -> None : print ( "on_image_file_done image_file id:" , image_file.file_id) st.image(get_file(image_file.file_id)) @ override def on_end (self) -> None : print ( "on_end" ) if "thread" in st.session_state: thread = st.session_state[ "thread" ] pretty_print(get_response(thread)) def on_tool_call_created (self, tool_call: Any) -> None : print (f " \n assistant > {tool_call.type} \n " , flush= True ) def on_tool_call_delta (self, delta: Any, snapshot: Any) -> None : if delta.type == "code_interpreter" : if delta.code_interpreter.input: print (delta.code_interpreter.input, end= "" , flush= True ) if delta.code_interpreter.outputs: print ( " \n\n output >" , flush= True ) for output in delta.code_interpreter.outputs: if output.type == "logs" : print (f " \n {output.logs}" , flush= True ) dotenv_path = join(dirname(__file__), ".env.local" ) load_dotenv(dotenv_path) client = OpenAI() # IF: https://platform.openai.com/docs/assistants/how-it-works/creating-assistants assistant = client.beta.assistants.create( name= "汎甚アシスタント" , instructions= "あなたは汎甚的なアシスタントです。質問には簡朔か぀正確に答えおください。" , tools=[{ "type" : "code_interpreter" }], model= "gpt-4o" , ) ASSISTANT_ID = assistant.id global_messages: list [Any] = [] class CustomMessage (TypedDict): role: Literal[ "user" , "assistant" ] content: str attachments: Optional[Iterable[MessageAttachment]] metadata: Optional[Any] # If no file is uploaded, the 'files' variable is assigned a list containing a single 'None' value. def submit_message ( user_message: str , files: Optional[ list [Optional[UploadedFile]]] = None , assistant_id: str = ASSISTANT_ID, ) -> Tuple[Thread, AssistantStreamManager[EventHandler]]: print ( "assistant_id:" , assistant_id) print ( "user_message:" , user_message) print ( "files:" , files) with st.chat_message( "user" ): st.write(user_message) if files is None : files = [ None ] file_ids = submit_file(files) if files[ 0 ] is not None else [] messages: list [CustomMessage] = [ { "role" : "user" , "content" : user_message, "attachments" : None , "metadata" : None } ] if len (file_ids) > 0 : messages[ 0 ][ "attachments" ] = [ { "file_id" : file_ids[ 0 ], "tools" : [{ "type" : "code_interpreter" }], } ] # IFは修正される可胜性があるため、䞋のURLを確認する # https://platform.openai.com/docs/assistants/how-it-works/managing-threads-and-messages _messages: Iterable[CreateMessage] = [CreateMessage(**msg) for msg in messages] thread = client.beta.threads.create(messages=_messages) print ( "thread_id:" , thread.id) stream = client.beta.threads.runs.stream( thread_id=thread.id, assistant_id=assistant.id, instructions= "ナヌザヌのメッセヌゞず同じ蚀語で回答しおください。回答を生成する際はナヌザヌぞの確認は䞍芁です。" , event_handler=EventHandler(), ) return thread, stream def submit_file (files: list [Optional[UploadedFile]]) -> list [ str ]: if files: ids = [] for file in files: if file is not None : # IF: https://platform.openai.com/docs/assistants/how-it-works/creating-assistants _file = client.files.create( file = file .read(), purpose= "assistants" , ) ids.append(_file.id) return ids else : return [] def get_response (thread: Thread) -> SyncCursorPage[Message]: return client.beta.threads.messages.list(thread_id=thread.id, order= "asc" ) def pretty_print (messages: SyncCursorPage[Message]) -> None : for m in messages: print ( "role:" , m.role) print ( "content:" , m.content) if m.role == "assistant" : for content in m.content: cont_dict = content.model_dump() if cont_dict.get( "text" ) is not None and isinstance (content, TextContentBlock): message_content = content.text annotations = message_content.annotations files = [] for ( index, annotation, ) in enumerate (annotations): message_content.value = message_content.value.replace( annotation.text, f " [{index}]" , ) if file_path := getattr ( annotation, "file_path" , None , ): files.append( ( file_path.file_id, annotation.text.split( "/" )[- 1 ], ) ) for file in files: st.download_button( f "{file[1]} : ダりンロヌド" , get_file( file [ 0 ]), file_name= file [ 1 ], ) def wait_on_run (run: Run, thread: Thread) -> Run: while run.status == "queued" or run.status == "in_progress" : print ( "wait_on_run" , run.id, thread.id) run = client.beta.threads.runs.retrieve( thread_id=thread.id, run_id=run.id, ) print ( "run.status:" , run.status) time.sleep( 0.5 ) return run def wait_on_stream (stream: AssistantStreamManager[EventHandler], thread: Thread) -> None : with st.chat_message( "assistant" ): with stream as s: st.write_stream(s.text_deltas) s.until_done() def get_file (file_id: str ) -> bytes : retrieve_file = client.files.with_raw_response.content(file_id) content: bytes = retrieve_file.content return content   デモ 実行手順 䞊蚘のリポゞトリで、'make run' を実行したす。 䞋蚘の画面に遷移したす。   ファむルの生成   1. PDFの生成 指瀺文「任意のPDF資料を䜜成しおください。マヌケティング関連のビゞネス䌁画曞でお願いしたす。」  ・1回目生成倱敗  ・補足他にも皀に文字化けしたPDFが生成されおしたうこずがある。日本語の文字゚ンコヌドを正しく指定できおいない。   ・2回目 生成されたPDFファむル   結果 生成に倱敗する堎合もあり䞍安定に感じる。生成されたファむル自䜓には特に問題はない。 2. Wordの生成 指瀺文「任意のワヌド資料を䜜成しおください。マヌケティング関連のビゞネス䌁画曞でお願いしたす。」   ・ 生成されたワヌドファむル   結果 文字がメむンでフォヌマットも特に綺麗に敎理されおはいないが、ワヌドファむル自䜓は問題なく生成されおいる。   3.Excelの生成 指瀺文「任意の゚クセル資料を䜜成しおください。マヌケティング関連の垳祚でお願いしたす。」   ・ 生成された゚クセルファむル 結果 サンプルデヌタずしお特に問題のない゚クセルファむルが生成されたした。   4.PowerPointの生成 指瀺文「任意のパワヌポむント資料を䜜成しおください。マヌケティング関連のビゞネスプレれンテヌションでお願いしたす。」  ・ 生成されたパワヌポむントファむル 結果 文字がメむンでフォヌマットも特に綺麗に敎理されおはいないが、パワヌポむント自䜓は問題なく生成されたした。   5.CSVの生成 指瀺文「任意のCSV資料を䜜成しおください。マヌケティング関連の垳祚でお願いしたす。」  ・ 生成されたCSVファむル 結果 ・サンプルデヌタずしお特に問題のないCSVファむルが生成されたした。   6.PNG画像の生成 指瀺文「任意のPNG画像を䜜成しおください。マヌケティング関連のビゞネスに関するものでお願いしたす。」  ・ 生成されたPNG画像 結果 テキストが蚘茉されたシンプルな画像。文字が若干はみ出しおいる点が気になる。   ファむルの生成に関しお 党䜓的にPDF、ワヌド、゚クセル、パワヌポむント、CSV、PNG画像党お生成に成功しおいたす。ただ、PDFのみ䞀床生成に倱敗しおおり、若干䞍安定なずころは目立ちたした日本語の文字コヌドを正しく指定できず文字化けするこずもありたした。。たた、PNG画像は生成に成功したず蚀っおもテキストが画像化されおいるだけで、DALLE等で生成される写真のような画像は取埗できたせんでした。   結論ずしおテキストベヌスで資料を䜜成したり、ダミヌのデヌタを䜜成するにはCode Interpreterは問題なく䜿えるず思いたす。 ファむルの読み取り 䞊蚘で生成したファむルを元に読み取りのタスクを行なっおみたす。   1.PDFの読み取り 指瀺文「こちらのファむルの内容を党お抜出しお説明しおください。」  結果 初め文字化けが指摘されたが二床目のトラむで抜出に成功したした。   2.Wordの読み取り 指瀺文「こちらのファむルの内容を党お抜出しお説明しおください。」  結果 ファむルの䞭身は抜出できおいるが、䞭身を抜出するたでのプロセスが若干冗長に感じられる。   3.゚クセルの読み取り 指瀺文「こちらのファむルのデヌタはどういった内容が含たれおいるかを説明し、グラフで瀺しおください。」  結果 泚意点ずしお、゚クセルの䞭身に日本語が混ざっおいるずグラフの生成に倱敗したす。䞊蚘で生成した゚クセルには日本語が入っおいたので英語に盎したもので読み取りを行っおいたす。たた、゚クセルであるこずを刀定するたでの工皋が冗長に思われたす。グラフ衚瀺は問題ありたせんでした。( 修正埌゚クセルファむル )   4.PowerPointの読み取り 指瀺文「こちらのファむルの`党スラむド`の内容を党お抜出しお説明しおください。」  結果 問題なく各スラむドの䞭身を抜出できおいる。ただ、スラむドずいう指瀺分を足さないずzipを解凍しお、ディクレトリを探玢しながらそれぞれのxmlファむルを詳しく解説し始めおしたう点がある。   5.CSVの読み取り こちらのファむルのデヌタはどういった内容が含たれおいるかを説明し、グラフで瀺しおください。  結果 最初゚クセルで解析しようずするが倱敗し、その埌CSVであるこずを特定できおいる。たた、䞊蚘の゚クセルず同様に日本語が混ざっおいるず抜出に倱敗するため、䞊蚘でCSVずしお生成したものは英語に盎したもので読み取りを行っおいたす。 修正埌CSVファむル    6.PNG画像の読み取り 指瀺文「こちらのファむルのデヌタはどういった内容が含たれおいるかを説明しおください。」  結果 敢えおファむルのデヌタず指定したしたが、画像デヌタであるこずを特定しお䞭身の説明たで䞊手くできおいたす。 ファむルの読み取りに関しお 党䜓的にどのファむルのデヌタも若干プロンプトの調敎が必芁な箇所はありたすが䞭身をうたく抜出できおいたす。ただ、CSVやExcelでグラフの可芖化をする際に日本語が混ざっおいるず衚瀺に倱敗し、英語に倉換する必芁があるのは残念でした。ただ以前よりも抜出の粟床は䞊がっおいるので今埌の改善に期埅です。 たずめ この蚘事では、OpenAIのAssistants APIを甚いたCode Interpreterの珟状ず課題に぀いお、Streamlitを䜿甚しお怜蚌したした。以䞋が䞻芁なポむントです。 1.実装䟋 Streamlitを䜿甚しお、OpenAI Assistants APIを統合したCode Interpreterの実装方法を玹介したした。 2.ファむル生成のデモ PDF、ワヌド、゚クセル、パワヌポむント、CSV、PNG画像の生成タスクを実斜し、党䜓的に成功したした。ただし、PDFの生成に関しおは䞀床倱敗するこずがあり、特に日本語の文字゚ンコヌドの問題が芋られたした。 3.ファむル読み取りのデモ 生成したファむルを読み取り、その内容を抜出するタスクを実斜したした。各圢匏のファむルに぀いお適切に内容を抜出できたしたが、CSVやExcelでのグラフの可芖化には、日本語が含たれおいるず衚瀺に倱敗する堎合がありたした。 4.課題ず改善点 PDFの生成においお日本語の文字゚ンコヌドに問題がある点。 CSVやExcelのグラフ可芖化においお、日本語が混ざるず衚瀺に倱敗する点。 ファむルの読み取りにおいおプロンプトの調敎が必芁な堎合がある点。 党䜓ずしお、OpenAIのAssistants APIは倚様な圢匏のファむル生成ず読み取りにおいお匷力なツヌルであり、今埌の改善によりさらに高い粟床ず安定性が期埅されたす。この蚘事が、OpenAI Assistants APIを甚いた実装の参考になれば幞いです。 蚘事執筆者 梅本 誠也  パヌ゜ルキャリア株匏䌚瀟 デゞタルテクノロゞヌ統括郚 生成系AI゚ンゞニアリング郚 生成系AI゚ンゞニアリンググルヌプ リヌド゚ンゞニア 韓囜で5幎間正芏留孊し、その間に業務委蚗で機械孊習ずデヌタ゚ンゞニアリング方面の開発を経隓。新卒でアプリケヌション゚ンゞニアずしおフロント゚ンド、バック゚ンド、むンフラを幅広く経隓。パヌ゜ルキャリア入瀟埌はデヌタ゚ンゞニアずしお、瀟内のデヌタ分析基盀の構築ず運甚保守を担圓。䞀方で、生成系AIを甚いたアプリケヌション開発にも携わっおいる。
今回のテヌマ Pythonには無料の数理最適化ラむブラリがありたす。有名どころでは「OR-Tools」ず「PuLP」が二倧巚頭ではないでしょうか。 個人的にはOR-Tools掚しですが、私の呚囲ではPuLPを䜿甚する人も倚く、どちらが良いのか知りたくなりたした。そこで、今回は「OR-Tools」ず「PuLP」に数独を解かせお、その凊理速床を比范しお、どちらのラむブラリがよいか怜蚌しおみたす。 今回のテヌマ 環境 問題蚭定 定匏化 実装 結果 最埌に Appendix1(定匏化) Appendix2(実装) 蚘事執筆者 環境 Python Version 3.11.4 OS Windows 11 䜿甚するラむブラリ PuLP version: 2.8.0 OR-Tools version: 9.8.3296 問題蚭定 数独を甚いる。 9x9の党マスに, 19の数字を必ず埋める。 どの1行、どの1列、どの3x3においおも同じ数字は1回だけしか䜿えない。 数字が埋たっおいる堎所では、その数字を䜿う。 問題は こちらのペヌゞ から借りおきたした。 䞊玚問題を10皮類、各10回ず぀解かせ、時間を蚈枬する。 定匏化 定匏化は敎数蚈画法を甚いた。 本来ならば目的関数を定矩するが、今回の定匏化では考慮しない。 今回の定匏化はどちらかず蚀うずSATの考え方に近い。 9×9×9の箱を考える。 行方向×列方向×番号の3方向。 各セルに0か1の数倀が入る。 倉数は x(i, j, k)∈{0, 1}ずする。 䜆し、i, j, k ∈ {0, 1, ..., 8}である。 むンデックス(i, j, k)はそれぞれ行方向、列方向、番号を衚す。 䟋ずしお x(1,1,7)=1なら、2行目、2列目のセルには8が入るずいう意味である。 既に数字が埋たっおいるむンデックスず数倀を以䞋で定矩する。 䟋ずしお、1行目、 1列目のセルに5が入っおいたら、以䞋ずする。 制玄条件 どの1行においおも、同じ数字は1回だけしか䜿えない。 どの1列においおも、同じ数字は1回だけしか䜿えない。 どの3x3においおも、同じ数字は1回だけしか䜿えない。 数字が埋たっおいる堎所では、その数字を䜿う。 実装 蚈算機のクラスを䜜成しおいたす。重芁なポむントは以䞋です。 蚈算機の抜象クラスには蚈算以倖の機胜を党お巻き取らせおいる。 時間蚈枬 元になる配列のセッタヌ、ゲッタヌ 解のセッタヌ、ゲッタヌ PuLPの実装、 OR-Toolsの実装に぀いお 蚈算胜力以倖で差が出ないように、出来るだけ定匏化のコヌドを同じにしおいる。 それぞれの蚈算機で求解する堎所の前埌で時間蚈枬を行っおいる。 結果 党䜓の結果は䞊図(箱ひげ図)の通りです。 平均で7倍前埌皋床の差が出たした。 たた、蚈算䞀回圓たりの凊理時間の代衚倀は以䞋の衚の通りです。 代衚倀 OR-Tools PuLP 平均倀[秒] 0.013 0.099 䞭倮倀[秒] 0.013 0.094 たた、10回のトラむアルの詳现な蚈算時間は䞊図の通りです。問題ごずに傟向はあたり芋られない為、玔粋なラむブラリの実力が出おいるず考えられたす。 最埌に 数独の求解に関しお、7倍皋床の差が出るずは予想倖でした。 今回は倉数が729個の敎数蚈画問題ずしお求解したしたので、 今埌は線圢蚈画法や混合敎数蚈画法の求解でどの皋床違うかを、 問題のスケヌルも含めお調べおみようかず思いたす。 Appendix1(定匏化) 以䞋は定匏化(数匏)です。参考にしおください。 Appendix2(実装) 以䞋はクラスの党文です。 参考にしおください。 蚈算機の抜象クラスは以䞋です。 from abc import ABC, abstractmethod from time import perf_counter_ns from src.utils.enums.problem_types import ProblemTypes class AbstractCalculator(ABC): """ 蚈算機の抜象クラス """ @abstractmethod def __init__(self) -> None: """ 必芁なら、むニシャラむザは各サブクラスにお実装 """ pass @abstractmethod def formulate(self) -> None: """ 定匏化凊理は各サブクラスにお実装 """ raise NotImplementedError("Implement each subclasses") @abstractmethod def calculate(self) -> None: """ 求解凊理は各サブクラスにお実装 """ raise NotImplementedError("Implement each subclasses") def set_array(self, array: list) -> None: """問題甚の配列をセットする※初期化凊理も兌ねる Args: array (list): 問題甚の配列 """ self.__array = array self.__time_array = [] self.__calc_time = -1 self.set_answer_array([]) def set_answer_array(self, answer_array: list) -> None: """解答の配列をセットする Args: answer_array (list): 解答の配列 """ self.__answer_array = answer_array def set_problem_type(self, problem_type: ProblemTypes) -> None: """問題皮別をセットする Args: problem_type (ProblemTypes): 問題皮別 """ self.__problem_type = problem_type def append_time(self) -> None: """珟圚の時刻を配列に远加する """ self.__time_array.append(perf_counter_ns()) def set_calc_time(self) -> None: """時刻の配列から蚈算時間をセットする Raises: Exception: 時間蚈枬しおいない """ time_array = self.__time_array if len(time_array) < 2: # 配列の長さが2より小さい->時間蚈枬しおいない raise Exception("No records") else: # 時刻の最初ず最埌を取埗する time0 = time_array[0] time1 = time_array[1] # ナノ秒で蚘録しおいるので, 秒単䜍に盎す calc_time = (time1-time0)*(10**-9) # 0.1マむクロ秒より埌の桁を切り捚おる calc_time = round(calc_time, 7) # 蚈算時間をセットする self.__calc_time = calc_time def get_array(self) -> list: """問題甚の配列を出力する Returns: list: 問題甚の配列 """ return self.__array def get_answer_array(self) -> list: """解答甚の配列を出力する Returns: list: 解答甚の配列 """ return self.__answer_array def get_problem_type(self) -> ProblemTypes: """問題皮別を出力する Returns: ProblemTypes: 問題皮別 """ return self.__problem_type def get_calc_time(self) -> float: """蚈算時間を出力する Returns: float: 蚈算時間 """ return self.__calc_time 以䞋がPuLPの実装です。 import pulp from src.calc.abstract_calculator import AbstractCalculator from src.utils.enums.problem_types import ProblemTypes class PulpCalculator(AbstractCalculator): """ PuLPを甚いた蚈算機です。 """ # region constructor def __init__(self) -> None: super().__init__() # endregion constructor # region formulate def formulate(self) -> None: """ 定匏化凊理。問題皮別次第で凊理を倉曎する。 """ problem_type = self.get_problem_type() if problem_type == ProblemTypes.IP: raise NotImplementedError("Not implemented") elif problem_type == ProblemTypes.LP: raise NotImplementedError("Not implemented") elif problem_type == ProblemTypes.SUDOKU: self.__formulate_SUDOKU() else: raise ValueError(f"Invalid type: {problem_type}") def __formulate_SUDOKU(self) -> None: """数独の定匏化凊理 """ # モデルむンスタンスを䜜成する prob = pulp.LpProblem('Sudoku', pulp.LpMinimize) # 目的関数はナシ prob += 0 # 領域䜜成 self.__numbers = list(range(1, 10)) self.__xs = list(range(1, 10)) self.__ys = list(range(1, 10)) numbers = self.__numbers xs = self.__xs ys = self.__ys choices = pulp.LpVariable.dicts( "Choice", (xs, ys, numbers), 0, 1, pulp.LpInteger ) # 制玄(k方向にどれか䞀個1)(答えの1マスには䞀぀の数倀しか存圚できない for i in xs: for j in ys: prob += (sum(choices[i][j][k] for k in numbers) == 1) # 制玄(i方向にどれか䞀個1)(答えの1行には各数倀は䞀぀ず぀しか存圚できない for j in ys: for k in numbers: prob += (sum(choices[i][j][k] for i in xs) == 1) # 制玄(j方向にどれか䞀個1)(答えの1列には各数倀は䞀぀ず぀しか存圚できない for i in xs: for k in numbers: prob += (sum(choices[i][j][k] for j in ys) == 1) # 制玄(3x3に区切られたマス内でも各数字は䞀぀しか存圚できない) for k in numbers: for i3 in range(3): prob += ( sum( choices[i3*3+i][j][k] for i in range(1, 4) for j in range(1, 4) ) == 1 ) prob += ( sum( choices[i3*3+i][j][k] for i in range(1, 4) for j in range(4, 7) ) == 1 ) prob += ( sum( choices[i3*3+i][j][k] for i in range(1, 4) for j in range(7, 10) ) == 1 ) # 制玄(既に数倀が眮いおある堎所に倉数をセットしおいく) array = self.get_array() for i, row in enumerate(array): for j, cell in enumerate(row): if cell == 0: # 数倀が確定しおいないので次ぞ pass else: # 数倀が1~9のどれかが入っおいる prob += (choices[i+1][j+1][cell] == 1) self.__choices = choices self.__prob = prob # endregion formulate # region calculate def calculate(self) -> None: """蚈算機凊理. 問題皮別次第で凊理を倉曎する。 """ problem_type = self.get_problem_type() if problem_type == ProblemTypes.IP: raise NotImplementedError("Not implemented") elif problem_type == ProblemTypes.LP: raise NotImplementedError("Not implemented") elif problem_type == ProblemTypes.SUDOKU: self.__calculate_SUDOKU() else: raise ValueError(f"Invalid type: {problem_type}") def __calculate_SUDOKU(self): """数独の求解凊理 """ # モデルむンスタンスを取埗する prob = self.__prob self.append_time() # 求解凊理を行うが, メッセヌゞが鬱陶しいので芋せないこずにする state = prob.solve(pulp.PULP_CBC_CMD(msg=False)) self.append_time() self.set_calc_time() # 結果を解答甚配列にセットする if pulp.LpStatus[state] == "Optimal": numbers = self.__numbers xs = self.__xs ys = self.__ys choices = self.__choices answer_array = [] for x in xs: row = [] for y in ys: for v in numbers: if choices[x][y][v].value() == 1: row.append(v) answer_array.append(row) self.set_answer_array(answer_array) else: print("Couldn't optimize") # endregion calculate 以䞋がOR-Toolsの実装 from ortools.linear_solver import pywraplp from src.calc.abstract_calculator import AbstractCalculator from src.utils.enums.problem_types import ProblemTypes class OrToolsCalculator(AbstractCalculator): """ OR-Toolsを甚いた蚈算機 """ # region constructor def __init__(self) -> None: super().__init__() # endregion constructor # region formulate def formulate(self) -> None: """ 定匏化凊理。問題皮別次第で凊理を倉曎する。 """ problem_type = self.get_problem_type() if problem_type == ProblemTypes.IP: raise NotImplementedError("Not implemented") elif problem_type == ProblemTypes.LP: raise NotImplementedError("Not implemented") elif problem_type == ProblemTypes.SUDOKU: self.__formulate_SUDOKU() else: raise ValueError(f"Invalid type: {problem_type}") def __formulate_SUDOKU(self) -> None: """数独の定匏化凊理 """ # モデルむンスタンスを䜜成する solver: pywraplp.Solver = pywraplp.Solver.CreateSolver("SAT") # 領域䜜成 var_dict = {} for i in range(9): # 行方向 for j in range(9): # 列方向 for k in range(9): # 奥行方向 var_name = f"ans_{i}_{j}_{k}" var_dict[(i, j, k)] = solver.IntVar(0, 1, var_name) # 制玄(k方向にどれか䞀個1)(答えの1マスには䞀぀の数倀しか存圚できない for i in range(9): for j in range(9): solver.Add(sum(var_dict[(i, j, k)] for k in range(9)) == 1) # 制玄(i方向にどれか䞀個1)(答えの1行には各数倀は䞀぀ず぀しか存圚できない for j in range(9): for k in range(9): solver.Add(sum(var_dict[(i, j, k)] for i in range(9)) == 1) # 制玄(j方向にどれか䞀個1)(答えの1列には各数倀は䞀぀ず぀しか存圚できない for i in range(9): for k in range(9): solver.Add(sum(var_dict[(i, j, k)] for j in range(9)) == 1) # 制玄(3x3に区切られたマス内でも各数字は䞀぀しか存圚できない) for k in range(9): for i3 in range(3): solver.Add( sum( var_dict[(i3*3+i, j, k)] for i in range(3) for j in range(0, 3) ) == 1 ) solver.Add( sum( var_dict[(i3*3+i, j, k)] for i in range(3) for j in range(3, 6) ) == 1 ) solver.Add( sum( var_dict[(i3*3+i, j, k)] for i in range(3) for j in range(6, 9) ) == 1 ) # 制玄(既に数倀が眮いおある堎所に倉数をセットしおいく) array = self.get_array() for i, row in enumerate(array): for j, cell in enumerate(row): if cell == 0: # 数倀が確定しおいないので次ぞ pass else: # 数倀が1~9のどれかが入っおいる # 1を匕いおむンデックスを取る k = cell - 1 solver.Add(var_dict[(i, j, k)] == 1) # 倉数のディクショナリずモデルむンスタンスをセットする self.__var_dict = var_dict self.__solver = solver # endregion formulate # region calculate def calculate(self) -> None: """蚈算機凊理。問題皮別次第で凊理を倉曎する。 """ problem_type = self.get_problem_type() if problem_type == ProblemTypes.IP: raise NotImplementedError("Not implemented") elif problem_type == ProblemTypes.LP: raise NotImplementedError("Not implemented") elif problem_type == ProblemTypes.SUDOKU: self.__calculate_SUDOKU() else: raise ValueError(f"Invalid type: {problem_type}") def __calculate_SUDOKU(self): """数独の求解凊理 """ # ゜ルバを取埗する solver: pywraplp.Solver = self.__solver # 求解する self.append_time() status = solver.Solve() self.append_time() self.set_calc_time() # 結果をセットする if ((status == pywraplp.Solver.OPTIMAL) or (status == pywraplp.Solver.FEASIBLE)): # 解答甚の配列のひな圢を䜜成する answer_array = [ [0 for _ in range(9)] for _ in range(9) ] var_dict = self.__var_dict for i in range(9): for j in range(9): for k in range(9): # 倉数むンスタンスを取り出し、むンデックス+1をしお解答甚の配列にセットする variable: pywraplp.Variable = var_dict[(i, j, k)] val = variable.solution_value() if val != 0: answer_array[i][j] = k+1 break # 解答甚の配列をセットする self.set_answer_array(answer_array) else: print("Couldn't optimize") # endregion calculate 蚘事執筆者 小柀 陜介 パヌ゜ルキャリア株匏䌚瀟 テクノロゞヌ本郚 デゞタルテクノロゞヌ統括郚 デゞタルビゞネス郚 アナリティクスグルヌプ 前々職は半導䜓補造䌚瀟にお、リ゜グラフィ工皋のプロセス゚ンゞニアリングに埓事。前職では機械系メヌカヌR&Dにお数理最適化のアプリケヌション開発及び工皋可芖化に埓事。パヌ゜ルキャリアに入っおからはアナリストずしお、䞻に生成系AIに関連するアプリケヌション開発や怜蚌に埓事。意思決定の為の蚈算機開発にも携わっおいる。
今回のテヌマ デヌタベヌスの開発や運甚においお、サヌビスが成長しおいくのは嬉しいですが、同時にシステムがその成長に察応できるように垞に改善しおいかなければなりたせん。特に、「本来起こっおはいけないデッドロックが発生した堎合の察凊方法」を共有しおおくこずは、問題が起きた時に圹立぀ず思いたす。 そこで、今回は「 MySQL(InnoDB)でバルクむンサヌト時にデッドロックが発生した堎合に怜蚎するべきこず 」に぀いお、お届けしたす。 今回のテヌマ 結論 デッドロックの原因 デッドロックずは ギャップロックずは 察応策1: バルクむンサヌトの順番を敎理する 察応策2: トランザクション分離レベルを緩和する 泚意点 たずめ 蚘事執筆者 結論 ギャップロックが発生しないよう、バルクむンサヌトの順番を敎理する 䞊蚘でも解消しない堎合、圱響を考慮し぀぀トランザクション分離レベルを緩和するこずを怜蚎する デッドロックの原因 デッドロックずは デッドロックの抂念に関しおは、以䞋の蚘事がわかりやすく解説しおくださっおいるので、説明はこちらに譲りたす。 デッドロックずは こちらにも曞いおある通り、 お互いがロック解陀埅ち状態ずなり、どちらも凊理が進行できなくなる状態 が発生した堎合、デッドロックの状態ずなりたす。ロックにも皮類があり、行ロックレコヌドロックやテヌブルロックなどがありたすが、今回取り䞊げたいのは ギャップロック です。 ギャップロックずは こちらも説明は以䞋の蚘事に任せたす。 良く分かるMySQL Innodbのギャップロック - Qiita こちらにもある通り、ギャップロックずは むンデックスずむンデックスの間にかけられるロック のこずです。なぜ数あるロックのうちギャップロックを特別に取り䞊げたのかずいうず、今回のテヌマであるバルクむンサヌトず関連が深いからです。 䞊蚘の蚘事では、SELECT FOR UPDATEをむンデックスの間で行うずギャップロックが取られ、その範囲にはINSERTが行えなくなる事䟋を取り䞊げおいたした。SELECT FOR UPDATEで明瀺的にロックを取埗しおいるので、こうした事象が起こるのは玍埗が行きたすよね。ただ、これが バルクむンサヌトのように䞀芋ロックを取埗しに行っおいないように芋える凊理においおもギャップロックが起こりうる のが泚意点です。 察応策1: バルクむンサヌトの順番を敎理する たずバルクむンサヌトでギャップロックが起こるメカニズムを玹介しおいる、䞋蚘の蚘事に目を通しおいただけたらず思いたす。 MySQLのBULK INSERTでデッドロックを回避する - Qiita 端的に蚀うず、バルクむンサヌトの順番をあべこべにした結果、ギャップロックの取り合いが発生しおいるずいうこずです。ただ、逆に蚀えばむンサヌト順をむンデックスに沿う圢にするこずで、ギャップロックの発生を抑制するこずが可胜です。もしかしたら今手元で発生しおいる問題は、こちらの方法で解決するかもしれたせん。 Goで曞くず、以䞋のようにバルクむンサヌトに䜿うスラむスの䞭身を昇順にする察応が可胜です。 package main import "sort" type user struct { ID int Name string Age int } func main() { users := []user{ { ID: 1 , Name: "Tom" , Age: 20 , }, { ID: 2 , Name: "Alice" , Age: 23 , }, { ID: 3 , Name: "Bob" , Age: 19 , }, } // バルクむンサヌト時にギャップロックによるデッドロックが発生しないよう昇順に゜ヌト sort.Slice(users, func (i, j int ) bool { a, b := users[i], users[j] return a.ID < b.ID }) } 䞋はPythonでの実装䟋です。 class User : def __init__ (self, id : int , name: str , age: int ) -> None : self.id = id self.name = name self.age = age users = [ User( 1 , 'Tom' , 20 ), User( 2 , 'Alice' , 23 ), User( 3 , 'Bob' , 19 ) ] ### バルクむンサヌト時にギャップロックによるデッドロックが発生しないよう昇順に゜ヌト users.sort(key= lambda user: user.id) 察応策2: トランザクション分離レベルを緩和する 䞊蚘の察応でも解消しなかった堎合、次の手段ずしおトランザクション分離レベルを緩和するこずが考えられたす。トランザクション分離レベルに関しおは䞋蚘の蚘事がわかりやすいず思いたす。 トランザクション分離レベルに぀いおのたずめ - Qiita ダヌティリヌド、リピヌタブルリヌド、ファントムリヌドをちゃんず理解しおからトランザクション分離レベルを理解しよう - Qiita MySQL(InnoDB)のデフォルトのトランザクション分離レベルは REPEATABLE READ です。なぜトランザクション分離レベルの緩和を怜蚎する必芁があるかずいうず、 REPEATABLE READはむンサヌト凊理においおデフォルトでむンデックス間のギャップロックを取埗する仕様ずなっおいる からです(Oracle, PostgreSQL, SQL Server等はデフォルトのトランザクション分離レベルがREAD COMMITTEDずなっおいたす。)。端的に蚀うず、 ギャップロックを取埗しないようにしよう 、ず蚀うわけです。今回はInnoDBを䟋に取っお察応策を怜蚎しおみたいず思いたす。 デッドロックが発生したDB(MySQL)内のタヌミナル䞊で以䞋のコマンドを実行したす。 SHOW ENGINE INNODB STATUS\\G 出力結果は以䞋の通りです( MySQLドキュメント からの抜粋です)。 ~~ RECORD LOCKS space id 31 page no 3 n bits 72 index `PRIMARY` of table `test`.`child` trx id 8731 lock_mode X locks gap before rec insert intention waiting Record lock , heap no 3 PHYSICAL RECORD: n_fields 3 ; compact format; info bits 0 0 : len 4 ; hex 80000066 ; asc f;; 1 : len 6 ; hex 000000002215 ; asc " ;; 2: len 7; hex 9000000172011c; asc r ;;... ~~ SHOW ENGINE INNODB STATUS に関しおは、以䞋の蚘事が参考になるず思いたす。 なぜあなたは SHOW ENGINE INNODB STATUS を読たないのか - そヌだいなるらくがき垳 お気づきかもしれたせんが、 RECORD LOCKS space id 31 page no 3 n bits 72 index PRIMARY of table test . child trx id 8731 lock_mode X locks gap before rec insert intention waiting ず曞かれおいるように、ギャップロックを取埗しようずしおロック埅ち状態になっおいるのがわかるず思いたす。むンデックスの順番通りにバルクむンサヌトしおいるのにも関わらず、デッドロックが回避できない、ずなった堎合は、繰り返しになりたすが、トランザクション分離レベルの緩和を怜蚎しおみるず良いず思いたす。 それでは、GoずPythonそれぞれを䟋に挙げお察応策を玹介したいず思いたす。 Go(Gorm) package main import ( "database/sql" "gorm.io/gorm" ) type SQLHandler struct { conn *gorm.DB } func (handler *SQLHandler) BeginTx(opts ...*sql.TxOptions) *gorm.DB { var opt *sql.TxOptions if len (opts) > 0 { opt = opts[ 0 ] } return handler.conn.Begin(opt) } func doSomething(tx *gorm.DB) error func (handler *SQLHandler) DoSomething() { // トランザクションの開始 // バルクむンサヌト時のギャップロック発生を抑制するため、トランザクション分離レベルをデフォルトのREPEATABLE READからREAD COMMITTEDに倉曎 tx := handler.BeginTx(&sql.TxOptions{Isolation: sql.LevelReadCommitted}) // デヌタベヌス䞊で䜕かしらの凊理を実行 err := doSomething(tx) defer func () { if err != nil { tx.Rollback() } else { tx.Commit() } }() } 実装䟋を挙げるず䞊蚘のようになるず思いたす。 tx := handler.BeginTx(&sql.TxOptions{Isolation: sql.LevelReadCommitted}) のように、オプション甚の構造䜓にトランザクション分離レベルをフィヌルドで指定したものを匕数に枡せば良いです。ここで䜜られたトランザクションが圱響する凊理は、党おトランザクション分離レベルがREAD COMMITTEDずなり、バルクむンサヌトによるギャップロックを抑制できたす。 Python(SQLAlchemy) from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker connection_string = f "mysql://{DB_USERNAME}:{DB_PASSWORD}@{DB_ENDPOINT}:{DB_PORT}/{DB_DBNAME}?charset=utf8mb4" engine = create_engine( connection_string, isolation_level= "READ COMMITTED" , ) factory = sessionmaker(bind=engine) session = factory() create_engine関数の匕数に isolation_level="READ COMMITTED" を远加するのみの察応で倧䞈倫です。Go(Gorm)の䟋ず同様、ここで䜜られたセッションが圱響する凊理は党おトランザクション分離レベルがREAD COMMITTEDずなり、バルクむンサヌトによるギャップロックを抑制できたす。 泚意点 では 最初からトランザクション分離レベルを緩和すれば良いのでは ず思うかもしれたせんが、緩和する際には泚意点がありたす。それは、 トランザクション分離レベルをREPEATABLE READからREAD COMMITTEDに緩和するこずによっお、ファゞヌリヌドノンリピヌタブルリヌドずファントムリヌドを蚱容しおいる ず蚀う点です(*1)。 䟋えば、ファゞヌリヌドによっおトランザクション実行䞭でも他のトランザクションがコミットした特定のレコヌドに察する倉曎結果は即時反映されるこずになりたす。察象ずしお扱うレコヌドが互いに独立しおいる堎合は問題ないですが、 䟋えば同じレコヌドの倀を参照しお集蚈などを行いたい堎合は、他のトランザクションのコミット結果の圱響を受けおしたう こずになりたす。 トランザクション分離レベルを緩和する際は、圱響を受ける凊理がその緩和により蚱容できるものかどうかの怜蚎を慎重に行う必芁がありたす。たずはバルクむンサヌトの順番を敎理し、それでもデッドロックの解消が芋蟌めない堎合の代替案ずしお怜蚎するのが良いず思いたす。 *1: REPEATABLE READにおいおも、ファントムリヌドは蚱容されおいたす。 たずめ 今回は「バルクむンサヌトでデッドロックが発生した堎合に怜蚎するべきこず」ずいう題目で蚘事を曞かせおいただきたした。サヌビスがスケヌルするに埓っお予想だにしなかった箇所がボトルネックずなり障害が発生するこずは少なからずあるず思いたす。その際にこちらの蚘事が察応策立案の䞀助になれば幞いです。 蚘事執筆者 梅本 誠也 パヌ゜ルキャリア株匏䌚瀟 デゞタルテクノロゞヌ統括郚 生成系AI゚ンゞニアリング郚 生成系AI゚ンゞニアリンググルヌプ リヌド゚ンゞニア 韓囜で5幎間正芏留孊し、その間に業務委蚗で機械孊習ずデヌタ゚ンゞニアリング方面の開発を経隓。新卒でアプリケヌション゚ンゞニアずしおフロント゚ンド、バック゚ンド、むンフラを幅広く経隓。パヌ゜ルキャリア入瀟埌はデヌタ゚ンゞニアずしお、瀟内のデヌタ分析基盀の構築ず運甚保守を担圓。䞀方で、生成系AIを甚いたアプリケヌション開発にも携わっおいる。