株匏䌚瀟Insight Edgeのブログ - TECH PLAY

TECH PLAY

株匏䌚瀟Insight Edge

株匏䌚瀟Insight Edge の技術ブログ

å…š206ä»¶

目次 はじめに クリヌンアヌキテクチャずは 䟋ずしお考えるアプリケヌション 生成AIアプリにおける難しさ 実際に䜜っおみる 実装を差し替えおみる たずめ はじめに こんにちは、InsightEdgeの開発チヌムに参画させおいただいおいたす䌊藀です。 InsightEdgeでは珟圚、LLM/生成AIを甚いたアプリ開発を倚く手掛けおいたす。 私もOpenAI等の生成AIを䜿ったアプリケヌションの実装に関わるこずが増えおきおおり、 ある皋床理解が進んできたずころで、改めおアヌキテクチャを掗緎させたいず思うようになりたした。 この蚘事では生成AIを組み蟌んだアプリを構築する際の、クリヌンアヌキテクチャを考えおいきたいず思いたす。 クリヌンアヌキテクチャずは たずは、クリヌンアヌキテクチャに぀いお軜く振り返りたしょう。 クリヌンアヌキテクチャでは゜フトりェアの理解・開発・デプロむ・運甚・保守を容易にするために、フレヌムワヌクやDB・UI・倖郚サヌビスなどぞの䟝存を最小にしたす。 この時の䞋蚘のような倚局構造に分割し、それぞれの局に圹割に合わせたクラスを配眮しおいきたす。 The Clean Architecture より抜粋 ここで登堎する局はそれぞれ䞋蚘のような圹割を持っおいたす Entities この局にはビゞネスルヌルやビゞネス䞊の抂念を衚すクラスを栌玍したす。 ドメむン駆動開発(DDD)やオニオンアヌキテクチャ的にいうずドメむンモデル/ドメむンサヌビスのレむダに該圓したす。 Use Cases アプリケヌション固有のビゞネスが含たれたす。 Use Case局のクラスはEntity局のクラスを䜿っおアプリケヌションの凊理フロヌを実行したす。 Controllers/Presenters Controllerは入力をUse Caseに合わせた圢に倉換した䞊で、Use Caseを実行したす。 PresenterはUse CaseがUIぞの出力をする時に呌び出されるクラスになりたす。 Gateways GatewayはEntityå±€/Use Case局で扱うクラスをDBや倖郚サヌビスに合わせた圢に倉換し、氞続化やAPIコヌルなどを行いたす。 その倖偎 DBそのものやUI、倖郚のサヌビスなどはすべおControler/Presenter/Gatewayを通じおやり取りするものになりたす。 これらの各局に含たれるコヌドは、必ずより内偎の局のコヌドだけに䟝存するようにするこずで、 サヌビス/ビゞネスの本質的なロゞック郚分を衚珟するコヌドが、フレヌムワヌクやUIずいった郚分の倉曎に 圱響を受けないように構成したす。 詳现に぀いおはオリゞナルのWebサむトや曞籍のほか、いろいろが出おいたすのでここでは割愛したす。 参考 The Clean Architecture 曞籍Clean Architecture 達人に孊ぶ゜フトりェアの構造ず蚭蚈 䟋ずしお考えるアプリケヌション アヌキテクチャを考える䞊での想定アプリケヌションずしお、ここではRAGを加えたChatGPTのようなアプリケヌションを䜜るものずしたす。 ナヌザはブラりザでアクセスする 自然蚀語で質問を入力するず、自然蚀語で回答が衚瀺される 回答䜜成時には、それたでのやり取りなどの文脈が考慮される 回答䜜成時には、あらかじめシステムに登録しおおいた関連情報が加味される 回答は生成完了しおから䞀床に衚瀺されるのではなく、生成された文字から逐次衚瀺される 生成AIアプリにおける難しさ 前述のようなアプリをクリヌンアヌキテクチャで䜜成しようずした際に、特に䞋蚘の点は怜蚎が必芁でした。 どの芁玠がEntityになるのか ストリヌミング圢匏のアりトプットはクリヌンアヌキテクチャで実珟できるのか それぞれ、どんな課題に察しお、どのように考えおいったのかを説明しおいきたいず思いたす。 どの芁玠がEntityになるのか 論点 クリヌンアヌキテクチャのEntity局にはアプリの栞ずなるビゞネスロゞックが眮かれたす。 䞀方で生成AIアプリ開発の䞭心ずなるのは、どうやっおGPT等の生成AIに望むクオリティのアりトプットを生成しおもらうかだず思いたす。 しかし、生成AIそのものはAPI経由で呌び出すのでアプリ倖にあり、これはクリヌンアヌキテクチャで蚀うずころのGatewayの先の郚分のはずです。 では、どんな郚分をEntityずしお䟝存関係の䞭心に眮くべきなのでしょうか。 考え方 今回想定しおいるアプリが提䟛する機胜は「質問を受けお、今の文脈に合わせお、関連情報を䜿っお、回答を生成する」です。 ここから考えるずEntityずしお衚珟するべき抂念は 質問 ・ 文脈 ・ 関連情報 ・ 回答 であるはずです。 ここにはプロンプトなどの生成AI的な芁玠は出おきたせんが、そもそもAIは実装/実珟手段の詳现なので、 適切な回答を返しおくれるのであれば、背埌にあるのはGPTでもGeminiでも、ただのデヌタベヌスでも良いずいうこずです。 これたで開発のたびに色々ず工倫しおきたプロンプトは本質的な郚分ではないのかず䞀瞬ショックを受けたしたが よく考えるずパフォヌマンス重芖のサヌビスでSQL郚分のチュヌニングをしおいるようなものですね。 どんなにチュヌニングが倧切なアプリであっおもSQLそのものがアヌキの䞭心ずはならない、ずいうのず同じです。 ストリヌミング圢匏のアりトプットはクリヌンアヌキテクチャで実珟できるのか 論点 GPTを䜿ったアプリケヌションでは、UX向䞊のためにGPTからの回答を逐次画面に衚瀺するUIが䞀般的だず思いたす。 これを行うためにはアプリのフロント゚ンドずバック゚ンドがHTTPストリヌミングのような圢で通信しなければなりたせん。 このずき、GPTの出力からアプリのフロント゚ンドたでの間の、 回答 に関連するすべおのクラスがストリヌミング圢匏のデヌタに察応できおいる必芁がありたす。 しかし、UIがストリヌミング出力だからずいっお、そこに合わせおUse Case局の仕様を倉曎するこずはクリヌンアヌキテクチャの重芖しおいる䟝存関係が逆転しおしたっおいる気がしたす。 クリヌンアヌキテクチャの考え方に沿ったたたストリヌミング型のUIに察応するにはどうしたらよいのでしょうか。 考え方 䞊蚘に぀いお考えおいる䞭で、自分の捉え方に思い蟌みがあるこずに気づきたした。 倉数の倀が決たっおから返华するのが「普通」で、ストリヌミング出力は「UIに合わせた特殊な圢」だず考えおいたのです。 pythonは蚀語自䜓にGeneratorやPromise等の「埌で倀が決たる仕様」の型を持っおいたす。 䜿うプログラミング蚀語で衚珟できるのであれば 回答 を「逐次生成されるもの」ずしお定矩しおしたっおもよいのではないでしょうか。 回答 ずいう抂念が、そもそも逐次生成される性質を持っおいる、ずいう捉え方です。 今回は回答(Answer)ずいうEntityをGeneratorの䞀皮ずしお定矩したした。 Answer: TypeAlias = Generator[ str , None , None ] この曞き方もEntityを Generator[str, None, None] 型なんかにしおしたっおよいのかずいう違和感があったのですが、 list[str] 等で衚珟するのず違いはないはず、ず思い玍埗するこずにしたした。 回答 の持぀性質をコヌドずしお衚珟した時に、たたたた Generator ずいう型が䞀番適切だったのだず解釈したす。 実際に䜜っおみる 䞊蚘を螏たえ、実装をしおみたす。 Entity・Use Case・Gateway・Controller/Presenterそれぞれを芋おいきたしょう。 党䜓の構成は以䞋のようになっおいたす。 ドメむン駆動開発(DDD)をする堎合だず domain や repository ずいった衚珟の方がよく䜿われるかもしれたせんが、 今回はクリヌンアヌキテクチャずの察応がわかりやすいように entity や gateway ずいった衚珟に統䞀しおいたす。 src ├── entity: ゚ンティティ局 │   ├── answer: 回答モデル │   ├── context: 文脈モデル │   ├── knowledge: 背景知識モデル │   └── question: 質問モデル ├── usecase: ナヌスケヌス局 │   ├── knowledge: 背景知識モデル │ └── chat: 質問回答ナヌスケヌス ├── adapter: アダプタ局 │   ├── controller: Use Caseを起動するためのController実装 │   ├── gateway: 各皮Gateway/Repositoryの実装 │   │   ├── answer: AnswerGateway実装 │   │   ├── context: ContextGateway実装 │   │   └── knowledge: KnowledgeGateway実装 │   └── presenter: 出力をハンドリングするPresenter実装 └── main_*.py: 起動のための゚ントリポむント Entity定矩 たずコアずなるEntitiy局には、前述した䞋蚘の4芁玠ず、その取埗を担圓するGatewayの抜象クラスを䜜成したす。 質問(Question) 文脈(Context) 背景知識(Knowledge) 回答(Answer) 質問(Question)関連 question.py Question: TypeAlias = str """ 質問文を衚す型。ただの文字列 """ 文脈(Context)関連 context.py ContextId: TypeAlias = int """ これたで文脈を取埗するためのキヌにする倀を衚す型。今回は敎数ずしお定矩する。 実際はナヌザやセッションに関する倀をキヌする想定。 """ Context: TypeAlias = str """ 文脈を衚す型。今回はただの文字列ずしお定矩する。 実際は過去の䌚話の履歎などを含むこずが考えられる。 "" context_gateway.py class ContextGateway (metaclass=ABCMeta): """文脈(Context)を取埗するためのGateway""" @ abstractmethod def get_context (self, context_id: ContextId) -> Context: """ContextIdに基づくContextを取埗する""" pass 背景知識(Knowledge)関連 knowledge.py Knowledge: TypeAlias = str """ 背景知識぀を衚す型。今回はただの文字列ずしお定矩する。 実際は参照先や、関連床のスコアなどを含むクラスにするこずが考えられる。 """ Knowledges: TypeAlias = list [Knowledge] """ 耇数の背景知識を衚す型 """ knowledge_gateway.py class KnowledgeGateway (metaclass=ABCMeta): """背景知識(Knowledge)を取埗するためのGateway""" @ abstractmethod def find_knowledges (self, question: Question) -> Knowledges: """Questionに関連する背景知識(Knowledge)を取埗する""" pass 回答(Answer)関連 answer.py Answer: TypeAlias = Generator[ str , None , None ] """ 回答を衚す型。文字列が逐次生成されるものずしお定矩する。 """ answer_gateway.py class AnswerGateway (metaclass=ABCMeta): """回答(Answer)を取埗するためのGateway""" @ abstractmethod def get_answer ( self, question: Question, context: Context, knowledges: Knowledges ) -> Answer: """Question/Context/Knowledgeに基づくAnswerを取埗する""" pass Gateway実装 (ダミヌ版) たずは動䜜確認するためにダミヌ版のGateway実装を䜜成したす。 それぞれ固定倀を返すようになっおいたす。 今回は以䞋の䟋でダミヌ文を䜜成したした。 文脈: 「組織のデヌタを掻甚するためのOpenAIアプリの開発で困っおいる」 背景知識 「InsightEdge瀟はOpenAIを䜿ったアプリ開発ができる」 「InsightEdge瀟にはデヌタサむ゚ンスの専門家がいる」 回答: 「InsightEdgeを怜蚎しおみおはいかがでしょうか」 dummy_context_gateway.py class DummyContextGateway (ContextGateway): """ ダミヌの文脈情報を返すContextGateway """ def get_context (self, context_id: ContextId) -> str : return Context( "組織のデヌタを掻甚するためのOpenAIアプリの開発で困っおいる" ) dummy_knowledge_gateway.py class DummyKnowledgeGateway (KnowledgeGateway): """ ダミヌの背景知識を返すKnowledgeGatway """ def find_knowledges (self, question: Question) -> Knowledges: return [ Knowledge( "InsightEdge瀟はOpenAIを䜿ったアプリ開発ができる" ), Knowledge( "InsightEdge瀟にはデヌタサむ゚ンスの専門家がいる" ), ] dummy_answer_gateway.py class DummyAnswerGateway (AnswerGateway): """ ダミヌの回答を返すAnswerGateway """ def get_answer ( self, question: Question, context: Context, knowledges: Knowledges ) -> Generator[ str , None , None ]: yield f "「{context}」ずいう文脈においお、 \n " sleep( 1 ) yield f "「{question}」ずいう質問に察しお、 \n " sleep( 1 ) for knowledge in knowledges: yield f "「{knowledge}」" sleep( 1 ) yield "ずいう背景知識をもずに、 \n " sleep( 1 ) yield "ダミヌの回答をしたす。 \n " sleep( 1 ) yield "InsightEdgeを怜蚎しおみおはいかがでしょうか \n " get_answer() の戻り倀は Generator である Answer ずしお芪クラスで定矩されおいたすが、こちらの実装は str 型を yield するこずで定矩を満たしおいたす。 なお、今回はストリヌミングの動きがわかるように sleep() を挟んでいたす。 Use Case/Port実装 続いお、Use Case局を䜜りたす。 ここではEntityを䜿甚しおアプリずしおの凊理フロヌを定矩するUse Caseず、 その出力の仕方を定矩するOutputPortを䜜成したす。 埌ほど出おくるControllerはこのUse Caseを呌び出す圢ずなり、 PresenterはOutputPortを継承したクラスずしお、Use Case局の定矩に埓っお実装するこずになりたす。 これはクリヌンアヌキテクチャの図では右䞋の郚分で衚珟されおいる郚分ずなりたす。 図ではUseCaseの芪ずなるInput Portも蚘茉されおいたすが、今回は省略したす。 図に厳密に埓っおUse Case Input Portを䜜成しControllerからの䟝存がそちらに向かう構造にするこずで、 Use Caseの倉曎をした堎合にControllerに圱響しにくくできたすが、 把握しおおくクラス/䟝存関係を枛らすこずの方がメリットが高いず考えおおり 自分の堎合はInput Portは䜜らない、ずいう遞択をするこずが倚いです。 では、実装の䞭身です。 たずは「質問を受けお回答を生成する」ずいうナヌスケヌスを実珟するためのクラスを䜜りたす。 chat_usecase.py class ChatUsecase : """ 質問に察する回答を返すナヌスケヌス """ def __init__ ( self, context_gateway: ContextGateway, knowledge_gateway: KnowledgeGateway, answer_generator: AnswerGateway, ) -> None : """ 䜿甚するGatewayをセットする """ self.context_gateway = context_gateway self.knowledge_gateway = knowledge_gateway self.answer_generator = answer_generator def execute ( self, question: Question, context_id: ContextId, output_port: ChatUsecaseOutputPort, ) -> None : """ ナヌスケヌスを実行する """ # 文脈を把握する context: Context = self.context_gateway.get_context(context_id) # 背景知識を取埗する knowledges: Knowledges = self.knowledge_gateway.find_knowledges(question) # 回答を䜜成する answer = self.answer_generator.get_answer(question, context, knowledges) # 回答を出力する output_port.emit(answer) そしおUse Caseのアりトプットを受け取るOutput Portを定矩したす。 このOutputPortを実装したPresenterであれば、アりトプットの仕方はなんでも良いずいうこずになりたす。 chat_usecase_output_port.py class ChatUsecaseOutputPort (metaclass=ABCMeta): """ ChatUsecaseの出力口の定矩""" @ abstractmethod def emit (self, answer: Answer) -> None : """Answerを出力甚に受け取る""" pass Presenter/Controllerコマンドラむン実行甚 最埌にPresenterずControllerを䜜成したす。 たずはシンプルにコマンドラむンで呌び出す想定で䜜っおみたす。 Controllerは暙準入力から質問を受け付け、Entityである Question 型に倉換しおから、ナヌスケヌスを起動したす。 cli_chat_controller.py class CliChatController : # CLI䞊で質問を受け取り、ナヌスケヌスを実行するコントロヌラ def __init__ (self, usecase: ChatUsecase, presenter: ChatUsecaseOutputPort): # 実行するナヌスケヌス self.usecase = usecase # ナヌスケヌスのOutputPortの実装 self.presenter = presenter def handle (self): # コンテクストIDを取埗する今回はサンプルなので固定 contextId = 1 # 質問文を受け取る question_str = input ( "質問を入力しおください: " ) question: Question = Question(question_str) # ナヌスケヌスを実行する self.usecase.execute(question, contextId, self.presenter) # 出力はPresenterが担圓するので、ここでは䜕もしない 続いおPresenterを䜜りたす。 CLIでの操䜜を想定し暙準出力ぞの衚瀺をするものを甚意したす。 ChatUsecaseOutputPort の実装(の1぀)になりたす。 stdout_chat_presenter.py class StdoutChatPresenter (ChatUsecaseOutputPort): """暙準出力にAnswerを出力するPresenter""" def emit (self, answer: str ) -> None : """Answerを出力甚に受け取る""" # Answerの内容を逐次出力する for answer_chunk in answer: sys.stdout.write(answer_chunk) sys.stdout.flush() 実行 さおここたでの実装を繋げお動かしおみたす。 ゚ントリポむント ゚ントリポむントずしお、手動でDependency Injection(以䞋DI)した䞊で、コントロヌラを呌び出す凊理を䜜りたす。 main_cli.py """ CLI䞊で実行するための゚ントリヌポむント """ # DI枈みのUse Caseを䜜成する context_gateway = DummyContextGateway() knowledge_gateway = DummyKnowledgeGateway() answer_gateway = DummyAnswerGateway() usecase = ChatUsecase(context_gateway, knowledge_gateway, answer_gateway) # DI枈みのコントロヌラを䜜成する presenter = StdoutChatPresenter() controller = CliChatController(usecase, presenter) # コントロヌラを呌び出す controller.handle() 実行結果 䞊蚘の゚ントリポむントからアプリを動かすずこのようになりたす。 DummyAnswerGateway によっお生成された結果が、暙準出力に逐次出力されおいたす。 さお、これでアプリの党䜓像は完成したした。 いわゆる生成AIアプリであっおも、アヌキテクチャの芳点ではAIそのものからは切り離されおいるずいうこずが改めお確認できたず思いたす。 実装を差し替えおみる ここからはGateway/Controller/Presenterの「詳现」を倉えおいきたしょう。 クリヌンアヌキテクチャを目指したこずで倉曎に匷いものになっおいるでしょうか。 AnswerGatewayをOpenAI利甚版にしおみる たずは回答の生成を実際にAzure OpenAIを䜿っお行うようにしおみたす。 DummyAnswerGateway を眮き換えるための別クラスを䜜りたす。 芪クラスは AnswerGateway です。 openai_answer_gateway.py class OpenAIAnswerGateway (AnswerGateway): """ OpenAIを甚いお回答を生成するAnswerGateway""" def __init__ (self): api_key = os.getenv( "AZURE_OPENAI_API_KEY" , "" ) api_base = os.getenv( "AZURE_OPENAI_API_BASE" , "" ) api_version = os.getenv( "AZURE_OPENAI_API_VERSION" , "" ) self.deployment_name = os.getenv( "AZURE_OPENAI_DEPLOYMENT_NAME" , "" ) # AzureOpenAIクラむアントを甚意する self.client = AzureOpenAI( api_key=api_key, api_version=api_version, azure_endpoint=api_base, ) def get_answer ( self, question: Question, context: Context, knowledges: Knowledges ) -> Answer: # OpenAIに質問を投げお回答を取埗する response = self.client.chat.completions.create( model=self.deployment_name, messages=[ { "role" : "user" , "content" : [ { "type" : "text" , "text" : f "{context}ずいう文脈においお、" + f "{knowledges}ずいう背景知識をもずに、" + f "{question}ずいう質問に察しお回答しおください。" , } ], }, ], stream= True , ) # OpenAIからの回答を逐次返す for chunk in response: choices = chunk.choices if choices and choices[ 0 ].delta and choices[ 0 ].delta.content is not None : yield str (chunk.choices[ 0 ].delta.content) # strをyieldするこずで、Answer型぀たりGenerator[str, None, None]型を満たす こちらの get_answer() も DummyAnswerGateway の時ず同じく str 型を yield しおいるので、戻り倀の型 Answer 型に合臎しおいたす。 ゚ントリヌポむント ゚ントリヌポむントは、 先ほどのCLI入力/衚瀺甚の実装から、 DummyAnswerGateway の代わりに䞊蚘の OpenAIAnswerGateway を䜿っお実行するよう、DIしおいる1行だけを倉曎したす。 今回は簡易化のため ContextGateway ず KnowledgeGateway はダミヌのたたずしたす。 実際にRAGを行う堎合は KnowledgeGateway の郚分にEmbeddingやVectorStoreを実装するこずになるず思いたす。 main_cli_openai.py """ CLI䞊で実行するための゚ントリヌポむント """ # DI枈みのUseCaseを䜜成する context_gateway = DummyContextGateway() knowledge_gateway = DummyKnowledgeGateway() answer_gateway = OpenAIAnswerGateway() # <= OpenAIAnswerGatewayを䜿う usecase = ChatUsecase(context_gateway, knowledge_gateway, answer_gateway) # DI枈みのコントロヌラを䜜成する presenter = StdoutChatPresenter() controller = CliChatController(usecase, presenter) # コントロヌラを呌び出す controller.handle() 実行結果 䞊蚘の゚ントリポむントから実行しおみたす。 はい、これだけで実際にAzure OpenAIを組み蟌んだアプリに倉わりたした。 以䞋のポむントのおかげで修正箇所が非垞に限定されおいたす。 各Gatewayの実装はEntity局で定矩した抜象Gatewayに埓うようになっおいる Use Caseも抜象のGatewayの定矩に䟝存しおいる 実際にどの実装を䜿うかはDIによっお決たる Presenter/ControllerをHTTPストリヌム版にしおみる 次はControllerずPresenterを差し替えお、APIずしお動䜜する圢にしおみたしょう。 ControllerはFastAPIを䜿っおHTTPリク゚ストを受け取るものを䜜成したす。 http_chat_controller.py class HttpChatController : # Httpリク゚ストで質問を受け取り、ナヌスケヌスを実行するコントロヌラ def __init__ (self, usecase: ChatUsecase, presenter: AbstractHttpChatPresenter): # 実行するナヌスケヌス self.usecase = usecase # ナヌスケヌスのOutputPortの実装 self.presenter = presenter # FastAPIのルヌタヌ蚭定 self.router = APIRouter() self.router.add_api_route( "/{context_id}" , self.handle, methods=[ "GET" ]) def handle (self, context_id: int , q: str ) -> Response: # 質問文を取埗する question = Question(q) # ナヌスケヌスを実行する self.usecase.execute(question, context_id, self.presenter) # レスポンスを返す return self.presenter.get_response() CliChatController ずほが䞀緒ですね。 Presenterずしおは ChatUsecaseOutputPort を継承し぀぀ Response の圢で取り出すための get_response() を持たせたいので、 その点を衚珟した抜象クラスをもう䞀段階挟みたす。 class AbstractHttpChatPresenter (ChatUsecaseOutputPort): """HTTP経由でAnswerを出力するPresenterの抜象クラス""" @ abstractmethod def emit (self, answer: Answer) -> None : """Answerを出力甚に受け取る""" pass @ abstractmethod def get_response (self) -> Response: """HTTPレスポンスの圢で回答を返す""" pass Presenterの実装は emit() で蚭定された Answer を HttpStream で返华するものを甚意したす。 http_stream_chat_presenter.py class HttpStreamChatPresenter (AbstractHttpChatPresenter): """HTTPストリヌミングでAnswerを出力するPresenter""" def emit (self, answer: Answer) -> None : """Answerを出力甚に受け取る""" self.answer = answer def get_response (self) -> Response: """HTTPストリヌムの圢で回答を返す""" response = StreamingResponse(self.answer, media_type= "text/event-stream" ) return response こちらはFastAPIの定矩する StreamingResponse を䜿っおいたす。 Entity局で定矩した Answer が Generator 型なので、簡単にストリヌミング察応ができたす。 ゚ントリヌポむント 䞊蚘のControllerをFastAPIで実行するような゚ントリポむントを甚意したす。 倉曎箇所は、Controler/Presenterの差し替えずサヌバの起動凊理の远加です。 main_http_openai.py """ Httpサヌバ䞊で実行するための゚ントリヌポむント """ # DI枈みのUseCaseを䜜成する context_gateway = DummyContextGateway() knowledge_gateway = DummyKnowledgeGateway() answer_gateway = OpenAIAnswerGateway() # OpenAIを䜿っお回答を行うAnswerGateway usecase = ChatUsecase(context_gateway, knowledge_gateway, answer_gateway) # DI枈みのコントロヌラを䜜成する presenter = HttpStreamChatPresenter() controller = HttpChatController(usecase, presenter) # コントロヌラをサヌバ䞊で呌び出し埅ち状態にする app = FastAPI() app.include_router(controller.router) uvicorn.run(app, host= "127.0.0.1" , port= 8000 ) 実行結果 䞊蚘を起動した䞊で、ブラりザでアクセスしおみたす。 無事にAPI化もできたした。 アプリの凊理そのものはUse Case局がEntity局のクラスを甚いお行う Controller/PresenterはUse Case局のクラスに埓う この2点のおかげで、入出力をCLIからHTTP圢匏の倉曎する際に、Use Caseå±€/Entity局に圱響を䞎えるこずなく行えおいたす。 ストリヌミングではないHTTPレスポンスにしたい堎合はどうするのか ここたでは内郚のEntityも出力のPresenterも回答を逐次凊理するようにしおいたした。 では「やっぱりストリヌミングではなく䞀床のHTTPレスポンスで回答を返华したくなった」ずいう堎合はどのような圱響があるでしょうか。 出力圢匏が倉わるので、新たにPresenterを甚意したす。 HTTP Responseを返す get_response() を持っおいお欲しいので、 AbstractHttpChatPresenter の子クラスずしお䜜成したす。 http_response_chat_presenter.py class HttpResponseChatPresenter (AbstractHttpChatPresenter): """HTTPレスポンスでAnswerを出力するPresenter""" def emit (self, answer: Answer) -> None : """Answerを出力甚に受け取る""" self.answer = answer def get_response (self) -> Response: """HTTPレスポンスの圢で回答を返す""" result = "" for chunk in self.answer: result += chunk print (result) response = Response(content=result, media_type= "text/plain" ) return response Entity局の Answer は Generater 型のたた、生成される回答をすべおPresenter内で受け取ったあずに1回のHTTPレスポンスを返すようにしおいたす。 ゚ントリヌポむント 呌び出しはHTTP経由で倉わらないので、 HttpChatController のたた、PresenterだけDIで倉曎したす。 """ Httpサヌバ䞊で実行するための゚ントリヌポむント """ # DI枈みのUseCaseを䜜成する context_gateway = DummyContextGateway() knowledge_gateway = DummyKnowledgeGateway() answer_gateway = OpenAIAnswerGateway() usecase = ChatUsecase(context_gateway, knowledge_gateway, answer_gateway) # DI枈みのコントロヌラを䜜成する presenter = HttpResponseChatPresenter() # <= 通垞レスポンスを返すPresenterに倉曎 controller = HttpChatController(usecase, presenter) # コントロヌラをサヌバ䞊で呌び出し埅ち状態にする app = FastAPI() app.include_router(controller.router) uvicorn.run(app, host= "127.0.0.1" , port= 8000 ) これでストリヌミングではなく、䞀括で回答が返华される圢になりたした。 Entityである Answer が Generater ずしお定矩されおいおも、Presenterが適切に凊理するこずで 倖からはただの str であるかのように衚瀺に䜿うこずができたす。 䜙談 今回は実斜したせんでしたが、バッチ凊理で回答を生成しお䜕かに栌玍したい堎合も、 バッチ凊理甚のControllerずPresenterを甚意するこずで察応できるはずです。 ただしその堎合には、Use Caseずしお衚珟するべきものが本圓にナヌザ操䜜ずバッチ凊理で同じなのかを怜蚎する必芁がありたす。 たずめ 今回は生成AIアプリの内郚をクリヌンアヌキテクチャで構成する方法に぀いお怜蚎したした。 生成AIを䜿ったアプリであっおも、クリヌンアヌキテクチャの考え方に沿っお局を分け、 アプリが扱う芁玠/抂念を生成AI自䜓の䜿い方ず切り離しお捉えお抜象化し、 䟝存関係が䞀方向に向かうように構成するこずで 回答生成方法の倉曎 アプリ起動方法の倉曎 出力圢匏の倉曎 などを、圱響範囲を最小にした䞊で実斜できるこずが確認できたした。 たた 回答(Answer) を Generator ずしおの性質を持ったものずしおモデル化するずいう工倫をするこずで、 生成AIアプリケヌションでよく䜿う逐次衚瀺圢匏ず、Request/Response圢匏の䞡方の出力に察応できるこずが分かりたした。 感想 今回クリヌンアヌキテクチャを目指す蚭蚈をしたこずで 生成AIアプリケヌションに぀いお自分が持っおいたメンタルモデルが、よりシンプルなものに曎新されたず感じたす。 新たにアプリを䜜るずきよりも、既存のアプリの方が抂念やフロヌが分かっおいお怜蚎しやすいず思いたすので 既存のアプリに぀いおクリヌンアヌキテクチャで䜜ったらこうなるのでは、ずいうのを䞀床考えおみるのも面癜いかもしれたせん。
はじめに 実斜背景 抂芁 事䟋展瀺 トヌクセッション 盞談窓口 その他 圓日の様子 最埌に はじめに こんにちは 昚幎10月にInsight Edgeぞコンサルタントずしお参画した、楠です。 今回は、2月21日(æ°Ž)に実斜いたしたしたInsight Edge初のオフラむンむベントに぀いおご報告いたしたす。 是非最埌たでお読みいただけたすず幞いです。 実斜背景 Insight Edgeは、2019幎7月の蚭立以来、アゞャむル開発・デヌタ分析・AIモデル開発を内補゚ンゞニアで実珟する組織ずしお、䜏友商事及び䜏友商事グルヌプの事業䌚瀟の事業䟡倀向䞊に寄䞎するべく、数々のDX案件に取り組んできたした。 この床、間もなく蚭立5幎を迎えるずいうタむミングで、これたでの足跡やInsight EdgeのCapabilityに぀いお玹介し、課題解決のヒントを埗おいただくためのオフラむンむベントを䌁画・実斜したした。 むベントの実斜抂芁は以䞋の通りです。 開催日時 2024幎2月21日氎11:00-17:30 堎所 MIRAI LAB PALETTE HUB 察象䜏友商事及び䜏友商事グルヌプ事業䌚瀟 党圹職員 MIRAI LAB PALETTE HUBを貞し切っお実斜したした。 むベントのキヌビゞュアル。䜏友商事グルヌプの「Digital Level UP」をテヌマずしたした。 抂芁 むベントでは、倧きく以䞋3぀のコンテンツを䌁画・実斜したした。 事䟋展瀺 Insight Edgeが過去に取り組んだ案件のうち9぀の案件に぀いお、売䞊向䞊・業務高床化ずいった倚様な珟堎課題に察するDX゜リュヌションを分かりやすく展瀺したした。 各案件の説明は実際に案件を担圓した゚ンゞニアが行い、いく぀かの案件に぀いおは実際に觊っおいただけるデモアプリも玹介し、来堎者に臚堎感をもっお䜓感頂きたした。 トヌクセッション 匊瀟CEO小坂らで䜏友商事グルヌプ内倖のDXに぀いお語るオヌプニングセッションを皮切りに、4぀のトヌクセッションを実斜したした。 内2぀のセッションでは、䜏友商事のナヌザ郚眲やグルヌプ事業䌚瀟の担圓者にも登壇いただき、実際の゚ピ゜ヌドを亀えお、生成AI掻甚やDX内補力匷化等のInsight Edgeずの協業案件に぀いお振り返っおいただきたした。 それ以倖にも、デヌタ掻甚のよくある事䟋や盞談に぀いお匊瀟デヌタサむ゚ンティストのリヌダヌ陣が語るセッションも実斜したした。 盞談窓口 DX 掚進に必芁なAIやデヌタ分析、開発など、様々な課題に関しお気軜に盞談可胜な窓口を蚭眮したした。 その他 Insight Edgeのロゎやむベントキヌビゞュアルをあしらったノベルティや、矎味しいドヌナツで来堎しおくださった方々をおもおなしたした ノベルティのボヌルペン。Insight Edgeずしお初めお䜜成したした。 ご来堎者党員にむベントのキヌビゞュアルを掲茉したチョコレヌトを配垃したした。 ご来堎者向けにはドヌナツやコヌヒヌを準備したした。 圓日の様子 圓日は合蚈で玄200人の方にご来堎いただき、DXに関する関心の高さを䌺うこずができたした。たた、トヌクセッションに぀いおも、甚意したスペヌスがほが満垭ずなったほか、䌚堎質問も倚数いただくこずができ、非垞に盛況ずなりたした。 特にオヌプニングセッションでは、匊瀟CEOの小坂からInsight Edgeの䜍眮づけやむベントの目的に぀いおご説明した埌、マネヌゞャヌの猪子・森から「内補化集団が果たす圹割」や「技術進展を取り蟌むこず・技術のリスクを芋極め正しく䜿うこずの重芁性」に぀いおプレれンを行いたした。䌚堎からはDXの掚進方法や運甚方法のノりハり、匊瀟の取り組みが䜏友商事グルヌプのDXに及がした圱響など様々な質問が飛び亀い、来堎者の高い枩床感や具䜓的な課題感をむベント開始すぐに感じられたした。 䌚堎にPCを配眮し、ご来堎者にデモ機を觊っおいただきたした。 事䟋展瀺スペヌスの様子。写真を䞀郚加工しおいたす。 オヌプニングセッションには匊瀟CEOの小坂も登壇したした。 最埌に Insight Edgeは、「技術の力で䞖界をRe-Designする」をMissionずしお、今埌も䜏友商事グルヌプのDX掚進を加速しお参りたす。各職皮に぀いお採甚を匷化しおおりたすので、是非 採甚ペヌゞ もご芧ください2025幎床に぀いおは新卒採甚も実斜予定です。 ここたでお読みいただき、ありがずうございたした
はじめに こんにちは昚幎9月からInsight Edgeの開発チヌムに参画した広束です。Insight Edgeでは生成AI案件を担圓しおいたす。 参画しおからただ間もないですが、技術遞定や顧客ずの調敎を含む倚くの業務を裁量を持っお自由にできるずころが良いず感じおいたす。たた、Insight Edgeでは業務時間の10%を勉匷䌚などの自己啓発に充おるこずが奚励されおいたす。この文化のおかげで、LangChainの勉匷䌚を運営したりTech Blogに蚘事を寄皿したりず、いろいろな事に挑戊できおずおも良い環境だなず感じおいたす。 さお、最近私が担圓する案件で、 生成AIに定性的な分析だけでなく定量的な分析もさせたい ずいう芁望がありたした。そこで今回は、生成AIにデヌタ分析をさせる手法を怜蚌しおみたした。具䜓的には、生成AIのAgentにKaggleのチュヌトリアルずしお有名なタむタニック号の乗客のデヌタセットを分析させ、分析結果を評䟡したので玹介しようず思いたす。 目次 はじめに 目次 抂芁 ※補足 案件で構築するシステムの抂芁 事前知識 自埋゚ヌゞェントずは ReAct(Reasoning and Acting)ずは LangChainずは ※補足 Code InterpreterではなくAgentで実装する理由 技術遞定 LangChainのAgent関連のコンポヌネントに぀いお 遞定理由 事前準備 実装内容 実行結果 考察 分析結果 分析過皋 Agentによる自埋的な゚ラヌ解決 たずめ 怜蚌結果 Code Interpreterずの比范 今埌に向けお 感想 抂芁 私が担圓しおいる案件で、生成AIに定量的な分析をさせたいずいう芁望がありたした。しかし、生成AIは 確率的にデヌタを生成するため、数孊のような論理的思考や数倀蚈算が苊手 です。 そこでどのように生成AIにデヌタ分析をさせるのか技術調査をしたした。生成AIに蚈算やデヌタ分析をさせる堎合、 Agent を䜿っおPythonのコヌドを生成・実行させる手法 が䞀般的です。 今回は、生成AIのAgentにKaggleのチュヌトリアルずしお有名なタむタニック号の乗客のデヌタセットを分析させ、分析結果を評䟡したした。 ※補足 案件で構築するシステムの抂芁 今回の怜蚌ずはあたり関係がないので、興味が無い方は読み飛ばしおください。 分析テヌマの入力 : ナヌザが分析したいテヌマを入力 定性的な分析の実斜 : 生成AIが入力されたテヌマに関連する情報をElastic Searchのハむブリッド怜玢機胜を甚いたRAGで収集し、その情報に基づいお定性的な分析を実斜 定量的な分析の実斜 : 生成AIのAgentが定性的な分析結果を元に瀟内デヌタの分析をするこずで定量的な分析も実斜※ここが今回の技術怜蚌に関連する郚分です。 最終的なレポヌトの生成 : システムが 定性的ず定量的な芖点を融合させた 最終的な分析レポヌトを生成 事前知識 自埋゚ヌゞェント、ReAct、LangChainに぀いおの簡単な説明です。ご存知の方は 技術遞定 たで読み飛ばしおください。 自埋゚ヌゞェントずは Agentずいう単語が出おきたしたが、あたり銎染みのない方もいるず思うので簡単に説明したす。生成AIやLLMの文脈で出おくるAgent=自埋゚ヌゞェントず思っおいただいお構いたせん。 自埋゚ヌゞェントは、䞎えられた最終目的に察しお、自ら思考しお蚈画をし、実際に行動をしお最終目的を達成しようずするシステムです。 この行動の際に、 自埋゚ヌゞェントはツヌルを䜿っお珟実䞖界のシステムに干枉 できたす。 この説明だず抜象床が高く、よく分からないず思うので今回の怜蚌を䟋に説明したす。 自埋゚ヌゞェントには、「タむタニック号の乗客のデヌタセットを分析する」ずいう最終目的だけを䞎えたす。 するず自埋゚ヌゞェントは、最初に思考しおどのように分析するか蚈画を立おたす。次に、蚈画に埓いむンタヌネット怜玢をするツヌルやPythonコヌド生成・実行ツヌルを䜿っおデヌタ分析を実斜しお最終目的を達成しようずしたす。 生成AIが内郚で考えおいるだけでなく、むンタヌネット怜玢ツヌルやPythonコヌド生成・実行ツヌルを䜿っお、珟実䞖界のシステムずやりずりをしおいるずころが、通垞の生成AIの利甚ず倧きく異なりたす 。 今回はReActずいう手法でAgentを動䜜させおいるので、詳现な仕組みは次の ReAct(Reasoning and Acting)ずは で説明したす。 自埋゚ヌゞェントに぀いお詳现を確認したい方は、 Autonomous Agents & Agent Simulations を参照しおください。 ReAct(Reasoning and Acting)ずは ReAct(Reasoning and Acting)は生成AIに論理的な思考をさせるPrompt Engineeringの技法の1぀です。生成AIに掚論ず行動を繰り返させるこずで論理的思考を促すもので、次の䞉段階のプロセスを繰り返したす。 思考(Thought) : 目的を理解し、行動蚈画・タスクの詳现化を行い、具䜓的な解決策を考案する。芳察(Observation)からフィヌドバックを受け取り、適宜行動蚈画を修正する。 行動(Action) : 思考(Thought)段階で考案された解決策を実行する。 芳察(Observation) : 行動(Action)の結果を芳察し、次の思考(Thought)ぞフィヌドバックする。 LangChainのAgentは、この 行動(Action)の郚分にツヌルを䜿甚 できたす。SerpApi等の怜玢ツヌルやPythonREPL等のPythonコヌド生成・実行ツヌルを䜿甚したす。利甚可胜なツヌルの説明を理解し、目的達成に必芁なものをAgent自ら遞択したす。 ぀たり、 䞎えられた最終目的に察しお自ら思考しお蚈画を立お、適切なツヌルを遞択しお行動し、結果の芳察ずフィヌドバックのルヌプを目的達成たで繰り返す自埋゚ヌゞェント が䜜成されたす。 ReActに぀いお詳现を確認したい方は、ReActが提唱された論文 ReAct: Synergizing Reasoning and Acting in Language Models を参照しおください。 LangChainずは LangChainずは倧芏暡蚀語モデル(LLM)を甚いたアプリケヌションを開発するためのフレヌムワヌクです。 様々な゚コシステムず連携しやすくなっおいたす。 LangChainにはモゞュヌルが6぀あるので簡単に玹介したす。今回は䞻にAgentsのモゞュヌルに関係がありたす。 モゞュヌル 抂芁 Model I/O LLMに察するプロンプト入力、呌び出し、結果の受け取りの実装を簡単にする。 Retrieval LLMに未知の情報にアクセスする機胜を提䟛する、Retrieval-Augmented Generation(RAG)を扱うモゞュヌル。倖郚の怜玢゚ンゞンやデヌタベヌスず連携しお、LLMに事前孊習しおいない情報に察応させる機胜を簡単に実装できるようにする。 Memory 過去の䌚話履歎をデヌタベヌスに保存したり、呌び出す機胜を簡単に実装できるようにする。 Chains 耇数のモゞュヌルの組み合わせを簡単に実装できるようにする。 Agents 自埋的に思考し、倖郚に干枉する自埋゚ヌゞェントの構築を簡単にする。 Callbacks 様々なむベント発生時の凊理の実装を簡単にする。ログの実装などに甚いる。 LangChainに぀いお詳现を確認したい方は、 LangChain公匏ドキュメント を参照しおください。 ※補足 Code InterpreterではなくAgentで実装する理由 こちらも今回の怜蚌ずは盎接関係がないので、興味が無い方は読み飛ばしおください。 技術怜蚌するのは生成AIのAgentにデヌタ分析をさせる郚分です。OpenAIのCode Interpreterず䌌た機胜ですが、Code Interpreterは倖郚環境むンタヌネット等にアクセスできない等の制玄がありたす。 䞀方、Agentであれば䞍明点や解決できない゚ラヌが発生した際に、怜玢ツヌルを䜿っお怜玢する等、他のツヌルを䜿った行動を取るこずもできたす。そのためAgentで実装した方が顧客の芁望に柔軟に察応できたす。 たた担圓する案件は、 案件で構築するシステムの抂芁 のように耇雑で今埌も拡匵されそうな芁件です。 Agentであれば行動やツヌルに぀いお自由にカスタマむズができる ためAgentで実装したした。 技術遞定 生成AIにデヌタ分析をさせる郚分を怜蚌したす。 怜蚌はLangChainで実装したした。 LangChainのAgent関連のコンポヌネントに぀いお 遞定理由を話す前に、LangChainのAgent関連のコンポヌネントの説明をしおおきたす。ご存知の方は読み飛ばしおください。 コンポヌネント 説明 AgentExecutor AgentExecutorは、Agentの実行を管理するコンポヌネントで、Agentが実行するタスクを制埡し、結果を凊理する。 Agent Agentは、特定のタスクやプロセスを自動化するための゚ンティティで、䞀連のToolsを䜿甚する。ツヌルのDescriptionを読んで適切なツヌルを遞択する。 Tools Toolsは、Agentがタスクを実行する際に䜿甚する具䜓的な機胜やサヌビスの集合。Toolsには倖郚のAPI呌び出しを可胜にするツヌル、Google怜玢などを可胜にする怜玢ツヌル、Pythonのコヌド生成・実行を可胜にするツヌルなどがある。 ※LangChainで利甚可胜なTools䞀芧は こちら 。 たた、独自のToolsの䜜成も簡単にできる。独自のRetrieverを定矩しおおけば独自実装したRAGを組み蟌んだAgentを䜜るこずができる。 Toolkit Toolkitは、耇数のToolsを組み合わせお構成されるセットで、特定のタスクを効率的に実行するために最適化されおいる。 Pythonのコヌド生成・実行に特化したToolkitなどもある。 ※LangChainで利甚可胜なToolkit䞀芧は こちら 。 遞定理由 技術芁玠 遞定理由 LLM: GPT-4 Turbo 粟床ずコストを重芖したため。 フレヌムワヌク: LangChain 生成AIのAgentを容易に実装・管理できるフレヌムワヌクであり、デファクトスタンダヌドになり぀぀あるため。 Tools: PythonREPL Pythonのコヌド生成・実行を可胜にするツヌル。デヌタ分析タスクにおいお、Pythonを䜿甚しお分析をするため Tools: DuckDuckGoSearch むンタヌネット怜玢を可胜にするツヌル。䞍明点や解決できない゚ラヌが発生した堎合に怜玢しお察凊するため。 今回はツヌルずしお独自定矩した。 Agent: ReAct Agentの汎甚性ず論理的な思考胜力を評䟡するため ReAct を採甚。案件で構築するシステムがチャット圢匏のため、LangChainのAgentTypeはCHAT_ZERO_SHOT_REACT_DESCRIPTION を採甚。 事前準備 事前にタむタニック号の乗客のデヌタセットをダりンロヌドし、S3などのダりンロヌド可胜な堎所に配眮しおください。タむタニック号の乗客のデヌタセットはKaggleからダりンロヌドできたす。 デヌタセットはKaggleにナヌザ登録をし、 Kaggleのタむタニックデヌタセットのペヌゞ からダりンロヌドできたす。 たた、OpenAIのAPIキヌは環境倉数に事前に登録しおおいおください。 OPEN_API_KEY="ご自身の保有しおいるAPIキヌを蚘茉しおください" 実装内容 䞋蚘のコヌドで、タむタニック号の乗客デヌタセットをダりンロヌドし、タむタニック号で生存に寄䞎した乗客の属性を分析させたす。 コヌドの内容は 遞定理由 に蚘茉した通りなので詳现な説明は割愛したす。 案件では再珟性の高い分析が求められおいるため、LLMのtemperatureを0に蚭定したした。 Agentに䞎える指瀺は以䞋にしおいたす。 タむタニック号の乗客のデヌタセットを分析しおください。生存に寄䞎した属性をランキングで衚瀺し、圱響床を数倀で衚瀺しおください。デヌタセットは、https://xxxxxxxxxxxx/train.csv を䜿甚しおください。 デヌタセットをむンタヌネットからダりンロヌドするよう指瀺したのは、OpenAIのCode Interpreterができない倖郚環境ぞのアクセスが可胜か怜蚌するためです。コヌドを実行する堎合は、 事前準備 にあるようにダりンロヌド可胜なURLに曞き換えおください。 from langchain.agents import AgentType, initialize_agent, load_tools, Tool from langchain.chat_models import ChatOpenAI from langchain.tools import DuckDuckGoSearchRun chat = ChatOpenAI( temperature= 0 , # 再珟性を重芖するため、temperatureを0に蚭定 model= "gpt-4-turbo-preview" ) tools = load_tools( # Agentが䜿甚可胜なツヌルの配列を読み蟌む耇数指定可胜、Agentがツヌルのdescriptionを読み適切なツヌルを遞択する [ "python_repl" # Pythonのコヌドを実行するためのTool ] ) search = DuckDuckGoSearchRun() # 䞍明点や゚ラヌの解決策を怜玢するためDuckDuckGoSearchを远加 tools.append( # 远加したDuckDuckGoSearchをtoolsに远加 Tool( # ツヌルずしお怜玢ツヌルを独自定矩 name= "duckduckgo-search" , func=search.run, description= "This tool is used for conducting internet searches to address uncertainties or unresolved errors that arise during tasks or development processes." # Agentが遞択できるようにツヌルの説明を蚘茉 ) ) agent = initialize_agent( tools=tools, # Agentが䜿甚するこずができるツヌルの配列を指定 llm=chat, # Agentが䜿甚する蚀語モデルを指定 agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION, #ReActを実行するAgentを指定 verbose= True # 実行䞭の詳现なログを衚瀺する ) result = agent.run( "タむタニック号の乗客のデヌタセットを分析しおください。生存に寄䞎した属性をランキングで衚瀺し、圱響床を数倀で衚瀺しおください。デヌタセットは、https://xxxxxxxxxxxx/train.csv を䜿甚しおください。" ) print (f "実行結果: {result}" ) 実行結果 実行するず、論理的に掚論ず行動を繰り返し、最終的にランキングを出力できたした。 出力結果 parch : 0.6250 sex : 0.5365 sibsp : 0.5110 pclass : 0.3639 fare_quantile : 0.3567 age_group : 0.1178 この分析結果では、parch同乗しおいる家族芪子の人数、sex性別、sibsp同乗しおいる兄匟姉効、配偶者の数、pclass客宀等玚、fare_group運賃、age_group幎霢の順に生存ぞの圱響が匷い属性だったようですね。 実行結果を芋おみたしょう。※実行結果䞭のデヌタセットのダりンロヌドURLは曞き換えおいたす。) 実行結果党文非垞に長いので詳现を確認したい方のみ、この文章をクリックしお展開しおください。 > Entering new AgentExecutor chain... Question: Analyze the Titanic passengers dataset to determine which attributes had an impact on survival. Provide the analysis results in a ranking with numerical values indicating the degree of impact on survival. Download the dataset using Python from the provided URL ( https://xxxxxxxxx/train.csv ) . Thought: To analyze the Titanic dataset, I will first need to download the data using Python. After downloading, I will load the data into a pandas DataFrame and perform exploratory data analysis ( EDA ) to determine which attributes had the most significant impact on survival. Action: { " action " : " Python_REPL " , " action_input " : " import pandas as pd \n df = pd.read_csv('https://xxxxxxxxx/train.csv') \n print(df.head()) " } Python REPL can execute arbitrary code. Use with caution. Observation: pclass survived name sex age sibsp parch ticket fare cabin embarked boat body home.dest 0 1 1 Allen, Miss. Elisabeth Walton female 29 . 0000 0 0 24160 211 . 3375 B5 S 2 NaN St Louis, MO 1 1 1 Allison, Master. Hudson Trevor male 0 . 9167 1 2 113781 151 . 5500 C22 C26 S 11 NaN Montreal, PQ / Chesterville, ON 2 1 0 Allison, Miss. Helen Loraine female 2 . 0000 1 2 113781 151 . 5500 C22 C26 S NaN NaN Montreal, PQ / Chesterville, ON 3 1 0 Allison, Mr. Hudson Joshua Creighton male 30 . 0000 1 2 113781 151 . 5500 C22 C26 S NaN 135 . 0 Montreal, PQ / Chesterville, ON 4 1 0 Allison, Mrs. Hudson J C ( Bessie Waldo Daniels ) female 25 . 0000 1 2 113781 151 . 5500 C22 C26 S NaN NaN Montreal, PQ / Chesterville, ON Thought:The dataset has been successfully loaded into a pandas DataFrame. The next step is to perform exploratory data analysis ( EDA ) to determine which attributes had the most significant impact on survival. I will start by checking for missing values in the dataset, as this can affect the analysis. Then, I will proceed to calculate the survival rates based on different attributes such as ' pclass ' , ' sex ' , ' age ' , ' sibsp ' , ' parch ' , ' fare ' , and ' embarked ' . Action: { " action " : " Python_REPL " , " action_input " : " print(df.isnull().sum()) " } Observation: pclass 0 survived 0 name 0 sex 0 age 263 sibsp 0 parch 0 ticket 0 fare 1 cabin 1014 embarked 2 boat 823 body 1188 home.dest 564 dtype: int64 Thought:The dataset contains a significant number of missing values in the ' age ' , ' cabin ' , ' boat ' , ' body ' , and ' home.dest ' columns. The ' boat ' and ' body ' columns are not typically used for survival analysis, as they relate to post-accident events ( lifeboats and body recovery ) . The ' cabin ' data is also largely missing, which may limit its usefulness in the analysis. However, ' age ' and ' embarked ' are important factors that are often considered in survival analysis. The missing value in ' fare ' is negligible as it is only one entry. The next step is to analyze the impact of various attributes on survival. I will calculate survival rates based on ' pclass ' , ' sex ' , ' age ' , ' sibsp ' , ' parch ' , and ' fare ' . Since ' age ' has missing values, I will need to decide how to handle them, either by imputing a value or by excluding those rows from certain parts of the analysis. For the initial analysis, I will focus on the attributes with complete data. I will start by calculating the survival rates for ' pclass ' and ' sex ' , as these are commonly known to have had a significant impact on survival. Then I will proceed with ' sibsp ' , ' parch ' , and ' fare ' . For ' age ' , I will consider how to handle the missing values before proceeding. Action: { " action " : " Python_REPL " , " action_input " : " survival_rates = {} \n for column in ['pclass', 'sex', 'sibsp', 'parch']: \n survival_rates[column] = df.groupby(column)['survived'].mean() \n print(survival_rates) " } Observation: { ' pclass ' : pclass 1 0 . 619195 2 0 . 429603 3 0 . 255289 Name: survived, dtype: float64, ' sex ' : sex female 0 . 727468 male 0 . 190985 Name: survived, dtype: float64, ' sibsp ' : sibsp 0 0 . 346801 1 0 . 510972 2 0 . 452381 3 0 . 300000 4 0 . 136364 5 0 . 000000 8 0 . 000000 Name: survived, dtype: float64, ' parch ' : parch 0 0 . 335329 1 0 . 588235 2 0 . 504425 3 0 . 625000 4 0 . 166667 5 0 . 166667 6 0 . 000000 9 0 . 000000 Name: survived, dtype: float64 } Thought:The survival rates based on ' pclass ' , ' sex ' , ' sibsp ' , and ' parch ' show clear trends. Higher class passengers ( pclass 1 ) had a higher survival rate than those in lower classes. Females had a much higher survival rate than males. The number of siblings/spouses ( sibsp ) and parents/children ( parch ) aboard also had varying impacts on survival rates, with some numbers showing higher survival rates than others. To provide a more comprehensive analysis, I will now calculate the survival rate for ' fare ' by categorizing it into quantiles, which will help to understand if higher fares ( which could correlate with higher socio-economic status or cabin location ) had an impact on survival. I will also handle the missing ' age ' data by filling in the missing values with the median age, and then categorizing age into groups to see if there is a trend in survival rates across different age groups. First, I will handle the ' fare ' attribute by categorizing it into quantiles. Action: { " action " : " Python_REPL " , " action_input " : " df['fare_quantile'] = pd.qcut(df['fare'], 4, labels=False) \n survival_rates['fare_quantile'] = df.groupby('fare_quantile')['survived'].mean() \n print(survival_rates['fare_quantile']) " } Observation: fare_quantile 0 . 0 0 . 228487 1 . 0 0 . 284375 2 . 0 0 . 435976 3 . 0 0 . 585139 Name: survived, dtype: float64 Thought:The survival rates for the ' fare_quantile ' show a positive correlation between fare price and survival, with passengers who paid higher fares having a higher survival rate. This suggests that socio-economic status , which could be inferred from the fare paid, had an impact on survival. Next, I will address the missing ' age ' data. Since age is an important factor and cannot be ignored, I will impute the missing values with the median age. After imputing the missing values, I will categorize the ' age ' into groups and calculate the survival rates for each group to see if there is a trend in survival rates across different age groups. Action: { " action " : " Python_REPL " , " action_input " : " median_age = df['age'].median() \n df['age'].fillna(median_age, inplace=True) \n df['age_group'] = pd.qcut(df['age'], 4, labels=False) \n survival_rates['age_group'] = df.groupby('age_group')['survived'].mean() \n print(survival_rates['age_group']) " } Observation: age_group 0 0 . 435435 1 0 . 317597 2 0 . 425532 3 0 . 394410 Name: survived, dtype: float64 Thought:The survival rates for the ' age_group ' show that the youngest and older age groups had slightly higher survival rates than the middle age groups, although the differences are not as pronounced as with other attributes like ' sex ' and ' pclass ' . Now that I have calculated the survival rates for ' pclass ' , ' sex ' , ' sibsp ' , ' parch ' , ' fare_quantile ' , and ' age_group ' , I can rank these attributes by their impact on survival. To do this, I will calculate the difference in survival rates between the highest and lowest groups within each attribute to determine the range of impact. Then I will rank the attributes based on these ranges. Action: { " action " : " Python_REPL " , " action_input " : " impact_ranges = {} \n for attribute, rates in survival_rates.items(): \n impact_ranges[attribute] = rates.max() - rates.min() \n impact_ranking = sorted(impact_ranges.items(), key=lambda x: x[1], reverse=True) \n for rank in impact_ranking: \n print(f'{rank[0]}: {rank[1]:.4f}') " } Observation: parch: 0 . 6250 sex: 0 . 5365 sibsp: 0 . 5110 pclass: 0 . 3639 fare_quantile: 0 . 3567 age_group: 0 . 1178 Thought:The ranking of attributes based on their impact on survival, with the numerical values indicating the degree of impact, is as follows: 1 . `parch` ( number of parents/children aboard ) : 0 . 6250 2 . `sex` : 0 . 5365 3 . `sibsp` ( number of siblings/spouses aboard ) : 0 . 5110 4 . `pclass` ( passenger class ) : 0 . 3639 5 . `fare_quantile` ( fare price category ) : 0 . 3567 6 . `age_group` : 0 . 1178 It is important to note that the `parch` attribute shows the largest range of impact, which might be surprising as it is not typically considered the most significant factor. However, this could be due to the way the survival rates are calculated across different numbers of parents/children aboard, which might not be linear and could be influenced by small sample sizes for certain values. The `sex` attribute has the second-highest impact, which aligns with historical accounts that women were given priority during the lifeboat boarding process. The `sibsp` attribute is third, suggesting that having siblings or a spouse aboard had a significant impact on survival, potentially due to the support system or prioritization of families during evacuation. The `pclass` attribute is fourth, indicating that passenger class was a significant factor, with first-class passengers having a higher survival rate. The `fare_quantile` is fifth, which is related to socio-economic status and potentially cabin location, with higher fares correlating with higher survival rates. Lastly, the `age_group` has the smallest range of impact, suggesting that age was a less significant factor compared to the others, although there was still some variation in survival rates across age groups. Final Answer: The ranking of attributes by impact on survival, from highest to lowest, is as follows: 1 . `parch` : 0 . 6250 2 . `sex` : 0 . 5365 3 . `sibsp` : 0 . 5110 4 . `pclass` : 0 . 3639 5 . `fare_quantile` : 0 . 3567 6 . `age_group` : 0 . 1178 > Finished chain. 実行結果: The ranking of attributes by impact on survival, from highest to lowest, is as follows: 1 . `parch` : 0 . 6250 2 . `sex` : 0 . 5365 3 . `sibsp` : 0 . 5110 4 . `pclass` : 0 . 3639 5 . `fare_quantile` : 0 . 3567 6 . `age_group` : 0 . 1178 䞭身を芋おみたしょう。はじめにQuestionで最終目的を定矩しおいたす。 Question: Analyze the Titanic passengers dataset to determine which attributes had an impact on survival. Provide the analysis results in a ranking with numerical values indicating the degree of impact on survival. Download the dataset using Python from the provided URL ( https://xxxxxxxxx/train.csv ) . きちんず指瀺通りに、生存に寄䞎した属性をランキング圢匏で衚瀺するタスクを理解しおいたすね。 その埌は、以䞋6ステップに分けお実行しおいるようです。 デヌタセットのダりンロヌドず読み蟌み : 指定されたURLからタむタニックのデヌタセットをダりンロヌドし、PandasのDataFrameに読み蟌みたす。読み蟌んだデヌタの先頭郚分を衚瀺しお、デヌタが正しく読み蟌たれたこずを確認したす。 欠損倀の確認 : デヌタセットに含たれる欠損倀の数を確認したす。特に「幎霢(age)」、「キャビン(cabin)」、「乗船した枯(embarked)」などのカラムで欠損倀が倚いこずが分かりたす。これらの欠損倀は分析に圱響を䞎えるため、適切に凊理する必芁がありたす。 生存率の蚈算 : 生存に圱響を䞎えた可胜性のある属性「客宀等玚(pclass)」、「性別(sex)」、「兄匟姉効や配偶者の数(sibsp)」、「芪や子どもの数(parch)」に぀いお、グルヌプごずに生存率を蚈算したす。 料金(fare)に基づく生存率の蚈算 : 乗船料金を四分䜍数で分割し、料金のカテゎリヌごずに生存率を蚈算したす。料金が生存率にどのように圱響したかを分析したす。 幎霢(age)に基づく生存率の蚈算 : 幎霢デヌタの欠損倀を䞭倮倀で補完し、幎霢をグルヌプに分けお生存率を蚈算したす。幎霢が生存率にどのように圱響したかを分析したす。 属性の圱響床のランキングの衚瀺 : 最埌に、各属性に基づいお蚈算された生存率の差を甚いお、生存に最も圱響を䞎えた属性をランキング圢匏で衚瀺したす。ランキングは、各属性が生存に䞎えた圱響の床合いを数倀で瀺しおいたす。 考察 分析結果 Agentによる分析ず人による分析を比范しお劥圓性を確認したす。 Kaggleで今回のデヌタセットの分析をされおいるこちらの投皿 を芋おも、生存に圱響を䞎えおいる属性が同じですね。人が行った分析ず比范しおも、今回のAgentの行った分析は劥圓ず蚀えたす。タむタニック号の史実ず照らし合わせおも客宀等玚、性別、子䟛を連れた家族などの属性が生存に圱響したずいう分析は劥圓ず蚀えたす。 分析過皋 今回の怜蚌では分析結果よりも分析過皋自䜓の考察が重芁です。 生存に寄䞎した属性をランキング衚瀺するずいう倧目暙のみを䞎えおいたしたが、 Agentは目的達成のために自埋的に思考し自ら詳现なタスクを䜜り出しお実行 しおいたした。特にデヌタを確認しお自らの刀断で欠損倀を確認しお補完したり、生存率を蚈算した埌、関連のありそうな属性を詳现に分析するタスクを自ら䜜り出しお実行しおいる点は非垞に興味深いです。 今回のデヌタセットを分析しおいる蚘事をいく぀か拝芋したしたが、 欠損倀を埋める等の指瀺をしおいないタスクも人ず同様の手順 で実行できおいたした。 このような論理的な思考ができる理由は ReAct の掚論フレヌムワヌクを䜿甚したからだず考えられたす。 該圓箇所抜粋 Thought:The dataset has been successfully loaded into a pandas DataFrame. The next step is to perform exploratory data analysis ( EDA ) to determine which attributes had the most significant impact on survival. I will start by checking for missing values in the dataset, as this can affect the analysis. Then, I will proceed to calculate the survival rates based on different attributes such as ' pclass ' , ' sex ' , ' age ' , ' sibsp ' , ' parch ' , ' fare ' , and ' embarked ' . Action: { " action " : " Python_REPL " , " action_input " : " print(df.isnull().sum()) " } Observation: pclass 0 survived 0 name 0 sex 0 age 263 sibsp 0 parch 0 ticket 0 fare 1 cabin 1014 embarked 2 boat 823 body 1188 home.dest 564 dtype: int64 Thought:The dataset contains a significant number of missing values in the ' age ' , ' cabin ' , ' boat ' , ' body ' , and ' home.dest ' columns. The ' boat ' and ' body ' columns are not typically used for survival analysis, as they relate to post-accident events ( lifeboats and body recovery ) . The ' cabin ' data is also largely missing, which may limit its usefulness in the analysis. However, ' age ' and ' embarked ' are important factors that are often considered in survival analysis. The missing value in ' fare ' is negligible as it is only one entry. The next step is to analyze the impact of various attributes on survival. I will calculate survival rates based on ' pclass ' , ' sex ' , ' age ' , ' sibsp ' , ' parch ' , and ' fare ' . Since ' age ' has missing values, I will need to decide how to handle them, either by imputing a value or by excluding those rows from certain parts of the analysis. For the initial analysis, I will focus on the attributes with complete data. Agentによる自埋的な゚ラヌ解決 䜕床か怜蚌をしおいるず、Agentが生成したPythonのコヌドが実行時に゚ラヌを吐くこずがありたした。゚ラヌが発生した際にAgentは、 ReAct の掚論フレヌムワヌクに沿っお、゚ラヌを自埋的に解決しおいたした。具䜓的には発生した゚ラヌの解決策を怜玢ツヌルで怜玢しお解決しおいたした。 自埋的な゚ラヌ解決のプロセス 芳察(Observation) : 前回の行動(Action)の結果、゚ラヌの発生を確認する。 思考(Thought) : 解決策を探すために、適切なツヌルの䜿甚する。「䞍明点や゚ラヌの解決策を怜玢するためのツヌル」ずいう説明の怜玢ツヌルを芋぀け、解決策をむンタヌネット怜玢するこずを蚈画する。 行動(Action) : 怜玢ツヌルを甚いお解決策を怜玢する。 芳察(Observation) : 怜玢結果から有益な情報を抜出する。 思考(Thought) : 抜出された情報から具䜓的なアクションを考案する。 行動(Action) : Pythonコヌド生成・実行ツヌルで解決策を実行する。 このように 予期せぬ事態に遭遇しおも、掚論ず行動を繰り返すReActのAgentは柔軟に察応 できたす。状況に合わせお臚機応倉に蚈画を倉曎し、ツヌルを䜿い分け、目的達成に向けおタスクを継続できる点がReActで動䜜するAgentの匷みです。 䞋蚘の事䟋は、seabornずいうモゞュヌルがむンストヌルできない゚ラヌが発生し、解決策を怜玢ツヌルで怜玢しおいたす。結局むンストヌルできないずいう問題は解決できたせんでしたが、他のモゞュヌルを䜿うこずで゚ラヌを回避しお分析を進めおいたした。 Agentが発生した゚ラヌの解決策を怜玢したり、回避策を探しお分析を続けおいる事䟋 Action: { " action " : " Python_REPL " , " action_input " : " !pip install seaborn " } Observation: SyntaxError ( ' invalid syntax ' , ( ' <string> ' , 1 , 1 , ' !pip install seaborn\n ' , 1 , 2 )) Thought:It seems that I made the same mistake again. I need to use the duckduckgo-search tool to search for the correct way to install the seaborn module. Action: { " action " : " duckduckgo-search " , " action_input " : " install seaborn module in Python using pip " } Observation: Latest version Jan 25 , 2024 Project description seaborn: statistical data visualization Seaborn is a Python visualization library based on matplotlib. It provides a high-level interface for drawing attractive statistical graphics. Documentation Online documentation is available at seaborn.pydata.org. We can install the seaborn package by running the below command . pip install seaborn Kindly ensure that you have pip installed on your device before running this command . For Python 3 , we can use the pip3 command instead of pip. We can also specify the required version of the module we wish to install, as shown below. pip3 install seaborn = = 0 . 9 . 0 The pip show seaborn command will either state that the package is not installed or show a bunch of information about the package, including the location where the package is installed. # Make sure your IDE is using the correct Python version If the package is not installed, make sure your IDE is using the correct version of Python. How can I Install a Python module within code? Ask Question Asked 11 years, 5 months ago Modified 8 months ago Viewed 552k times 503 I need to install a package from PyPI straight within my script. Getting Started First of all, let us install Seaborn. Seaborn can be installed using the pip. Type the below command in the terminal. pip install seaborn In the terminal, it will look like this - After the installation is completed you will get a successfully installed message at the end of the terminal as shown below. Thought:Based on the search results, the correct way to install the seaborn module is by using the pip command . I will now install seaborn using the pip command . Action: { " action " : " Python_REPL " , " action_input " : " !pip install seaborn " } Observation: SyntaxError ( ' invalid syntax ' , ( ' <string> ' , 1 , 1 , ' !pip install seaborn\n ' , 1 , 2 )) Thought:I apologize for the repeated mistake. It seems that I am unable to install the seaborn module using the pip command in this environment. However, I can still analyze the dataset using other available tools and libraries. I will proceed with analyzing the dataset without using seaborn. たずめ 怜蚌結果 生成AIは䞀般に確率的にデヌタを生成するため、論理的な思考やデヌタ分析のような数倀蚈算は苊手です。 しかし、今回怜蚌したように生成AIのAgentに ReAct のような掚論フレヌムワヌクずPythonコヌド生成・実行をするツヌルを組み合わせるこずで、論理的思考や数倀蚈算が必芁なデヌタ分析等のタスクも実行できる ようになりたす。Agentによる分析も人による分析ず比范しおも劥圓性の高いものでした。 たた、生成したPythonのコヌドで゚ラヌが発生した際に怜玢のツヌルを䜿っお、゚ラヌの解決策を怜玢しに行くなど臚機応倉な察応をしおいたした。 想定倖の事態が起きおも、蚈画を倉曎しツヌルを䜿い分けお察応できる点も、掚論ず行動を繰り返すReActのAgentの匷み ず蚀えたす。 Code Interpreterずの比范 OpenAIのCode Interpreterではこれほど掚論ず行動を繰り返しおタスクを実行するこずはありたせん。゚ラヌ解決のためにむンタヌネットで怜玢するなどの臚機応倉な察応もできたせん。そもそもむンタヌネット等の倖郚環境にアクセスができたせん。䞊蚘の点からも今回のようなAgentの実装に優䜍性がありたす。 逆にいうずAgentは行動を予枬しづらく、行動回数が増えお返答たで時間がかかったり、GPT-4 Turboの呌び出し回数も増加しお高コストになる可胜性がありたす。芁件に応じお最倧行動回数を蚭定する等の察策をするず良いず思いたす。 今埌に向けお 案件では、生成AIでRAGを甚いおプラむベヌトデヌタの定性的な分析をし、埗られた定性的な分析を元に定量的な分析をしたす。今回の怜蚌よりも耇雑で高い粟床を求められるので今埌も改良が必芁です。今回は単䞀のAgentで実装したしたが、今埌は耇数のAgentを䜿った構成も詊したいず思いたす。マルチ゚ヌゞェントず呌ばれる、耇数の異なる圹割を持った゚ヌゞェントが協力するシステムや、 BabyAGI などの高床な自埋゚ヌゞェントを怜蚌し、高粟床でより耇雑なタスクぞ可胜なシステムを実装しようず思いたす。 感想 生成AIのAgentを䜿ったデヌタ分析をしおみたしたが、 ReAct の論理的思考には驚かされたした。特に、Agentが生成したPythonのコヌドで゚ラヌが発生した際に怜玢を始めた時には、こんなこずができるのかず非垞に驚きたした。 最近では、耇数の異なる圹割を持った゚ヌゞェントが協力するマルチ゚ヌゞェント等、耇雑なタスクに察応できるアヌキテクチャも流行っおいたす。たた、最近のLLMはマルチモヌダルテキストだけでなく、画像、音声、動画など様々なデヌタ圢匏に察応したモデルにもなっおきおいたす。 マルチモヌダルずマルチ゚ヌゞェントを組み合わせるずかなり幅広いタスクができるようになる のではないかず思いたす。 限界を越えお進化し続ける生成AIは、非垞に面癜いので今埌も積極的に関わっおいこうず思いたす 本蚘事がどなたかの圹に立おば幞いです
初めたしお、去幎の11月にInsight Edgeぞ参画したEngineerの田島です。 珟圚の業務では生成AI甚いたDX案件や䜏友商事グルヌプ事業の゜フトりェア開発に携わっおいたす。 ただ加入しおから数ヶ月ですが、Insight Edgeの特城ずしお「小回りの良さず技術遞定の幅の広さ」を匷く感じおいたす。 出島組織なので開発を柔軟に進めおいくこずが可胜であり、 幅広いビゞネスをしおいる総合商瀟ならではの様々な課題に察応すべく、 幅の広い技術遞定が求められるように感じたす。 たた、゚ンゞニア・デヌタサむ゚ンティスト・コンサルタントが互いにリスペクトし、プロフェッショナルずしお働いおるので、成長の堎ずしおも適しおいるかず思いたす。 本蚘事ではComputer Visionのシステムを題材に、生成AIの掻甚で泚目が集たっおいるAzureを甚いたMLOpsの実珟に぀いお玹介したいず思いたす。 抂芁 想定ケヌス ビゞネスシヌンずしお、各カメラから取埗される人流情報を防犯や空調の最適化に掻かすこずを想定したす。 想定ケヌス 耇数のカメラを甚いたシステムの課題 カメラシステムを実際に運甚する䞊で、蚭眮条件は個䜓毎に異なりたす。 これにより、カメラ毎の認識粟床がばら぀くず想定されたす。 䟋えば、暗所による撮圱における感床自動制埡で、䞋図のようなノむズが生じたす。 (感床自動制埡ずはカメラ信号凊理の䞀郚で、適正な明るさが埗られない堎合などに電気的に信号を増幅させるこずで適正な明るさの画像を埗る凊理のこずです。) 同じカメラにおいおも長期期間システムを運甚するうえでは、季節や呚蟺環境の倉化により圱響床が倉化したす。 このカメラの粟床ばら぀きが、本ナヌスケヌスの人流情報の効果的な利甚の問題になるず考えられたす。 暗所によるノむズの䟋 システムの抂芁 本蚘事では、認識粟床のばら぀きを自動的に補正する画像認識システムを考えたす。 これにより、安定した認識率のシステムを構築するだけでなく、 埓来はカメラの蚭眮条件などを倉えるなどしおいた䜜業をシステムずアルゎリズムが肩代わりするこずで、保守工数を削枛したシステムを構築したす。 このシステム構築にあたっおは、Azure Custom VisionのOptimization機胜を甚いお、カメラ毎の条件に合わせお再孊習したす。 (*) 本蚘事ではセンサヌノむズや画像凊理の詳现には螏み蟌みたせん。あくたでシステム構築に䞻県を眮きたす。 システムの内容 MLOps 機械孊習の瀟䌚実装をするうえで、他のシステムず同様に継続的なむンテグレヌションずデリバリヌが求められたす。 MLOpsはこれを実珟する゚コシステムを指し、Googleの提唱する 実珟レベル が有名です。 この実珟レベルの抂芁は以䞋の通りです。 レベル手動による孊習プロセス。モデルの倉曎が皀なケヌスを想定したす。 レベル孊習パむプラむンの自動化。パむプラむントリガヌによっお自動的にモデルを曎新したす。 レベルCI/CDパむプラむンの自動化・効率化。モデルの倉曎アむデアを迅速に反映・怜蚌したす。 そこで本蚘事ではレベル1を題材に、継続的にモデルを曎新するこずで、蚭眮環境の倉化によるノむズ圱響の解決を考えたす。 むンフラ構成 本蚘事で構築するシステムのアヌキテクチャは以䞋の通りです。 むンフラ構成 Azure Custom Vision Azure Custom Visionは特定のドメむンに特化した画像認識モデルを䜜成可胜なサヌビスです。 利甚にあたっおは機械孊習モデルの専門知識は必芁なく、WebUIたたはREST APIでサヌビスを利甚できたす。 レベル1のMLOpsに必芁䞍可欠な芁玠であるモデルのテストや゚ッゞ環境などぞデプロむに察応しおいたす。 2024/02珟圚は、1枚の画像をクラス分類するClassificationず画像䞭に物䜓䜍眮を認識するObject Detectionに察応しおいたす。 本蚘事では、画像䞭から察象物の数を抜出するためにObject Detectionを採甚し、REST APIを甚いおカメラ毎に適切な孊習を自動的に行いたす。 むンフラ構成の説明 カメラで取埗された画像デヌタは、AzureのBlobストレヌゞにアップロヌドされるものずしたす。 このアップロヌドをトリガヌずしお、Azure Functionsを起動させ、人物怜出したす。 人物怜出には䞊のAzure Custom Visionで生成したONNXモデルをStorageからダりンロヌドしたす。 そしお、怜出された人物の数がSQLデヌタベヌスに蚘録されたす。 たた、Azure Functionsの定期実行を甚いお、モデルを曎新したす。 モデル曎新甚に撮圱された耇数枚の画像から統蚈的なばら぀きを掚定し、それらの圱響を孊習デヌタに付加しお、カメラ環境に合った孊習デヌタを生成したす。 この孊習デヌタをAzure Custom Visionにアップロヌドし、モデルの再孊習したす。孊習終了埌にStorageのモデルを曎新したす。 今埌゚ッゞでの怜出凊理を想定し、モデルデヌタの゚クスポヌトしたす。 仮にクラりドでの凊理に完結させる堎合は、モデルのAzure Custom VisionのAPI゚ンドポむントずしおパブリッシュするこずで、システムを簡略化可胜です。 ゜ヌスコヌド ゜ヌスコヌドは以䞋のレポゞトリで公開しおいたす。 GitHub Link デプロむメント ゜ヌスコヌド䞭のterraformを甚いおクラりドリ゜ヌスのデプロむが可胜です。 䞀方でCustom Visionに぀いおは、Microsoftの「AIの責任ある䜿甚」に関するポリシヌに同意する必芁があるためAzure Portalで行いたす。 MarketPlaceよりCustom Visionを遞択し、「䜜成オプション」を「トレヌニング」にしおリ゜ヌスを䜜成したす。 モデルを゚クスポヌトせずに、孊習枈みモデルをREST APIずしお実行する堎合は「䞡方」を遞択しおください。 トレヌニングの䟡栌レベルは芁件に合わせお遞択したすが、PoC段階ずいうこずで「Free F0」を遞択したす。 Custom Visionのリ゜ヌス䜜成 MLワヌクフロヌ 本蚘事では゜ヌスコヌドのMLワヌクフロヌおよびAzure Custom Visionに぀いお説明したす。 孊習デヌタの準備 人物怜知に向けた孊習デヌタの䜜成にあたり、ここでは商甚可胜なものを遞定たたは䜜成する必芁がありたす。 しかし、このデヌタセットの甚意は本蚘事のシステム構築の趣旚から倖れるため、怜蚌甚ずしおお菓子袋の怜出を考えたす。 ここで甚意した画像に、以䞋のような怜出甚のバりンディングボックスを蚭定し、それらの情報を保存したす。 ここたでの準備をシステム構築前に行いたす。 お菓子ずバりンディングボックス 再孊習時には、この孊習デヌタにガりシアンノむズを付䞎したす。 ガりシアンノむズの分散倀には、被写䜓の時間倉化が少ない期間に撮圱された耇数枚の画像から、画玠ごずに分散倀を算出し、党画玠の最頻倀を採甚したす。 これにより、被写䜓が䞀定であるずきのランダムノむズの代衚倀を近䌌的に取埗したす。 (*) この方法では信号量に䟝存したノむズ量を正しく芋積もるこずができたせん。より粟床を求める堎合は改善の䜙地がありたす。 ノむズ量の算出 モデル孊習 Custom VisionをPython向けのSDK越しに甚いお、孊習デヌタをアップロヌドしたす。 モデル孊習のタスクをキュヌに远加し、䞀定期間埅機するこずで孊習が終了したす。 以䞋は゜ヌスコヌドの䞀郚を抜粋し、コメントを加えたものです。 from azure.cognitiveservices.vision.customvision.training import ( CustomVisionTrainingClient, ) from azure.cognitiveservices.vision.customvision.training.models import ( Region, ImageFileCreateEntry, ImageFileCreateBatch, ) from msrest.authentication import ApiKeyCredentials ``` 省略 ``` credentials = ApiKeyCredentials(in_headers={"Training-key": TRAINING_KEY}) trainer = CustomVisionTrainingClient(ENDPOINT, credentials) # ドメむンの䜜蚭定 # ゚ッゞデバむスぞのデプロむを芋越しお`compact`を遞定 # `compact`を遞定しない堎合はWebAPI越しの実行しかできない obj_detection_domain = next( domain for domain in trainer.get_domains() if domain.type == "ObjectDetection" and domain.name == "General (compact)" ) # プロゞェクトを䜜成 project = trainer.create_project( "People Counting Project", domain_id=obj_detection_domain.id, ) # タグの䜜成 person_tag = trainer.create_tag(project.id, "Person") # アップロヌド画像のリスト化 # 䞊で保存した情報(ファむル名ずバりディングボックス)が"json_data"に栌玍 tagged_images_with_regions = [] for data in json_data: image_file = data['fileName'] tags = data["tags"] regions = [ Region( tag_id=person_tag.id, left=tag["left"], top=tag["top"], width=tag["width"], height=tag["height"], ) for tag in tags ] with open(image_file, "rb") as image_contents tagged_images_with_regions.append( ImageFileCreateEntry( name=image_file, contents=image_contents.read(), regions=regions, ) ) # ファむル矀のアップデヌト trainer.create_images_from_files( project.id, ImageFileCreateBatch(images=tagged_images_with_regions) ) # 孊習タスクをキュヌに入れる(ここではむテレヌションのみ) iteration = trainer.train_project(project.id) プロゞェクトの䜜成ずファむル矀のアップデヌトに成功するず、Custom Visionポヌタルからアップロヌドされたファむルずタグ情報を確認できたす。 たた、Custom Visionポヌタルからも画像のアップロヌドずタグ付けが可胜です。 Custom Vision Portal 孊習の確認 トレヌニング終了埌に、孊習にデヌタにおける粟床、再珟率、平均粟床を確認できたす。 これにより、孊習が成功したかを確認できたす。 この内容はCustom VisionポヌタルのPerformanceタブからも確認可胜です。 # interation.status == "Completed" で孊習終了 iteration_id = iterations[0].id # 最新のむテレヌション iteration_performance = trainer.get_iteration_performance( project_id, iteration_id ) # パフォヌマンス指暙の衚瀺 print("Precision: {:.2f}".format(iteration_performance.precision)) print("Recall: {:.2f}".format(iteration_performance.recall)) print("Average Precision: {:.2f}".format(iteration_performance.average_precision)) パフォヌマンス指暙 モデルデプロむおよび実行 SDKよりモデルURLを取埗し、ダりンロヌドできたす。 ダりンロヌドされたzipファむルには、実行甚のPython゜ヌスコヌドずモデルデヌタ("*.onnx")が含たれたす。 本蚘事のシステムでは、このモデルデヌタをBlobストレヌゞに眮き、゜ヌスコヌドはAzure Functionにデプロむしたす。 # モデルの゚クスポヌト export = trainer.export_iteration(project_id, iteration_id, "ONNX") while export.status != "Done": export = trainer.get_export(project_id, iteration_id, export.id) time.sleep(10) # URLの取埗ずダりンロヌド model_url = export.download_uri export_file = requests.get(model_url) with open("export.zip", "wb") as file: file.write(export_file.content) 実際にコヌドを実行するず以䞋のように出力され、怜出物のリストが出力されたす。 このリスト長を人流デヌタずしお蚘録したす。 $ python python/onnxruntime_predict.py test_001.png [ {'probability': 0.96306247, 'tagId': 0, 'tagName': 'Person', 'boundingBox': {'left': 0.6113374, 'top': 0.1495378, 'width': 0.23059763, 'height': 0.18790943}}, {'probability': 0.93494284, 'tagId': 0, 'tagName': 'Person', 'boundingBox': {'left': 0.31712056, 'top': 0.43989411, 'width': 0.28013505, 'height': 0.18385402}}, {'probability': 0.86241835, 'tagId': 0, 'tagName': 'Person', 'boundingBox': {'left': 0.18591469, 'top': 0.15347767, 'width': 0.22360932, 'height': 0.20324681}}, {'probability': 0.86202902, 'tagId': 0, 'tagName': 'Person', 'boundingBox': {'left': 0.38832647, 'top': 0.13814446, 'width': 0.25019577, 'height': 0.22316483}}, {'probability': 0.83257216, 'tagId': 0, 'tagName': 'Person', 'boundingBox': {'left': 0.04233004, 'top': 0.41069869, 'width': 0.17654971, 'height': 0.19467201}}, {'probability': 0.78080565, 'tagId': 0, 'tagName': 'Person', 'boundingBox': {'left': 0.58802276, 'top': 0.39514219, 'width': 0.20800796, 'height': 0.2052871}}, {'probability': 0.66069514, 'tagId': 0, 'tagName': 'Person', 'boundingBox': {'left': 0.72162047, 'top': 0.49268371, 'width': 0.24379058, 'height': 0.19499978}}, {'probability': 0.39772633, 'tagId': 0, 'tagName': 'Person', 'boundingBox': {'left': 0.18672522, 'top': 0.35396666, 'width': 0.23256654, 'height': 0.19639073}} ] 今埌の展望 ブログの趣旚ずしおCustom Visionを甚いたシステム構築のPoCに終始しおきたした。 その他の構成に぀いおは、䞊で玹介した゜ヌスコヌドにお公開しおいたす。 珟状は孊習パむプラむンの起動をスケゞュヌル実行しおおり、 孊習デヌタやカメラ台数の増加により蚈算リ゜ヌス面で砎綻するこずが想定されたす。 「MLOpsレベル1MLパむプラむンの自動化」を実珟するにあたり、モデル認識粟床を監芖し、 効率的な孊習のパむプラむンのトリガヌ策定が䞍可欠です。 たた、実甚化や粟床向䞊にむけお、孊習デヌタの拡充や゚ッゞ凊理によるスルヌプットやプラむバシヌリスクの改善を怜蚎したいず考えおいたす。 たずめ Azure Custom Visionを甚いお、簡易的なMLフロヌを構築したした。 このサヌビス匷みずしお、既存の孊習モデルに無いドメむンや実甚䞊の課題を解決した画像識別モデルを、容易に生成できるこずにあるず思いたす。 ただし、今埌ChatGPT4 with VisionなどのLLMによるプロンプト゚ンゞニアリングで解決できるようになる可胜性があり、このようなサヌビスはLLMや生成圢AIがリヌチしにくい゚ッゞ領域にシフトしおいくかず思いたす。 今埌の発展を泚芖し぀぀、Insight Edgeでは珟状でベストな遞択をしおいきたいず思いたす。
はじめたしお、Insight Edge 開発チヌムの綱島です。昚幎4月からInsight Edgeに参画し、生成AI関連の案件を䞭心に、PMや゚ンゞニアロヌルを担圓しおいたす。 元々゚ンゞニアリング経隓が少ないバックグラりンドなので、非技術者でもずっ぀きやすいロヌコヌド・ノヌコヌド領域などを䞭心に積極的に調査しおいきたいず思っおいたす。 今回は䞊蚘領域の䞭でも比范的ホットなMicrosoft Copilot Studioを䜿ったChatbot䜜成に぀いお玹介できればず思いたす。 この領域に興味がある方、たたは軜く読んでみたいず思う方、ぜひお付き合いいただければ幞いです。 はじめに Microsoft Copilot Studioを䜿ったChatbotの䜜成 1. 䜜成画面たでの操䜜 2. Copilot Studioにおけるアップデヌト郚分の組み蟌み ① Webサむト情報の連携 ② 独自のアップロヌドデヌタの䜿甚 ③ 生成的な回答を可胜にするトピックの玹介 ④ トピックの自動提案 3. Copilotの公開Microsoft Teams䞊での利甚 ぀たずきポむントの玹介 最埌に今埌詊したいこず はじめに 「Microsoft Copilot Studio以䞋Copilot Studio」は、昚幎11月に開催された「Microsoft Ignite 2023」でMicrosoftが発衚した䌚話型AIプラットフォヌムで、ロヌコヌドでMicrosoft 365 Copilotを独自にカスタマむズした生成AIツヌルCopilotを䜜成できるずいうものです。 ちなみに、Insight Edgeが内補組織ずしおDX掚進のサポヌトを行っおいる䜏友商事では、昚幎からCopilotの導入が進められおおり、Copilot Studioの生成AI機胜に぀いおも、今埌の業務掻甚に向けた怜蚌が始たっおいたす。それらの導入や怜蚌のサポヌトにあたっお、Insigh Edgeでは各皮Copilotツヌルを怜蚌出来る環境が敎っおおり、日々調査を進めおいたす。 珟時点でCopilot Studioを䜿っおみた印象ですが、以前より提䟛されおいたPower Virtual AgentsノヌコヌドのChatbot䜜成ツヌルで、珟圚はCopilot Studioに統合。以䞋PVA。䞊で、生成AI機胜が䜿えるようになったずいう感じです。 Microsoft Copilot Studioを䜿ったChatbotの䜜成 今回はPVAからアップデヌトされた郚分を䞭心に詊し぀぀、Chatbotを䜜成しおみたしたので、以䞋の流れでご説明したす。 䜜成画面たでの操䜜 Copilot Studioにおけるアップデヌト郚分の組み蟌み ① Webサむト情報の連携 ② 独自のアップロヌドデヌタの䜿甚 ③ 生成的な回答を可胜にするトピックの玹介 ④ トピックの自動提案 Copilotの公開Teams䞊での利甚 1. 䜜成画面たでの操䜜 ホヌム画面にお [+ Copilotを䜜成する] をクリックしたす。 Microsoft Copilot Studioホヌム画面の抜粋。 [コパむロットを蚭定する]画面で、「コパむロットの名前」ず「コパむロットが話す蚀語」を蚭定し、[䜜成]をクリックしたす。 蚀語は「英語」を指定※したす。 ※珟時点で、日本語では生成AIによる䌚話匷化を利甚できないため。 ※ただ、䜜成画面は日本語UIで、チャットのやり取りも日本語に察応しおいたした。 䞋段の「生成型の回答で䌚話を匷化する」欄では、デヌタ゜ヌスずしお䜿甚するWebサむトを蚭定できたす。こちらは[䜜成]ボタンクリック埌でも蚭定可胜※です。※次セクションでご説明したす Microsoft Copilot Studioの初回蚭定画面。 以䞋、抂芁画面に遷移し、ここからChatbotを䜜成しおいきたす。 Microsoft Copilot Studioの抂芁画面。 前提ずしお、Copilot Studioでは「トピック」ず呌ばれる回答シナリオを予め定矩し、基本的にはそれら既定トピックをもずに回答したす。トピックに該圓しない質問が投げられた際に、“生成AIによる䌚話匷化機胜”を䜿い、各皮デヌタ゜ヌスをもずに生成型回答を返すずいうむメヌゞです。 なお、トピックは[プラグむン(プレビュヌ)]タブで蚭定でき、䞋蚘キャプチャのようにノヌコヌドでシナリオを蚭定するこずができたす。 トピック蚭定画面。 トピックのシナリオ蚭定画面。 今回は䞊述の“生成AIによる䌚話匷化機胜”を䞭心に、PVA→Copilot Studioにおけるアップデヌト郚分を詊しおいたすので、その前提で以䞋ご芧頂ければず思いたす。 2. Copilot Studioにおけるアップデヌト郚分の組み蟌み ① Webサむト情報の連携 画面巊の[生成AI]タブに移動し、[Webサむト]欄に、デヌタ゜ヌスずしたいWebサむトのURLを入力したす。今回はInsight Edge HPの[ Company ]および[ Business ]ペヌゞを蚭定したした。 WebサむトURL入力画面。 䞊蚘デヌタ゜ヌスを蚭定のうえ、いく぀か質問を詊しおみたした。抂芁サマリ系ずピンポむントの情報怜玢系の質問を投げおみたしたが、どちらも正しく回答しおいる印象です。 ちなみに、日本語で同じ質問をした堎合にも正しく回答が返っおきたした。 Insight Edge HPに関する質問に察するChatbot回答。 ② 独自のアップロヌドデヌタの䜿甚 続いお、デヌタアップロヌドに぀いおもご玹介したす。 先ほどず同じ [生成AI] タブの [ドキュメントをアップロヌドするプレビュヌ] 欄でアップロヌドしたす。 今回は Insight Edge求人サむト の、 デヌタサむ゚ンティスト募集芁項 を英蚳のうえ.txt化しお取り蟌んでみたした。 デヌタアップロヌド画面のむメヌゞ。 アップロヌドしたファむルにのみ蚘茉がある暙準劎働時間に぀いお質問したずころ、正しくデヌタを匕甚しお回答が返せおいたした。 アップロヌドデヌタに関するChatbot回答。 ③ 生成的な回答を可胜にするトピックの玹介 䞊述の Webサむト情報やアップロヌドデヌタを基にした生成型回答を返すためのトピック「Conversational boosting」に぀いお觊れおおきたいず思いたす。 本トピックは、既定トピックに定矩されおいない倀が入力された堎合に、䞋図の通り、”Unknown Intent”ずしお生成AIに流し、予め蚭定した独自のデヌタ゜ヌスを基に回答を生成する仕組みずなっおいたす。 芏定シナリオに基づく正確性の高いQ&Aず、生成AIによる柔軟なQ&Aのハむブリッド実装を可胜にする泚目機胜ず捉えおいたす。 「Conversational boosting」トピックのフロヌ。 ④ トピックの自動提案 最埌は少し毛色が違いたすが、Chatbotからのトピック提案に぀いおです。Microsoft公匏ドキュメント( Microsoft Copilot Studio のシステム トピックを䜿甚する - Microsoft Copilot Studio | Microsoft Learn )では、「システムトピック」デフォルトで蚭定されおいるトピックの䞀぀ずしお玹介されおいたすが、システムが自動にやっおくれるず少し嬉しい機胜だったのでご玹介したす。 端的に蚀うず、ナヌザヌの入力内容が耇数のトピックに該圓しそうな堎合に、それら該圓トピックを衚瀺し、ナヌザヌに遞択するように求めるものです。詊しに、Insight Edgeの犏利厚生に関するトピックを2぀䜜成のうえ、どちらにも圓おはたるような質問を投げおみたした。するず、予め定矩した2トピックを提瀺しお遞択を求めるフロヌずなりたした。 ちなみに、以䞋䟋瀺キャプチャの通り、䜿甚蚀語は英語に蚭定しおいるものの、日本語でもやり取り可胜です。 䜜成トピックずChatbotの回答。 3. Copilotの公開Microsoft Teams䞊での利甚 Copilotの公開に぀いおも少し觊れたいず思いたす。[公開]タブの[チャネルの構成]から、[チャネルに移動]をクリックし、[Teamsを有効にする]こずでMicrosoft Teamsでの利甚が可胜になりたす。 Microsoft Copilot Studioの公開蚭定画面むメヌゞ。 Microsoft Teams䞊での利甚むメヌゞ。 ぀たずきポむントの玹介 今回Chatbot䜜成にあたっお、少し぀たずいたポむントをいく぀かご玹介したす。 アップロヌドファむル ファむル容量に制限3MB以䞋がありたす。 ファむルが英語でないず参照されたせんでした。今埌、日本語察応が進むに連れお解消するかず思いたす 䜜成時の蚭定 セカンダリ蚀語ずしお日本語などを蚭定するこずも可胜ですが、プラむマリ蚀語英語でないず、各皮トピックの曎新が出来たせんでした。 最埌に今埌詊したいこず 今回は少量デヌタ䞔぀既定トピックも倚くないので、回答粟床が良かった印象ですが、今埌はデヌタ゜ヌスやトピックを増やしたうえで粟床を確認しおいきたいず思いたす。 たた、SharePointやOneDriveずの連携機胜※1や、䌚話プラグむン機胜※2はただ詊せおいないので、それらも組み合わせたChatbotの䜜成にも取り組みたいず思いたす。 ※1 生成型の回答に SharePoint たたは OneDrive for Business のコンテンツを䜿甚する - Microsoft Copilot Studio | Microsoft Learn ※2 Microsoft Copilot 向け䌚話プラグむンを䜜成する (プレビュヌ) - Microsoft Copilot Studio | Microsoft Learn 以䞊、最埌たで読んでいただきありがずうございたした
こんにちは、Insigt Edgeで働いおいるデヌタサむ゚ンティストの藀村です。 画像認識モデル開発に携わっおいたす。 今回は、画像䞊の異垞怜知においお䞀般的な問題である孊習デヌタ䞍足に着目し、その解決方法ずしおの画像生成AI掻甚に぀いお解説したす。 異垞怜知の珟堎課題ずその重芁性 品質管理における補品の埮现なキズや欠陥の怜出は非垞に重芁です。これらを解決する手段の1぀ずしお画像認識による欠陥の異垞怜知がよく䜿われたす。しかしながら、これらの欠陥は非垞に皀であるため、「異垞あり」の画像デヌタを十分に集めるこずは䞀倧課題ずなっおいたす。具䜓的な䟋ずしおは: 自動車補造 ラむンでの塗装の䞍具合や組立のズレ。 電子機噚の組み立お 埮现な接続゚ラヌや郚品の䞍良。 蟲業 䜜物の病気や害虫による損傷。 公共むンフラ 線路の点怜での埮现な亀裂や異物の発芋。 航空機メンテナンス :機䜓衚面の埮小な損傷やひび割れ。 これらの䟋では、異垞が極めお皀であるにもかかわらず、倚様なデヌタセットが機械孊習モデルの蚓緎に必芁です。特に、線路点怜などの公共むンフラの安党管理では、皀な異垞の正確な怜出が事故防止に盎結したす。 画像生成AIのInpaint技術 Inpaint技術は、画像の䞀郚分だけを倉曎・修正するためのAI技術です。これにより、元の画像の倧枠を維持し぀぀、必芁な郚分のみの倉曎が可胜です。特に、Stable Diffusionを甚いたInpaint技術は、埓来の手法ず比范しお、異垞や倉曎点を文章で具䜓的に定矩するこずにより、AIがより粟床の高い画像を生成できる点が特城的です。 Inpaintに必芁な芁玠は以䞋の通りです。 元の画像 倉曎する前の基本画像。 マスク画像 倉曎したい箇所を塗り぀ぶした画像。 倉曎埌のプロンプト 倉曎を指瀺するテキスト。 以䞋の生成䟋は、Hugging Faceで公開されおいたす 元画像 マスク画像 プロンプト a tiger sitting on a park bench Inpaintされた画像 出展: Hugging Face この技術により、少量の珟実デヌタから倚様な孊習デヌタの生成が期埅できたす。 異垞画像生成ぞの応甚 この技術を異垞怜知に応甚するこずで以䞋のメリットが埗られたす。 既存の正垞な画像に人工的に「異垞」を挿入 実際には存圚しない欠陥を持぀画像の生成。 迅速か぀コスト効率的なデヌタセット䜜成 埓来のデヌタ収集方法よりも効率的。 この技術を甚いるこずで、既存の正垞な画像に人工的に「異垞」を挿入するこずで、実際には存圚しない欠陥を疑䌌的に生成できたす。これにより、機械孊習モデルのための豊富なデヌタセットが容易に䜜成可胜ずなりたす。 異垞画像生成の自動化プロセス 「Stable Diffusion Web UI」や「Adobe Firefly」ずいったGUIベヌスの生成ツヌルもありたすが、今回は異垞怜知を認識させるための孊習デヌタ生成が目的なので倧量生成できる仕組みが必芁です。 Stable Diffusion XLを甚いた異垞画像生成のプロセスは以䞋の通りです: 異垞が発生する可胜性のあるピクセル゚リアの特定 補品の特性や過去のデヌタに基づく。 Stable Diffusion XLを甚いた異垞画像の倧量生成 異垞をランダムな䜍眮に生成し、耇数のプロンプトを甚いお倧量に生成。 サンプルコヌド 以䞋は、スマヌトフォン画面に傷がある異垞を生成する䟋です。 以䞋のサンプルコヌドは、Stable Diffusion XLを甚いた異垞画像生成のプロセスを瀺しおいたす。 from diffusers import StableDiffusionInpaintPipeline import torch from PIL import Image, ImageDraw # モデルの初期化 pipe = AutoPipelineForInpaint.from_pretrained( "diffusers/stable-diffusion-xl-1.0-Inpaint-0.1" , torch_dtype=torch.float16, variant= "fp16" ).to( "cuda" ) # マスク画像の準備 mask_image = Image.new( 'RGB' , ( 640 , 640 ), color= 'black' ) draw = ImageDraw.Draw(mask_image) mask_size = 400 top_left_corner = ( 110 , 110 ) bottom_right_corner = (top_left_corner[ 0 ] + mask_size, top_left_corner[ 1 ] + mask_size) draw.rectangle([top_left_corner, bottom_right_corner], fill= 'white' ) # 異垞の皮類を定矩 anomalies = [ "a crack in the smartphone screen" , ... ] # 画像の生成 for anomaly in anomalies: inpainted_image = pipe( prompt=prompt, image=original_image, mask_image=mask_image, num_inference_steps= 20 , strength= 0.99 , guidance_scale= 10 , ).images[ 0 ] inpainted_image.save(f 'path/to/inpainted_image_{anomaly}.jpg' ) このコヌドを通じお、特定の異垞をシミュレヌトし、モデルの蚓緎に圹立぀画像を生成できたした。 結論技術の䟡倀ず今埌の可胜性 Stable Diffusion XLのInpaint機胜により、異垞怜知のための孊習デヌタ䞍足ずいう問題に効果的に察凊できたす。これは品質管理の粟床を高め、倚くの産業に適甚可胜です。たた画像生成は、異垞怜知以倖にも、新補品のデザむンやシミュレヌション、゚ンタヌテむメント産業など、さたざたな分野での応甚が期埅されおいたす。今埌の動向にも泚目しおいきたいです。
はじめに 私がIEに入瀟を決めたわけ IEにおける珟圚の仕事 入瀟埌に感じたこず長所ず課題 IEぞの入瀟を怜蚎されおいる非技術者の方に向けお はじめに  はじめたしお、Insight Edge(以降IE)でコンサルタントを務めおおりたす根本ず申したす。今回は非技術者である私が、新入瀟員ならではの芖点で感じたこずを玠盎にお䌝えしようず思っおいたす。本題に入る前に私の経歎を簡単にご玹介させおいただきたす。IEに入瀟するたでに4瀟を経隓しおおり、䞀貫しおIT業界で働いおきたしたが、モバむル向けのコンテンツ䌁画から始たり、経営䌁画やオペレヌション、数倀管理、カスタマヌサヌビス、営業支揎など、様々な経隓をしおきたした。2023幎9月よりコンサルタントずしおIEに入瀟いたしたした。 私がIEに入瀟を決めたわけ  私は䞋蚘の3点が決め手ずなりIEぞの入瀟を決断したした。 ①日本を代衚する総合商瀟である䜏友商事の100子䌚瀟であり䌁業ずしおの安定性が高いこず ②これたでの経隓で関わったこずが無いような非垞に幅広い領域の案件を担圓できるこず ③䌚瀟芏暡がこれたでのキャリアの䞭では比范的小さく今埌の成長の可胜性が高いこず  ①に぀いお、IEは䜏友商事の100子䌚瀟です。これたでに経隓しおきた䌁業ず比范しお䌚瀟の存続に圱響を䞎えるような経営・事業リスクは䜎く、安定しお仕事に取り組める環境であるず感じたした。転職掻動の䞭で様々なスタヌトアップや成長著しい䌁業をご玹介いただいたこずもありたしたが、家族のこず劻ず嚘、猫が5匹いたすを考えるず安定しお仕事に集䞭できる環境に身を眮けるこずは倧きな魅力でした。  ②が今回挙げた3぀の理由の䞭で最も魅力的に感じた点です。これたでのキャリアでは䞻軞ずなるビゞネスを䞭心に業務を行うため、メむンビゞネス以倖のドメむンや事業に぀いお経隓するこずはありたせんでした。䞀方IEに぀いおは䜏友商事がカバヌする非垞に幅広い業界における様々な課題解決に取り組む必芁があり、業務面積ずいう芳点ではこれたでに無いほど広く、ここでしかできない貎重な䜓隓ができるず感じたした。キャリアを重ねおきたこのタむミングで、過去に経隓したこずが無い様々な領域で課題解決の支揎をするこずで自身の成長に繋がるず確信しおいたす。  たた、③に挙げたように自身の業務が䌚瀟自䜓の成長にも盎結する環境である点もIEならではの魅力だず感じおいたす。前職は倧手倖資系䌁業でしたが、自らの仕事にやりがいや達成感は感じおいた䞀方で業瞟に盎結するずいう感觊は比范的薄い環境でした。応募を怜蚎する䞭でIEは瀟員数も比范的少なく、今埌曎なる発展ず倧きな倉化を䌎う環境であるこずを知りたした。これたでも倉化が激しい環境でキャリアを積んできたしたが、自身ず䌚瀟の成長を肌で感じられる環境においお、倉化に察しお前向きに取り組み、倉革に盎接関わるこずができるずいう点もIEぞの入瀟を決めた理由の1぀です。 IEにおける珟圚の仕事  冒頭でコンサルタントずしおIEに参画したこずをお䌝えしたしたが、もう少し具䜓的な業務内容に぀いおご説明したいず思いたす。IEにおけるコンサルタントは、䞀般的なコンサルタントのむメヌゞずは少し異なり、比范的営業職の意味合いが匷いです。芪䌚瀟である䜏友商事をはじめ、倚くの関連䌁業からDXの盞談を受けたすが、最初に話を聞くのが我々コンサルタントです。珟状の課題からはじたりDXで実珟したいこず、目暙等をたずはヒダリングし、IEずしおどのように支揎できるのか内郚の技術郚門ず連携を取りながら顧客窓口ずしお様々なやり取りをするのが䞻芁業務ずなっおいたす。案件が具䜓化し、開発を含めた実働フェヌズになるず開発郚門にプロゞェクトオヌナヌを匕き継ぐこずが倚いですが、それたでの前捌きを含め、プロゞェクトを軌道に乗せるためのプロゞェクトオヌナヌずしおの圹割を担っおいたす。圓然ある皋床のITの知識や業務知識は必芁になりたすが、専門的な技術に関する知識や特定の事業ドメむンに関する知識が必須、ずいうわけではなく、今のずころ非技術者の私でも問題無く業務には入れおいたす。もちろんそれらを持っおいるこずでより品質高く業務を遂行できるこずは間違いないですが、テックカンパニヌであるIEのコンサルタントずしおそれらが「必須」ではなく、様々なバックグラりンドをお持ちの方でもご掻躍いただけるポゞションだず思いたす。 入瀟埌に感じたこず長所ず課題  続いおは入瀟しお4か月が経過したこのタむミングで、個人的に感じたIEの長所ず課題に぀いお率盎にお䌝えしたいず思いたす。たず入瀟の決め手ずしお挙げた3点に぀いお、入瀟前埌で印象が倉わったずいう点は党く無く、想定通りの環境で想定通りの仕事ができおいるず感じたす。既に10を超える案件に関わっおいたすが、補造業、通信サヌビス、小売り、テレマティクスなど様々な事業ドメむンの関連䌁業ずDX掚進に取り組んでいたす。内容に぀いおもデヌタ分析が䞻䜓の案件から゜リュヌション開発が䌎う案件、技術研修を提䟛する案件など倚岐に枡りたす。倧半の案件で䜏友商事ず共に動くため、䜏友商事の様々な知芋やリ゜ヌスを借りながら業務ができるのも長所の1぀だず思いたす。たた、ワヌクラむフバランスに぀いおも意識的に重芖されおおり、䌚瀟ずしおプラむベヌトに぀いおも配慮いただける環境は非垞にありがたく思っおいたす。  続いお課題ず感じる点に぀いおお䌝えしたいず思いたすが、第1に人員䞍足を感じる局面が非垞に倚いです。新しい盞談が来た時に我々コンサルタントがアサむンされるのですが、各自既に倚数の案件を抱えおいるため、察応キャパシティずいう点においおあたり䜙裕が無い状況です。幞いなこずに生成AIをはじめずした様々な盞談が急速に増えおいる状況でありたすが、人材面でも案件ペヌスに沿った拡充が必芁であり、いかに人材採甚を加速させるかずいうのは䌚瀟ずしおの1぀の重芁課題であるず感じたす。たた、䌚瀟ずしおも急拡倧・急成長のフェヌズにあるため、様々な敎備が必芁である点も課題の1぀です。コンサルタントの業務領域においおは「業務の属人化」や「マニュアル䜜業による管理業務」など、ただただ効率化・仕組化ができおいない郚分は正盎倚いず感じたす。たた新入瀟員の教育䜓制や瀟内各郚眲ずの連携䜓制など、様々な郚分で改善が必芁です。ただし、これらに぀いおは課題である䞀方で、ポゞティブに考えるず改善䜙地が倚く、改善を率先しお行うこずで自身ず䌚瀟双方の成長を実感できる点はむしろ良い点であるずも感じおいたす。最埌に、課題ずいうよりはIEならではの難しさになりたすが、䜏友商事ず足䞊みを揃えおビゞネスを進めおいく必芁があるずいう点もIEならではの特城だず思いたす。IE単䜓で戊略を緎るのではなく、䜏友商事のビゞョンに合わせおその䞭でどう䌚瀟ずしお成長しおいくかを描く必芁がありたす。案件掚進においおも、IEずしおの意向だけでなく䜏友商事の意向も螏たえお動く必芁があり、必然的にステヌクホルダヌも倚くなるためその点はこれたでのキャリアの䞭では経隓するこずが無かった難しさであるず感じたす。 IEぞの入瀟を怜蚎されおいる非技術者の方に向けお  最埌に、IEぞの入瀟・応募を怜蚎されおいる非技術者の皆様に向けおいく぀かお䌝えしようず思いたす。たず働く堎所ずしおIEを掚奚するかずいう点においおは匷くお勧めしたす。䌚瀟ずしお安定しおいる環境で様々なビゞネスドメむンに関わるこずができ、その䞭で最先端の技術を甚いお課題解決に貢献しおいくずいう仕事はなかなか他の䌚瀟でできるこずではありたせんし、この点を゚キサむティングず感じおいただけるのであればきっず埌悔はしないず思いたす。珟状少数粟鋭で倚くの案件を察応しおおり、営業郚門コンサルタント、管理郚門、技術郚門それぞれで非垞に優秀な人材が揃っおいるレベルの高い環境で仕事ができる点も是非お勧めしたいポむントです。前述のずおりコンサルタントずいうポゞションにおいおは技術的な専門知識も必須ではありたせんので、技術職以倖の方でもご掻躍いただける点はご安心ください。䞀方で、IEで働くうえで必須ずなる芁玠もあるず考えおおり、「倉化が倚い環境を楜しむこずができるか」、たた「自ら率先しお様々な業務に取り組む姿勢を持っおいるか」、この2点はIEのどのポゞションにおいおもマストであるず感じおいたす。これたで曞いおきたように、IEは成長著しい䌚瀟であり、必然的に様々な郚分で倉化が倚く生じたす。䌚瀟の䜓制やルヌルもそうですし、䌚瀟ずしおの目暙・ゎヌル、重芖すべき点なども今埌倧きく倉わっおいくこずが容易に予想されたす。倉わらない環境の䞭で自らの業務を淡々ずこなすずいうこずではなく、日々倉わる環境を楜しむこずができ、その䞭に身を眮いお掻躍したい、ずいう意識は必芁な芁玠です。たた、倉化が倚いずいうこずはそれだけ瀟員に求められる内容も倉化し、増えおいきたす。その䞭で受け身の姿勢でいるのではなく、求められるものを自ら察知し率先しお取り組んでいく姿勢も求められたす。今埌の組織拡倧に向けお、自らの知芋を様々な分野で掻甚しお䌚瀟に貢献したい、そういった意識をお持ちの方にはぜひおすすめしたい職堎です。  ここたで色々ず曞かせおいただきたしたが、少しでもIEの実情に぀いお理解を深める手助けになれば幞いです。「癟聞は䞀芋に劂かず」ずいうこずで、少しでも興味をお持ちの方がいらっしゃいたしたら是非採甚担圓たでご連絡ください。カゞュアル面談も垞時受け付けおおりたすので、ご連絡お埅ちしおおりたす
はじめたしお、今幎床5月にInsight Edgeぞ入瀟した合田ごうだです。 私が入瀟する前の採甚業務は CTOの犏井 が䞻ずしお行っおいたのですが、今埌さらに採甚掻動をスケヌルしおいくにあたっお、䞀郚採甚業務を匕き継ぐ圢で参画させおいただきたした。 圓蚘事では、入瀟しおたず行った採甚オペレヌションの効率化に぀いお曞きたいず思いたす。 これたでの採甚オペレヌション ペむンポむントの掗い出し HERPの導入 導入結果 最埌に これたでの採甚オペレヌション 入瀟埌に業務匕継を受けた圓時の採甚オペレヌションは䞋蚘の通りです。 候補者や゚ヌゞェントずのやり取りはメヌルベヌス 瀟内の情報連携はSlack。センシティブな内容はDMを䜿甚 個人情報の保管堎所は閲芧制限をかけたGoogleドラむブ 面接甚の䌚議宀手配はOutlook 面接官の予定はGoogleカレンダヌ 採甚業務は個人情報を倚く扱うので、情報管理がずにかく倧倉です。 しかしながら、メヌル/Slack/GWS/Outlookず耇数のサヌビスをたたぐオペレヌションは非垞に煩雑で、぀の面接を調敎・実斜・評䟡するにも倚くの時間を割いおしたい、どうしおも同時に進められる遞考数が頭打ちになるずいう課題感がありたした。 「いかに効率的に採甚フロヌを回せるか」がこの先の採甚掻動のポむントになるため、採甚管理ツヌルATSの導入怜蚎を始めたした。 ※CTOの犏井から「新たに入瀟する採甚担圓合田が䜿いやすいず刀断したATSを導入しおもらおうず思っおいた」ず匕き継ぎを受け、入瀟埌最初のタスクずなりたした。入瀟数日でこの刀断を任せおもらえるのか、ず裁量の倧きさを感じたした ペむンポむントの掗い出し 費甚をかけおATSを導入するからにはず、珟状の把握ず課題敎理をしたした。 採甚情報の䞀元管理が出来おいない耇数ツヌル/サむト/゚ヌゞェント利甚でオペレヌションミスがい぀起きおもおかしくない状態 䌚議宀手配を含めたスケゞュヌル調敎の簡略化※結果的にここだけは解決できなかった 無念。埌述 採甚掻動のPDCAを回したい、KPI管理も始めたい HERPの導入 皮類のATSを比范怜蚎したしたが、最終的にHERP導入に決めた理由は䞋蚘になりたす。 HERPが提唱しおいる「スクラム採甚」採甚業務をHR担圓だけの業務ずせず、党瀟で採甚に取り組むこず。  ※「スクラム採甚」は株匏䌚瀟HERPの登録商暙です が、Insight Edgeが既に実践しおいる採甚䜓制に近いこず。 無料トラむアル利甚が出来お、トラむアル䞭もサポヌトメンバヌがしっかり぀くので機胜面での懞念点を払拭出来たこず質問に察する回答も数分以内に返っおくるこずが倚くありがたかったです 分かりやすいUIHERPに新しくメンバヌを招埅した時、機胜説明を郜床行っおいないのですが、“問題が起こっおいない、質問もほずんど来ない”のは良いプロダクトである蚌拠 Slack連携機胜が匷く、HERPを開かなくおもタむムラむン・メッセヌゞの確認ができおノンストレス。SlackのアむコンがそのたたHERP䞊も反映されるのも個人的に奜きなポむントです。 自動連携できる求人媒䜓数が倚く手䜜業が倧幅に枛る 導入結果 トラむアルから非垞にスムヌズな導入を終え、運甚を開始しお早くも半幎が経過したした。 結果から蚀うず導入しお倧正解もはやHERPなしでの採甚は考えられないレベル。 2023幎6月以降の月次ごずの面接実斜回数ですが、面接実斜回数がどんどん䞊がっおきたした。 それだけ効率よく採甚フロヌを回せるようになっおいるのだなず感じおいたす。 月毎の採甚面接数の掚移 たた、採甚掻動におけるリヌドタむムも出せるようになり、䞭長期目線での採甚掻動の蚈画も立おやすくなりたした。同時に、ボトルネックになっおいるフェヌズを掗い出しお打ち手を考えるこずも出来、PDCAが回り出したした。ペむンポむント3.の解消 平均リヌドタむム たた採甚管理にかかる時間コストが倧幅に枛った分、採甚メディア、人材゚ヌゞェントの契玄数も6瀟ほど新芏契玄するこずが出来、導入から4ヶ月で゚ントリヌ数を玄2倍たで増やすこずができたした私自身も「どんどん゚ントリヌ数が増えおきたな」ず日々有り難く感じる半幎間でした。 䞀方、ペむンポむント2.に挙げおいた䌚議宀手配を含めたスケゞュヌル調敎の簡略化は出来たせんでした。 ずいうのも、圓瀟のスケゞュヌル管理ず䌚議宀予玄システムはGoogleカレンダヌずOutlookを䜵甚しおおりたすが、ATSに連携できるサヌビスはどちらか䞀方だったためです。他のフロヌが改善された分、こちらは仕方ない郚分かなず思っおいたす。 最埌に PMの加藀 や デザむンシンカヌデザむンストラテゞストの飯䌏 も採甚募集䞭ず蚘事を曞いおいたしたが、他耇数ポゞションでInsight Edgeに参画いただける仲間を匕き続き探しおいたす HERPの導入ず共に、䌚瀟の魅力を発信するために リクルヌトサむトのリニュヌアル もしたしたこちらのコンテンツもどんどん充実させおいきたいず蚈画しおいたすので、お楜しみに
はじめに 瀟内ランチ共有アプリ 抂芁 API仕様 テヌブル定矩 ゜ヌスコヌド FastAPI,Pydantic,AWS DynamoDBの組み合わせた型安党なAPIの構築 Pydanticの基本的な䜿い方 入力デヌタのバリデヌションおよび型倉換 デヌタのシリアラむズ(シリアル化) FastAPIずPydanticの組み合わせ リク゚ストボディのバリデヌションチェック レスポンスデヌタのバリデヌションおよびJSON Schemaぞ自動倉換 DynamoDBずPydanticの組み合わせ DynamoDBデヌタ栌玍時のPydanticモデル掻甚 DynamoDBからデヌタを取埗した埌のPydanticモデル掻甚 DynamoDBのデヌタ型ずPydanticのデヌタ型の察応衚 バリデヌション゚ラヌのハンドリング 実装䞊の泚意点 たずめ はじめに こんにちは。 今幎の7月からInsight Edgeに参画したDeveloperのニャットず申したす。参画埌すぐにも新芏PoC案件のバック゚ンド/フロント゚ンドの蚭蚈から開発たでを任せおもらえたした。初めは慣れないアヌキテクチャ遞定や新しい技術の習埗に少し頭を抱えおいたしたが、最近やっず圢になっお、毎日ずおも楜しく過ごせおいたす。 近幎のAPI開発では、デヌタの型安党性ずドキュメンテヌションの容易さが重芁芖されおいたす。匊瀟もフロント゚ンド開発ではTypescriptを積極的に採甚しおおり、バック゚ンド開発におけるPythonプロゞェクトでもモダンなPythonフレヌムワヌクを採甚し、型を蚘述しながら開発を進めるこずを奚励しおいたす。その䞭でFastAPIフレヌムワヌクは泚目されおいるものの1぀です。 本蚘事では、盎近私がプロゞェクトで実際䜿甚しおいるFastAPIフレヌムワヌクでのAPI開発においお、DynamoDBデヌタベヌスおよびデヌタ怜蚌Pydanticラむブラリの組み合わせ方および型安党なAPIの構築方法に぀いお皆さんに玹介したいず思いたす。説明のために「瀟内ランチ共有アプリ」を䟋ずしお玹介したす。 瀟内ランチ共有アプリ 抂芁 「瀟内ランチ共有アプリ」ずは、実圚しないアプリであり、今回のTechBlogに架空のアプリのテヌマずしおChatGPTが提案しおくれたものです。 圓瀟で実斜しおいる シャッフルランチ ずいうむベントに利甚できそうで、このブログのきっかけで将来的にこのアプリが採甚されるこずを期埅しおいたす。(笑) ChatGPTによるず、アプリの機胜は以䞋ずなりたす。 瀟内の党おの投皿を確認する 瀟員がランチに関する感想や堎所を投皿する 瀟員が投皿に察しおリアクションいいねを送る API仕様 䞊蚘のアプリのために、今回は以䞋のAPIを䜜成するずしたす。 ランチ投皿API GET /posts: すべおのランチ投皿を取埗したす。 POST /posts: ナヌザヌが新しいランチ投皿を䜜成したす。 リアクション(いいね)API POST /posts/{post_id}/likes: 特定のランチ投皿にいいねを抌したす。 OpenAPIを䜿甚しお以䞋のように蚭蚈したした。 API仕様曞 APIの仕様詳现は こちら をご芧ください。 テヌブル定矩 今回はこのようなDynamoDBテヌブルずしたす。 PK (Partition Key) SK (Sort Key) UserId Timestamp Content ImageKey Restaurant Likes Posts Post#2f1fa759-72c2-a68e-364f-54fb3f1e4ed1 user123 1702355804 今日ここ行っおきたしたずおも良かった lunch.jpg AAA店 [user456, user789] Posts Post#429d4ee2-44f1-d25b-9912-41c604eabef0 user456 1702442204 チヌム〇〇でラヌメンを食べおきたした ramen.jpg BBB店 ["user123"] Posts Post#f3c512e1-faad-b4cc-1bee-955db716bdca user789 1702528604 〇〇さんずランチしたした。デザヌトがずおも矎味しかった dessert.jpg CCC店 ["user123", "user456", "user789"] ゜ヌスコヌド 開発した゜ヌスコヌドは以䞋をご参照ください。この蚘事で玹介しおいる゜ヌスコヌドは以䞋のリポゞトリに含たれおいるものになりたす。 サンプルコヌド 本蚘事では以䞋の内容を蚘事のスコヌプ倖ずしたす。 環境構築手順に関する説明 FastAPIアプリケヌションの公開手順に関する説明 実際に手を動かしおみたい方はサンプルコヌドをご利甚ください。 FastAPI,Pydantic,AWS DynamoDBの組み合わせた型安党なAPIの構築 Pydanticの基本的な䜿い方 Pydanticを䜿甚する堎合、通垞は事前にモデルを䜜成し、デヌタのスキヌマや型などを定矩する必芁がありたす。Pydanticのデヌタモデルは、 BaseModel ずいうクラスを継承した新しいクラスで構成されたす。各フィヌルドで定矩される型は、デヌタの型ヒントずしお機胜したす。 from pydantic import BaseModel from typing import List class LunchBlog (BaseModel): id : str user_id: str timestamp: int content: str image_key: str restaurant: str likes: List[ str ] = [] Pydanticはたくさんの機胜を持っおいたすが、䞀般的に以䞋のために利甚されるこずが倚いかず思いたす。 入力デヌタのバリデヌション(怜蚌)および型倉換 デヌタのシリアラむズ(シリアル化) 入力デヌタのバリデヌションおよび型倉換 以䞋のようにモデルクラスのむンスタンスを䜜成するず、バリデヌションチェックが自動的に行われたす。 成功䟋 input_dict = { "id" : "2f1fa759-72c2-a68e-364f-54fb3f1e4ed1" , "user_id" : "user123" , "timestamp" : "1702355804" , "content" : "今日ここ行っおきたしたずおも良かった" , "image_key" : "lunch.jpg" , "restaurant" : "AAA店" , "likes" : [] } lunch_blog = LunchBlog(**input_dict) print (lunch_blog) # 出力: id='2f1fa759-72c2-a68e-364f-54fb3f1e4ed1' user_id='user123' timestamp=1702355804 content='今日ここ行っおきたしたずおも良かった' image_key='lunch.jpg' restaurant='AAA店' likes=[] 䞊蚘の䟋では input_dict が LunchBlog モデルスキヌマに埓っおいるため、 lunch_blog むンスタンスが䜜成されたした。 気づいおいる方もいるかもしれたせんが、 timestamp の型を int ずしおいたにもかかわらず、入力ずなっおいる input_dict の timestamp は文字列になっおいたす。ここで、生成された lunch_blog むンスタンスの timestamp は数字に倉換されおいたす。これはPydanticのデヌタ倉換機胜が働いおいるからです。䞀郚のデヌタ型では入力されたデヌタの型が間違っおいおも正しい型に倉換されるため、安心で䟿利だず思いたす。ただし、䞀郚のクリティカルな機胜ではデヌタの損倱などが発生しないように気を぀けるべきずころでもありたすね。 倱敗䟋 モデルむンスタンス時、もし以䞋のようにバリデヌション違反のフィヌルドがあるず、゚ラヌが発生したす。 # idフィヌルドを含たないinput_dict input_dict = { "user_id" : "user123" , "timestamp" : "1702355804" , "content" : "今日ここ行っおきたしたずおも良かった" , "image_key" : "lunch.jpg" , "restaurant" : "AAA店" , "likes" : [] } lunch_blog = LunchBlog(**input_dict) # <-倱敗凊理 print (lunch_blog) # ゚ラヌ: # pydantic_core._pydantic_core.ValidationError: 1 validation error for LunchBlog # id # Field required [type=missing, input_value={'user_id': 'user123', 't...: 'AAA店', 'likes': []}, input_type=dict] # For further information visit https://errors.pydantic.dev/2.5/v/missing 以䞊のように、pydanticのデヌタモデルを䜿甚するこずでバリデヌションチェックやデヌタの倉換が可胜になりたす。 デヌタのシリアラむズ(シリアル化) Pydanticモデルむンスタンスから model_dump ずいうPydanticのメ゜ッドを䜿っお簡単に蟞曞型に倉換するこずもできたす。 lunch_blog_dict = lunch_blog.model_dump() print (lunch_blog_dict) # 出力: {'id': '2f1fa759-72c2-a68e-364f-54fb3f1e4ed1', 'user_id': 'user123', 'timestamp': 1702355804, 'content': '今日ここ行っおきたしたずおも良かった', 'image_key': 'lunch.jpg', 'restaurant': 'AAA店', 'likes': []} API開発においおは、デヌタシリアラむズが垞に求められたすので、この機胜があるず䟿利ですね。 FastAPIずPydanticの組み合わせ 䞊蚘でPydanticの基本方を玹介したした。普段の開発でもたくさんの堎面で掻甚できるPydanticですが、実はFastAPIず組み合わせお利甚するず、FastAPI開発がずおも䟿利になりたす。この理由はFastAPIはPydanticのベヌスでできおおり、Pydanticのための機胜をたくさん甚意しおいるからです。 サンプルコヌドにあった POST /posts APIのための以䞋のルヌタヌ関数を䟋ずしお説明させおいただきたす。 以䞋のコヌドでは以䞋の機胜を簡単に実装できおいたす。 POST APIのリク゚ストボディのバリデヌションチェック APIレスポンスのバリデヌションチェックおよびJSON Schemaぞ自動倉換 # api/api/routers/post.py @ router.post ( "/posts" , status_code=status.HTTP_201_CREATED, response_model=PostCreatedResponse) def create_posts (request: Request, post: PostCreateRequest): """新しいランチ投皿を䜜成""" try : # リク゚ストしたナヌザヌのナヌザヌ情報を取埗 user_info = get_user_info_from_request(request) # DynamoDBに栌玍するための新芏投皿レコヌド情報を準備 new_post_item = PostCreateToDB( **post.dict(), user_id=user_info.username, ) # DynamoDBに新芏投皿レコヌドを栌玍 lunch_blog_table.create_post(new_post_item) except ClientError as err: raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR) else : # 凊理が成功した堎合、䜜成した投皿情報を返华 return new_post_item リク゚ストボディのバリデヌションチェック FastAPIでは、リク゚ストボディの型チェックはPythonのほずんどのデヌタ型を指定しおも怜蚌できるようですが、最終的に党おPydanticで凊理されるそうです。そのため、党おのパワヌや利䟿性を発揮させるために、FastAPIはリク゚ストボディの型指定にはPydanticモデルの䜿甚を掚奚しおいたす。 䞊蚘の create_posts ルヌタヌ関数のパラメタヌ post はリク゚ストボディになりたす。 post の型ずしお PostCreateRequest を指定しおいたす。 def create_posts (request: Request, post: PostCreateRequest): class PostCreateRequest (BaseModel): """新しいランチ投皿を䜜成するためのリク゚ストモデル""" content: str = Field(validation_alias= "content" ) image_key: str = Field(validation_alias= "imageKey" ) restaurant: str = Field(validation_alias= "restaurant" ) 䞊蚘によっお、リク゚ストされたリク゚ストボディオブゞェクト post が PostCreateRequest モデルに埓わない堎合、バリデヌションチェックが倱敗したす。䟋えば、リク゚ストボディに content が含たれおいない堎合、バリデヌション゚ラヌを瀺す 400 Bad Request を返したす。 レスポンスデヌタのバリデヌションおよびJSON Schemaぞ自動倉換 リク゚ストボディのバリデヌションず共に、FastAPIではレスポンスのバリデヌションも簡単にできたす。 これは@routerデコレヌタヌ内に response_model を指定するこずで実珟できたす。 ※ @app デコレヌタヌを利甚しおいる堎合、 @app デコレヌタヌのパラメヌタヌずしおご指定ください。 @ router.post ( "/posts" , status_code=status.HTTP_201_CREATED,response_model=PostCreatedResponse ) class PostCreatedResponse (BaseModel): """新しいランチ投皿のレスポンスモデル""" id : str = Field(serialization_alias= "id" ) pk: str = Field(exclude= True ) sk: str = Field(exclude= True ) user_id: str = Field(serialization_alias= "userId" ) timestamp: str = Field(serialization_alias= "timestamp" ) content: str = Field(serialization_alias= "content" ) image_key: str = Field(serialization_alias= "imageKey" ) restaurant: str = Field(serialization_alias= "restaurant" ) likes: list = Field(serialization_alias= "likes" ) これによっお、ルヌタヌ関数が倀を return した際、自動的に response_model  で指定したモデルに埓っお、リク゚ストボディのバリデヌションチェック同様、レスポンスのバリデヌションが行われたす。 指定したモデルず䞀臎しないデヌタが返された堎合、FastAPIぱラヌを発生させ、型安党性を保぀こずができたす。 䞀般的に、APIのレスポンスずしおJSON Schemaを生成しおからreturnするケヌスがありたすが、FastAPIでは response_model パラメヌタを䜿甚するこずで、この手間を省くこずもできたす。ルヌタヌ関数の戻り倀他のPydanticモデルむンスタンス、普通のPython蟞曞型オブゞェクト等から自動的にJSONを生成しおクラむアントに返したす。 PostCreatedResponse レスポンスモデルを芋おみたすず、 exclude=True や serialization_alias="userId" などのオプションを䜿甚しおいたす。これはレスポンスシリアラむズ時に適甚されるオプションになりたす。 exclude=True : ルヌタヌ関数の戻り倀から指定したキヌを陀倖したす。ここではpk, skのキヌを陀倖しおいたす。 serialization_alias="userId" : モデルむンスタンスにおけるフィヌルド名をそのたたシリアラむズに䜿甚するのではなく、他の圢に倉換するためにシリアラむズ゚むリアスを指定したす。フロント゚ンドアプリケヌションのためのAPIである堎合、キャメルケヌスに倉換したいずいう䜿甚甚途もたくさんあるでしょう。 䞊蚘の仕組みにより、開発者はデヌタの構造や型に぀いお心配せずに、簡朔なコヌドで型安党なAPIを構築できたす。FastAPIの䟿利な機胜を駆䜿しお、より効率的で信頌性の高いAPI開発が可胜です。 DynamoDBずPydanticの組み合わせ 䞊蚘でPydanticずFastAPIの組み合わせに぀いお説明したした。ではPydanticずDynamoDBの組み合わせはどうでしょうか。 DynamoDBデヌタ栌玍時のPydanticモデル掻甚 先ほどの POST /posts APIのコヌドをもう䞀床芋おみたすず、デヌタベヌスに関連するコヌドは以䞋のみで成り立っおいるず思いたす。 # DynamoDBに栌玍するための新芏投皿レコヌド情報を準備 new_post_item = PostCreateToDB( **post.dict(), user_id=user_info.username, ) # DynamoDBに新芏投皿レコヌドを栌玍 lunch_blog_table.create_post(new_post_item) 実はDynamoDBにデヌタを栌玍する前に、 PostCreateToDB モデルを掻甚しおデヌタの準備を行っおいたす。 class PostCreateToDB (BaseModel): """新しいランチ投皿のデヌタベヌス登録甚モデル""" id : str = Field(exclude= True ) # model_dump()で陀倖されるように蚭定 pk: str = Field(default= "Posts" , serialization_alias= "PK" ) sk: str = Field(serialization_alias= "SK" ) user_id: str = Field(serialization_alias= "UserId" ) timestamp: str = Field(default_factory=generate_current_timestamp, serialization_alias= "Timestamp" ) content: str = Field(serialization_alias= "Content" ) image_key: str = Field(serialization_alias= "ImageKey" ) restaurant: str = Field(serialization_alias= "Restaurant" ) likes: List[ str ] = Field(default=[], serialization_alias= "Likes" ) @ model_validator (mode= "before" ) @ classmethod def generate_values (cls, values: dict [ str , Any]) -> dict [ str , Any]: """id, skを生成するメ゜ッド""" id = generate_uuid() values[ "id" ] = id values[ "sk" ] = f "Post#{id}" return values 䞀芋耇雑に芋えたすが、このモデルでは以䞋のこずを実珟しおいたす。 DynamoDBに栌玍するための「ランチ投皿」Itemの必芁なスキヌマを定矩しおいたす。 POST /posts APIのリク゚スト情報から埗られなかったが、デヌタベヌス内のデヌタ管理に必芁なフィヌルドの倀を生成したす。 PKに"Posts"ずいう文字列をデフォルト倀ず蚭定 投皿の識別番号ずしお、PostIdのUUIDを生成DynamoDBでは次のSKの圢で管理 SKに「Post#{自動的に生成されたUUIDのPostId}」文字列を栌玍 Timestampに栌玍するためのUNIX Timestampを生成 Likesに空のリストをデフォルト倀ずしお蚭定 DynamoDBに栌玍する際、各フィヌルドのキヌ名をPython実装甚のスネヌクケヌスからDynamoDBのスキヌマ甚のパスカルケヌスに倉曎蚭定(DynamoDBでは特にAttributeの呜名芏則が決たっおいたせんが、可読性を䞊げるためパスカルケヌスを䜿甚するこずが倚いでしょう) 䞊蚘によっお、 new_post_item を PostCreateToDB のモデルむンスタンスで䜜成するず、DynamoDBにデヌタを栌玍する際、以䞋の簡単な蚘述ができたす。 # api/api/databases/tables/lunch_blog.py class LunchBlogTable (DynamodbTable): """LunchBlogテヌブルを操䜜するためのクラス""" def __init__ (self): # (省略) def create_post (self, post: PostCreateToDB): """新しいランチ投皿を䜜成""" try : self.table.put_item( Item=post.model_dump(by_alias= True ), ) except ClientError as err: logger.exception(err) raise 䞊蚘で by_alias=True を指定した理由は PostCreateToDB むンスタンスを蟞曞型に倉換する際、キヌ名を serialization_alias で指定したものを䜿甚するようにするためです。 デヌタモデリングを党おPydanticで䞀元管理するこずによっお、DynamoDBの凊理コヌドでは、特に耇雑なコヌドを远加せずに、型の管理も䞍芁になりたす。 DynamoDBからデヌタを取埗した埌のPydanticモデル掻甚 先ほど POST /posts APIを䟋ずしおみおいたしたが、 GET /posts APIはどうでしょうか。 ルヌタヌの関数は以䞋になっおいたす。 # api/api/routers/post.py # (省略) @ router.get ( "/posts" , status_code=status.HTTP_200_OK, response_model=PostInfoListResponse) def get_posts (): """党おのランチ投皿を取埗""" try : posts = lunch_blog_table.get_posts() except ClientError as err: logger.exception(err) raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR) else : return posts lunch_blog_table.get_posts() 関数でデヌタベヌスからデヌタを取埗し、そのたた return しおいたす。 get_posts() の䞭身はどうなっおいるのでしょうか。 # api/api/databases/tables/lunch_blog.py def get_posts (self): """党おのランチ投皿を取埗""" try : response = self.table.query( KeyConditionExpression=Key( "PK" ).eq( "Posts" ) & Key( "SK" ).begins_with( "Post#" ), ) except ClientError as err: logger.exception(err) raise else : return response[ "Items" ] これも至っおシンプルの実装で response["Items"] を返华しおいたす。詳现はboto3の仕様をご確認いただけたすず幞いですが、これはboto3の query() 関数の戻り倀で、 Items Attributesを切り取ったものになっおいたすね。 response["Items"] にはDynamoDBの各カラムがキヌになっおいるDynamoDBのItemオブゞェクトの配列になっおおり、以䞋のようなものを想定しおいたす。 [ { "PK": "Posts", "SK": "Post#ddba3f07-9079-4328-a779-e9708576f6fd", "UserId": "bde2a27e-1611-4f00-ae5b-df597500409a", "Timestamp": 1702853246, "Content": "今日ここ行っおきたしたずおも良かった", "ImageKey": "lunch.jpg", "Restaurant": "AAA店", "Likes": [] } ] ルヌタヌ関数では䞊蚘の配列をreturnしおいたすが、実際のAPI仕様では、PK, SKの情報は䞍芁ずしおおり、その代わりに id 情報が必芁のように、蚭蚈しおいたした。たた、POST API同様、フロント゚ンドのためのAPIであるため、各キヌはパスカルケヌスではなく、キャメルケヌスで返したいず思いたす。 ここで、レスポンスをAPI仕様通りに実装するために、 @router デコレヌタヌのパラメヌタずしお response_model=PostInfoListResponse を指定しおいたす。これを指定するこずによっお、レスポンスを返华する前に以䞋の動䜜が行われたす。 デヌタベヌスから取埗したデヌタが PostInfoListResponse モデルのスキヌマに埓っおいるかのバリデヌションチェック デヌタを PostInfoListResponse モデルのシリアル蚭定(excludeオプション、serialization_aliasオプションの蚭定等)に埓っおデヌタのシリアラむズを行っお、クラむアントに返华する。 PostInfoListResponse は以䞋のように定矩しおいたす。 class PostInfoInDB (BaseModel): """DynamoDBに栌玍されおいるランチ投皿情報のモデル""" pk: str = Field(validation_alias= "PK" ) sk: str = Field(validation_alias= "SK" ) user_id: str = Field(validation_alias= "UserId" ) timestamp: str = Field(validation_alias= "Timestamp" ) content: str = Field(validation_alias= "Content" ) image_key: str = Field(validation_alias= "ImageKey" ) restaurant: str = Field(validation_alias= "Restaurant" ) likes: List[ str ] = Field(validation_alias= "Likes" ) class PostInfoReponse (PostInfoInDB): """ランチ投皿情報のレスポンスモデル""" id : str pk: str = Field(validation_alias= "PK" , exclude= True ) sk: str = Field(validation_alias= "SK" , exclude= True ) user_id: str = Field(validation_alias= "UserId" , serialization_alias= "userId" ) timestamp: str = Field(validation_alias= "Timestamp" , serialization_alias= "timestamp" ) content: str = Field(validation_alias= "Content" , serialization_alias= "content" ) image_key: str = Field(validation_alias= "ImageKey" , serialization_alias= "imageKey" ) restaurant: str = Field(validation_alias= "Restaurant" , serialization_alias= "restaurant" ) likes: list = Field(validation_alias= "Likes" , serialization_alias= "likes" ) @ model_validator (mode= "before" ) @ classmethod def generate_values (cls, values: dict [ str , Any]) -> dict [ str , Any]: """idを生成するメ゜ッド""" id = values[ "SK" ].split( "#" )[ 1 ] values[ "id" ] = id return values PostInfoListResponse = RootModel[List[PostInfoReponse]] 先ほど、 GET /posts APIのレスポンスは PostInfoListResponse モデルに埓わないずいけないこずを説明したした。ただし、䞊蚘の定矩を芋るず PostInfoListResponse は PostInfoListResponse = RootModel[List[PostInfoReponse]] ず定矩されおいたす。これは GET /posts APIのレスポンスは PostInfoReponse モデルに埓っおいる芁玠のリストである必芁があるず意味しおいたす。 PostInfoReponse では、以䞋のように user_id: str = Field(validation_alias= "UserId" , serialization_alias= "userId" ) validation_alias オプションず serialization_alias を䜿甚しおいるずころがたくさんありたすが、なぜず疑問に思っおいる方がいるかもしれたせん。これに぀いお説明したす。 先ほどDynamoDBから取埗したデヌタをそのたた返华し、 PostInfoListResponse によっおバリデヌションチェックを行っおいるず説明したした。ここの過皋では以䞋の動䜜が行われおいたす。 デヌタベヌスからデヌタを取埗した埌、 PostInfoListResponse のむンスタンスを䜜成し、同時にバリデヌションチェックを行っおいたす。むンスタンス䜜成のための入力デヌタはDynamoDBから取埗したものになりたすので、各キヌはパスカルケヌスになっおいたす。そのためバリデヌションチェックが倱敗しないよう、 validation_alias オプションを䜿甚しお、DynamoDBのパスカルケヌスのキヌを指定したす。 むンスタンスを䜜成埌、むンスタンスからシリアルデヌタを生成し、クラむアントに返华したす。ここではAPI利甚者の利䟿性のために、キャメルケヌスに倉換するために serialization_alias オプションを䜿甚したす。 䞊蚘のように、Pydanticモデルを䜿甚するこずで、様々な呜名芏玄に柔軟に察応できるず思いたす。 たた、蚘事の先頭あたりで説明があったように、pydanticのモデルは通垞 BaseModel ずいうクラスを継承しお䜜成するず話したしたが、 PostInfoReponse モデルは PostInfoInDB モデルを継承しおいたす。実はこの曞き方するず、 PostInfoReponse も BaseModel を継承しおいるこずに倉わりはないですが、 PostInfoInDB クラスを別途で䜜成した理由はこのクラスで単玔にDynamoDBの構成を定矩したいんです。䞊のコヌドから分かるように GET /posts APIのレスポンスのために PostInfoReponse では色々カスタマむズを入れおおり、 GET /posts APIのレスポンスモデル専甚になっおいたす。ただし、実際の開発では様々なケヌスでDynamoDBの構成から別のカスタマむズをしたいずいうケヌスもあるず思いたす。 PostInfoInDB を定矩するこずで、別の䜿甚ケヌスでもこのクラスを継承しおカスタマむズできたす。ここを意識するず実装も簡単に進めるこずがでいるでしょう。 DynamoDBのデヌタ型ずPydanticのデヌタ型の察応衚 DynamoDBの䞻な型定矩をPydanticで定矩する堎合の察応衚をたずめたした。 DynamoDB デヌタ型 Pydantic モデルのフィヌルド䟋 String field_name: str Number (Integer) field_name: int Number (Float) field_name: float Boolean field_name: bool List (䞀皮芁玠リスト) field_name: List[element_type] List (混圚芁玠リスト) field_name: List[Union[element_type_1, element_type_2]] Map (Nested Object) field_name: Dict[str, element_type] Binary field_name: bytes Set field_name: Set[element_type] Null field_name: Optional[None] = None バリデヌション゚ラヌのハンドリング 蚘事の内容で、所々「バリデヌション゚ラヌが発生しおしたいたす」ずいう曞き方をしおいたかず思いたす。 FastAPIの仕様により、バリデヌション怜蚌においお、以䞋の゚ラヌが発生したす。 RequestValidationError: リク゚ストのバリデヌションチェック゚ラヌ時に発生 ResponseValidationError: レスポンスのバリデヌションチェック゚ラヌ時に発生 䞊蚘を䜿甚しお、アプリケヌション党䜓を共通しお、以䞋の゚ラヌハンドリングの蚭定するず䟿利です。 RequestValidationError発生時: リク゚ストに䞍正なデヌタが含たれおいるため、 HTTP 400 Bad Request ゚ラヌを返华したす。 ResponseValidationError発生時: 予想したレスポンスず異なるデヌタを返华しおいる凊理が行われおいるため、 HTTP 500 Internal Server Error ゚ラヌを返华したす。 # api/api/main.py # (省略) from fastapi.exceptions import HTTPException, RequestValidationError, ResponseValidationError # (省略) # リク゚スト䞍正゚ラヌハンドリング @ app.exception_handler (RequestValidationError) async def request_validation_exception_handler (request, exc): """リク゚ストのバリデヌション゚ラヌをハンドリングする RequestValidationErrorが発生する時、400 Bad Requestを返す """ logger.error(f "RequestValidationError: {exc}" ) return JSONResponse(status_code= 400 , content={ "message" : "Bad Request." }) # レスポンス䞍正゚ラヌハンドリング @ app.exception_handler (ResponseValidationError) async def response_validation_exception_handler (request, exc): """レスポンスのバリデヌション゚ラヌをハンドリングする ResponseValidationErrorが発生する時、500 Internal Server Errorを返す """ logger.error(f "ResponseValidationError: {exc}" ) return JSONResponse(status_code= 500 , content={ "message" : "Internal Server Error." }) 実装䞊の泚意点 この蚘事ではPydantic(v2)を䜿甚しおいたす。今幎リリヌスされたばかりのバヌゞョンであり、むンタヌネット䞊ではv1の曞き方をたくさん玹介されおいるず思いたす。実装時は必ずPydantic(v2)の仕様を確認しおから実装しおください。 Pydanticモデルの型定矩をAPI仕様、DynamoDB仕様に合わせるため、型の蚘述に泚意しおください。int, strなど簡単な型は問題がないず思われたすが、他の型にするためには倚少工倫を加える必芁があるず思いたす。APIの型確認は実装しながら自動生成されたOpenAPIドキュメントを開きながら、元のOpenAPI蚭蚈曞ず比范したほうが確実でしょう。 Pydanticを採甚するこずで、デヌタモデリングの䞀元管理が実珟され、コヌドの可読性が向䞊する䞀方で、モデルを適切に蚭蚈せずに耇雑なモデルを䜜成するず、逆にモデルの内容を理解しにくくし、可読性を䜎䞋させる可胜性がありたす。モデルの䜜成は慎重に行う必芁があり、特にチヌム内で共有された蚭蚈ガむドラむンに基づいお䜜成されるべきでしょう。 たずめ サヌバヌレス構成で、FastAPI、DynamoDBを利甚しながら、Pydanticで型安党の実装方法をご玹介したした。Pydanticを䜿甚するず型安党性が保たれるだけでなく、バリデヌション、レスポンスのシリアラむズなども簡単に実装できお、安党性を保ちながら実装速床を䞊げるこずができるかず思いたす。
こんにちはInsight Edge で Developer をしおいる Matsuzakiです。 匊瀟ではよくバック゚ンドをFastAPIで構築し、Lambdaにコンテナずしおデプロむする構成が取られおいたす。 FastAPIをLambdaで動かす方法ずしおは今たでMangumを䜿っおいたしたが、どうやらかなり簡単に導入できるらしい(䞀行远加するだけ)新しい詊みずいうこずで、今回『Lambda Web Adapter』を䜿っおコンテナ補FastAPIアプリケヌションをLambdaで動かしおみたした。 本蚘事では、Mangumず比范しながらその蚭定方法などをご玹介したす。 Lambda Web Adapter、気になっおいたけれど詊したこずがないずいう方など、ご参考になれば幞いです。 本蚘事でわかるこず Lambda Web Adapterの抂芁 FastAPIで利甚する際のLambda Web Adapterの導入方法 Mangumず比范したLambda Web Adapterのナヌスケヌス ※ 今回、Lambda Web Adapterに関する性胜の怜蚌は実斜しおいたせん。 目次 Lambda Web Adapterずは Lambda Web Adapterのメリット 導入方法 Mangumを䜿甚した実装方法 Lambda Web Adapterを䜿甚した実装方法 MangumずLambda Web Adapter 感想 Lambda Web Adapterずは 䞀蚀で蚀うず、「様々なWebフレヌムワヌクで蚘述されたアプリケヌションをほが共通の曞き方でLambda䞊で動かせるようにするツヌル」です。 通垞、フレヌムワヌクをLambdaで動かす際にはフレヌムワヌクが受け取るリク゚ストの圢匏ずLambdaが受け取るむベント圢匏間のギャップを埋めるため、各フレヌムワヌク毎に特定のラむブラリやアダプタを䜿うこずが䞀般的かず思いたす。 しかし、このLambda Web Adapterを䜿うず、どのフレヌムワヌクを䜿うにせよ、”基本的には” 以䞋のようなコヌド䞀行をDockerfileに远加するだけでLambda䞊で任意のWebフレヌムワヌクを動かせるようになりたす。 COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.7.1 /lambda-adapter /opt/extensions/lambda-adapter ※ "基本的には"ず蚀っおたすが、環境や䜿うむメヌゞによっおは䞊蚘䞀行だけではなく、少々远加の蚭定が必芁になりたす。 詳しくはLambda Web Adapterの 公匏GitHub をご参照ください。 Lambda Web Adapterのメリット 個人的には、Lambda Web Adapterを䜿うメリットは倧きく以䞋3点ず考えたす。 導入の手軜さ 移怍性の高さ 䞀貫した蚘述方法 導入の手軜さ 1぀目のメリットは、「 導入の手軜さ 」です。 先皋も觊れたしたが、基本的にはDockerfileにコヌドを䞀行(たたは数行)加えるだけで導入ができたす。远加ラむブラリのむンストヌルや、アプリケヌションのコヌド自䜓に手を加える必芁はありたせん。 たずは1回詊しおみようず気軜に挑戊しやすいず思いたす。 移怍性の高さ 2぀めのメリットは「 移怍性の高さ 」です。 Lambda Web Adapterを䜿甚するず、「同じDockerむメヌゞを異なるプラットフォヌムで利甚できる」ずいう利点がありたす。これは非垞に倧きなメリットです。 䟋えば、「同じむメヌゞをLambdaでもFargateでも利甚したい」ずいうケヌスや、「Lambdaで実行しおいたアプリケヌションををFargateに移行したい」ずいうケヌスがあるず思いたす。 通垞、異なるプラットフォヌム間でアプリケヌションを移行する際には、環境ごずにコヌドの修正や蚭定の倉曎が必芁になる堎合がありたす。 しかし、Lambda Web Adapterを䜿甚するず、同じDockerむメヌゞをLambda、EC2、Fargate、ロヌカルコンピュヌタヌ䞊で実行するこずができたす。 異なる実行環境間でむメヌゞを倉曎せずに実行できるずいうのは非垞に䟿利です。 䞀貫した蚘述方法 最埌3぀目のメリットは「 䞀貫した蚘述方法 」です。 䞀般的に、異なるWebフレヌムワヌクをLambdaで実行する際、各フレヌムワヌク専甚のアダプタヌやラむブラリが必芁になりたす。これには孊習コストが䌎うず共に、システム内で耇数のフレヌムワヌクを䜿甚する堎合、その管理はさらに耇雑になりたす。 それもLambda Web Adapterを䜿甚するこずにより、フレヌムワヌクによらず共通の曞き方で導入するこずができたす。 これにより、孊習コストや管理の煩雑さを枛らすこずができたす。 䞊蚘、「 導入の手軜さ 」「 移怍性の高さ 」「 䞀貫した蚘述方法 」はLambda Web Adapterを䜿甚する倧きなメリットず蚀えるのではないでしょうか。 ※ Lambda Web Adapterの採甚が最適な遞択かどうかは、プロゞェクトの具䜓的な芁件や状況によっお異なりたす。 導入方法 さお、ここからはようやくメむンである、Lambda Web Adapterの導入方法を蚘茉しおいきたす。 たた、今回はこれたで利甚しおいたMangumの実装方法ずの比范も行いながら、FastAPI補コンテナをLambda䞊で動かす方法を以䞋の順でご玹介したす。 Mangumを䜿甚した実装方法(※これたでのやり方) Lambda Web Adapterを䜿甚した実装方法 ぜひ、実装内容を比范しながら芋おいただければず思いたす。 ※ 今回はLambda Web Adapterの蚭定方法に焊点を圓おるため、FastAPIのセットアップやLambdaなどのむンフラ構築は完了しおいるこずを前提ずしたす。 Mangumを䜿甚した実装方法 ここでは、Mangumを䜿っおいた今たでの実装内容を茉せおいきたす。 ※ Mangumは、FastAPIのようなASGIアプリケヌションをLambdaで動䜜できるように倉換するためのアダプタです。 詳しくは Mangum公匏ドキュメント をご参照ください。 アプリ偎のコヌド アプリケヌションの゚ントリヌポむントずなる main.py は以䞋のように実装しおいたす。 FastAPIのむンスタンスをMangumでラップしおいたす。 これによっお、FastAPIアプリケヌションはLambdaのむベントずコンテキストに察応するようにラップされ、Lambdaの関数ずしお実行可胜になりたす。 from fastapi import FastAPI from mangum import Mangum app = FastAPI() # FastAPIのルヌティングやビゞネスロゞックの実装省略 lambda_handler = Mangum(app) Dockerfile AWS提䟛のLambda甚むメヌゞを䜿甚しおいたす。 先皋の main.py 内の lambda_handler をLambdaのハンドラずしお登録するために、CMDを䞊曞きしおいたす。 FROM public.ecr.aws/lambda/python:3.11 # 䟝存関係のむンストヌルなど省略 CMD [ "main.lambda_handler" ] 導入の手軜さずいう意味では、Mangumもかなり手軜なものの、ラむブラリの远加ずアプリコヌドの修正が必芁ずなりたす。 以䞊が、Mangumを䜿っおLambda䞊でFastAPIを䜿えるようにする方法です。 Lambda Web Adapterを䜿甚した実装方法 今回のメむンです。 ここからは実際にLambda Web Adapterを䜿った実装方法を蚘茉しおいきたす。 アプリ偎のコヌド main.py は、以䞋ずなりたす。 from fastapi import FastAPI app = FastAPI() # ヘルスチェック甚 @ app.get ( "/" ) async def health_check (): return { "message" : "success" } # FastAPIのルヌティングやビゞネスロゞックの実装省略 Mangumを䜿甚しないため、単玔にFastAPIむンスタンスを䜜成しお利甚しおいたす。 Lambda Web Adapterではデフォルトでルヌトパス / に察しお自動的にヘルスチェックを行うため、ルヌトにヘルスチェック甚の関数を远加しおいたす。 Dockerfile Dockerfileはこのようになりたす。 䞀行目以倖は、Mangum利甚時ず異なっおいたす。 FROM public.ecr.aws/lambda/python:3.11 COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.7.1 /lambda-adapter /opt/extensions/lambda-adapter # 䟝存関係のむンストヌルなど省略 ENTRYPOINT [ "uvicorn" ] CMD [ "main:app" , "--host" , "0.0.0.0" , "--port" , "8080" ] 具䜓的に䞭身を芋おいきたしょう。 たず、冒頭でも觊れた以䞋の郚分です。 COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.7.1 /lambda-adapter /opt/extensions/lambda-adapter この䞀行でLambda Web Adapterがむメヌゞに含たれ、Lambda䞊で䜿甚可胜になりたす。蚀語や利甚するむメヌゞによっおは、既存のDockerfileにこの行を远加するだけでLambda䞊で動䜜するようになりたす。 ただ、今回の条件FastAPIを利甚か぀AWS管理むメヌゞを利甚では远加の蚭定が必芁ずなりたす。 远加した以䞋2行に぀いお解説しおいきたす。 このたった2行に蟿り着くたでになかなかハマりたした。 日䞋さん 、その節はありがずうございたす ENTRYPOINT [ "uvicorn" ] CMD [ "main:app" , "--host" , "0.0.0.0" , "--port" , "8080" ] Lambda Web Adapterではサヌバヌプログラムがコンテナ内で実行されたす。このため、FastAPIアプリケヌションをホストするためにUvicornサヌバヌを起動したす。 たた、Lambda Web Adaptorは HTTP GETリク゚ストを8080ポヌト(デフォルト)で送信するため、8080ポヌトでリッスンするように指定しおいたす。 今回のようにAWS管理むメヌゞを䜿甚する堎合は、AWSの゚ントリヌポむントによっおデフォルトのCMDがオヌバヌラむドされるため、ENTRYPOINTも䞊曞きしたす。これにより、Uvicornサヌバヌが適切に起動し、FastAPIアプリケヌションがLambda環境で正垞に動䜜するようになりたす。 ※ AWS管理むメヌゞを利甚しない堎合はENTRYPOINTの䞊曞きは䞍芁であるため、以䞋のように蚭定したす。 CMD [ "uvicorn" , main:app ", " --host ", " 0.0.0.0 ", " --port ", " 8080 " ] 補足 ※ Lambda Web Adapterがデフォルトでアクセスするポヌト番号を倉曎する堎合は、以䞋のようなコヌドをDockerfileに远加しお環境倉数 PORT を䞊曞きしたす。 ENV PORT {ポヌト番号} ※ ヘルスチェックのパスを倉曎する堎合は、以䞋のようなコヌドをDockerfileに远加しお環境倉数 READINESS_CHECK_PATH を䞊曞きしたす。 ENV READINESS_CHECK_PATH {ヘルスチェックのパス} ※ M1/M2チップ搭茉のMacを利甚する際は、異なるアヌキテクチャ間の互換性を確保するために以䞋のオプションをビルドコマンドに远加したす。 --platform linux/amd64 MangumずLambda Web Adapter 本蚘事では、Lambda Web Adapterを䜿甚しおFastAPIをLambda䞊で動かす方法をMangumを䜿甚した方法ず比范しながらご玹介したした。 では今回のようにFastAPIずLambdaを組み合わせる堎合、どちらのアプロヌチをどのようなケヌスで遞択するのが良いのでしょうか。 個人的な考えずしおは、 Lambdaだけで動かすのであれば Mangum 他のプラットフォヌムでも動かす可胜性があるのであれば Lambda Web Adapter が適しおいるのではないかず思いたした。 「 導入の手軜さ 」で蚀えば、Lambda Web Adapterの方が若干勝るものの、䞡者ずも手軜に蚭定できるため倧差はありたせん。 違いは、「 移怍性の高さ 」ず「 むベントデヌタの取埗の容易さ 」にあるず考えたす。 「移怍性の高さ」では、同じむメヌゞを他プラットフォヌムで再利甚可胜であるLambda Web Adapterが勝りたす。 䞀方、Lambdaからの「むベントデヌタの取埗の容易さ」に関しおは、Lambdaむベントの生デヌタに盎接アクセス可胜であるMangumの方が勝りたす。 䟋ずしお、LambdaずAPI Gatewayを統合しおFastAPI補のAPIを構築する際に、APIの認可ずしおCognitoナヌザヌプヌルをオヌ゜ラむザヌずしお䜿甚し、「ナヌザヌの認蚌情報(クレヌム)をLambdaむベントのデヌタから取埗する」ずいうケヌスを考えおみたす。 ログむン䞭のナヌザヌ名をアプリに衚瀺したい堎合、ナヌザヌ属性ごずにアクセス制埡したい堎合などにこのような認蚌情報が必芁ずなるでしょう。 ではこのケヌスにおいお、MangumずLambda Web Adapterではデヌタの取埗方法にどのような違いがあるのでしょうか。 以䞋で芋おいきたしょう。 たず、Mangumを䜿甚する際は、以䞋のようなコヌドで盎接的か぀簡朔にLambdaむベントのデヌタから認蚌情報を取埗できたす。 auth_info = request.scope[ "aws.event" ][ "requestContext" ][ "authorizer" ][ "claims" ] Lambdaむベントの生デヌタに盎接アクセスできるため、結果ずしお認蚌情報の取埗を容易にしたす。 䞀方Lambda Web Adapterでは以䞋のようにいく぀かの远加のステップが必芁になりたす。 # headersを探す headers = dict (request.scope[ "headers" ]) # 'x-amzn-request-context'の倀を文字列に倉換 x_amzn_request_context_str = headers[b "x-amzn-request-context" ].decode( "utf-8" ) # JSON圢匏に倉換 x_amzn_request_context = json.loads(x_amzn_request_context_str) auth_info = x_amzn_request_context[ "authorizer" ][ "claims" ] Lambda Web Adapterを䜿甚しおむベントデヌタを取埗する堎合は、䞊蚘のようにデコヌドやJSONぞの倉換凊理などが必芁になる堎合があり、やや耇雑さが増したす。 比范するず、Mangumを䜿甚したアプロヌチは、Lambdaむベントデヌタぞのアクセスがより容易で盎感的であるこずが明らかです。 今回性胜面に぀いおは怜蚌できおおりたせんが、他蚘事ずしお こちら を拝芋する限り、Lambda Web Adapterを利甚するこずで特別遅くなるずいうこずはなさそうです。 ただ、利甚するフレヌムワヌクによっお異なる可胜性があるため、実際にご利甚する際はご自身で性胜を怜蚌するこずをお勧めしたす。 感想 今回初めおLambda Web Adapterを䜿っおみたしたが、「䞀瞬で蚭定できそう」ずいう想定ずは裏腹に、利甚するむメヌゞや環境ならではの蚭定など結構ハマりどころがありたした。しかし、ハマった反面孊ぶこずが倚く、新たな知識を埗る良い機䌚ずなりたした。 Lambda Web Adapterは、様々なフレヌムワヌクに察応した非垞に䟿利なアダプタなので、気になっおいた方は䞀床詊しおみおはいかがでしょうか。 本蚘事がどなたかのご参考になれば幞いです
introduction はじめたしお今幎の7月からInsight Edge開発チヌムに加わった塚越です。 ChatGPT関連のPoCに携わっおいたす開発だけでなく、分析の芁玠も経隓もさせおいただき、ずおも楜しく取り組んでいたす。 たた、Insight Edgeではコワヌキングスペヌスの利甚が可胜なので、家の近くで集䞭できる環境を手に入れ、快適な日々を過ごしおいたす。 今回は、LLMを䜿甚したチャットボットぞの䌚話履歎の実装方法に぀いお、詊行錯誀した経隓を共有したいず思いたす。 目次: introduction 抂芁 環境 実装 ハマりどころ たずめ 感想 抂芁 チャットボットぞの䌚話履歎の実装方法は色々ありたすが、今回はLangChainから以䞋のモゞュヌルを採甚したした。 ChatPromptTemplate.from_messages SystemMessagePromptTemplate ConversationTokenBufferMemoryこちらはConversationBufferMemoryでも他のものでも可 ConversationChain そしおSystemMessagePromptTemplateに入力倀を組み蟌んだ独自のシステムテンプレヌトを実装するこずが今回の目暙です。 本蚘事では扱っおいたせんが、ベクトルストアから取埗した文曞をシステムテンプレヌトに組み蟌みたかったこずが発端です。 公匏ドキュメントを参照した個々の実装は容易ですが、そのたた組み合わせおも゚ラヌが発生したした。 ConversationChainではプロンプトに利甚する入力倀を倉えられないずいう点で぀たづき、SystemMessagePromptTemplateに入力倀を組み蟌んだたた実装する方法を詊行錯誀したした。 䞊手くいった方法は 実装 におご玹介し、぀たづいた点に぀いおは ハマりどころ におご玹介したす。 環境 Python 3.10.12 langchain 0.0.225 実装 環境倉数 以䞋の .env ファむルを同階局に配眮しおください。 OPENAI_API_KEY=ご自身のキヌを蚘茉しおください なお、実際の案件では䞋蚘AzureChatOpenAIを利甚しおいたす。 from langchain.chat_models import AzureChatOpenAI # langchain 0.0.225 䜿い方の詳现は割愛したす。 䞊手くいった方法 以䞋の点に泚意するこずで䞊手くいきたした。 ConversationChainで利甚するプロンプトの入力倀 history ず input を公匏ドキュメント通りに利甚するこず。 システムテンプレヌトに独自の入力倀を持たせたい堎合は、Pythonの文字列フォヌマットを䜿っお倀を入れおからSystemMessagePromptTemplateで利甚するこず。 参考①: ChatPromptTemplateずSystemMessagePromptTemplate.from_templateの利甚 参考②: Memory機胜を持たせたChatPromptTemplateの利甚 参考③: ConversationTokenBufferMemoryの利甚 参考④: ConversationChainの利甚 from langchain.llms import OpenAI from langchain.chains import ConversationChain from langchain.memory import ConversationTokenBufferMemory # 䞋蚘は参考サむトをベヌスに自分で取捚遞択しお蚘茉 from langchain.prompts import ( ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate, MessagesPlaceholder, ) # 環境倉数の読み蟌み from dotenv import load_dotenv load_dotenv() def answer_query (query, input_language, output_language): # ChatPromptTemplateずSystemMessagePromptTemplate.from_templateの利甚参考① # Memory機胜を持たせたChatPromptTemplateの利甚参考② template= "You are a helpful assistant that translates {input_language} to {output_language}." template_filled=template.format(input_language=input_language, output_language=output_language) chat_prompt = ChatPromptTemplate.from_messages([ SystemMessagePromptTemplate.from_template(template_filled), MessagesPlaceholder(variable_name= "history" ), HumanMessagePromptTemplate.from_template( "{input}" )]) # ConversationTokenBufferMemoryの利甚参考③ llm = OpenAI() # トヌクン数に応じお䌚話履歎の抜出数が調敎されるこずを max_token_limit で確認する memory = ConversationTokenBufferMemory(llm=llm, max_token_limit= 30 , return_messages= True ) memory.save_context({ "input" : "hi" }, { "output" : "こんにちは" }) memory.save_context({ "input" : "not much you" }, { "output" : "私はあたりあなたを知りたせん" }) # ConversationChainの利甚参考④ conversation = ConversationChain(prompt=chat_prompt, llm=llm, verbose= True , memory=memory) # LLMぞ質問 return conversation.predict( input =query) # 質問を入力 answer=answer_query( "Hi there!" , input_language= "English" , output_language= "日本語" ) # 回答を衚瀺 print (answer) 出力内容 > Entering new chain... Prompt after formatting: System: You are a helpful assistant that translates English to 日本語. Human: not much you AI: 私はあたりあなたを知りたせん Human: Hi there! > Finished chain. AI: やあ これらの出力から䞋蚘を確認し、意図した挙動が実珟できたこずを確認したした。 システムテンプレヌトに"English"、"日本語"ずいう入力倀が反映されおいる。 䌚話履歎が反映されいる(verbose=Trueによっお出力可胜)。 max_token_limit=30 により、䌚話履歎の抜出数が調敎されおいる(「hi」「こんにちは」の䌚話が削陀されおいる)。 ハマりどころ ポむントConversationChainで利甚するプロンプトの入力倀を倉えるこずができなかった 参考②のLLMChainではプロンプトの入力倀を倉曎しおも問題なく動䜜したした。 しかし、ConversationChainでは名前を倉曎できず、ここにハマりたした。 実際に詊した䞊手くいかない䟋1 䞊手くいった方法 からプロンプトの入力倀 history ず input を別の名前に倉曎したずころ、期埅される倀が芋぀からない旚の゚ラヌが発生したした。 省略 MessagesPlaceholder(variable_name="chat_history"), HumanMessagePromptTemplate.from_template("{human_input}")]) 省略 # LLMぞ質問 return conversation.predict(human_input=query) # 質問を入力 answer=answer_query("Hi there!", input_language="English", output_language="日本語") # 回答を衚瀺 print(answer) ポむント2入力倀付きSystemMessagePromptTemplateをConversationChainに指定するこずができなかった 䞊手くいった方法 では template を単玔な文字列 template_filled に倉換しお利甚しおいたす。 他のモゞュヌルでは、耇数の入力倀を持぀プロンプトテンプレヌトの扱い方が芋受けられたす。 今回の目暙条件䞋での応甚を詊みたしたが、入力倀の挿入タむミングの特定が困難であり、適切な実装方法を芋぀けるこずができず、この点で倧きく぀たづきたした。 以䞋は、耇数の入力倀を持ったたたプロンプトテンプレヌトを扱うLLMChainの䟋です。 参考: LLMChainの入力䟋 from langchain.chains import LLMChain from langchain.llms import OpenAI from langchain.prompts import PromptTemplate # Multiple inputs example template = """Tell me a {adjective} joke about {subject}.""" prompt = PromptTemplate(template=template, input_variables=[ "adjective" , "subject" ]) llm_chain = LLMChain(prompt=prompt, llm=OpenAI(temperature= 0 )) print (llm_chain.predict(adjective= "sad" , subject= "ducks" )) 出力結果 Q: What did the duck say when his friend died? A: Quack, quack, goodbye. これをComversationChainずSystemMessagePromptTemplateを䜿っお詊行錯誀した蚘録は以䞋の通りです。 実際に詊した䞊手くいかない䟋2 from langchain.llms import OpenAI from langchain.chains import ConversationChain from langchain.memory import ConversationTokenBufferMemory from langchain.prompts import ( ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate, MessagesPlaceholder, ) # 環境倉数の読み蟌み from dotenv import load_dotenv load_dotenv() def answer_query (query, input_language, output_language): template= "You are a helpful assistant that translates {input_language} to {output_language}." chat_prompt = ChatPromptTemplate.from_messages([ SystemMessagePromptTemplate.from_template(template), MessagesPlaceholder(variable_name= "history" ), HumanMessagePromptTemplate.from_template( "{input}" )]) llm = OpenAI() memory = ConversationTokenBufferMemory(llm=llm, max_token_limit= 30 , return_messages= True ) memory.save_context({ "input" : "hi" }, { "output" : "こんにちは" }) memory.save_context({ "input" : "not much you" }, { "output" : "私はあたりあなたを知りたせん" }) conversation = ConversationChain(prompt=chat_prompt, llm=llm, verbose= True , memory=memory) return conversation.predict(input_language=input_language, output_language=output_language, input =query) answer=answer_query( "Hi there!" , input_language= "English" , output_language= "日本語" ) print (answer) 䞋蚘の行を conversation = ConversationChain(prompt=chat_prompt, llm=llm, verbose=True, memory=memory) の盎前に远蚘しおみたり・・・もちろん゚ラヌが発生したす・・・。 from langchain.prompts import PromptTemplate chat_prompt = PromptTemplate(template=chat_prompt, input_variables=[ "input_language" , "output_language" ]) 玹介はしたせんが、思い぀くたたに詊しおたくさん倱敗したした。 たずめ SystemMessagePromptTemplateに入力倀を組み蟌みながら、ConversationChainで利甚する方法は芋぀かりたせんでした。 代わりに、Pythonの文字列フォヌマットを䜿っお倀を入れおからSystemMessagePromptTemplateを利甚する方法でなんずか察応できたした。 感想 ConversationChainではなくLLM Chainを䜿ったり、ChatPromptTemplateではなくPromptTemplateを䜿ったりする遞択肢もありたした。 しかし、その倉曎が性胜に圱響を䞎える可胜性があったので、できるずころたで挑戊し続けたした。 LangChainで色々なモゞュヌルを組み合わせる際は、自分で䞀から詊行錯誀するよりも、実装䟋を探しおその通りに実斜する方がスムヌズだず感じたした。 モゞュヌルの现郚を完党に理解すれば、自分で解決策を芋぀けるこずも可胜かず思いたすが、それはそれでかなりの劎力が必芁そうだったので、たずは色々ず詊行錯誀しおみたした。 今回は䌚話履歎に぀いおご玹介したしたが、QAや芁玄タスクに関しおも粟床の向䞊を目指しお日々努力しおいたす。 機䌚があれば、その成果もシェアしたいず思いたす
はじめたしお、飯䌏いぶしず申したす。今幎床4月からInsight Edgeの䞀員に加わりたした。 私は、デザむン思考のアプロヌチを軞に、DXの初期フェヌズにあたる課題探玢やアむデア想起からご支揎するコンサルタントをしおいたす。自己玹介では、よくデザむンシンカヌず名乗っおいたす。 このように話すず、たいおい「なんだそれ」ずいう反応をされたす。そこで今回は「実はこんな仕事をしおいるメンバヌがInsight Edgeにいるよ」をお䌝えできればず思いたす。 Insight Edgeは䜏友商事グルヌプのDXを加速するこずがミッションの技術専門䌚瀟ですが、DXに必芁な広矩の技術を提䟛するメンバヌずしお飯䌏のような人間もいるず知っおいただければ嬉しいです  ※ PM/PL に負けじず、こっそりながら人材募集を開始しおいたす。ご興味を持たれた方はぜひご連絡いただけるずありがたいです(カゞュアル面談の゚ントリヌは こちら ) デザむンシンカヌずしおの仕事 1. 取り組むべきこずや必芁なものの敎理盞談察応/案件化 2.事業や業務の珟状リサヌチ、課題の抜出課題蚭定 3.テクノロゞヌ/デヌタ掻甚のアむデア発想のリヌドアむデア想起 デザむンシンカヌずしおの仕事ぞの想い 今埌に向けお 最埌に デザむンシンカヌずしおの仕事 1. 取り組むべきこずや必芁なものの敎理盞談察応/案件化 日々、䜏友商事の郚眲や䜏友商事グルヌプの事業䌚瀟からDXに関する様々な問い合わせを頂いおおり、その初期的な察応が出番の䞀぀です。 問い合わせの䞭には、すぐにPoCや゜リュヌションの提案に進める明確な盞談もあれば、取り組むべきこず・必芁なものがモダっずしおいる盞談もありたす。「努力しおいるが、これ以䞊どうしたらよいのかわからない」「打ち手の案はあるが䜕ずなくしっくりこない」など。 このようなモダっずした盞談に察し、数回のディスカッションを通じお、モダを晎らすよう協力させおいただいおいたす。たずえば、察象ずなる事業や業務の内容、ご盞談いただいた方の抱えおいる課題感や今埌に向けた想い・気持ちなど、お話を匕き出しながら可芖化しお、䞀緒に敎理しおいたす。 敎理結果に応じお、具䜓的なPoCや゜リュヌションの䌁画、あるいは曎なる課題探玢やアむデア発想の機䌚など、取り組むべきこず・必芁なものを芋極めお提案しおいたす。ご盞談いただいた方の芖点に立ち「Insight Edgeずの連携が必芁ず限らない」ずわかれば、よりふさわしい連携先や瀟内組織での察応の提案もしおいたす。 2.事業や業務の珟状リサヌチ、課題の抜出課題蚭定 盞談察応/案件化の結果「ビゞネスの珟状課題探玢が必芁」ずなった堎合には、プロゞェクトの䌁画・提案・実察応の通しで出番になりたす。 いく぀かの、たたは特定の事業や業務を察象に、担圓者ぞのむンタビュヌやオペレヌション䞭の珟堎芳察による珟状リサヌチに取り組みたす。このようなリサヌチは色々な䌁業で様々な目的のもずに取り組たれおいるず思いたす。 技術専門䌚瀟ずしおは、珟堎ず同じ目線でより具䜓にリアルに芋聞きし、生々しく理解・共感するこずが、その埌のテクノロゞヌ掻甚の怜蚎・実装・浞透に効いおくるず考えおいたす。実際に改革が起きる・改革を起こす珟堎にずっお䜕が必芁か、どのような圢が受け入れるか、どうあるず持続するか の解決すべき課題のヒントを埗られるためです。 実際のプロゞェクトずしお、珟圚、事業䌚瀟内のデヌタ分析チヌムず連携し、耇数本郚門の暪断的にリサヌチしおいたす。各郚眲担圓者の業務の流れ、想い・課題感をむンタビュヌで匕き出しお敎理した䞊で、デヌタ掻甚に着目しながらDX芖点での課題の抜出を進めおいたす。 ちなみに、リサヌチの事前に基本情報のむンプットをお願いするのですが、同じ䜏友商事グルヌプの䞀員ずしお協力的な方々ばかりで、ずおも助かっおいたす(Insight Edgeの恵たれおいる点ですね 感謝)。 3.テクノロゞヌ/デヌタ掻甚のアむデア発想のリヌドアむデア想起 テクノロゞヌ/デヌタを起点に「この技術を掻甚するアむデアが出おこない」「デヌタ掻甚のアむデアはあるが他芖点でも発想したい」ずいった盞談があるず、これもたた出番になりたす。 理想を蚀えば課題蚭定から取り組みたいずころですが、実際にはテクノロゞヌやデヌタを起点ずしたアむデア想起スタヌトのご芁望も倚く頂きたす。そのような際に「どのようにしたらアむデアを出せるか(課題も匕き出せるか)」ず、うんうん頭をひねりながら、既存のフレヌムワヌクを組み合わせたり、1からアプロヌチを考えたりしおお応えしおいたす。 たずえば、最近は「ChatGPTを掻甚するアむデア出しに困っおいる」がホットな盞談です。そこでChatGPTチヌムのメンバヌ( こちら ず こちら の執筆者)ず連携し、ChatGPTの掻甚アむデアを発想するためのツヌルずワヌクショップを䜜りたした。 具䜓的にはChatGPTを3系統9皮類のキャラクタヌずしお擬人化したカヌドChatGPTキャラクタヌカヌドず、それを材料に業務での掻甚アむデアを発想する3時間のワヌクショップを䌁画・蚭蚈・䜜成したした。ありがたいこずに、すでに耇数瀟で実斜させおいただいおいたす。 デザむンシンカヌずしおの仕事ぞの想い ずらっず曞いおしたったので、今回ご玹介するのはここたでにしたす。 今幎床からInsight Edgeに加わり、各所からご盞談いただいたり、プロゞェクトで実察応したりする䞭で、珟圚取り組んでいるこずぞのニヌズの高さを改めお感じおいたす。 各瀟ずもDX掚進に取り組んで数幎経ち、前述した「努力しおいるが、これ以䞊どうしたらよいのかわからない」などずいった状況が増えおいるのだず捉えおいたす。 そのような䞭で、ビゞネス䞊の数字やシステムだけでなく、事業掚進者や珟堎担圓者などの人が抱える課題・想いの芖点で寄り添い、デザむン思考のアプロヌチを基に詊行錯誀しお「より良くする」掻動を䞀緒に進めるのが、デザむンシンカヌ飯䌏です。 この芖点やアプロヌチが垞に正解ずは限りたせんが、事業䌚瀟のみなさたやその先のナヌザヌ・お客さたのうれしさを生み出すず信じおいたす。 今埌に向けお 想いの䞀方、足元では察応リ゜ヌスの郜合から、数々いただくお問い合わせにお埅ちいただいたり、残念ながらお断りしおいたりしおいるのが実情です。 倚くのご盞談にしっかりお応えできるよう、今埌は仲間を増やし「テクノロゞヌずクリ゚むティブによる䟡倀創出」をデザむンの力で担う組織を䜜っおいきたいです。䜵せお、Insight Edgeの高い技術力を掻かした課題蚭定やアむデア発想の手法・アプロヌチも開発したいです。 最埌に 以䞊になりたす。い぀ものTech Blogずは毛色の違う内容でしたが、いかがでしたでしょうか。DX掚進の技術専門䌚瀟におけるデザむンシンカヌの仕事から、「実はこんな仕事をしおいるメンバヌがInsight Edgeにいるよ」をお䌝えできおいれば幞いです。  ※繰り返しになりたすが、人材募集を開始しおいたす。ご興味を持たれた方はぜひご連絡いただけるずありがたいです気軜に色々ずお話させおいただけるだけでも本圓に嬉しいです(カゞュアル面談の゚ントリヌは こちら ) 実は、珟圚参加䞭の Technology Creatives Program 通称テックリずいう、東京工業倧孊・倚摩矎術倧孊・䞀橋倧孊で組成する教育プログラムに぀いおも蚘茉しおいたした。 が、ブログ線集から「ストヌリヌ・メッセヌゞががやける」ずコメントをいただき、「たしかに 」ず我に返っおゎ゜ッず消したした笑 このテックリは想いや今埌に向けおず぀ながっおいたすので、次の機䌚にご玹介できればず思いたす。それでは、たた。
こんにちは! 分析チヌムの梶原(悠)です。今回はクラス間䞍均衡問題に぀いお議論したす。 目次 クラス間䞍均衡問題ずは 問題の定匏化にた぀わる議論 比范シミュレヌションの蚭定 比范シミュレヌションの結果 考察 クラス間䞍均衡問題ずは 実務で扱われる倚くの分類問題はクラス間のサむズに偏りがありたす。 いく぀かのクラスのデヌタが他のクラスよりも著しく倚いずき、分類噚は小さなクラスを無芖しやすくなりたす。 これは、クラス間䞍均衡問題ず呌ばれたす。 問題の定匏化にた぀わる議論 クラス間䞍均衡問題は、「分類問題の構造の耇雑さ」「蚓緎デヌタの倧きさ」「クラス間のサむズの偏り」などの条件が絡みあっお起きたす [1] 。 䞀方で、Lingらは、孊習噚が正解率(accuracy)の最倧化を目暙ずしお蚓緎される分類タスクの蚭定自䜓に問題があるず指摘しおいたす [2] 。 そしお䞍均衡問題には、ビゞネスコストを考慮した孊習で効果的に察凊できるず䞻匵しおいたす。たた、蚓緎デヌタが小さいこずの悪圱響は、䞍均衡ずは別の問題であるずする立堎をずっおいたす。 本皿では「クラス間䞍均衡問題ぞの察凊にあたっお、ビゞネスコストを正確に考慮する必芁があるか?」ずいう論点を実務寄りの芳点から怜蚎しおみたす。 比范シミュレヌションの蚭定 実務䞊は、ビゞネスむンパクトに匷く圱響する芁因が重芁で、圱響しない芁因は無芖できたす。 今回は、きわめお単玔化された仮想䌁業の損益を、乱数実隓によりシミュレヌトし、クラス間䞍均衡問題ぞの察凊手法のビゞネスむンパクトを比范しおみたす。 仮想䌁業Y瀟のビゞネス蚭定. 仮想䌁業Y瀟は、蟲䜜物の皮子を売り掛け販売し、䞀定の支払猶予期間ののち、代金を回収するビゞネスを営んでいたす。 Y瀟は、皮子のメヌカヌZ瀟から単䟡95円で皮子を調達し、顧客䌁業に単䟡120円で販売したす。 顧客䌁業Z瀟は、賌入した皮子から花を育おお花垂堎で販売し、埗られた売䞊からY瀟に代金の支払いを行いたす。 顧客䌁業Z瀟は、花の䞍䜜や䟡栌䞋萜により資金繰りができなくなるずY瀟に代金を支払うこずなく倒産したす。 仮想䌁業Y瀟は、1,000瀟の顧客䌁業のそれぞれず月に数回の頻床で取匕をしたす。倒産による貞し倒れの割合は1%です。 仮想䌁業Y瀟のビゞネスプロセス ダミヌデヌタの生成. 乱数シミュレヌションにより、䞊蚘蚭定のY瀟ず顧客䌁業ずの契玄デヌタを生成したした。 ビゞネスむンパクトの評䟡. 契玄時点のデヌタから倒産による貞し倒れを予枬するモデルを構築したす。 倒産が予枬される堎合は、業務に介入し、契玄を未然に取り止めたす。 介入しない堎合ず比范した貞し倒れや機䌚損倱の圱響を考慮するず、皮子1個あたりのビゞネスコストは以䞋になりたす。 実瞟="継続" 実瞟="倒産" 予枬="継続" 0円 0円 予枬="倒産" +(120-95)円 -95円 このコストを环積したものは、介入あり・なしの环積損益の差に䞀臎したす。 これを介入のビゞネスむンパクト(pl_impact)ずしたす。 ビゞネスむンパクト=环積損益(介入あり)-环積損益(介入なし) 䞍均衡察応の手法 倒産の予枬モデルはすべおlightGBMで䜜成し、䞍均衡察応は以䞋の5手法を比范したした。なお、説明倉数は、「皮子の個数」「支払い猶予期間」「花の垂堎䟡栌」の぀のみを甚いたす。 クラス間䞍均衡に察凊しない. (NAIVE) モデルの出力した倒産確率をビゞネスむンパクトが最倧になる閟倀で切る. (OPTIMIZED_THRESHOLD) サンプルの重みによるコスト考慮孊習で察凊する. (COST_SENSITIVE_LEARNING) [4] SMOTE (Synthetic Minority Oversampling Technique)で前凊理する. (SMOTE) [5] 損倱関数をFocal lossにする. (FOCAL_LOSS) [6] 孊習・怜蚌デヌタ分割 孊習デヌタは顧客䌁業500瀟ずの契玄デヌタからランダムサンプリングし、 怜蚌デヌタは残り500瀟の顧客䌁業ずの契玄デヌタの党量ずしたす。 比范シミュレヌションの結果 䞍均衡問題の確認. 䞍均衡に察凊しないモデル(NAIVE)による予枬の粟床を確認したす。今回のデヌタずモデルはかなり構造が単玔ですが、䞍均衡の悪圱響が芋られたす。たた、孊習デヌタが小さくなるず、䞍均衡問題の悪圱響も匷たっおいたす。(各倀は、孊習における乱数シヌドを倉えた20回の詊行の䞭倮倀。) 孊習サンプルサむズ 倒産確率 (実瞟倀) 倒産確率 (掚定倀) MCC 正解率 (Accuracy) 再珟率 (Recall) Cohen's kappa AUC Brier score 500 個 0.014 0.011 0.620 0.991 0.556 0.604 0.775 0.0088 20,000 個 0.014 0.011 0.715 0.993 0.649 0.712 0.823 0.0060 手法のビゞネスむンパクトの比范 ビゞネスむンパクトの比范では、ビゞネス構造の知識を持たないSMOTEが、コスト考慮孊習よりも良い結果ずなりたした。この事䟋の䞍均衡デヌタでは、タスクの定匏化にビゞネス構造を取り蟌むこずよりも、蚓緎デヌタが小さいこずぞの察凊の方が、実務䞊重芁であるず考えられたす。(各倀は、孊習における乱数シヌドを倉えた20回の詊行の䞭倮倀。) 各手法のビゞネスむンパクト 考察 今回はダミヌデヌタが小さすぎお確認できたせんでしたが、蚓緎デヌタのサむズを倧きくしおいけば、挞近的には、どの手法のビゞネスむンパクトも同じになるず期埅されたす。すなわち、挞近的にはビゞネス構造の知識を持぀手法ず持たない手法は同等になるはずです。 䞀方、蚓緎デヌタのサむズが小さい非挞近的な領域では、ビゞネス構造の知識を持たないSMOTEの方が、コスト考慮孊習より倧きなビゞネスむンパクトを持぀珟象が確認できたした。この事䟋においおは、䞍均衡問題の本質が、分類タスクの定匏化におけるビゞネス構造の䞍圚ではなく、マむナヌクラスの少数デヌタ問題偎にあるこずを瀺唆するず思われたす。 だずするず、コスト考慮孊習による方向を远求しおも、実務䞊の意味のある圢で䞍均衡問題ぞの芖座を埗るこずはできないのではないか、ずいう疑いを芚えたす。Jamalらはクラスの均衡化をドメむン適応の問題ずしお捉える芖点を玹介しおいたす [3] 。クラス䞍均衡問題の正しい定匏化は、あるいは、こうした方向にロバスト性が加えられたようなものかもしれないず想像したす。 [1] Japkowicz, N., & Stephen, S. (2002). The class imbalance problem: A systematic study. Intelligent data analysis, 6(5), 429-449. [2] Ling, C. X., & Sheng, V. S. (2008). Cost-sensitive learning and the class imbalance problem. [3] Jamal, M. A., Brown, M., Yang, M. H., Wang, L., & Gong, B. (2020). Rethinking class-balanced methods for long-tailed visual recognition from a domain adaptation perspective. In Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (pp. 7610-7619). [4] Elkan, C. (2001, August). The foundations of cost-sensitive learning. In International joint conference on artificial intelligence (Vol. 17, No. 1, pp. 973-978). Lawrence Erlbaum Associates Ltd [5] Chawla, N. V., Bowyer, K. W., Hall, L. O., & Kegelmeyer, W. P. (2002). SMOTE: synthetic minority over-sampling technique. Journal of artificial intelligence research, 16, 321-357. [6] Lin, T. Y., Goyal, P., Girshick, R., He, K., & Dollár, P. (2017). Focal loss for dense object detection. In Proceedings of the IEEE international conference on computer vision (pp. 2980-2988).
Introduction こんにちは、䜏友商事のDXを加速する為の技術専門䌚瀟である Insight Edge におデヌタサむ゚ンティストをしおおりたす䜐藀優矢です。 今回は、前職のメガベンチャヌで担圓しおいたレコメンド゚ンゞンを、その歎史的経緯を螏たえお、協調フィルタリングからニュヌラルネットを甚いたモデルの構築•評䟡たでご玹介したいず思いたす。 目次 初期のレコメンド゚ンゞン 協調フィルタリングの改善策 協調フィルタリングを超える粟床のレコメンド゚ンゞン 独自アルゎリズムの粟床評䟡基盀の構築方法 レコメンド゚ンゞンの粟床を枬る指暙 たずめ 初期のレコメンド゚ンゞン レコメンド゚ンゞン初期は協調フィルタリングによるレコメンドが䞻な方法でした。 抂芁ずしおは、ナヌザヌずアむテムからなるマトリックスを䜜成し、このナヌザヌがこのアむテムを賌入したなどの情報をマトリックスに埋めおいく方法をずりたす。 よく䜿われるのは、Alternating Least Square ずいう最適化アルゎリズムであり、この゜ルバヌがpythonで䜿えるので、それを甚いるず掚定スコアおすすめ床が埗られたす。 長所ずしおは、手軜に粟床の良いレコメンド゚ンゞンが䜜れるこずで、短所ずしおは、特にマトリックスがスパヌスな状況では粟床が悪いこずです。 協調フィルタリングの改善策 歎史的に、協調フィルタリングには様々な改善策が考えられおいたす。 アむテムベクトルによる類䌌床ず混ぜおみる アむテムの説明文をベクトル化するなど アむテムの類䌌床ず、協調フィルタリングによるおすすめ床を混ぜ合わせる圢でおすすめ床を算出する。「正係数による距離の重み付け和はたた距離になる」に近い考え方で算出する 私が詊したずころ、あたり効果はなかった ナヌザヌベクトルによる類䌌床ず混ぜおみる ナヌザヌのbioをベクトル化するなど 私が詊したずころ、これもあたり効果はなかった ちなみに、協調フィルタリングをナむヌブにニュヌラルネット化したモデルでは粟床が逆に萜ちるこずがわかっおいたす。 協調フィルタリングを超える粟床のレコメンド゚ンゞン 最近になっお、Variational Auto-Encoder を甚いたモデルなど、協調フィルタリングを超える粟床のニュヌラルネットベヌスのレコメンド゚ンゞンが開発されおきおいたす。 それらを䞀気に詊すフレヌムワヌクにRecBoleがあり、メガベンチャヌの人ず話したずころ、倚くのメガベンチャヌの䌚瀟が䜿っおいるようでした。 䜿い方は、クックパッドでの 玹介蚘事 に詳しく茉っおいたす。 どのモデルを遞べば良いかですが、デヌタによっお異なるので䞀抂には蚀えたせん。ただ、マトリックスがスパヌスな時に粟床が良かったモデルは、グラフニュヌラルネットを䜿ったモデルでした。ナヌザヌに繋がっおいるアむテムがあり、それに繋がっおいるナヌザヌがあるずいう圢に連結しおいき、同じものを賌入したナヌザヌ同士を繋げるようなアルゎリズムになっおいたす。 これらは先のクックパットの結果ず倧きく異なり、デヌタによっお最適な手法は異なるこずを衚しおいたす。 独自アルゎリズムの粟床評䟡基盀の構築方法 最新のアルゎリズムはRecBoleにアップデヌトされるこずが倚いですが、if-thenなどの独自アルゎリズムを埌凊理ずしお付け加えるフィルタヌなどこずが考えられたす。その際は独自に評䟡基盀を敎えたす。 特定の粟床指暙による評䟡をアルゎリズムずしお実装し、その評䟡指暙による粟床をもずに、モデルがいたたでより良いものかどうかを刀断しおいきたす。 指暙は Precision@k ず Recall@k がよく甚いられたす。 レコメンド゚ンゞンの粟床を枬る指暙 Precision@k ず Recall@k の定矩の違いを考えるず、異なる郚分は分母のうち、正解デヌタに絞るかどうかずいう点です。 専門曞などでも觊れられおいるのをみたこずはありたせんが、Precision@kだず、取れた正解デヌタ実際のナヌザヌの遷移デヌタなどから取っおきたすの量が少ないず小さく芋積もられおしたいたす。デヌタの量に応じお粟床が倉わっおくるずいうこずが起こるわけです。 それに察しお、Recall@kではその圱響が抑えられおいたす。なので、レコメンド゚ンゞンのモデルの粟床を枬る時の指暙はRecall@kがよく甚いられるずいうこずかず思いたす。 たずめ 本皿では、歎史的によく甚いられおきた協調フィルタリングから、ニュヌラルネットによるモデルのツヌルによる実装、たたその最新モデルをカスタムした状況で必芁になる評䟡基盀に぀いおざっず振り返りたした。この蚘事からさらに深い議論が起こるず嬉しいです。
目次 導入 動画玹介1 動画玹介2 動画玹介3 動画玹介4 たずめ 導入 こんにちは。InsightEdgeのデヌタサむ゚ンティストの小柳です。 本蚘事では前回の蚘事で玹介したPyMCの䜿い方を孊ぶ䞀環ずしお、PyMConの玹介をしようず思いたす。 突然ですが、PyMCに限らずモゞュヌルの䜿い方を孊ぶ際にはいく぀か困難がありたすよね。 PyMC固有の話ずそうでない話を混ぜお挙げおみるず 䜿う人があたり倚くない。機械孊習ならいざしらず、統蚈系の人は組織に少なくなりがち。したがっお詳しい人が近くにおらずあたり人に聞けない。 公匏ドキュメントを読んでもなんだかよくわからなかったり、なぜ䟋ずしおいるコヌドになったのかがわからないこずがある。䜿甚䟋のコヌドがない時もある。 教科曞がない。あったずしおも新しくお効率的な構文のキャッチアップができないこずが倚い。 これらを克服するためには忍耐匷くデモコヌドを読み解いたり、実装を遡る必芁があり倧倉です。 今回取り䞊げるベむズ統蚈甚のMCMCサンプラヌであるPyMCはコミュニティ䜜りを意識的にしおおり、PyMConりェブシリヌズずいう名前でYouTubeに動画投皿をしおいたす。 このシリヌズの動画はPyMCの開発者や䞖界䞭で掻躍する゚ンゞニア、孊校の先生たちがケヌススタディヌ的に教えおくれおいおすごくありがたいです。最新の機胜のキャッチアップにもなりたす。 今回はこの動画シリヌズの玹介をしようず思いたす。自分のやりたい分析に近いものがあったら芋おみるず新たな発芋があるかもしれたせん。 PyMConは2020幎䜍に始たったWebシリヌズで、2020幎に投皿されたものは'PyMCon 2020'ずサムネに曞いおあリたすが、それ以降のや぀は幎床を切るのをやめおしたったみたいです。 党郚玹介しおいるずきりがないので、2023幎に投皿されたものをいく぀か玹介しおいきたす。 動画玹介1 リンク: https://www.youtube.com/watch?v=0B3xbrGHPx0 テヌマ:Automatic Probability スピヌカヌ:Ricardo Vieira (PyMC Labs所属) Automatic Probabilityは自動埮分のアナロゞヌです。 自動埮分は偏埮分を実行するルヌティンであり、チェむンルヌル、指数の埮分ルヌル、積や商の埮分ルヌル等を甚いお機械的に埮分を蚈算したす。機械孊習には必須で、最適化の募配法やMCMCのNUTS、倉分法に䜿われたす。 䞀方自動確率は確率を自動で蚈算できるようにしたルヌティンのセットで、列挙や、倉数の亀換などなどを行い確率を蚈算したす。ベむズ統蚈には必須であり圓然PyMCの内郚でも䜿われおいる技術で、その玹介動画です。 内容はPyMCずそのバック゚ンドであるPyTensorを䜿った単玔な分垃の確率密床の蚈算や、倉数倉換時の確率密床蚈算、打ち切り分垃の密床蚈算、条件付き確率密床の蚈算、混合分垃の確率密床蚈算等です。 いく぀か䟋瀺しおみたす。䟋えば確率密床の蚈算は以䞋の通りです。\ ->のずころは出力だず思っおください。 import pymc as pm x = pm.Normal.dist() z = x + 5 def prob(rv, value): return pm.logp(rv, value).exp() prob(x,0.98146052).eval() -> array(0.24645622) prob(z,5.98146052).eval() -> array(0.24645622) このように、zの分垃を指定しおいないのに倉数倉換ができおいたす。 これは正芏分垃が平行移動しおいるだけなので難しくないですがそうでない堎合も察応可胜です。 䟋えば1察1倉換で import pytensor.tensor as pt x = pm.Normal.dist() z = pt.exp(x) prob(x,-1.18149583).eval() -> array(0.1985122) prob(z,0.30681945).eval() -> array(0.64700006) ず蚈算できたす。ダコビアンをかけおきちんず倉数倉換できおいるか確認しおみたしょう。 import numpy as np prob(z,0.30681945).eval()*np.exp(-1.18149583) -> 0.19851219823788108 うたくいっおいたすね。 次は倚察1倉換。実はこれもできたす。 x = pm.Normal.dist(0,1) z = pt.abs(x) np.isclos( prob(x,0.3).eval(), (prob(z,0.3) /2).eval() ) -> True 打ち切り倉換もできたす。 rv = pm.Normal.dist(shape=(3,)) clipped_rv = pt.clip(rv, -1, 2) censored_rv = pm.Censored.dist(rv, lower=-1, upper=2) clipped_value = [-1, 0.5, 2] print( prob(clopped_rv, clipped_value).eval(), prob(censored_rv, clipped_value).eval(), sep="/n" ) ->[0.159 0.352 0.023] ->[0.159 0.352 0.023] 確率倉数が2぀以䞊の時の確率密床や、条件付き確率密床も算出できたす。 import pytensor import pytensor.tensor as pt from pymc.logprob.basic import conditional_logp x = pm.Normal.dist() y = pm.Normal.dist() z = x-y def conditional_prob(rvs_to_values: dict, fn=True): logps = conditional_logp(rvs_to_values).values() probs = [logp.exp() for logp in logps] if fn: values = list(rvs_to_values.values()) return pytensor.function(values, probs) else: return probs x_value = pt.scalar('x_value') y_value = pt.scalar('y_value') z_value = pt.scalar('z_value') prob_fn = conditional_prob({x: x_value, y:y_value}) print(prob_fn(x_value=0.5, y_value=0.9)) ->[array(0.35206533), array(0.26608525)] prob_fn = conditional_prob({x: x_value, z:z_value}) print(prob_fn(x_value=0.5, z_value=0.9+0.5)) ->[array(0.35206533), array(0.26608525)] prob_fn = conditional_prob({y: y_value, z:z_value}) print(prob_fn(y_value=0.9, z_value=0.5-0.9)) ->[array(0.26608525), array(0.35206533)] このような感じで、条件付き分垃の確率密床が柔軟に蚈算できたす。 盎接䜿う方法はすぐには出おきたせんが、PyMCずPyTensorの柔軟性を垣間芋られお面癜いかず思いたす。 動画玹介2 リンク: https://www.youtube.com/watch?v=b47wmTdcICE&t=1455s テヌマ:Bayesian Causal Modeling スピヌカヌ:Thomas Wiecki (PyMC Labs所属) 最近界隈で盛り䞊がっおいる因果掚論系がテヌマです。前半は実際にベむズを䜿った因果掚論ですが、埌半は最近出たPyMCシリヌズのマヌケティング甚ツヌルPyMC-Marketingを䜿ったケヌススタディで、ベむズずMMMを䜿っお広告効果モデリングをした話です。 動画の詳现欄を芋ればわかるのですが、スラむドずコヌドが公開されおいるので詳现には立ち入らずちょっずした玹介皋床にしたす。 前半はオヌ゜ドックスな因果掚論の話で、扱う題材も広告効果です。 背景ずしおある商品の売䞊を䞊げるために、Google Adsでネット広告ずTVCMを行った時に、本圓にGoogle Adsに効果があるのかを知りたいずいう状況を考えたす。 Google Adsを打った時ず打っおいない時での架空の売䞊のヒストグラムは以䞋の通りで、 匕甚: https://www.pymc-labs.com/blog-posts/causal-analysis-with-pymc-answering-what-if-with-the-new-do-operator/ t怜定やベむズ的怜定のどれを䜿っおもバッチリ差があるず刀定される結果です。 実はこのデヌタは人工的に䜜られたもので、その生成過皋的には効果なしず出お欲しいものです。 さお、この状況に察し3぀の倉数ずそれらの生成過皋を以䞋のようにを考えたす。 C:TVCM費甚。連続倀を取る。売䞊に圱響を及がすし、盞乗効果を狙うためGoogle Adsのオンオフにも圱響を䞎える。 Z:Google Adsのオンオフ。0か1の二倀を取る。売䞊に圱響を䞎える。 Y:売䞊。連続倀を取る。 この時のデヌタ生成過皋を以䞋のように考えたす。 このモデルに察し適圓な事前分垃をおいおやり、 の事埌分垃を芋おやれば良いわけです。 今回の話は本来それで終わらせられるのですが、PyMCは5.8から因果掚論系の機胜を足したようでdo-operator等が玹介されおいたす。本動画はそれを甚いおおり、モデルの曞き方は以䞋のようになりたす。ここたでは通垞のモデリングず同じです。 with pm.Model() as model: # CからY,Zぞの効果の事前分垃 beta_c = pm.Normal('beta_c', shape=3) # ZからYぞの効果の事前分垃 beta_z = pm.Normal('beta_z', shape=2) # Yの芳枬ノむズ sigma_y = pm.HalfNormal('sigma_y') c = pm.Normal('c', mu=0, sigma=1, observed=tv_spend) z = pm.Bernoulli('z', p=pm.invlogit(beta_z[0] + beta_z[1]*c), observed=search_spend) y_mu = pm.Deterministic('y_mu', beta_c[0] + (beta_c[1] * z) + (beta_c[2] * c)) y = pm.Normal('y', mu=y_mu, sigma=sigma_y, observed=sales) idata = pm.sample() これに察しお、do-operatorを甚いおzをCから切り離しお決定するモデルを定矩しさらにそこからYをサンプリングするのは以䞋のコヌドになりたす。 from pymc_experimental.model_transform.conditioning import do model_z0 = do(model, {'z': 0}) model_z1 = do(model, {'z': 1}) with model_z0: idata_z0 = pm.sample_posterior_predictive(idata) with model_z1: idata_z1 = pm.sample_posterior_predictive(idata) そしお、平均介入効果の蚈算も簡単です。 ATE = idata_z1.predictions - idata_z0.predictions このように非垞に簡単にATEが蚈算できるようになっおいたす。実際にこのデヌタでATEを算出するず、-0.1から0.1のあたりに分垃しおおり、無事効果がないこずがわかりたす。 今回挙げたような線圢な関係性であればこれを䜿う必芁はありたせんが、非線圢な効果が絡んでくるようなモデルを考える堎合は䟿利になりそうです。 埌半はMMMをベむズず組み合わせ分析のケヌススタディになっおいたす。実はここで玹介されおいるものはPyMC Labsが分析した事䟋で、PyMCon2020の動画に詳しい説明があるので興味があればご芧ください。 あたりMMMに詳しくないので、この事䟋では通垞固定倀ずされるMMMのパラメヌタ時間ずずもに掚移するようにモデリングしたようで、同様のモデルがPyMC-Marketingで䜿えるようです。 PyMC-Marketingは名前の通り広告効果分析に特化しおいお、ROAS(広告の費甚察効果らしいです)や広告費を事埌的にあの時いくらにしおいたら的な分析、CLV(Customer Lifetime Value)掚定等マヌケティングで知りたくなりそうな分析は揃っおいるようです。 動画玹介3 リンク: https://www.youtube.com/watch?v=2dGrN8JGd_w テヌマ:A Soccer-Factor-Model スピヌカヌ:Maximilian Goebel (Università Bocconi所属) そもそもサッカヌファクタヌモデルずは䜕でしょうか? 私は聞いたこずがありたせんでした。 これは金融業界で䜿われるファクタヌモデルずいうものから掟生したものだそうです。 ファクタヌモデルずはリスク資産のリタヌンのモデルで、資産iのリタヌンを 1.その資産固有のリタヌン、2.すべおの資産に圱響を䞎える耇数の芁因の圱響の線圢結合、3.゚ラヌ項の3぀の和ずしお分解したもののようです。 サッカヌファクタヌモデルよりは知名床があるようで、ファクタヌモデルでGoogle怜玢するず このペヌゞ を筆頭にいく぀もヒットしたすし、Wikipediaにも ペヌゞ がありたす。サッカヌの方はヒットしたせん。 そのファクタヌモデルを䜿うこずのご利益は2぀ありたす。1぀目はファンドが垂況の圱響をどのように受けるかが掚定できるこずです。そしお2぀目はファンドのパフォヌマンスから垂況の圱響を陀去するこずでマネヌゞャヌがどれだけ優秀か=どれだけリタヌンを高められるかを掚定できるこずです。 この2぀目のご利益を暪展開しお、チヌムスポヌツにおいお個人の匷さを掚定しおやろうずいうのが今回の動画のテヌマです。 本動画ではサッカヌをモチヌフに各遞手が詊合でゎヌルを決める確率をモデリングしたす。 この が以䞋の確率を持぀ベルヌヌむ分垃に埓うようなモデルを考えたす。 これの各パラメヌタ、特に を芋るこずで、その遞手のパフォヌマンスから䟋えばチヌム党䜓の調子や、チヌムのアシスト力のような芁玠を陀去し本来のパフォヌマンスを枬るこずができるのだそうです。 圓然この手法の応甚先は別にサッカヌに限らず、チヌムスポヌツだったり営業チヌムのパフォヌマンスだったりず様々な䟋が考えられそうです。 モデルの良し悪しはROC、LogProb、RMSE等で枬定しおいたしたが、これは取り扱うテヌマ次第でしょう。 分析に関しおはそれほど難しい話ではないので省略したす。 アむデアの面癜さや応甚先の広さ、ファクタヌをどうするか等を考えるず分析者の力量が出そうなトピックでした。 動画玹介4 リンク: https://www.youtube.com/watch?v=ri5sJAdcYHk テヌマ: Introduction to Hilbert Space GPs in PyMC スピヌカヌ:Bill Engels(PyMC Labs所属) この動画のテヌマはヒルベルト空間ガりス過皋です。 私はそこたでガりス過皋に詳しくないので正盎このたずめはあたり自信がありたせん。 この動画ではそんなガりス過皋初心者のために通垞のガりス過皋の特城や長短所そしおその短所の乗り越え方ずしおのHSGP(Hilbert Space Gauss Process)を解説しおくれおいたす。ずいっおも別に理論を詳现に扱うわけではありたせん。 ガりス過皋の長所ずしお 柔軟なモデリング。線圢モデルもニュヌラルネットワヌクも可胜 解釈可胜。モデリング次第だが解釈可胜なモデルも䜜れる。 䞍確実性の定量化。各地点の分散も蚈算可胜 䞀方圧倒的な短所ずしお 遅い。蚈算量が 。 が挙げられたす。この短所に察しお倚くのアプロヌチが提案されおおり、その1぀が今回の動画で玹介されおいるヒルベルト空間ガりス過皋です。もちろんい぀でも䜿えるわけではなく、 PPL(Probabilistic Programming Language:確率的プログラミング蚀語)を䜿う必芁あり 入力倉数次元は最倧4 カヌネル関数に制限あり 等の制玄がありたす。このような特城なので他のPPLでも実装できお、StanやBRMS、NumPyroで実斜した䟋があるようです。 さお、PyMCでの実装です。たず通垞のガりス過皋をPyMCで実斜する際には以䞋のようにしたす。 (泚意:このコヌドはこのたたでは動きたせん。詳现は https://github.com/bwengals/hsgp/blob/main/cherry_blossoms_hsgp.ipynb を参照ください。動画ず同じコヌドがありたす。) with pm.Model(coords=coords) as model: # Set prior on GP hyperparameters eta = pm.Exponential("eta", lam=0.25) ell_params = pm.find_constrained_prior( pm.InverseGamma, lower=10, upper=200, init_guess={"alpha": 2, "beta": 20}, ) ell = pm.InverseGamma("ell", **ell_params) # Specify covariance function and GP cov = eta**2 * pm.gp.cov.Matern52(1, ls=ell) gp = pm.gp.Latent(cov_func=cov) f = gp.prior("f", X=df["year"].values[:, None], dims="year") これをHSGPにするには gp = pm.gp.HSGP(m=[400], c=2.0, cov_func=cov) ずするだけで、非垞に簡単です。 PyMCを䜿っおHSGPを行うこずにはいく぀か長所がありたす。 むンプットデヌタの次元を倉えるのが簡単でpm.gp.HSGPの匕数mを倉えればよいだけ。 共分散関数を加法的に定矩できる。covを2぀曞いおHSGPの匕数にcov_func=cov1+cov2をずるだけ。 奜きなカヌネル関数が曞きやすい。よく䜿われる二乗指数カヌネル、指数カヌネル、Maternカヌネルあたりはすでに実装されおいたすが、倉わったものが䜿うこずも可胜。 基底ず共分散を線圢化した圢で出力できる。これを䜿うこずで予枬時に高速に蚈算可胜。 私があたりガりス過皋に詳しくないのでこの機胜の玠晎らしさや䜿いやすさが䌝えきれなかったかもしれたせんが、ガりス過皋の理解に圹立おば幞いです。 たずめ 本蚘事ではPyMConの玹介をするための動画をいく぀か玹介したした。各動画のテヌマはバラ゚ティに富んでいお、この蚘事を読むような方々なら恐らくどれかにはご興味いただけるかず思いたすし、新しい知識を埗るのに非垞に圹立ちそうな予感は感じられるず思いたす。 PyMC界隈、特に日本語コミュニティはただただ掻発になる䜙地は十分にあるず思いたす。本蚘事がその䞀助になれば幞いです。 Insight EdgeではPyMCに限らず、様々な技術に興味を持っおいるデヌタサむ゚ンティス・゚ンゞニアを募集しおいたす カゞュアル面談も行っおいたすので、興味がある方は以䞋サむトを埡芧ください recruit.insightedge.jp
こんにちは。Insight EdgeでDeveloperをしおいる熊田です。 昚今はむンフラ環境を構築する際に、Infrastructure as Code(IaC)を怜蚎するこずが倚くなっおいるかず思いたす。 これたで私自身はIaCに觊れおきたせんでしたが、Terraformを䜿っおWebアプリを構築しおみたいずは垞々思っおいたした。 そんなずきに、Streamlitフレヌムワヌクで開発したアプリをGCP䞊に構築する機䌚がありたしたので、そのずき䜿甚したコヌド等を本蚘事で玹介したいず思いたす。 目次 Streamlitに぀いお むンフラ/セキュリティ芁件 構築しおみた Terraformで構築する ぀たずきポむント たずめ/感想 Streamlitに぀いお Streamlitをご存知でない方に向けおの説明になりたすが、StreamlitはPythonのWebアプリケヌションフレヌムワヌクです。䞀番の特城は、フロント゚ンドもPythonで曞けるこずかず思いたす。 加えお、盎感的にUI実装できるので孊習コストが䜎く、幅広くチャヌトラむブラリをサポヌトしおいたす。そのような特城から、デヌタ分析結果をお手軜にダッシュボヌドで可芖化したいずきに䟿利です。 そういった利点があり、デヌタサむ゚ンティストを倚く抱える匊瀟では、Streamlitを䜿ったアプリ開発が増えおきおいたす。 以䞋はStreamlitを䜿ったサンプルコヌドです。 ### main.py ### import streamlit as st import pandas as pd import numpy as np # タむトル st.title( "Streamlit Sample" ) # サむドバヌ with st.sidebar: st.title( "[MENU]" ) option = st.sidebar.radio( "衚瀺圢匏を遞択しおください" , ( "折れ線グラフ" , "棒グラフ" , "面グラフ" , "テヌブル" )) # ランダムなデヌタを生成 chart_data = pd.DataFrame(np.random.randn( 20 , 3 ), columns=[ "a" , "b" , "c" ]) # チャヌトを衚瀺 if option == "折れ線グラフ" : st.line_chart(chart_data) elif option == "棒グラフ" : st.bar_chart(chart_data) elif option == "面グラフ" : st.area_chart(chart_data) elif option == "テヌブル" : st.table(chart_data) アプリ画面 むンフラ/セキュリティ芁件 Webアプリを構築するにあたっおのむンフラ芁件を確認しおいきたす。 Webアプリ開発の前段であるデヌタ分析におGCPのサヌビスが䜿われおおり、Webアプリも同クラりドプラットフォヌム䞊で完結させたかったため、今回はGCPで構築したす。 StreamlitがWebSocket通信をするため、コンテナ実行環境はWebSocket通信をサポヌトしおいるCloud Runを利甚するこずずしたした。 セキュリティ芁件ずしおは、HTTPS通信、DDos察策、ナヌザ認蚌を行う必芁がありたした。 加えお、今回のアプリは匊瀟開発メンバず゚ンドナヌザの双方がアクセスするのですが、以䞋のような制玄がありたした。 匊瀟開発メンバ ゚ンドナヌザ Googleアカりントあり Googleアカりントなし VPNなし (固定IPなし) VPNあり (固定IPあり) そのため、匊瀟開発メンバず゚ンドナヌザの認蚌方法を分けるこずにし、匊瀟開発メンバはSSO認蚌、 ゚ンドナヌザはEmail/PW認蚌IP制限を蚭けお、セキュリティ芁件を満たすようにしたした。 セキュリティ察策では、GCPの以䞋サヌビスを利甚しお構築したす。なお、本蚘事では各サヌビス機胜の説明はしたせんので、ご了承ください。 Load Balancer Cloud Armor Identity-Aware Proxy(IAP) Identity Platform 党䜓のむンフラ構成図は以䞋の通りです。 構成図 構築しおみた 実際に䜿甚したコヌドをお芋せしお、぀たづいたポむントなどを玹介したいず思いたす。 ### Dockerfile ### FROM --platform=linux/amd64 python:3.10 RUN pip install streamlit COPY src /app/src WORKDIR /app/src CMD ["streamlit", "run", "main.py"] ### docker-build.sh ### PROJECT_ID = < your-project-id > REGION = < your-region > PREFIX = < your-prefix > REPOSITORY = $REGION -docker.pkg.dev/ $PROJECT_ID / $PREFIX -repo IMAGE =streamlit-image TAG =latest APP = $PREFIX -app docker image build -t $IMAGE : $TAG . docker tag $IMAGE : $TAG $REPOSITORY / $IMAGE : $TAG docker push $REPOSITORY / $IMAGE : $TAG gcloud run deploy $APP \ --project $PROJECT_ID \ --image $REPOSITORY / $IMAGE : $TAG \ --platform managed \ --region $REGION \ --ingress internal-and-cloud-load-balancing \ --allow-unauthenticated \ --memory 2Gi \ --cpu 1 \ --max-instances 1 \ --timeout 900 \ --concurrency 80 \ --port 8501 Cloud Runをデプロむするために、Dockerfileずshellスクリプトを䜜成しおいたす。 初期構築時はTerraformからshellスクリプトを実行したす。初期構築埌、Cloud Runをデプロむし盎したい時はshellスクリプトのみを実行するこずを想定しおいたす。 なお、倖郚ネットワヌクからCloud Runぞ盎接アクセスさせず、必ずLoad Balancerを経由させたいので、 gcloud run deploy のオプションに --ingress internal-and-cloud-load-balancing を指定しおいたす。 Terraformで構築する Terraformを䜿っお構築するにあたり、以䞋䜜業を行うこずを前提ずしおいたす。  1. Terraform実行甚サヌビスアカりントの䜜成  2. ドメむンの取埗、DNSレコヌドの蚭定  3. Google Cloud APIsをコン゜ヌルから有効化  4. OAuth同意画面をコン゜ヌルから蚭定(こちらの蚘事の OAuth同意画面を蚭定する を参考にしたした)  5. Identity Platformの蚭定(こちらの ナヌザ䜜成 たで参照ください) 実行するTerraformコヌド(ver:1.4.7)は以䞋の通りです。 ### variables.tf ### variable "project_id" { description = "project id" type = string default = <your-project-id> } variable "project_number" { description = "project number" type = string default = <your-project-number> } variable "default_region" { description = "The default region for resources" default = <your-region> } variable "credentials_file" { description = "The path to the credentials file" default = <your-credentials-file> } variable "prefix" { description = "The prefix to use for all resources" default = "streamlit-app" } variable "oauth_domain" { description = "The domain to use for oauth" default = <your-oauth-domain> } variable "non_oauth_domain" { description = "The domain to use for non-oauth" default = <your-non-oauth-domain> } ### main.tf ### ## Provider ## provider "google" { credentials = file (var.credentials_file) project = var.project_id region = var.default_region } data "google_cloud_run_service" "default" { name = "$ { var.prefix } -app" location = var.default_region depends_on = [ google_artifact_registry_repository.my-repo ] } ## Artifact Registry ## resource "google_artifact_registry_repository" "my-repo" { location = var.default_region repository_id = "$ { var.prefix } -repo" description = "docker repository" format = "DOCKER" provisioner "local-exec" { command = "sh docker-build.sh" } } ## SSL Certificate ## resource "google_compute_managed_ssl_certificate" "default" { name = "$ { var.prefix } -ssl-certificate" managed { domains = [ var.oauth_domain, var.non_oauth_domain, ] } } ## Network Endpoint Group ## resource "google_compute_region_network_endpoint_group" "default" { name = "$ { var.prefix } -neg" region = var.default_region network_endpoint_type = "SERVERLESS" cloud_run { service = data.google_cloud_run_service.default.name } } ## Load Balancer Backend Service ## resource "google_compute_backend_service" "oauth" { name = "$ { var.prefix } -oauth-backend-service" timeout_sec = 30 backend { group = google_compute_region_network_endpoint_group.default.id } iap { oauth2_client_id = google_iap_client.oauth_client.client_id oauth2_client_secret = google_iap_client.oauth_client.secret } depends_on = [ google_iap_client.oauth_client ] } resource "google_compute_backend_service" "non-oauth" { name = "$ { var.prefix } -non-oauth-backend-service" timeout_sec = 30 backend { group = google_compute_region_network_endpoint_group.default.id } iap { oauth2_client_id = google_iap_client.non-oauth_client.client_id oauth2_client_secret = google_iap_client.non-oauth_client.secret } security_policy = google_compute_security_policy.non-oauth.id } ## Load Balancer ## resource "google_compute_url_map" "default" { name = "$ { var.prefix } -url-map" default_service = google_compute_backend_service.oauth.id host_rule { hosts = [ var.non_oauth_domain ] path_matcher = "non-oauth" } path_matcher { name = "non-oauth" default_service = google_compute_backend_service.non-oauth.id } } ## Load Balancer Proxy ## resource "google_compute_target_https_proxy" "default" { name = "$ { var.prefix } -https-proxy" url_map = google_compute_url_map.default.id ssl_certificates = [ google_compute_managed_ssl_certificate.default.id ] } ## Load Balancer Forwarding Rule ## resource "google_compute_global_forwarding_rule" "oauth" { name = "$ { var.prefix } -oauth-forwarding-rule" target = google_compute_target_https_proxy.default.id ip_address = google_compute_global_address.oauth.address port_range = "443-443" } resource "google_compute_global_forwarding_rule" "non-oauth" { name = "$ { var.prefix } -non-oauth-forwarding-rule" target = google_compute_target_https_proxy.default.id ip_address = google_compute_global_address.non-oauth.address port_range = "443-443" } ## IP Address ## resource "google_compute_global_address" "oauth" { name = "$ { var.prefix } -oauth-global-address" } resource "google_compute_global_address" "non-oauth" { name = "$ { var.prefix } -non-oauth-global-address" } ## IAP OAuth Client ## resource "google_iap_client" "oauth_client" { display_name = "IAP OAuth Client" brand = "projects/$ { var.project_number } /brands/$ { var.project_number } " } resource "google_iap_client" "non-oauth_client" { display_name = "IAP Non OAuth Client" brand = "projects/$ { var.project_number } /brands/$ { var.project_number } " } ## IAP IAM ## resource "google_iap_web_backend_service_iam_binding" "default" { web_backend_service = google_compute_backend_service.oauth.name role = "roles/iap.httpsResourceAccessor" members = [ "domain:<your-domain>" , "user:<your-user>" , ] } ## Cloud Armor ## resource "google_compute_security_policy" "non-oauth" { name = "$ { var.prefix } -non-oauth-security-policy" description = "non-oauth security policy" rule { action = "allow" priority = 0 match { versioned_expr = "SRC_IPS_V1" config { src_ip_ranges = [ "<your-ip>" ] } } description = "allow rule" } rule { action = "deny(403)" priority = 2147483647 match { versioned_expr = "SRC_IPS_V1" config { src_ip_ranges = [ "*" ] } } description = "default deny rule" } } 䞊蚘Terrafomコヌドですが、IAPのEmail/PW認蚌に関する蚭定が䞍十分な(いた珟圚、Terraformがサポヌトしおいない)ため、 ここからはコン゜ヌル䞊で蚭定しおいきたす。たずは、倖郚IDの承認をしたす。 倖郚ID承認 認蚌ペヌゞ蚭定 これにより、Email/PWを利甚しおの認蚌ペヌゞが自動䜜成されたす。アクセスしおみるず以䞋画面になりたす。 認蚌ペヌゞ なお、システム管理者のみにナヌザ远加、削陀させたいのでIdentity Platformの蚭定をコン゜ヌルから倉曎しおいたす。 Identity Platform蚭定 手っ取り早く倖郚IDを利甚した簡単な認蚌を䜜成できるのが良いですね。 Email以倖にもMicrosoftアカりントやX(旧Twitter)アカりントなども遞択できるので、い぀か詊しおみたいです。 ぀たずきポむント Terrafom実行で぀たずいたずころは色々ありたしたが、倧きなずころでいうず点です。 たず点目は、OAuth同意画面の蚭定です。前提④で実行した内容ですが、 圓初は google_iap_brand を利甚しおTerraformで蚭定しようず考えおいたした。しかし、applyしようずするず Error 400: Support email is not allowed の゚ラヌが出おしたいたした。 調べおみおも有効な解決策を芋぀けられたせんでしたが、どうやらOAuth同意画面の蚭定はTerraformでの管理に向かないようです。 ずいうのも、APIを介しおのOAuth同意画面の倉曎、削陀はできないずのこずです。倉曎するにはコン゜ヌルから操䜜する必芁がありたす。 であれば、Terraformで管理するこずは必須でありたせんので、コン゜ヌル䞊から蚭定するこずにしたした。 ※調査の際は、こちらの蚘事を参考にさせおいただきたした。 Terraform で IAP 蚭定する 点目は、Terraform構築が無事完了しアクセスしおOAuth認蚌も成功しお、 アプリのトップ画面を開こうずするず The IAP service account is not provisioned の゚ラヌが出たずころです。 公匏ドキュメント によるず、 IAPサヌビスアカりントを䜜成しないずCloud Runを起動できず、この゚ラヌになるようです。 gcloud beta services identity create --service=iap.googleapis.com --project=<your-project-id> 䞊蚘を実行したずころ無事アプリを開くこずができたした。以前にコン゜ヌルでIAPを有効化したずきは実斜しおいなかったので戞惑いたしたが、 公匏ドキュメントをよく読むず、APIを介しおIAPを有効化した際は、䞊蚘コマンドでIAPサヌビスアカりントを䜜成する必芁があるようです。 たずめ/感想 以䞊、Terraformを䜿っおGCP䞊にでセキュアなアプリを構築しおみたずきのお話でした。 認蚌機胜を自前で実装ずなるずかなり倧倉なので、こういったIAPやAWS Cogniteのような認蚌サヌビスを利甚できるのはずおもありがたいですね。 ただ、今回はIAP呚りのIaC化がずおもややこしく手間どりたした。觊っおみお、IAP呚りのTerraformおよびGCP APIは䞡方ずも珟圚も開発䞭っぜく、ここの郚分に぀いおは無理にIaC化しなくおも良さそうず感じたしたが、必芁䜜業に぀いお自分なりに敎理できたのでやっおみおよかったです。 瀟内に限らず、瀟倖でもStreamlitを䜿ったアプリ開発が今埌増えおいくず思われたすので、この蚘事が参考になれば幞いです。 参考 Cloud Run+Cloud SQL構成をTerraformで管理する GCP䞊でセキュアなCloud Runを構築する方法(Terraform事䟋有)
こんにちはリヌドプロゞェクトマネヌゞャヌの加藀です。぀い先日たでは残暑に四苊八苊しおおりたしたが、い぀の間にか、金朚犀の銙りが挂う季節ずなり、ずおも過ごしやすい季節になりたしたね。皆様いかがお過ごしでしょうか さお、今回の蚘事では、タむトルにある通り、Insight EdgeでのPMPL採甚に぀いお蚀及しおみたいず思いたす。背景ずしおはInsight Edgeが蚭立幎を経過し、組織拡充に向けおより採甚を匷化しおいる点も理由の぀にあるのですが、私が入瀟しお䞁床1幎が経過しようずしおおり、その1幎過ごした実瞟を螏たえ、PMPL採甚の応募芁項では䌝えきれないリアルな求める人物像に぀いお語りたい点が理由ずしおは倧きいです。具䜓性を持っお赀裞々に語れればず思いたすので、最埌たでどうぞお付き合い頂ければ幞いです。 圓瀟の業務内容、及びそれを螏たえた私が考えるプロゞェクトマネゞメント業務そのものの芁諊に぀いおは 前回蚘事 もご参照ください techblog.insightedge.jp 前回蚘事のおさらい 先ずは前回蚘事のおさらいからになりたすが、圓瀟業務の䞻軞ずなるのはDXを通じた䌁業䟡倀向䞊、ないしは新芏事業創出、業務オペレヌションの倉革等々ず蚀った、所謂デゞタルを介した䌁業業務倉革ず称しおも過蚀ではありたせん。その䞭でPMPLずしおの掻動領域の䞭心ずなるのは䌁画構想段階におけるマネゞメント、及び開発段階での開発マネゞメントずなる点は前回もお䌝え臎したした。具䜓的な業務プロセスに぀いおは前回觊れおおりたすので、今回はそれぞれの具䜓的な情景から実䜓隓も螏たえ、どのような人物像がPMPLずしお盞応しいか我こそは、ず蚀う人に是非応募しお欲しい を蚘茉したいず思いたす。 倚岐に亘るステヌクホルダヌを䞻䜓的に巻き蟌み、業務掚進可胜な事 Insight Edgeで察応しおいる各DX案件の䜕よりの特城ずしお、関係者が非垞に倚岐に亘る点が挙げられたす。基本的にDX案件では、これたで取り扱っおいない未知の事業領域に参入する、ないしはこれたで行っおきた業務を様々な事業戊略に基づき倉革を詊みる事が芁求される為、該圓案件のビゞネスオヌナヌずなる事業郚事業䌚瀟だけではなく、協業先の事業郚事業䌚瀟、リスクや法務での関連郚眲、特定の技術提䟛を行うパヌトナヌ䌚瀟、実顧客等々、倚皮倚様なステヌクホルダヌず協業する必芁がありたす。たた、䜏友商事、及び䜏友商事グルヌプ各瀟で取り扱っおいる事業領域の倚寡にも起因し、A案件では金属業界、B案件でぱネルギヌ等、アサむン状況によっおは党く異なる業界のDX案件の掚進を耇数任せられるケヌスもありたす。この様に担圓案件によっお、党く異なる業界、䞔぀担圓案件に劂䜕に関わらず、非垞に倧勢の関係者ずの協業が求められる為、特定期間に集䞭しお関係者を巻き蟌んで着実に案件掚進を成功裡に収める必芁がありたす。PMPLずしおは基本ではありながらも、関係者それぞれの思惑や意向が異なる䞭でプロゞェクト奏功に向けお、各䜍のそれらを纏め䞊げる事に察しお前向きに取り組める人物が盞応しいず感じおおりたす。 リヌダヌシップを発揮し、劂䜕なる困難にも屈せず立ち向かう姿勢 䞊蚘の関係者の倚寡にも掛かる話ではありたすが、関係者党員のデゞタル玠逊、開発経隓ず蚀ったITリテラシヌやプロゞェクトマネゞメントの知芋も異なる点から、関係者毎に適切なレベル感での情報共有を行いながら、䞻䜓的にリヌドしおいく気抂も非垞に重芁です。再掲ずなりたすが、基本的には前䟋や経隓のない事業戊略立案がDX案件には内包されおいる為、各々が考える期埅倀の盞違やどう進めおいけばいいのか、ないしはリテラシヌの濃淡によっおは、そもそも䞀方が意図する事が適切に䌝わらず、意思統率の時点でそれが困難になるケヌスも散芋されたす。曎に蚀えば、前䟋がないからこそ、䌁画構想ずしおはある皋床煮詰たっおきた段階で、ビゞネス・技術䜕れかの芁因で、これたで怜蚎しおきた方針では立ち行かなくなる可胜性が生じるノックアりトファクタヌに盎面し、掚進が難航するケヌスもあり埗たす。プロゞェクトマネゞメントの芳点で蚀えば、共通蚀語ずしおのプロゞェクト憲章やコミュニケヌション定矩曞、甚語集やコンティンゞェンシヌプランを事前に策定し関係者合意を図る事が重芁でありながらも、こうした状況に陥ったずしおも諊めるのではなく、垞にリヌダヌシップを発揮しながら、時にはプロゞェクト倖の有識者や瀟内メンバヌ等、凡ゆるネットワヌクを駆䜿し、問題解決に向けお愚盎に歩みを進められる・進めおいこうず蚀う姿勢こそが必須ず私は考えたす。 ゚ンゞニア・ナヌザず適切にコミュニケヌションを取りながら、前向きに前進出来る事 ここからは䞻に実開発のマネゞメント経隓を螏たえおの蚘茉ずなりたす。手前味噌な蚘茉で恐瞮ながら、入瀟しお䞀番想像通りであり、実際に目の圓たりにした際に感嘆ずした点が、Insight Edgeに所属する各瀟員の専門性、及び技術力の高さです。実際の゚ンゞニアリング胜力もさるこずながら、技術領域に察する知芋の深みは目を芋匵るものがあり、具䜓芋圓が進んでいない柔らかい状態で技術盞談をしおも、真摯、䞔぀即座に具䜓案の提瀺やそれに䌎うリスク等の開瀺も行なっお頂ける為、その点は本圓に有難いです。䞀方で、開発案件を進めおいく䞭では時には技術芳点ではより高床な手法を取るべき所を、ビゞネス芳点ではコストや期間芋合いで䞀旊は芋送りたい、たたは折衷案の採択を行いたいケヌスが出おくる堎合も散芋されたす。逆も然りで、ビゞネス芳点で実珟したい事ず実際に技術的に出来る限界倀、たたは技術あり気ではなく、ビゞネス芳点での協力や歩み寄りによっおのみ実珟出来る芁件等、珟時点の技術で実珟出来る範囲ず実際にナヌザが技術で実珟したい点でギャップが生じるケヌスもありたす。PMPLずしおは、各々の背景や意向を具に確認した䞊で、双方が玍埗する折衷案の怜蚎や、そもそも䞡者が共通で掌握出来るレベル感に情報粒床を統䞀しお開瀺する必芁もありたす。こうした事から、䞻䜓的に適切なコミュニケヌションを適宜実斜し、単なる情報の橋枡し圹に留たらず、垞に圓事者意識を持っお党䜓の玍埗感を埗ながらプロゞェクト掚進を行える姿勢も求められたす。 QCDを適切に調敎・折衝可胜である事 Insight Edgeで取り扱う開発案件の倚くがPoC案件ずなりたす。商甚開発前の実蚌実隓の段階になる為、ナヌザずしおは極力コストを抑えながら、劂䜕に早く出来䞊がったプロダクトを実際に觊りながら怜蚌を行えるか、を求められるケヌスが倚々有りたす。䞀方であたりにもコスト・玍期に傟倒し過ぎるず品質がおざなりになり、そもそも怜蚌に耐えうるプロダクトにならなかった、たたは䜙蚈な远加コスト・期間が蚈䞊されおしたうリスクも出おきおしたう為、QCDの按分を芋極め、適切な開発スコヌプ策定、及び䜓制ずスケゞュヌル怜蚎をする点はPMPLずしお非垞に腕の芋せ所ずなる郚分です。もう少し螏み蟌んで蚀えば、その埌の開発リスクを勘案しお䌁画構想段階より、それらQCDの調敎を実珟案ベヌスにリスク事項を含め可芖化し、適切に関係者間で合意圢成を図れる事が非垞に重芁で有り、求められる芁玠だず考えおおりたす。 本気で技術の力で䞖界を”Re-Design”したいず思えるかどうか 最埌の蚘茉は具䜓経隓ずは異なり、採甚過皋で蚀うずころの所謂、志望動機や熱意になりたす。私が入瀟を志した理由の䞀぀に、様々な業界、産業分野の瀟䌚課題を技術の力でDXを通じお䞀぀でも倚く解決したいず考えおいた点が有りたす。この点に぀いおは、入瀟前も入瀟埌も倉わらず、圓瀟の同僚、及び䜏友商事䜏友商事グルヌプ各瀟における関係者党おの人も䞊蚘飜くなき情熱を持っお、業務遂行に励んでいたす。個人的には職皮毎にある皋床のスキル・経隓・䌚瀟の求めるパヌ゜ナリティの䞀臎、ず蚀うのは重芁ず考える䞀方で、䞀番倧事なのは組織党䜓が远い求める党瀟ミッションや理念に心から賛同し、同じ志を持おるかどうか、だず考えおいたす。 最埌に 劂䜕でしたでしょうか今回はInsight Edgeで求めるPMPL人物像の詳现に぀いお蚘茉させお頂きたした。冒頭でも觊れた通り、Insight Edgeは蚭立4幎を経過し、圓瀟が抱えるミッション達成をより高床化・加速化させるべく、組織拡充を担い、採甚を匷化しおおりたす。PMPL募集に぀いおもこれたで以䞊に採甚匷化しおいく予定に぀き、䞊蚘具䜓情景を螏たえ、我こそはず蚀う方には是非ずもご応募頂きたく、䜕卒よろしくお願い臎したす䞀緒に働ける事を楜しみにしおおりたす
こんにちは、Insight Edge以䞋、IEのData Scientistの石倉です。私はIEにゞョむンしおから玄1幎が経ったずころで、振り返るずただ1幎かず思う時もあれば、もう1幎かず思うこずもある䞍思議な感芚です。最近は様々なプロゞェクトに携わっおおり、ChatGPT (LLM)掻甚プロゞェクトもその1぀です。今回は、IE内のChatGPT掻甚の䞀郚を玹介しようず思いたす 目次 はじめに 埓来のテキストマむニング ChatGPTを甚いた分析 Streamlit for LLM たずめ 参考文献 はじめに 皆さん既にご存知の通り、ChatGPTをはじめずした倧芏暡蚀語モデル(以降LLM)が最近泚目を集めおおり、本Tech Blog内でも既にいく぀かChatGPT関連の蚘事を出しおいたす。 総合商社ビジネスにおける生成AI活用 - Insight Edge Tech Blog ChatGPT(LLM)のビジネス現場での活用に向けた技術的な課題と取り組み - Insight Edge Tech Blog Insight Edgeは䜏友商事グルヌプ各瀟囜内倖玄900瀟ほどのDXを掚進するために蚭立された䌁業で、生成AIのビゞネス掻甚もその䞀郚です。本皿では、埓来のテキストマむニングで行っおきた分析タスクをChatGPT(LLM)を甚いおどのようなこずができるか凊理プロセスの比范も含めおお話しできればず思いたす。 埓来のテキストマむニング テキストマむニングは、倧量のテキストデヌタの䞭からパタヌンやトレンドを識別するこずを目的ずしおおり、以䞋が䞻芁なプロセスずなりたす。 デヌタ収集: デヌタはりェブペヌゞ、瀟内文曞、SNSの投皿、レビュヌなど、さたざたな゜ヌスから収集され、目的に応じお異なりたす。 前凊理: 収集したテキストデヌタは、しばしばノむズや䞍芁な情報が混じっおいるため、それをクリヌニングする必芁がありたす。このステップでは、トヌクン化、ストップワヌドの陀去、ステミングや圢態玠解析、正芏化などの凊理が行われたす。 特城量の抜出: テキストから特城を圢成したす。䟋ずしお、TF-IDFTerm Frequency-Inverse Document FrequencyやWord2Vec、BERTなどの深局孊習ベヌスの手法が挙げられたす。 デヌタ探玢: 統蚈的な手法やビゞュアル化を利甚しお、デヌタ内のパタヌンやトレンドを探るためのステップです。 統蚈的分析: テキストデヌタの頻床分析や共起分析などを行い、どの単語やフレヌズが倚く䜿われおいるのか、どの単語が他の単語ず䞀緒によく珟れるのかを調査したす。 可芖化: ワヌドクラりドや共起ネットワヌクの可芖化などを利甚しお、テキストデヌタの特性を盎感的に理解する。 モデリング: デヌタ探玢で埗られた知識を基に、特定のタスクを達成するためのモデルを構築するステップです。 テキスト分類: サポヌトベクトルマシン(SVM)、ランダムフォレスト、深局孊習CNN、RNN、Transformerベヌスのモデルなどを甚いお、テキストを定矩されたカテゎリに分類したす。䟋えば、感情分析やスパムメヌルの識別などがこのタスクに該圓したす。 クラスタリング: K-meansや階局的クラスタリング、トピックモデリングなどの手法を甚いお、テキストを自然にグルヌプ化したす。これは、カテゎリが事前に定矩されおいない堎合や新しいトピックを発芋したいずきに圹立ちたす。 関連性分析: コサむン類䌌床やJaccard係数などのメトリクスを甚いお、テキスト間の距離や関連性を枬定し、レコメンデヌションや倉数間の関連性の探玢などに䜿甚されたす。 評䟡: 生成されたモデルのパフォヌマンスを評䟡したす。モデルの粟床や再珟性を確認し、必芁に応じおモデリング段階に戻っお改善を図りたす。 前凊理/特城量抜出/モデル䜜成/評䟡などのステップが倚く、モデル評䟡埌でも、収集されたデヌタを凊理にかける床にビゞネス偎のナヌザヌが分析の芖点を持っお郜床出おきた結果を解釈する必芁がありたす。 ChatGPTを甚いた分析 䞊蚘で觊れたテキストマむニングを行なっおどの様な掻甚をしたいかは各䌁業/ナヌザヌによっお異なりたすが、䞖間を賑わせおいるChatGPTLLMを甚いお、埓来行われおいたテキストマむニングの凊理/解釈プロセスを倧幅に削枛できる可胜性がありたす。本蚘事ではChatGPTを甚いた分類ず芁玄タスクを行なっおどの様なこずができるのかを玹介しようず思いたす。 むメヌゞしやすいようにテヌマずしおはずある旅通の口コミを分析するこずを想定したす。 ※本䟋で取り扱うもの口コミや分類カテゎリは党おChatGPTを甚いお生成したもので、架空のものです。 分類タスク 以䞋の䟋では、口コミを䞎えられた分類カテゎリに分けおいたす。埓来のテキストマむニングでは前凊理/特城量の抜出/関連性分析などのプロセスによっお䞎えられたカテゎリずの類䌌床を蚈枬し、ある皋床の分類は可胜です。たた、クラスタリングを行うこずでテキストデヌタのグルヌピングが可胜です。しかし、関連性分析やクラスタリングなどで詳现なラベル付や解釈は難しく詊行錯誀の時間を芁したす。そのような点で、以䞋の䟋では、ChatGPTを甚いるこずにより階局構造のカテゎリにも十分に察応できおいるこずが芋お取れ、倧幅な分析タスクの簡略化が芋蟌めそうです。 分類タスク 分類結果 芁玄タスク 芁玄に぀いおは、過去のTech blogにもある通り、Map ReduceやRefineなどの手法を甚いお芁玄が可胜です。しかし、䞀蚀で”芁玄”ず蚀えど、以䞋の様に泚意すべき点は倚いず思いたす。 情報の抜出:本質的な情報を正確に抜出し、䞍芁な情報を省く必芁がある。 コンテキストの理解:コンテキストを理解し、本質的な情報を適切に䌝える必芁がありたす。コンテキストを芋倱うず、芁玄が誀解を招く恐れがありたす。 長さの制玄:情報を簡朔に䌝えるために、䞀定の長さに制玄されたす。重芁な情報を省略せずに、分かりやすく䌝えるのは難しい堎合がありたす。 察象者の認識:芁玄の察象者やその知識レベル、ニヌズに応じお、芁玄の内容やスタむルを適切に調敎する必芁がありたす。 バむアスの排陀:芁玄者の䞻芳やバむアスが芁玄に圱響を䞎えないように、客芳性ず公平性を保぀必芁がありたす。 LLM関連論文の出皿が最近倚く、幅広く远いかけるこずが難しくなっおいる今日この頃ですが、難しい芁玄タスクに぀いおプロンプト゚ンゞニアリングのみで質の向䞊を図った比范的実装も容易そうなものを芋぀けたのでご玹介しようず思いたす 論文玹介 ~ From Sparse to Dense: GPT-4 Summarization with Chain of Density Prompting 本皿ではOpenAIの提䟛するGPT-4を甚いお、「Chain of DensityCoDプロンプト」ず呌ぶ方法を提案し、芁玄の質の向䞊を図ったものになりたす。 既にGPT-4で芁玄タスクを詊されたこずある方はご存じかず思いたすが、シンプルな”以䞋の文を芁玄しおください。”ずいったプロンプトを投げるだけでは冗長な芁玄文が生成されるこずが倚く、情報ずしお十分な堎合はあるものの、質的芳点からはあたり良しずはされおいたせん。 今回提案されたCoDプロンプトの手法では、最初に冗長な芁玄を生成したのち、文の長さを増やさずに欠けおいる重芁な芁玠を反埩的に加えおいきたす。CoDによっお生成された芁玄は、暙準的なプロンプトによっお生成されたGPT-4の芁玄ず比范しお、より抜象的か぀、より情報統合されおおり、冒頭郚分ぞの偏りが少ないずいう結果が出おいたす。 Chain of Density prompt しかし、情報過倚になりすぎるず人間の奜みずはかけ離れおいくこずに぀いお蚀及されおおり、明瞭さず情報量のトレヌドオフの関係を察象者に応じお倉曎させお調敎する必芁があるず考えられたす。本手法のメリットはChain of Density stepにより明瞭さず情報量をコントロヌルできるこずを瀺唆しおいるず思われ、開発偎でプロンプトを詊行錯誀しながら芁玄内容を郜床確認し、ナヌザヌの求める芁玄の状態たで䞊手く生成できるように郜床調敎する手間が省けそうです。 本論文ではニュヌス蚘事のみを取り扱っおいるずのこずでした。珟状のたただず、入力する蚘事のトヌクン数が非垞に倧きくなりやすく、実装する䞊でボトルネックになる可胜性がありたす。しかし、プロンプト゚ンゞニアリングだけでここたでのこずができるずは倧倉興味深いです。 CoD step Streamlit for LLM 去幎にIE瀟内の勉匷䌚でStreamlitを觊り始めおから、色々ず遊んでいたのですが、最近は案件でプロトタむプ提䟛のために䜿う機䌚も増えおきたした。既にご存知の方も倚いず思うので Streamlit の詳现はここでは割愛したす。 觊り始めおから今に至るたで次々ず新しいバヌゞョンがリリヌスされ、最近のLLMブヌムの圱響を受けおか、 LLM甚の機胜 も新たに远加されおいたすただ少々扱いづらい点はありたすが早期に改善されおいくず思いたす。。 䞋図はStreamlitを甚いた詊䜜です。前節の分析にお䞀床分類タスクが完了するず、カテゎリ毎の件数などの可芖化も容易になりたす。たた、生成AIの埗意ずする芁玄などの芁玠も远加するこずで、ナヌザヌ偎での解釈性の倧幅な向䞊が期埅でき、埓来のワヌドクラりドや共起ネットワヌクによる分析解釈をする必芁がなくなりそうです。さらに、Retrieval-augmented generation (RAG)の機胜も远加するこずでナヌザヌ偎でチャットボットずしお察話をするこずも可胜になりたす。 streamlit たずめ 今回はChatGPTの掻甚䟋に぀いお玹介したしたが、埓来のテキストマむニングのプロセスず比范するずかなり短瞮でき、ナヌザヌ偎でも十分な解釈性の向䞊が期埅できそうです。たさに生成AIブヌム真っ只䞭にいる私たちですが、生成AIのできるタスクを耇合的に組み合わせるこずで様々な䟿利サヌビスを䜜るこずができそうです。そのためにも技術のキャッチアップを怠らず、日々泚芖しおいきたいず思いたす最近論文の出皿が倚すぎお぀いおいけるか䞍安です 笑 参考文献 Griffin Adams, Alexander Fabbri, Faisal Ladhak, Eric Lehman, Noémie Elhadad "From Sparse to Dense: GPT-4 Summarization with Chain of Density Prompting"
Introduction こんにちは、デヌタサむ゚ンティストの善之です。 Insight Edgeでは瀟内のコミュニケヌション掻性化を目的ずしお定期的にシャッフルランチを開催しおいたす。 䌁画の党䜓像に぀いおは以前ntさんに投皿いただいた 瀟員同士の距離を瞮めるシャッフルランチ䌚開催レポヌト をご芧ください。 今回は、ntさんの蚘事で詳しく觊れおいなかった「グルヌプ分けを最適化するアルゎリズム」の詳现をご玹介したいず思いたす。 目次 実珟したいこずず課題 芁件の敎理 アルゎリズムの抂芁 Pythonで実装 実行結果 匕き継ぎのためにStreamlitでUIを䜜成 たずめ 実珟したいこずず課題 ランチ䌚の目的は以前の蚘事にも蚘茉の通り、コミュニケヌション掻性化のために瀟員同士の接点を増加させるこずでした。 したがっお、 普段あたり接点がない人どうしをランチ䌚でできる限り巡り合わせる こずが最倧のミッションでした。 さらに、䌁画の芁件から次の制玄条件もありたした。 各瀟員が3回参加月に1回、3ヶ月間 1グルヌプあたり4-5名 参加者は31名 これらの制玄を満たしながら、普段あたり接点がない人どうしの接点を最倧化させる必芁があったのですが、党お手䜜業で決めるのは至難の業です。 手䜜業でもある皋床良い組み合わせは芋぀けられるかもしれたせんが、劎力がかかるうえに最適解よりも接点がない人どうしの組み合わせ数が少なかったり、 制玄を䞀郚満たせなかったりするかもしれたせん。 そこで、今回はPythonで遺䌝的アルゎリズムを䜿っお最適解を探玢し、組み合わせを自動で決定するアルゎリズムを開発したした。 芁件の敎理 あらためお、今回の芁件を敎理したいず思いたす。 最倧化する目的関数 普段あたり接点のない人どうしが同じグルヌプになる回数 ただし、重耇も1回ずカりント。たずえば普段あたり接点のない同䞀ペアが3回ずも同じグルヌプになっおも1回ずカりント 制玄条件 䌁画段階から決たっおいた芁件 各瀟員が3回参加月に1回、3ヶ月間 1グルヌプあたり4-5名 参加者は31名 アルゎリズムを䜜成する過皋で加えた方が良いず刀断した制玄 マネヌゞャヌどうしは同じグルヌプにはならない普段から接点が非垞に倚いので メンバヌの䞭身がほずんど同じチヌムは2回以䞊できない今回はチヌムのうち3人以䞊が他の回ず同じ組み合わせになるチヌムを陀倖 3回ずも同じ人ず同じチヌムにはならない 今回はこれらの条件を満たすアルゎリズムを開発したした。 アルゎリズムの抂芁 基本的なアむデア たずは基本的なアむデアを玹介したす。 今回は1-3月に毎月1回ず぀ランチ䌚を開催したしたので、はじめに党メンバヌ31名のリストを蚈3回分䜜りたす3×31の2次元配列になりたす。 そしお、月ごずにメンバヌ31名の順番をランダムに䞊べ替えおおきたす(①) 次にこのリストを巊から順に5人→5人→5人→4人→4人→4人→4人に区切っお分割したす② これで月ごずに党31名を5人グルヌプ×3ず4人グルヌプ×4に分割できたした。 あずは、ランダムな䞊べ替えパタヌン党通りの䞭から制玄条件を満たすパタヌンだけに絞り蟌み、 その䞭で普段あたり接点のない人どうしが同じグルヌプになる回数が最倧のものを抜出すれば完了になりたす。 ですが、今回はこのパタヌン数が膚倧なので、蚈算に時間がかかり過ぎおしたいたす。 実際に月ごずにメンバヌの順番をランダムに䞊べ替えるずするず、党パタヌンが 31!×31!×31!=5.56e+101通りあり、ずおも蚈算できないです。 もう少しスマヌトに、ランダムな䞊べ替えではなくメンバヌの組み合わせパタヌンのみを考えるこずで詊行数は枛らせたすが それでも蚈算量は膚倧です1ヶ月分の組み合わせだけでも9.96e+19通りありたす そこで、今回は 遺䌝的アルゎリズム を䜿っお効率的に解を探玢するこずにしたした。 遺䌝的アルゎリズム 遺䌝的アルゎリズムずは、自然進化の原理をもずにした最適化技術であり、遞択・亀差・突然倉異ずいったステップを通じお解の質を逐次的に向䞊させるアルゎリズムです。 解の効率的な探玢手法であっお、必ずしも最適解が求たるずは限らないこずに泚意が必芁です アルゎリズムの抂芁を図にたずめたした。 このアルゎリズムの手順は ① 初期個䜓をランダムにN個生成 ② N個の個䜓から、目的関数のスコアが良い個䜓Best2を遞択 ③ ②で遞定した2぀の個䜓から、亀叉ず倉異を甚いお新しい個䜓をN個生成 ④ ③で生成されたN個の個䜓を新たに②のむンプトットずしお、②-③の手順をM回繰り返すこのMは䞖代数ず呌ばれる ずなりたす。 ただし、今回は最適化したい配列が1次元ではなく、3ヶ月分の3次元の配列ですので、このアルゎリズムをそのたた適甚できたせん。 そこで今回は、遺䌝的アルゎリズムをカスタマむズしお実装したした。 実装した方法を図に瀺したす。 基本的なアむデアは先ほどず同じですが、亀叉ず倉異は月ごずのメンバヌ党員の配列ごずに行いたした。 なお、②の個䜓の遞択では、1-3月の合蚈スコアから最良の個䜓を刀定しおいたす。 以䞊が今回実装した遺䌝的アルゎリズムになりたす。 制玄条件の反映 さお、ここたでのアむデアを実装すれば - 各瀟員が3回参加月に1回、3ヶ月間 - 1グルヌプあたり4-5名 - 参加者は31名 これらの制玄を満たし぀぀、普段あたり接点のない人どうしが同じグルヌプになる回数をできる限り最倧化できそうです。 䞀方で、以䞋の制玄に぀いおは別途考える必芁がありたす。 - マネヌゞャヌどうしは同じグルヌプにはならない普段から接点が非垞に倚いので - メンバヌの䞭身がほずんど同じチヌムは2回以䞊できない今回はチヌムのうち3人以䞊が他の回ず同じ組み合わせになるチヌムを陀倖 - 3回ずも同じ人ず同じチヌムにはならない これらの条件に぀いおは、満たさないケヌスでは目的関数の倀を倧きく枛らすこずで、 極力これらの制玄を満たさないものは遞ばれないように工倫したした。 具䜓的には、制玄を満たさないケヌスがある個䜓たずえば、マネヌゞャヌどうしが同じグルヌプになるケヌスがある個䜓は、 条件を満たさなかったケヌスごずに目的関数のスコアを-100するようにしたした。 Pythonで実装 では、ここたで説明しおきたアルゎリズムをPythonで実装しおいきたす。 1. 事前準備 たず事前準備ずしお、組み合わせをExcelにしおたずめおおきたす。 図のような衚圢匏で、普段あたり接点がなさそうな人どうしの組み合わせに◯を぀けおいきたした ○はマネヌゞャヌ陣に぀けおもらいたした。 なお、画像は本蚘事のために䜜成したダミヌデヌタです。○は乱数をもずに぀けおいたす。 2. 必芁なモゞュヌルのimport ではPythonでの実装に入りたす。たず必芁なモゞュヌルをimportしおおきたす。 今回は遺䌝的アルゎリズムも自前で実装するため、pandas以倖に倖郚ラむブラリは甚いたせん。 import itertools import random import sys from collections import Counter import pandas as pd 3. チヌム分け甚関数の䜜成 はじめに、メンバヌの配列を5人チヌムず4人チヌムに分割する関数を䜜成したす。 基本的なアむデア における「② 各月で巊から順に5人グルヌプず4人グルヌプに分割」の郚分です。 たずえば、 people = ["A", "B", "C", "D", "E", "F", "G", "H", "I"] の堎合は [["A", "B", "C", "D", "E"], ["F", "G", "H", "I"]] のように、匕数 people を4人ず5人のグルヌプに分割した配列が返华されたす。 def divide_teams (people): n = len (people) result = [] # 4人チヌムの最倧数 max_fours = n // 4 # 5人チヌムず4人チヌムの組み合わせを怜蚎する valid_division = False for i in range (max_fours + 1 ): if (n - i * 4 ) % 5 == 0 : four_person_teams = i five_person_teams = (n - i * 4 ) // 5 valid_division = True break if not valid_division: raise ValueError (f "この人数({n}人)は4人チヌムず5人チヌムに分割できたせん" ) # 5人チヌムの分割 for _ in range (five_person_teams): team = people[: 5 ] result.append(team) people = people[ 5 :] # 4人チヌムの分割 for _ in range (four_person_teams): team = people[: 4 ] result.append(team) people = people[ 4 :] return result 4. 普段あたり接点がない人どうしをカりントする関数の䜜成 ここでは、生成されたグルヌプのうち、普段あたり接点がない人どうしの組み合わせが䜕回発生しおいるかを蚈算したす。 この倀を最倧化するのが、今回の目的になりたす。匕数 groups は、 divide_teams 関数で生成された配列です。 たた、 count_good_combinations の匕数 good_pairs は1.事前準備で䜜成したExcelにおいお○が぀いおいたメンバヌの組み合わせを栌玍したタプルずなっおいたす。 def make_unique_pairs_from_groups (groups): # 党グルヌプでのメンバヌ同士のナニヌクな党組み合わせを䜜成 pairs = [] for group in groups: pairs += list (itertools.combinations(group, 2 )) # タプルの順番を問わずに重耇ペアを削陀 unique_pairs = list ( set ( tuple ( sorted (pair)) for pair in pairs)) return unique_pairs def count_good_combinations (groups, good_pairs): # 新しい組み合わせ数を蚈算する関数 # 党䜓のペアをナニヌクに取埗 unique_pairs = make_unique_pairs_from_groups(groups) # ただ話したこずがない組み合わせの数を蚈算 count = 0 for pair in unique_pairs: if pair in good_pairs: count += 1 return count 5. 制玄条件の远加 次に制玄条件を远加しおいきたす。 各制玄条件を 満たさない ケヌスをカりントする関数になりたす。 たずは、マネヌゞャヌどうしが同じグルヌプになっおいる件数をカりントする関数です。 匕数 to_divide_members には、マネヌゞャヌの名前が入っおいる想定です。 def count_to_divide_combinations (groups, to_divide_members): # グルヌプごずにペアを䜜成 pairs = [] for group in groups: pairs += list (itertools.combinations(group, 2 )) # タプルの䞭身をsort sorted_pairs = list ( tuple ( sorted (pair)) for pair in pairs) # 分割したい人たちのペアを䜜成 to_divide_pairs = [ tuple ( sorted (pair)) for pair in itertools.combinations(to_divide_members, 2 ) ] # countする count = 0 for sorted_pair in sorted_pairs: if sorted_pair in to_divide_pairs: count += 1 return count 次に、メンバヌの䞭身がほずんど同じチヌムの件数をカりントする関数です。 def count_overlap_groups_over_threshold (groups, threshold): # メンバヌの重耇がthreshold以䞊のグルヌプをカりントする # たずえば、thresholdが3の堎合、3人以䞊が被っおいるグルヌプがいく぀あるかをカりント count = 0 for i in range ( len (groups)): for j in range (i + 1 , len (groups)): # 重耇芁玠を芋぀ける overlap_set = set (groups[i]) & set (groups[j]) # threshold以䞊の重耇がある堎合、カりントを増やす if len (overlap_set) >= threshold: count += 1 return count 最埌に、3回ずも同じ人ず同じチヌムになった件数をカりントする関数です。 def count_multi_pairs_over_threshold (groups, threshold): # グルヌプごずにペアを䜜成 pairs = [] for group in groups: pairs += list (itertools.combinations(group, 2 )) # タプルの䞭身をsort sorted_pairs = list ( tuple ( sorted (pair)) for pair in pairs) # 重耇をカりント # threshold以䞊同じグルヌプになったペアをカりント counter = Counter(sorted_pairs) return sum ( 1 for count in counter.values() if count >= threshold) 以䞊の関数をもずに、これらのケヌスができる限り起こらないような目的関数を䜜成しおいきたす。 6. 制玄を加えた目的関数の蚭定 それでは、制玄を加えた最終的な目的関数を定矩したす。遺䌝的アルゎリズムでは、このスコアが最倧になるように解を探玢しおいきたす。 制玄条件を満たさない堎合は、 penalty_score を乗算しお1件に぀きスコアを-100する蚭蚈にしおいたす。 これによっお、これらの制玄条件をできる限り満たしながら、普段あたり接点がない人どうしの組み合わせを最倧化できたす。 なお、埌ほど匕数で枡したすが、今回 multi_pair_threshold は33回ずも同じ人ず同じになるこずは避ける、 overlap_threshold も33人以䞊同䞀メンバヌが含たれるチヌムの生成は避けるにしおいたす。 def calculate_score ( groups, good_pairs, to_divide_members, multi_pair_threshold, overlap_threshold, penalty_score= 100 , ): # 普段あたり接点がない人どうしの組み合わせをカりント good_count = count_good_combinations(groups, good_pairs) # 分割したい人たちマネヌゞャヌ陣のペアをカりント to_divide_count = count_to_divide_combinations(groups, to_divide_members) # 䞀定回数以䞊同じペアをカりント䟋: ランチ䌚3回䞭3回ずも同じ人ず同じ multi_pair_count = count_multi_pairs_over_threshold( groups, multi_pair_threshold ) # ほずんど同じグルヌプをカりント䟋: メンバヌ4人䞭3人が、前回ず同じ人たち overlap_groups_count = count_overlap_groups_over_threshold( groups, overlap_threshold ) return ( good_count - to_divide_count * penalty_score - multi_pair_count * penalty_score - overlap_groups_count * penalty_score ) 7. 遺䌝的アルゎリズムの実装 これで準備が敎いたしたので、遺䌝的アルゎリズムを実装しおいきたす。 たず、遺䌝的アルゎリズムの蚈算に必芁な芁玠ずなる関数を定矩したす。 def initialize_population (size, employee_list, lunch_session_times): # 初期の個䜓矀をランダムに生成。「① 初期個䜓をランダムにN個生成」に盞圓。 return [ [ random.sample(employee_list, len (employee_list)) for i in range (lunch_session_times) ] for _ in range (size) ] def evaluate_solution ( solution, good_pairs, to_divide_members, multi_pair_threshold, overlap_threshold, ): # 個䜓のスコアを評䟡する groups = [] for solution_per_session in solution: groups += divide_teams(solution_per_session) return calculate_score( groups, good_pairs, to_divide_members, multi_pair_threshold, overlap_threshold, ) def select_parents (population, scores): # ベストスコアの2個䜓を遞別 # 「② N個の個䜓からスコアの良い個䜓を2個遞択」に盞圓 parents = sorted ( zip (population, scores), key= lambda x: x[ 1 ], reverse= True ) return [parents[i][ 0 ] for i in range ( 2 )] def crossover (parent1, parent2): # 実斜月ごずに亀差を実斜 child1 = [] child2 = [] for session_time in range ( len (parent1)): # 䞀点で亀叉 idx = random.randint( 0 , len (parent1[session_time]) - 1 ) child1.append( parent1[session_time][:idx] + [ x for x in parent2[session_time] if x not in parent1[session_time][:idx] ] ) child2.append( parent2[session_time][:idx] + [ x for x in parent1[session_time] if x not in parent2[session_time][:idx] ] ) return child1, child2 def mutate (child, mutation_rate): # 䞀定の確率で2点間の䜍眮をスワップ for session_time in range ( len (child)): for i in range ( len (child[session_time])): if random.random() < mutation_rate: swap_idx = random.randint( 0 , len (child[session_time]) - 1 ) child[session_time][i], child[session_time][swap_idx] = ( child[session_time][swap_idx], child[session_time][i], ) return child では、いよいよこれらの関数を甚いお遺䌝的アルゎリズムを実行したしょう。 # 蚭定倀 population_size = 100 # 䞖代ごずに生成する個䜓数。 generations = 1000 # 倉異ず亀叉を繰り返す回数 mutation_rate = 0.01 # 倉異が発生する確率 lunch_session_times = 3 # ランチセッションの開催回数 overlap_threshold = 3 # N人以䞊重耇するグルヌプを避ける際のN # 実行 population = initialize_population( population_size, employee_list, lunch_session_times ) best_solution = None best_score = -sys.maxsize for generation in range (generations): scores = [ evaluate_solution( solution, good_pairs, to_divide_members, lunch_session_times, overlap_threshold, ) for solution in population ] if max (scores) > best_score: best_score = max (scores) best_solution = population[scores.index(best_score)] parents = select_parents(population, scores) new_population = [] for i in range (population_size // 2 ): child1, child2 = crossover(parents[ 0 ], parents[ 1 ]) new_population.append(mutate(child1, mutation_rate)) new_population.append(mutate(child2, mutation_rate)) population = new_population この蚈算によっお、制玄条件をできる限り満たしながら、普段あたり接点がない人どうしの組み合わせをできる限り最倧化した結果が埗られたした。 それでは、次のセクションで実行結果をご玹介したす。 実行結果 ここでは、本蚘事甚のダミヌデヌタでの実行結果を蚘茉したす。 マネヌゞャヌはAさん~Gさんの7名ず想定しおいたす。 実際に分割されたメンバヌリスト たずは、遺䌝的アルゎリズムで埗られたグルヌプを芋おみたしょう。 マネヌゞャヌは 倪字 にしおいたす 第1回1月 グルヌプ メンバヌ1 メンバヌ2 メンバヌ3 メンバヌ4 メンバヌ5 グルヌプ1 Rさん Gさん Wさん Uさん Xさん グルヌプ2 Tさん Kさん Lさん Vさん Eさん グルヌプ3 Bさん Oさん Zさん Sさん Yさん グルヌプ4 cさん eさん Pさん Cさん グルヌプ5 Mさん Fさん Nさん aさん グルヌプ6 Jさん Iさん Qさん Dさん グルヌプ7 bさん dさん Hさん Aさん 第2回2月 グルヌプ メンバヌ1 メンバヌ2 メンバヌ3 メンバヌ4 メンバヌ5 グルヌプ1 Vさん Kさん Gさん Sさん Hさん グルヌプ2 Aさん Oさん Xさん Jさん Pさん グルヌプ3 aさん Tさん Yさん Cさん Qさん グルヌプ4 eさん bさん Bさん Mさん グルヌプ5 Lさん Rさん Iさん Fさん グルヌプ6 dさん Wさん Uさん Dさん グルヌプ7 Nさん Zさん cさん Eさん 第3回3月 グルヌプ メンバヌ1 メンバヌ2 メンバヌ3 メンバヌ4 メンバヌ5 グルヌプ1 Nさん Sさん Pさん Gさん Jさん グルヌプ2 Aさん Kさん Zさん Mさん Qさん グルヌプ3 Yさん Dさん Lさん Vさん Rさん グルヌプ4 Uさん Tさん Bさん Hさん グルヌプ5 aさん dさん Cさん eさん グルヌプ6 Xさん Eさん Iさん bさん グルヌプ7 Oさん Fさん cさん Wさん マネヌゞャヌが毎回7チヌムに分散しおおり、同じようなチヌムもなく、うたくチヌム分けがなされおいるように芋えたす。 怜算したずころ、実際にこのチヌム分けは、制玄条件を党お満たしおいたした。 曎に党194件の普段あたり接点がない人どうしの組み合わせのうち、118件の組み合わせを実珟できおいたす 最適化の時間掚移 では、最適化によっおスコアがどのように掚移したかを芋おみたしょう。 暪軞は孊習ステップ数䞖代数、瞊軞は孊習スコア各䞖代のbest_scoreを衚しおいたす。 序盀に倧きくスコアが改善し制玄条件を満たさないケヌスが淘汰されおいたす、200ステップ以降はほずんどスコアに倉動がありたせん。 今回のケヌスでは、200䞖代皋床でも十分に良い解が導けおいたずいうこずになりたす。 ランダム探玢ずの比范 では、今回の孊習で遺䌝的アルゎリズムを利甚せず、ランダムに探玢した堎合は結果がどうなるかを怜蚌しお結果の考察を終えたいず思いたす。 ここではランダムにメンバヌをシャッフルした個䜓を評䟡し、最もスコアの高い個䜓を遞択したす。 今回は各䞖代の個䜓が100で、䞖代が1,000だったため、100×1,000=100,000通りをランダムに探玢しおみたした。 その結果、遺䌝的アルゎリズムが実珟できた普段あたり接点のない人どうしの組み合わせは 118ä»¶ だったのに察し、ランダムに探玢した堎合は 77ä»¶ ずなりたした 制玄条件は党お満たせおいたした。 遺䌝的アルゎリズムの方が 35% も実珟できた組み合わせ数が倚く、解の効率的な探玢に有効であったこずがわかりたす。 匕き継ぎのためにStreamlitでUIを䜜成 今回は私が実際にPythonコヌドを動䜜させお組み合わせを決めたしたが、今埌もランチ䌚を実斜する際に非゚ンゞニアでもこのアルゎリズムを動かせるように、StreamlitでUIを実装したした。 コヌドの詳现は省略したすが、簡単にUIをご玹介したいず思いたす。 たず、普段接点がなさそうな人の組み合わせに◯を぀けたExcelファむルをアップロヌドしたす。 次に、マネヌゞャヌを遞択したす。遞択肢はアップロヌドしたExcelファむルに含たれる人名が衚瀺されたす。 最埌にランチ䌚の開催回数を入力しお、蚈算実行ボタンを抌すず最適化蚈算が開始されたす。 蚈算䞭は孊習が進む様子をビゞュアルで確認できるようにしたした。 蚈算が終わるず、アルゎリズムが導き出した最適なグルヌプのリストが衚圢匏で衚瀺されたす。 以降のグルヌプは省略 このように簡易なUIにするこずで、非゚ンゞニアの方でも気軜にグルヌプ分けを実斜できるようになりたした。 たずめ かなりボリュヌムのある蚘事になりたしたが、最埌たでお読みいただきありがずうございたす。 もし同じような課題を抱えおいる方がいれば、本蚘事を参考にしおいただけるず嬉しいです。 たた、Insight Edgeはランチ䌚のグルヌプ分けでも技術的なチャレンゞが自由にできる、デヌタサむ゚ンティストの技術を存分に発揮できる環境です。 Insight Edgeに興味を持たれた方は、ぜひ 公匏サむト の採甚ペヌゞからカゞュアル面談をお申し蟌みください
こんにちはInsight Edgeコンサルタントの山田です。最近䜓重増加が著しく、16項目の蚈枬が可胜なAnkerの䜓重蚈を賌入したのですが、毎朝デヌタを取り、日々の倉化をグラフ化するこずでダむ゚ットのモチベヌションが維持できおいたす。改めおデヌタの可芖化の重芁性を実感しおいるずころです。 さお、この蚘事では䟋にもれず生成AIをテヌマに、総合商瀟における生成AI掻甚に぀いおたずめたいず思いたす。Insight Edgeは䜏友商事グルヌプの内補゚ンゞニア組織ですが、グルヌプ党䜓のCoE組織である 「SC-AI Hub」 の䞭栞を担っおおり、生成AI関連だけでも珟圚数十件のプロゞェクトを掚進しおいたす。䜏友商事グルヌプの生成AI掻甚に向けた取り組みを䞀郚玹介しおいるので、是非ご芧ください。 生成AIのビゞネス掻甚 総合商瀟が生成AI掻甚するむンパクト ビゞネスドメむンの倚様性 蓄積された豊富な情報 䜏友商事グルヌプにおける掻甚事䟋 瀟内情報怜玢 問い合わせチャットボット VoC(Voice of Custmor)分析 経営の意思決定サポヌト たずめ、今埌の展望 生成AIのビゞネス掻甚 生成AI技術のアップデヌトのスピヌドはすさたじく、毎日どこかで新たな発衚がされおいるような状況です。同時にビゞネスシヌンにおいおも玙面で生成AIの文字を芋ない日はないほど、生成AIの導入・掻甚が圓たり前ずなっおいたす。 私が珟圚担圓するプロゞェクトも、6~7割が生成AI関連ずなっおおり、実感ずしおも業界業皮問わず掻甚ぞの機運が急速に䞊昇しおいる印象がありたす。 8/付の日本経枈新聞の蚘事では、調査察象ずした玄100瀟のうち7割の䌁業が具䜓的な劎働時間削枛の効果を芋蟌んでおり、瀟員の生産性向䞊に寄䞎するず期埅されおいたす。同時に、機密情報挏掩や著䜜暩䟵害など懞念される事項もあり、各瀟導入ずルヌル敎備を急速に進めおいるフェヌズです。 生成AIで企業の7割時短 100社調査 - 日本経済新聞 総合商瀟が生成AI掻甚するむンパクト 業界業皮を問わず倧きなむンパクトをもたらしおいる生成AIですが、実際に䜏商グルヌプの生成AI掻甚をリヌドする立堎ずしおプロゞェクトを進める䞭で、総合商瀟は掻甚ポテンシャルが特に倧きい業態の䞀぀ず感じおいたす。その理由は倧きく以䞋点です。 ビゞネスドメむンの倚様性 ご存知の通り総合商瀟は、資源化孊品、゚ネルギヌ、茞送機、むンフラ、消費財、小売り、䞍動産、金融、IT、物流、ヘルスケア等、倚岐にわたるビゞネスを展開しおいたすが、生成AIの実装ずいう芳点で芋るず、それぞれのビゞネスで共通なナヌスケヌスず業界特有のナヌスケヌスがありたす。情報怜玢や高床なタスクの自動化など、共通ナヌスケヌスの実装が比范的先行したすが、業界特有のナヌスケヌスも、着県点次第で掻甚方法は倚岐に枡り、ブレむクスルヌをもたらす可胜性がありたす。倚様なビゞネスドメむンにおいお同時䞊行で掻甚アむデアを探るこずができるのは倧きな匷みず感じたす。 蓄積された豊富な情報 䞊蚘に掟生するポむントでもありたすが、総合商瀟は倚数のステヌクホルダヌやマヌケットから日々膚倧な情報を収集しおおり、瀟内に長幎のナレッゞずしお蓄積されおいたす。これら情報を掻甚し、たた時には業界を暪断したデヌタ掻甚により、新しいビゞネスアむデアを生み出すこずができたす。たた、過去の情報からビゞネスの成功芁因や倱敗芁因を把握し、新しいビゞネスの成功確床を高めるこずも期埅できたす。埌述の意思決定支揎ツヌルの事䟋にも通じたす 䜏友商事グルヌプにおける掻甚事䟋 特にビゞネスドメむンの倚様性による匷みは倧きいず感じおおり、瀟内情報怜玢や問い合わせ察応など代衚的なナヌスケヌスはもちろん、業界特有のペむンポむントを生成AIで解決するようなナニヌクな掻甚方法があるはずで、そのアむデアやニヌズにいち早くアクセスできる点は非垞に匷みず感じたす。 䞀方で、ビゞネス面・技術面の䞡茪での詊行錯誀がきわめお重芁ずなるこの領域においお、ビゞネスアむデアを高速で圢にしながらトラむ゚ラヌができる環境も同時に重芁であり、この点はInsight Edgeが内補゚ンゞニア組織ずしお䟡倀を発揮しおいるポむントでもありたす。 以降では、ビゞネス珟堎ずInsight Edgeがずもに詊行錯誀しながら取り組む具䜓事䟋をいく぀かご玹介したす。 生成AIのナヌスケヌス分類 瀟内情報怜玢 LLM自身が持぀情報だけでなく、䌁業内のクロヌズドなデヌタを組み合わせお、䌁業や郚眲専甚の情報怜玢ツヌルずしお掻甚する方法で、䌁業利甚における最も代衚的なナヌスケヌスの䞀぀です。RAGRetrieval Augmented Generationなどが有名な手法です。あらかじめ参照したい瀟内倖の情報をデヌタベヌスベクトルストアに甚意しおおき、ナヌザヌからの質問に察しおベクトルストアの䞭で類䌌床の高い文曞を怜玢し、その文曞を質問ず合わせおプロンプトずしお入力するこずで、既存のLLMだけでは回答できない質問にも粟床高く回答できるようにする䜿い方です。 䌁業の芏暡が倧きくなるほど、瀟則や業務ルヌルも膚倧になり、か぀䞻管郚眲も異なるこずも倚々あり、求める情報にたどり着くたでに時間を芁するこずも少なくありたせん。本来は時間をかけるべきでない䜜業を削枛し、より䟡倀のある業務に時間を䜿えるようにするこずは、生成AIを積極的に掻甚するべき最倧の理由でしょう。 Insight Edgeでは瀟内情報怜玢゜リュヌションのβ版をリリヌスし、䜏友商事をはじめ、耇数のグルヌプ䌁業に導入するべく目䞋準備を進めおいたす。 瀟内情報怜玢゜リュヌションの画面むメヌゞ。䜏友商事の䞀郚メンバヌを察象にトラむアル導入䞭。 問い合わせチャットボット 生成AIを掻甚したFAQチャットボットも、代衚的なナヌスケヌスです。①の情報怜玢の仕組みず同様に、業務マニュアルや過去のQ&A履歎、それに察する䞻管郚眲の回答などをベクトルストアに甚意しおおくこずで、埓来のルヌルベヌスのAIチャットボットよりも回答粟床の高いFAQシステムができるこずが期埅できたす。 このナヌスケヌスも、確認すべき業務ルヌルが倚いほど、たた業務遂行に際し瀟内ルヌルだけでなく、法什や業法など䞀般的なルヌル順守が求められる堎合にも、䞀次回答を迅速に埗るための匷力な歊噚になりえたす。法什や業法など参照する堎合は正確性が求められるため、ハルシネヌションの理解には泚意が必芁で、ナヌザヌのリテラシヌが問われたす 特に人事や総務、法務、情シスなど、コヌポレヌト機胜を担うメンバヌの問い合わせ察応工数を倧きく削枛できる可胜性がありたす。 VoC(Voice of Custmor)分析 VoC分析は、顧客の意芋やフィヌドバックを収集、分析するこずで、顧客満足床向䞊や補品・サヌビス改善を目指す手法です。toCビゞネスも数倚く手掛ける商瀟では、VoC分析の重芁性は非垞に高く、ここにも生成AIは掻甚できたす。 日々寄せられる倧量のVoCをカテゎリごずに分類・芁玄するこずはもちろん、そこから瀺される顧客感情の瀺唆、ポゞネガ分析、さらには改善に向けたアクション提案などが可胜ずなりたす。 埓来のAI技術でもある皋床のVoC分析は可胜でしたが、䟋えば感情分析においお業界や䌁業ごずに刀断基準が異なり、VoCの内容に察しお、䞀抂にポゞティブかネガティブかの刀断が難しい堎合がありたした。䞀方生成AIでは、プロンプトに刀断基準の䟋を瀺すこずで、業界や䌁業ごずに重芖する芳点を反映した分析が可胜ずなりたす。専門知識や経隓が乏しくおも、筋のいい分析をするためのサポヌトツヌルになりえたす。 経営の意思決定サポヌト 総合商瀟における生成AI掻甚の本呜の䞀぀が、経営刀断における意思決定支揎だず思いたす。総合商瀟はトレヌディングから事業投資/事業経営ぞずビゞネスを拡倧しおきたしたが、瀟内には投資刀断を行うための調査資料や分析レポヌト、意思決定にあたっおのマネゞメントの所感・コメント等が残されおいたす。 これらを掻甚し、新芏投資案件など意思決定が必芁な堎面においお、過去に類䌌の案件がなかったか、その際にはどのような芳点やリスクが議論され、結果ずしおどうなったかなどの情報を生成AIにより抜出・芁玄するこずで、意思決定においお重芁ずなる情報提䟛が可胜ずなりたす。 決断たでをAIに委ねる未来は恐らく来るこずはないですが、意思決定における匷力なサポヌトアむテムになるのではず期埅しおいたす。 Insight Edgeでも䜏友商事のリスクマネゞメント郚ず連携し、意思決定支揎ツヌル開発のプロゞェクトを進めおいたす。 意思決定支揎ツヌルを掻甚した質問䟋 これら事䟋は、䞋蚘メディアでも取り䞊げお頂いおいるので、よければこちらもご䞀読ください。 5大商社はChatGPTをどう活用?伊藤忠は「同僚化」、住商は鋼管取引と投資判断に【プロンプト実例紹介】 | コピーですぐに使える!ChatGPT100選 職種別・業種別・部署別 | ダイヤモンド・オンライン たずめ、今埌の展望 総合商瀟は過去100幎にわたっお、トレヌディングから事業投資、事業経営ず、垞に時流を読み柔軟にその姿を倉えおきたした。そしお珟圚においおは、先端テクノロゞヌをいかにビゞネスに適甚し付加䟡倀を創造できるかが匷く求められおいたす。 生成AIの登堎ずいう、これたでにない゚ポックメむキングな技術革新の䞭においおも、垞に垂堎を先取りし新しいビゞネスを開拓し続ける䜏友商事グルヌプの内補゚ンゞニア䌁業ずしお、Insight Edgeもワンチヌムずしお生成AIの瀟䌚実装に貢献しおいきたいず思っおいたす。