ãã®èšäºã¯ Safie Engineers' Blog! Advent Calendar 17æ¥ç®ã®èšäºã§ãã ã¯ããã« ã»ãŒãã£ãŒæ ªåŒäŒç€Ÿ AIéçºéšã§ããã¯ãªãŒããåããæ©æ¬ã§ãã æ¬èšäºã§ã¯ãç§ã2025幎ã®1幎éãéã㊠èšèšã»å®æœããŠããAIéçºéšã®æè¡ããŒãã£ã³ã°ã®åãçµã¿ã«ã€ããŠã玹ä»ããŸãã ãããã®ããŒãã£ã³ã°ã¯ãããã¯ãªãŒããšããŠæ²ãã ãç¶ç¶çãªåŠã³ãšæé·ã®æ©äŒãæäŸããçµç¹å
šäœã®æè¡åãåºäžãããã ãšããç®çã®ããšäŒç»ããŸããã å
·äœçã«ã¯ã以äžã®4ã€ã®æŽ»åã軞ãšããŠéçšããŠããŸãã è«æèªã¿ ïŒéé± 30åïŒ ã³ãŒãèªã¿ ïŒéé± 30åïŒ ååŒ·äŒ ïŒéé± 1æéïŒ ææçºè¡šäŒ ïŒéé± 1æéïŒ ããããã®ããŒãã£ã³ã°ã«èŸŒããæå³ãšã2025幎ã®å®æœç¶æ³ã«ã€ããŠè©³ããã話ãããŸãã ã¯ããã« è«æèªã¿ â ãšããžã§ã®ãªã¢ã«ã¿ã€ã åŠç â¡ æ åè§£æ ⢠Multimodal & Reasoning ã³ãŒãèªã¿ ååŒ·äŒ â ãšã³ãžãã¢ãªã³ã°ãã©ã¯ãã£ã¹ã»ããã¥ã¡ã³ããŒã·ã§ã³ â¡ ãœãããŠã§ã¢èšèš ⢠ãã¹ãã»å質ä¿èšŒ ⣠Pythonãšã³ã·ã¹ãã ã»æè¡ã¹ã¿ã㯠†çµç¹è«ã»ãã£ãªã¢ ææçºè¡šäŒ ãŸãšã è«æèªã¿ AIéçºéšã§ã¯ãæ¥é²ææ©ã§é²åããAIæè¡ããã¬ã³ããçŽ æ©ããã£ããã¢ããããããã補åéçºãžéå
ããããšãç®æããŠããŸãããããã£ãŠãæ¥å課é¡ã«é¢é£ããè«æã調æ»ããåžžã«ææ°ã®ååãææ¡ãç¶ããå§¿å¢ã¯äžå¯æ¬ ã§ãã ãŸããèªãã å
容ãããŒã ã«ã¢ãŠããããããããšã¯ãçºè¡šè
èªèº«ã®çè§£ãæ·±ããã ãã§ãªããèãæãšãªãã¡ã³ããŒã®ç¥èŠæ¡å€§ã«ãå¯äžããŸãã 2025幎ã¯ãããŒã å
šäœã§èš31æ¬ã®è«æãåãäžããè°è«ãè¡ããŸãããä»å¹Žã®éžå®ããŒããæ¯ãè¿ããšãåœç€Ÿã®æ åãã©ãããã©ãŒã äºæ¥ã«çŽçµãã以äžã®3åéãäžå¿ãšãªããŸããã â ãšããžã§ã®ãªã¢ã«ã¿ã€ã åŠç ãªã¢ã«ã¿ã€ã æ§ãæ±ãããããšããžããã€ã¹ïŒã«ã¡ã©ïŒå
ã«ãããŠãæšè«ç²ŸåºŠãšåŠçå¹çãäž¡ç«ãããæè¡ã§ãã ææ°ã®ç©äœæ€åº: YOLOv12, YOLOv13, YOLOE ãªã©ãé«éãã€é«ç²ŸåºŠãªæ€åºã¢ã㫠軜éåã»é«éå: MobileMambaãéååæè¡ãªã©ãéããããªãœãŒã¹ã§é«æ§èœãªã¢ãã«ã皌åãããææ³ é«åºŠãªãã©ããã³ã°: æ··éç°å¢äžã§ã®äººç©è¿œè·¡ããIDã¹ã€ããã®æå¶æè¡ â¡ æ åè§£æ æ åãããªããžã§ã¯ããç°åžžããæ°å€ã»æ§é åããŒã¿ããšããŠæ£ç¢ºã«æœåºããæè¡ã§ãã ç°åžžæ€ç¥ã»å®å
šç®¡ç: 建èšçŸå Žã®å®å
šç¢ºèªããé²ç¯çšéã§ã®å±éºå¯ç¥èœåã®åäž 3D埩å
ã»æ·±åºŠæšå®: CameraHMR, Depth Anything V2ãªã©ãåçŒã«ã¡ã©ã®2Dæ åããã人ç©ã®å§¿å¢ã空éã®å¥¥è¡ãã埩å
ããé«åºŠãªå€æã«ã€ãªããæè¡ ⢠Multimodal & Reasoning æ°å€ããŒã¿ã®æœåºã«çãŸãããLLM/VLMãçšããŠæ åã®ãæèãæå³ããçè§£ã»æšè«ããæè¡ã§ãã æ åçè§£ã®æ·±å: InternVideo2, MM-VIDãªã©ãé·æéæ åãããäœãèµ·ããŠãããããèšèªåããæ€çŽ¢ãèŠçŽãå¯èœã«ããåºç€æè¡ã æšè«èœåã®åŒ·å: DeepSeek-R1, Chain of Draftãªã©ãAIãæèãæ·±ãèªã¿è§£ãããã«ã·ããŒã·ã§ã³ãæããŠç¢ºãããã倿ãäžãããã®åºç€ç ç©¶ ã³ãŒãèªã¿ ãããã¯ããšã³ãžãã¢ã«ãšã£ãŠãèšèšåããã³å®è£
åã®åäžã¯æ¥µããŠéèŠã§ãã æ¥åžžæ¥åã®é²æç®¡çã ãã§ã¯ãã³ãŒãã¬ãã«ãŸã§èžã¿èŸŒãã å質ã工倫ãå
±æãããããšã¯å°é£ã§ãããŸããPull Requestäžã®ã¬ãã¥ãŒã ãã§ã¯ãã¬ãã¥ã¢ä»¥å€ã®ã¡ã³ããŒãžã®ãã¬ããžå
±æãäžè¶³ããã¡ã§ãããšããèª²é¡æããããŸããã ããã§ãä»è
ã®åªããèšèšãå®è£
ã«è§Šããããšã§ãèªåãæ¡çšããŠããè¯ãã³ãŒããæžãããããšããæèãé«ããèªç¶ãšãã¹ããã©ã¯ãã£ã¹ãå
±æã»å®è·µããããªãæåãç®æããŸããã 2025幎ã¯ã èš22å ã®ã³ãŒãèªã¿ã宿œããå®è£
ã®ãã¹ããã©ã¯ãã£ã¹ã«ã€ããŠè°è«ãæ·±ããŸããã ååŒ·äŒ è«æèªã¿ã§åŸãæå
端ã®ç¥èããå®çšçãªãããã¯ããšããŠèœãšã蟌ãããã®ããšã³ãžãã¢ãªã³ã°åããé«ããã¹ããå€å²ã«ãããããŒãã«åãçµã¿ãŸããã â ãšã³ãžãã¢ãªã³ã°ãã©ã¯ãã£ã¹ã»ããã¥ã¡ã³ããŒã·ã§ã³ ã³ãŒããæžã以åã®ãã©ãäŒãããããã©ãã¬ãã¥ãŒãããããšããåºç€ã¹ãã«ã«çŠç¹ãåœãŠãŸããã Google Engineering Practice Google Technical Writing Course (One / Two / Error Message) èããæè¡ã»æžãæè¡ â¡ ãœãããŠã§ã¢èšèš å
ç¢ã§ä¿å®æ§ã®é«ããœãããŠã§ã¢ãäœãããã®èšèšçè«ã«ã€ããŠåŠã³ãŸããã ã¯ãªãŒã³ã¢ãŒããã¯ã㣠ãã¡ã€ã³é§åèšèš ãã¶ã€ã³ãã¿ãŒã³ ⢠ãã¹ãã»å質ä¿èšŒ ã³ãŒãã®ä¿¡é Œæ§ãæ
ä¿ããããã®ãã¹ãææ³ããå質ã«å¯Ÿããèãæ¹ãæ·±ããŸããã ãã¹ãã±ãŒã¹èšèš ã³ãŒãåè³ªã®ææšãšç®¡ç ⣠Pythonãšã³ã·ã¹ãã ã»æè¡ã¹ã¿ã㯠Pythonãäžå¿ãšãããããå®è£
ã«è¿ãæè¡ã¹ã¿ãã¯ãèšèªä»æ§ãå
±æããŸããã astral-sh/uv ã®æŽ»çš PyO3ãšmaturinã«ããPythonãšRustã®é£æº Pythonã³ãŒãã®ãããã¡ã€ãªã³ã°ææ³ ææ°ã®Pythonèšèªä»æ§ ã«ã©ãŒãããžã¡ã³ãã®åºç€ †çµç¹è«ã»ãã£ãªã¢ ãããŒãžã£ãŒã«ãåå ããã ããçµç¹ã®ããæ¹ããã£ãªã¢æ§ç¯ã«ã€ããŠãèŠç¹ãåºããŸããã 髿 ¡éçããèããçµç¹ã®é²å ïœãã£ãŒã«çµç¹ãšã¯ïœ ãéç£åãšã³ãžãã¢ãããã®è±åŽïŒé¢æ¥å®ãèªããåæ§ãæŽ»ããæ¡çšé¢æ¥ã®å¿åŸ ææçºè¡šäŒ 2025幎12æçŸåšãAIéçºéšã¯13åäœå¶ãšãªããçµç¹èŠæš¡ãæ¡å€§ããŸããã 人æ°ãå¢ããã«ã€ããéçºæ¥åã«ãããŠããäºããäœãããŠããã®ã詳现ãŸã§æŽã¿ã«ããããšããç¶æ
ãçããã¡ã§ãã ãã®ããŒãã£ã³ã°ã¯ãéçºã®ææãããçšåºŠãŸãšãŸã£ã段éã§ãåã¡ã³ããŒãå®åã«ãããææãçºè¡šããå ŽãšããŠèšããŸãããçºè¡šè
ã«ãšã£ãŠã¯ããããžã§ã¯ãã®æçŸ©ã»ç®çã»ææïŒäºæ¥è²¢ç®ïŒãæ¹ããŠèšèªåããæ©äŒãšãªããŸãã 仲éã®ææã詳ããç¥ãããšã¯ãããŒã å
šäœã®ã¢ãããŒã·ã§ã³ãé«ãããšãšãã«ãçžäºçè§£ãšé£æºã®åŒ·åã«ã€ãªãã£ãŠãããšæããŠããŸãã ãŸãšã 2025å¹Žã®æŽ»åãæ¯ãè¿ããšããããã®ããŒãã£ã³ã°ã¯åãªãç¥èã®ã€ã³ãããã«ãšã©ãŸããããè«æããŒã¹ã®æå
端æè¡ãã確ããªãšã³ãžãã¢ãªã³ã°åã§ãçå®ã«è£œåãžèœãšã蟌ãã§ããããšãããAIéçºéšãããæåã®éžæã«ã€ãªãããŸããã ä»åŸããã®ãµã€ã¯ã«ãå®çãããæè¡ã楜ãã¿ãªãããçæ¯ã«ãããã¯ããšåãåããçµç¹ãžãšæé·ããŠãããã°ãšæã£ãŠããŸãã
ãã®èšäºã¯ Safie Engineers' Blog! Advent Calendar 16æ¥ç®ã®èšäºã§ãã ã¿ãªããŸåããŸããŠãAIéçºéšã®è
äºã§ãã æšä»ãAIéçºã®çŸå Žã§ã¯ãåã«ç²ŸåºŠã®é«ãã¢ãã«ãäœãã ãã§ãªãã ãããã«ããŠAIããããã¯ããšããŠäœ¿ãã圢ã«ãããã ãšãããšã³ãžãã¢ãªã³ã°åãåŒ·ãæ±ããããŠãããšæããŸãã æã
AIéçºéšã«ãããŠãäŸå€ã§ã¯ãããŸããã çŽ æŽãããã¢ãã«ãã§ããŠãããããåããããã®ãµãŒããŒè²»çšãè«å€§ã§ããã°ãããžãã¹ãšããŠæç«ããªãããã§ããç¹ã«ã«ã¡ã©æ åãæ±ãå ŽåãããŒã¿éã¯èšå€§ã§ãåŠçã®é
å»¶ã¯èš±ãããŸããã ãããã«æšè«ã®å®è¡é床ãäžãããã ãã©ãããã°ã¯ã©ãŠãïŒEC2ïŒã®ã€ã³ã¹ã¿ã³ã¹ã³ã¹ããæ¥µéãŸã§å®ãã§ãããã ãããã¯ãã¢ãã«ã®ãã©ã¡ãŒã¿ãã¥ãŒãã³ã°ãšåãããããç§ãã¡ã«ãšã£ãŠéèŠãªã詊è¡é¯èª€ãã®ããŒãã§ãã ä»åã¯ãgRPCã䜿ã£ãAIæšè«ãµãŒããŒã«ãããŠå®è£
æ¹æ³ã«ããã©ããããã³ã¹ãå·®ãçããã®ãã«ã€ããŠç޹ä»ããŸãã 1. ãªããgRPCã®å®è£
æ¹æ³ã«ãã ããã®ãïŒ 2. æ³å®ã±ãŒã¹ 3. å®è£
å
±éïŒProtoå®çŸ© å
±éïŒæ¬äŒŒçãªæšè«è² è· (Heavy Task) å
±éïŒClientã®å®è£
â åæPythonã®å®è£
â¡ éåæPythonã®å®è£
⢠éåæC++ã®å®è£
4. ãã³ãããŒã¯çµæ 枬å®ç°å¢ 枬å®çµæãµã㪠èå¯ â åæPython vs â¡ éåæPython â¡åæPython vs â¢éåæC++ ãŸãšã æ®ããã課é¡ãšä»åŸã®å±æ PoCãããããã¯ããž 1. ãªããgRPCã®å®è£
æ¹æ³ã«ãã ããã®ãïŒ AIæšè«ãµãŒããŒã®ã³ã¹ãæ§é ãèããæãæãé«äŸ¡ãªãªãœãŒã¹ã¯ãGPUãããCPUãã§ãã ããããäžè¬çãªWebãµãŒããŒã®å®è£
ïŒåæåŠçïŒã§ã¯ãéä¿¡åŸ
ã¡ãI/OåŸ
ã¡ã®éããã®é«äŸ¡ãªãªãœãŒã¹ããåŸ
ã¡ãŒããããããŠããŸããŸãã åæåŠçã®ç¡é§: ãããŒã¿åä¿¡åŸ
ã¡ãã®éãCPUã¯éãã§ããïŒã®ã«èª²éãããïŒã Pythonã®éç: éåæã«ããŠããGILïŒGlobal Interpreter LockïŒã®å¶çŽã§ããã«ãã³ã¢CPUãç©ãã é«äŸ¡ãªã€ã³ã¹ã¿ã³ã¹ã䜿ã£ãŠãã1ã³ã¢ãã䜿ãåããªãã ããã§ã¯ãããã髿§èœãªEC2ã€ã³ã¹ã¿ã³ã¹ãå¥çŽããŠããã¹ã«ãŒãããïŒåŠçã§ããã«ã¡ã©å°æ°ïŒã¯äŒžã³ããã³ã¹ãã°ãããèšãäžãã£ãŠããŸããŸãã ãé«äŸ¡ãªã³ã³ãã¥ãŒããªãœãŒã¹ãã1ããªç§ãããšãéã°ãããæ¥µéãŸã§äœ¿ãåãã«ã¯ã©ãããã°ãããïŒã ãã®çããèŠã€ããããã«ãä»å㯠â åæPython ã â¡éåæPython ã â¢éåæC++ ã®3ãã¿ãŒã³ãå®è£
ããããããã®ããã©ãŒãã³ã¹ãšã³ã¹ãå¹çã培åºçã«æ¯èŒããŸããã ãªãREST APIãWebSocketã§ã¯ãªããgRPCãªã®ãïŒ ä»åã®ããªã¢ã«ã¿ã€ã æ åè§£æãã«ãããŠãgRPCãæ¡çšããçç±ã¯äž»ã«2ç¹ãããŸãã Bidirectional StreamingïŒåæ¹åã¹ããªãŒãã³ã°ïŒ: HTTP/1.1ïŒRESTïŒã®ãããªã1ãªã¯ãšã¹ã1ã¬ã¹ãã³ã¹ãã§ã¯ã30FPSã®æ åãéãç¶ããéã®ãªãŒããŒãããã倧ããããŸããgRPCãªããæ¥ç¶ãç¶æãããŸãŸåæ¹åã«ããŒã¿ãæµãç¶ãããããããäœé
å»¶ãªæšè«ãå¯èœã§ãã Schema DrivenïŒã¹ããŒãé§åïŒ: PythonãšC++ãšããç°ãªãèšèªéã§é«éã«é£æºããããã«ã¯ãå³å¯ãªåå®çŸ©ïŒProtobufïŒã«ããã³ãŒãèªåçæãäžå¯æ¬ ã§ãããããã«ãããæåã§ã®ããŒã¿ããŒã¹å®è£
ã«ãããã°ãæ§èœå£åãé²ããŸãã ïŒâ»gRPCèªäœã®åºç€ã«ã€ããŠã¯ã@S4nToæ§ããçŽ æµãªèšäºãæçš¿ãããŠãããŸãã®ã§ããã¡ãã䜵ããŠãåç
§ãã ããã https://qiita.com/S4nTo/items/0ff0445542538ef49a05 ïŒ ãããããã«ã¡ã©æ åãæž¡ããããããšã®åŠçã¯AIãšã³ãžãã¢ã«ä»»ããïŒããšãããã¹ã«å¯ŸããŠãæã
ããµãŒããŒãµã€ãã®æè¡éžå®ïŒãšã³ãžãã¢ãªã³ã°ïŒã§ã©ããŸã§å¿ããããããããã¯ãµãŒãã¹ã®éçšã³ã¹ãã æ°åã®äžããããã¯ååã®äž ã«åæžã§ããå¯èœæ§ãç§ããŠããã®ã§ãã 2. æ³å®ã±ãŒã¹ ä»åã®èšäºã§æ³å®ããã·ã¹ãã æ§æã¯ä»¥äžã®éãã§ãã ã¯ã©ã€ã¢ã³ã: 倿°ã®ãããã¯ãŒã¯ã«ã¡ã©ïŒãŸãã¯ã²ãŒããŠã§ã€ïŒãæ åãã¬ãŒã ãçµ¶ãéãªãéä¿¡ãç¶ããã ãµãŒããŒ: AIæšè«ãµãŒããŒïŒEC2ã€ã³ã¹ã¿ã³ã¹ïŒãåãåã£ãæ åã«å¯ŸããŠç©äœæ€åºãè¡ããBBOXïŒåº§æšïŒãªã©ã®ã¡ã¿ããŒã¿ãè¿ãã éä¿¡èŠä»¶: ãããã³ã«: gRPC (Bidirectional Streaming) åææ¥ç¶æ°: 1å°ã®ãµãŒããŒã§å¯èœãªéãå€ã é
å»¶: ãªã¢ã«ã¿ã€ã æ§ãæ±ããããããããã¥ãŒè©°ãŸãã«ããé
å»¶ã¯NGã ãã®æ§æã«ãããŠããPythonã®åæãµãŒããŒããPythonã®éåæãµãŒããŒãããããŠãC++ã®éåæãµãŒããŒãã§å®è£
ããå Žåã«ãããã©ãŒãã³ã¹ã«ã©ãã ãã®å·®ãåºãã®ããèŠãŠãããŸãã 3. å®è£
å
±éïŒProtoå®çŸ© ããããã®å®è£
ãã¿ãŒã³ã§çšããProtocolBufferã®å®çŸ©ã«ãªããŸãã ObjectDetection ãšãããµãŒãã¹ã DetectStream ãšããRPCã¡ãœãããæã€ãšãããã®ã§ããå®éã®ç»åã¹ããªãŒã ãæèããŠæžããŠããŸãããä»åã®å®è£
ã§ã¯åŠçèªäœã¯ãããŒã®Taskãå®è¡ããããäžèº«ã¯ã»ãšãã©äœ¿ãããŸããã syntax = "proto3"; package camera_ai; // ãµãŒãã¹å®çŸ© service ObjectDetection { // åæ¹åã¹ããªãŒãã³ã°: // ã¯ã©ã€ã¢ã³ãã¯æ åãã¬ãŒã ãéãç¶ãããµãŒããŒã¯æšè«çµæãè¿ãç¶ãã rpc DetectStream (stream DetectRequest) returns (stream DetectResponse) {} } // ãªã¯ãšã¹ã: ã«ã¡ã©ããã®1ãã¬ãŒã åã®ããŒã¿ message DetectRequest { // éåæåŠçã§ã¯ãªã¯ãšã¹ããšã¬ã¹ãã³ã¹ã®é åºãä¿èšŒãããªãå Žåãã // ã¯ã©ã€ã¢ã³ãåŽã§çµæããããã³ã°ãããããã«IDãå¿
é ã§ãã uint64 frame_id = 1; // ç»åããŒã¿ (JPEG/PNGçã®ãšã³ã³ãŒãæžã¿ããŒã¿ããŸãã¯RawããŒã¿) bytes image_data = 2; // å¿
èŠã«å¿ããŠç»åãµã€ãºãªã©ãå
¥ããããšããããŸããã // ã·ã³ãã«ã«ããããä»åã¯çããŠãOKã§ãã // int32 width = 3; // int32 height = 4; } // ã¬ã¹ãã³ã¹: 1ãã¬ãŒã ã«å¯Ÿããæšè«çµæ message DetectResponse { // ãªã¯ãšã¹ãã® frame_id ããã®ãŸãŸè¿ãããšã§ã // ã¯ã©ã€ã¢ã³ãã¯ã©ã®ç»åã®æšè«çµæããç¹å®ã§ããŸãã uint64 frame_id = 1; // 1æã®ç»åã«è€æ°ã®ç©äœãåã£ãŠãããã repeated ã«ããŸã repeated Object objects = 2; } // æ€åºãããåã
ã®ç©äœ message Object { string label = 1; // ã¯ã©ã¹å (äŸ: "person", "car") float confidence = 2; // 確信床 (0.0 - 1.0) BoundingBox bbox = 3; // åº§æšæ
å ± } // ããŠã³ãã£ã³ã°ããã¯ã¹ (OpenCVã®cv::Rectã«åãããŠãããšæ¥œã§ã) message BoundingBox { int32 x = 1; int32 y = 2; int32 width = 3; int32 height = 4; } å
±éïŒæ¬äŒŒçãªæšè«è² è· (Heavy Task) GPUæšè«ã¯éåæã§ãããå®éã«ã¯ç»åã®ååŠçïŒãã³ãŒãã»ãªãµã€ãºïŒãåŸåŠçïŒNMSçïŒã§Pythonã®CPUãªãœãŒã¹ã倧éã«æ¶è²»ãããŸãããã®ãé ããããã«ããã¯ããåçŸããããã sleep ã§ã¯ãªã while ã«ãŒãã§CPUãåããŸãã def heavy_inference_simulation (target_ms= 30 ): start = time.perf_counter() # æå®æéãCPUã空åãããŠè² è·ãããã while (time.perf_counter() - start) < (target_ms / 1000.0 ): pass return "Result BBOX" å
±éïŒClientã®å®è£
ãŸãã¯ãµãŒããŒã«ãããæãã»ã©ã®è² è·ããããã¯ã©ã€ã¢ã³ãã§ãã Pythonã® asyncio ã䜿ãã1å°ã®ãã·ã³ããè€æ°ã®ã«ã¡ã©æ¥ç¶ãæ¬äŒŒçã«çæããŸãã async def main (): print (f "Starting Load Test with {NUM_CLIENTS} clients for {TEST_DURATION} seconds..." ) # ã¯ã©ã€ã¢ã³ãã¿ã¹ã¯ãå
šãŠèµ·å tasks = [] for i in range (NUM_CLIENTS): tasks.append(run_single_client(i)) # å
šå¡åæã«ã¢ã¯ã»ã¹ãããšãšã©ãŒã«ãªããããã®ã§ããããã«éå§æéãããã if i % 10 == 0 : await asyncio.sleep( 0.05 ) # å
šã¿ã¹ã¯ã®å®äºãåŸ
〠await asyncio.gather(*tasks) â åæPythonã®å®è£
ãŸãã¯æ¯èŒå¯Ÿè±¡ãšãªããæšæºçãªåæå®è£
ã§ãã protobufã§å®çŸ©ããã ObjectDetectionServicer.DetectStream ã«ã¹ããªãŒã ãåããšã£ãåŸã®åŠçãæžãã°ããã ãã®ã·ã³ãã«ãªå®è£
ã«ãªããŸãã concurrent.futures.ThreadPoolExecutor ã䜿ãã1æ¥ç¶ã«ã€ã1ã¹ã¬ãããå²ãåœãŠãŸãã ç¹åŸŽ: å®è£
ã¯äžçªç°¡åã 匱ç¹: max_workers ïŒã¹ã¬ããæ°ïŒãæ¥ç¶äžéã«ãªãããã以äžã®æ¥ç¶ã¯ãã¥ãŒåŸ
ã¡ã«ãªããé
å»¶ãæ¿å¢ããã class ObjectDetectionServicer (pb_grpc.ObjectDetectionServicer): def DetectStream (self, request_iterator, context): """ åæ¹åã¹ããªãŒãã³ã°ã®å®è£
ã request_iterator: ã¯ã©ã€ã¢ã³ãããéãããŠãããªã¯ãšã¹ãã®ã€ãã¬ãŒã¿ """ print (f "[{time.ctime()}] New connection established." ) # ã¯ã©ã€ã¢ã³ããã stream ã§éãããŠããããŒã¿ã1ã€ãã€åŠç for request in request_iterator: frame_id = request.frame_id img_data = request.image_data # ããã«ç»åããŒã¿(bytes)ãå
¥ã # --- ããã§æ¬æ¥ã¯æšè«ãè¡ã --- # ä»åã¯ãããŒã®æšè«æéãèšãã(äŸ: 30ms) heavy_inference_simulation(target_ms= 30 ) # ãããŒã®çµæãäœæ print (f "Sync processing frame_id: {frame_id}" ) # ã¬ã¹ãã³ã¹ãäœæ response = pb.DetectResponse( frame_id=frame_id, objects=[ pb.Object( label= "person" , confidence=random.uniform( 0.8 , 0.99 ), bbox=pb.BoundingBox(x= 100 , y= 100 , width= 50 , height= 200 ) ) ] ) # çµæãè¿ã yield response â¡ éåæPythonã®å®è£
次ã«ã asyncio çã§ããéåæçãPythonã§ã¯ç°¡åã«å®è£
ããããšãã§ããŸãã ObjectDetectionServicer.DetectStream ã«asyncãã€ããŠéåæã«å¯Ÿå¿ããã圢ã«ãªããŸãã æšè«éšåã run_in_executor ã§ã¹ã¬ããããŒã«ã«éãããã€ãã³ãã«ãŒããæ¢ããªãããã«å·¥å€«ããŸãã ç¹åŸŽ: æ¥ç¶èªäœã¯å€§éã«ãã°ããïŒC10k察å¿ïŒã çŸå®: Pythonã® GIL (Global Interpreter Lock) ã®å¶çŽã«ãããè€æ°ã®ã¹ã¬ããã§èšç®ããããšããŠããåæã«åããCPUã³ã¢ã¯å®è³ª1ã€ã ããCPUããŠã³ããªåŠçïŒååŠççïŒãéãªããšè©°ãŸãã class ObjectDetectionServicer (object_detection_pb2_grpc.ObjectDetectionServicer): async def DetectStream (self, request_iterator, context): loop = asyncio.get_running_loop() async for request in request_iterator: # ã工倫ãéãåŠçãå¥ã¹ã¬ããã«éãããŠãã€ãã³ãã«ãŒããå®ã # ããããPythonã³ãŒãã§ãã以äžãGILã®åªçžããã¯éããããªã... await loop.run_in_executor( None , heavy_inference_simulation, 30 ) yield object_detection_pb2.DetectResponse(...) ⢠éåæC++ã®å®è£
æåŸã«ãä»åã®äž»åœ¹ã§ããC++å®è£
ã§ãã Pythonãšã¯ç°ãªãã CallDataãCompletionQueue ã«ã€ã㊠çè§£ããå¿
èŠããããããå®è£
æ¹æ³ã¯å°ãè€éã«ãªããŸãã CallDataã¯ã©ã¹ Clientãšã®1ã€æ¥ç¶ããšã®ç¶æ
ãšããŒã¿ãã管çããã¯ã©ã¹ã«ãªããŸãã éåæåŠçã§ã¯ãåŠçããã£ããäžæãããŠã¹ã¬ãããå¥ã®ä»äºã«ç§»ããããã颿°ã®ããŒã«ã«å€æ°ãã«ããŒã¿ãæ®ããŠããããšãã§ããŸããããã®ããã以äžã®æ
å ±ãããŒãã¡ã¢ãªäžã®ãªããžã§ã¯ãïŒCallDataïŒãšããŠä¿æãç¶ããŸã ã³ã³ããã¹ã: ServerContext ã Request ã Response ãªã©ã®ããŒã¿å®äœã ã¹ããŒãïŒç¶æ
ïŒ: çŸåšãã®æ¥ç¶ããæ¥ç¶åŸ
ã¡ããªã®ãããåä¿¡äžããªã®ãããéä¿¡äžããªã®ãã瀺ãç¶æ
é·ç§»ïŒã¹ããŒããã·ã³ïŒã ããžãã¯: ã€ãã³ããåãåã£ãéã«å®è¡ãã¹ãåŠçå
å®¹ïŒ Proceed ã¡ãœããïŒã CompletionQueueã¯ã©ã¹ CompletionQueue ã¯ãgRPCã©ã€ãã©ãªå
éšïŒã«ãŒãã«ããããã¯ãŒã¯å±€ïŒãšãã¢ããªã±ãŒã·ã§ã³ïŒãŠãŒã¶ãŒã³ãŒãïŒãã€ãªã é£çµ¡éè·¯ã®ãããªãã®ã§ãã éåæã§è¡ãããæäœïŒããŒã¿ã®èªã¿èŸŒã¿ãæžã蟌ã¿ãæ¥ç¶ç¢ºç«ãªã©ïŒãå®äºããéããã®éç¥ïŒã€ãã³ãïŒããã¹ãŠãã®ãã¥ãŒã«æ ŒçŽãããŸãã å®å
šã«ã¹ã¬ããã»ãŒãã§ãããè€æ°ã®ã¹ã¬ããããåæã«ã¢ã¯ã»ã¹ããŠãå®å
šã«åäœããããã«èšèšãããŠããŸãã ã¯ãŒã«ãŒã¹ã¬ããã¯ããã®ãã¥ãŒã«å¯Ÿã㊠Next() ã¡ãœãããåŒã³åºãããäœãå®äºããä»äºã¯ãªããïŒããšåãåãããŸããã€ãã³ããããã°å³åº§ã«åãåºãããªããã°ã€ãã³ããæ¥ããŸã§åŸ
æ©ïŒãããã¯ïŒããŸãã CallDataã¯ã©ã¹ã®å®è£
äŸ class CallData { public : CallData (ObjectDetection::AsyncService* service, ServerCompletionQueue* cq) : service_ (service), cq_ (cq), stream_ (&ctx_), status_ (CREATE) { // ã€ã³ã¹ã¿ã³ã¹çæãšåæã«ãæ¥ç¶åŸ
ã¡ãç¶æ
ã«å
¥ã Proceed (); } void Proceed () { if (status_ == CREATE) { // 1. CREATEç¶æ
: // gRPCã·ã¹ãã ã«å¯ŸããŠãæ¬¡ã®æ¥ç¶èŠæ±ãæ¥ããããã®CallDataã䜿ã£ãŠãããšäŸé Œããã // ã¿ã°ãšã㊠`this` (èªåèªèº«ã®ãã€ã³ã¿) ãæž¡ãã®ãå®ç³ã status_ = PROCESS; service_-> RequestDetectStream (&ctx_, &stream_, cq_, cq_, this ); } else if (status_ == PROCESS) { // 2. PROCESSç¶æ
(åææ¥ç¶å®äº): // æ°ããæ¥ç¶ã確ç«ãããç¬éã«ããã«æ¥ãã // éèŠ: 次ã®ã¯ã©ã€ã¢ã³ãã®ããã«ãæ°ãã CallData ãå³åº§ã«äœã£ãŠåŸ
æ©ããã(Factoryãã¿ãŒã³) new CallData (service_, cq_); // æåã®èªã¿èŸŒã¿ãéå§ãã // èªã¿èŸŒã¿ãçµãã£ããããŸã `this` (èªå) ãåŒã°ããããã«ã¿ã°ä»ããã status_ = READING; stream_. Read (&request_, this ); } else if (status_ == READING) { // 3. READINGç¶æ
(Readå®äº): // ã¯ã©ã€ã¢ã³ããã request_ ã«ããŒã¿ãå
¥ã£ãç¶æ
ã§ããã«æ¥ãã // --- æšè«åŠç (Mock) --- // request_.image_data() ã cv::Mat ã«å€æãããããå Žæ HeavyInferenceSimulation ( 5 ); // 5msã®éãåŠçãã·ãã¥ã¬ãŒã response_. set_frame_id (request_. frame_id ()); auto * obj = response_. add_objects (); // objã«çµæãã»ãããã // çµæãæžã蟌ã status_ = WRITING; stream_. Write (response_, this ); } else if (status_ == WRITING) { // 4. WRITINGç¶æ
(Writeå®äº): // ã¯ã©ã€ã¢ã³ããžã®éä¿¡å®äºåŸã«ããã«æ¥ãã std :: cout << "Processed frame_id: " << response_. frame_id () << std :: endl ; // ã¬ã¹ãã³ã¹ãã¯ãªã¢ããŠæ¬¡ã®ããŒã¿ãèªã response_. Clear (); status_ = READING; stream_. Read (&request_, this ); } else { // FINISHç¶æ
assert (status_ == FINISH); delete this ; // èªåã®åœ¹ç®ã¯çµãã£ãã®ã§èªæ±ºãã } } // ã¯ã©ã€ã¢ã³ãåææãªã©ã®åŸåŠççš void Finish () { status_ = FINISH; stream_. Finish (Status::OK, this ); } // å€éšããã¢ã¯ã»ã¹ããã¿ã°çšã®ã¢ã¯ã»ãµ // åŠçãæåããã(ok)ã«ãã£ãŠæåãå€ããå¶åŸ¡ãå¿
èŠ void OnEvent ( bool ok) { if (!ok) { std :: cout << "Client disconnected or finished reading/writing." << std :: endl ; Finish (); return ; } Proceed (); } ã¯ãŒã«ãŒã¹ã¬ããã®ç«ã¡äžããšCompletionQueueã®åŒã³åºãäŸ // ãµãŒããŒã®ã¡ã€ã³ã¯ã©ã¹ class ServerImpl { public : ~ ServerImpl () { server_-> Shutdown (); cq_-> Shutdown (); } void Run () { std :: string server_address ( "0.0.0.0:50051" ); ServerBuilder builder; builder. AddListeningPort (server_address, grpc:: InsecureServerCredentials ()); builder. RegisterService (&service_); // CompletionQueue (ã€ãã³ããã¥ãŒ) ã®äœæ cq_ = builder. AddCompletionQueue (); server_ = builder. BuildAndStart (); std :: cout << "Server listening on " << server_address << std :: endl ; // æåã®1ã€ç®ã® CallData ãæå
¥ããŠåŸ
ã¡åãéå§ new CallData (&service_, cq_. get ()); // ã€ãã³ãã«ãŒã void * tag; // ã€ãã³ãã«çŽä»ããã¿ã° (CallDataã®ãã€ã³ã¿ãå
¥ã) bool ok; std :: vector < std :: thread > threads; int thread_count = 15 ; // ãµãŒããŒã®CPUã³ã¢æ°ã«åãããã®ãäžè¬ç for ( int i = 0 ; i < thread_count; i++) { threads. emplace_back ([ this , i](){ std :: cout << "Worker Thread " << i << " started." << std :: endl ; void * tag; bool ok; // è€æ°ã®ã¹ã¬ããããåã cq_ (ãã¥ãŒ) ãåæã«ç£èŠããã // gRPCã®CompletionQueueã¯ã¹ã¬ããã»ãŒããªã®ã§ãç«¶åã¯å
éšã§è§£æ±ºããŠãããã while (cq_-> Next (&tag, &ok)) { // 空ããŠããã¹ã¬ãããã€ãã³ããæŸã£ãŠåŠçãå®è¡ static_cast <CallData*>(tag)-> OnEvent (ok); } }); } // å
šã¹ã¬ããã®çµäºãåŸ
ã€ïŒå®éã¯Ctrl+CããããŸã§åž°ã£ãŠããªãïŒ for ( auto & t : threads) { if (t. joinable ()) t. join (); } } ä»åã®å®è£
ã®ã€ã¡ãŒãžã以äžã«å³ç€ºããŠããŸãã C++å®è£
ã®ã€ã¡ãŒãž Clientã DetectStream ãåŒã³åºããš ComletionQueue ã«ã€ãã³ãéç¥ãããã空ããŠããWorker Threadã CallData ãåŒã³åºããŸãã CallData 㯠Proceed ã«ããèªèº«ã®ç¶æ
ãã¿ãªããåŠçãé²ããŸããç»åãæž¡ãããŠããã®ã§ããã°ãæšè«ã宿œããŠçµæã Clinet ã«è¿ããŸãã éèŠãªãã€ã³ãã¯Completion Queueãã¹ã¬ããã»ãŒãã§ãããåã¹ã¬ããããŸããã§äœ¿ãããŠããç¹ã§ããããã®ä»çµã¿ãéåæå®è¡ãå®çŸããŠãããšãããŸãã åWorker Threadã¯ç©ºããŠããé ããã€ãã³ãéç¥ã®ãã£ã CallData ãåŠçããŠãããŸãããã®ããã CallData 1 ã Worker Thread 1 ã§åŒã°ããããšãããã°ã Worker Thread N ã§åŒã°ããããšããããŸããåæåŠçãšç°ãªãã®ã¯ããã®ããã«ã¹ã¬ãããç¹å®ã®Clientã®ã¹ããªãŒã ãå æããã«ãåWorker ThreadãååããŠå€ãã®Clientã®ã¹ããªãŒã ãåŠçããããšã«ãããŸãã 4. ãã³ãããŒã¯çµæ å®éã«ããããã®å®è£
æ¹æ³ã§ã©ããããã®å·®ãåºãã®ãã確èªããŠãããŸãã æž¬å®ç°å¢ é
ç® å
容 ãã·ã³ Intel(R) Core(TM) Ultra 7 155H (1.40 GHz)ã16ã³ã¢ Python 3.10.18 CXX 17 æšè«è² è· 5mséã®ã«ãŒãåŠç ã¯ã©ã€ã¢ã³ã 30å° ã¹ããªãŒã æé 10ç§ ã¹ããªãŒã FPS 10 枬å®çµæãµã㪠åã
ãRequestãåãåãResponseãè¿ããŸã§ã®æéãèšæž¬ããçµæã以äžã«ãªããŸãã å®è£
ãã¿ãŒã³ å¹³åæé (Avg) æé (Min) æé
(Max) è©äŸ¡ â åæ Python 63823.44ms 25.03ms 127814.19ms â ç Žç¶» â¡ éåæ Python 45678.62ms 15.19ms 90461.10ms â ç Žç¶» ⢠éåæ C++ 13.157ms 5.611ms 71.566ms ð æç« 10FPSãé
å»¶ãªãåŠçããããã«ã¯ æé
Max ã100ms以äžã§ããå¿
èŠããããŸãã â¢éåæ C++ ã¯äžèšã®æ¡ä»¶ãæºããã®ã§æ¬ãã·ã³ã§ 30å°ã®ã¯ã©ã€ã¢ã³ã ããã°ãããšãã§ããããšãããããŸãã Clientæ°ã®ã¿ãå€ããŠããã æé
Max ã芳枬ããçµæã以äžã®ã°ã©ãã«ããŸããã åŠçæé(Max)ã®æ¯èŒ â åæPython ã â¡éåæPython ã 1 00msãäžåãClientæ°ã¯2ãŸã§ãªã®ã§ãæ¬ãã·ã³ã§ 2å°ã®ã¯ã©ã€ã¢ã³ã ãããã°ããªãããšãããããŸãã å®è£
æ¹æ³ã«ãã£ãŠã³ã¹ãã« 15åã®å·® ãã§ããšããçµæã«ãªããŸããã èå¯ â åæPython vs â¡ éåæPython åãPythonãåãGILã®å¶çŽäžã«ãããªãããåæçã ãã Max 127ç§ ïŒéåæçãã30ç§ä»¥äžæªåïŒãšããé
å»¶ãèšé²ããŸããã ãã®æ±ºå®çãªå·®ã¯ã ãã¹ã¬ãããå æããæéã®é·ãã ã«ãããŸãã 1. 20åã®æ€
åãš30人ã®å®¢ ä»åã®ãµãŒããŒïŒ16ã³ã¢ïŒã§ã¯ãPythonã®ããã©ã«ãèšå®ã«ãã çŽ20åã®ã¹ã¬ãã ã皌åããŠããŸããã ããã« 30å°ã®ã«ã¡ã© ãåæã«æ¥ç¶ãããšãäœãèµ·ããã§ããããã 2. åæçã®æå ïŒæ¥ç¶ïŒå æ åæå®è£
ã§ã¯ããã¹ããªãŒãã³ã°äžã®10ç§éãã¹ã¬ããããã£ãšå æãããŸãã éå§çŽåŸ: 20å°ãã€ãªãã£ãç¬éãå
šã¹ã¬ãããåãŸããŸãã åŸ
ã¡ãŒãã: æ®ã10å°ã¯ãåã®äººã®é
ä¿¡ïŒ10ç§ïŒãçµãããŸã§ã æ¥ç¶ããããšããèš±ãããåŸ
æ© ãããããŸãã çµæ: ãåŸ
ã¡æé10ç§ãïŒãåŠçæéãã確å®ããé
å»¶ãè·³ãäžãããŸããã 3. éåæçã®åå ïŒèšç®ïŒå æ éåæå®è£
ã§ã¯ãã¹ã¬ãããå æããã®ã¯ãæšè«ããŠããäžç¬ïŒ5msïŒãã ãã§ãã é«å転: 5msã§åžãç«ã€ããã20åã®ã¹ã¬ããã§30å°ã次ã
ãšãã°ãããšãã§ããŸãã çµæ: ãå
¥ãå£ã§ã®éåæãããèµ·ãããå°ãªããšãæ¥ç¶ãšããŒã¿åä¿¡ã¯ã¹ã ãŒãºã«è¡ãããŸããã â¡åæPython vs â¢éåæC++ ç¶ããŠãåããéåæã¢ãŒããã¯ãã£ããæ¡çšããŠããäž¡è
ã®æ¯èŒã§ããçµæã¯ãC++ãPythonã 1200åä»¥äž ã®é床差ã§å§åããŸããã äž¡è
ãšããã¹ã¬ããããŒã«ãã䜿ã£ãŠèšç®ã䞊ååããããšããŠããŸããããããå®éã®CPUã³ã¢ã®äœ¿ããæ¹ã¯å¯Ÿç
§çã§ãã Pythonã®éç (GIL): ã³ãŒãäžã§ã¹ã¬ããã15åç«ãŠãŠããPythonã® GIL (Global Interpreter Lock) ã®å¶çŽã«ãããåæã«Pythonã³ãŒããå®è¡ã§ããã®ã¯ åžžã«1ã¹ã¬ããã ã ã§ãã 15è»ç·ã®é«ééè·¯ãããã®ã«ã å·¥äºèŠå¶ã§ããã£ã1è»ç·ãããéè¡ã§ããªã ç¶æ
ãšåãã§ãã30å°ã®ã«ã¡ã©ããæ¥ãããŒã¿ãããã®çްã1è»ç·ã«æ®ºå°ãããããå€§æžæ»ïŒ90ç§ã®é
å»¶ïŒãçºçããŸããã C++ã®ç䟡 : GILãååšããŸããã15åã®ã¹ã¬ãããã 15åã®CPUã³ã¢ãã¹ãŠãåæã«äœ¿çš ããŠèšç®ããŸãã 15è»ç·ããã«ã«äœ¿ã£ãŠè»ããã¥ã³ãã¥ã³æµããããã30å°çšåºŠã®äº€ééã§ã¯æžæ»ãªã©èµ·ãããããããŸããã ãŸãšã æ¬èšäºã§ã¯ãåæã»éåæã®ã¢ãŒããã¯ãã£ã®éãããããŠPythonã»C++ãšããèšèªç¹æ§ã®éãããã·ã¹ãã ã®ããã©ãŒãã³ã¹ã«ã©ãã»ã©å·®ãããããããæ€èšŒããŸããã å®éšã®çµæãåãããŒããŠã§ã¢ã䜿ã£ãŠããŠããå®è£
æ¹æ³ãå€ããã ãã§ ã1å°ã®ãµãŒããŒã«å容ã§ããã«ã¡ã©å°æ°ãã15å以äžå€ããåŸã ããšã確èªã§ããŸãããããã¯ãã¯ã©ãŠãã€ã³ãã©è²»çšã1/15ã«ãªãå¯èœæ§ã瀺åããŠããããšã³ãžãã¢ãªã³ã°ã®å·¥å€«ãäºæ¥ã®åçæ§ã«çŽçµããããšã蚌æããŠããŸãã æ®ããã課é¡ãšä»åŸã®å±æ ä»åã¯ãéåæC++ã®å¯èœæ§ãã«ãã©ãŒã«ã¹ããŸããããæ€èšŒããããŠããªãããŒããæ®ãããŠããŸãã Python MultiProcessing: Pythonã®GILãšããé害ã¯ããã«ãããã»ã¹åã«ãã£ãŠåé¿ããææ®µãååšããŸããã¡ã¢ãªæ¶è²»éãšã®ãã¬ãŒããªãã«ã¯ãªããŸãããPythonã®çç£æ§ãç¶æãã€ã€æ§èœãäžããã¢ãããŒããšããŠæ€èšŒã®äŸ¡å€ããããŸãã åæC++ãšã®æ¯èŒ: ãC++ã ããéããã®ããéåæã ããéããã®ããããå³å¯ã«åãåãããããåæC++å®è£
ãšã®æ¯èŒãè峿·±ãããŒãã§ãã ããããå«ãããããªãæ€èšŒã¯ã次åã®èšäºã§ãå±ãã§ããã°ãšæããŸãã PoCãããããã¯ããž å®éã®ãããã¯ãéçºã¯ãä»åã®ãããªCPUã«ãŒãåŠçãããé¥ãã«è€éã§ãã æ åã®ãã³ãŒãããªãµã€ãºãªã©ã®ååŠçããããŠGPUãçšããæšè«åŠçãããããé
å»¶ãªããã€ãã©ã€ã³åããããã«ã NVIDIA DeepStream ã®ãããªç¹åããããŒã«ããããæŽ»çšããŠããããªãå¹çåãç®æãéããããŸãã ããããã©ã®ãããªææ®µãéžã¶ã«ãããæ¬è³ªã¯å€ãããŸããã AIéçºè
ãã¢ãã«ã®ç²ŸåºŠã ãã§ãªãã ãå®è¡é床ãããéçšã³ã¹ãããæèããèšèš ãè¡ãããšã ãã®ãšã³ãžãã¢ãªã³ã°ãžã®æèããããAIãåãªãPoCïŒæŠå¿µå®èšŒïŒã§çµãããããæç¶å¯èœãªããžãã¹äŸ¡å€ãçãããããã¯ãããžãšæè¯ãããéµã«ãªãã®ã§ãã
ãã®èšäºã¯Â Safie Engineers' Blog! Advent Calendar  ã®15æ¥ç®ã®èšäºã§ãã ã¯ããã« ããã«ã¡ã¯ãã»ãŒãã£ãŒ ã§ãµãŒããŒãµã€ããšã³ãžãã¢ãããŠããéæãšãããŸãã ä»å㯠AWS ECS Blue/Greenãããã€ããµãŒãã¹ã«å°å
¥ããŠã¿ãã®ã§ããã¡ãã«ã€ããŠå
±æãããŠãã ããã AWS ECS Blue/Green ãããã€ã¯ä»å¹Žã«ãªã£ãŠæå¹åãããæ©èœã§ãä»è¿ã¯ ECS ã§ã¯ããŒãªã³ã°ãªãªãŒã¹ã®ã¿ãBlue/Green ãããã€ãããå Žå㯠CodeDeployã䜿ãå¿
èŠããããŸããã ä»åã®æ©èœè¿œå ã§ãECSã®ãµãŒãã¹èšå®ã®å€æŽãšé¢é£ãªãœãŒã¹ã远å ããããšã§ãECSã®èšå®ã®ã¿ã§ Blue/Greenãããã€ãã§ããããã«ãªããŸããã ä»åãæã
ã®ããŒã ã§éçšããŠãããµãŒããŒã«ã€ããŠãé©çšããŠã¿ãŸããã ã¯ããã« èæ¯ãšã¢ãããŒã·ã§ã³ ãªãªãŒã¹ã®ææ³ ããŒãªã³ã°ãªãªãŒã¹ Blue/Green ããã〠B/G ãããã€ã®ãã㌠ECS ã«ããã B/G ãããã€ã®éžæè¢ Lifecycle Hooks ã«ãããªãªãŒã¹å®å
šæ§åäž å¶éäºé
ãšããããã€ã³ã 1. B/G â ããŒãªã³ã°ãžã®åãæ¿ãæ 2. ALBãªã¹ããŒã«ãŒã«ã®å¶é çŸç¶ã®èª²é¡ãšä»åŸã®å±æ ãããã« èæ¯ãšã¢ãããŒã·ã§ã³ çŸåšãæã
ã®ããŒã ã§ã¯ãèªèšŒãµãŒããŒã®éçšãããŠããŸãã ãã¡ãã¯å€ãã®ãµãŒãã¹ã§å©çšãããããããªãªãŒã¹ã®éã®é害ã®ãªã¹ã¯ãæå°éã«æããããšã課é¡ã§ããã ç¹ã«ãç°å¢å·®åã«èµ·å ããé害ãèæ
®æŒããªã©ã¯stagingç°å¢ã§ã®ãã§ãã¯ããæŒããããããµãŒãã¹ã®å®å®æ§ãè
ãããªã¹ã¯ãšãªã£ãŠããŸãã ãããã®èª²é¡ã解決ãããããæã
ã¯æ¢åã®ãããã€ææ³ãèŠçŽããããå®å
šæ§ã®é«ããªãªãŒã¹ããã»ã¹ãžãšæ¹åãå³ãããšã«ããæ°ãã«å°å
¥ããã Blue/Green ãããã€ãå©çšããããšã«ããŸããã ãªãªãŒã¹ã®ææ³ ããŒãªã³ã°ãªãªãŒã¹ çŸåšãECSã®ããã©ã«ãã§ããæ¡çšãããŠããã®ã¯ ããŒãªã³ã°ãªãªãŒã¹ ã§ãã äžéšã®ãµãŒããŒããæ°ããããŒãžã§ã³ã段éçã«é©çšããŠãããããã€æ¹æ³ã§ãããµãŒãã¹ã忢ããã«ãããã€ããããšãã§ããŸãã Blue/Green ãããã€ãšæ¯ã¹ããšããŒã«ããã¯ã«æéãããããäžæçã«æ°æ§ãµãŒããŒãæ··åšãããã¡ãªããã¯ãããŸãããã€ã³ãã©ã®æ§æèªäœã¯ã·ã³ãã«ã§ç®¡çããããã§ãã Blue/Green ããã〠Blue(æ§ç°å¢)ãš Green(æ°ç°å¢) ãäœæãããã©ãã£ãã¯ãåãæ¿ããããšã§ãããã€ããææ³ã§ Blueç°å¢ã¯èœãšããã«ãäžå®æéæ®ããããåé¡çºçæã®ããŠã³ã¿ã€ã ãå°ãªããªããŸããããŒãªã³ã°ãããã€ã®åãæ¿ãã«ã¯ã¿ã¹ã¯ã®èµ·åãåŸ
ã€å¿
èŠããããŸããããã©ãã£ãã¯ã®åãæ¿ãã§æžããããæ©ãããŒã«ããã¯ãã§ããŸããäžæ¹ãã€ã³ãã©ã®æ§æãå¢ãããããã€ã®è€éãã¯å¢ããŸãããŸãã管çãããªãœãŒã¹ãå¢ããŸãã èªèšŒãµãŒããŒã®ããã«ãµãŒãã¹ã¬ãã«ãé«ãããªã¹ã¯ãæå°ã«ãããå Žåã«ã¯ãããŒã«ããã¯ãæ©ã確å®ã«å®çŸã§ãã Blue/Green ãããã€ã¯æå¹ãªéžæè¢ã«ãªããšæããŸãã B/G ãããã€ã®ãã㌠B/G ãããã€ã¯ã以äžã®æé ã§é²ã¿ãŸããåé¡çºçæã® åãæ»ããã€ã³ããæç¢º ã§ãæé 5ã6ã®éã§ããã°ãå³åº§ã«Blueç°å¢ïŒæ§ç°å¢ïŒã«ãã©ãã£ãã¯ãæ»ãããšãå¯èœã§ãã åæç¶æ
: Blueç°å¢ (æ§ããŒãžã§ã³) ã«ãã©ãã£ãã¯ãæµããŠããã Greenç°å¢ (æ°ããŒãžã§ã³) ãæ§ç¯ã ãã¹ãçšãã©ãã£ãã¯ãGreenç°å¢ã«æµãã åäœæ€èšŒ ã宿œã æ¬çªãã©ãã£ãã¯ãGreenç°å¢ãžäžéšãŸãã¯å
šäœã« 段éçã«ç§»è¡ ã ãã©ãã£ãã¯ãGreenç°å¢ã« 100%åãæ¿ã ã äžå®æéã®ç£èŠåŸãBlueç°å¢ã 忢 ã åºå
ž: Amazon ECS blue/green service deployments workflow WebããŒãž https://docs.aws.amazon.com/AmazonECS/latest/developerguide/blue-green-deployment-how-it-works.html (2025幎12æ9æ¥ã¢ã¯ã»ã¹) ECS ã«ããã B/G ãããã€ã®éžæè¢ AWSã§ã¯ãECSç°å¢ã§B/Gãããã€ãå®çŸããæ¹æ³ãšããŠã以äžã®2çš®é¡ãæäŸãããŠããŸãã CodeDeploy ã䜿ã ïŒåŸæ¥ã®æ¹åŒïŒ ECS B/G ãããã€ã䜿ã ïŒECS ãµãŒãã¹èšå®ã«çµ±åãããæ°ããæ¹åŒïŒ æ¯èŒé
ç® CodeDeploy 飿º ECS B/G ããã〠(NEW) ãã©ãã£ãã¯ç§»è¡ è±å¯ (Canary, Linear, AllAtOnceãªã©æ¯çãèªç±ã«èšå®å¯èœ) çŸç¶ã¯ AllAtOnce ã®ã¿ ã èšå®ç®¡ç CodeDeployåŽã§èšå®ã ECSãµãŒãã¹å®çŸ©ã«çµ±åããã 管çããŸãšãŸã ã æŠç¥åãæ¿ã è€éã ããŒãªã³ã° â B/G ã®å€æŽããµããŒã ãããŠããæ¯èŒçæ¥œã æ€èšŒãã㯠Lifecycle Hooks (åºå®ã¿ã€ã ã¢ãŠã) Lifecycle Hooks (æè»ãªã¿ã€ã ã¢ãŠãèšå®ãå¯èœ) æã
ã¯ã èšå®ç®¡çã®å®¹æã ãšãå°æ¥ç㪠ããŒãªã³ã°ãªãªãŒã¹ãžã®åãæ»ãã®å®¹æã ãè©äŸ¡ãã ECS B/G ããã〠ãéžæããŸããã Lifecycle Hooks ã«ãããªãªãŒã¹å®å
šæ§åäž ECS B/G ãããã€ããã³ CodeDeployã«ã¯ã Lifecycle Hooks ãšããéåžžã«éèŠãªæ©èœããããŸãã ããã¯ãããã€ã®ç¹å®ã®ã¹ããŒãžïŒäŸ: ãã©ãã£ãã¯åãæ¿ãåïŒã§ãã«ã¹ã¿ã ã® æ€èšŒã¹ãããïŒAWS LambdaïŒãå®è¡ãããã®æ€èšŒãæåãããŸã§ãããã€ã®é²è¡ããããã¯ã§ããæ©èœã§ãã ããã¯ã®å©çšã€ã¡ãŒãž: æ°ããGreenç°å¢ã«ãã©ãã£ãã¯ãæµããåã«ãHealth Checkãç°¡åãªSmoke Testçšã®Lambdaãå®è¡ããç°å¢èµ·å ã®èšå®ãã¹ããªãããèªåçã«æ€èšŒã§ããŸãã ããã«ããããã©ãã£ãã¯ãæ¬çªç°å¢ã«åãæ¿ããåã«ãèšå®ãã¹ãªã©ã«ããé害ãªã¹ã¯ã倧å¹
ã«äœæžããããå®å
š ã«ãããã€ãé²ããããšãå¯èœã«ãªããŸãã Safieã§ã¯ãç°¡åãªSmoke Testçšã®Lambdaãæ¬çªãã©ãã£ãã¯åãæ¿ãåã«å®è¡ãããã§ãã¯ããäžã§ãããã€ã§ããããã«å€æŽããŸããã å¶éäºé
ãšããããã€ã³ã å°å
¥ã«ããããããã€ãã®æ³šæç¹ãšå¶éäºé
ã«çŽé¢ããŸããã 1. B/G â ããŒãªã³ã°ãžã®åãæ¿ãæ B/Gãããã€èšå®ãè§£é€ãããŒãªã³ã°ã«æ»ããçŽåŸã®ãããã€ã§ãå
éšçã«B/Gãããã€ã®èšå®ïŒäŸ: ããŒã«ïŒãåç
§ãç¶ããããšããããŸããããã®åœ±é¿ã§ãæ°èŠãããã€ãã§ããªããªãäºæ
ãçºçããŸãããïŒ1æïŒ => äžå¿
èŠãªIAMããŒã«ã®åé€ã¯æ
éã«è¡ã å¿
èŠããããŸãã 2. ALBãªã¹ããŒã«ãŒã«ã®å¶é ALBã®èšå®ã§ããªã¹ããŒã«ãŒã«æ°ã®äžéããããŸãïŒã¢ã«ãŠã³ãããªãŒãžã§ã³ã«ããç°ãªãå¯èœæ§ããïŒãB/Gãããã€ã§ã¯ãã©ãã£ãã¯åãæ¿ãã«ãªã¹ããŒã«ãŒã«ãå©çšãããããå€ãã®ãªã¹ããŒã«ãŒã«ã䜿çšããŠããæ¢åã®ALBã§ã¯ãB/Gãããã€ã®å°å
¥ãé£ããå ŽåããããŸãã çŸç¶ã®èª²é¡ãšä»åŸã®å±æ ããŒãªã³ã°ãªãªãŒã¹ãã Blue/Greenãããã€ã«åãæ¿ããããšã§ãçŽ æ©ãããŒã«ããã¯ããããã€åã®æ€èšŒãã§ããããã«ãªããŸããã ãã ããæ€èšŒã¯ããç°¡åãªãã®ã§ãç¹å®ã®ãŠãŒã¹ã±ãŒã¹ã®èæ
®æŒããã«ããŒã§ãããéžæã§ãããããã€æŠç¥ã«ãå¶éããããŸã (äŸãã°, CodeDeployãšéãã«ããªã¢ãªãªãŒã¹ã¯ã§ããªã)*1 ä»åŸã®å±æãšããŠãE2E/çµ±åãã¹ããšã®çµã¿åããããAWS ECS ä»åŸã®æ©èœè¿œå ã«åãããŠããæè»ãªãããã€ãã§ããããã«æ€èšãããããäºå®ã§ãã ããã䌌ã課é¡ããã€æ¹ãããã°ãå°å
¥ãæ€èšããŠã¿ãŠã¯ãããã§ããããïŒ ãããã« æåŸã«ãªããŸãããã»ãŒãã£ãŒã§ã¯ãšã³ãžãã¢ãç©æ¥µçã«åéããŠããŸããæ°ã«ãªãæ¹ã¯ãã¡ããã芧ãã ããïŒ https://safie.co.jp/teams/engineering/ ã«ãžã¥ã¢ã«é¢è«ããåãä»ããŠãããŸãã®ã§ãæ°è»œã«å¿åããã ããã°ãšæããŸãïŒ æåŸãŸã§ãèªã¿ããã ããããããšãããããŸããã *1 2025/10/30 ~ ã§ AWS ECS 㯠ãªãã¢ããã〠㚠ã«ããªã¢ãããã€ã®ãµããŒããéå§ããŠãŸã ( https://aws.amazon.com/jp/about-aws/whats-new/2025/10/amazon-ecs-built-in-linear-canary-deployments/ )
ãã®èšäºã¯ Safie Engineers' Blog! Advent Calendar  14æ¥ç®ã®èšäºã§ã ã¯ããã« ã¯ãããŸããŠïŒãšã³ãžãã¢ãªã³ã°ãªãã£ã¹ã®å±±åŽéº»è¡£åïŒ @ymzaki_m4 ïŒãšç³ããŸãã ã»ãŒãã£ãŒã«ã¯2025幎3æã«å
¥ç€Ÿããéçºæ¬éšã®çµç¹éçºå
šè¬ã«æºãã£ãŠããŸãã ïŒãšã³ãžãã¢ãªã³ã°ãªãã£ã¹ã®ãä»äºã«ã€ããŠã¯ãæšå¹Žã®èšäºãè¯ããã°ã芧ãã ããïŒïŒ engineers.safie.link ä»åã¯ãç§ããããŸã§åãçµãã ãçµç¹ã®æšªé£æºåŒ·åã ã«é¢ããæœçã«ã€ããŠã玹ä»ããŸãã çµç¹ã®æ¡å€§ã«ãã£ãŠçãå§ãã課é¡ãšããã®è§£æ¶ã«åããæåã®äžæ©ãçµç¹ãããžã¡ã³ãã§åããããªæ©ã¿ãæ±ããæ¹ã®ãäœãã¡ãã£ãšãããã£ããã«ãªãã°å¹žãã§ãã ã¯ãã㫠匷åãªçµç¹ã®å®çŸãžïŒèª²é¡ãæ¢ã æ¬è³ªçãªèª²é¡ãç¹å®ïŒæµ®ã圫ãã«ãªã£ã2ã€ã®å£ ãæšªã®ã€ãªããããçãïŒGL暪æããŒãã£ã³ã°ã®å®è¡ãšèšèš çµç¹å€é©ã®ç¬¬äžæ©ãšã次ã®ç®æš ããã㫠匷åãªçµç¹ã®å®çŸãžïŒèª²é¡ãæ¢ã éçºæ¬éšã®ä»å¹ŽåºŠïŒFY25ïŒã®ç®æšã®1ã€ãšããŠã ã匷åãªçµç¹ãã®å®çŸ ãæ²ããããŠããŸããã ã»ãŒãã£ãŒã®ãããªãäºæ¥æé·ãä¿é²ããããã«ã¯ãå°æ¥ã®æé·ãå®çŸãããä»èŸŒã¿ãçµç¹äœå¶ã®æŽåãé²ããå¿
èŠããããŸããã ãã®ããã«ã¯ãçŸç¶ã®æé·éåºŠã«æºè¶³ãããçµç¹æåã®éžæãåäººã®æé·æ¯æŽãæ
å ±é£æºåŒ·åãªã©ãå€é¢çãªæé·ã匷åã«æšãé²ããããšãéèŠãšãªããŸãã ããããç¶æ³äžã§å
¥ç€Ÿããç§ãã¯ããã«åãçµãã ããšã¯ãéçºæ¬éšã®éšå®€é·ãã°ã«ãŒããªãŒããŒïŒGLïŒãšã®1on1ã§ã çµç¹ã®çŸç¶ãå€è§çã«ææ¡ ããããšã§ããã çŽ3é±éãããŠèš25åã®éšå®€é·ãGLã«å¯ŸããŠãã¢ãªã³ã°ã宿œããŸããã çŸåšã®çµç¹ã®åãçµã¿ã課é¡ãªã©ã«ã€ããŠãæ¡çšããªã³ããŒãã£ã³ã°ãè²æãè©äŸ¡ãæåéžæãéçºããã»ã¹ãªã©ã®å¹
åºãåãå£ã§ã䌺ãããŸããã æ¥åã®åéãçž«ã£ãŠå¿«ãå¿ããŠãã ãããã¿ãªãããæ±ããŠããæ³ããçµç¹ã®çŸç¶ãææ¡ããããšãã§ããŸãããïŒããããšãããããŸããïŒïŒ æ¬è³ªçãªèª²é¡ãç¹å®ïŒæµ®ã圫ãã«ãªã£ã2ã€ã®å£ ãã¢ãªã³ã°å
容㯠æ§é åã»æœè±¡å ããéçºæ¬éšå
šäœã®æ¬è³ªçãªèª²é¡ãç¹å®ããŸããã ãããã®èª²é¡ãåºã«ã解決ã®ããã®éçãèããçŽè¿ã§å®æœãã¹ãå
·äœçãªæœçãçå®ããŸããã ãŸããçµç¹ãšããŠèª²é¡æã倧ãããã®ã以äžã®4ã€ã®ããŒãã«åé¡ããŸããã çµç¹éå¶ã®åºç€åŒ·å 人æè²æã»æé·ã®ä»çµã¿å æ¥åå¹çãšçç£æ§åäž çµç¹æåãšåž°å±æèã®éžæ ããã«ãçæã»äžé·æã«åé¡ãã課é¡ã®é¢é£æ§ãšæœçã®åªå
é äœãæ¢ã£ãŠãããŸããã ãã®çµæãçŽè¿ã§åãçµãã¹ã課é¡ã以äžã®2ã€ã§ãããšç¹å®ããã«è³ããŸããã çµç¹ã®æç¢ºãªæ¹åæ§ã»ããžã§ã³ãäžè¶³ããŠãã 圹å²ãæš©éãäžæç¢ºã§ã暪ã®ã€ãªãããèã ãããã®2ã€ã®èª²é¡ã解決ããŠããã«ãããããŸãã¯ãæ¢åã®ãªãœãŒã¹ã掻çšããŠããã«å®æœå¯èœã§ãçŽæ¥çã«å¹æãèŠèŸŒãããã®ãã«åãçµã¿ãçå®ã«ææãžãšã€ãªããŠãããŸããäžæ¹ã§ããæ ¹æ¬çè§£æ±ºã«æéãèŠããæ°ããªä»çµã¿ãæåã®éžæãå¿
èŠãªãã®ãã«ã€ããŠã¯ããã¯ãã£ã¹ãã£ã³ã°ã§èšç»ãçå®ãããã®äž¡èŒªã§èª²é¡è§£æ±ºãæšé²ããŸãã ããã§ããŸãçæããã®ã ãGLã®æšªé£æºåŒ·åã ã§ããã GLãšããçµç¹ã®äžæ žãæ
ãååšãç©æ¥µçã«é£æºããããšã§ãçµç¹ã®äžäœæãéžæããã°ã«ãŒããè¶
ããŠææãä»å 䟡å€ãåµåºãç¶ããããçµç¹ãç®æããããšèããŸããã ãŸããGLã®åæ°ä»¥äžããå
±é課é¡ãšããŠæããããã®ããGL圹å²ãšæš©éã®å®çŸ©ã®ææ§ããããéšéã»ããŒã éã®æ
å ±å
±æãšé£æºã®åŒ±ããã§ãããããããçµç¹ã®æ¹åæ§ã®äžæç¢ºããæšªã®ã€ãªããã®åžèãã«ã€ãªãã£ãŠãããšãèããããŸããã ãã®çæçãªåºç€åŒ·åããé·æçãªæé·ã®ããã®ãåå°ããåºããäžã§å¿
èŠã ã£ãã®ã§ãã éçºæ¬éšFY25äžæããã¯ãªãïŒ2025幎7æéå¬ïŒã§ã®èª¬æè³æããïŒäžéšæ¹å€ïŒ ãæšªã®ã€ãªããããçãïŒGL暪æããŒãã£ã³ã°ã®å®è¡ãšèšèš ãGLã®æšªé£æºåŒ·åããé²ããããã«ã ãGL暪æããŒãã£ã³ã°ã ã®å®æéå¬ãäŒç»ããŸããã ãã®äŒè°ã¯ãçµç¹ã®äžæ žãæ
ãGLããèªèº«ã®ããŒã ãè¶
ããŠçµç¹å
šäœãçè§£ããçžäºã«ååããªãããããè¯ãçµç¹ãå
±ã«åµã£ãŠããããã®ã äž»äœçãªå Ž ããšå®çŸ©ããGLã®äžã§æå¿ãåã£ãŠå§ããããšãšããŸããã äŒç»ã®æ€èšã«ããã£ãŠç¹ã«æèããç¹ã¯ä»¥äžã®4ç¹ã§ãã äžæ¹çãªæ
å ±æäŸã§ã¯ãªããåæ¹åã®å¯Ÿè©±ãã¯ãŒã¯ãäžå¿ãšããèšèšã«ãã æ¯æã®éçºæ¬éšäŒã§å®æœå
容ãå
šäœå
±æããããšã§ã掻åã®éææ§ãé«ãã ååã§ããŒããæç¢ºã«å®ããææ¥ããã®æŽ»åã«ã€ãªããã¢ãŠãããããæèãã ã¢ãŠããããã宿œåŸã¢ã³ã±ãŒããèžãŸããäŒè°èªäœã®æ¹åãç¹°ãè¿ã ãŸããç®æãç¶æ
ãšãã®ããã®ã¹ããããæèããªãããæ®µéçãªããŒãããããèšå®ããŸããã äŒè°ã¯8æããéå§ããæ1å以äžã®é »åºŠã§ç¶ç¶çã«éå¬ããŸããã ã¯ããã¯ãçžäºçè§£ãšå®å¿ã§ããå Žã®éžæããããŒãã«ãåå è
å士ã®äº€æµãéèŠããŸãããåãéããããšã«ãå®è·µãšæ¹åã®ãµã€ã¯ã«ããéèŠããå
·äœçãªçŸå Žã®èª²é¡è§£æ±ºã®ããã®è°è«ãããããžã¡ã³ãã¹ãã«åäžãæèããåŠç¿ãåãå
¥ããçµç¹ãžã®è²¢ç®ãèŠéã«å
¥ããŠãããŸããã 11ææ«ãŸã§ã§å
š6åéå¬ããŸããããåœåããGLã®ã¿ãªãããææ¬²çã«åå ããŠãã ãããäŒè°ãžã®æºè¶³åºŠãé«ãç¶æ
ãç¶æã§ããŠããŸããïŒããããšãããããŸãïŒïŒïŒ ãŸããèŠæãèžãŸããŠäŒè°ã®éå¶ãã³ã³ãã³ãã調æŽããããšã§ããããžã¡ã³ãã¹ãã«åäžãªã©ãžã®è²¢ç®åºŠãé«ããããŠããããšãã¢ã³ã±ãŒãçµæãéããŠæããããšãã§ããŸããã çµç¹å€é©ã®ç¬¬äžæ©ãšã次ã®ç®æš ãGL暪æããŒãã£ã³ã°ãã¯ãGLå士ã éšéãããŒã ãè¶
ããŠèª²é¡ãå
±æãæ¯ãåã ããã®ã暪ã®ã€ãªãããã匷åãã ã©ã€ã³ãããžã¡ã³ãèœåã®åäž ãšããææãåºå§ããŠãããšæããŠããŸãã ä»åŸã¯ããã«ãé·ææœçãšã㊠ãçµç¹ããžã§ã³ã®çå®ãšèšèªåã ãé²ããããšèããŠããŸãã ãå®è¡åãšåµé åãå
Œãåããäºæ¥æé·ã«å¿
èŠãªå€åã«è¿
éã«å¯Ÿå¿ã§ããçµç¹ããç®æãããã®æ³ããèšèªåããŠç€Ÿå
å€ã«ç€ºãããšã§ãæ³ãã«å
±æããã¡ã³ããŒãéãŸããç°æäžäœããªåŒ·ãçµç¹ãšãªãããããªãäºæ¥æé·ã«è²¢ç®ã§ããããã«åãçµãã§ãããŸãïŒ ãŸãããããŸã§ã®åãçµã¿ãéããŠãã»ãŒãã£ãŒã¯ èªãèãã倿ããè¡åããããšã§ãèªåŸçã«äŸ¡å€ãåµé ãã ã¡ã³ããŒã®ã¹ã¿ã³ã¹ã倧åã«ããŠããããšåŒ·ãæããããšãã§ããŸããã ãããããçµç¹èª²é¡ã«çæ¯ã«åãåããæ¹åããã»ã¹ãç¶ç¶çã«æšé²ããŠãããŸãã ãããã« æ¬èšäºã§ã¯ãç§ãåãçµãã çµç¹å€é©ã®ç¬¬äžæ©ã«ã€ããŠã玹ä»ããŸããã ãŸã éåã°ã§ããããããšãæ°å€ãããã®ã§ããã€ãå¥ã®æ©äŒã«ã玹ä»ã§ããã°ãšæããŸãã ã€ãã§ã«å®£äŒã§ãïŒã»ãŒãã£ãŒã§ã¯ äžç·ã«åã仲éãåéäž ã§ãïŒ å°ãã§ããèå³ãæã£ãŠããã ãããããã²ä»¥äžã®æ¡çšãµã€ããèŠããŠã¿ãŠãã ããã safie.co.jp æåŸãŸã§èªãã§ããã ããããããšãããããŸããã
ãã®èšäºã¯ ã»ãŒãã£ãŒæ ªåŒäŒç€Ÿ Advent Calendar 2025 ã®13æ¥ç®ã®èšäºã§ãïŒð ã¯ããã« ããã«ã¡ã¯ïŒ ã»ãŒãã£ãŒæ ªåŒäŒç€Ÿ åºå¹¹ã·ã¹ãã éçºéš æŠç¥ã°ã«ãŒãã®äœã
æšã§ãã çŽïŒå¹Žåãã»ãŒãã£ãŒã®äžéæ¡çšã®éžèãåããããšããŠããç§ã¯éæ¹ã«æ®ããŠããŸããã»ã»ã» ãªããªã ãã»ãŒãã£ãŒã®åºå¹¹ã·ã¹ãã éçºéšãšã¯ãªã«ãã ã«ã€ããŠã®æ
å ±ããåéèŠé
以å€ã«ã»ãŒèŠã€ããããªãã£ãããã§ãã éå»ã®ç§ãšåãããã«ãåºå¹¹ã·ã¹ãã éçºéšã«èå³ã¯ãããã©ãæ
å ±ãå
šç¶èŠåœãããªããªã»ã»ããšãå°ãã®ã¿ãªãããžãã»ãŒãã£ãŒã®åºå¹¹ã·ã¹ãã éçºéšã«ã€ããŠã玹ä»ããããšæããŸãïŒ ã¯ããã« ã»ãŒãã£ãŒã«ããããåºå¹¹ã·ã¹ãã ã åºå¹¹ã·ã¹ãã éçºéšã«ã€ã㊠åºå¹¹ã·ã¹ãã éçºéšã£ãŠã©ããªé°å²æ°ïŒ ãããã« ã»ãŒãã£ãŒã«ããããåºå¹¹ã·ã¹ãã ã ã¿ãªããã¯ãåºå¹¹ã·ã¹ãã ããšèããŠã©ããªã·ã¹ãã ãæãæµ®ãã¹ãã§ããããïŒ ã»ãŒãã£ãŒã«ãããŠãåºå¹¹ã·ã¹ãã 㯠ãäŒæ¥æŽ»åã«å¿
èŠäžå¯æ¬ ãªæå°éã®æ¥åãåãæ±ãã·ã¹ãã ã ãšå®çŸ©ãããŠããŸãã ãšèšãããŠããã¡ãã£ãšã€ã¡ãŒãžãããã«ããã§ãããã ã»ãŒãã£ãŒã¯ãã¯ã©ãŠãé²ç»ãµãŒãã¹ãšããSaaSããžãã¹ãå±éãã€ã€ãã«ã¡ã©ããã€ã¹ãªã©ã®ãã¢ãïŒããŒããŠã§ã¢ïŒããåãæ±ã£ãŠããç¹ãç¹åŸŽã§ãã ãã®ãããäŒæ¥æŽ»åã«å¿
èŠäžå¯æ¬ ãªæå°éã®æ¥åããšããŠã以äžã®ãããªé åãå®çŸ©ããŠããŸãã ãã¢ããã管çããé åïŒSCMããµãŒãã¹/補åä¿èšŒç®¡ç ããµãã¹ã¯ãªãã·ã§ã³ãã管çããé åïŒå¥çŽç®¡ç ãã¢ããããµãã¹ã¯ãããè«æ±ã管çããé åïŒè«æ±ç®¡ç å¶æ¥æŽ»åãæ¯ããé åïŒSFA/CRM äŒæ¥æŽ»åã®æ ¹å¹¹ãæ¯ããé åïŒäŒèšç®¡çãçµç¹ç®¡çãããŒã¿åæ/æŽ»çš ã§ã¯ããããã®é åã«ã€ããŠãããããã©ã®ãããªã·ã¹ãã ãå©çšããŠããã®ã§ããããïŒ å©çšã·ã¹ãã ãé åããšã«ã°ã«ãŒãã³ã°ãããšä»¥äžã®ãããªåœ¢ãšãªããŸãã ãã®ããã«æ§ã
ãªã·ã¹ãã ãçµã¿åãããªãããæ¥ã
ã®æ¥åãã²ããŠã¯é¡§å®¢ã®ã»ãŒãã£ãŒå©çšãæ¯ããŠããã®ããã»ãŒãã£ãŒã«ããããåºå¹¹ã·ã¹ãã ãã§ãã åºå¹¹ã·ã¹ãã ã«ã€ããŠã¯éå»ã®ããã¯ããã°ã§ã玹ä»ããŠããŸãã®ã§ãèå³ãæãããæ¹ã¯ãã²ãã¡ããã芧ãã ããã ãã¢ããÃããµãã¹ã¯ãæ¥åã·ã¹ãã 玹ä»ïŒ åºå¹¹ã·ã¹ãã éçºéšã«ã€ã㊠ãããŸã§ã玹ä»ããŠããåºå¹¹ã·ã¹ãã ã®ãã¡ãCRMã·ã¹ãã 矀ãå¥çŽã»è«æ±ã»äŒèšç®¡çã·ã¹ãã 矀ã管çããŠããã®ããåºå¹¹ã·ã¹ãã éçºéšãã§ãã ïŒæ³šïŒããŒã¿åæåºç€ã¯ããŒã¿ããªãã³æšé²å®€ãæ
åœããŠããããã¡ããéå»èšäºã§ç޹ä»ãããŠããŸãã What is ããŒã¿åæåºç€ ïŒ åºå¹¹ã·ã¹ãã éçºéšã®Mission㯠ãæç¶å¯èœã§æè»ãªåºå¹¹ã·ã¹ãã ãæäŸããäŒæ¥ã®æé·ãšçµå¶å¹çåãæ¯ããã ã§ãããã»ãŒãã£ãŒã®ãããªãæé·ãæ¯ããããã®åºç€ã¥ããã«åãçµãã§ããŸãã åºå¹¹ã·ã¹ãã éçºéšã¯ä»¥äžã®3ã°ã«ãŒãã§æ§æãããŠããŸãã éçºç¬¬ïŒã°ã«ãŒã éçºç¬¬ïŒã°ã«ãŒã æŠç¥ã°ã«ãŒã ããããã®ã°ã«ãŒãã®åœ¹å²ã¯ä»¥äžã®éãã§ãã éçºç¬¬ïŒã°ã«ãŒã äž»ã«Salesforceã«é¢ããéçºã»ä¿å®ãæ
åœããŠããŸãã ã»ãŒãã£ãŒã§ã¯Salesforceãå¹
åºãé åã§æŽ»çšããŠãããå¶æ¥ããã«ã¹ã¿ããŒãµããŒããŸã§ãæ§ã
ãªéšçœ²ã®æ¥åãæ¯ãã倧åãªåºç€ãšãªã£ãŠããŸãã éçºç¬¬ïŒã°ã«ãŒãã§ã¯ã瀟å
ã®èŠæãå
ã«éçºã»ãªãªãŒã¹ãè¡ã£ãŠããã»ããçŸåšã¯SCMæ¥åã®æ¹åãç®çãšãããå±±æ¡ãããžã§ã¯ããïŒè£œåã»åšåº«ç®¡çã·ã¹ãã ã®åŒ·åïŒã«å
補ã§åãçµãã§ããã瀟å
ãŠãŒã¶ãŒã§ããCSæ¬éšã®ã¡ã³ããŒãšå¯ã«é£æºããªããéçºãé²ããŠããŸãã ãŠãŒã¶ãŒéšéãšäžäœãšãªã£ãŠã®ãããžã§ã¯ãéå¶ã¯ãã»ãŒãã£ãŒã®åºå¹¹ã·ã¹ãã éçºã«ããã倧ããªééå³ã®ã²ãšã€ã§ãã éçºç¬¬ïŒã°ã«ãŒã äž»ã«ECãµã€ããZuoraãè«æ±æžç®¡çããã«é¢ããéçºã»ä¿å®ãæ
åœããŠããŸãã å¥çŽç®¡çã»è«æ±ç®¡çãšãã顧客圱é¿ã倧ããã·ã¹ãã ãæ
åœããŠãããæ¥ã
ã®ããŒã¿ã®æŽåæ§ç¢ºèªãææ¬¡æ±ºæžã®ç¢ºèªãšãã£ãéèŠãªæ¥åãå€ãæ
åœããŠããŸãã ãããã åäŒç€Ÿã®æ¥åã·ã¹ãã éçºãECãµã€ãã®ä¿å®ãªã©ãå¹
åºãé åã®ãããžã§ã¯ããæ
åœããéçºç¬¬ïŒã°ã«ãŒãã§ããã2026幎ããã¯äŒèšé åãžã®SAPå°å
¥ãè¡ããæ¬
ãããžã§ã¯ãããæ¬æ Œã¹ã¿ãŒãããã»ãŒãã£ãŒã®æé·ãæ¯ããããã®å€§ããªãããžã§ã¯ããä»åŸæ°å¹Žç¶ãèŠèŸŒã¿ã§ãã æŠç¥ã°ã«ãŒã äž»ã«åºå¹¹ã·ã¹ãã å
šäœã®æŠç¥äŒç»ããéçºãããžã§ã¯ãã«ããããããžã§ã¯ããããŒãžã£ãŒïŒPMïŒãšããŠã®åœ¹å²ãæ
åœããŠããŸãã åè¿°ã®å±±æ¡ãããžã§ã¯ãã»æ¬
ãããžã§ã¯ãã®PMããåäŒç€Ÿã®æ¥åã·ã¹ãã æ§ç¯ãããžã§ã¯ãã®PMã代çåºåãèªç€Ÿéçºã·ã¹ãã ã®ãããã¯ããããŒãžã£ãŒïŒPdMïŒãšãã£ã圢ã§ãåã¡ã³ããŒãããããã®ãããžã§ã¯ãã®æšé²åœ¹ãæ
ã£ãŠãããéšé暪æçãªèª²é¡ã®è§£æ±ºããªãŒãããŠããŸãã åºå¹¹ã·ã¹ãã éçºéšã£ãŠã©ããªé°å²æ°ïŒ ç§ãå
¥ç€ŸåŸããã«æããã®ã¯ããèœã¡çãããã ãããªäººãå€ããé°å²æ°ã§ããã äžæ¹ã§ãã·ã¹ãã ã«é¢ããè°è«ã§ã¯ããããã®ããã¯ã°ã©ãŠã³ããåºã«æ§ã
ãªæèŠãé£ã³äº€ããããããåºå¹¹ã·ã¹ãã æ§ç¯ã«åããç±ãæããæ¥ã
æããŠããŸãã ãŸããè²å
äžã®ã¡ã³ããŒãå€ããè£éåŽåå¶ãããããŠæè»ã«åè²ãŠãšäž¡ç«ããŠããã¡ã³ããŒãå€ãã§ãã ãããžã§ã¯ãåäœã§ã®æŽ»åãå€ãåºå¹¹ã·ã¹ãã éçºéšã§ãããéé±ã§éå¬ãããŠãããåºå¹¹ã·ã¹ãã éçºéšäŒãã§ã¯ãå
šå¡ãäžèšè©±ãããã§ãã¯ã€ã³ããåé ã«èšããããŠããããåäŸã®æã®å€äŒã¿ã®æãåºããèåŸã®å€¢ãçãæ¹ãã䟿å©ãªããªãŒãœããããªã©å€å²ã«ãããããŒããå
ã«ãäºãã®äººãšãªããç¥ãè¯ãæ©äŒãšãªã£ãŠããŸãã ãã«ããªã³ã°éšã«åå ããŠããã¡ã³ããŒã®å ±åãããåãããšã®ãã«ã²ã®é£Œè²ãšããœãŒããè²äŒæãã®ããã¡ã³ããŒãšèµ€ã¡ããã®ç»å Žãªã©ããç°æäžäœãã®ã»ãŒãã£ãŒãããããããããªãžã£ã³ã«ã®ãšããœãŒããé£ã³åºãç¬ããçµ¶ããªãæéã§ãç§ãæ¯åãšãŠã楜ãã¿ã«ããŠããŸãã ãããã« åºå¹¹ã·ã¹ãã éçºéšã«ã€ããŠã®ã玹ä»ã¯ãããã§ããã§ããããïŒ ãã®èšäºãèªãã çããã®åºå¹¹ã·ã¹ãã éçºéšãžã®è§£å床ãå°ãã§ãäžãã£ãŠãããããããã§ãã ã»ãŒãã£ãŒã®ãããªãæé·ãæ¯ãããããåºå¹¹ã·ã¹ãã ã¯ä»ãŸãã«é²åã®æãè¿ããŠããŸãã»ã»ã»ïŒ ãããªãæé·ãèŠæ®ãã ä»ã®ã»ãŒãã£ãŒãã ãããããå³ããããã€ãããã¯ãªåºå¹¹ã·ã¹ãã åæ§ç¯ ã«ãããªããäžç·ã«åãçµãã§ã¿ãŸãããïŒ åºå¹¹ã·ã¹ãã éçºéšã§ã¯ãäžç·ã«åããŠããã ãã仲éãçµ¶è³åéäžã§ãïŒ èå³ãæã£ãŠããã ããæ¹ã¯ããã²æ¡çšãµã€ããã芧ãã ããã safie.co.jp
ãã®èšäºã¯ Safie Engineers' Blog! Advent Calendar 12æ¥ç®ã®èšäºã§ãã ã¯ããã« ãã®ãã¹ãã³ãŒãããŸã å
šéšãæãã§æžããŠããŸããïŒ ä»ã¯ã©ããªçæAIã䜿ã£ãŠããã®ãïŒ ãªããå
šèªåãã§ã¯ãªãã®ãïŒ å®è·µïŒClaude Codeã䜿ã£ããã¹ãåèªåå4ã¹ããã ãã®ã¯ãŒã¯ãããŒãããããããæé以äžã®ã䟡å€ã ãããã«ïŒAIãšã®åæ¥ãåœããåã«ãªãæªæ¥ãž ã¯ããã« ããã«ã¡ã¯ïŒã»ãŒãã£ãŒæ ªåŒäŒç€Ÿã§ãµãŒããŒãµã€ããšã³ãžãã¢ãããŠããåäž( @Bobtaroh )ã§ããæ°å2幎ç®ãšãªããç§ãå«ãåæã®ãšã³ãžãã¢ãã¡ããããããã®é
å±å
ã§äžçæžåœã«æ¥åãããªããŠããŸãã æ¬èšäºã§ã¯ãåããæ°å2幎ç®ã§ããããã³ããšã³ãéçºãæ
åœããŠããæ±æ¢ããã«ã€ã³ã¿ãã¥ãŒãè¡ããéçºçŸå Žã§è©±é¡ã®ãClaude CodeããæŽ»çšãã ãã¹ãåèªååã®ã¯ãŒã¯ãã㌠ã«ã€ããŠç޹ä»ããŸãã ãAIã«å
šéšä»»ãããã®ã§ã¯ãªãããããŠãåèªååããéžã¶ãã®çç±ãšãå
·äœçãªå®è·µææ³ã«ã€ããŠæ·±æãããŸããã ãã®ãã¹ãã³ãŒãããŸã å
šéšãæãã§æžããŠããŸããïŒ ãã¹ãã³ãŒãã¯ãã¢ããªã±ãŒã·ã§ã³ã®å質æ
ä¿ã«äžå¯æ¬ ã§ããããã®å®è£
ã¯æãšããŠãšã³ãžãã¢ã®è² æ
ã«ãªãããšããããŸããã»ãŒãã£ãŒã®ããã³ãéçºããŒã ã§ã¯ãç¹ã«ä»¥äžã®èª²é¡ããããŸããã å€§èŠæš¡ãªãã¶ã€ã³ã·ã¹ãã ç§»è¡ããã£ãŠããŠãå·¥æ°èŠç©ããäžããã¹ããåŸåãã«ããŠãã ãã¹ããå®è£
ããç®æå€ãã£ã é
å±ãããŠããéçºããã³ã³ããŒãã³ãã40~50ã»ã©ããã1ã³ã³ããŒãã³ãããã1000è¡ã»ã©ã®ãã¹ããå¿
èŠã ã£ã ãã¹ãã®äžã«ã¯ãäœæ¥ã«è¿ãåçŽãªå®è£
ãå€ãååšãããšã³ãžãã¢ã®ã¢ãããŒã·ã§ã³ãããŸãäžããã¥ããåŽé¢ãå°ã
ãã£ã ãããã®èª²é¡ãæ±ããŠããæã«ãäžéã§ã¯Coding Agentãæ³šç®ãéãå§ããåŒç€Ÿã§ã瀟å
ããŒã«ãšããŠGeminiãClaude Codeã®å©çšç°å¢ãæŽåãããŸããããããæ©ã«ãä»åã®ãã¹ãã®åèªååã¯ãŒã¯ãããŒãçµãããšã«è³ã£ããšã®ããšã§ããã ä»ã¯ã©ããªçæAIã䜿ã£ãŠããã®ãïŒ æšä»ãClaude Code以å€ã®ããŸããŸãªçæAIãç»å ŽããŠããŸããã以äžã®4ã€ã®çæAIã«é¢ããŠãã©ã®ããã«äœ¿ãåããŠããã®ããæ±æ¢ããã«èããŠã¿ãŸããã Gemini çžæ£çãªååš Geminiåäœã§ã¿ã¹ã¯ããé¡ãããããšã¯ãªãã調ã¹ãããã®ããŒã«ãšããŠäœ¿ãããšãå€ã äŒè°äžã«åºãŠããåãããªãããšã«ã€ããŠãèãããšããããã Claude Code éšäžã«è¿ãååš ä»¥äžã®ä»äºãæããŠãã ãã¹ãã®å®è£
æ°èŠéçºã®éåœ¢äœæ è€éãªå®è£
ã®è§£èª¬äŸé Œ Github Copilot 以å䜿ã£ãŠããããä»ã¯å®å
šã«äœ¿çšããŠããªã Bedrock Chat Geminiãå°å
¥ãããåãŸã§ã¯äž»æµã ã£ãããä»ã¯äœ¿çšããŠããªã 2025幎12æçŸåšã§ã¯ãäž»ã«GeminiãšClaude Codeã䜿çšããŠãããšã®ããšã§ããã ãªããå
šèªåãã§ã¯ãªãã®ãïŒ çŸåšã®ãã¹ãåèªååã«è³ããŸã§ã«ã¯æ§ã
ãªè©Šè¡é¯èª€ããããŸããã åŒç€Ÿã§Claude Codeãå©çšå¯èœã«ãªãåãŸã§ã¯ãGithub Copilot Agentã䜿ã£ãŠãOne-shotã®ããã³ããã§ãã¹ããçæãããææ³ã詊ã¿ãŸããããããããããžã§ã¯ãåºæã®ã«ãŒã«ãå®ãããªãã£ãããæå³ããªãã³ãŒããçæãããããšãçµæãšããŠåºåã®6ã7å²ã人éãæžãçŽãããšã«ãªã£ãŠããŸããã Claude Codeãå©çšå¯èœã«ãªã£ãåœåã§ã¯ãåçãªå€åã¯ãããŸããã§ãããGithub Copilotã§Sonnet 4ã¢ãã«ã䜿çšããããšãã§ããŠãããããGithub Copilotã§å¹ã£ãä»çµã¿ããã®ãŸãŸæµçšããŠãããšã®ããšã§ããhooksãmemoryã®åæ£åã®å©çšã詊ã¿ãŸãããã管çãé£ãããããŒã éçºã«ãªããªãåããªããšããããšãããããŸããã çŸåšã§ã¯ãSubagentsãçšããŠãèšèšãå®è£
ãã¹ã¿ã€ã«ã¬ãã¥ãŒãšçµ±åã®4ã€ã«å·¥çšãåããããšã§ãåèªååãŸã§é²ããããšãã§ãããšã®ããšã§ãã å®è·µïŒClaude Codeã䜿ã£ããã¹ãåèªåå4ã¹ããã Claude Codeã䜿ã£ãåèªååã®è©³çŽ°èª¬æãããŸãã ãã®åèªååã§ã¯ã䞻㫠Subagents ã®æ©èœã䜿ã£ãŠããŸããSubagentsãšã¯ãã¡ã€ã³ã®äŒè©±ã«å·Šå³ãããã«ç¹å®ã®ã³ã³ããã¹ããä¿æããé©åãªæš©éã®ãã®ãšãç¹å®ã®é åã«ç¹åããŠç²ŸåºŠãåäžãããããšãã§ããåå©çšå¯èœãªãšãŒãžã§ã³ãã®ããšã§ããå
¬åŒãµã€ã( https://code.claude.com/docs/ja/sub-agents )ã§ã¯ã以äžã®4ã€ã®å©ç¹ãæããããŠããŸãã ã³ã³ããã¹ãã®ä¿æ ç¹åããå°éç¥è åå©çšæ§ æè»ãªæš©é ãã®æ©èœãšClaude Codeã®ãã¡ã€ã«ä»æ§ã«åŸã£ãŠã以äžã®ãã¡ã€ã«æ§æã§å®çŸããŠããŸãã .claude âââ agents # Agentã®å®çŸ©ãè©°ãŸã£ããã£ã¬ã¯ã㪠â âââ consolidate-text-fixes.md â âââ generate-test-spec.md â âââ implement-test.md â âââ investigate-test-pattern.md â âââ review-test-first.md â âââ review-test-second.md â âââ review-test-third.md â âââ search-translation-key.md âââ commands # ã¯ãŒã¯ãããŒ(ã³ãã³ã)ãå®è¡ãããå®çŸ©ãè©°ãŸã£ããã£ã¬ã¯ã㪠âââ test-workflow.md commandsãã£ã¬ã¯ããªã§å®çŸ©ããã¯ãŒã¯ãããŒ(test-worklow.md)ã§ã¯ã以äžã®ãããªæ§æã«ãªã£ãŠããŸãã ðœå®éã®test-workflow.mdã®äžèº«ãèŠãã(ãããã¯ãªãã¯ïŒ) --- name: test-workflow description: ãã¹ãèšèšã»å®è£
ã»ã¬ãã¥ãŒã®äžé£ã®ã¯ãŒã¯ãã㌠--- # ãã¹ãå®è£
ã¯ãŒã¯ãããŒç®¡çãšãŒãžã§ã³ã ãã®ãšãŒãžã§ã³ãã¯ããã¹ãã®èšèšããå®è£
ãã¬ãã¥ãŒãŸã§ã®äžé£ã®ã¯ãŒã¯ãããŒã管çããŸãã**åãã§ãŒãºã§é©åãªãµããšãŒãžã§ã³ããåŒã³åºã**ãé«å質ãªãã¹ãã³ãŒããäœæããŸãã ## ã¯ãŒã¯ãããŒæŠèŠ 1. **ãã¹ãèšèš** â 2. **ãã¹ãå®è£
** â 3A. **䞊åãã¹ãã¬ãã¥ãŒ** â 3B. **çµ±åä¿®æ£ã»æçµèª¿æŽ** â 4. **æçµç¢ºèª** ãã¹ãèšèšåŸã«ãŠãŒã¶ãŒã¬ãã¥ãŒãæ±ãããŠãŒã¶ãŒã®ä¿®æ£åŸæ¿èªãåŸãŠãããã¹ãå®è£
以éã®ãã§ãŒãºã«é²ã¿ãŸãã ## å®è¡æé ### Phase 1: ãã¹ãèšèš ð **䜿çšãšãŒãžã§ã³ã**: `generate-test-spec` 1. 察象ãã¡ã€ã«ãåæ 2. ãã¹ãèšèšæžãäœæïŒ`<fileName>ãã¹ãèšèšæž.md`ïŒ 3. **ãŠãŒã¶ãŒã«èšèšæžã®ã¬ãã¥ãŒã»ä¿®æ£ãäŸé Œ** 4. æ¿èªãåŸããæ¬¡ãã§ãŒãºãž ### Phase 2: ãã¹ãå®è£
ð» **䜿çšãšãŒãžã§ã³ã**: `implement-test` 1. ãã¹ãèšèšæžãåºã«ãã¹ãã³ãŒããå®è£
2. ãã¹ããå®è¡ããŠã«ãã¬ããžç¢ºèª 3. ãšã©ãŒãããå Žåã¯ä¿®æ£ïŒæå€§3å詊è¡ïŒ ### Phase 3A: 䞊åãã¹ãã¬ãã¥ãŒ ð 3ã€ã®ãã¹ãã¬ãã¥ãŒãšãŒãžã§ã³ãã**䞊åå®è¡**ããŠããã®çµæãçµåããåé¡ã®åæãšæ¹åæ¹éã1ã€äœæããŸãïŒ #### Review 1: åºæ¬ä¿®æ£åæ **䜿çšãšãŒãžã§ã³ã**: `review-test-first` - åçimportãgetStateãéåæåŠçãªã©ã®åºæ¬çãªåé¡ãåæ - æ¹åæ¹éãšå
·äœçãªä¿®æ£å
å®¹ãææ¡ - **ãã¡ã€ã«ä¿®æ£ããã¹ãå®è¡ã¯è¡ããªã** #### Review 2: DOMã»ãããã£ãŒã»èšå®åæ **䜿çšãšãŒãžã§ã³ã**: `review-test-second` - detectChangesãtranslate颿°ãMockStoreValueãªã©ã®åé¡ãåæ - æ¹åæ¹éãšå
·äœçãªä¿®æ£å
å®¹ãææ¡ - **ãã¡ã€ã«ä¿®æ£ããã¹ãå®è¡ã¯è¡ããªã** #### Review 3: spyOnã»é
åã»è¿œå ã«ãŒã«åæ **䜿çšãšãŒãžã§ã³ã**: `review-test-third` - å°çšãããã£ãŒãspyOné
眮ãDOMèŠçŽ ååŸãªã©ã®åé¡ãåæ - æ¹åæ¹éãšå
·äœçãªä¿®æ£å
å®¹ãææ¡ - **ãã¡ã€ã«ä¿®æ£ããã¹ãå®è¡ã¯è¡ããªã** #### ã¬ãã¥ãŒçµæãã¡ã€ã«çæ - ã¬ãã¥ãŒçµæãã¡ã€ã«å: `<fileName>ã¬ãã¥ãŒçµæ.md` - 管çã®ããã¬ãã¥ãŒå¯Ÿè±¡ãã¡ã€ã«ãšåãã£ã¬ã¯ããªã«çæ - å å·¥ã¯è¡ããåã¬ãã¥ãŒãšãŒãžã§ã³ãããè¿åŽãããçµæãçµåãã ### Phase 3B: çµ±åä¿®æ£ã»æçµèª¿æŽ ð ïž **䜿çšãšãŒãžã§ã³ã**: `consolidate-test-fixes` - **åãã§ãŒãºã§äœæããã¬ãã¥ãŒçµæãã¡ã€ã«ãæž¡ããŸã** 1. **å®éã®ä¿®æ£å®è¡**: çµ±åãããä¿®æ£èšç»ã«åŸã£ãŠãã¡ã€ã«ãä¿®æ£ 2. **ãã¹ãå®è¡**: ä¿®æ£åŸã®ãã¹ããå®è¡ããŠåäœç¢ºèª 3. **æçµèª¿æŽ**: ãšã©ãŒãããã°åå åæããŠåä¿®æ£ 4. **æçµç¢ºèª**: ããäžåºŠäžŠåãã¹ãã¬ãã¥ãŒãè¡ããä¿®æ£ãå®äºããŠãããã確èªãã 5. **ã¬ãã¥ãŒãã¡ã€ã«ã®åé€**: äžèŠã«ãªã£ãã¬ãã¥ãŒãã¡ã€ã«ãåé€ãã ### Phase 4: å®è£
æçµç¢ºèª â
ïž å®è£
å
容ãèšèšæžããä¹é¢ããå
容ã«ãªã£ãŠããªãããç¢ºèª ## 泚æäºé
### åãã§ãŒãºå
±é - ãšã©ãŒãåé¡ãçºçããå Žåã¯è©³çްããŠãŒã¶ãŒã«å ±å ### ãã¹ãå®è¡ã³ãã³ã ```bash npm run test <project> --specs=<testFile> --agent # e.g. npm run test viewer --specs=hoge.component --agent ``` YOU MUST: **ãã¹ãå®è¡æã¯å¿
ã`npm run test <project> --specs=<testFile> --agent`ã䜿çšããä»ã®ã³ãã³ãå®è¡ã詊ã¿ãªãããšãç¹ã«`--agent`ãªãã·ã§ã³ã远å ããªããšãã¹ããçµäºããŸãã** - `<project>`: ãããžã§ã¯ãåïŒ`viewer`, `myportal`, `core`, `sdk`ã®ããããïŒ - `<testFile>`: `.spec.ts`ãé€ããã¹ããã¡ã€ã«ãã¹ãäŸïŒ`example.component` ### åè³ªåºæº - ã«ãã¬ããž: 95%ä»¥äž - ãã¹ãŠã®ãã¹ãã±ãŒã¹ãæåããããš - ã³ãŒãã¹ã¿ã€ã«ããããžã§ã¯ãã®èŠçŽã«æºæ ããŠããããš ## ãã©ãã«ã·ã¥ãŒãã£ã³ã° ### ãã¹ãã倱æããå Žå 1. ãšã©ãŒã¡ãã»ãŒãžãç¢ºèª 2. consolidate-test-fixesãšãŒãžã§ã³ãã§åä¿®æ£ãè©Šè¡ 3. 3å詊è¡ããŠã解決ããªãå Žåã¯`investigate-test-pattern`ãšãŒãžã§ã³ãã䜿çšããŠåæ§ã®å®è£
ããªãã調æ»ããŠããåä¿®æ£ ### ã¬ãã¥ãŒã§åé¡ãèŠã€ãããªãå Žå 1. 該åœããã¬ãã¥ãŒãšãŒãžã§ã³ãïŒreview-test-\*ïŒãåå®è¡ 2. ç¹å®ã®åé¡ã«çŠç¹ãåœãŠãŠã¬ãã¥ãŒãæç€º 3. æ°ããªã¬ãã¥ãŒçµæã§consolidate-test-fixesãåå®è¡ å
šäœã®æµããšããŠã¯ã以äžã®4ã¹ãããã§ãã ãã¹ãèšèš ãŸã generate-test-spec ãšãŒãžã§ã³ãã察象ã³ãŒããåæãããã¹ãèšèšæžãäœæããŸããããã§éèŠãªã®ã ã人éã®æ¿èªã ãå¿
é ã«ããŠããç¹ã§ããèšèšæžããããžã§ã¯ãã®æå³ãšåèŽããŠãããããšã³ãžãã¢ã確èªããä¿®æ£ãçµãŠOKãåºãŠåããŠå®è£
ãã§ãŒãºãžé²ãããã«ããŠããŸãã ãã¹ãå®è£
æ¿èªãããèšèšæžãå
ã«ã implement-test ãšãŒãžã§ã³ããã³ãŒãã£ã³ã°ãè¡ããŸããããã§ã¯ãã¹ãã®å®è¡ãšã«ãã¬ããžç¢ºèªãŸã§ãèªåŸçã«è¡ãããšã©ãŒãåºãã°èªå·±ä¿®æ£ããããã«æç€ºããŠããŸãã ããã§å·¥å€«ããç¹ã¯ãå®è£
å
容ã«çŽæ¥é¢ä¿ããªãåŒç€Ÿç¹æã®ã«ãŒã«ïŒåœåèŠåãã¹ã¿ã€ã«ïŒã¯ãããŠãã®å·¥çšã§ã¯æç€ºããªãããšã§ããã«ãŒã«ã峿 Œã«å®ãããããšãããšãèå¿ãªåŠçã«é¢ããããžãã¯ã®ç²ŸåºŠãèœã¡ãŠããŸãåŸåããã£ãçµéšããã£ãããã§ããããã«ãã£ãŠããŸãã¯çŽç²ãªåŠçã®ã¿ã«éäžãããããšã§ãæ¬æ¥ã®ã³ãŒãã£ã³ã°ã¹ãã«ãååã«çºæ®ããŠãããã Claude Codeãèªä¿¡ãæã£ãŠ å®è£
ããŠããããããã«ãªã£ããšã®ããšã§ãã 䞊åããªãã«ã¬ãã¥ãŒ å®è£
ãããã³ãŒãã«å¯Ÿãã3ã€ã®ç°ãªãå°éå®¶ãšãŒãžã§ã³ãã 䞊åã§ ã¬ãã¥ãŒãè¡ããŸãã Reviewer A: åºæ¬çãªæ§æãéåæåŠçã®ãã§ã㯠Reviewer B: DOMæäœããããã£ãŒã®æ£ç¢ºæ§ãã§ã㯠Reviewer C: SpyOnãã¢ãã¯å®çŸ©ãªã©ãé«åºŠãªã«ãŒã«ã®ãã§ã㯠ãã®éçšã§ã¯ã2çªç®ã®ã¹ãããã®åºåçµæãããšã«ãåŠçå
容ã«ã¯é¢ä¿ãªãåŒç€Ÿç¹æã®ã«ãŒã«ã«æ²¿ã£ãŠãããã®ç¢ºèªã®ã¬ãã¥ãŒãè¡ããææ¡ã®ã¿ãè¡ããŸããã³ãŒãç·šéã¯è¡ããŸããã ããã«ãã£ãŠã以äžã®3ã€ã®ã¡ãªããããã£ããšã®ããšã§ãã è€æ°ã®é
ç®ãAgentã«æãããšã现ããèŠèœãšããå€ããªãåŸåã«ãã£ãããSubagentsã§åããããšã§ãç¹å®ã®èгç¹ã«çµãããšãã§ãã粟床ãäžãã£ã 䞊åå®è¡ããããšã§ãå®è¡é床ãåäžãã åŠçå
容ã®ã¬ãã¥ãŒã¯èæ
®ããã«ãã¹ã¿ã€ã«ã¬ãã¥ãŒã«éå®ãããããšã§ããã®éçšã§åŒç€Ÿç¹æã®ã«ãŒã«ã衚çŸãå
¥ã蟌ãããšãã§ãã çµ±åä¿®æ£ã»æçµèª¿æŽ 3å¹ã®ã¬ãã¥ã¢ãŒããäžãã£ãŠããææäºé
ã consolidate-test-fixes ãšãŒãžã§ã³ããéçŽããå®éã®ã³ãŒãä¿®æ£ã«é©çšããŸããæåŸã«æ¹ããŠãã¹ããåããèšèšæžãšã®ä¹é¢ããªããã確èªããŠå®äºãšãªããŸãã ãã®ã¯ãŒã¯ãããŒãããããããæé以äžã®ã䟡å€ã ãã®ãåèªååããå°å
¥ããçµæããã¹ãå®è£
ã«ãããæéã¯ äœæã§çŽ20%ççž® ãããŸãããæ°åã ãèŠããšåçãªå€åã§ã¯ãªãããã«èŠãããããããŸãããããããæ±æ¢ããã¯ãæéç瞮以äžã®äŸ¡å€ãããããšèªããŸãã 䞊è¡åŠçã«ããçç£æ§åäž AIãã³ãŒããæžããŠããéã人éã¯Slackã®è¿ä¿¡ãBacklogã®æŽçããããã¯ä»ã®è€éãªå®è£
ã®èå¯ãªã©ãå¥ã®ã¿ã¹ã¯ãããªããããã«ãªããŸããã0ãã1ã®é¢åãªèšè¿°ãAIãè©ä»£ããããŠãããããšã§ãè³ã®ã¡ã¢ãªãä»ã®æ¥åã«å²ããããã«ãªã£ãããã§ãã å質ã®åäž AIãšã®å¯Ÿè©±ã®äžã§ãããã®ãšããžã±ãŒã¹ã¯èæ
®ããŸãããïŒããšéã«ææãããããšããããäžäººã§æžãããããã¹ãã®ç¶²çŸ
æ§ãäžãã£ããšãããŸãã ãããã«ïŒAIãšã®åæ¥ãåœããåã«ãªãæªæ¥ãž ä»åã¯ãæ°å2幎ç®ãå®è·µãããçæAIãçšãããã¹ãåèªååã¯ãŒã¯ãããŒã«ã€ããŠç޹ä»ããŸãããä»å玹ä»ããã¯ãŒã¯ãããŒãå°å
¥ããããšã§ã2025幎6æã2025幎12æãŸã§ã«å®äºãããšããç®æšã ã£ãäºå®ãã2ã¶ææ©ãçµããããšãã§ãããšã®ããšã§ãã ä»åŸã¯ããã®ããŠããŠãããŒã å
šäœããéçºéšçœ²å
šäœã«åºãã€ã€ããããªã粟床ã®åäžã«åãçµãã§ãããããšã®ããšã§ãã ãŸããçæAIããã¹ãèªåå以å€ã®ããšã§äœ¿ã£ãŠããããåéã¯ããããèããŠã¿ãŸããã ãå匷ã«äœ¿ããããªãšæã£ãŠããŸãïŒ10æã«åºå€ããŠã10æã12æã¯ãšãŒãžã§ã³ãã«ä»»ããŠããéã«ãåªé
ã«ã³ãŒããŒã飲ã¿ãªããææ°æè¡ã®ãã£ããã¢ããã«è²»ãããããªãšæã£ãŠãŸãããããŠããã£ãšäœ¿ããšãŒãžã§ã³ããå¢ãããŠã10ã20å¹ã®Agentã«å¯ŸããŠæç€ºãåºããŠãæã£ãŠã¿ãããªãšããéæããããŸããã æåŸã«ãããããAIã䜿ãããªããããšèããŠããåŸèŒ©ãåŠçãšã³ãžãã¢ãžã®ã¢ããã€ã¹ãããããŸããã ã䜿ãããªãæ¹ãããçæAIã«èãããè¯ããšæããŸãïŒç¬ããã€ãã³ãŒãã£ã³ã°ãæµè¡ã£ãŠããŸããããã¯ããèªãåã¯åŒãç¶ãå¿
èŠã«ãªã£ãŠããã®ã§ã¯ãªãããšæã£ãŠããŸãã倧åãªã®ã¯ãAIã«äœ¿ãããã®ã§ã¯ãªãã䜿ãããªãåŽã«ãªãããšãAIãåºããŠããææç©ã«å¯ŸããŠãèªåã®é ã§èããçãã責任ãæã€ããšã³ãžãã¢ãšããŠã®ãæèåãããããããã®æä»£ããéèŠã«ãªããšæããŸããã AIã¯ãããŸã§ããŒã«ã§ãããæåŸã«å質ãä¿èšŒããã®ã¯ãšã³ãžãã¢èªèº«ã§ãããã®åœããåã®ååãå¿ããã«ãAIããè³¢ãéšäžãã®ãããªç«ã¡äœçœ®ã§æŽ»çšããååããŠããã¹ã¿ã€ã«ããããããããã®éçºã®ã¹ã¿ã³ããŒãã«ãªã£ãŠããã®ãããããŸããã ããŸæ¹ããŠãAIãšã®åãåãæ¹ãæèçã«èããããšãæãéèŠã ãšæ°ä»ããããŸããã 以äžãæ°å2幎ç®ãå®è·µãããã¹ãåèªååã«é¢ããã玹ä»ã§ããã
ãã®èšäºã¯Â Safie Engineers' Blog! Advent Calendar 2025 11æ¥ç®ã®èšäºã§ãã ã¯ããã« ä»å¹Žãæ®ããšããããšããããšãªããŸããããAIéçºéšã®ç°äžã§ãã çŸåšã¯ãè€æ°ã®ã«ã¡ã©æ åãçµ±åããŠè§£æããã·ã¹ãã ã®R&DïŒç ç©¶éçºïŒã«åãçµãã§ããŸãã ç»åèªèAIã®åéã§ã¯Pythonãäž»æµã§ããã ãPythonã§ããžãã¯ãæžããããåŠçãé
ãããŠãªã¢ã«ã¿ã€ã æ§ã確ä¿ã§ããªãã ãšããå£ã«ã¶ã€ãã£ãããšã¯ãããŸãããïŒ ä»åã¯ã6å°ã®ã«ã¡ã©ã䜿ã£ã ãªã¢ã«ã¿ã€ã ãã«ãã«ã¡ã©ãã©ããã³ã° ãå®è£
ããéçšã§ãŸãã«ãã®åé¡ã«çŽé¢ããäžéšã®åŠçã Rust ã«çœ®ãæããããšã§åçãªé«éåãå®çŸãã話ã玹ä»ããŸãã ãRustã¯é£ãããããšæã£ãŠããæ¹ã§ããPythonãšé£æºãããã ããªãæå€ãšããŒãã«ã¯é«ããããŸããããã²æåŸãŸã§ãä»ãåããã ããã ã¯ããã« ãªã¢ã«ã¿ã€ã ãã«ãã«ã¡ã©ãã©ããã³ã°ãšã¯ ã·ã¹ãã æ§æãšæè¡ã¹ã¿ã㯠1. æšè«éšïŒæ åã®ãã³ãŒãã»AIæšè«ïŒ 2. çµ±åéšïŒãã©ããã³ã°ã»IDçµ±åïŒ Pythonã§ã®éçãšRustãžã®è»¢æ ãªãRustãéžãã ã PyO3ãšmaturinã䜿ã£ãå®è£
ãã㌠åæããŒã« 1. ãããžã§ã¯ãã®ã»ããã¢ãã 2. Rustã³ãŒãã®å®è£
(src/lib.rs) 3. Pythonããã®åŒã³åºã (main.py) 4. ãã«ããšå®è¡ å°å
¥çµæïŒ10å以äžã®é«éåãå®çŸ ãŸãšã ãªã¢ã«ã¿ã€ã ãã«ãã«ã¡ã©ãã©ããã³ã°ãšã¯ ãªã¢ã«ã¿ã€ã ãã«ãã«ã¡ã©ãã©ããã³ã°ïŒãªã³ã©ã€ã³ãã«ãã«ã¡ã©ãã©ããã³ã°ïŒãšã¯ãRTSPãªã©ã§æ¥ç¶ããè€æ°ã®ã«ã¡ã©ããçŸåšã®æ åãååŸãããªã¢ã«ã¿ã€ã ã«ä»¥äžã®åŠçãè¡ãæè¡ã§ãã æ€åº : ã«ã¡ã©ããšã«è¢«åäœã®é åïŒããŠã³ãã£ã³ã°ããã¯ã¹ïŒãæ€åº 远跡 : ã«ã¡ã©å
ã§è¢«åäœã远跡ããã«ã¡ã©å
ã®IDãå²ãåœãŠ ç¹åŸŽæœåº : 被åäœã®èŠãç®ã®ç¹åŸŽéïŒReIDç¹åŸŽéãªã©ïŒãæœåº çµ±å : å
šã«ã¡ã©ã®æ
å ±ãçµ±åãããšãªã¢å
šäœã§ã被åäœãã©ãã«ãããããäžæã«ç¹å® ãããã ãæ¬¡ã®ãã¬ãŒã ã®æ åãæ¥ãåã ã«å®äºãããå¿
èŠããããŸãã ä»åç®æããã¹ããã¯ã¯ã ããããã¯ãŒã¯ã«ã¡ã©6å°ãå20FPSã ã§ããã€ãŸããå
šã«ã¡ã©ã®åŠçã 50ããªç§ïŒ1000ms / 20fpsïŒä»¥å
ã«å®äºãããªããã°ãé
å»¶ãçºçããŠããŸããŸãã ã·ã¹ãã æ§æãšæè¡ã¹ã¿ã㯠ã·ã¹ãã ã®å€§ãŸããªæ§æå³ã¯ä»¥äžã®éãã§ãã åŠçã¯å€§ãããæšè«éšããšãçµ±åéšãã«åãããŠããŸãã 1. æšè«éšïŒæ åã®ãã³ãŒãã»AIæšè«ïŒ GPUãªãœãŒã¹ãæå€§éã«æŽ»ãããããNVIDIAã®æè¡ãæ¡çšããŠããŸãã DeepStream SDK GStreamerããŒã¹ã®ãã«ãã¡ãã£ã¢ãã¬ãŒã ã¯ãŒã¯ãåç»ã®ãã³ãŒããDNNæšè«ããã€ãã©ã€ã³åŠçã§é«éã«å®è¡å¯èœã§ãã DeepStream Python Apps DeepStreamãPythonããå¶åŸ¡ããããã®ãã€ã³ãã£ã³ã°ã§ãã ãåºå
žãNVIDIA-AI-IOT, deepstream_python_apps, GitHub https://github.com/NVIDIA-AI-IOT/deepstream_python_apps ïŒ2025幎11æ23æ¥ã¢ã¯ã»ã¹ïŒ 2. çµ±åéšïŒãã©ããã³ã°ã»IDçµ±åïŒ æšè«çµæãåãåããããžãã¯ããŒã¹ã§è¢«åäœã®åäžæ§å€å®ãè¡ããŸãã Python : å
šäœã®å¶åŸ¡ã»ã°ã«ãŒã³ãŒã Rust : èšç®ã³ã¹ãã®é«ããããã³ã°åŠçãæ
åœ PyO3 & maturin : PythonãšRustãç¹ãããã®ããŒã«çŸ€ ãåºå
žãPyO3 Project, PyO3 User Guide, WebããŒãž https://pyo3.rs/main/index.html ïŒ2025幎12æ10æ¥ã¢ã¯ã»ã¹ïŒ ãåºå
žãPyO3 Project, maturin, GitHub https://github.com/PyO3/maturin ïŒ2025幎12æ10æ¥ã¢ã¯ã»ã¹ïŒ Pythonã§ã®éçãšRustãžã®è»¢æ æšè«éšã«é¢ããŠã¯ãDeepStreamã®æ©æµã«ããPythonãã€ã³ãã£ã³ã°çµç±ã§ãååé«éã§ããã åé¡ãçºçããã®ã¯ãåŸæ®µã®ãçµ±åéšãã§ãã è€æ°ã®ã«ã¡ã©ããæ€åºããã被åäœã®äœçœ®ãç¹åŸŽéãç·åœããã§æ¯èŒããåäžè¢«åäœå€å®ãè¡ãåŠçïŒãããã³ã°åŠçïŒã«ãããŠãPythonã®åŠçé床ãããã«ããã¯ã«ãªããŸããã ã«ã¡ã©ãå¢ãã被åäœãå¢ããã°å¢ããã»ã©èšç®éã¯ææ°é¢æ°çã«å¢å ããŸãã çŽç²ãªPythonå®è£
ã§ãã¹ããããšããã被åäœãå€ãã·ãŒã³ã§ã¯åŠçã« æ°çŸããªç§ ããã£ãŠããŸããŸãããç®æšã®50ããªç§ã倧å¹
ã«è¶
ããŠãããæ åã¯ã«ã¯ã€ããåŠçèœã¡ã¯é¿ããããªãç¶æ
ã§ãã ãªãRustãéžãã ã NumPyãªã©ã䜿ã£ããã¯ãã«åãæ€èšããŸããããæ¡ä»¶åå²ãå«ãè€éãªããžãã¯ã ã£ããããã³ã³ãã€ã«èšèªãžã®çœ®ãæããæ€èšããŸãããããã§çœçŸœã®ç¢ãç«ã£ãã®ã Rust ã§ãã C++䞊ã¿ã®é«éæ§ : ã¡ã¢ãªå®å
šæ§ãæ
ä¿ããªããçéã§åãã PyO3ã®ãšã³ã·ã¹ãã : Pythonãšã®é£æºãéåžžã«å®¹æã§ãæ¢åã®Pythonã³ãŒãã®äžéšã ããRust颿°ã«çœ®ãæãããéšåçãªå°å
¥ããããããã ãå
šäœãæžãçŽãã®ã¯ç¡çã ããéãã«ãŒãåŠçã ãRustã«ä»»ãããããšããæŠç¥ã§ãã PyO3ãšmaturinã䜿ã£ãå®è£
ãã㌠ããããã¯ãå®éã«ä»åæ¡çšããéçºãããŒã玹ä»ããŸãã ããã±ãŒãžç®¡çã«ã¯ãæè¿è©±é¡ã®é«éãªããŒã« uv ã䜿çšããŸããã åæããŒã« uv : Pythonã®ããã±ãŒãžç®¡çã»ãããžã§ã¯ã管çããŒã« Rust : ã³ã³ãã€ã©èšèªïŒcargoãªã©ãå«ãŸããŸãïŒ 1. ãããžã§ã¯ãã®ã»ããã¢ãã maturin ã䜿ãã°ãRustã®ãããžã§ã¯ãäœæããPythonããã±ãŒãžãšããŠã®ãã«ããŸã§äžæ°é貫ã§è¡ããŸãã # äœæ¥ãã£ã¬ã¯ããªãžç§»å cd ${WORK_DIR} # maturinã®ã€ã³ã¹ããŒã«ïŒuv toolã䜿çšïŒ uv tool install maturin # PyO3ãã€ã³ãã£ã³ã°ãå«ãæ°èŠãããžã§ã¯ãäœæ # --mixed ãªãã·ã§ã³ã§PythonãšRustã®ãã€ããªããæ§æãäœæ uvx maturin new -b pyo3 --mixed study_maturin cd study_maturin # ä»®æ³ç°å¢ã®äœæïŒPython 3.12æå®ïŒ uv venv -p 3 . 12 2. Rustã³ãŒãã®å®è£
(src/lib.rs) ããã©ã«ãã§çæãããã³ãŒãã§ãã use pyo3 :: prelude :: * ; /// 2ã€ã®æ°å€ãè¶³ããŠæååãšããŠè¿ã颿° #[pyfunction] fn sum_as_string (a: usize , b: usize ) -> PyResult < String > { Ok ((a + b). to_string ()) } /// Pythonã¢ãžã¥ãŒã«ãšããŠã®å®çŸ© #[pymodule] fn study_maturin (m: & Bound < '_ , PyModule > ) -> PyResult < () > { // PythonããåŒã¹ã颿°ãšããŠç»é² m. add_function ( wrap_pyfunction! (sum_as_string, m) ? ) ? ; Ok (()) } 3. Pythonããã®åŒã³åºã (main.py) ãã«ããããRustã®é¢æ°ã¯ãéåžžã®Pythonã¢ãžã¥ãŒã«ãšåãããã«importããŠäœ¿çšã§ããŸãã import study_maturin def main (): a = 2 b = 3 # Rustã§å®è£
ããã颿°ãåŒã³åºã result = study_maturin.sum_as_string(a, b) print (f "The sum of {a} and {b} is: {result}" ) if __name__ == "__main__" : main() 4. ãã«ããšå®è¡ éçºã¢ãŒãïŒ maturin develop ïŒã§ãã«ããããšãçŸåšã®ä»®æ³ç°å¢ã«ããã±ãŒãžãã€ã³ã¹ããŒã«ãããŸããæ¬çªæ§èœãåºããã --release ãä»ããŠããŸãã # ãã£ãã·ã¥ã¯ãªã¢ïŒå¿µã®ããïŒ uv cache clean # ãªãªãŒã¹ãã«ãã§ã€ã³ã¹ããŒã« uvx maturin develop --release # Pythonã¹ã¯ãªããå®è¡ uv run main.py å®è¡çµæ: The sum of 2 and 3 is: 5 ãã®ããã«ãéåžžã«å°ãªãæé ã§Rustã®é¢æ°ãPythonããåŒã³åºãããšãã§ããŸããã ä»åã¯åçŽãªè¶³ãç®ã§ãããå®éã®æ¥åã§ã¯ããã«ããã«ãã«ã¡ã©ã®IDçµ±åããžãã¯ããå®è£
ããŸããã RuståŽã§æ§é äœãå®çŸ©ããŠPythonã®ã¯ã©ã¹ãšããŠæ±ã£ãããåãã³ãïŒ.pyiãã¡ã€ã«ïŒãçæããŠVSCodeã§ã®è£å®ãå¹ããããããããšãå¯èœã§ãã å°å
¥çµæïŒ10å以äžã®é«éåãå®çŸ çµ±åéšã®ããã«ããã¯ãšãªã£ãŠããè§£æããžãã¯ãRustã«çœ®ãæããçµæãããã©ãŒãã³ã¹ã¯åçã«æ¹åããŸããã Before (Python) : 1ãã¬ãŒã ããã 300msè¶
ïŒããŒã¯æïŒ After (Rust) : 1ãã¬ãŒã ããã 30ms以å
çŽ10å以äžã®é«éå ãéæããç®æšãšããŠããã6å°ã»20FPSïŒ50ms以å
ïŒãã®åŠçæéãäœè£ãæã£ãŠã¯ãªã¢ããããšãã§ããŸãããããã«ããããªã¢ã«ã¿ã€ã ã§æ»ãããªãã©ããã³ã°ãå®çŸã§ããŠããŸãã ãŸãšã ãPythonã¯é
ãããšè«Šããåã«ãããã«ããã¯éšåã ããRustã«ãªãããŒãããã¢ãããŒãã¯éåžžã«æå¹ã§ããã ç¹ã« PyO3 ãš maturin ïŒãã㊠uv ïŒã®ãšã³ã·ã¹ãã ã®ãããã§ãPythonãšã³ãžãã¢ã«ãšã£ãŠãRustå°å
¥ã®æ·å±
ã¯ããªãäœããªã£ãŠãããšæããŸãã ä»åã¯ããžãã¯ã®äžéšã®ã¿ã®çœ®ãæãã§ããããä»åŸã¯Rustã§åŠçããé åãåºããã·ã¹ãã å
šäœã®å
ç¢æ§ãšããã©ãŒãã³ã¹åäžã«ææŠããŠãããããšæããŸãã
ãã®èšäºã¯ Safie Engineers' Blog! Advent Calendar 10æ¥ç®ã®èšäºã§ã ããã«ã¡ã¯ïŒSafieïŒã»ãŒãã£ãŒïŒã§ã¢ãã€ã«ã¢ããªã®éçºãããŠããæ²³å( @rui_qma )ã§ãã ð ã¯ããã«ïŒãªãComposeã§ãã©ãã°ïŒãããããå¿
èŠãªã®ã åŸæ¥ã®Viewã·ã¹ãã ãšã®å£ AndroidããŒã ã§ã¯Android ViewããŒã¹ã®UIãã Jetpack Compose ããŒã¹ã®UIãžã®ç§»è¡ãé²ããŠããŸãã åŒç€Ÿã®ãããã¯ãã Safie Viewer ïŒã»ãŒãã£ãŒ ãã¥ãŒã¢ãŒïŒãã®ã«ã¡ã©äžèЧç»é¢ã«ã¯ãã«ã¡ã©ã®é çªããã©ãã°ïŒããããïŒD&DïŒã«ãã£ãŠäžŠã³æ¿ããæ©èœããããŸãã åŸæ¥ã®Android Viewã§ã¯ã RecyclerView ã« ItemTouchHelper ãçµã¿åãããããšã§ãD&Dã«ããäžŠã³æ¿ããå
¬åŒAPIãšããŠç°¡åã«å®çŸã§ããŠããŸããã ããããJetpack Composeã§ã¯ã2025幎11æçŸåšã LazyVerticalGrid ïŒãŸã㯠LazyColumn ïŒå
ã§åæ§ã®D&DäžŠã³æ¿ãæ©èœããå
¬åŒAPIã ãã§ãå®çŸããããã®å°çšã®ã³ã³ããŒãã³ãã¯ãŸã æäŸãããŠããŸããã( composeBom : 2025.11.01ã§ç¢ºèª) æ¬èšäºã§ã¯ããã®ãComposeã§ãã©ãã°ïŒããããã«ããäžŠã³æ¿ããå¯èœãªã°ãªãããããå
¬åŒAPIæªæäŸã®äžã§ã©ã®ããã«äœã蟌ããããã®èšèšãšå®è£
ææ³ã«ã€ããŠè§£èª¬ããŸãã ð ã¯ããã«ïŒãªãComposeã§ãã©ãã°ïŒãããããå¿
èŠãªã®ã åŸæ¥ã®Viewã·ã¹ãã ãšã®å£ âš å®çŸãããæ©èœã®èŠä»¶å®çŸ© ðŠÂ Step0: åå°ãšãªãComposableãçšæ ðStep1: èŠçŽ ã®é·æŒãæ€åºãšè§ŠèŠãã£ãŒããã㯠å®è£
ã®ãã€ã³ã âïžStep2: èŠçŽ ããã©ãã°ããŠç§»åãã å®è£
ã®ãã€ã³ã ðStep3: ãã©ãã°ã«ããèŠçŽ ã®å
¥ãæ¿ãåŠç å®è£
ã®ãã€ã³ã ð«Step4: å
¥ãæ¿ããéã®ã¢ãã¡ãŒã·ã§ã³ãå®è£
å®è£
ã®ãã€ã³ã â¬ïžStep5: ãªã¹ãã®äžäžç«¯å°éæã®èªåã¹ã¯ããŒã« å®è£
ã®ãã€ã³ã ð ãŸãšããšä»åŸã®å±æ ðå°æ¥çãªèŠéã ð» å®è£
ã³ãŒã âš å®çŸãããæ©èœã®èŠä»¶å®çŸ© ä»åã®èšäºã§å®è£
ãç®æãD&DäžŠã³æ¿ãã°ãªããã®èŠä»¶ã¯ä»¥äžã®5ç¹ã§ãã èŠçŽ ã é·æŒã ããã¿ã€ãã³ã°ã§D&Då¯èœç¶æ
ã«ãã è§ŠèŠãã£ãŒããã㯠ãå®è¡ããã ãã©ãã°ã«æ²¿ã£ãŠèŠçŽ ãç§»åãããã é çªã®å
¥ãæ¿ãããçºçããå Žåã ã¢ãã¡ãŒã·ã§ã³ ã§èŠèŠçã«è¡šçŸããã ãã©ãã°äœçœ®ããªã¹ãã®äžäžç«¯ã«éããå Žåã ãªã¹ãèªäœãèªåã§ã¹ã¯ããŒã« ããã ãã©ãã°çµäºæã«èŠçŽ ãå®äœçœ®ã«æ»ãã ãããã®æ©èœããåå°ãšãªãComposableããæ®µéçã«å®è£
ããŠãããŸãã ðŠÂ Step0: åå°ãšãªãComposableãçšæ ä»åã®èšèšæ¹éãšããŠLazyVerticalGridãã©ããããComposableãäœæã(DraggableGridãšåœå)ããã®Composableã®äžã§ç¶æ
ã®ç®¡çåã³D&Dæ©èœã®æ¡åŒµãé²ããŠãããŸãã @Composable fun DraggableGrid( list: List < String >, modifier: Modifier = Modifier, itemContent: @Composable (item: Camera, modifier: Modifier) -> Unit , ) { val lazyGridState = rememberLazyGridState() LazyVerticalGrid( modifier = modifier, columns = GridCells.Fixed( 3 ), state = lazyGridState, horizontalArrangement = Arrangement.spacedBy( 12 .dp), verticalArrangement = Arrangement.spacedBy( 12 .dp), ) { items(list) { id, modifier -> itemContent(id, modifier) } } } ðStep1: èŠçŽ ã®é·æŒãæ€åºãšè§ŠèŠãã£ãŒããã㯠èŠçŽ ã®é·æŒããæ€ç¥ããåŠçãå®è£
ããŸãã å®è£
ã®ãã€ã³ã ãã©ãã°å¯Ÿè±¡ã®ComposeèŠçŽ ã« Modifier.pointerInput ã远å pointerInputå
ã§ãžã§ã¹ãã£ãŒæ€åºé¢æ° detectDragGesturesAfterLongPress ã§é·æŒããæ€åº onDragStart ã«é·æŒãæã®åŠçã onDrag ã«ãã©ãã°äžã®åŠçãå®è£
ãã è§ŠèŠãã£ãŒãããã¯ã¯ performHapticFeedback ãåŒã³åºãããšã§åäœããããã以äžã®ããã«å®è£
ããããšã«ãã£ãŠãŠãŒã¶ãŒã«é·æŒãç¶æ
ã§ããããšãç¥ãããããšãã§ããŸãã Developers ... val haptic = LocalHapticFeedback.current LazyVerticalGrid( modifier = modifier.pointerInput( Unit ) { detectDragGesturesAfterLongPress( onDragStart = { offset -> // ãã©ãã°éå§æã«è¡ãããåŠçãããã«å®è£
ãã haptic.performHapticFeedback(HapticFeedbackType.LongPress) // è§ŠèŠãã£ãŒããã㯠}, onDrag = { change, dragAmount -> // ãã©ãã°äžã«è¡ãããåŠçãããã«å®è£
ãã change.consume() // ãã©ãã°ã€ãã³ãã®æ¶è²» }, onDragEnd = { // ãã©ãã°çµäºæã«è¡ãããåŠçãããã«å®è£
ãã }, onDragCancel = { // ãã©ãã°ããã£ã³ã»ã«ãããæã«è¡ãããåŠçãããã«å®è£
ãã } ) }, ... âïžStep2: èŠçŽ ããã©ãã°ããŠç§»åãã Step1ã§èšè¿°ããdetectDragGesturesAfterLongPressã®ã³ãŒã«ããã¯ã«ãã©ãã°ã«é¢ããåŠçãå®è£
ããŠãããŸãã å®è£
ã®ãã€ã³ã onDragStartã§ãã©ãã°å¯Ÿè±¡ã®ã€ã³ããã¯ã¹ãååŸ onDragã§ãã©ãã°éãå ç®ããŠä¿æ ãã©ãã°å¯Ÿè±¡èŠçŽ ã«å¯Ÿã㊠Modifier.offset ã§ãã©ãã°éãæå®ããŠç§»å onDragEnd, onDragCancelã§ãã©ãã°éãåæå ïŒä»åã¯ç°¡åã«å®è£
ããããã«Composableå
ã§ã€ã³ããã¯ã¹ããªãã»ããçã®ç¶æ
ã管çããŠããŸãããStateã¯ã©ã¹ã®äœæãªã©Viewãšã¯åé¢ããŠç®¡çããããšããªã¹ã¹ã¡ããŸãïŒ val density = LocalDensity.current var draggingIndex by remember { mutableIntStateOf( 0 ) } var dragOffset by remember { mutableStateOf(Offset.Zero) } LazyVerticalGrid( modifier = modifier.pointerInput( Unit ) { detectDragGesturesAfterLongPress( onDragStart = { offset -> // ãã©ãã°éå§äœçœ®ã®ã€ã³ããã¯ã¹ãååŸ draggingIndex = lazyGridState.layoutInfo.visibleItemsInfo.find { info -> val rect = Rect(info.offset.toOffset(), info.size.toSize()) rect.contains(offset) }?.index ?: - 1 haptic.performHapticFeedback(HapticFeedbackType.LongPress) // è§ŠèŠãã£ãŒããã㯠}, onDrag = { change, dragAmount -> dragOffset + = dragAmount change.consume() // ãã©ãã°ã€ãã³ãã®æ¶è²» }, onDragEnd = { dragOffset = Offset.Zero }, onDragCancel = { dragOffset = Offset.Zero } ) }, ... ) { itemsIndexed( items = list, key = { index, item -> item }, ) { index: Int , item: String -> val dragging = draggingIndex == index val modifier = if (dragging) { Modifier .offset( x = with(density) { dragOffset.x.toDp() }, y = with(density) { dragOffset.y.toDp() }, ) .zIndex( 1f ) // ãã©ãã°äžã®ã¢ã€ãã ãåé¢ã«è¡šç€º } else { Modifier } itemContent(item, modifier) } } ðStep3: ãã©ãã°ã«ããèŠçŽ ã®å
¥ãæ¿ãåŠç ãã©ãã°äžã¢ã€ãã ã® äžå¿äœçœ® ãä»èŠçŽ ã®é åã«å
¥ã£ãã¿ã€ãã³ã°ã§ããªã¹ãã®é çªãå
¥ãæ¿ããåŠçãå®è¡ããŸãã å®è£
ã®ãã€ã³ã èŠçŽ å
¥ãæ¿ãã³ãŒã«ããã¯(ex: onListChange)ãå®çŸ©ããäžŠã³æ¿ãã®åŠçãå®è£
ãã ãã©ãã°äžã¢ã€ãã ã®äžå¿äœçœ®ãç®åºãã äžå¿äœçœ®ãä»èŠçŽ ã®é åå
ã«ååšããå ŽåãèŠçŽ å
¥ãæ¿ãã³ãŒã«ããã¯ãå®è¡ãã å®éã®å
¥ãæ¿ãããžãã¯ã¯è€éã«ãªããããããã§ã¯è©³çްã岿ããŸããããªã¹ã倿Žã芪ã«å§ããã³ãŒã«ããã¯èšèšãéèŠã§ãã詳现ãªå®è£
㯠ã³ãã© ãåç
§ãã ããã ð«Step4: å
¥ãæ¿ããéã®ã¢ãã¡ãŒã·ã§ã³ãå®è£
èŠçŽ ãå
¥ãæ¿ãã£ãããšããŠãŒã¶ãŒã«ããããããäŒãããããã¢ãã¡ãŒã·ã§ã³ã远å ããŸãã ãã®Stepã«é¢ããŠã¯æšæºã§æäŸãããŠããæ©èœãå©çšããããšã§ãæè»œã«å®è£
ããããšãã§ããŸãã å®è£
ã®ãã€ã³ã ã¢ã€ãã ã«ããŒãèšå®ãã å
¥ãæ¿ããããåŽã®èŠçŽ ã« Modifier.animateItem() ãèšå®ãã itemsIndexed( items = list, key = { index, item -> item }, // ComposeåŽã§ã¢ã€ãã ãç¹å®ããããã®ã㌠) { index: Int , item: String -> val dragging = draggableGridState.draggingIndex == index val offset = draggableGridState.dragOffset val modifier = if (dragging) { Modifier .offset( x = with(density) { offset.x.toDp() }, y = with(density) { offset.y.toDp() }, ) .zIndex( 1f ) } else { Modifier.animateItem() // å
¥ãæ¿ããããåŽã«ã¢ãã¡ãŒã·ã§ã³ãèšå® } itemContent(item, modifier) } â¬ïžStep5: ãªã¹ãã®äžäžç«¯å°éæã®èªåã¹ã¯ããŒã« äŸãã°ã1çªç®ãã100çªç®ã«ç§»åãããããšãã£ã倧å¹
ãªç§»åãè¡ãããå ŽåãçŸç¶ã¯1åã®ãã©ãã°ã«ã€ãæå€§1ç»é¢åããç§»åã§ããªããããè€æ°åã®ãã©ãã°ãå¿
èŠã«ãªããŸãã ãã®åé¡ã解決ããããããã©ãã°ã«ãã£ãŠãªã¹ãã®äžäžç«¯ãŸã§æã£ãŠãã£ãå Žåã¯ãªã¹ãèªäœã®ã¹ã¯ããŒã«ãè¡ãæ©èœãå®è£
ããŸãã å®è£
ã®ãã€ã³ã ãã©ãã°äžã®èŠçŽ ããªã¹ãã®äžäžç«¯ããã©ãã ãã¯ã¿åºããŠããããç®åºãã ã¯ã¿åºããŠããå Žåã¯ãã¯ã¿åºããéã«å¿ããY軞移åéãç®åºãã ãªã¹ããšèŠçŽ ã®äž¡æ¹ãåæã«Y軞移åéåã ãç§»åããïŒåæããïŒ ãã®å®è£
ã¯ããã©ãŒãã³ã¹ãšç«¶ååé¿ã®èгç¹ããè€éãªéšåã§ãããã¹ã¯ããŒã«ãšèŠçŽ ç§»åãåæã«è¡ãåæåŠçã«å·¥å€«ãå¿
èŠã§ãã詳现ãªå®è£
㯠ã³ãã© ãåç
§ãã ããã ð ãŸãšããšä»åŸã®å±æ æ¬èšäºã§ã¯ãJetpack Composeã«ãããŠæšæºã§æäŸãããŠããªãæ©èœãã Modifier.pointerInput ãæŽ»çšããŠãŒãããäœãèŸŒãææ³ã解説ããŸããã ã¿ããã€ãã³ãã®æ€åºããªãã»ããã«ããäœçœ®èª¿æŽã Modifier.animateItem() ã«ããã¢ãã¡ãŒã·ã§ã³ããããŠèªåã¹ã¯ããŒã«ãçµã¿åãããããšã§ãåŸæ¥ã®Android Viewã® RecyclerView + ItemTouchHelper ã«å¹æµãããé«åºŠãªUXãå®çŸããããšãã§ããŸããã ãã®å®è£
ã«ã¯ææ¢ãã®éšåãå€ãããªãã¡ã¯ã¿ãªã³ã°ãããã©ãŒãã³ã¹æ¹åã®äœå°ã¯ååã«ãããšèããŠããŸãããæ¬èšäºãçæ§ã®Composeå®è£
ã®æå©ããšãªãã°å¹žãã§ãã ðå°æ¥çãªèŠéã å·çæç¹ã§ã¯èªåã§ã®å®è£
ãå¿
èŠã§ããããããŒããããã«ã¯ãã©ãã°ïŒããããã«é¢ããèšèŒããããããå°æ¥çã«ã¯æšæºæ©èœãšããŠãµããŒããããå¯èœæ§ãé«ãã§ãã åºå
žïŒJetpack Compose ã®ããŒãããã https://developer.android.com/jetpack/androidx/compose-roadmap?hl=ja ïŒ2025幎12æ3æ¥ã¢ã¯ã»ã¹ïŒ ãããŸã§ã¯ä»å解説ãããããªèªåã®å®è£
ãè¡ããããããã¯ãåŸæ¥ã®Android Viewã® ItemTouchHelper ã ComposeView ã§ãã¹ãããŠå©çšãããšããéžæè¢ãäžã€ã®åé¿çãšãªããŸããç¶æ³ã«å¿ããŠãæé©ãªã¢ãããŒããéžæããŠãã ããã ð» å®è£
ã³ãŒã å·çã«ããã£ãŠå®è£
ããã³ãŒãå
šäœã¯ã以äžã®GitHubãªããžããªã§å
¬éããŠããŸããæ¯éåèã«ããŠãã ããã https://github.com/ruiqma/DraggableGridSample ã¢ãã€ã«ããŒã ã¯éçºãã仲éãåéããŠããŸãïŒ open.talentio.com open.talentio.com
ãã®èšäºã¯ Safie Engineers' Blog! Advent Calendar 2025 9æ¥ç®ã®èšäºã§ãã ã¯ããã« ããã«ã¡ã¯ããšã³ãžãã¢ãªã³ã°ãªãã£ã¹ã®æšªé ( @m_yokomichi )ã§ãã 2025幎ãAIæè¡ã¯ç§ãã¡ã®äºæ³ãè¶
ããã¹ããŒãã§é²åãéããŸãããããŸãçæAIã䜿ãããªãããåŠãã¯ãå人ã®çç£æ§ã ãã§ãªãã ãšã³ãžãã¢ãšããŠã®ãã£ãªã¢ãã²ããŠã¯äŒæ¥ã®ç«¶äºåãã®ãã®ãå·Šå³ãã ãšèšã£ãŠãéèšã§ã¯ãããŸããã ä»åŸã掻çšã§ããå±€ãšããã§ãªãå±€ã®å·®ã¯åºããäžæ¹ã§ãããã®ãããçæAIã®æŽ»çšã¯ç§ãã¡ã»ãŒãã£ãŒã«ãšã£ãŠãå
šç€Ÿã®éèŠèª²é¡ã§ãããéçºæ¬éšãšããŠçµç¹çã«åãåãã¹ãããŒããšãªã£ãŠããŸãã æ¬èšäºã§ã¯ãéçºæ¬éšå
šäœã§åãçµãã§ãããçæAIå©çšä¿é²ãããžã§ã¯ããã«ã€ããŠã以äžã®ãã€ã³ããäžå¿ã«ã玹ä»ããŸãã çµç¹èª²é¡ã解決ããããã®ã5ã€ã®æŠç¥è»žã ããã ã¢ããã§é²ããå®éã®æŽ»åå
容 å°å
¥ã«ããå
·äœçãªææãšä»åŸã®å±æ åãªãããŒã«ã®å°å
¥äºäŸã§ã¯ãªãããçµç¹æåãã©ãå€ããŠãããããšãã芳ç¹ã§ã®å
šè²ããäŒãããŸãã ã¯ããã« ç§ãã¡ãçŽé¢ããŠããã5ã€ã®å£ã 1. æ
å ±åéã®ãéå¹çæ§ã 2. æè¡æ€èšŒã»å°å
¥ã®ãå±äººåã 3. ãã¬ããžã®ããµã€ãåã 4. æŽ»çšæ©éã®ã枩床差ã 5. æè¡çåãçµã¿ã®ãèªç¥äžè¶³ã 解決ãžã®æŠç¥çã¢ãããŒãïŒ5ã€ã®è»ž ãããžã§ã¯ãå
šäœæ§æ³å³ 軞1ïŒæ
å ±åéæŽ»æ§å ð¡ 軞2ïŒæè¡æ€èšŒã»å°å
¥ ð ïž è»ž3ïŒãã¬ããžããŒã¿ããŒã¹ãããžã¡ã³ã ð 軞4ïŒçæAI掻æ§å ð¥ 軞5ïŒç€Ÿå€çºä¿¡ ð¢ å®éã®æŽ»åãšæ³å®å€ã®åé¿ 20åã®æå¿ãéçµ åç§äŒã«ããèªåŸçãªéå¶ ææãšä»åŸã®å±æ äž»ãªææ ä»åŸã®ããŒãããã ãããã« ç§ãã¡ãçŽé¢ããŠããã5ã€ã®å£ã çæAI掻çšãçµç¹çã«æšé²ããããšããéãç§ãã¡ã¯å€§ããåããŠ5ã€ã®åé¡é åã«çŽé¢ããŠããŸããããããã¯ãå€ãã®éçºçµç¹ãå
±éããŠæ±ããæ©ã¿ã§ã¯ãªãã§ããããã 1. æ
å ±åéã®ãéå¹çæ§ã å€éšã®æè¡ååãå人ããã©ãã©ã«è¿œã£ãŠãããããçµç¹ãšããŠã®ã€ã³ããããéå¹çã§ããããé£ã®ããŒã ãåã調æ»ãããŠããããšããè»èŒªã®åçºæãèµ·ããŠãããçµç¹ãšããŠã®ã¹ããŒãæãæãªãããŠããŸããã 2. æè¡æ€èšŒã»å°å
¥ã®ãå±äººåã ããã®æ°æ©èœã䜿ãããããšæã£ãŠããå°å
¥ããã»ã¹ãè©äŸ¡åºæºãäžæç¢ºã§ãããçµæãšããŠãææ¬²ããã¡ã³ããŒã®æè¡éžå®ã«æéãããããæçãªæè¡ã®å°å
¥ã«ããæ©äŒæå€±ãçºçããŠããŸããã 3. ãã¬ããžã®ããµã€ãåã Aããã¯é«åºŠãªããã³ãããç¥ã£ãŠããã®ã«ãBããã¯åã課é¡ã§èºããŠãããæåäºäŸã倱æäºäŸïŒã¢ã³ããã¿ãŒã³ïŒãå
±æããããããŠããŠãå人ã®é ã®äžã ãã«çãŸã£ãŠããŸããã 4. æŽ»çšæ©éã®ã枩床差ã ã䟿å©ããã ãã©ãèªåã®æ¥åã§ã®äœ¿ãæãããããªãããšããã¡ã³ããŒãå€ããäžéšã®æåºŠãé«ãå±€ã ããæŽ»çšããŠããç¶æ
ã§ããã 5. æè¡çåãçµã¿ã®ãèªç¥äžè¶³ã ãã£ããå
é²çãªåãçµã¿ãããŠããŠãããããå€éšã«äŒãã£ãŠããªããã°æ¡çšããã©ã³ãã£ã³ã°ã«ã¯ç¹ãããŸããããŸããå€éšã³ãã¥ããã£ãšã®æ¥ç¹ãèãããã£ãŒãããã¯ãåŸãæ©äŒãäžè¶³ããŠããŸããã 解決ãžã®æŠç¥çã¢ãããŒãïŒ5ã€ã®è»ž ãããã®èª²é¡ãæç Žãããããç§ãã¡ã¯ã5ã€ã®è»žããå®çŸ©ããæŠç¥çãªã¢ãããŒããéå§ããŸããã ãããžã§ã¯ãå
šäœæ§æ³å³ ãŸãã以äžã®ãµã€ã¯ã«ãåãããšã§ãçæAIïŒAIæè¡ïŒã®å°å
¥ã»å®çãç®æããŸãããçæAIå©çšä¿é²ããŒã ããããšãªããéçºæ¬éšå
šäœãå·»ã蟌ãã§ããŸãã ããããã¯ãå
·äœçãª5ã€ã®è»žã«ã€ããŠè§£èª¬ããŸãã 軞1ïŒæ
å ±åéæŽ»æ§å ð¡ ç®çïŒ çµç¹çãªãã¢ã³ãããã®æåºŠãé«ããæè¡éžå®ãé«éåãã å人ã®åªåã«äŸåããŠããæ
å ±åéããçµç¹ã®æŽ»åãžãšæè¯ãããŸããã ãã¬ã³ãã®å®ç¹èŠ³æž¬: ææ°ããŒã«ãäºäŸãããŒã ã§åæ
ããŠèª¿æ» å°å
¥ãžã£ããž: å©ç𿹿³ãæç¢ºãªãã®ã¯ãå®åæ€èšŒããžãæªå°å
¥æè¡ã¯ãäŒç»ããžãšã¹ã ãŒãºã«ç§»è¡ããããããŒãç¢ºç« è»ž2ïŒæè¡æ€èšŒã»å°å
¥ ð ïž ç®çïŒ æ°æè¡ããå®å
šã«ããçŽ æ©ãã詊ããç°å¢ãäœã ã䜿ã£ãŠã¿ããããã䜿ãããã«ããããã®ç°å¢æŽåã§ãã ç°å¢æŽå: ã¢ã«ãŠã³ã管çãLLM Proxyåºç€ã®æ§ç¯ ã¬ã€ãã©ã€ã³çå®: ã»ãã¥ãªãã£ãå人æ
å ±ã®åãæ±ããæ©å¯æ
å ±ã®ä¿æã«é¢ããã«ãŒã«ãæç¢ºåããå®å
šã«å©çšã§ããç°å¢ãæäŸ 軞3ïŒãã¬ããžããŒã¿ããŒã¹ãããžã¡ã³ã ð ç®çïŒ ç¥èŠããè³ç£ãåããè»èŒªã®åçºæãé²ã DBæ§ç¯: ãã¹ããã©ã¯ãã£ã¹ã倱æäºäŸãããã³ããã©ã€ãã©ãªãäžå
管ç ã¡ã³ããã³ã¹: æ
å ±ã®é®®åºŠãä¿ã€ãããé³è
åããæ
å ±ã®æŽæ°ãããŒãæŽå ãã³ãã¬ãŒãå: éçºãåæãããã¥ã¡ã³ãäœæãªã©ãçšéå¥ã®ãåå©çšå¯èœãªããã³ããããæŽå 軞4ïŒçæAI掻æ§å ð¥ ç®çïŒ çµç¹å
šäœã®ãç±éããäžããæåãäœã ã€ãã³ãéå¬: å匷äŒãLTïŒã©ã€ããã³ã°ããŒã¯ïŒãããã«ãœã³ãªã©ãäŒç» 暪å±é: æåäºäŸãéšéãè¶
ããŠå
±æãããèªåããã£ãŠã¿ããããšãã空æ°ãéžæ 軞5ïŒç€Ÿå€çºä¿¡ ð¢ ç®çïŒ åãçµã¿ãã䟡å€ãã«å€ããæ°ããªç¥èŠãåŒã³èŸŒã ã¢ãŠãããã: æè¡ããã°ãã€ãã³ãç»å£ãéããçºä¿¡ éæµ: 瀟å€ããã®ãã£ãŒãããã¯ã瀟å
ã«åã蟌ã¿ããããªãæ¹åã«ã€ãªãããµã€ã¯ã« å®éã®æŽ»åãšæ³å®å€ã®åé¿ æŠç¥ã¯æããŸããããç§äžäººã§å®è¡ã§ãããã®ã§ã¯ãããŸãããããã§éçºæ¬éšå
šäœããã¡ã³ããŒãå
¬åãããšãããäºæ³å€ã®åå¿ããããŸããã 20åã®æå¿ãéçµ åœåã¯æ°åéãŸãã°è¯ããšèããŠããŸãããã çŽ20åãã®ã¡ã³ããŒãæãæããŠãããŸããã éçºæ¬éšã®ãšã³ãžãã¢ãã¡ããããã«ãã®èª²é¡ã«ç±æãæã£ãŠãããã®è¡šãã§ãããéåžžã«å¬ãã誀ç®ã§ããã åç§äŒã«ããèªåŸçãªéå¶ ã¡ã³ããŒã®èªäž»æ§ãå°éããåè¿°ã®5ã€ã®è»žããšã«ãåç§äŒããçµæããŸããã 鱿¬¡ã»éé±ã§å®äŸMTGãè¡ããããããã®åŒ·ã¿ã掻ãããŠã¢ã¯ã·ã§ã³ãã©ã³ãå®è¡ããŠããŸãããããããŠã³ã§ã¯ãªããçŸå Žã®ãšã³ãžãã¢ãäž»å°ããããã ã¢ããåã®ãããžã§ã¯ããšããŠæ©èœããŠããŸãã ææãšä»åŸã®å±æ 2025幎9æã®çºè¶³ããæ°ã¶æãåå°ã¥ããã«æ³šåããŠããŸãããããã§ã«ç®ã«èŠããå€åãèµ·ããŠããŸãã äž»ãªææ å©çšçã®åäž: Claude Codeã®Maxãã©ã³çã®é«åºŠãªæ©èœãå©çšããã¡ã³ããŒãåææ¯ã§å¢å åŸåã åŠç¿æåã®å®ç: éçºæ¬éšã® çŽåæ° ãçæAIå匷äŒã«åå ã ãã¬ããžããŒã¹çšŒå: ç¬èªã®ããŒã¿ããŒã¹ãæ§ç¯ãããæ¥ã
ç¥èŠãèç©ãããŠããã ããŒã¿ã«ãµã€ãéèš: ããŒã«ãã¬ã€ãã©ã€ã³ãææ°æ
å ±ãéçŽãããçæAIããŒã¿ã«ããå
¬éã ä»åŸã®ããŒãããã ð çæïŒFY25幎床å
ïŒ æè¡æ€èšŒ: LLM Proxyåºç€ã®æ§ç¯ãClaude Teamãã©ã³ãžã®ç§»ç®¡ã 掻æ§å: LT倧äŒã®å®æœïŒ11/27ã12/11äºå®ïŒããã³ãºãªã³ã»ããã«ãœã³ã®éå¬ã ãã¬ããž: ããã³ããã©ã€ãã©ãªã®ã«ããŽãªæ¡å
ïŒã³ãŒãã¬ãã¥ãŒãèšè𿝿Žãªã©ïŒã ð äžé·æïŒæ¥å¹ŽåºŠä»¥éïŒ å¹ææž¬å®: åãªãå©çšè
æ°ã§ã¯ãªããã³ãŒãå質ãéçºé床ãªã©ãçç£æ§ææšããžã®è²¢ç®ãå¯èŠåã å
šç€Ÿå±é: éçºæ¬éšã§å¹ã£ãããŠããŠãä»éšéãžæšªå±éããå
šç€ŸçãªDXãæ¯æŽã æåã®å®ç: æ°å
¥ç€Ÿå¡åãã®ãçæAI掻çšç ä¿®ããªã©ãéããAI掻çšã空æ°ã®ãããªãåœããåãã«ããã ãããã« çæAIãçµç¹ã§æŽ»çšã§ããŠããç¶æ
ã«ããã«ã¯ãå人ã®ãç¹ãã®æŽ»åã ãã§ã¯éçããããŸããçµç¹å
šäœã§æŠç¥çã«åãçµã¿ããé¢ãã®æŽ»åã«ããããšã§åããŠãç¥èŠã®æšæºåãæåéžæãå¯èœã«ãªããŸãã ä»åã玹ä»ããã5ã€ã®è»žãã¯ãããŸã§ã»ãŒãã£ãŒã®äžäŸã§ãããçµç¹çãªAI掻çšã«æ©ãçæ§ã®ãã³ãã«ãªãã°å¹žãã§ãã ã»ãŒãã£ãŒéçºæ¬éšã§ã¯ãä»åŸãã€ãã³ãçãéããŠç¥èŠããªãŒãã³ã«ããŠãããŸããããã¡ã§ã¯ããããŠãããïŒããšããä»ç€Ÿã®çæ§ããã²æ
å ±äº€æãããŠãã ããïŒ
ãã®èšäºã¯Â Safie Engineers' Blog! Advent Calendar  ã®8æ¥ç®ã®èšäºã§ãã ããã«ã¡ã¯ãã»ãŒãã£ãŒæ ªåŒäŒç€Ÿã§ãµã€ããŒã»ãã¥ãªãã£ãæ
åœããŠããéåã§ãã ååã®èšäºã ã»ãŒãã£ãŒã®ãµã€ããŒã»ãã¥ãªãã£æŠç¥ã®äœãæ¹ ãã§ã¯ãç§ãã¡ãç®æããã»ãã¥ãªãã£ãåœããåã®æåããšãããã«å°éããããã®æŠç¥ãã«ã€ããŠãäŒãããŸãããä»åã¯ãæŠç¥ã®å
·äœçãªæã¡æã®äžã€ã ãè
åšã¢ããªã³ã°ã ã«ã€ããŠæ·±æãããŸãã ãè
åšã¢ããªã³ã°ããšèããšãå°éçšèªãå€ããŠãé£ãããããæéããããããããšæããŠããŸãããšã¯ãããŸãããïŒ æ£çŽã«èšããšãç§ãã¡ãæåã¯ããã§ããã ãããã詊è¡é¯èª€ããŠãã©ãçããçµè«ã¯ã·ã³ãã«ã§ããè
åšã¢ããªã³ã°ã®æ¬è³ªã¯ ãé¢ä¿è
å士ã®å¯Ÿè©±ãä¿é²ããã³ãã¥ãã±ãŒã·ã§ã³ããŒã«ã ã ãšããããšã ä»åã¯ãäžè¬çãªè
åšã¢ããªã³ã°ã®ææ³ã解説ãã€ã€ãããããã»ãŒãã£ãŒã§ã¯ã©ãè§£éããéçšããŠãããããšãã å®è·µçãªãã¬ããžïŒïŒã»ãŒãã£ãŒæµã®åïŒ ãã»ããã§å
¬éããŸããããããè
åšã¢ããªã³ã°ãå§ãããæ¹ããã£ãšæŽ»çšããŠããããæ¹ã®ãçããæç§æžãã«ãªãã°å¹žãã§ãã ãããããè
åšã¢ããªã³ã°ãã£ãŠäœïŒ ãªãä»ãç§ãã¡ããããæšãã®ã è
åšã¢ããªã³ã°ã®é²ãæ¹ïŒè§£èª¬ãšã»ãŒãã£ãŒæµã®å®è·µïŒ 4ã€ã®éèŠãªè³ªå ãå1ãç§ãã¡ã¯äœã«åãçµãã§ãããïŒ ïœã¢ãã«ãäœãïœ ãå2ãäœãåé¡ã«ãªããããïŒ ïœSTRIDEã§ãªã¹ã¯ãèŠã€ããïœ ãå3ãããã«å¯ŸããŠäœãããã®ãïŒ ïœãªã¹ã¯è©äŸ¡ãšå¯Ÿçïœ ãå4ãååã«ããŸãã§ãããïŒ ïœãµããããïœ ã»ãŒãã£ãŒã§ã®æŽ»çšäºäŸ 1. ã»ãã¥ãªãã£ã¬ãã¥ãŒãžã®ãéšåå°å
¥ã 2. ãããã«å§ããããããã³ãã¬ãŒãã®çšæ 3. çæAIããå¯æçžŠå£«ãã«ãã ãããã« ãããããè
åšã¢ããªã³ã°ãã£ãŠäœïŒ äžèšã§ãããšã ãã·ã¹ãã ãäœãåã«ãæ»æè
ã®èŠç¹ãèžãŸããèµ·ãããå°ãããšããåæãã察çãèããæŽ»åã ã§ãã éåžžãéçºã®çŸå Žã§ã¯ãã©ããªæ©èœãäœããïŒèŠä»¶ïŒãããã©ããã£ãŠäœããïŒèšèšïŒãã«éäžããã¡ã§ããããã« ãäœãåé¡ã«ãªããããïŒã»ãã¥ãªãã£ãªã¹ã¯ïŒã ãšããèŠç¹ããã©ã¹ããŸãã ãªãä»ãç§ãã¡ããããæšãã®ã çç±ã¯å€§ãã2ã€ãããŸãã ãã·ããã¬ãããã®äžçæšæºã ãã NISTã®ãSSDFããOWASPã®ãSAMM v2ããªã©ãäž»èŠãªã¬ã€ãã©ã€ã³ã§æšå¥šãããŠããŸããèšè𿮵éã§ãªã¹ã¯ã朰ãããšã§ãææ»ããé²ãããã§ãã çããã»ãã¥ãªãã£æè²ã«ãªãããïŒâ
æéèŠïŒ ç§ãç¹ã«éèŠããŠããã®ã¯ãã¡ãã§ããè
åšã¢ããªã³ã°ãè¡ãã«ã¯ããšã³ãžãã¢ãPMãã»ãã¥ãªãã£æ
åœè
ãéãŸã£ãŠäŒè©±ãããå¿
èŠããããŸãã ãããã®ããŒã¿ã£ãŠãã©ãããæµãã§DBã«å
¥ããã ã£ãïŒã ããã®APIãèªèšŒãªãã§å©ãããããºãããïŒã ããããäŒè©±èªäœãã座åŠã®ç ä¿®ãããã¯ããã«å¹æç㪠ãçããã»ãã¥ãªãã£æè²ã ã«ãªããŸãããã¡ã€ã³ç¥èãšã»ãã¥ãªãã£ç¥èãã察話ãéããŠããŒã å
šäœã«æã¿æž¡ãã®ã§ãã è
åšã¢ããªã³ã°ã®é²ãæ¹ïŒè§£èª¬ãšã»ãŒãã£ãŒæµã®å®è·µïŒ ã§ã¯ãå
·äœçã«ã©ãé²ããã°ããã®ã§ããããïŒ åºæ¬ã¯ä»¥äžã® ã4ã€ã®éèŠãªè³ªåã ã«çãã圢ã§é²ããŠãããŸãã ããã§å€§äºãªå¿æ§ã㯠ãå®ç§ãç®æããªãã ããšãã»ãŒãã£ãŒã§ã¯ã ãééã£ãŠãããããããŸãã¯ãã¯ã€ãããŒãã«çµµãæããŠè©±ããã ãåèšèã«ããŠããŸãã 4ã€ã®éèŠãªè³ªå ãå1ãç§ãã¡ã¯äœã«åãçµãã§ãããïŒ ïœã¢ãã«ãäœãïœ ãŸãã¯ãã·ã¹ãã ã®ã圢ããå¯èŠåããŸããäžè¬çã«ã¯ãããŒã¿ãããŒãã€ã€ã°ã©ã ïŒDFDïŒãæšå¥šãããŸãã â DFDã®æžãæ¹ïŒãããªã詳现ãæããªãïŒ DFDã¯ãããŒã¿ãã©ãããæ¥ãŠãã©ããžè¡ãã®ãããšããæµãã«æ³šç®ããå³ã§ãã 以äžã®5ã€ã®èŠçŽ ã§å³ã衚çŸããŸãã ããã»ã¹ (Process) ïŒåŠçãæ©èœïŒäžžïŒ ããŒã¿ã¹ã㢠(Data Store) ïŒDBããã¡ã€ã«ãªã©ã®ããŒã¿ãçãŸããšããïŒäºæ¬ç·ïŒ å€éšãšã³ãã£ã㣠(External Entity) ïŒãŠãŒã¶ãŒã飿ºã·ã¹ãã ïŒåè§ïŒ ããŒã¿ãã㌠(Data Flow) ïŒããŒã¿ã®æµãïŒç¢å°ïŒ ä¿¡é Œå¢ç (Trust Boundary) ïŒã€ã³ã¿ãŒããããšç€Ÿå
LANã®éãªã©ã®å¢çç·ïŒç¹ç·ïŒ ããããèœãšã穎ãããæåããè©³çŽ°ã«æãããšããŠæ«æããããšããããšãç§ãã¡ã¯ ãæœè±¡ããå
·äœãžã ãšãã2ã¹ããããããããããŠããŸãã â ã³ã³ããã¹ããã€ã€ã°ã©ã ã§ãŸãã¯ãå€ããšãäžããåãã ã·ã¹ãã å
šäœã1ã€ã®ãç®±ããšããŠæããå€éšïŒãŠãŒã¶ãŒã飿ºã·ã¹ãã ïŒãšã®ããåãã ããæããŸããããã ãã§ãå®ãã¹ãç¯å²ããæç¢ºã«ãªããŸãã â¡ ã¬ãã«0ãã€ã€ã°ã©ã ã§å
éšæ§é ãåè§£ãã æ¬¡ã«ãç®±ã®äžèº«ãäž»èŠãªããã»ã¹ã«åè§£ããããŒã¿ã®ä¿åå ŽæïŒããŒã¿ã¹ãã¢ïŒãæãè¶³ããŸãã ããã§æãéèŠãªã®ã ãä¿¡é Œå¢çïŒTrust BoundaryïŒã ãšããç¹ç·ã§ãããããããŒã¿ããŸãããšããè
åšãçºçãããããªããŸãã å¿
èŠã«å¿ããŠãããããããã«ã¬ãã«1âŠãã®ããã«è©³çްåããŠãããŸãã â ã»ãŒãã£ãŒæµã®å®è·µïŒå³å¯ããããã察話ã®çš®ãïŒ æç§æžéãã®èšå·ïŒäžžãäºæ¬ç·ãªã©ïŒã䜿ãããšãããšãããã§ãã£ãŠãïŒããšæãæ¢ãŸããã¡ã§ããç§ãã¡ã®çŸå Žã§ã¯ã ããã¯ã€ãããŒãïŒãŸãã¯MiroïŒã«10åãããã§æããã¬ãã«ã§ããã ãšããŠããŸãã å³å¯ãªèšæ³ããã ãããŒã¿ã®æµãïŒç·ïŒã ãåã£ãŠããã°OKã 詳现ãªèšèšå³ã§ããå¿
èŠã¯ãªããå
ã»ã©ã® ãä¿¡é Œå¢çïŒç¹ç·ïŒãããŸããå Žæ ããããã°ããããæ»æãã€ã³ãã ãšå€æã§ããã å ããŠãäžåºŠã§çµããã«ãããåŸã
ã«è©³çŽ°åºŠãäžããŠããã¹ã¿ã€ã«ãåã£ãŠããŸãã ð ãã£ãšåŠã³ããæ¹ãž å
·äœçãªDFDã®äœãæ¹ã¯ãæžç±ãããŒã¿ãããŒãã€ã¢ã°ã©ã ãã«ããã®æè¡ããããã ã·ã¹ãã èšèšã®å¯èœæ§ãïŒå€§å¶åå¹žãæŸæ°žå®å³° / ç¿æ³³ç€ŸïŒãéåžžã«åèã«ãªããŸãã ãå2ãäœãåé¡ã«ãªããããïŒ ïœSTRIDEã§ãªã¹ã¯ãèŠã€ããïœ ã¢ãã«ãã§ããããæ¬¡ã¯ããããæ»æããããã©ããªãïŒããèããŸãã ããã§ã®ãã€ã³ãã¯ãé«åºŠãªãããã³ã°æ¹æ³ãèªãã®ã§ã¯ãªãã ãèµ·ãããå°ãããšã ãæŽãåºãããšã§ããæ»æææ³ã®è©±ã«ãªããšå°éå®¶ããããããªããªããŸããããå°ãããšããªãé¢ä¿è
å
šå¡ã§è°è«ã§ããŸãã â STRIDEãã¬ãŒã ã¯ãŒã¯ è
åšãèŠã€ããåãå£ãšããŠã ãSTRIDEïŒã¹ãã©ã€ãïŒã ãšãããã¬ãŒã ã¯ãŒã¯ã䜿ããšäŸ¿å©ã§ãã以äžã®ãããªãåãããããããªããå1ã§äœæããDFDäžã«ä»ç®ã§æžãåºããŠãããšã¹ã ãŒãºã§ãã é æå è
åšã®çš®é¡ åãããã®äŸ å
·äœäŸïŒWebã¢ããªïŒ S Spoofing (ãªãããŸã) ç§ãã¡ãŸãã¯ãŠãŒã¶ãŒã¯ããªãããŸããèµ·ããŠäœãå°ããïŒ ä»äººã®ã¢ã«ãŠã³ãã§ãã°ã€ã³ããã T Tampering (æ¹ãã) ç§ãã¡ãŸãã¯ãŠãŒã¶ãŒã¯ãããŒã¿æ¹ãããèµ·ããŠäœãå°ããïŒ DBã®å€ãéä¿¡å
å®¹ãæžãæãããã R Repudiation (åŠèª) ç§ãã¡ãŸãã¯ãŠãŒã¶ãŒã¯ãåŠèªã§ããç¶æ
ã§äœãå°ããïŒ ãæäœããŠããªãããšèšãéãããã I Information Disclosure (æ
å ±æŒæŽ©) ç§ãã¡ãŸãã¯ãŠãŒã¶ãŒã¯ãããŒã¿æŒæŽ©ãèµ·ããŠäœãå°ããïŒ å人æ
å ±ãæ©å¯ããŒã¿ãæŒãã D Denial of Service (ãµãŒãã¹æåŠ) ç§ãã¡ãŸãã¯ãŠãŒã¶ãŒã¯ãã·ã¹ãã ã®åæ¢/é
å»¶ãèµ·ããŠäœãå°ããïŒ ã·ã¹ãã ãããŠã³ããŠäœ¿ããªããªã E Elevation of Privilege (æš©éææ Œ) ç§ãã¡ãŸãã¯ãŠãŒã¶ãŒã¯ãæš©éãè¶ããæäœãã§ããŠäœãå°ããïŒ äžè¬ãŠãŒã¶ãŒã管çè
æäœãè¡ã â ã»ãŒãã£ãŒæµã®å®è·µïŒãæè忢ãé²ãã«ã³ãããšããŠäœ¿ã STRIDEãäºåã«ãã¹ãŠæèšããå¿
èŠã¯ãããŸãããç§ãã¡ã¯äžèšã®ãããªå
·äœäŸãããã€ãæ·»ãã衚ããåããç«ãŠãããã®ã«ã³ãããšããŠäœ¿ã£ãŠããŸãã ã¬ãã¥ãŒã®å Žã§åããããããã®ããªã¬ãŒã«ãªãã°ååã§ãããšã³ãžãã¢ããããããã ãšããããããšãèµ·ãããšå°ããŸããããšæ°ã¥ãã°ããããç«æŽŸãªè
åšåæã§ããå°éçšèªãèŠããããã ãå°ãããšããèšèªåã§ããããš ãéèŠããŠããŸãã ð ãã£ãšåŠã³ããæ¹ãž STRIDEãã»ãã¥ã¢èšèšã«ã€ããŠã¯ãæžç±ãã»ãã¥ã¢ãªãœãããŠã§ã¢ã®èšèšãšéçº è
åšã¢ããªã³ã°ã«åºã¥ãæ®éçã¢ãããŒããïŒããŒã¬ã³ã»ã³ã³ãã§ã«ã㌠/ ç§åã·ã¹ãã ïŒãããããã§ãã ãå3ãããã«å¯ŸããŠäœãããã®ãïŒ ïœãªã¹ã¯è©äŸ¡ãšå¯Ÿçïœ è
åšãããããåºãŠãããšããå
šéšçŽããªããŠç¡çïŒããšãªã£ãŠããŸããŸãããã 倧äºãªã®ã¯ããåæã«ãã¹ãŠã察çããããšã¯ã§ããªãã ãšããåæã«ç«ã€ããšã§ãããªãœãŒã¹ãæéãæéã§ããããåªå
é äœãã€ããå¿
èŠããããŸãã ãªã¹ã¯ãããïŒ ãçºç確çãÃã圱é¿åºŠãã§å®æ§çã«è©äŸ¡ããŠåªå
åºŠãæ±ºããŸãã 察çïŒ ãªã¹ã¯ãé«ãã®ãã®ããé ã«ãã±ããåããããã¯ãã°ã«ç©ã¿ãŸãã â ãªã¹ã¯ãããã®äŸ â ã»ãŒãã£ãŒæµã®å®è·µïŒå¿
èŠã«å¿ããŠè©äŸ¡æ¹æ³ãå€ãã æç§æžçã«ã¯å³å¯ã«ã¹ã³ã¢ãªã³ã°ããŠè©äŸ¡ããããšãæšå¥šãããã¡ã§ãããå
šãŠã®ãªã¹ã¯ã§ããããããšã¹ããŒããèœã¡ãŠããŸããŸãã ã»ãŒãã£ãŒã§ã¯ã察象ã·ã¹ãã ãæ
å ±ã®éèŠåºŠã«å¿ããŠãè©äŸ¡æ¹æ³ïŒç©å·®ãïŒãã䜿ãåããŠããŸãã ã¹ããŒãæãæè»æ§ãæ±ããããéåžžã®æ©èœã¯ãã宿§è©äŸ¡ïŒé«ã»äžã»äœïŒãã§ã¹ããŒãã£ã«å€æãã察çã®èŠåŠã決ããŸããäžæ¹ã§ã決æžåšããç¹ã«éèŠãªåºç€ã·ã¹ãã ã¯ããå®éè©äŸ¡ïŒ CVSS ã OWASP Risk Rating Methodology çïŒããçšããŠå³å¯ã«ã¹ã³ã¢ãªã³ã°ããç£æ»ã«ãèãããæ ¹æ ãæ®ããŸãããã¡ããã2ã€ãçµã¿åãããã±ãŒã¹ããããŸãã ãã¹ããŒãéèŠããšãå³å¯ããã®ã¡ãªããªãã€ããããšããããç§ãã¡ã¯å€§åã«ããŠããŸãã ð ãã£ãšåŠã³ããæ¹ãž ãªã¹ã¯è©äŸ¡ã®æ·±æãã«ã¯ãæžç±ãè
åšã€ã³ããªãžã§ã³ã¹ã®æç§æžãïŒç³å·æä¹
/ æè¡è©è«ç€ŸïŒãåèã«ãªããŸãã ãå4ãååã«ããŸãã§ãããïŒ ïœãµããããïœ ãã®ãµããããã¯é£ã°ãããã¡ã§ãããå®ã¯è
åšã¢ããªã³ã°ãçµç¹ãããŒã ã«æµžéãããããã«ã¯ããšãŠãéèŠãªåãã«ãªããŸãã 察çã劥åœãã©ããã®è©äŸ¡ã倧äºã§ããããè
åšã¢ããªã³ã°ã®é²ãæ¹èªäœãã©ãã ã£ããã ã®ãµããããã§çµéšåŠç¿ã®ãµã€ã¯ã«ãåããŸãã â ã»ãŒãã£ãŒæµã®å®è·µïŒ10åã§çµãããããã¿ã€ã ããã¯ã¹ãïŒ ãµããããã®ææ³ã¯å€æ°ãããŸãããã»ãŒãã£ãŒã§ã¯è»œéã«å®æœã§ãããïŒ/ÎïŒãã©ã¹/ãã«ã¿ïŒããæ¡çšããŠã ã10åéã ãšããæéãåºåã£ãŠå®è·µããŠããŸããçç±ã¯ãéããããšç¶ããªãããã§ããç¶ç¶æ§ã倧äºã ãDFDã®ã¹ã³ãŒããåºãããŠè°è«ãçºæ£ãããã ãÃÃããã詳ãããããæ¬¡ã¯åŒãŒãã ããããå°ããªæ¹åã®ç©ã¿éãïŒã¢ãžã£ã€ã«ãªã¢ãããŒãïŒããããŒã ã®ã»ãã¥ãªãã£çèãè²ãŠãŠãããŸãã ð ãã£ãšåŠã³ããæ¹ãž ãµããããã®ææ³ãæçšæ§ãåŠã¶ãªããæžç±ãã¢ãžã£ã€ã«ãªããŒã ãã€ãã ãµããããã¬ã€ããã㯠å§ãæ¹ã»ãµããããã®åã»ææ³ã»ãã€ã³ãã»ãããïŒæ£® äžæš¹ïŒç¿æ³³ç€ŸïŒãããããã§ãã ã»ãŒãã£ãŒã§ã®æŽ»çšäºäŸ ãããŸã§è
åšã¢ããªã³ã°ã®ææ³ãšã»ãŒãã£ãŒæµã®å®è·µããäŒãããŸãããã§ã¯ããããå
·äœçã«ã©ã®ããã«çŸå Žã«èœãšã蟌ãã§ããã®ãïŒç§ãã¡ã®çŸåšã®åãçµã¿ã玹ä»ããŸãã 1. ã»ãã¥ãªãã£ã¬ãã¥ãŒãžã®ãéšåå°å
¥ã ãããŸã§ãã§ãã¯ãªã¹ãããŒã¹ã§è¡ã£ãŠããã»ãã¥ãªãã£ã¬ãã¥ãŒã®äžéšã«ãè
åšã¢ããªã³ã°ãåãå
¥ãå§ããŠããŸãã éçºè
ãã説æãåããéãã»ãã¥ãªãã£ããŒã ãæå
ã§ç°¡æçãªã¢ãã«ãäœãããããã®ããŒã¿ã®æµããä¿¡é Œå¢çãŸããã§ããã©å€§äžå€«ïŒããšãã£ã察話ãããŸãã ãã§ãã¯ãªã¹ãã ãã§ã¯èŠããªãéèŠç®æã®ã¬ãã¥ãŒãã§ããŸãããéçãªã¢ãŒããã¯ãã£å³ãããããŒã¿ãããã»ã¹ã®æµããæŽçã§ããã®ã§ãéçºè
ããã奜è©ã§ããç§èªèº«ããå€ãã®ã»ãã¥ãªãã£ã¬ãã¥ãŒã宿œããäžã§ããããã©ããªã£ãŠãã£ãïŒããšãªã£ããšãã«ãã¬ãã¥ãŒæã«äœæããã¢ãã«ãèŠãããšã§æãåºãããšãã§ããŠå©ãã£ãŠãŸãã ã»ãã¥ãªãã£ã¬ãã¥ãŒã§äœã£ãè
åšã¢ãã«ã®äŸ 2. ãããã«å§ããããããã³ãã¬ãŒãã®çšæ ãæºåãé¢åããšããå¿ççããŒãã«ãäžããããããªã³ã©ã€ã³ãã¯ã€ãããŒãããŒã«ïŒMiroïŒã« ãè
åšã¢ããªã³ã°ãã³ãã¬ãŒãã ãäœæããŸããã DFDã®ããŒããšSTRIDEã®ä»ç®ããããŠãé²ãæ¹ãããããããé
眮ãããŠããŸãããããéãã°ãããã«è°è«ã«å
¥ããç¶æ
ãäœã£ãŠããŸãã è
åšã¢ããªã³ã°ãã³ãã¬ãŒãïŒMiroïŒ 3. çæAIããå¯æçžŠå£«ãã«ãã ãããæè¿ã®ããããããã¯ã§ããç§ãã¡ã¯ çæAIïŒGeminiçïŒ ãç©æ¥µçã«æŽ»çšããŠããŸãã ãŒããããã©ããªè
åšãããïŒããšèããã®ã¯ãèªç¥è² è·ãé«ãäœæ¥ã§ããããã§ãã·ã¹ãã ã®æŠèŠããŠãŒã¹ã±ãŒã¹ãAIã«äžããŠã ãDFDã®ãã©ãããããæ³å®ãããè
åšãªã¹ãã ãåºåãããŸãã ãã¡ããAIã®åºåã¯å®ç§ã§ã¯ãããŸããããããã ãAIãåºãã80ç¹ã®åçããã人éã®ãšã³ãžãã¢ããã»ãŒãã£ãŒã®çŸå Žç¥èïŒãã¡ã€ã³ç¥èïŒãã§ä¿®æ£ã»è£å®ããŠ100ç¹ã«ãã ãšããããã»ã¹ã¯ããŒãããèããããå§åçã«å¹ççã§ãã äŸãã°ããå°èŠæš¡ãªIoTã¯ã©ãŠãã«ã¡ã©ã·ã¹ãã ããšãããé¡ã§Geminiã«åºåãããäŸããã¡ãã§ããïŒæ³šïŒã»ãŒãã£ãŒã®ã·ã¹ãã ã§ã¯ãããŸããïŒ Geminiãåºåããã¢ãã«ïŒMermaidïŒ Geminiãåºåãããªã¹ã¯ã®äžäŸ ãã«ã¡ã©ã®ç©çççé£ããšãã£ããIoTãªãã§ã¯ã®ãªã¹ã¯ãŸã§ææããŠãããŠããŸãããããå©ãå°ã«ããããšã§ãè°è«ã®ã¹ã¿ãŒãå°ç¹ã倧å¹
ã«é²ããããšãã§ããŸãã ãããã« è
åšã¢ããªã³ã°ãçµç¹ã«æµžéãããããã«äžçªå€§åãªããšãããã¯ã ãæåããå®ç§ãç®æããªãã ããšã§ãã æåããæ£è§£ã®å³ãäœãããšãããšæãæ¢ãŸã£ãŠããŸããŸãããééã£ãŠãŠãããããããŸãã¯ãã¯ã€ãããŒãã«çµµãæããŠè©±ãããããã®ã¹ã¿ã³ã¹ããããã»ãã¥ãªãã£æåãäœãç¬¬äžæ©ã ãšç§ã¯ä¿¡ããŠããŸãã ãã®èšäºãèªãã§ããã¡ãã£ãšé¢çœããã ãªããšæã£ãæ¹ã¯ããã²æ¬¡ã®èšèšã¬ãã¥ãŒã§ ããããæ»æè
ã«çããããšããŠãèµ·ãããå°ãããšã¯äœã§ãããïŒã ãšåããããŠã¿ãŠãã ããã ã»ãŒãã£ãŒã§ã¯ãããããã察話ãã倧åã«ããªãããã»ãã¥ãªãã£ããå°éå®¶ã ãã®ä»äºããããåŸæ¥å¡ã¿ããªã®ä»äºãã«å€ããŠããããšããŠããŸãã ãäžç·ã«æåãäœã£ãŠããããïŒããšããæ¹ãããã°ããã²ã«ãžã¥ã¢ã«ã«ã話ãããŸãããïŒ https://safie.co.jp/teams https://open.talentio.com/r/1/c/safie/pages/71628
ãã®èšäºã¯ Safie Engineers' Blog! Advent Calendar ã®7æ¥ç®ã®èšäºã§ãã æ
å ±ã·ã¹ãã ã°ã«ãŒãã®æŸå°Ÿã§ãã 以åãåœããã°ã«ãŠãæ
ã·ã¹ããŒã ãã¢ãžã£ã€ã«åã®ä»äºã®è©±ãžå€é©ããéã®èšäºãæžãããŠããã ããŸããã engineers.safie.link ä»åã¯ãã®ç¶ç·šãšããŠãã¢ãžã£ã€ã«ãªããŒã äœããããã«é²ããäžã§çãŸããã ããããããªã¹ãããçšããç¶ç¶çæ¹åïŒã«ã€ãŒã³ïŒã®åãçµã¿ ã«ã€ããŠã話ãããŸãã ãé ããè² åµããžã®æ°ä»ã å¿ççããŒãã«ãäžããããããããªã¹ãã ç»é²ã³ã¹ããäžãããä»çµã¿ã ããããããããçãŸããå
·äœçãªã«ã€ãŒã³ 1. å
¥ç€ŸãããŒã«ãããããã»ã¹ã®æšæºå 2. é害察å¿ã®è±å±äººåïŒã¯ãã¹ãã¡ã³ã¯ã·ã§ãã«ãªããŒã ãžïŒ ãªãŒããŒä»»ãã«ããªããæç¶å¯èœãªéçšã«åã㊠ãé ããè² åµããžã®æ°ä»ã ã¹ããªã³ããåãäžã§ãæ¥ã
ã®æ¥åã«åãããã¡ãªãå°ããªéåæããæŸçœ®ããããšã§ãåé¡ãçºçããããšã«æ°ã¥ããŸããã ãããã¯åŸã§å¯Ÿå¿ããã»ãããããããšäŒè©±ã«ã¯åºããã®ã®ãã¿ã¹ã¯åãããã«æµããŠããŸããå¿ããé ã«åããã©ãã«ãçºçããŠææ»ãã«ãªãããšããããŸããã ããã¯ã¢ãžã£ã€ã«ã§èšããšããã® ãéææ§ã ãæ¬ ããŠããç¶æ
ã§ãããèŠããªãæè¡çè² åµãããŒã ã«èç©ãããŠããç¶æ
ã§ããã ããã§ç§ãã¡ã¯ããå®ç§ãªè§£æ±ºçããæåããæ±ããã®ã§ã¯ãªãããŸã㯠ãå°ããªéåæãããŒã ã§æ€ç¥ããã«ã€ãŒã³ããä»çµã¿ã ãäœãããšã«ããŸãããæ¹éã¯ä»¥äžã®2ç¹ã§ãã ã¹ããã¯ããïŒéæåïŒ: ããããªããããã¡ãã£ãšæ°ã«ãªãããå¯èŠåããå Žæãäœã æ¯ãè¿ãïŒæ€æ»ãšé©å¿ïŒ: 宿çã«èŠçŽããåçºé²æ¢ã®ä»çµã¿ã«å€ãã å¿ççããŒãã«ãäžããããããããªã¹ãã ãã®ä»çµã¿ãåããããNotionã«ããŒã¿ããŒã¹ãäœæããŸããã ããã§éèŠãªã®ã¯ã ãã¿ã¹ã¯ããšããŠç»é²ããã®ã§ã¯ãªãããããããããšããŠç»é²ããããš ã§ãã ãã¿ã¹ã¯ç»é²ããšèšããããšããå®äºæ¡ä»¶ã¯ïŒããæéã¯ïŒããšèããŠããŸããç»é²ã®å¿ççããŒãã«ãäžãã£ãŠããŸããŸãã ã¢ãžã£ã€ã«ãªããŒã ã«ã¯å¿ççå®å
šæ§ãäžå¯æ¬ ã§ããããã ããããããªã¹ãã ãšããååã«ããããšã§ãæªå®æã®ç¶æ
ã§ãæ°è»œã«æŸã蟌ããããã«ããŸããã ç»é²ã³ã¹ããäžãããä»çµã¿ã éçšãã培åºçã«ããŒãã«ãäžãã工倫ãããŸããã æåç»é²: æäŒãéè«ã§åºããã®ã¯ãã®å Žã§è¿œå Slack飿ºã«ããèªåç»é²: Slackäžã§èª²é¡ãããçºèšããã£ãéãç¹å®ã®ã¹ã¿ã³ããæŒããšèªåçã«Notionã®ããããããªã¹ããã«èµ·ç¥šããã ããã«ããããããŒæ
å ±ãšããŠæµããŠããŸããã¡ãªSlackäžã®äŒè©±ãã匷å¶çã«ã¹ããã¯æ
å ±ãšããŠèç©ããä»çµã¿ãæŽããŸããã ãªã¹ãã«å
¥ã£ãé
ç®ã¯ã2é±éã«äžåºŠã®ãµã€ã¯ã«ã§æ£åžããè¡ããŸããããã§åã㊠ãèŠå®ãïŒä»ã¯äœãããªãïŒã ã ã鲿äžïŒã¿ã¹ã¯åããïŒã ãã倿ããŸãã ããŒã ã®ãªãœãŒã¹ã«ã¯éãããããããããããããã¯å
šãŠã®é
ç®ãæ¹åããã®ã§ã¯ãªããçŸæç¹ã§ ã¯çŸç¶ç¶æã§ãåé¡ãªããšããŒã ã§å€æã§ãããã®ã¯äžæŠããçŸåšã®å¯Ÿå¿ã§ç¶ç¶ããã ãšããããšããããŸããã ããããããããçãŸããå
·äœçãªã«ã€ãŒã³ ãã®ãµã€ã¯ã«ãåãããšã§ãå®éã«ã©ã®ãããªæ¹åãè¡ãããããã玹ä»ããŸãã 1. å
¥ç€ŸãããŒã«ãããããã»ã¹ã®æšæºå æ°å
¥ç€Ÿå¡åãã®ITãªãªãšã³ããŒã·ã§ã³ã«ã€ããŠãæ¯æã®æ¯ãè¿ããéããŠããã»ã¹ãæ¹åããŸããã äœæ¥ãããŒã®çµ±äž: éçšåœ¢æ
ããšã«ãã©ãã©ã ã£ãæé ãçµ±äžããè€éæ§ãæé€ïŒãªãã¬ãŒã·ã§ã³ãã¹ã®åæžïŒ ãã£ãŒãããã¯ã®åæ : PCéµéæãä»£æ¿æ©è²žäžæã®ããã€ãªããããããªã¹ãããæŸãäžããäºå察çãããŒã远å äžåºŠæ±ºããã«ãŒã«ãå確èªããçºçããäºè±¡ã«åãããŠãããŒèªäœãã¢ããããŒããç¶ããŠããŸãã 2. é害察å¿ã®è±å±äººåïŒã¯ãã¹ãã¡ã³ã¯ã·ã§ãã«ãªããŒã ãžïŒ ãããã¯ãŒã¯é害ã¯ãã©ãããŠãç¹å®ã®ãšãã¹ããŒãã«äŸåããã¡ãªé åã§ããããããã¢ãžã£ã€ã«ãªããŒã ã¯ã誰ããããªããšåããªããç¶æ
ãè¯ããšããŸããã ããã§ãããããããªã¹ããã«äžãã£ãé害察å¿ãæ¯ãè¿ãã ãåŸæ¥å¡ã®æ¥åãæ¢ããæéãæ¥µåçãããïŒMTTRã®ççž®ïŒ ãããšã«ãã©ãŒã«ã¹ãçµã£ãåå察å¿ããã¥ã¢ã«ãäœæããŸããã ããã«ããã ãããã¯ãŒã¯å°ä»»æ
åœè
以å€ã§ãäžæ¬¡åãåããå¯èœã«ãªããããŒã å
šäœã§ã®å¯Ÿå¿åãåäžããŸããã ãªãŒããŒä»»ãã«ããªããæç¶å¯èœãªéçšã«åã㊠ããããããªã¹ããã®éçšã¯ãçŸåšã¯ã°ã«ãŒããªãŒããŒã§ããç§ããã¡ã·ãªããŒãããããšãå€ãã§ãããé·æçã«ã¯ ããŒã ã¡ã³ããŒã®èª°ãã課é¡ãçºèŠããèªåŸçã«æ¹åãµã€ã¯ã«ãåããïŒèªå·±çµç¹åïŒãç¶æ
ãç®æããŠãããããšèããŠããŸãã ä»åŸã¯éçšã«ãŒã«ã®ããã¥ã¡ã³ãåãé²ãã誰ã§ããã®ããã»ã¹ãéçšã§ããããã«ããŠãããŸãããŸããæºãŸã£ãŠãã ãèŠå®ããã¹ããŒã¿ã¹ã®æ£åžãã宿çãªã€ãã³ããšããŠçµã¿èŸŒã¿ãããããããªã¹ãããå¥å
šã«ä¿ã€ä»çµã¿ ãäœã£ãŠããäºå®ã§ãã æ¥å¹Žä»¥éããããããå°ããªãã«ã€ãŒã³ããç¹°ãè¿ããå€åã«åŒ·ãæ
ã·ã¹ããŒã ãäœã£ãŠãããããšæããŸãã
ãã®èšäºã¯ ã»ãŒãã£ãŒæ ªåŒäŒç€Ÿ Advent Calendar 2025 ã®12æ6æ¥ã®èšäºã§ãã ããã«ã¡ã¯ïŒ ã»ãŒãã£ãŒæ ªåŒäŒç€Ÿã®Androidãšã³ãžãã¢ã®ãžã§ããŒã ( @yujiro45 )ã§ãð æšå¹Žãç§ãæžããã Androidã§SceneViewã䜿ã£ãŠã3D/ARã衚瀺ãã ããšããèšäºã§ãã¢ããªã«3D/ARæ©èœãç°¡åã«å®è£
ã§ããã©ã€ãã©ãªã玹ä»ããŸããã ãããçŸåšãSceneViewã¯ã¡ã³ããã³ã¹ãããŠããããã³ã³ããªãã¥ãŒã¿ãŒããã® GitHubã§ã®ã³ã¡ã³ã ã«ããã°æ°ãããªãªãŒã¹ã®äºå®ã¯ãããŸããã åºå
žïŒGithub, https://github.com/SceneView/sceneview-android/issues/623#issuecomment-3097955731 (2025/11/12ã¢ã¯ã»ã¹) æ¬èšäºã§ã¯ã Android XR ã®æ°ããã©ã€ãã©ãªã SceneCore ãã䜿ã£ãŠãã¢ããªå
ã«3D/ARã衚瀺ããæ¹æ³ã説æããŸãã Android XRãšã¯ Android XRã®Emulatoräœææ¹æ³ SceneView vs SceneCore 3Dã¢ãã«ã衚瀺ãã SceneView SceneCore ExoPlayerã®åç»ã衚瀺ãã SceneView SceneCore ãŸãšã Android XRãšã¯ Android XR ã¯ãAR/VRåãã®ãããã»ãããã¹ããŒãã°ã©ã¹çšã«äœããããAIæèŒã®Android OSã§ããã¢ããªã3D空éã«è¡šç€ºã»æäœã§ããéçºã§ã¯Compose for XRãSceneCoreãªã©ã®ã©ã€ãã©ãªã䜿ã£ãŠå®è£
ããŸãã Android XRã®Emulatoräœææ¹æ³ Android XRã¯ãXRã察å¿ãã端æ«ã§ãã䜿ããªãã®ã§ç«¯æ«æã£ãŠããªãå Žåã¯ãXRã®Emulatorãäœæããªããšãããªãã§ãã ã»ãã·ã§ã³ã®äœæã¯ãAndroid XR ããã€ã¹ã§ã®ã¿ãµããŒããããŠããŸããäºææ§ã®ãªãããã€ã¹ã§ã»ãã·ã§ã³ãäœæããããšãããšãçµæã¯å€±æããŸãã https://developer.android.com/develop/xr/jetpack-xr-sdk/add-session Android Studioã®ããã€ã¹ãããŒãžã£ãŒã§XRã®ã«ããŽãªããããŸããããã§ãXRã®Emulatorãç°¡åã«äœæã§ããŸãã SceneView vs SceneCore 3Dã¢ãã«ã衚瀺ãã ð¡ãã®èšäºã§ã¯ãSceneCoreã®ææ°çïŒå·çæç¹ïŒã§ãã 1.0.0-alpha08 ã䜿çšããŠããŸãã SceneViewã¯ææ°çã® 2.3.0 ã䜿çšããŠããŸãã SceneViewãšSceneCoreã®éããçè§£ãããããäž¡æ¹ã®ã©ã€ãã©ãªã§ãããã€ãåãã®3Dã¢ãã«ã衚瀺ããŠã¿ãŸãããïŒÙ©( 'Ï' )Ù åºå
žïŒSketchfab, https://sketchfab.com/3d-models/android-7c30eda007684abbb78ea4b99d22fc2c ã(2025/11/12ã¢ã¯ã»ã¹) SceneView SceneviewexampleTheme { val engine = rememberEngine() val modelLoader = rememberModelLoader(engine) // 3Dã¢ãã«çšã®ããŒããäœæ val modelNode = ModelNode( // 3Dã¢ãã«ã®èªã¿èŸŒã¿ (/res/raw) modelInstance = modelLoader.createModelInstance(R.raw.android) ).apply { // 3Dã¢ãã«ã®åæèšå® scale = Scale( 1 / 40f ) position = Position( 0f ) } Scene( modifier = Modifier.fillMaxSize(), engine = engine, modelLoader = modelLoader, childNodes = rememberNodes { // ã¢ãã«ããŒãã®è¿œå add(modelNode) } ) } çµæïŒ è©³çŽ°ã¯ã以åã®èšäºã Androidã§SceneViewã䜿ã£ãŠã3D/ARã衚瀺ãã ãã§èª¬æããŠããã®ã§ããã²èªãã§ãã ãããð SceneCore Subspace { val session = LocalSession.current ?: return @Subspace val capabilities = LocalSpatialCapabilities.current var entity by remember(session) { mutableStateOf<GltfModelEntity?>( null ) } LaunchedEffect(session, capabilities.isContent3dEnabled) { // Full Spaceã¢ãŒãã«åãæ¿ã if ( ! capabilities.isContent3dEnabled) { session.scene.requestFullSpaceMode() return @LaunchedEffect } // çæã¯1åã ã if (entity == null ) { // 3Dã¢ãã«ã®èªã¿èŸŒã¿ (app/src/main/assets/models/android.glb) val model = GltfModel.create(session, Paths. get ( "models" , "android.glb" )) // 3Dã¢ãã«ãäœæãã entity = GltfModelEntity.create(session, model).apply { // Positionãèšå®ãã setPose(Pose(Vector3( 0f , 0f , - 1.5f ), Quaternion.Identity)) // Scaleãèšå®ãã setScale( 0.2f ) } } } // Lifecycle管ç DisposableEffect(session) { onDispose { entity?.setEnabled( false ) entity?.parent = null entity = null } } } çµæïŒAndroid XRã§3Dã¢ãã«ã衚瀺ã§ããŸãããïŒ SceneViewãšSceneCoreã®äž»ãªéãã¯ä»¥äžãšãªããŸãã SceneView SceneCore 3D Space Scene Subspace 3Dãªããžã§ã¯ã Node Entity 3Dã¢ãã«ã®Path /res/raw/ app/src/main/assets/models/ Lifecycleå¯Ÿå¿ rememberEngine / rememberModelLoader / rememberNodes ã䜿çšãããšãCompose ãã©ã€ããµã€ã¯ã«ãé¢åã¿ãããlifecycleã察å¿ããã®ã¯äžèŠã§ãã SceneCore ã® Entity 㯠XRåŽã§èªåç Žæ£ãããªããããComposableã®çµäºãã»ãã·ã§ã³åæ¿æã« DisposableEffect(session) å
ã§æç€ºçã«è§£æŸããªããšãããªãã§ãïŒã¡ã¢ãªãªãŒã¯é²æ¢ã®ããïŒã 3Dãªããžã§ã¯ãã®è¿œå æ¹æ³ Scene ã䜿ããšãäžã« Node ãäœæã§ããŸãã childNodes = rememberNodes { add(modelNode) } ã®ããã« Node ã远å ãããšã衚瀺ãããŸãã GltfModelEntity.create(session, model) ãåŒã¶ãšã3Dã¢ãã«çšã® Entity ãäœæããã .add() ããªããŠã衚瀺ãããŸãã 3Dã¹ããŒã¹ã¢ãŒããåãæ¿ãã äžèŠ Android XRã®Entityã䜿ãæã session.scene.requestFullSpaceMode() ã®ããã«ãFull Spaceã¢ãŒãã«åãæ¿ããªããšãããªãã§ãã ExoPlayerã®åç»ã衚瀺ãã åºå
žïŒPexels, https://www.pexels.com/ja-jp/video/13299023/ ã(2025/11/12ã¢ã¯ã»ã¹) SceneView SceneViewã§ä»¥åã®èšäºã Androidã§SceneViewã䜿ã£ãŠã3D/ARã衚瀺ãã ãã§æžããéãã§ãMaterialãäœæããªããšãããªãã§ãã class ExoPlayerVideoMaterial( engine: Engine, exoPlayer: ExoPlayer, private val materialLoader: MaterialLoader, ) { // SurfaceTextureäœæ private val surfaceTexture = SurfaceTexture( 0 ).apply { detachFromGLContext() } // SurfaceTextureâSurfaceäœæ private val surface = Surface(surfaceTexture) // Textureã®ããã«ãFilamentã®Streamäœæ private val stream = Stream.Builder() .stream(surfaceTexture) .build(engine) // Textureäœæ private val texture = VideoTexture.Builder() .stream(stream) .build(engine) // VideoTextureã䜿ã£ãMaterialInstanceäœæ val videoInstance get () = materialLoader.createVideoInstance(videoTexture = texture).apply { setExternalTexture(texture) } init { // ExoPlayerã®Surfaceèšå® exoPlayer.setVideoSurface(surface) } } SceneviewexampleTheme { // ExoPlayerã®èšå® val player = remember { ExoPlayer.Builder(context).build().apply { repeatMode = Player.REPEAT_MODE_ALL } } // ãã£ãã®äœæããExoPlayerVideoMaterial val videoMaterial = ExoPlayerVideoMaterial(engine, player, materialLoader) val videoNode = PlaneNode( engine = engine, // åç»ã¯16:9ã®ãã size = Size( 16f , 9f ), // Nodeã®MaterialInstanceèšå® materialInstance = videoMaterial.videoInstance, ) ARScene( //... childNodes = rememberNodes { // ããŒãã®è¿œå add(videoNode) }, ) } çµæïŒ SceneCore ExoPlayerã® .setVideoSurface() ã䜿ããš Surface ã«åçã§ããŸããSceneCoreã«ã¯ SurfaceEntity ãããã Surface ãæäŸãããããExoPlayerãæ¥ç¶ããŠXRã§åçã§ããŸãã Subspace { val session = LocalSession.current ?: return @Subspace val capabilities = LocalSpatialCapabilities.current val context = LocalContext.current // äœæãã SurfaceEntity ãä¿æ var surface by remember(session) { mutableStateOf<SurfaceEntity?>( null ) } // ExoPlayer ã¯ã³ã³ããŒã¶ãã«ã®ã©ã€ããµã€ã¯ã«ã«åãããŠ1ã€ã ã val player = remember { ExoPlayer.Builder(context).build().apply { repeatMode = Player.REPEAT_MODE_ALL } } // Lifecycleã®ãã DisposableEffect(session) { onDispose { player.clearVideoSurface() player.release() surface?.setEnabled( false ) surface?.parent = null surface = null } } LaunchedEffect(session, capabilities.isContent3dEnabled) { // Full Spaceã¢ãŒãã®åãæ¿ã if ( ! capabilities.isContent3dEnabled) { session.scene.requestFullSpaceMode() return @LaunchedEffect } if (surface == null ) { // SurfaceEntity val surfaceEntity = SurfaceEntity.create( session = session, pose = Pose( // Positionãèšå®ãã Vector3( 0f , 0f , - 1.5f ), ), // åç»ã¯16:9ã®ãã shape = SurfaceEntity.Shape.Quad(FloatSize2d( 16f , 9f )), ) // Scaleãèšå®ãã surfaceEntity.setScale( 0.25f ) // æåã®é»å¡ããé¿ããããã1ãã¬ãŒã ç®ãŸã§é衚瀺 surfaceEntity.setEnabled( false ) // ExoPlayerãSurfaceEntityã«æ¥ç¶ããŠåçïŒres/raw/video.mp4ïŒ val uri = RawResourceDataSource.buildRawResourceUri(R.raw.video) player.setVideoSurface(surfaceEntity.getSurface()) player.setMediaItem(MediaItem.fromUri(uri)) player.prepare() player.addListener( object : Player.Listener { override fun onRenderedFirstFrame() { screen.setEnabled( true ) } }) player.play() surface = surfaceEntity } } } çµæïŒAndroid XRã§åç»ã衚瀺ã§ããŸããïŒð åç»ã衚瀺ããããã«ã SceneView ãš SceneCore ã®äž»ãªéãã¯ä»¥äžãšãªããŸãã SceneView SceneCore ExoPlayerã®è¡šç€ºæ¹æ³ VideoNode ãã³ã¡ã³ãã¢ãŠããããŠããã®ã§ãåç»åççšã® Material ãäœæå¿
èŠããããŸãã SurfaceEntity ã䜿ããšãç°¡åã«åç»åçã§ããŸãã ãŸãšã SceneViewã¯ã¡ã³ããã³ã¹ãããŠããªãã®ã§ãSceneCoreã¯æåãªä»£æ¿ã§ããæžãæ¹ã¯ãããã䌌ãŠãããGoogleãäœã£ãŠããã©ã€ãã©ãªã§ãããã ãåè¿°ã®ãšãããAndroid XRã«å¯Ÿå¿ããããã€ã¹ã§ã®ã¿åäœããŸããäžè¬çãªã¹ããŒããã©ã³ã§ã¯å®è¡ã§ããŸãããããã²Emulatorã§è©ŠããŠéãã§ã¿ãŠãã ããïŒ ã¢ãã€ã«ããŒã ã¯éçºãã仲éãåéããŠããŸãïŒ open.talentio.com open.talentio.com
ãã®èšäºã¯Â Safie Engineers' Blog! Advent Calendar  ã®5æ¥ç®ã®èšäºã§ãã ã¯ãããŸããŠãã¯ãªãªãã£ãããžã¡ã³ããªãã£ã¹ QCDã°ã«ãŒãã®çš²å¡ã§ãã ãã®èšäºãæžãããšæã£ãçç±ã§ããã 2025幎1æã«ã»ãŒãã£ãŒã®QAããŒã ã«ãžã§ã€ã³ããŠãã°ããçµã¡ãŸããã®ã§ãããããã®QAãšã³ãžãã¢ãã»ãŒãã£ãŒã®QAããŒã ã§ã©ããªããšã«åãçµãã§ãããæ¯ãè¿ãããšæããŸããã ããŒã ã®ãã¹ã掻åãæ¹åããããã«ã©ã®ãããªæœçãå®è¡ããŠããã®ããå
±æããããšã§ãQAãšã³ãžãã¢ã®æ¹ã
ãéçºããŒã ã®æ¹ã
ã«ãšã£ãŠäœãããã®ãã³ãã«ãªãã°å¹žãã§ãã MagicPodã§ã®ãã¹ãèªåå QAãããŒã®æ¹å ã¹ã¯ã©ã ã®æ¹å MagicPodã§ã®ãã¹ãèªåå QAãæ
åœããããšã«ãªã£ãã·ã¹ãã ã¯ã¡ããã©ãã¹ãèªååãããããšãããã§ãŒãºã ã£ãããããã®ãã£ããã¢ããããè¡ããŸããã æ¡çšããŠããããŒã«ããMagicPodããšãããã®ã§ãäžèšã®ãããªç¹åŸŽããããŸãã AIã«ããã¹ã¯ãªããäœææ¯æŽïŒèªå修埩 ã€ã³ã¹ããŒã«äžèŠãªæè»œããšãã¯ã©ãŠãã®ç«¯æ«ããã©ãŠã¶ã䜿ã£ãŠããã«ãã¹ãäœæå¯èœ Webã¢ããªã»ã¢ãã€ã«ã¢ããªã«å¯Ÿå¿ MagicPodã¯æè»œããšçŽæçãªæäœãã§ãããšããããšã§ããã¡ãã¯äœãåŠç¿ã³ã¹ãã§å®è£
ã§ããããã«ãªããŸãããMagicPodã«è©³ããã¡ã³ãããªã³ããŒãã£ã³ã°ãããŠãããã®ã倧ããã£ãã§ãã å
±æã¹ãããã倿°ã®æŽ»çšãäžæãªããŒã¿åå²ãªã©ãã¯ãã«ã«ã«äœ¿ãããªãããšãããšãŸãæè¡ã¯å¿
èŠã«ãªã£ãŠããŸãã äžéããã¹ãã®èªååãå®äºã§ããŠãæ¥ã
ã®éçšã«ã®ãããšãããšãããå®çŸã§ããã®ã¯ããŒã ã¡ã³ãã®äœæ¥æéãæ¥ã
åºå®ã§æŒãããã®ãè¯ãã£ããšæããŸãïŒåŒ·å¶åŽåïŒ æ¥ã
åºå®ã®æéã確ä¿ããŠè¯ãã£ããã€ã³ãã¯ä»¥äžã§ãã å®è£
ã§å°ã£ãŠãããšããã質åããŠè§£æ¶ãããã å®è£
ãé²ããã¢ãããŒã·ã§ã³ã«ãªã å
šä»¶æåããæã¯æ°æã¡ãè¯ãã§ããé³¥ãç«ããããããã§ãã ãã®ãèªååã®æéããããããããããã¹ãèªååå®è£
ãçµãã£ãåŸã«å€§ããã®æ¹ä¿®ããã£ãŠããã¹ãèªååã¯è
ãããšãªããéçšãç¶ç¶ã§ããŠããŸãã QAãããŒã®æ¹å ä»ã«åãçµãã ã®ãQAãããŒã®æ¹åã§ãã éšã®ç®æšã§ãã£ããã¹ãã«ãŸã€ããâå·¥æ°åæžâãâå質åäžâãããã³çŸå Žã®âäžâã®è§£æ¶ãšããè»žã§æ¹åã«åãçµã¿ãŸããã æœçã®äžéš å·¥æ°åæžã®æ¹ã§ã¯èªåã§ãã£ãšããããããªãšæããããšããæ¯ãè¿ãããŒãã£ã³ã°ã§ã¡ã³ããŒãã話é¡ã«äžãã£ããã®ãæ¹åäºé
ãšããŠããã¯ã¢ããããŸããã äžèšã®æ¹åãèœã¡çããŠããã¯NotebookLMã䜿ã£ãŠãã¬ããžããŸãšããããéæ©èœèŠä»¶ã®ãã¹ã芳ç¹ãã·ã¹ãããã£ãã¯ã«çã蟌ãããAIã«äžå
·ååæãããããAIã«ãã¹ãã±ãŒã¹ã¬ãã¥ãŒããããããªã©ã«åãçµãã§ããŸãã ãã¹ãèšèšã§å€ãããšããã§ããšãæ¹ä¿®å
容ã«ãã£ãŠã¯ãã¹ãã±ãŒã¹ã®ç²åºŠã倧ããããŠãã¹ãã±ãŒã¹äœæã®å·¥æ°ãæžããããã«ããŸããã ãã¹ã宿œã®æ¹ã§ã¯ã客æ§ã¯Firefoxãã»ãšãã©äœ¿çšãããŠããªããšããäºãããŒã¿ããåãã£ãããããªã°ã¬ãã·ã§ã³ãã¹ãã¯èªåãã¹ãã«ä»»ããŠãæåã§ã®ãã¹ãã倧ããæžãããŸããã ãã¹ãã®æéã¯ãããã§ããããããŸãããå¿
èŠååãªãã¹ããå°ãªãæéã§ãããšããããšãæèããŠããŸãã ã¹ã¯ã©ã ã®æ¹å æåŸã«ã¹ã¯ã©ã ã®æ¹åãšããããšã§æã®ãã€ãªãŒã¹ã¿ã³ãã¢ããã®äžã«ããã§ãã¯ã¢ãŠããã®ã³ãŒããŒãäœãããã«ããŸããã ãã§ãã¯ã¢ãŠãã¯âäœã話ããŠãè¯ããâãšããã³ãŒããŒã§åœçªå¶ã§ãã QAé¢ä¿ã®ã話ãããããšãããã°ã奜ããªæŒ«ç»ãæ ç»ãæè¿è©±é¡ã®ââãããããã«ãªããããããã©ã¿ããªã©ãã§æè²·ã£ãŠããã¢ã¿ãã¯25圢åŒã®ã¯ã€ãºåè² ãããããç«ã®èéããåæ³ãããâèéæ¶²ïŒïŒïŒâããªããè¶³ã«ä»ããŠãŠãããèããã§ããããªã©ãªã©æããç¬ããèµ·ãããããŠããŠæ¥œãã¿ãªæéã«ãªã£ãŠããŸãã ããã¯ããŒã ã®å¿ççå®å
šæ§ãé«ããã®ã«äžåœ¹è²·ã£ãŠãããšæããŸãã ãããã®åãçµã¿ãéããŠãããŒã å
šäœãæ¹å掻åã«å¯Ÿããæèãé«ããããè¯ãQAããã»ã¹ã远æ±ããæåãéžæããã€ã€ãããŸããçŸç¶ã«æºè¶³ããã«ä»åŸãç¶ç¶çã«æ¹åãéããŠããäºå®ã§ãã ãã®æ°ãæã¯ãåã«ãã¹ããããã ãã§ãªããæ°ããããŒã ãšããŠæé·ããããã®åºç€ãç¯ãæéã§ãããä»åŸãããè¯ããããã¯ãå質ãšãã¹ãå質ã远æ±ããéçºããŒã ãšå
±ã«ã客æ§ã®ã«ã¡ã©ç®¡çãæ¥œã«ããçŽ æŽããããããã¯ããäžã®äžã«å±ããŠãããããšæããŸãã
ãã®èšäºã¯Â Safie Engineers' Blog! Advent Calendar  ã®4æ¥ç®ã®èšäºã§ãã ããã«ã¡ã¯ãã«ã«ãã£ãŒïŒã³ãã¥ãã±ãŒã·ã§ã³å®€ã® ããã ã¿ãã ã§ãã ã«ã«ãã£ãŒïŒã³ãã¥ãã±ãŒã·ã§ã³å®€ã¯ã瀟é·çŽèœçµç¹ãšããŠç€Ÿå
å€ã®åºå ±æŽ»åçãæ
åœããŠããããŒã ã§ãããæ åããæªæ¥ãã€ããããšããã»ãŒãã£ãŒã®ããžã§ã³å®çŸã«åããŠãã»ãŒãã£ãŒã«ã«ãã£ãŒããæšé²ããæŽ»åãå
å
ããŠããŸãã ç§ã¯2025幎4æãã¡ããã©åœç€Ÿã®ç€Ÿå¡æ°ã500åãè¶
ããã¿ã€ãã³ã°ã§ã»ãŒãã£ãŒã«è»¢è·ããŸãããã»ãŒãã£ãŒãäžå Žãã2021幎ããæ¯ã¹ããšç€Ÿå¡æ°ã¯2å以äžãããžãã¹ãçµç¹ãå§åçãªã¹ããŒãã§æé·ããŠããäŒç€Ÿã«å
¥ç€Ÿãããªããšæã£ãã®ãèŠããŠããŸãã äžè¬çã«ãçµç¹ãæ¡å€§ãããšãé£ã®ããŒã ãäœãããŠãããåãããªãïŒãµã€ãåïŒãããçµå¶ã®æå³ãäŒãããªãããšãã£ã課é¡ãçãŸããã¡ã§ãã å€ãã®äŒæ¥ã§ã¯ç€Ÿå
å ±ãšããã°ããã¹ããå€ããšæããŸãããç§ãã¡ã¯ãæ åããŒã¿ããæ±ãããã¯äŒæ¥ãšããŠãããã¹ãã§ã¯åãèœãšãããŠããŸããç±éãããæèããããéèŠã ãšèãããåç»ãã«ãã瀟å
ã³ãã¥ãã±ãŒã·ã§ã³ãè¡ã£ãŠããŸããããšããããšã§ãä»åã¯ç§ãæ
åœããŠãã瀟å
åç»ã¡ãã£ã¢ã空ãã¯ãã«ã€ããŠã玹ä»ããŸãã ã空ãã¯ããšã¯ çŸç¶ææ¡ã®ããã®ã¢ã¯ã·ã§ã³ çŸåšãŸã§ã«å®æœããããš ä¿¡é Œé¢ä¿ãã¬ãã¬ããžãããå
¬åŒçºä¿¡ãããããç¥ã£ãŠãã人ã ãåç»ã®åŒ±ç¹ããè£å®ããïŒÎ±ã®èŠçŽããã¹ã ã³ãã¥ãã±ãŒã·ã§ã³ã¯ç¶ããããš ã空ãã¯ããšã¯ 端çã«ãããšãã空ãã¯ïŒåç»ç€Ÿå
å ±ããšèããŠããã ããšã€ã¡ãŒãžãããããããšæããŸããã¹ã¿ãŒãããã®ã¯2023幎10æã§ãä»ãŸã§2幎以äžã«æž¡ãç¶ç¶ããŠç€Ÿå
åãã®çºä¿¡ãç¶ããŠããŸããã ã空ãã¯ãã¯éç§°ã§ãæ£åŒåç§°ã¯ã空é£ã¶ãã¯ããŠ~Safie's company newsletter~ãã§ããã»ãŒãã£ãŒã®ã·ã³ãã«ããŒã¯ã§ãã銎æã¿ã®ããã¯ããŠãã¯ç¥æµã®è±¡åŸŽãšãããŠããŸããã空ãã¯ãã®ååã«ã¯ã瀟å¡äžäººã²ãšããæã€ç¥æµãã·ã§ã¢ãããäºãã®ç¥æµã®åŸªç°ãéããŠã瀟å
ã³ãã¥ãã±ãŒã·ã§ã³ã掻çºã«ããŠãããããšããæ³ãã蟌ããããŠããŸãã 空ãã¯ã¯2ã€ã®ã«ããŽãªã§æ§æãããŠããŸãã Sadoxãµã㳠瀟é·ã®äœæž¡å³¶ãããã¹ããŒã«ãŒãšããŠèªãã³ã³ãã³ã ãã¯ããŠãã¡ã®ç¥æµæ³ 瀟å¡ã®æŽ»èºãéšçœ²ã®åãçµã¿ãèªãã³ã³ãã³ã å·ŠïŒSadoxãµãã³ã2030å¹Žç®æãããš_ã¹ãã¬ããçµç¹ã®èª²é¡ãšè§£æ±ºã«ãããŠã å³ïŒãã¯ããŠãã¡ã®ç¥æµæ³ããã¶ã€ã³ã»ã³ã¿ãŒ_ããŽãã¶ã€ã³ã®ææ³ãšãã»ãŒãã£ãŒãã€ãããã¶ã€ã³ãšã¯ã çŸç¶ææ¡ã®ããã®ã¢ã¯ã·ã§ã³ ç§ãæ
åœã«ãªã£ãŠãŸãè¡ã£ãã®ã¯ã¢ã³ã±ãŒãã§ãã瀟å¡ã®ã空ãã¯ã掻çšç¶æ³ãç¥ããä»åŸã®äŒç»ã«ãããŠåèãšããããã«è¡ãããšã«ããŸããã çµæãšããŠã90ïŒ
以äžã®äººãèªèããŠããã瀟å¡ã®2/3ã¯äœããã®ã³ã³ãã³ãã¯èŠãããšããããšããããžãã£ããªåçãåŸãããŸãããäžæ¹ã§ãèŠãããšããªãïŒããšãã瀟å¡ãå°ãªãããããç¶æ³ãããããŸãããèŠãæ©äŒããªãã£ã人ã¯å€§ããåãããšä»¥äžã®3ã€ã«åé¡ãããããšãææ¡ã§ããŸããã å¿ããèŠãæéããªã æŽæ°ã¿ã€ãã³ã°äžæ ããããååšãç¥ããªãã£ã å±ããçžæã§ããã瀟å¡ãã®çæ§ã®å£°ã確èªããããšã§ãå®éã«æŽ»åã®æ¹åæ§ã決ããããšã«ãç¹ãã£ããããåæã§ã¢ã³ã±ãŒãããšã£ãããšã¯éåžžã«æçšã§ããã çŸåšãŸã§ã«å®æœããããš ã¢ã³ã±ãŒãã宿œãã5æããçŸåšãŸã§ããŸãã¯çæç®ç·ã§ããã«ã§ããããšããã¢ã¯ã·ã§ã³ãè¡ã£ãŠããŸããã倧ããåãããšãåç¥ã®å·¥å€«ããšãããŸããŸãªç€Ÿå¡ãç»å ŽããäŒç»ãã§ãããã®ããã°ã§ã¯ãåç¥ã®å·¥å€«ãã«ãã©ãŒã«ã¹ããŠããå°ã詳ããã話ãããããšæããŸãã ä¿¡é Œé¢ä¿ãã¬ãã¬ããžãããå
¬åŒçºä¿¡ãããããç¥ã£ãŠãã人ã çªç¶ã®è©±ã§ãããå人ããæçŽãæž¡ããããšãããããããå¿
ãç®ãéããŸãããããããšåãã§åãããŒã ãé¢ä¿æ§ã®æ·±ãã¡ã³ããŒããã®Slackã¯ç®ã«ã€ããšæãã®ã§ããããããŸãããç¥ããªã人ããã®å
šäœã«åããSlackã¯èŠèœãšããã¡ã§ã¯ãªãã§ããããã ã空ãã¯ãã®åç¥ã¯ç€Ÿå
ã®SlackãæŽ»çšããŠçºä¿¡ããŠããŸãããå
šäœã¡ã³ã·ã§ã³ã§ã®ç§ããã®åç¥ã¯ãæ
å ±ã®ããã€ãºããšããŠåŠçãããŠããŸãå¯èœæ§ããããšæããŠããŸããã ããã§çç®ããã®ãã瀟å
ã«ãããããœãŒã·ã£ã«ã°ã©ãïŒäººéé¢ä¿ã®ã€ãªããïŒãã®æŽ»çšã§ããæ
åœè
ããèšããããããæ®æ®µé¢ããã®ããååãããåºæŒããã®ã§èŠãŠãã ããããšèšãããæ¹ããå§åçã«èŠèŽææ¬²ãæ¹§ãã¯ãã ã¢ããã°ãªææ³ã§ããããåºæŒè
ã«åç¥ååããé¡ãããããšãããããŒãçµã¿èŸŒãããšã§ããç¹ãã®çºä¿¡ããé¢ãã®åºããã«å€ãã工倫ãåãå
¥ããŸããã æè¿ããåºæŒè
ããã§ã¯ãªãã®ã§ããã瀟å¡ã®æ¹ãé¢çœãããšãèªèº«ã®ããŒã ã«çºä¿¡ããŠããã ããããšã§ã¢ã¯ã»ã¹ãæ¥å¢ããã±ãŒã¹ããããŸããããããã埪ç°ããã£ãšå¢ããããããã®ããã®åæãšããŠã¯ç€Ÿå¡ã®çæ§ããããããïŒããšæã£ãŠãããã³ã³ãã³ããéèŠã§ããäŒç»èªäœãåãå
¥ããŠããŸãããåŒãç¶ãè¯ãã³ã³ãã³ãäœãã«ã¯ç¹ã«æéãå²ããŠãããããšæããŸããã ãåç»ã®åŒ±ç¹ããè£å®ããïŒÎ±ã®èŠçŽããã¹ã æ åã¯å§åçã«åŸãããæ
å ±éãå€ãã®ãã¡ãªããã§ããäžæ¹ã§ããå¿ããæã«æãæ¢ããŠåç»ãèŠãã®ã¯æ£çŽããã©ããåéã ãšããŠãããšããã®ã¯æ£çŽããã®ã§ã¯ãšæããŸãã ãã®ããã空ãã¯NotionããŒãžã§å
¬éããéã«ãèå³ããããããã¯ãã©ãããæ°ç§ã§å€æã§ããããã«ãåç»ã§è©±ãããŠããããšããç®æ¡æžãã§æ·»ããããã«ãã工倫ãã¯ãããŸããã ãŸããèŠçŽã®äœæã«ã¯NotebookLMã«ç·šéããæ åãèªã¿èŸŒãŸããŠãããããããã¹ãæ¡ãæ€èšããããšã§å¹çåãé²ããŠããŸãã ã³ãã¥ãã±ãŒã·ã§ã³ã¯ç¶ããããš æ
åœãåŒãç¶ãéã«åä»»æ
åœè
ã®ã³ã¡ã³ãã§æãå°è±¡ã«æ®ã£ãããšã¯ãç¶ç¶ããŠçºä¿¡ãç¶ããããšã倧äºã«ããŠããããšãã話ã§ããéŠãããããã«ãªããããåæãããŸãããããã¯ãç§ãã³ã³ãã³ãã®çºä¿¡ã¯ç¶ç¶ããŠç¶ããŠããããšã倧äºã ãšæã£ãŠããããã§ãã çŸåšãã»ãŒãã£ãŒã¯éçºæ¬éšãå«ãã5ã€ã®æ¬éšã500人以äžã®ç€Ÿå¡ãããäŒç€Ÿã«æé·ããããžãã¹ãçµç¹ãæŽãªãé£èºã«åããŠã¿ããªã§æ©ã¿ãå éãããŠããŸãã æåŸã«ãªããŸãããã瀟å
ã®æŠç¥ãéçºç§è©±ãªã©ãå«ãŸãããããã空ãã¯ããèŠãããšãã§ããã®ã¯ç€Ÿå¡ã ãã®ç¹æš©ã§ããã»ãŒãã£ãŒã®ãä»äºã«ãèå³ãããæ¹ã¯ æ¡çšãµã€ã ããã²ã芧ãã ããã safie.co.jp ãã®èšäºãèªãã§ããã ããæ¹ãã仲éãšãªãåç»ãèŠãããã¯ããŸãåºæŒè
ãšããŠç»å Žããããšããæ¥ãæ¥ãã®ã楜ãã¿ã«ããŠããŸãã ä»åŸããããé¢çœããã圹ç«ã€ããæ¥œããã空ãã¯ã®çºä¿¡ãæåŸ
ããŠããã ãããšå¬ããã§ãïŒ
ã¯ããã« ãã®èšäºã¯ Safie Engineers' Blog! Advent Calendar ã®3æ¥ç®ã®èšäºã§ãã ããã«ã¡ã¯ãæè¡åºå ±ã®ãããïŒ @hitsan ïŒã§ãã 2024幎ã®äžç€ããæè¡åºå ±ãã¯ããã2025幎ã¯ã»ãŒãã£ãŒã«ãšã£ãŠ ãæè¡åºå ±æŽ»åãæ¬æ Œå§åããã幎ã ãšãããéåžžã«å€§ããªç¯ç®ã®1幎ãšãªããŸããã ãããŸã§ãæè¡çºä¿¡ã¯è¡ã£ãŠããŸããããä»å¹Žã¯çºä¿¡æ°ãå¢ããããšã«æ³šåããŸããã æ¬èšäºã§ã¯ãã»ãŒãã£ãŒã®æè¡åºå ±ãæ²ããããã·ã§ã³ãšã2025幎ã«åãçµãã å
·äœçãªæœçã«ã€ããŠæ¯ãè¿ããŸãã ã¯ããã« ã»ãŒãã£ãŒã«ãããæè¡åºå ±ã®ããã·ã§ã³ ãã¡ã³ãå¢ãããããããåºãã 2025å¹Žã®æŽ»å 1. ã€ãã³ãç»å£æ°ãå¢ãããã 2. æè¡åºå ±å°çšXã¢ã«ãŠã³ããã€ãã£ãã çŽè¿ã®ã€ãã³ãæ
å ± BASEãšã»ãŒãã£ãŒãèªãããã¯ãšã³ãéçºã®æè¡çè² åµè§£æ¶ãžã®éã®ã çæAIã§æ¥åãæ¹åãNightïŒ ãããã« ã»ãŒãã£ãŒã«ãããæè¡åºå ±ã®ããã·ã§ã³ ãã¡ã³ãå¢ãããããããåºãã æè¡åºå ±ãšããŠæ²ããŠããæå€§ã®ããã·ã§ã³ããã㯠瀟å
å€ã«ã»ãŒãã£ãŒã®ãã¡ã³ãå¢ããããš ã§ãã ãã®èšèã«ã¯2ã€ã®æå³ã蟌ããããŠããŸãã ãã»ãŒãã£ãŒã£ãŠæè¡çã«é¢çœãäŒç€Ÿã ãããšèªç¥ããŠãããããšã ãšã³ãžãã¢èªèº«ãèªåãã¡ã®éçºããŠãããããã¯ãã¯ããããšèžã匵ããç¶æ
ãäœãããšã ã©ãã»ã©ããããã¯ããè¯ããŠãäŒãããªããã°ãã¡ã³ã¯å¢ããŸããããã®ããã·ã§ã³ãéæããããã«ã以äžã®ãããª3幎èšç»ãçå®ããŸããã 幎床 ãã§ãŒãº 2025幎 çºä¿¡æåã®éžæ 2026幎 èãæãæèããçºä¿¡ 2027幎 ããã¯ãã©ã³ãã®ç¢ºç« 2025å¹Žã®æŽ»å 2025幎ã®ããŒãã¯ãåå£ã¥ãããšçºä¿¡æåã®éžæãã§ãã æåãäœãããã«ã¯ããŸãè¡åã®ç·éãå¢ããå¿
èŠããããŸããããã§æåžæ°ãå¢ãããŸããã çºä¿¡æ°ïŒæåžïŒãå¢ããã°ããèªåãã¡ã¯æè¡çºä¿¡ãããçµç¹ã ããšããèªèãçãŸãã 第äžè
ã®ç®ã«è§Šããããšã§ããèªåãã¡ãåœããåã«ãã£ãŠããããšã¯ãå®ã¯ãããããšãªãã ããšæ°ã¥ãã ããããå®çŸããããã«ãå
·äœçã«å®è¡ããæœçãã玹ä»ããŸãã 1. ã€ãã³ãç»å£æ°ãå¢ãããã ä»å¹Žã¯ã€ãã³ããžã®åå ã»é嬿°ã¯æšå¹Žãšæ¯èŒããŠ2åã«ãªããŸããã 2024幎ãŸã§ã¯äŸé Œãããã°ç»å£ãããšããã¹ã¿ã³ã¹ã§ããã2025幎ããã¯ä»ç€Ÿãšå
±å¬ããŠã€ãã³ããäŒç»ããããã«ãªããŸããã äŒç»ããè¡ãããšã§ãã¿ãŒã²ããå±€ãäŒãããæè¡ããŒããã³ã³ãããŒã«ã§ããããã«ãªãã以äžã®ãããªãããã¯ãæ·±ãæãäžããããšãã§ããŸããã æ åè§£æã¢ããªã±ãŒã·ã§ã³ã®éçºãã©ãããã©ãŒã æ§ç¯ã®çŽ¹ä» è¥æãšã³ãžãã¢ã®æŽ»èº å€§èŠæš¡ãããã¯ãã«ãããæè¡çè² åµã®è§£æ¶ äŒç»ããæºããããšã§ãåå è
ããã®ãã£ãŒãããã¯ããšã³ãžãã¢ãžçŽæ¥éå
ãããµã€ã¯ã«ãäœããŠããŸãã 2. æè¡åºå ±å°çšXã¢ã«ãŠã³ããã€ãã£ãã å
æãã»ãŒãã£ãŒæè¡åºå ±ã¢ã«ãŠã³ãïŒ @SafieDev ïŒãæ°ãã«éèšããŸããã ã¯ãããŸããŠïŒãã®ã¢ã«ãŠã³ãã¯ãã»ãŒãã£ãŒã®æè¡æ
å ±ããšã³ãžãã¢ã®åãçµã¿ãçºä¿¡ããã¢ã«ãŠã³ãã§ãð ãšã³ãžãã¢ã®çãããæ°ã«ãªãæ
å ±ããå±ãããŸãã ãã²ãæ°è»œã«ãã©ããŒããŠãã ããïŒ #ã»ãŒãã£ãŒ #ãšã³ãžã㢠#éçºè
#æè¡åºå ± — ã»ãŒãã£ãŒæè¡åºå ± (@SafieDev) 2025幎11æ7æ¥ ãããŸã§ã¯äŒæ¥å
¬åŒã¢ã«ãŠã³ãããçºä¿¡ããŠããŸãããã以äžã®çç±ããç¬ç«ãããŸããã ãšã³ãžãã¢ãPdMããã¶ã€ããŒã«ç¹åããæ
å ±ãå±ããã ãšã³ãžãã¢ã®æ¥åžžçãªåãçµã¿ã詊è¡é¯èª€ãçºä¿¡ããã äŒæ¥ã®å
¬åŒã¢ã«ãŠã³ããããé«é »åºŠã§æçš¿ããã ã¢ã«ãŠã³ããåããããšã§ãããã¯ããã°ã®æŽæ°æ
å ±ãã€ãã³ãæ
å ±ã«å ããéçºçŸå Žã®ç©ºæ°æãäŒãããããªçºä¿¡ã匷åããŠããŸãããã²ãã©ããŒããé¡ãããŸãïŒ çŽè¿ã®ã€ãã³ãæ
å ± 12æã¯æ³šç®ã®ã€ãã³ãã2ä»¶éå¬ããŸãããã²ãåå ãã ããã BASEãšã»ãŒãã£ãŒãèªãããã¯ãšã³ãéçºã®æè¡çè² åµè§£æ¶ãžã®éã®ã ææ¥ã12/4(æš)ã«BASEæ ªåŒäŒç€Ÿæ§ãšå
±å¬ã§ããã¯ãšã³ãã®æè¡çè² åµã«ãã©ãŒã«ã¹ããã€ãã³ããéå¬ããŸããã»ãŒãã£ãŒããã¯ãå€§èŠæš¡ãªã¢ãŒããã¯ãã£ã®åãçµã¿ã«ã€ããŠç޹ä»äºå®ã§ãã safie.connpass.com çæAIã§æ¥åãæ¹åãNightïŒ 12/15(æ)ã«ã¯ãçæAIãæŽ»çšããæ¥åæ¹åã€ãã³ããéå¬ããŸãã ãã¡ãã¯LTãã»ãã·ã§ã³ã§ã¯ãªããã¯ãŒã«ãã«ãã§åœ¢åŒãæ¡çšãåå è
å
šå¡ã§æ¥åæ¹åã®ã¢ã€ãã¢ããã£ã¹ã«ãã·ã§ã³ããåå åã€ãã³ãã§ãã safie.connpass.com ãããã« 2025å¹Žã®æŽ»åãæ¯ãè¿ããŸããããæ£çŽã«èšãã°ãå
šå¡ãèªç¶ãšçºä¿¡ããæåã«ã¯ãŸã å°éã§ããŠããŸããã ä»å¹Žã¯ã€ãã³ããšããå Žãçšæããæåžæ°ãå¢ããããšã«ã¯æåããŸããããããããããçµç¹å
šäœã®ç¿æ
£ãšããŠå®çãèªèµ°ããŠãããŸã§ã«ã¯ããŸã ããã€ãã®ããŒãã«ããããŸãã ãŸã ãŸã ææ¢ãã§ããããããããèµ°ãç¶ããã®ã§2026幎ã®ã»ãŒãã£ãŒã®æè¡çºä¿¡ã«ãããã²ãæåŸ
ãã ããã
ãã®èšäºã¯ Safie Engineers' Blog! Advent Calendar 2æ¥ç®ã®èšäºã§ãã ã¯ããã« ç§ã«ã§ããããš æ°ãã«äœã£ããã® ã¢ããªã®çŽ¹ä» äœã£ããã£ãã äœãæ¹ AWS Bedrockã§ãé¡ãçæ Next.jsã§UIå®è£
AWS Amplifyã§ããã〠çµããã« ã¯ããã« ããã«ã¡ã¯ïŒã»ãŒãã£ãŒã«25æ°åã§å
¥ç€ŸããAIéçºéšã«é
å±ãããå·äžã§ãã åŠçæä»£ã¯ç ç©¶ã§ãäººã®æ©ãæ¹ãè§£æããAIã®éçºãããŠããŸããã ãããŠé
å±åã«è¡ãããç ä¿®ã§ã¯ã瀟å
ååã管çããã¢ããªTreasure CollectionãéçºããŸãããïŒTreasure Collectionã®èšäºã¯åŸæ¥æ²èŒãããã®ã§ãã²ãäžèªãã ãããïŒ ãã®èšäºã§ã¯ç§ãæ°ããªæè¡é åã身ã«ä»ããããã«ã¢ããªã®éçºã«ææŠãã話ãããããšæããŸãã ç§ã«ã§ããããš å
ã«è¿°ã¹ãããã«ãåŠçæä»£ã¯Pythonãã€ãã£ãŠæ åã®ç ç©¶ãããŠããŸããããããŠç ä¿®ã®Treasure Collectionã®éçºã§ã¯ãå
¥ç€ŸãããŸã§ã«äœéšããããšããªãã£ãããã³ããšã³ãé åãæ
åœããŸãããç ä¿®ãçµããŠãããã³ããšã³ããšããã¯ãšã³ãïŒããŒã¿åŠçïŒã®é åãçµéšãããšã³ãžãã¢ã«ãªããŸããã ããããªãããã€ã³ãã©é åãåãããªããšããæ°ã¥ããåŸãŸããã Treasure Collectionã¯Webã¢ããªã§ããããã€ãªã©ã®ã€ã³ãã©åãã¯ãã¹ãŠããŒã ã¡ã³ããŒãå®è£
ããŠãããŸãããããã³ããšã³ãã®æè¡ã¯èº«ã«ã€ããããŸããããã¢ããªããŠãŒã¶ãŒã«å±ããæ¹æ³ãåãããªããšããç¶æ³ã«ãªããŸããã æ°ãã«äœã£ããã® ãããããç ä¿®ãçµããåŸã«éçºãã ice-breaker ãšããWebã¢ããªã®ç޹ä»ãããŸãããã®ã¢ããªãäœã£ãããšã§æ°ããªæè¡é åãäœéšã§ãããŠãŒã¶ãŒã«äœã£ããã®ãå±ããããããã«ãªã£ãã®ã§ãããå
±æã§ããã°ãšæããŸãã ã¢ããªã®çŽ¹ä» ice-breakerã¯ããŒãã£ã³ã°ãªã©ã®åé ã§è¡ãã¢ã€ã¹ãã¬ã€ã¯ã»ãã§ãã¯ã€ã³ã®ãé¡ãæäŸããŸãã ã¢ã€ã¹ãã¬ã€ã¯ãšãã§ãã¯ã€ã³ã¯å°ãç°ãªããã®ã§ããã倧ãŸãã«ä»¥äžã®ããã«èª¬æã§ããŸãã ã¢ã€ã¹ãã¬ã€ã¯ããã§ãã¯ã€ã³ãšã¯ ç®çïŒéãŸãã®åé ã§ãåå è
ã®éã®ç·åŒµãã»ãããå Žã«æŽ»æ°ãäžäœæãçã¿åºãããšã ç¹åŸŽïŒãå Žãã®é°å²æ°ã¥ããã«çŠç¹ãåœãŠãã å€ãã®å Žåãã²ãŒã ãç°¡åãªã¢ã¯ãã£ããã£åœ¢åŒã§è¡ãããã åå è
åå£«ãæ°è»œã«è©±ãããã£ãããæäŸããæ¬é¡ã«å
¥ãåã®å¿ççãªéå£ãåãé€ãã ãã®ã¢ã€ã¹ãã¬ã€ã¯ããã§ãã¯ã€ã³ã¯ã»ãŒãã£ãŒã«å
¥ç€ŸããŠããäœåºŠãè¡ã£ãŠããŸããããããŠãã®åºŠãã¢ã€ã¹ãã¬ã€ã¯ããã§ãã¯ã€ã³ã«åœ¹ç«ã€ã¢ããªãéçºããŸããã ã¢ããªã«ã¢ã¯ã»ã¹ãããšæ¬¡ã®ãããªç»é¢ã衚瀺ãããŸãã ç»é¢å·ŠåŽã®â話é¡ãçæâãã¿ã³ãæŒããšãã¿ã³ã®äžã«ãé¡ã衚瀺ãããŸãã åå è
äžèЧã«ååãå
¥åãâ远å âãã¿ã³ãæŒããšåå è
ã远å ãããŠãããŸãã âæ¬¡ã®çºè¡šè
âãã¿ã³ãæŒããšãã¿ã³ã®å·Šã«æ¬¡ã®çºè¡šè
ã衚瀺ãããçºè¡šæžã¿ã«çºè¡šè
ã远å ãããŸãã âæ¬¡ã®çºè¡šè
âãã¿ã³ãäœåºŠãæŒããŠãå
šå¡ãçºè¡šæžã¿ã«è¿œå ããããšâçµäºïŒå
šå¡è©±ãçµãããŸããâãšè¡šç€ºãããŸãã äœã£ããã£ãã é
å±åã«è¡ã£ãŠããç ä¿®ã®é±æ¬¡å®äŸã®åé ã«ã10åçšåºŠã®ã¢ã€ã¹ãã¬ã€ã¯ãè¡ã£ãŠããŸããã ã¢ã€ã¹ãã¬ã€ã¯ã®ãé¡ã¯ãã®éœåºŠèããŠããããã«ããé¡ã«å°ãããšããããŸããã ãŸãé²ãæ¹ã¯ãé¡ãèãã人ãæåã«çºè¡šããŠãçºè¡šããäººãæ¬¡ã®çºè¡šè
ãæåãããšããæ¹åŒããšã£ãŠããŸããããã®é²ãæ¹ã¯ã¢ã€ã¹ãã¬ã€ã¯ãçãäžããããæ¹æ³ã§ããããããããå
šå¡çºè¡šããïŒããšç¢ºèªããããæ¬¡èª°ã«ãããããšæ©ãã ãããŠãæéã䜿ã£ãŠããŸãããã«ã¢ã€ã¹ãã¬ã€ã¯ã®äºå®æéãå°ãè¶
ããŠããŸããšããåé¡ããããŸããã è¡ã£ãŠããã¢ã€ã¹ãã¬ã€ã¯ã®ãããä¿ã¡ãªãããå°ãããšã解決ããããã®ã¢ããªãäœã£ãŠã¿ãããšæã£ãããšããã®ã¢ããªãäœã£ããã£ããã§ãã äœãæ¹ ããããã¯ã¢ããªã®äœãæ¹ã説æããŸãã AWS Bedrockã§ãé¡ãçæ ãŸããã¢ããªã®æ žãšãªããé¡ã®çæã«ã€ããŠã§ãã ãé¡ã®çæã¯çæAIã§è¡ã£ãŠããŸããçæAIã¯AWS Bedrockããå©çšããŸãããAWS Bedrockã«ã¢ã¯ã»ã¹ããAPIããŒãçºè¡ããŸãã Next.jsã§UIå®è£
UIã¯Next.jsã§å®è£
ããŸãããNext.jsã䜿ã£ãçç±ã¯ç ä¿®ã§å¯äžèº«ã«ã€ããããã³ããšã³ãã®æè¡ã¹ã¿ãã¯ã ããã§ãã ã¢ããªã®æ§æã¯ä»¥äžã®ããã«ãªã£ãŠããŸãã src/app/ âââ page.tsx # ã¡ã€ã³UIïŒã¯ã©ã€ã¢ã³ãã³ã³ããŒãã³ãïŒ âââ api/ â âââ bedrock/ â âââ route.ts # Bedrock APIåŒã³åºãïŒãµãŒããŒãµã€ãïŒ âââ components/ âââ addNames.tsx # åå è
远å ã³ã³ããŒãã³ã âââ participants.tsx # åå è
衚瀺ã³ã³ããŒãã³ã UIã¯ã·ã³ãã«ãªã®ã§ãã¹ãŠã®ç޹ä»ã¯æ§ããŸããã工倫ããããšã2ã€ç޹ä»ããŸãã åã話é¡ã衚瀺ãããªãããã«ããã³ãããæ¹å api/bedrock/route.ts ã§ã¯AWS Bedrockã®APIã«ããã³ãããå«ãã ãAPI Requestãéä¿¡ããŠããŸãããã®ã³ãŒãã¯ä»¥äžã®ããã«ãªã£ãŠããŸãã import { BedrockRuntimeClient, ConverseCommand } from "@aws-sdk/client-bedrock-runtime"; import { NextRequest, NextResponse } from "next/server"; export async function POST(request: NextRequest) { try { const url = "xxx"; const history = (await request.json()).history || []; const payload = { "messages": [ { "role": "user", "content": [{"text": "ã¡ãã£ãšå€ãã£ãã¢ã€ã¹ãã¬ã€ã¯ã®è©±é¡ã1ã€è¿ããŠã" + "éå»ã®è©±é¡å±¥æŽ: " + history.join(", ") }] } ], "inferenceConfig": { "temperature": 1.0, "maxTokens": 500, "topP": 1.0, } }; const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${process.env.NEXT_PUBLIC_API_KEY}` }, body: JSON.stringify(payload) }); const data = await response.json(); return NextResponse.json({ output: data }); } catch (error) { console.error("API Error:", error); } } éå»ã®è©±é¡å±¥æŽã page.tsx ãšé£æºããŠããã³ããã«å«ããªãã話é¡ãäœåºŠãçæãããšãã«åã話é¡ã衚瀺ãããªãããã«ããŸããã Next.jsã®ãµãŒããŒãµã€ãããAPI Rrequestãéä¿¡ 以äžã®ã³ãŒã㯠page.tsx ã«å®è£
ããã話é¡ãçæãããšãã«å®è¡ããã颿°ã§ãããã®é¢æ°ã§ã¯ãŸã api/bedrock ã«API Requestãéä¿¡ããŸããããã¯Next.jsã®ãµãŒããŒãµã€ãã§å®è£
ãããŠããAPIã§ãã const onGenerate = async () => { setloading(true); const data = await fetch("/api/bedrock", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ history: history, }), }) .then((res) => res.json()) .then((data) => { setResult(data.output.output.message.content[0].text); setHistory([...history, data.output.output.message.content[0].text]); }) .catch((error) => { console.error("Error fetching data:", error); }); setloading(false); }; å
ã«èª¬æããããã«AWS Bedrockãžã®API Requestã®é信㯠api/bedrock ããè¡ãããŸãã ãã®ããã«APIãçµç±ããŠAWS Bedrockãå©çšããŠããããšã«ã¯çç±ããããŸããããã¯AWS Bedrock ãžã® API Requestã®éä¿¡ã¯ããã³ããšã³ãããè¡ããªãããã§ããã»ãã¥ãªãã£äžã®çç±ã§ãã®ä»æ§ã«ãªã£ãŠããŸãã ä»åéçºã«çšããNext.jsã§ã¯å¥éããã¯ãšã³ããµãŒããŒãç«ãŠãã«ãµãŒããŒãµã€ãã«APIãšã³ããã€ã³ããç«ãŠãããšãã§ããŸããå³ããããéçºäžã«çãã課é¡ã解決ãããã¹ã ãŒãºãªéçºãé²ããããšãã§ããŸããã AWS Amplifyã§ããã〠ããŒã«ã«ç°å¢ã§åäœç¢ºèªãå®äºãããããããã€ã®æºåã§ãã ãããã€ã¯AWS Amplifyã§è¡ããŸãããAWS Amplifyã䜿ã£ãŠæ³å以äžã«æè»œã«ãããã€ãè¡ããŸããã AWS Amplifyãžã¯Githubçµç±ã§ã¢ããªããããã€ã§ããŸãã äœæããã¢ããªãGithubãžpushããã以äžã®AWSã®ããã¥ã¢ã«ã«åŸã£ãŠèšå®ãè¡ããŸãã https://docs.aws.amazon.com/ja_jp/amplify/latest/userguide/setting-up-GitHub-access.html#setting-up-github-app èšå®åŸã«AWS Amplifyã«ã¢ã¯ã»ã¹ãã以äžã®æµãã§AWS Amplifyäžã«ã¢ããªãäœæããŸãããããã€ããŒã¯GithubãéžæããŸããã ãããŸã§é²ããŠãåé¡ããªããã°ãã¹ãŠã®ã¢ããªããããããã€ãå§ãŸã£ãŠããããšã確èªã§ããŸãã5åçšåºŠåŸ
ã€ãšããããã€æžã¿ã«å€ãã£ãŠããŸããã ãã®æç¹ã§ãã¢ããªã¯ãããã€ããã¢ã¯ã»ã¹ããããšãã§ããŸãããããäžã€å¿
èŠãªèšå®ããããŸãã ç°å¢å€æ°ã®èšå®ã§ãã ãã¹ãŠã®ã¢ããªããããããã€ããã¢ããªãã¯ãªãã¯ããŸãããµã€ãã¡ãã¥ãŒã®ãã¹ãã£ã³ã°ãç°å¢å€æ°ãéžæããŠã以äžã®ç»é¢ã«é·ç§»ããŸãã ããã§å€æ°ã¯ããŒã«ã«ç°å¢ã§äœ¿ã.envãã¡ã€ã«ã§æ±ºãã倿°åã§ããå€ã¯ååŸæžã¿ã®AWS Bedrockã®APIããŒãå
¥åããŸãã ãããŸã§è¡ããšã¢ããªã¯ããŒã«ã«ãšåãããã«åäœããŸãããããã€ã»ãªãªãŒã¹ã®å®äºã§ãã çµããã« ãã®èšäºã§ã¯ç§ãåããŠèªèº«ã®åã§ãããã€ãè¡ã£ãã¢ããªã®ç޹ä»ãããŸããã ã¢ããªãäœã£ãŠã¿ãŠèããããšã倧ãã2ã€ãããŸãã 1ã€ç®ã¯ãœãããŠã§ã¢ãµãŒãã¹ã®ç解床ãäžãã£ãããšã§ãããããŸã§ã¯ã©ããã£ãããµãŒãã¹ãšããŠåäœãããã ãããšããæŒ ç¶ãšããçåãæ±ããªããéçºãªã©ãè¡ã£ãŠããŸããããããã©ããã£ããããããææ®µã1ã€ã§ãç¥ããããšã¯ãšãŠãè¯ãããšã ãšæããŸãã 2ã€ç®ã¯å¥ã®AWSãµãŒãã¹ãå©çšããããšæã£ãããšã§ããç§ã¯AIéçºã«é·ãéæºãã£ãŠããŸãããããããã¯ããŒã«ã«ç°å¢ã®ãã·ã³ã§åäœãããã ãã§ããããããæ©ã«ãªãªãžããªãã£ãæã£ãAIã䜿ã£ãã¢ããªããŠãŒã¶ãŒã«å±ããŠã¿ãããšæããŸããã ç§ãã»ãŒãã£ãŒã«å
¥ç€ŸããŠ8ã«æçµã¡ãŸãããããã®éæ°ããæè¡é åãäœéšã身ã«çããªãã課é¡è§£æ±ºã«åãçµããŠããŸãããã®èšäºãèªãã§ããã ãã人ã«ãšã£ãŠãã»ãŒãã£ãŒã§åããªããã©ã®ããã«æè¡ã身ã«çãæé·ã§ããããäŒãããšå¹žãã§ãã
ãã®èšäºã¯ Safie Engineers' Blog! Advent Calendar  1æ¥ç®ã®èšäºã§ãã ã¯ããã« ããããã1on1ããšã¯ïŒ å®çŸ©ã®åç¢ºèª 1on1 ã®ãŽãŒã«ïŒããããå§¿ïŒ äººã«ãã©ãŒã«ã¹ãã察話å1on1ã®ããã å
·äœçãªè³ªåäŸïŒïŒãæè¿ã©ãïŒããããè¯ããã工倫 å
·äœçãªè³ªåäŸïŒïŒæªæ¥å¿åãžã®èªå° 1on1 ã¯çµç¹éçºã®æåç· æåŸã« ã¯ããã« ã»ãŒãã£ãŒã® VPoE å
Œ éçºæ¬éš ãšã³ãžãã¢ãªã³ã°ãªãã£ã¹ 宀é·ã®æŠç°ã§ãã 2023幎ã«ã»ãŒãã£ãŒã«å
¥ç€Ÿãããšã³ãžãã¢çµç¹ã®çµç¹éçºã«åãçµããšã³ãžãã¢ãªã³ã°ãããŒãžã£ãŒãšããŠæŽ»åããŠããŸããã»ãŒãã£ãŒã§ã¯åµæ¥åœåãã 1on1 æå ãæ ¹ä»ããŠãããç§èªèº«2025幎ã«ã¯600件以äžã®1on1ã宿œããŸãããåè·ãå«ãããšã³ãžãã¢çµç¹éçºã®çµéšãšãã³ãŒãã³ã°ãæ¬è³ªè¡ååŠãªã©ã®åŠã³ã掻ããããã©ã€ïŒãšã©ãŒããåŸãã1on1ã®æ¬è³ªãã玹ä»ããŸãã ãããã ã1on1ããšã¯ïŒ å®çŸ©ã®åç¢ºèª ç§ãèãã1on1ã®å®çŸ©ã¯ä»¥äžã®éãã§ãã ð¡ 1on1ãšã¯ïŒ 1on1ãšã¯ãã¡ã³ã¿ãŒãšã¡ã³ãã£ãŒã宿çã«ãã³ããŒãã³ã§è¡ãããŒãã£ã³ã°ã®ããšã 人äºè©äŸ¡ãç®çãšããé¢è«ãšã¯ç°ãªãã äººã®æé·ä¿é²ãšçµç¹ã®æŽ»æ§å ãäž»ãªç®çãšãããäžåžã»éšäžã®é¢ä¿æ§ã«éããã人ãšçµç¹ã®æé·ãä¿ãããã®å¯Ÿè©±ã®å Žã§ããã ãã®1on1ã®å®çŸ©ã«ã¯ ããããæ£è§£ããšããåã¯ãããŸããã 1on1ã§ã¯ãæ¥åã®è©±ã¯ãã¹ãã§ã¯ãªãããšããäžè¬çãªé¢šæœ®ããããŸãããç§ã¯ãã®éãã§ã¯ãªããšèããŸãã ãªããªããã¡ã³ãã£ãŒãç®ã®åã®æ¥åã§å°ã£ãŠããã®ã«ãããã解決ããŠããããããããªã人ã«èããªãã®ã¯ãã©ã¹ãã¬ãŒã·ã§ã³ãããŸãã ããç¡çã«ãã£ãªã¢ã®è©±ã«èªå°ããããã ã¡ã³ãã£ãŒãæ¬åœã«æ±ããŠãã話 ãããããšããçµæçã«æé·ã«ã€ãªãããŸãã 1on1 ã®ãŽãŒã«ïŒããããå§¿ïŒ ã§ã¯ãç®æãã¹ã1on1ã®ãŽãŒã«ïŒããããå§¿ïŒã¯äœã§ããããã ããã¯ ãæ¬¡ã1on1ããããã ãšæã£ãŠããããç¶æ³ãäœãããšã§ãã 1on1ã¯ãäžåºŠããã®ã€ãã³ãã§ã¯ãªã ç¶ç¶ããŠããæå³ã®ãããã® ã«ãªããŸãã ååãããç¶æãã察話ãéããããšã§åããŠãäººã®æé·ãšçµç¹ã®æŽ»æ§åãšããç®çã«è¿ã¥ããŸãã ã¡ã³ã¿ãŒã®ã¹ã¿ã³ã¹ ã¡ã³ãã£ãŒã®ç¶æ³ã«åãããŠèšæ©å¿å€ã«å¯Ÿå¿ãã å
·äœçãªè¡å æ¥åã®è©±ãããã£ãªã¢ã®è©±ããããã³ãŒãã³ã°ãããã°ããã£ãŒãã³ã°ããã éèŠããããš ãã®ç¬éã1on1çŽåŸã«å¿å°ããæéãäœãããšã§ã¯ãªããæã«ã¯ãã¬ãã£ããªãã£ãŒãããã¯ãå¿
èŠ ç®æãç¶æ³ã 察話åŸãæéçµéãšå
±ã«æ°ã¥ãããããè¡åå€å®¹ãä¿ããçµæã䌎ãããšããããŠã察話ãç¶ç¶ã§ããŠããããšã 人ã«ãã©ãŒã«ã¹ãã察話å1on1ã®ããã ãæ¬¡ãããããããšæã£ãŠãããããã®ã³ãããã㯠ã察話ããããç¶æ³ã ãäœãããšã§ãã 察話ããããã®éµã¯ããäºïŒã³ãïŒãã§ã¯ãªã ã人ïŒããïŒãã«ãã©ãŒã«ã¹ ãã質åãããããšã«ãããŸãã â
ãäºããžã®è³ªå vs. ã人ããžã®è³ªå äŸãã°ãã¡ã³ãã£ãŒããé£ãã«è¡ã£ãŠããŸããããšè©±ããå Žåã®è³ªåäŸã§ãã 質åã®çŠç¹ å
·äœçãªè³ªåäŸ ã¡ã³ãã£ãŒã®ååããæ¹ äºã(ã³ã)ã - ã©ãè¡ããŸãããïŒ - é£ããŸãããïŒãããã äºå®ã®æ·±å ã 人ã(ãã)ã - 楜ãããŸãããïŒ - é£ã奜ããªãã§ããïŒ èªåã«åãåã£ãŠãããŠãã ãšæãã話ãããããªã 人㮠ææ
ïŒæ¥œããã奜ããªã©ïŒã«å¯ãæ·»ã 質åãæèãããšãã話ããããããªããŸãã äŸãã°ä»äºã§å€±æãããšãã¯ãªã倱æãããã®ãïŒã§ã¯ãªãããã®æã©ãæã£ãïŒã©ãæãããïŒãªãããæããã®ãïŒã¡ã³ã¿ãŒã®èªåã¯ã©ãæã£ããïŒäŸãã°æ²ããã£ããšãïŒãªã©ããäºãã®ææ
ãæ·±å ãã·ã§ã¢ããããšã§ãã人ã«åãåããããã«ãªããŸãã å
·äœçãªè³ªåäŸïŒïŒãæè¿ã©ãïŒããããè¯ããã工倫 1on1 ã®åãã«ãæè¿ã©ãïŒãããå§ãŸãããšã¯ãããããšæããŸãã ãã ããã®ãæè¿ã©ãïŒãã ãã§ã¯ãå°ããã£ãããªãã§ãã æåã®å°å
¥ãšããŠããã² ã¡ã³ã¿ãŒã®ææ ãä»ãå ããŠã»ããã§ãã ãããããšã¡ã³ãã£ãŒã¯ãã話ãããããªããŸããããã¯ã ã¡ã³ã¿ãŒã®æ°æã¡ïŒææ
ïŒãå
ã«äŒããŠãã ããšã§ãå
±æãçã¿ãããã¹ã ãŒãºãªå¯Ÿè©±ã«ã€ãªãã广ããããŸãã ããè¯ã質åäŸ ãã€ã³ã æè¿ã©ãïŒ ããå®äŸã§ã®ÃÃã®çºè¡šè¯ãã£ããå
容ãã ãã© ã€ãã€ã話ããŠããŠæåããã ããžãã£ããªææ ãäŒãã話ããã£ãããäœã æè¿ã©ãïŒ æ®æ¥æéãå€ããªã£ãŠãããããªã®ã§ ã¡ãã£ãšå¿é
æžå¿µç¹ïŒå¿é
ïŒ ãäŒããå®å
šãªå Žã§è©±ãããšãä¿ã â æ³šæãã¹ã質åäŸ ãæè¿ã©ãïŒå
æ°ããªãããã«æããã©å€§äžå€«ïŒ äœããã£ãïŒ ãã¯è¯ã質åã§ã¯ãããŸããã ãªããªããäœããã£ãïŒãã¯ã äºã®æ·±å ã ã«ã€ãªããããã§ããæ¬åœã«å
æ°ããªããšãã¯ãæ¥åžžã®å°ããªããšã®ç©ã¿éãã§ããããšãå€ãããç¹å¥ãªããšã¯ãããŸããããšããåçã§å¯Ÿè©±ãçµãã£ãŠããŸãå¯èœæ§ããããŸãã ããã æè¿ã©ãïŒå
æ°ããªãããã«æããã©å€§äžå€«ïŒ å¿é
ã§ãã å¿é
ããŠããæ°æã¡ãæ£çŽã«äŒããŠåå¿ãåŸ
ã¡ãŸãããã è£è¶³ ã¡ãªã¿ã«ç§ã¯1on1ãå§ãŸãåã«ãã®äººã®Goodãã€ã³ããæ¢ããšããäºåæºåããããããŸãããã¬ãã£ããªæ
å ±ã¯åºãããããã§ãããããžãã£ããªæ
å ±ã¯ãªããªã衚ã«åºãŠããŸããã1on1ã§ããžãã£ãæ
å ±ã亀æã§ããã°çµç¹å
šäœã®é°å²æ°ã«ãã€ãªãããŸãããã²ãEMã¯ããžãã£ãæ
å ±ãåžžã«æŸã£ãŠ1on1ã«ã€ãªããŠã»ãããšæããŸãã å
·äœçãªè³ªåäŸïŒïŒæªæ¥å¿åãžã®èªå° 1on1ã¯éå»ã®æ¯ãè¿ãïŒãµããããïŒã«ãªããã¡ã§ãã¯ã¯ã¯ã¯ãã«ããåŸåããããŸããéå»ã®çµæã¯åãããã£ãŠããããã§ãã ã§ããã ã æªæ¥ã®è©± ã«èªå°ããŸãããã 質åäŸ ç®ç ååããä»åãŸã§ã® èªå·±æºè¶³åºŠãäœç¹ ãããŸããïŒïŒ100ç¹æºç¹ã§ïŒ ã¡ã³ãã£ãŒã®çŸç¶èªèãåŒãåºã ïŒäŸïŒ60ç¹ãšåçïŒ40ç¹è¶³ããŠããªããã©ããã® 40ç¹ãå¢ããããã«ã¯äœãå¿
èŠã§ããïŒ ç§ãäžç·ã«ååã§ããããšãããŸããïŒ æ¬¡åãŸã§ã® Next Action ãã¡ã³ãã£ãŒäž»äœã§æ±ºãã æªæ¥ã®è©± ãžèªå°ãã ããã§ã®ãã€ã³ãã¯ãã¡ã³ãã£ãŒåŽã ãã§ãªãã ã¡ã³ã¿ãŒåŽã®Next Actionãæ±ºããããš ïŒå°ããªããšã§OKïŒããäºãã®ã³ãããã¡ã³ãã«ãããäžäœæãçãŸããŸãã 1on1 ã¯çµç¹éçºã®æåç· äŒç€Ÿãçµç¹ã¯äººã®éãŸãã§ããã çµç¹ïŒäºº ã§ãã 1on1ã¯ããã®äººã®ããšãç¥ãããã® äžçªã®ææ®µ ã§ãããçµç¹éçºã®æåç·ã§ãã1on1ãæ©èœããããšã§æ
å ±ãæµéããçµç¹ã掻æ§åãããã£ããã«ãªããŸãã ãã²EMïŒãšã³ãžãã¢ãªã³ã°ãããŒãžã£ãŒïŒã®çããã«ã¯ããã®1on1ã䜿ãããªããŠã»ãããšæããŸãã æ£è§£ããªãããããé¢çœãïŒ ãã®èšäºããããªãã®1on1ãæ¥œãããã£ããã«ãªãã°å¹žãã§ãã ð ãŸãšãïŒäººã«åãåã1on1ã®5ã€ã®èŠç¹ 1. åºæ¬ã¹ã¿ã³ã¹ã 1on1ã®ããæ¹ã«æ£è§£ã¯ãªã (ã¡ã³ãã£ãŒã®ç¶æ³ã«èšæ©å¿å€ã«å¯Ÿå¿ãã) 2. ç®çãã 人ïŒãšçµç¹ïŒãæé·ããããã«ã人ïŒãšçµç¹ïŒã«åãåãæéã 3. ãŽãŒã«ã ãæ¬¡ã1on1ããããã ãšæã£ãŠãããããšïŒç¶ç¶ã«ããæé·ãšææïŒ 4. ã³ã ãã ãäºãã§ã¯ãªã ã人ãã«ãã©ãŒã«ã¹ ãã質åã§ããã å
±æãšæ°ã¥ã ãäžãã 5. äŸ¡å€ ãã çµç¹éçºã®æåç·ãšããŠã æ
å ±æµéãšçµç¹æŽ»æ§å ã®ãã£ãããšãªã 6. é¡ããã 1on1 èªäœã楜ãããïŒ æåŸã« æ¬èšäºã§ã¯ãç§ãåãçµãã§ãã1on1ã®å®è·µã®äžéšãã玹ä»ããŸããã 1on1 ã¯å¥¥æ·±ãèªåèªèº«ããŸã ãŸã è¶³ããŠããªãéšåããããåžžã«ãµããããã宿œäžã§ãã ãŸãããã€ã³ãã¯ã»ãã«ãããïŒäŸãã°ã1on1 ã®æ
å ±ãã©ãä»ã®äººã«ã·ã§ã¢ããŠçµç¹å€é©ã«äœ¿ã£ãŠãããïŒãšèããŠããæ¥ã
奮éäžã§ãããŸããã€ãå¥ã®æ©äŒã«ã玹ä»ã§ããã°ãšæããŸãã æåŸã«å®£äŒã§ãïŒã»ãŒãã£ãŒã§ã¯ äžç·ã«åã仲éãåéäž ã§ãïŒ å°ãã§ããèå³ãæã£ãŠããã ãããããã²ä»¥äžã® æ¡çšãµã€ã ãèŠããŠã¿ãŠãã ããã
ã¯ããã« ããã«ã¡ã¯ãã»ãŒãã£ãŒã§ãµãŒããŒãµã€ããšã³ãžãã¢ãããŠããéæã§ãã æ¬èšäºã¯ãffmpegãåããŠäœ¿ãæ¹ãã360床ã«ã¡ã©ã®ãã¯ãŒãåŠçã«ã€ããŠåŠã³ããæ¹ã察象ã«ããŠããŸããå°éçãªç¥èã¯äžèŠã§ãã®ã§ããã²ãæ°è»œã«ãèªã¿ãã ããã ã»ãŒãã£ãŒã§ã¯ãå倩çã«ã¡ã©ãªã©ãéçŒã¬ã³ãºãçšããŠåºç¯å²ãæ®åœ±ãã360床ã«ã¡ã©ã®æ åãåãæ±ã£ãŠããŸãããã®ããããã®ãããªã«ã¡ã©ã®ç»åãæ åããã¯ãŒã (æªã¿ãè£æ£ããæªã¿ã®å°ãªãæ åã«å€æããããš) ãããŠãŒã¹ã±ãŒã¹ãååšããŸããä»äºãããéçšã§ãffmpegã®ãããªãã£ã«ã¿ãŒã䜿ã£ã倿ã«ã€ããŠèª¿ã¹ãã®ã§ãã¡ãã§å
±æããããŸãã ã¯ããã« ffmpegãšvfãªãã·ã§ã³ã«ã€ã㊠ãã¯ãŒãã®å
·äœçãªæé ãŸãšã ffmpegãšvfãªãã·ã§ã³ã«ã€ã㊠ffmpegã¯ãåç»ãé³å£°ãèšé²ã»å€æã»åçãããœãããŠã§ã¢ã§æ§ã
ãªåŠçãè¡ãããšãã§ããŸãããã®äžã§ããvfãªãã·ã§ã³(video filter ãªãã·ã§ã³) ã¯ãå
¥åã«å¯Ÿããæ åãæ¡å€§ãããäžéšåãåãåããè²ãè£æ£ãããªã©ã®åŠç(ãã£ã«ã¿ãŒ) ãé©çšããããšãã§ããæ©èœã§ãã ç°¡ç¥åãããšãäžèšã®ãããªã·ã³ã¿ãã¯ã¹ã§ãªãã·ã§ã³ãæå®ããããšãã§ããŸãã -vf <ãã£ã«ã¿å>=<ãã£ã«ã¿ãŒããšã®ãªãã·ã§ã³> (å®éã«ã¯ãã£ãšè€éãªæå®ãå¯èœã§ãã詳现ã¯å
¬åŒãµã€ãããåç
§ãã ããã https://ffmpeg.org/ffmpeg-filters.html) äŸãã°ãcropãã£ã«ã¿ãŒã§ããã°ãäžèšã®ãããªã³ãã³ãã§ç»é¢ã®äžéšãåãåã£ãæ åãäœãããšãã§ããŸãã ffmpeg -i input.mp4 -vf crop=500:500:100:100 output.mp4 vfãªãã·ã§ã³ã®äžã«ã¯ãv360ãã£ã«ã¿ãŒãããã360床ã«ã¡ã©ã§æ®åœ±ãããéçŒãªã©ã®æ åããã¯ãŒããããæ åã«å€æããããšãã§ããŸãã ãã¯ãŒãã®å
·äœçãªæé 360床ã«ã¡ã©ã®æ åãšç°å¢ã®æºå ä»åã¯ãffmpegã³ãã³ãã䜿ã£ã360床ã«ã¡ã©ã®å€æã«ã€ããŠèª¬æããŸãã å©çšããããŒã«ã®ããŒãžã§ã³ã¯äžèšã«ãªããŸãã ffmpegã®ããŒãžã§ã³ã¯7.1.1ã§ãã ãã¯ãŒãã®ããã®ffmpegã³ãã³ãã®èšè¿° ãã¯ãŒãã®ããã®ffmpegã³ãã³ãã®èšè¿° ä»åã¯ãv360ãã£ã«ã¿ãŒã䜿ã£ãŠãå倩çã«ã¡ã©ãªã©ã§æ®åœ±ããããéçŒ (fisheye)ã圢åŒã®æ åãæªã¿ãè£æ£ããæ åã«å€æããŸãã v360ãã£ã«ã¿ãŒã¯äžèšã®ãããªã·ã³ã¿ãã¯ã¹ã§æ§æãããŠãã âv360=<å
¥åã®åœ¢åŒ>:<åºåã®åœ¢åŒ>:<key=valueã§æå®ãããªãã·ã§ã³> ãšãã£ã圢åŒã§æå®ã§ããŸãã äŸãã°ãäžèšã®ã³ãã³ãã§ããã°æå®ãããªãã·ã§ã³ã§ãéçŒ (fisheye) ã®æ åãããã¯ãŒããããéåžžã®æ åã«å€æãããŸãã ffmpeg -i input.mp4 -vf âv360=fisheye:flat:v_fov=50:yaw=50â output.mp4 v360ãã£ã«ã¿ãŒã§ã¯ãäžèšã®ãããªå
¥å/åºåå
ãçšæãããŠããŸãã e / equirect => Equirectangular projection flat / gnomonic / rectilinear => regular video fisheye => éçŒ pannini => Pannini projection. and etc å
¥å/åºå圢åŒããšã«å¿
èŠãªãã©ã¡ãŒã¿ãŒãå€ãããæ§ã
ãªå€æãè¡ãããšãã§ããŸãã v360ã®ãã£ã«ã¿ãŒã§ã¯ãå
±éã§yaw/pitch/roll ãªã©ã®ã«ã¡ã©ã®èŠç¹ãã³ã³ãããŒã«ãããªãã·ã§ã³ããã«ã¡ã©ã®å転ãå¶åŸ¡ãããªãã·ã§ã³ããããŸãã ä»å䜿çšãã flatãã£ã«ã¿ãŒã§ã¯ãç¹ã«ãã¯ãŒãåŸã®èª¿æŽãè¡ããããåºåããã«ã¡ã©ã®ç»è§ã以äžã®ãªãã·ã§ã³ã§å¶åŸ¡ã§ããŸãã v_fov (åçŽç»è§) h_fov (æ°Žå¹³ç»è§) d_fov (察è§ç»è§) ãããã®ãªãã·ã§ã³ãå©çšããããšã§ã倿åŸã®æ åã现ãã調æŽããããšãå¯èœã§ãã ã³ãã³ãã®å®è¡äŸ äŸ1: äžäžã®æ¯ãåã ffmpeg -i input.mp4 -vf v360=fisheye:flat:v_fov=50:pitch=<è§åºŠ> output.mp4 äŸ2: å·Šå³ã®æ¯ãåã ffmpeg -i input.mp4 -vf v360=fisheye:flat:v_fov=50:yaw=<è§åºŠ> out.mp4 äŸ3: å³ã«æ¯ãåããæ åã®å·Šååã ããåãåã ffmpeg -i input.mp4 -vf v360=fisheye:flat:v_fov=50:yaw=30,crop=iw/2:ih:0:0 output.mp4 ãŸãšã ãã®ããã«éçŒã®æ åãªã©360床ã«ã¡ã©ã§æ®åœ±ããæ åã¯ãç°¡åã«ãã¯ãŒãããããšãã§ããŸããç»åãåç»ã®å€æã«åœ¹ç«ãŠãŠããã ããã°å¹žãã§ãã ã»ãŒãã£ãŒã§ã¯ããã®ãããªæ åè§£ææè¡ã掻çšããããé«åºŠãªãµãŒãã¹ãæäŸããŠããŸããèå³ããæã¡ããã ããŸãããããã²æ¡çšæ
å ±ãã芧ãã ããã
ã¯ããã« ããã«ã¡ã¯ãããŒã¿ããªãã³æšé²å®€ã§ããŒã¿ãšã³ãžãã¢ããã£ãŠããé¶Žã§ãïŒ ã¿ãªãããLightdashã®Table calculationæ©èœã£ãŠäœ¿ã£ãŠãŸããïŒ èªåã¯Lightdashãè§Šã£ãŠããŠ[+Table calculation]ãšãã衚èšãèŠãããéã« ãTable calculationã£ãŠããšã¯è¡šèšç®æ©èœã®ããšãã Tableauãšãã«ãããåºåããçµæããŒã¿ã®äžã§éèšããããããã€ã㪠ãããšäŸ¿å©ã ããªâŠãã®ãã¡äœ¿ãæ©äŒããã£ãããã ã¿ãããªããšèããŠããŸãè§Šããã¹ã«ãŒããŠãŸãã⊠åããããªæ¹ãããã£ãããã®ã§ã¯ãªãã§ããããïŒ å®ã¯Lightdashã®Table calculationæ©èœã¯ã¡ãã£ãšé¢çœãæ©èœã«ãªã£ãŠããã®ã§ããã§ã玹ä»ããããšæããŸãïŒ ã¯ããã« Table calculationãè§Šã£ãŠã¿ãã ãã³ãã¬ãŒãæ©èœããããŸã å®ã¯ããã ããããªãã£ãTable calculation æåŸã« We are hiring! Table calculationãè§Šã£ãŠã¿ãã ãŸãã¯Querying from tablesããèŠããããŒãã«ãéžæããResultã®å³äžã«ãã[+Table calculation]ãæŒããŠã¿ããšâŠ ãããªç»é¢ãåºãŠããŸãã ã€ãŸãåºåããããŒã¿ã䜿ã£ãŠSQLãæžããŠéèšããããšããæããªãã§ããã ãã¯ã衚èšç®ãšããã°ãŠã£ã³ããŠé¢æ°ãšããããšã§æžããŠã¿ãŸãïŒ ä»åãµã³ãã«ã§çšæããã¹ãŒããŒããŒã±ããããŒã¿ã§å£²äžåæ¥æ¯ãäœã£ãŠã¿ãŸãã â»æ¬èšäºã«ç»å ŽããããããããŒããã¯ããµã³ãã«ããŒã¿çšã«äœæããæ¶ç©ºã®åç§°ã§ãããå®åšã®ãããªãåºèã»å£äœãšãäžåé¢ä¿ãããŸãã SQLã¯ãããªæãã§ããç·šéç»é¢ã§æåãå
¥åãããšãµãžã§ã¹ãããŠãããã®ã§äŸ¿å©ã§ãã ${sample_supermarket_sales.sum_of_total_price} / LAG(${sample_supermarket_sales.sum_of_total_price} OVER(${sample_supermarket_sales.sale_date_day})) ãã®ããŒã¿ã¯ãœãŒããèšå®ããŠããã®ã§äžæŠORDER BYã¯èšèŒããé²ããŠã¿ãŸãã ãã©ãŒãããã¯ããŒã»ã³ã衚瀺ã«ããŸãããã ä¿åããŠå®è¡ãããšãããªæãã«ãªããŸããïŒ ãŸããã®äœã£ãé
ç®ãçŽæ¥ãã£ã«ã¿ãŒã«èšå®ããããšãã§ããŸãïŒ å³äžã®ãã¿ã³ãæŒããš[Filter by 売äžåæ¥æ¯]ãããã®ã§æŒããŠã¿ããšâŠ ãã£ã«ã¿ãŒæ¬ã«è¿œå ãããŸããïŒ ããã䜿ã£ãŠåæ¥å£²äžæ¯100%è¶ãã®æ¥ãåºããŠã¿ãããªããŠããšãã§ããŸãã ãã³ãã¬ãŒãæ©èœããããŸã ãŠã£ã³ããŠé¢æ°ã¯SQLã«æ
£ããŠããªãæ¹ã ãšæ£çŽé£ããéšåããããŸããã⊠ã§ããLightdashã«ã¯ãã³ãã¬ãŒããçšæãããŠãŸãïŒ [Sum of total price]ã®å³äžã®ãã¿ã³ãæŒããšãAdd quick calculationã«ãã³ãã¬ãŒãããããŸãã Percent change from previous(åããã®å€åç)ãã¯ãªãã¯ããŠã¿ãŸãã é
ç®ãèªåã§äœæãããŸããïŒ äžå¿å
容ã確èªããããé
ç®å³äžãæŒããEdit calcultationãã¯ãªãã¯ããŸãã å
容çã«ã¯å
ã»ã©èªåãäœã£ãã¯ãšãªã®å
容ã«è¿ãããžãã¯ããããããã«å¯ŸããŠ1ãåŒããŠãã圢ã«ãªããŸãã ãªããæ³šæããŠæ¬²ããã®ãLAG颿°ã®ORDER BYã®ç®æãDESCã«ãªã£ãŠããŸãã æ¥ä»ã§æé ã«ãããããããã¯æ¶ããŠãããŸãããã ããã¯èŠãããã®ã«ãããšæãã®ã§é©å®èª¿æŽããŠãã ããïŒ å®è¡ããçµæã¯ãããªããŸãããæ£çŽãã£ã¡ã®æ¹ãããããããã§ããïŒw ãã®ããã«ãã³ãã¬ãŒããããŸã䜿ããšãµã¯ããšäœããŸãã ä»ã«ããã³ãã¬ãŒãã¯ããã®ã§ãã²å
¬åŒããã¥ã¡ã³ã㮠解説ããŒãž ãã確èªãã ããã ãŸãä»ã®æä»£ã¯ChatGPTå
çãGeminiå
çãªã©ã«èãã°ããããããæããŠãããŸãããäœã£ãŠãããŸããæå¹ã«æŽ»çšããŠãããŸãããïŒ å®ã¯ããã ããããªãã£ãTable calculation ããŠããããŸã§è§Šã£ãŠããTable calculationã§ããå¯ãã®è¯ãæ¹ã¯ãã®ããšã«æ°ã¥ããŠãããããããŸãã⊠ãSQLã§æžããã£ãŠããšã¯SQLã§ãããããšã¯å²ãšäœã§ãã§ããã®ã§ã¯âŠïŒ ããã§ããäœã§ãã§ããŸãã ããšãã°ãã®ãããªCASEæãæžããŠããããã©ã°ãç«ãŠãããšãã§ããŸã(Result typeã¯booleanã«ããŠãŸã) ã¹ãã¢ãšååã®æååãçµåãããããªããã¹ãèšç®ãã§ããŸã(Result typeã¯stringã«ããŠãŸã) ãªããèªåãæã£ãŠã衚èšç®ãšéãâŠïŒïŒïŒïŒ éèšããé
ç®ãããã«å¥œããªããã«ããŒã¿å å·¥ã»èšç®ã§ããã®ã§é¢çœããšæããŸãã ãŸãå°ãåã® Lightdashã¢ããããŒã ã§äœæãã衚èšç®é
ç®ãåå©çšã§ããããã«ãªããŸããã ã€ãŸããããã£ãŠå
ã»ã©äœæããããããã©ã°ãšã¹ãã¢ãšååã®é
ç®ãåãããããšãå¯èœã§ãã äœæãã衚èšç®çµæãããã«èšç®ããŠâŠã¿ããã«åºããŠãããã®ã§æè»æ§ãäžãã£ãŠããã§ããïŒ æåŸã« Table calculationã¯å®çŸ©ãããã¡ããªãã¯ã§å¯Ÿå¿ã§ããªãã£ãéèšãããŒã¿å å·¥ãã«ããŒããæ©èœãšãªã£ãŠããŠå©çšãããæ¹ã¯ããããæ©èœããããšèªèãããŠãããæ¹ãè¯ãæ©èœã ãšæããŸãïŒ ãã å
¬åŒããã¥ã¡ã³ãã«ã èšèŒ ããããŸãããã®Table calculationã¯äžæçãªããŒãºã«å¯Ÿå¿ãããã®ãšããŠã¯è¯ãæ©èœã§ãããç¹°ãè¿ãåå©çšãããŠããå Žåã¯dbtåŽã®å®çŸ©ã«è¿œå ããŠç®¡çããããã«ããæ¹ãè¯ãã®ã§ç®¡çè
ã¯é©å®ãã§ãã¯ããŠãããŸãããã We are hiring! çŸåšãããŒã¿ããªãã³æšé²å®€ã§ã¯ ããŒã¿ãšã³ãžãã¢/ã¢ããªãã£ã¯ã¹ãšã³ãžãã¢ã倧åéäž ã§ãïŒ ã»ãŒãã£ãŒã®ããã€ã¹ãã¢ããªã±ãŒã·ã§ã³ããã¯1æ¥ãããæ°ååä»¶ã®ãã°ãçºçããããŒã¿éã¯ç·åœ¢çã«å¢å ããŠããŸãã ãã®ãããªè¶
ããã°ããŒã¿ãå¹ççã«åŠçããããžãã¹ã®æææ±ºå®ã«ç¹ããããã®ä»çµã¿ãäžç·ã«äœã£ãŠã¿ãŸãããïŒ ãèå³ã®ããæ¹ã¯ ã»ãŒãã£ãŒæ¡çšãµã€ã ãèŠããŠã¿ãŠäžããïŒ ããLightdash Lifeããããã§ã¯ãŸãïŒ
ããã«ã¡ã¯ïŒã»ãŒãã£ãŒã§ããŒããŠã§ã¢éçºãæ
åœããŠããæäžžã§ãã ãåãã®éãããã»ãŒãã£ãŒãã¯ã¯ã©ãŠãé²ç»ãµãŒãã¹ããœãããŠã§ã¢ãäºæ¥ã®äžæ žãšããäŒç€Ÿã§ãã ãããŠåœç¶ã®ããã«ãã¯ã©ãŠãããœãããŠã§ã¢ã®æè¡ãããŒã¹ãšãããšã³ãžãã¢ã®å²åãå€ãäŒç€Ÿã«ãªããŸãã ããããã客æ§ã«æé«ã®äœéšããå±ãããããã«ã¯ãæ åã®å
¥ãå£ãšãªãã«ã¡ã©ãã¯ãããšãããããŒããŠã§ã¢ãã®ååšãæ¬ ãããŸããã 仿¥ã¯ãæ®æ®µããŸãèªãããããšã®ãªããã»ãŒãã£ãŒã®ããŒããŠã§ã¢ãžã®ç±ãæ³ããšããã®åè³ªãæ¯ããåãçµã¿ã«ã€ããŠã玹ä»ããããšæããŸãã ãã¹ãŠã¯ãã客æ§ã«å¯ãæ·»ããããã« ããã ä»å
¥ãããã ãã§ã¯çµãããªããã»ãŒãã£ãŒã®è£œåè©äŸ¡ ä»çµã¿ã§æ¯ããå質ã補åè©äŸ¡ããã»ã¹ã®æšæºå äžå
·åè§£æãããè
ã®èŠãã©ãã ãããã« ãã¹ãŠã¯ãã客æ§ã«å¯ãæ·»ããããã« ç§ãã¡ããŒããŠã§ã¢æ
åœãæã倧åã«ããŠããã®ã¯ã ãã客æ§ã«å¯ãæ·»ã£ã補åïŒããŒããŠã§ã¢ïŒãæäŸããŠããã ãšããããšãŠãã·ã³ãã«ãªæ¹éã§ãã ã客æ§ãã©ã®ãããªã·ãŒã³ã§ãã©ã®ãããªèª²é¡ã解決ãããã®ãã ãããæ·±ãçè§£ããæ©èœãæ§èœã¯ãã¡ããã®ããšãé·æã«ããã£ãŠå®å¿ããŠäœ¿ããå質ããããŠå®å
šæ§ãå
Œãåãã補åããå±ãããããšã ãããç§ãã¡ã®äœ¿åœã§ãã ã»ãŒãã£ãŒãæäŸããããŒããŠã§ã¢è£œåã«ã¯ãä»ç€Ÿãã賌å
¥ãã補åïŒäžéšãã»ãŒãã£ãŒåãã«ã«ã¹ã¿ãã€ãºãããã®ãå«ãïŒãšãèªç€Ÿã§éçºãã補åã®2çš®é¡ããããŸãã ä»åã¯ãç¹ã«ä»ç€Ÿè£œåãã客æ§ã«ãå±ãããéã®ãç§ãã¡ã®ãã ããã«ã€ããŠã話ãããŸãã ããã ä»å
¥ãããã ãã§ã¯çµãããªããã»ãŒãã£ãŒã®è£œåè©äŸ¡ ä»ç€Ÿè£œåãéžå®ããäžã§ãç§ãã¡ã¯ç¹ã«ä»¥äžã®2ã€ã®ããã»ã¹ã«å€ãã®æéãè²»ãããŠããŸãã ã客æ§ã®å©çšã·ãŒã³ã®ææ¡ãšçè§£ æäŸãã補åã®èšèšææ³ã®èªã¿åã Fig1 ãªããªãããã®2ã€ã®ã¹ããããçãã«ãããšããæã蟌ã¿ãã«ãã£ãŠåŸã
倧ããªåé¡ãåŒãèµ·ãããããªãããã§ãã ãæ®éã¯ããã®ã¯ãã ããšãã£ãæã蟌ã¿ãæé€ããã客æ§ã®æ¬åœã®ããŒãºãšè£œåã®ç¹æ§ãæ£ç¢ºã«çµã³ã€ããã ãããŠãé¢ä¿è
å
šå¡ããã®å
±éçè§£ã®äžã«ç«ã€ããšãããããžã§ã¯ãæåã®éµãæ¡ã£ãŠããŸãã ãã®èãæ¹ã«åºã¥ããç§ãã¡ã¯ä»¥äžã®ãããªã¹ãããã§è£œåã®è©äŸ¡ãé²ããŠããŸãã ã客æ§ã®èŠæ±å
容ãæç¢ºã«ããææžåããïŒãŠãŒã¶ãŒæ
å ±ïŒ éžæãã補åã®ä»æ§ïŒæ©èœãæ§èœãå質ãªã©ïŒãã客æ§ã®èŠæ±ãæºãããŠãããã確èªããïŒè£œåæ
å ±ïŒ ã«ã¿ãã°ã¹ããã¯ã ãã§ã¯ç¢ºèªã§ããªãé
ç®ãæŽãåºããè©äŸ¡ã»æ€èšŒã宿œããïŒè¿œå è©äŸ¡ïŒ Fig2 ä»çµã¿ã§æ¯ããå質ã補åè©äŸ¡ããã»ã¹ã®æšæºå ãèšãã¯æããè¡ãã¯é£ããã§ããããããã®è£œåè©äŸ¡ããã»ã¹ãæ
åœè
ã®ã¹ãã«ãçµéšã ãã«äŸåããŠããŸããšãå質ã«ã°ãã€ããçãŸããŠããŸããŸãã ããã§ç§ãã¡ã¯ã誰ãæ
åœããŠãäžå®ã®å質ãæ
ä¿ã§ããããã«ãè©äŸ¡ããã»ã¹ãåè¿°ã®ããã«æšæºåããå°çšã®å
¥åãã©ãŒã ïŒäžèšåç
§ïŒãæé æžãæŽåããŠããŸãã å©çšã·ãŒã³ã®ææ¡: 補åèšçœ®èŠä»¶ç¢ºèªã·ãŒã 補åã®èšèšã»å®å
šææ³ã®ææ¡: èšçœ®ã¬ã€ãã®ç¢ºèªã·ãŒãã補åèªèšŒã®ç¢ºèªã·ãŒã è£œåæ§èœã»å質ã®ç¢ºèª: è£œåæ§èœã®ç¢ºèªã·ãŒãã補åå質ã®ç¢ºèªã·ãŒã Fig3 ããã«ããœãããŠã§ã¢ãšã³ãžãã¢ãå€ãåšç±ããã»ãŒãã£ãŒã®ç¹æ§ãèžãŸããåã·ãŒãã®å
¥åæ¹æ³ã泚æç¹ããŸãšããæé æžãæºåããŸããã ããã¯ãæ®æ®µããèšçœ®æ¥åãéšæã«è§ŠããŠããæ
åœã§ããã°çšèªã«ã粟éããŠããŸãããã©ãã«ã©ããã£ãæ
å ±ãããããããããããŸãã ããããé »åºŠã®äœã人ãäœæ¥ãå§ããããšãããšãæãã®ã»ãæéãããã£ãããããŸãããã®ãããªèæ¯ã«å¯Ÿå¿ããããã®æé æžãäœæããŠããŸãã Fig4 ããããçšããããšã«ãããããŒããŠã§ã¢ã®å°éå®¶ã§ãªããŠããã¹ã ãŒãºãã€ç¶²çŸ
çã«æ€èšŒãé²ããããç°å¢ãæŽããŠããŸãã å ããŠã䜿çšäžã®æ³šæãå®å
šäžã®æ³šæãèªèšŒåæãšãã£ãæèšãçšèªã衚çŸãå瀟ã§å¹
åºãåçŽãªæ€çŽ¢ã§ã¯ãããããªããã®ã«ã¯çæAIãçšããããšãæ³å®ãã察象é
ç®ã調æ»ã§ããããã«ããŒãã¬ãŒãºã䜵èšããŠããŸãã å€ãã®äººã宿ããŠããéããçæAIã«ãã調æ»ã®ã¡ãªããã¯ãç¶²çŸ
çãªæœåºãã§ããããšã«ããã調æ»ç¯å²ãäžååãªããšã«ããæããæŒãã®çºçãé²ãããšãã§ããŸãã ããããªããã調æ»è
ã®çµéšã»ç¥èãå°ãªãå Žåã«ã¯ãçæAIã«å
¥åãããã¬ãŒãºãååã§ãªãããã®ã¡ãªãããååã«äº«åã§ããªãã±ãŒã¹ã®çºçããããŸãã ãããããããã¬ãŒãºäŸã䜵èšããåºåçµæãéå®ãããããªãããã«ããŠããŸãã Fig5 äžå
·åè§£æãããè
ã®èŠãã©ãã ãã®ããã«ç¢ºèªãè¡ã£ã補åã§ãã£ãŠã販売åŸã«ãæ®å¿µãªããäœããã®äžå
·åãçºçããããšããããŸãããããªæãããç§ãã¡ããŒããŠã§ã¢æ
åœã®è
ã®èŠãã©ããã§ãã è§£æã®é²ãæ¹ã§äžçªãããã¡ãªããšã¯ãã€ãçµéšãšåã«é Œã£ãŠè§£æãé²ããŠããŸãããšã§ãã åœããã°ããã®ã§ãããåœãŠãå€ãããšåå ç©¶æãå°é£ã«ãªãããšãå€ã
ãããŸãã æã
ã¯è£œé ã¡ãŒã«ãŒã§ã¯ãªãã倧éã«äžã®äžã«è£œåãåºè·ããŠããããã§ã¯ãªãã®ã§ãè§£æãã§ããäžå
·å察象æ©ãæ°å°çšåºŠã§ããããšãåžžã§ãã æ
éã«ããšãé²ããããšãéèŠã«ãªããŸãã ãã®ãããªããšãèžãŸããªãããçµéšè±å¯ãªãšã³ãžãã¢ããããã§ãªãã¡ã³ããŒããåãæ
å ±ãæ®ããªããè§£æãé²ãããããããäœç³»çãªäžå
·åè§£æãããŒãæ§ç¯ããŠããŸãã äžå
·åå ±åã®ç¢ºèªïŒäžå
·åå ±å確èªã·ãŒãïŒ äžå
·ååã®å€èгïŒå€èŠ³ç¢ºèªå ±åã·ãŒãïŒ äžå
·ååçŸïŒåçŸç¢ºèªå ±åã·ãŒãïŒ äžå
·ååã®åè§£ïŒå解確èªå ±åã·ãŒãïŒ äžå
·ååã®è§£æïŒè§£æå ±åã·ãŒãïŒ åã·ãŒãã«ã¯ãHWãšã³ãžãã¢ã®çµéšããŠãã確èªé
ç®ããªã¹ãããããã®å
容ãé æ¬¡ãã§ãã¯ããŠããã€ããã«ãªã£ãŠããŸãã ããã«ãããåŸæ»ãã®ãªããç確ãªåå ç©¶æãšãåçºé²æ¢ã«ç¹ããŠããŸãã Fig6 ãããã« ä»åã¯ãã»ãŒãã£ãŒã®ããŒããŠã§ã¢ãžã®åãçµã¿ãç¹ã«ä»ç€Ÿè£œåãè©äŸ¡ããéã®ããã»ã¹åã³äžå
·åè§£æã«ã€ããŠã玹ä»ããŸããã ããã¯ã HWãšã³ãžãã¢ãæ±ããã»ãŒãã£ãŒã ããããã®ã¢ãããŒãã§ã ã ç§ãã¡ã®ç®æšã¯ããã® HWãšã³ãžãã¢ã®çµéšãèŠèã«è£æã¡ãããä»çµã¿ ãããã«é²åãããHWãšã³ãžãã¢ä»¥å€ã®ã¡ã³ããŒãå«ããå
šäœã®åºäžããããããšã§ã客æ§ã«å質ã®é«ãããŒããŠã§ã¢ãå±ããããããã«ããããšã§ãã æ¬¡åã¯ãããäžã€ã®æ±ã§ãããèªç€Ÿéçºè£œåãã«ã€ããŠã詳ããã話ãããããšæããŸãã®ã§ããæ¥œãã¿ã«ïŒ