G-gen ã®çŠäºã§ããGoogle Workspace Events API ãš NotebookLM Enterprise API ãå©çšããŠãGoogle ãã©ã€ãäžã®ãã¡ã€ã«æäœãããªã¬ãŒã« NotebookLM ã®ããŒãããã¯ç®¡çãèªååããã¢ãŒããã¯ãã£ãšããã®å®è£
äŸã玹ä»ããŸãã ã¯ããã« åœèšäºã®æŠèŠ NotebookLM Enterprise ãšã¯ Google Workspace Events API ãšã¯ å
責äºé
å®çŸãããããš ç®çãšåŠçã®å
容 æ§æå³ïŒTo-beïŒ æ§æå³ïŒCan-beïŒ ã€ãã³ãåŠçæ¹åŒã«ã€ã㊠äºåæºå ããããããŒãã¬ãã¥ãŒããã°ã©ã ãžã®ç»é² åçš®APIã®æå¹å ãµãŒãã¹ã¢ã«ãŠã³ãã®æºåãšæš©éç§»è² ãµãŒãã¹ã¢ã«ãŠã³ãã®äœæ ãã¡ã€ã³å
šäœã®å§ä»»ã®èšå® Pub/Sub ã®æºå ãµã³ãã«ã¢ããªã±ãŒã·ã§ã³ ãã¡ã€ã«æ§æ ã©ã€ãã©ãªã®ã€ã³ã¹ããŒã« ç°å¢å€æ°ã®èšå® Google Workspace Events APIã§ã€ãã³ããè³Œèª ã€ãã³ããåŠçã NotebookLM ãæäœ åäœç¢ºèª ã¯ããã« åœèšäºã®æŠèŠ NotebookLM ã¯ãçµç¹ã®ãã¬ããžæŽ»çšã«éåžžã«åŒ·åãªããŒã«ã§ãããéçšã«ãããŠèª²é¡ããããŸããäŸãã°ãäžåºŠããŒãããã¯ã«ç»é²ãããœãŒã¹ã¯ãå
ã®ãã¡ã€ã«ãæŽæ°ãããŠãèªåã§ã¯åæãããŸããããã®ãããåžžã«ææ°ã®æ
å ±ãåæ ãããã«ã¯ãæäœæ¥ã§ããŒãããã¯å
ã®ãœãŒã¹ã®æŽæ°ãå¿
èŠã§ãããŸããæ°ãããã¬ããžã®ãããã¯ããšã«ããŒãããã¯ã®äœæããœãŒã¹ã®è¿œå ãæäœæ¥ã§è¡ãã®ã¯ãéçšè² è·ãé«ããªããã¡ã§ãã åœèšäºã§ã¯ããããã®èª²é¡ã解決ãããããGoogle ãã©ã€ãäžã®ãã¡ã€ã«ãæŽæ°ãããšãé¢é£ãã NotebookLM Enterprise ã®ããŒãããã¯ãèªåã§äœæããããœãŒã¹ãæ°èŠè¿œå ã»æŽæ°ãããä»çµã¿ãšå®è£
æ¹æ³ã解説ããŸãã ãã®èªååãå®çŸããããã«ã NotebookLM Enterprise API ãšãçŸåšããããããŒãã¬ãã¥ãŒçãšããŠæäŸãããŠãã Google Workspace Events API ã䜿çšããŸãã NotebookLM Enterprise ãšã¯ NotebookLM Enterprise ã¯ãçµç¹ã®å
éšæ
å ±ïŒããã¥ã¡ã³ããããŒã¿ïŒããœãŒã¹ãšããŠäœ¿çšãããAIæèŒã®èª¿æ»ã»äœæã¢ã·ã¹ã¿ã³ãã§ããç¡åçã® NotebookLM ããGoogle Workspace ã«ä»å±ãã NotebookLM Pro ãšã¯ç°ãªããEnterprise ç㯠Google Cloud ãããžã§ã¯ãå
ã§æå¹åãããããé«åºŠãªçµç¹å©çšãåæãšããæ©èœãæäŸãããŸãã ç¡åçã Pro çãšã®è©³çŽ°ãªæ©èœæ¯èŒã«ã€ããŠã¯ã以äžã®èšäºããåç
§ãã ããã blog.g-gen.co.jp Enterprise çã®ç¹çãã¹ãç¹ãšããŠããŸãé«åºŠãªID飿ºãšã¢ã¯ã»ã¹å¶åŸ¡ãæããããŸããGoogle Workspace ã¢ã«ãŠã³ãã ãã§ãªããMicrosoft Entra ID ã Okta ãªã©ã®ãµãŒãããŒãã£IDãããã€ããŒãšã®é£æºã«å¯Ÿå¿ããŠãããIAM ã䜿çšããã¢ã¯ã»ã¹å¶åŸ¡ãå¯èœã§ãã ãŸããVPC Service Controls ã«ãã匷åºãªã»ãã¥ãªãã£å¢çãèšå®ã§ããã»ãããµããŒããããã¡ã€ã«åœ¢åŒãšã㊠Microsoft WordãPowerPointãExcel ã远å ãããŠããŸãã ãããŠæãéèŠãªç¹åŸŽãšããŠãEnterprise çã¯å¯äž API ãæäŸãããŠãããåœèšäºã§ç޹ä»ãããããªå€éšã·ã¹ãã ãšã®é£æºãæ¥åèªååãå®çŸã§ããŸãã åè : What is NotebookLM Enterprise? Google Workspace Events API ãšã¯ Google Workspace Events API ã¯ãGoogle Workspace äžã§çºçããã€ãã³ãïŒäŸ: Google ãã©ã€ãã§ã®ãã¡ã€ã«ã®äœæã»æŽæ°ãGoogle Chat ã®ã¹ããŒã¹ãžã®ã¡ãã»ãŒãžæçš¿ãªã©ïŒããµãã¹ã¯ã©ã€ãïŒè³ŒèªïŒããããã® API ã§ãã ã€ãã³ããçºçãããšãéç¥ãšã³ããã€ã³ãã§ãã Cloud Pub/Sub ããã㯠ã«å¯ŸããŠãªã¢ã«ã¿ã€ã ã«è¿ã圢ã§éç¥ãéä¿¡ãããŸããããã«ãããGoogle Workspace äžã®ã¢ã¯ãã£ããã£ãããªã¬ãŒãšããã¢ããªã±ãŒã·ã§ã³é£æºãèªåååŠçãå®è£
ã§ããŸãã åœèšäºå·çæç¹ïŒ2025幎10æïŒã§ã¯ãããããããŒãã¬ãã¥ãŒçãšããŠæäŸãããŠããŸãããããã£ãŠãåœèšäºã§è§£èª¬ããå
容ã¯äžè¬æäŸïŒGAïŒã®éã«å€æŽãããå¯èœæ§ãããããšãäºããäºæ¿ãã ããã åè : Google Workspace Events API æŠèŠ åè : Google Workspace ããããã㌠ãã¬ãã¥ãŒ ããã°ã©ã å
責äºé
åœèšäºã§ç޹ä»ããããã°ã©ã ã®ãœãŒã¹ã³ãŒããæ§æãã¡ã€ã«ã¯ããèªèº«ã®è²¬ä»»ã®ããšã䜿çšãåŒçšãæ¹å€ãåé
åžããŠæ§ããŸããã ãã ããåãœãŒã¹ã³ãŒããåå ã§çºçããäžå©çããã©ãã«ã«ã€ããŠã¯ãåœç€Ÿã¯äžåã®è²¬ä»»ãè² ããŸããã å®çŸãããããš ç®çãšåŠçã®å
容 åœèšäºã§å®è£
ããã·ã¹ãã ã¯ã ãç¹å®ã® Google ãã©ã€ããã©ã«ããš NotebookLM Enterprise ã®ããŒãããã¯ãåæãããã ããšãç®çãšããŠããŸãã ãŠãŒã¶ãŒã®æäœãããªã¬ãŒã«ã·ã¹ãã ãã©ã®ããã«èªååŠçãè¡ãããå
·äœçãªæµãã以äžã«ç€ºããŸãã åŠçã®æµã ãŠãŒã¶ãŒã®æäœïŒGoogle ãã©ã€ãïŒ ã·ã¹ãã ã®èªååŠçïŒNotebookLM EnterpriseïŒ 1 NotebookLM-TopicA ãã©ã«ããäœæããæåã®ãã¡ã€ã«ã远å ãã NotebookLM-TopicA ããŒãããã¯ãæ°èŠäœæãã远å ããããã¡ã€ã«ããœãŒã¹ãšããŠç»é²ãã 2 NotebookLM-TopicA ãã©ã«ãã«2ã€ç®ã®ãã¡ã€ã«ã远å ãã æ¢åã® NotebookLM-TopicA ããŒãããã¯ã«ã2ã€ç®ã®ãã¡ã€ã«ããœãŒã¹ãšããŠç»é²ãã 3 NotebookLM-TopicA ãã©ã«ãå
ã®æ¢åãã¡ã€ã«ãæŽæ°ãã æ¢åã® NotebookLM-TopicA ããŒãããã¯å
ã®å¯Ÿå¿ãããœãŒã¹ãåé€ããæ¹ããŠãœãŒã¹ãšããŠç»é²ãã ãã®ããã«ããŠãŒã¶ãŒã¯ Google ãã©ã€ãäžã§ãã¡ã€ã«ã管çããã ãã§ãæèããããšãªã NotebookLM ã®ãã¬ããžãåžžã«ææ°ã®ç¶æ
ã«ä¿ã€ããšãã§ããŸãã ãã ããä»åã¯ããŒãããã¯ç®¡çèªååã®æ§ææ€èšã®ãã£ãããäžããããã®èšäºã§ããæ¬èšäºã§æç€ºãããµã³ãã«ã¯åºæ¬åäœã«çãŸããããå®éã®éçšã§ã¯ä»¥äžã®ãããªèæ
®ãå¥éå¿
èŠãšãªããŸãã Google Workspace ã€ãã³ãã®ãµãã¹ã¯ãªãã·ã§ã³æŽæ° ããŒãããã¯ã®ãœãŒã¹ã«ç»é²ãããã¡ã€ã«çš®é¡ã®å€å® ããŒãããã¯ã®ãœãŒã¹ã«ç»é²ãããã¡ã€ã«ã®ç§»åãåé€ã®ãã³ããªã³ã° åæåŠçã®äžã§åããœãŒã¹ã«å¯Ÿããã€ãã³ããè€æ°çºçããŠããå Žåã¯åæåŠçã1åã«ãŸãšãã äŸå€åŠçããªãã©ã€åŠç ...ãªã© æ§æå³ïŒTo-beïŒ ä»åå®è£
ããèªååã·ã¹ãã ã¯ãè€æ°ã® Google Cloud ãµãŒãã¹ã飿ºãããããšã§å®çŸããŸãã以äžã«ãæ¬çªéçšãæ³å®ãããããã¹ãã¢ãŒããã¯ãã£ãã®å
šäœå³ãšãåã³ã³ããŒãã³ãã®åœ¹å²ã解説ããŸãã æ§æå³ïŒTo-beïŒ ã³ã³ããŒãã³ã åœ¹å² Google ãã©ã€ã ãŠãŒã¶ãŒãããŒãããã¯ã®ãœãŒã¹ãšãªãããã¥ã¡ã³ããä¿åã»ç®¡çããå Žæã§ããç¹å®ã®ãã©ã«ããžã®ãã¡ã€ã«ã®è¿œå ãæŽæ°ããèªååã®ããªã¬ãŒãšãªããŸãã Google Workspace Events API Google ãã©ã€ãã§ã®ãã¡ã€ã«æäœãç£èŠããã€ãã³ãïŒãã¡ã€ã«ã®äœæã»å
容倿Žãªã©ïŒãçºçããéã«ããã®æ
å ±ã Cloud Pub/Sub ãžéç¥ãã圹å²ãæ
ããŸãã Cloud Pub/Sub Google Workspace Events API ããã®éç¥ãåãåããã¡ãã»ãŒãžããã¥ãŒã€ã³ã°ããŸããåŸè¿°ã® Cloud Run jobs ããã®ãã¥ãŒããã¡ãã»ãŒãžãååŸïŒPullïŒããŠåŠçãéå§ããŸãã Cloud Run jobs ã€ãã³ãåŠçã®ã¡ã€ã³ããžãã¯ïŒã³ã³ããåãããPythonã¹ã¯ãªããïŒãå®è¡ããç°å¢ã§ãã Cloud Scheduler ã«ãã£ãŠå®æå®è¡ãããPub/Sub ããã€ãã³ããäžæ¬ïŒãããïŒã§ååŸããåŠçããŸãã Firestore Google ãã©ã€ãã®ãã©ã«ãããã¡ã€ã« ID ãšãããã«å¯Ÿå¿ãã NotebookLM ã®ããŒããã㯠ID ã®å¯Ÿå¿é¢ä¿ãä¿åã»ç®¡çããããã® NoSQL ããŒã¿ããŒã¹ã§ãã NotebookLM Enterprise API Cloud Run jobs ã§å®è¡ãããã¹ã¯ãªããããã®æç€ºãåããå®éã«ããŒãããã¯ã®äœæããœãŒã¹ã®è¿œå ãšãã£ãæäœãå®è¡ããŸãã æ§æå³ïŒCan-beïŒ åœèšäºã§ã¯ãã®ã¢ãŒããã¯ãã£ã®äžæ žããªã ã€ãã³ãåŠçããžã㯠ã«çŠç¹ãåœãŠãŸãããã®ãããå®è£
ã®è§£èª¬ã§ã¯ Cloud Run jobs ã®èšå®ãŸã§ã¯èžã¿èŸŒãŸããPython ã¹ã¯ãªããã ããŒã«ã«ç°å¢ã§å®è¡ãã æ¹æ³ãã玹ä»ããŸãã åœèšäºã§å®è£
ããç¯å²ã®æ§æå³ãã以äžã«èšèŒããŸãã æ§æå³ïŒCan-beïŒ ã€ãã³ãåŠçæ¹åŒã«ã€ã㊠ä»åã®ã¢ãŒããã¯ãã£ã§ã¯ãã€ãã³ãåŠçã« Cloud Pub/Sub ããã® Push å ã§ã¯ãªããCloud Run jobs ã«ãã Pull å ã®å®æå®è¡ãæ¡çšããŠããŸãã ãã®çç±ã¯ãGoogle Workspace Events API ã®æ§è³ªã«ãããŸãããã¡ã€ã«ã®ç·šéäžã¯ãçæéã«å€æ°ã®æŽæ°ã€ãã³ããçºçããå¯èœæ§ãããããã®éœåºŠ Push åã§åŠçãèµ·åãããšãéå¹çãã€ã³ã¹ãå¢ã«ç¹ããæãããããŸãã ãã®ãããäžå®ééïŒäŸ: 5åããšïŒã§ãžã§ããèµ·åããPub/Sub ã«æºãŸã£ãã€ãã³ãããŸãšããŠååŸã»åŠçãã Pull åã®ãããåŠçæ¹åŒããã³ã¹ãå¹çãè¯ããªããŸãã äºåæºå ããããããŒãã¬ãã¥ãŒããã°ã©ã ãžã®ç»é² 2025幎10æçŸåšãGoogle Workspace Events API ã¯ãããããããŒãã¬ãã¥ãŒã®ãããGoogle Workspace ããããã㌠ãã¬ãã¥ãŒ ããã°ã©ã ãžã®ç»é²ãå¿
èŠã§ãã ç»é²ã«é¢ããå
容ã¯ã以äžã®åèãµã€ãããåç
§ãã ããã åè : Google Workspace ããããã㌠ãã¬ãã¥ãŒ ããã°ã©ã åçš®APIã®æå¹å 䜿çšãã Google Cloud ãããžã§ã¯ãã§ä»¥äžã® API ãæå¹åããŸãã gcloud services enable \ workspaceevents.googleapis.com \ pubsub.googleapis.com \ drive.googleapis.com \ discoveryengine.googleapis.com \ firestore.googleapis.com ãµãŒãã¹ã¢ã«ãŠã³ãã®æºåãšæš©éç§»è² ä»åã®ä»çµã¿ã§ã¯ãã¹ã¯ãªããããŠãŒã¶ãŒã«ä»£ãã£ãŠ Google ãã©ã€ãã®ãã¡ã€ã«ã«ã¢ã¯ã»ã¹ããå¿
èŠããããŸãããããå®çŸããããã«ã ãµãŒãã¹ã¢ã«ãŠã³ã ãäœæããããã¡ã€ã³å
šäœã®å§ä»»ããšããä»çµã¿ã䜿çšããŠããã®ãµãŒãã¹ã¢ã«ãŠã³ãã«ãŠãŒã¶ãŒããŒã¿ãžã®ã¢ã¯ã»ã¹æš©ãä»äžããŸãã ãã¡ã€ã³å
šäœã®å§ä»»ã¯ããŠãŒã¶ãŒã®åæãå¿
èŠãšããã«ãGoogle Workspace ãŠãŒã¶ãŒã®ããŒã¿ã«ã¢ã¯ã»ã¹ããæš©éãã¢ããªã±ãŒã·ã§ã³ã«ä»äžã§ããæ©èœã§ãã ãµãŒãã¹ã¢ã«ãŠã³ãã®äœæ ãµãŒãã¹ã¢ã«ãŠã³ãã®äœæãšããŒã«ä»äž # ç°å¢å€æ°ã®èšå® PIPELINE_GCP_PROJECT_ID =t-fukui NOTEBOOKLM_GCP_PROJECT_ID =massive-clone-455106-n9 SA_NAME =domain-wide-delegation-sa # ãµãŒãã¹ã¢ã«ãŠã³ãã®äœæ gcloud iam service-accounts create $SA_NAME \ --display-name =" ãã¡ã€ã³å
šäœã®å§ä»»çšã®ãµãŒãã¹ã¢ã«ãŠã³ã " # ããŒã«ä»äžïŒNotebookLM ãåãããããžã§ã¯ãçšïŒ gcloud projects add-iam-policy-binding $PIPELINE_GCP_PROJECT_ID \ --member =" serviceAccount: $SA_NAME @ $PIPELINE_GCP_PROJECT_ID .iam.gserviceaccount.com " \ --role =" roles/logging.logWriter " \ --condition = None gcloud projects add-iam-policy-binding $PIPELINE_GCP_PROJECT_ID \ --member =" serviceAccount: $SA_NAME @ $PIPELINE_GCP_PROJECT_ID .iam.gserviceaccount.com " \ --role =" roles/pubsub.subscriber " \ --condition = None gcloud projects add-iam-policy-binding $PIPELINE_GCP_PROJECT_ID \ --member =" serviceAccount: $SA_NAME @ $PIPELINE_GCP_PROJECT_ID .iam.gserviceaccount.com " \ --role =" roles/datastore.user " \ --condition = None # ããŒã«ä»äžïŒNotebookLM ããŒãããã¯èªå管çã®ä»çµã¿ãåãããããžã§ã¯ãçšïŒ gcloud projects add-iam-policy-binding $NOTEBOOKLM_GCP_PROJECT_ID \ --member =" serviceAccount: $SA_NAME @ $PIPELINE_GCP_PROJECT_ID .iam.gserviceaccount.com " \ --role =" roles/logging.logWriter " \ --condition = None äœæãããµãŒãã¹ã¢ã«ãŠã³ãã® OAuth 2 ã¯ã©ã€ã¢ã³ã ID ãååŸïŒåŸã®æé ã§äœ¿çšïŒ gcloud iam service-accounts describe \ domain-wide-delegation-sa@ $( gcloud config get-value project ) .iam.gserviceaccount.com \ --format =' value(uniqueId) ' ãã¡ã€ã³å
šäœã®å§ä»»ã®èšå® ç¹æš©ç®¡çè
ã¢ã«ãŠã³ãã§ Google 管çã³ã³ãœãŒã«ã«ãã°ã€ã³ããŸãã Google 管çã³ã³ãœãŒã«ïŒããŒã [ã»ãã¥ãªãã£] > [ã¢ã¯ã»ã¹ãšããŒã¿ç®¡ç] > [API ã®å¶åŸ¡] > [ãã¡ã€ã³å
šäœã®å§ä»»ã管ç] > [æ°ãã远å ] ãéžæããŸãã ãã¡ã€ã³å
šäœã®å§ä»»ïŒæ°ãã远å ãéžæ 以äžã®å€ãå
¥åããŠã[æ¿èª] ãéžæããŸãã é
ç®å å
¥åå€ ã¯ã©ã€ã¢ã³ã ID åã®æé ã§ååŸããããµãŒãã¹ã¢ã«ãŠã³ãã® OAuth 2 ã¯ã©ã€ã¢ã³ã IDãã®å€ OAuth ã¹ã³ãŒã https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/pubsub æ°ããã¯ã©ã€ã¢ã³ã ID ã远å åè : API ã¢ã¯ã»ã¹ããã¡ã€ã³å
šäœã®å§ä»»ã§å¶åŸ¡ãã Pub/Sub ã®æºå Google Workspace Events API ããã®éç¥ãåãåãããã® Pub/Sub ãããã¯ãšãã¹ã¯ãªãããã¡ãã»ãŒãžãèªã¿åºãããã®ãµãã¹ã¯ãªãã·ã§ã³ãäœæããŸãã ãããã¯ãšãµãã¹ã¯ãªãã·ã§ã³ã®äœæ # ãããã¯ãäœæ gcloud pubsub topics create blog-topic # ãµãã¹ã¯ãªãã·ã§ã³ãäœæ gcloud pubsub subscriptions create blog-subscription --topic = blog-topic --ack-deadline = 600 ãããã¯ãžã®ãããªãã·ã¥æš©éã®ä»äž # ãããã¯IDãååŸ export TOPIC_ID = $( gcloud pubsub topics describe " blog-topic " --format =' value(name) ' ) # Workspace Events API ã®ãµãŒãã¹ã¢ã«ãŠã³ãã«æš©éãä»äž gcloud pubsub topics add-iam-policy-binding ${TOPIC_ID} \ --member =" serviceAccount:drive-api-event-push@system.gserviceaccount.com " \ --role =" roles/pubsub.publisher " åè : Pub/Sub ãããã¯ãäœæããŠãµãã¹ã¯ã©ã€ããã ãµã³ãã«ã¢ããªã±ãŒã·ã§ã³ ãã¡ã€ã«æ§æ ä»åéçºãã Python ãã¡ã€ã«ã®æ§æã¯ä»¥äžã®ãšããã§ãã ãã¡ã€ã«å çšé xxx-yyy.json ãã¡ã€ã³å
šäœã®å§ä»»ã§èšå®ãããµãŒãã¹ã¢ã«ãŠã³ãã®ãµãŒãã¹ã¢ã«ãŠã³ãããŒãã¡ã€ã« ãµãŒãã¹ã¢ã«ãŠã³ãããŒã®åãæ±ãã«ã¯æ³šæãå¿
èŠã§ãã詳现ã¯ãåèãµã€ãããµãŒãã¹ ã¢ã«ãŠã³ã ããŒã管çããããã®ãã¹ã ãã©ã¯ãã£ã¹ãããåç
§ãã ããã åœèšäºã§ã¯ãæ€èšŒç®çã§ããã°ã©ã ãããŒã«ã«ã§å®è¡ããããããµãŒãã¹ ã¢ã«ãŠã³ã ããŒãå¿
èŠã§ãããCloud Run jobs çã§å®è¡ããå Žåã¯ããµãŒãã¹ã«ã¢ã¿ããããããµãŒãã¹ã¢ã«ãŠã³ãã®æ
å ±ã䜿çšãããããããµãŒãã¹ ã¢ã«ãŠã³ã ããŒã¯äžèŠã§ãã .env ç°å¢å€æ°çšã®ãã¡ã€ã« create_subscription.py Google Workspace Events APIã§ã€ãã³ãã賌èªãããã¡ã€ã« process_events.py 倿Žã€ãã³ããåŠçããNotebookLM ã®ããŒãããã¯ããœãŒã¹ãäœæãæŽæ°ãããã¡ã€ã« åè : ãµãŒãã¹ ã¢ã«ãŠã³ã ããŒãäœæãã åè : ãµãŒãã¹ ã¢ã«ãŠã³ã ããŒã管çããããã®ãã¹ã ãã©ã¯ãã£ã¹ ã©ã€ãã©ãªã®ã€ã³ã¹ããŒã« ãµã³ãã«ããã°ã©ã ãåããããã«ã以äžã® Python ã©ã€ãã©ãªãã€ã³ã¹ããŒã«ããŸãã python-dotenv == 1 . 1 . 1 google-auth-oauthlib == 1 . 2 . 2 firebase-admin == 7 . 1 . 0 google-api-python-client == 2 . 181 . 0 google-cloud-pubsub == 2 . 31 . 1 ç°å¢å€æ°ã®èšå® èšå®ããå€ã¯ããèªèº«ã®ç°å¢ã«åãããŠå€æŽããŠãã ããã .env # ãã¡ã€ã³å
šäœã®å§ä»»ã§èšå®ãããµãŒãã¹ã¢ã«ãŠã³ãã®ãµãŒãã¹ã¢ã«ãŠã³ãããŒã®ãã¹ GOOGLE_APPLICATION_CREDENTIALS = " /aaa/bbb/ccc/xxx-yyy.json " # NotebookLM ããŒãããã¯èªå管çã®ä»çµã¿ãåãã Google Cloud ãããžã§ã¯ã ID PIPELINE_GCP_PROJECT_ID = " xxx " # NotebookLM ãåãã Google Cloud ãããžã§ã¯ã çªå· NOTEBOOKLM_GCP_PROJECT_NUMBER = " 123 " # å§ä»»ããããŠãŒã¶ãŒã®ã¡ãŒã«ã¢ãã¬ã¹ # â» ãã¡ã€ã³å
šäœã®å§ä»»èšå®ãè¡ã£ãçµç¹ã®ãŠãŒã¶ãŒã§ããããš # ⻠以äžã®æš©éãæããŠããããš #ããâ ç£èŠå¯Ÿè±¡ã®ãã©ã«ãã®å
±æãã©ã€ãã®ã«ãŒãã«å¯ŸããŠãé²èЧè
ã以äžã®æš©é #ããâ Cloud NotebookLM ãŠãŒã¶ãŒïŒããŒã¿çïŒïŒroles/discoveryengine.notebookLmUserïŒä»¥äžã®æš©é DELEGATED_USER_EMAIL = " xxx@xxx.co.jp " # ç£èŠå¯Ÿè±¡ã®ãã©ã«ã # â» ä»æ§ã«ãããå
±æãã©ã€ãã®ã«ãŒããã©ã«ãã¯æå®äžå¯ã§ããå
±æãã©ã€ãå
ã«ãã©ã«ããäœæããŠãäœæãããã©ã«ããæå®ããŠãã ãã TARGET_RESOURCE = " //drive.googleapis.com/files/xxx " # ç£èŠã®éç¥å
ã® Pub/Sub ãããã¯å, ãµãã¹ã¯ãªãã·ã§ã³ TOPIC_NAME = " blog-topic " PUBSUB_SUBSCRIPTION_ID = " blog-subscription " # ããŒãããã¯ã®ãã±ãŒã·ã§ã³ NOTEBOOKLM_LOCATION = " global " Google Workspace Events APIã§ã€ãã³ããè³Œèª Google Workspace Events API ã䜿çšããã«ã¯ããŸããã©ã®ãªãœãŒã¹ãã®ãã©ã®ã€ãã³ãããç£èŠãããããå®çŸ©ããããµãã¹ã¯ãªãã·ã§ã³ïŒè³ŒèªïŒããäœæããå¿
èŠããããŸãã ä»åã¯ãç¹å®ã® Google ãã©ã€ããã©ã«ãé
äžã§çºçãããã¡ã€ã«ã®äœæãšå
容倿Žã®ã€ãã³ãã賌èªãããµãã¹ã¯ãªãã·ã§ã³ãäœæããŸãã create_subscription.py import json import os import time from typing import Any, Dict from dotenv import load_dotenv from google.auth import default from google.auth.exceptions import RefreshError from google.auth.transport.requests import AuthorizedSession, Request from requests.exceptions import HTTPError # .envãã¡ã€ã«ããç°å¢å€æ°ãèªã¿èŸŒã load_dotenv() class DriveSubscriptionCreator : """ Google Workspace Events API ã䜿çšããŠãGoogle ãã©ã€ãã®ãªãœãŒã¹ã«å¯Ÿãã ãµãã¹ã¯ãªãã·ã§ã³ãäœæããã¯ã©ã¹ã """ def __init__ (self): """å
±éã§äœ¿çšãã倿°ã®åæåãåçš®ã¯ã©ã€ã¢ã³ããã»ããã¢ããããã""" self._set_env_value() self.credentials = self._initialize_credentials() self.authed_session = AuthorizedSession(self.credentials) def _set_env_value (self): """ç°å¢å€æ°ã®å€ãååŸããŠå€æ°ã«èšå®ãã""" # å¿
é ã®ç°å¢å€æ°ãšã€ã³ã¹ã¿ã³ã¹å€æ°åã®ãããã³ã° required_env_vars = { "DELEGATED_USER_EMAIL" : "delegated_user_email" , "PIPELINE_GCP_PROJECT_ID" : "pipeline_gcp_project_id" , "TOPIC_NAME" : "topic_name" , "TARGET_RESOURCE" : "target_resource" , } # ã«ãŒãã§ç°å¢å€æ°ãååŸããèšå®ãããŠããªããã°äŸå€ãçºçããã for env_name, attr_name in required_env_vars.items(): value = os.getenv(env_name) if not value: raise ValueError (f "ç°å¢å€æ° {env_name} ãèšå®ãããŠããŸããã" ) # setattr() ã䜿ã£ãŠã€ã³ã¹ã¿ã³ã¹å€æ°ïŒself.xxxïŒãèšå® setattr (self, attr_name, value) def _initialize_credentials (self): """ãã¡ã€ã³å
šäœã®å§ä»»ã䜿çšããŠèªèšŒæ
å ±ãåæåããã³ãªãã¬ãã·ã¥ããã""" print ( "èªèšŒæ
å ±ãåæåããŠããŸã..." ) try : default_credentials, _ = default(scopes=[ "https://www.googleapis.com/auth/drive.readonly" ]) credentials = default_credentials.with_subject(self.delegated_user_email) credentials.refresh(Request()) print ( "èªèšŒã«æåããŸããã" ) return credentials except RefreshError as e: print ( "èªèšŒãšã©ãŒ: ãµãŒãã¹ã¢ã«ãŠã³ãã®æš©éå§ä»»èšå®ã確èªããŠãã ããã" ) print (f "ãšã©ãŒè©³çް: {e}" ) raise def _create_subscription (self) -> str : """ãµãã¹ã¯ãªãã·ã§ã³äœæãªã¯ãšã¹ããéä¿¡ãããªãã¬ãŒã·ã§ã³åãååŸããã""" print (f "ãµãã¹ã¯ãªãã·ã§ã³ãäœæããŠããŸã... Target: {self.target_resource}" ) body = { "targetResource" : self.target_resource, "eventTypes" : [ "google.workspace.drive.file.v3.created" , "google.workspace.drive.file.v3.contentChanged" , ], "notificationEndpoint" : { "pubsubTopic" : f "projects/{self.pipeline_gcp_project_id}/topics/{self.topic_name}" }, "driveOptions" : { "includeDescendants" : True }, "payloadOptions" : { "includeResource" : True , "fieldMask" : "file.id,file.name,file.mimeType,file.parents" , }, "ttl" : "14400s" , } try : response = self.authed_session.post( "https://workspaceevents.googleapis.com/v1beta/subscriptions" , json=body, ) response.raise_for_status() operation = response.json() print ( "ãµãã¹ã¯ãªãã·ã§ã³äœæãªã¯ãšã¹ããåçãããŸããã" ) print ( "LRO:" , json.dumps(operation, ensure_ascii= False , indent= 2 )) return operation[ "name" ] except HTTPError as e: print ( "ãµãã¹ã¯ãªãã·ã§ã³ã®äœæã«å€±æããŸããã" ) print (f "ãšã©ãŒ: {e.response.text}" ) raise def _wait_for_operation (self, op_name: str ) -> Dict[ str , Any]: """Long Running Operation ã®å®äºãåŸ
ã€ã""" print (f "ãªãã¬ãŒã·ã§ã³ã®å®äºãåŸ
ã£ãŠããŸã: {op_name}" ) while True : try : poll = self.authed_session.get(f "https://workspaceevents.googleapis.com/v1beta/{op_name}" ) poll.raise_for_status() j = poll.json() if j.get( "done" ): if "error" in j: raise RuntimeError (json.dumps(j[ "error" ])) print ( "ãªãã¬ãŒã·ã§ã³ãå®äºããŸããã" ) return j.get( "response" , {}) print ( "ãªãã¬ãŒã·ã§ã³ã¯ãŸã é²è¡äžã§ãã2ç§åŸ
æ©ããŸã..." ) time.sleep( 2 ) except HTTPError as e: print ( "ãªãã¬ãŒã·ã§ã³ã®ããŒãªã³ã°äžã«ãšã©ãŒãçºçããŸããã" ) print (f "ãšã©ãŒ: {e.response.text}" ) raise def run (self): """ãµãã¹ã¯ãªãã·ã§ã³äœæã®ã¡ã€ã³ãããŒãå®è¡ããã""" try : op_name = self._create_subscription() result = self._wait_for_operation(op_name) print ( " \n --- ãµãã¹ã¯ãªãã·ã§ã³äœæå®äº ---" ) print (json.dumps(result, ensure_ascii= False , indent= 2 )) print ( "---------------------------------" ) except (HTTPError, ValueError , RuntimeError ) as e: print (f " \n ãµãã¹ã¯ãªãã·ã§ã³äœæããã»ã¹ã§ãšã©ãŒãçºçããŸãã: {e}" ) if __name__ == "__main__" : try : creator = DriveSubscriptionCreator() creator.run() except Exception as e: print (f "ã¹ã¯ãªããã®å®è¡ã«å€±æããŸãã: {e}" ) åè : Google Workspace ãµãã¹ã¯ãªãã·ã§ã³ãäœæãã åè : ãµãã¹ã¯ãªãã·ã§ã³äœæã®ã€ãã³ãã¿ã€ã ã€ãã³ããåŠçã NotebookLM ãæäœ Pub/Sub ã«æºãŸã£ãã€ãã³ãã¡ãã»ãŒãžãååŸãããã®æ
å ±ã«åºã¥ããŠå®éã« NotebookLM ã®ããŒãããã¯ãšãœãŒã¹ã管çããã¹ã¯ãªãããäœæããŸãã ãã®ã¹ã¯ãªããã¯ãä»åã®èªååã®ä»çµã¿ã«ãããå¿èéšã§ããã以äžã®åœ¹å²ãæ
ããŸãã Pub/Sub ãã Drive ã®ã€ãã³ãã¡ãã»ãŒãžãååŸããã ã€ãã³ãæ
å ±ãããã¡ã€ã«IDãç¹å®ããDrive API ã§è©³çްãªãã¡ã€ã«æ
å ±ãååŸããã Firestore ã䜿ã£ãŠãDrive ã®ãã©ã«ããš NotebookLM ã®ããŒãããã¯ã®å¯Ÿå¿é¢ä¿ã管çããã NotebookLM Enterprise API ãåŒã³åºããããŒãããã¯ã®äœæã»ãœãŒã¹ã®è¿œå ã»æŽæ°ïŒåé€ã»è¿œå ïŒãè¡ãã process_events.py import json import os from typing import Any, Dict, Optional, Tuple from dotenv import load_dotenv from firebase_admin import firestore from google.auth import default from google.auth.exceptions import RefreshError from google.auth.transport.requests import AuthorizedSession, Request from google.cloud import pubsub_v1 from googleapiclient.discovery import build from requests.exceptions import HTTPError # .envãã¡ã€ã«ããç°å¢å€æ°ãèªã¿èŸŒã load_dotenv() class DriveEventProcessor : """ Google ãã©ã€ãã®ã€ãã³ããåŠçããNotebookLMãšé£æºããããã»ããµã """ def __init__ (self): """å
±éã§äœ¿çšãã倿°ã®åæåãåçš®ã¯ã©ã€ã¢ã³ããã»ããã¢ããããã""" self._set_env_value() sa_credentials, delegated_credentials = self._initialize_credentials() # ãå§ä»»ãŠãŒã¶ãŒãšããŠæäœããAPIã # Drive, NotebookLM (authed_session) ã¯ãŠãŒã¶ãŒã®ããŒã¿ã«ã¢ã¯ã»ã¹ãã self.credentials = delegated_credentials # äºææ§ã®ããã«ç¶æ self.authed_session = AuthorizedSession(delegated_credentials) self.drive = build( "drive" , "v3" , credentials=delegated_credentials) # ããµãŒãã¹ã¢ã«ãŠã³ããšããŠæäœããAPIã # Firestore, Pub/Sub ã¯GCPãªãœãŒã¹ã«ã¢ã¯ã»ã¹ãã self.firestore_client = firestore.Client(credentials=sa_credentials) self.subscriber_client = pubsub_v1.SubscriberClient(credentials=sa_credentials) # NotebookLM APIã®ãšã³ããã€ã³ãèšå® endpoint_prefix = "" if self.notebooklm_location == "global" else f "{self.notebooklm_location}-" self.notebooklm_base_url = f "https://{endpoint_prefix}discoveryengine.googleapis.com/v1alpha" def _set_env_value (self): """ç°å¢å€æ°ã®å€ãååŸããŠå€æ°ã«èšå®ãã""" # å¿
é ã®ç°å¢å€æ°ãšã€ã³ã¹ã¿ã³ã¹å€æ°åã®ãããã³ã° required_env_vars = { "DELEGATED_USER_EMAIL" : "delegated_user_email" , "PIPELINE_GCP_PROJECT_ID" : "pipeline_gcp_project_id" , "NOTEBOOKLM_GCP_PROJECT_NUMBER" : "notebooklm_gcp_project_number" , "PUBSUB_SUBSCRIPTION_ID" : "pubsub_subscription_id" , "NOTEBOOKLM_LOCATION" : "notebooklm_location" , } # ã«ãŒãã§ç°å¢å€æ°ãååŸããèšå®ãããŠããªããã°äŸå€ãçºçããã for env_name, attr_name in required_env_vars.items(): value = os.getenv(env_name) if not value: raise ValueError (f "ç°å¢å€æ° {env_name} ãèšå®ãããŠããŸããã" ) # setattr() ã䜿ã£ãŠã€ã³ã¹ã¿ã³ã¹å€æ°ïŒself.xxxïŒãèšå® setattr (self, attr_name, value) def _initialize_credentials (self) -> Tuple[Any, Any]: """ãµãŒãã¹ã¢ã«ãŠã³ãèªèº«ã®èªèšŒæ
å ±ãšããã¡ã€ã³å
šäœã®å§ä»»ã䜿çšããèªèšŒæ
å ±ã®äž¡æ¹ãè¿ãã""" try : # å
±éã®ã¹ã³ãŒãã§ããã©ã«ãïŒãµãŒãã¹ã¢ã«ãŠã³ãèªèº«ïŒã®èªèšŒæ
å ±ãååŸ sa_credentials, _ = default( scopes=[ "https://www.googleapis.com/auth/drive.readonly" , "https://www.googleapis.com/auth/cloud-platform" , "https://www.googleapis.com/auth/pubsub" , ] ) # å§ä»»ããããŠãŒã¶ãŒã®èªèšŒæ
å ±ãäœæ delegated_credentials = sa_credentials.with_subject(self.delegated_user_email) delegated_credentials.refresh(Request()) print ( "èªèšŒã«æåããŸããã" ) # (ãµãŒãã¹ã¢ã«ãŠã³ãèªèº«ã®èªèšŒæ
å ±, å§ä»»ãŠãŒã¶ãŒã®èªèšŒæ
å ±) ã®ã¿ãã«ã§è¿ã return sa_credentials, delegated_credentials except RefreshError as e: print ( "èªèšŒãšã©ãŒ: ãµãŒãã¹ã¢ã«ãŠã³ãã®æš©éå§ä»»èšå®ã確èªããŠãã ããã" ) print (f "ãšã©ãŒè©³çް: {e}" ) raise def _create_notebook (self, title: str ) -> str : """NotebookLMã«æ°ããããŒãããã¯ãäœæããã""" url = f "{self.notebooklm_base_url}/projects/{self.notebooklm_gcp_project_number}/locations/{self.notebooklm_location}/notebooks" response = self.authed_session.post(url, json={ "title" : title}) response.raise_for_status() return response.json()[ "notebookId" ] def _add_drive_source (self, notebook_id: str , file_id: str , mime_type: str , display_name: str ) -> dict : """NotebookLMã®ããŒãããã¯ã«Google ãã©ã€ãã®ãœãŒã¹ã远å ããã""" url = f "{self.notebooklm_base_url}/projects/{self.notebooklm_gcp_project_number}/locations/{self.notebooklm_location}/notebooks/{notebook_id}/sources:batchCreate" body = { "userContents" : [ { "googleDriveContent" : { "documentId" : file_id, "mimeType" : mime_type, "sourceName" : display_name, } } ] } response = self.authed_session.post(url, json=body) response.raise_for_status() return response.json() def _delete_source (self, notebook_id: str , source_id: str ): """NotebookLMã®ããŒãããã¯ãããœãŒã¹ãåé€ããã""" url = f "{self.notebooklm_base_url}/projects/{self.notebooklm_gcp_project_number}/locations/{self.notebooklm_location}/notebooks/{notebook_id}/sources:batchDelete" source_full_name = f "projects/{self.notebooklm_gcp_project_number}/locations/{self.notebooklm_location}/notebooks/{notebook_id}/sources/{source_id}" body = { "names" : [source_full_name]} response = self.authed_session.post(url, json=body) response.raise_for_status() def _get_file_info (self, file_id: str ) -> Optional[Dict[ str , Any]]: """Google ãã©ã€ããããã¡ã€ã«ã¡ã¿ããŒã¿ãååŸããã""" try : return ( self.drive.files() .get( fileId=file_id, fields= "id,name,mimeType,parents,driveId" , supportsAllDrives= True , ) .execute() ) except HTTPError as e: print (f "Driveãã¡ã€ã«æ
å ±ã®ååŸã«å€±æããŸãã (ID: {file_id}): {e}" ) return None def _get_notebook_folder_info (self, file_meta: Dict[ str , Any]) -> Optional[Tuple[ str , str ]]: """ãã¡ã€ã«ã®èŠªãé¡ããããŒãããã¯ã®åºæºãšãªããã©ã«ãã®IDãšååãååŸããã""" path_items = [] parent_id = (file_meta.get( "parents" ) or [ None ])[ 0 ] while parent_id: try : parent_meta = self._get_file_info(parent_id) if not parent_meta: return None path_items.insert( 0 , { "id" : parent_meta[ "id" ], "name" : parent_meta[ "name" ]}) is_shared_drive_root = not parent_meta.get( "parents" ) and parent_meta.get( "driveId" ) if is_shared_drive_root: drive_info = self.drive.drives().get(driveId=parent_meta[ "driveId" ], fields= "name" ).execute() path_items.insert( 0 , { "id" : parent_meta[ "driveId" ], "name" : drive_info[ "name" ]}) break parent_id = (parent_meta.get( "parents" ) or [ None ])[ 0 ] except HTTPError as e: print (f "芪ãã©ã«ãã®æ¢çŽ¢äžã«ãšã©ãŒãçºçããŸãã (ID: {parent_id}): {e}" ) return None # éå±€ãæåŸ
éãããã§ã㯠(å
±æãã©ã€ã > ãã©ã€ã(èªåã§å
¥ã) > ãµãã¹ã¯ãªãã·ã§ã³ãã©ã«ã > ããŒãããã¯ãã©ã«ã) if len (path_items) >= 4 : notebook_folder = path_items[ 3 ] return notebook_folder.get( "id" ), notebook_folder.get( "name" ) return None def _get_or_create_notebook (self, folder_id: str , title: str ) -> Optional[ str ]: """Firestore/NotebookLMããããŒãããã¯ãååŸãŸãã¯æ°èŠäœæããã""" notebook_ref = self.firestore_client.collection( "notebooks" ).document(folder_id) notebook_doc = notebook_ref.get() if notebook_doc.exists: print (f "æ¢åã®ããŒãããã¯ãFirestoreã§çºèŠ: '{title}'" ) return notebook_doc.to_dict().get( "notebookId" ) else : print (f "ããŒãããã¯ãèŠã€ãããŸãããæ°èŠäœæããŸã: '{title}'..." ) try : new_notebook_id = self._create_notebook(title) print (f "NotebookLMã«ããŒãããã¯ãäœæããŸãã: {new_notebook_id}" ) notebook_data = { "notebookId" : new_notebook_id, "title" : title, "sources" : {}} notebook_ref.set(notebook_data) print (f "Firestoreã«ããŒãããã¯æ
å ±ãä¿åããŸãã: '{title}'" ) return new_notebook_id except HTTPError as e: print (f "ããŒãããã¯ã®æ°èŠäœæãŸãã¯Firestoreãžã®ä¿åã«å€±æããŸãã: {e}" ) return None def process_drive_event (self, event_data: Dict[ str , Any]): """åäžã®Driveã€ãã³ããåŠçããã""" file_id = event_data.get( "file" , {}).get( "id" ) if not file_id: print ( "ã€ãã³ãããŒã¿ã«ãã¡ã€ã«IDãèŠã€ãããŸããã" ) return print (f "ã€ãã³ããåŠçäž (File ID: {file_id})" ) file_info = self._get_file_info(file_id) if not file_info: return if file_info[ "mimeType" ] == "application/vnd.google-apps.folder" : print (f "ãã©ã«ãã¯ã¹ãããããŸã: {file_info.get('name')}" ) return folder_info = self._get_notebook_folder_info(file_info) if not folder_info: print (f "ããŒãããã¯ãã©ã«ããç¹å®ã§ããŸããã§ãã: {file_info.get('name')}" ) return notebook_folder_id, notebook_title = folder_info notebook_id = self._get_or_create_notebook(notebook_folder_id, notebook_title) if not notebook_id: return notebook_ref = self.firestore_client.collection( "notebooks" ).document(notebook_folder_id) notebook_data = notebook_ref.get().to_dict() or {} existing_source = notebook_data.get( "sources" , {}).get(file_id) try : if existing_source and existing_source.get( "sourceId" ): print (f "æ¢åãœãŒã¹ãæŽæ°ããŸã: {file_info['name']}" ) self._delete_source(notebook_id, existing_source[ "sourceId" ][ "id" ]) print (f "å€ããœãŒã¹ãåé€ããŸãã: {existing_source['sourceId']['id']}" ) print (f "æ°ãããœãŒã¹ã远å ããŸã: {file_info['name']}" ) source_info = self._add_drive_source(notebook_id, file_id, file_info[ "mimeType" ], file_info[ "name" ]) new_source_id = source_info.get( "sources" , [{}])[ 0 ].get( "sourceId" ) if new_source_id: update_path = f "sources.{file_id}" notebook_ref.update( { update_path: { "sourceId" : new_source_id, "displayName" : file_info[ "name" ], "updatedAt" : firestore.SERVER_TIMESTAMP, } } ) print ( "Firestoreã®ãœãŒã¹æ
å ±ãæŽæ°ããŸããã" ) else : print ( "NotebookLMã®å¿çããæ°ããSourceIDãååŸã§ããŸããã§ããã" ) except HTTPError as e: print (f "ãœãŒã¹ã®åŠçäžã«ãšã©ãŒãçºçããŸãã: {e}" ) except Exception as e: print (f "äºæãã¬ãšã©ãŒãçºçããŸãã: {e}" ) print (f "ãã¡ã€ã«(ID: {file_id})ã®åŠçãå®äºããŸããã" ) def run (self, batch_size: int = 10 ): """ Pub/Subããã¡ãã»ãŒãžãååŸããã€ãã³ãåŠçã«ãŒããéå§ããã batch_size ã®å€ã倧ãããããããšãPub/Subã¡ãã»ãŒãžååŸããACKãŸã§ã®æéãé·ããªãã確èªå¿çæéãéããŠã¡ãã»ãŒãžãåéãããå¯èœæ§ãé«ããªããŸãã """ subscription_path = self.subscriber_client.subscription_path( self.pipeline_gcp_project_id, self.pubsub_subscription_id ) print (f "ãµãã¹ã¯ãªãã·ã§ã³ããªãã¹ã³äž: {subscription_path}..." ) total_processed = 0 try : while True : response = self.subscriber_client.pull( subscription=subscription_path, max_messages=batch_size, return_immediately= True ) if not response.received_messages: print ( "åŠçããã¡ãã»ãŒãžã¯ãããŸããã" ) break print (f "{len(response.received_messages)}ä»¶ã®ã¡ãã»ãŒãžãååŸããŸããã" ) ack_ids = [] for msg in response.received_messages: try : event_data = json.loads(msg.message.data.decode( "utf-8" )) self.process_drive_event(event_data) ack_ids.append(msg.ack_id) total_processed += 1 except json.JSONDecodeError as e: print (f "ã¡ãã»ãŒãžã®JSONããŒã¹ã«å€±æããŸãã: {e}" ) ack_ids.append(msg.ack_id) # åŠçã§ããªãã¡ãã»ãŒãžã¯ACKããŠåé
ä¿¡ãé²ã except Exception as e: print (f "ã¡ãã»ãŒãžåŠçäžã«äºæãã¬ãšã©ãŒãçºçããŸãããå詊è¡ãããŸãã: {e}" ) # ãšã©ãŒãçºçããã¡ãã»ãŒãžã¯ACKãããåé
ä¿¡ãåŸ
〠if ack_ids: self.subscriber_client.acknowledge(subscription=subscription_path, ack_ids=ack_ids) print (f "{len(ack_ids)}ä»¶ã®ã¡ãã»ãŒãžã確èªå¿çããŸããã" ) except Exception as e: print (f "ã¡ãã»ãŒãžååŸã«ãŒãã§ãšã©ãŒãçºçããŸãã: {e}" ) finally : self.subscriber_client.close() print ( "ãµãã¹ã¯ã©ã€ããŒãã¯ããŒãºããŸããã" ) print (f "--- ãããåŠçå®äºãåèš {total_processed} ä»¶ã®ã¡ãã»ãŒãžãåŠçããŸãã ---" ) if __name__ == "__main__" : try : processor = DriveEventProcessor() processor.run() except Exception as e: print (f "ã¹ã¯ãªããã®å®è¡ã«å€±æããŸãã: {e}" ) åè : Create and manage notebooks (API) åäœç¢ºèª ããŒãããã¯ãäœæãããŠããªãç¶æ
ã§ãããŒãããã¯ã®æ°èŠäœæããœãŒã¹ã®è¿œå ã»æŽæ°ã®ç¢ºèªãè¡ããŸãã NotebookLMïŒãããç»é¢ïŒåäœç¢ºèªåã®ç¶æ
ïŒ æäœ1 create_subscription.py ãå®è¡ããŸãã æäœ2 ç£èŠå¯Ÿè±¡ãã©ã«ãã«ããã©ã«ããæ°èŠäœæãããã®äžã«ãã¡ã€ã«ã远å ããŸãã ç£èŠå¯Ÿè±¡ãã©ã«ã âââ æ¡ä»¶1 â âââ æ¡ä»¶1ã®ãã¡ã€ã« âââ æ¡ä»¶2 âââ æ¡ä»¶2ã®ãã¡ã€ã« ãã¡ã€ã«çš®é¡ åå ãã¡ã€ã«ã®å
容 ãã©ã«ã æ¡ä»¶1 â ãã©ã«ã æ¡ä»¶2 â Google ããã¥ã¡ã³ã æ¡ä»¶1ã®ãã¡ã€ã« 仿¥ã®å€©æ°ã¯ããã³ãã§ã Google ã¹ã©ã€ã æ¡ä»¶2ã®ãã¡ã€ã« 奜ããªé£ã¹ç©ã¯ãçŸãã§ã æäœ3 process_events.py ãå®è¡ããŸãã ãã©ã«ãã«å¯Ÿå¿ããããŒãããã¯ãäœæãããŠããŸãã NotebookLMïŒãããç»é¢ïŒåäœç¢ºèªåŸã®ç¶æ
ïŒ äœæãããã¡ã€ã«ãæ£ãããœãŒã¹ãšããŠè¿œå ãããŠããŸãã NotebookLMïŒããŒãããã¯ïŒæ¡ä»¶1ã®ãœãŒã¹ç¢ºèªïŒ NotebookLMïŒããŒãããã¯ïŒæ¡ä»¶2ã®ãœãŒã¹ç¢ºèªïŒ æäœ4 æ¢åãã¡ã€ã«ã®æŽæ°ãšãæ¢åãã©ã«ããžãã¡ã€ã«ã远å ããŸãã æ¢åãã¡ã€ã«ãæ¡ä»¶1ã®ãã¡ã€ã«ãã®å
容ã 仿¥ã®å€©æ°ã¯ãæ¡ãã³ãã§ã ã«å€æŽããŸãã æ¢åãã©ã«ããæ¡ä»¶2ãã«ãGoogle ããã¥ã¡ã³ãã®ãã¡ã€ã«ãæ°èŠã«è¿œå ããŸããïŒå
å®¹ïŒ é©åºŠãªå€§ããã®ãã³ã¯ãè»æµ·èãã§ã ïŒ æäœ5 process_events.py ãå®è¡ããŸãã æŽæ°ãããã¡ã€ã«ãæ£ãããœãŒã¹ãšããŠåæ ãããŠããŸãã NotebookLMïŒããŒãããã¯ïŒæ¡ä»¶1ã®æŽæ°ãœãŒã¹ç¢ºèªïŒ æ°ãã«è¿œå ãããã¡ã€ã«ããœãŒã¹ãšããŠæ£ãã远å ãããŠããŸãã NotebookLMïŒããŒãããã¯ïŒæ¡ä»¶2ã®ãœãŒã¹è¿œå 確èªïŒ çŠäº éä¹ (èšäºäžèЧ) ã«ã¹ã¿ããŒãµã¯ã»ã¹èª² ãšã³ãžã㢠2024幎2æ G-gen JOIN å
ã¯ã¢ããªã±ãŒã·ã§ã³ãšã³ãžãã¢(ã€ã³ãã©ã¯AWS)ãšããŠãPM/PLã»äžæµå·¥çšãæ
åœãG-genã®Google Cloudãžã®ç±éãGoogle Cloudã®é
åãå³ãããªããæ¥ã
粟é²