ãæäœã RAG ã·ã¹ãã ãã§ RAG ã®ä»çµã¿ãåŠã³çŽã
ã¯ããã«
Google Cloud ã§ã¯ãRAG ãæè»œã«å®çŸããææ®µãšããŠãVertex AI Search ã Vertex AI RAG Engine ãªã©ã®ãããŒãžããµãŒãã¹ãæäŸãããŠããŸãããããã¯ããã¯ãã«æ€çŽ¢ãšã³ãžã³ã§ãã Vector Search ãå©çšããŠãç¬èªã® RAG ã·ã¹ãã ãæ§ç¯ããããšãã§ããŸãã
æ¥åã·ã¹ãã ãšããŠå©çšããéã¯ããããã®ãµãŒãã¹ãå©çšããããšã§ãã¹ã±ãŒã©ããªãã£ã®é«ãã·ã¹ãã ã容æã«æ§ç¯ã§ããŸãããã·ã¹ãã èšèšã«é¢ãããšã³ãžãã¢ãšããŠã¯ããããã RAG ãšã¯ã©ã®ãããªä»çµã¿ã§ãã©ã®ãããªåŠçãè£åŽã§è¡ãããŠããã®ããçè§£ããŠããããšã倧åã§ããããã§ãã®èšäºã§ã¯ãåè¿°ã®äŸ¿å©ãªãµãŒãã¹ããããŠå©çšãããèªåã® RAG ã·ã¹ãã ãæäœãããããšã§ãRAG ãæ§æããããŒããé«å質ãªçµæãè¿ãããã®å·¥å€«ãåŠã³ãŸãã
RAG ã®ä»çµã¿
ã¯ããã«ãäžèšã®èšäºãåèã«ããŠãRAG ã®ä»çµã¿ãç°¡åã«ããããããŠãããŸãã
ãŸãããã°ã©ãŠã³ãã£ã³ã°ãš RAG ã®éãã«ã€ããŠãã§ã¯ãRAG ã®åºæ¬çãªåŠçã®æµããæ¬¡ã®ããã«ãŸãšããŸããã
- å©çšè
ã質åãå
¥åãã
ãâ - 質åã®åçã«å¿
èŠãªæ
å ±ãæ€çŽ¢ãã
ãâ - æ€çŽ¢ã§åŸãããæ å ±ãšè³ªåã LLM ã«å ¥åããŠåçãçæãã
ãã®äžã§ããRAG ã·ã¹ãã æ§ç¯ã®é£ãããã§ã¯ããå ¥åããã質åã«å¿ããŠãåçã«å¿ èŠãªæ å ±ãçç¢ºã«æ€çŽ¢ã»çºèŠããä»çµã¿ããå®è£ ããéšåããRAG ã·ã¹ãã æ§ç¯ã®èª²é¡ã®1ã€ã«ãªãããšã説æããŸããã
RAG ã·ã¹ãã ã®èãæ¹ãçãŸããåœåã¯ãæ€çŽ¢å¯Ÿè±¡ã®ããã¥ã¡ã³ã矀ã«å«ãŸããããã¹ããäžå®ã®æåæ°ã®ããã£ã³ã¯ãã«åå²ããŠããŒã¿ããŒã¹ã«ä¿åããäžã§ãåç §ããã¹ããã£ã³ã¯ãæ€çŽ¢ããæ¹åŒãäž»ã«çšããããŠããŸãããç¹ã«åæã® RAG ã·ã¹ãã ã§ã¯ãããããã®ãã£ã³ã¯ã®ãµã€ãºã¯ãè±èªãªã100åèªãæ¥æ¬èªãªã200ã500æåçšåºŠãšå°ããªãã®ã§ããããã®ãããæ€çŽ¢ã§åŸãããè€æ°ã®ãã£ã³ã¯ãå¯ãéããéã«ãç¡é¢ä¿ãªããã¥ã¡ã³ãã®çްããªãã£ã³ã¯ãæ··åšããŠãåçã«åœ¹ç«ã€æå³ã®ããæ å ±ã«ãªãã«ãããšãã課é¡ããããŸãããããããã®ãã£ã³ã¯ã«ã¯ãåå¥ã®æèãèæ¯æ å ±ãä»éããŠããã¯ãã§ããããããã¯åã ã®ãã£ã³ã¯ã«ã¯å«ãŸããªãããã§ãã

ç°ãªãããã¥ã¡ã³ãã®å°ããªãã£ã³ã¯ãéããŠãæèãèæ¯æ
å ±ãåŸãããªã
ãã®ããã«å°ããªãã£ã³ã¯ã䜿çšããã®ã¯ã次ã®ãããªæè¡çå¶çŽã«ãããã®ã§ããã
- LLM ã®ã³ã³ããã¹ããŠã£ã³ããŠã®å¶éïŒåæã® LLM ã§ã¯ãããã³ããã«å ¥åã§ããããã¹ãã¯ã2,048ã4,096ããŒã¯ã³ãäžéã«ãªã£ãŠãããè€æ°ã®æ€çŽ¢çµæãå«ããã«ã¯ãäžã€äžã€ã®ãã£ã³ã¯ãå°ããããå¿ èŠããããŸããã
- åã蟌ã¿ã¢ãã«ã®éçïŒãã£ã³ã¯ãé·ããããšãåã蟌ã¿ãã¯ãã«ãšããŠæœåºããã¹ããäž»èŠãªæ å ±ãããããŸãã«ãªããæ€çŽ¢ç²ŸåºŠãäžããåŸåã«ãããŸããã
ããã§ã2ã€ç®ã®ãåã蟌ã¿ã¢ãã«ãã«ã€ããŠè£è¶³ããŠãããŸãã質åã«åºã¥ããŠåçã«å¿ èŠãªæ å ±ãå«ããã£ã³ã¯ãæ€çŽ¢ããéã¯ãéåžžããåã蟌ã¿ã¢ãã«ãã«ãã£ãŠãããã¹ãããåã蟌ã¿ãã¯ãã«ãã«å€æããäžã§ãåã蟌ã¿ãã¯ãã«ã®é¡äŒŒåºŠã«åºã¥ããŠæ€çŽ¢ããŸããå ·äœçã«ã¯ã次ã®ãããªæé ã«ãªããŸãã
- åã蟌ã¿ã¢ãã«ãçšããŠãããããã®ãã£ã³ã¯ã髿¬¡å 空éã®ãåã蟌ã¿ãã¯ãã«ãã«å€æãã
- åãããåã蟌ã¿ã¢ãã«ãçšããŠã質åæãåã蟌ã¿ãã¯ãã«ã«å€æãã
- 質åæã®åã蟌ã¿ãã¯ãã«ãšé¡äŒŒããå€ã®åã蟌ã¿ãã¯ãã«ãæã€ãã£ã³ã¯ãæ€çŽ¢ãã

åã蟌ã¿ãã¯ãã«ã®é¡äŒŒåºŠã«ããæ€çŽ¢
åã蟌ã¿ã¢ãã«ãçæããåã蟌ã¿ãã¯ãã«ã¯ãããããã®ããã¹ãã«å«ãŸããæ å ±ãæœè±¡çã«è¡šçŸãããã®ã§ã2ã€ã®ããã¹ãã«å«ãŸããæ å ±ãé¡äŒŒããŠããã°ãããããã®ããã¹ãããã¯ãé¡äŒŒããå€ã®åã蟌ã¿ãã¯ãã«ãçæãããŸãã
ãã ããåã蟌ã¿ãã¯ãã«ã衚çŸã§ããæ å ±éã«ã¯éçããããŸãã®ã§ãããŸããŸæ å ±ãå«ãã é·ããã£ã³ã¯ã®å Žåãæ€çŽ¢ã«å¿ èŠãªæ å ±ãé©åã«å«ãã åã蟌ã¿ãã¯ãã«ã®çæãé£ãããªããŸãããããããåã蟌ã¿ãã¯ãã«ã®éçãã§ææããå 容ã§ãã
çŸä»£ç㪠RAG ã®æŠç¥
åé ã§ãå°ããªãã£ã³ã¯ãå¿ èŠãªãæè¡çå¶çŽãã説æããŸããããLLM ãšåã蟌ã¿ã¢ãã«ã®é²åã«ããããããã¯éå»ã®ãã®ã«ãªãã€ã€ãããŸãããŸããLLM ã®ã³ã³ããã¹ããŠã£ã³ããŠã¯å€§å¹ ã«åºãããŸãããGemini 2.5 Flash ã§ããã°ãçŽ100äžããŒã¯ã³ãå ¥åå¯èœã§ãæ¥æ¬èªã§ããã°ã70äžã80äžåã«çžåœããŸãã
åŸã£ãŠããã»ã©å€§ããªãã¡ã€ã«ã§ãªããã°ãåççæã«å¿ èŠãªæ å ±ãå«ãã ããã¥ã¡ã³ãããã£ã³ã¯ã«åå²ããã«å ¥åããããšãå¯èœã§ããããã«ãGemini ã¯ãã«ãã¢ãŒãã«ã¢ãã«ã§ãã®ã§ãå³è¡šãå«ã PDF ãã¡ã€ã«ããã®ãŸãŸã®åœ¢ã§å ¥åããããšãã§ããŸããããããã°ã質åå 容ã«çŽæ¥é¢é£ããªãèæ¯æ å ±ãå«ããŠã該åœããã¥ã¡ã³ãã«å«ãŸãããã¹ãŠã®æ å ±ãèžãŸãããããé©åãªåçãçæã§ããŸãã
ãã ãããã®å Žåãããã¥ã¡ã³ãããã£ã³ã¯ã«åå²ããã®ã§ã¯ãªããããã¥ã¡ã³ãããšã«åã蟌ã¿ãã¯ãã«ãçæããŠãåçæã«åç §ããããã¥ã¡ã³ããæ€çŽ¢ããããã«ãå ã«è§Šãããåã蟌ã¿ã¢ãã«ã®éçããžã®å¯Ÿå¿ãå¿ èŠã§ããããŸããŸãªæ å ±ãå«ãããã¥ã¡ã³ãããããäž»èŠãªæ å ±ãããããªãå«ãåã蟌ã¿ãã¯ãã«ã¯çæã§ããã®ã§ããããïŒ
ãã®ç¹ã«ã€ããŠã¯ãããã¥ã¡ã³ããçŽæ¥åã蟌ã¿ãã¯ãã«ã«å€æããã®ã§ã¯ãªããäºåã« LLM ãçšããŠããææžã®ç®çã察象ãšãªãèªè ãè©²åœææžãæ¢ãéã«äœ¿ãããããªããŒã¯ãŒãããªã©ãæœåºããããã¹ããçæããŠããããåã蟌ã¿ãã¯ãã«ã«å€æããŸããããã«ã質åæã«ã€ããŠãåæ§ã«ãLLM ã§ãåçããããã«æ¢ãã¹ãæ å ±ãåçã«å«ãŸããããŒã¯ãŒãããªã©ãçæããŠããããåã蟌ã¿ãã¯ãã«ã«å€æããŸããããããã°ãã質åæããæ³å®ãããããŒã¯ãŒããã«ãã£ãŠã質åæãšå¯Ÿå¿ããããã¥ã¡ã³ããããŸããããã§ããŸãã
ãã®åŸã®ãã³ãºãªã³ã§çšãã顿ããå ·äœäŸã瀺ããŠãããŸããããæ°å®¿åºãå ¬éããŠãããæ°å®¿åºãããã®ã¬ã€ããã«å«ãŸããããã¿ïŒç°å¢ïŒãªãµã€ã¯ã«ããšããã¿ã€ãã«ã® PDF ãã¡ã€ã«ããã¯ã次ã®ãããªããã¹ããçæãããŸãããã®ããã¹ããåã蟌ã¿ãã¯ãã«ã«å€æãããã®ã䜿çšããŸãã
ããã¹ã1
ææžã¿ã€ãã«ïŒãã¿ïŒç°å¢ïŒãªãµã€ã¯ã«
ææžãµããªãŒïŒæ¬ææžã¯ãæ°å®¿åºã®äœæ°ããã³äºæ¥è
åãã«ããã¿ãšè³æºã®é©åãªåå¥ã»æåºæ¹æ³ã
ãªãµã€ã¯ã«ã«é¢ããæ
å ±ãæäŸããç·åã¬ã€ãã§ãã
...ïŒäžç¥ïŒ...
ãã¿ã®é©æ£åŠçã«é¢ããåçš®åãåããã¯ãåæž
æäºåæãæž
æã»ã³ã¿ãŒããã¿æžéãªãµã€ã¯ã«èª²ã
ç°å¢å¯Ÿç課ãžé£çµ¡ããããä¿ããŠããŸãã
æ€çŽ¢ããŒã¯ãŒãïŒãã¿ãè³æºããªãµã€ã¯ã«ãåå¥ãåºãæ¹ãç²å€§ãã¿ãçãããã¿ã
éå±ã»é¶åšã»ã¬ã©ã¹ãã¿ãå€çŽããã©ã¹ããã¯ãã³ãã»çŒ¶ã»ãããããã«ãã¹ãã¬ãŒçŒ¶ã
å®¶é»ãªãµã€ã¯ã«ãããœã³ã³ãªãµã€ã¯ã«ãäºæ¥ç³»ãã¿ãè·¯äžå«ç
ããã€æšãŠãåç©è¢«å®³ã
é²é³¥ããããéå£ååããªãµã€ã¯ã«æŽ»åã»ã³ã¿ãŒããšã³ã®ã£ã©ãªãŒæ°å®¿ãç°å¢çžè«ã
å
¬å®³çžè«ãã¯ããã¢ãã¿ãŒãæž
æäºåæãæž
æã»ã³ã¿ãŒãæ°å®¿åº
äžæ¹ããæè¿åŒã£è¶ããŠããã®ã§ãããå€ãé»åã¬ã³ãžãæšãŠãã«ã¯ã©ãããã°ããã§ããïŒããšãã質åæããã¯æ¬¡ã®ããã¹ããçæãããã®ã§ããããåã蟌ã¿ãã¯ãã«ã«å€æããŸãã
ããã¹ã2
é»åã¬ã³ãžã®åŠåæ¹æ³ã«ã€ããŠãèªæ²»äœã®ã¬ã€ãããã¯ãã以äžã®æ
å ±ãæ¢ããŠãã ããã
ãŸããé»åã¬ã³ãž åŠåæ¹æ³ããç²å€§ãã¿ é»åã¬ã³ãžããå°åå®¶é»ãªãµã€ã¯ã« é»åã¬ã³ãžã
ã®é
ç®ã確èªããŸãã
ç²å€§ãã¿ãšããŠåºãå Žåããç³ãèŸŒã¿æ¹æ³ïŒé»è©±ãã€ã³ã¿ãŒããããªã©ïŒããææ°æã
ãç²å€§ãã¿åŠçåžã®è³Œå
¥å Žæããå鿥ããåéå Žæããéç¹çã«æ¢ããŸãã
å°åå®¶é»ãªãµã€ã¯ã«ã®å¯Ÿè±¡ã§ããã°ããååããã¯ã¹èšçœ®å Žæããååæ¹æ³ãã確èªããŸãã
æž
æå·¥å ŽãåŠçæœèšãžã®ãæã¡èŸŒã¿ããå¯èœãããã®éã®ãæéããå仿éããæã¡èŸŒã¿å Žæã
ã確èªããŸãã
å®¶é»ãªãµã€ã¯ã«æ³ã®å¯Ÿè±¡å€ã§ããããšã念ã®ãã確èªãã誀ã£ãæ
å ±ã«æããããªãããã«ããŸãã
èªæ²»äœãæšå¥šãããäžçšåå忥è
ãã®æ
å ±ãããã°ããããåèã«ããŸããããã¿åå¥ã¬ã€ãã
ããã¿åºãã«ãŒã«ãã®é»åã¬ã³ãžã«é¢ããèšè¿°ã詳ãã調ã¹ãŸãããã
ããããã°ããããã¹ã1ãã¯ããããã¹ã2ãã«é¢é£ããæ å ±ãå«ãããšãæç¢ºã«ããããŸããã€ãŸããããã2ã€ã®ããã¹ãããçæãããåã蟌ã¿ãã¯ãã«ã¯é¡äŒŒåºŠãé«ããªãã質åã®åçã«å¿ èŠãªããã¥ã¡ã³ããã¡ã€ã«ã確å®ã«æ€çŽ¢ã§ããŸãã
æäœã RAG ã·ã¹ãã ãå®è£ ãã
æ°å®¿åºãå ¬éããŠãããæ°å®¿åºãããã®ã¬ã€ããïŒ20åçšåºŠã® PDF ææžïŒã«åºã¥ããŠãåºæ°ã®è³ªåã«åçããã³ã³ã·ã§ã«ãžã¥ AI ãäœæããŸãã
ããã§ã¯ã質åã®åçã«å¿ èŠãª PDF ããã¡ã€ã«åäœã§æ€çŽ¢ã»ç¹å®ããåŸã«ãããã3ã® PDF ããã®ãŸãŸããã³ããã«åã蟌ãã§åçãçæããã¢ãããŒããåããŸãããã®éã質åã«é¢é£ãã PDF ã¯æ¬¡ã®æ¹æ³ã§æ€çŽ¢ããŸãã
- å PDF ã®ãµããªãŒããã¹ããåã蟌ã¿ãã¯ãã«ïŒãµããªãŒãã¯ãã«ïŒã«å€æããŠãã
- 質åæãããæ€çŽ¢çšã¯ãšãªãŒããçæããŠããããåã蟌ã¿ãã¯ãã«ïŒã¯ãšãªãŒãã¯ãã«ïŒã«å€æãã
- ã¯ãšãªãŒãã¯ãã«ãšãµããªãŒãã¯ãã«é¡äŒŒåºŠããé¢é£æ§ãé«ã PDF ãç¹å®ãã
ãŸãã質åè ã®ãããã¡ã€ã«ãéå»ã®è³ªåãè£å©çã«å ¥åããããšã§ãããŒãœãã©ã€ãºãããåçãçæããä»çµã¿ãå®è£ ããŸãã
ç°å¢æºå
Vertex AI workbench ã®ããŒãããã¯äžã§å®è£ ããªãã説æããããã«ããŸãã¯ãããŒãããã¯ã®å®è¡ç°å¢ãçšæããŸããæ°ãããããžã§ã¯ããäœæããããCloud Shell ã®ã³ãã³ã端æ«ãéããŠãå¿ èŠãª API ãæå¹åããŸãã
gcloud services enable \
aiplatform.googleapis.com \
notebooks.googleapis.com \
cloudresourcemanager.googleapis.com
ãŸããGemini API ã GCS ãã±ããã«ã¢ã¯ã»ã¹ã§ããããã«ãIAM ããŒã«ãä»äžããŠãããŸãã
PROJECT_ID=$(gcloud config list --format 'value(core.project)' 2>/dev/null)
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)' 2>/dev/null)
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-aiplatform.iam.gserviceaccount.com" \
--role='roles/storage.objectUser'
ç¶ããŠãWorkbench ã®ã€ã³ã¹ã¿ã³ã¹ãäœæããŸãã
PROJECT_ID=$(gcloud config list --format 'value(core.project)')
gcloud workbench instances create rag-development \
--project=$PROJECT_ID \
--location=us-central1-a \
--machine-type=e2-standard-2
ã¯ã©ãŠãã³ã³ãœãŒã«ã®ããã²ãŒã·ã§ã³ã¡ãã¥ãŒãããVertex AIãâãWorkbenchããéžæãããšãäœæããã€ã³ã¹ã¿ã³ã¹ rag-development ããããŸããã€ã³ã¹ã¿ã³ã¹ã®èµ·åãå®äºããã®ãåŸ ã£ãŠããJUPYTERLAB ãéãããã¯ãªãã¯ãããããPython 3(ipykernel)ãã®æ°èŠããŒãããã¯ãäœæããŸãã
ãã®åŸã¯ãããŒãããã¯ã®ã»ã«ã§ã³ãŒããå®è¡ããŠãããŸãã
äºåæºå
å¿ èŠãªã¢ãžã¥ãŒã«ãã€ã³ããŒãããŠãSDK ã¯ã©ã€ã³ã¢ã³ããåæåããäžã§ãPDF ãã¡ã€ã«ãä¿åããã¹ãã¬ãŒãžãã±ãããäœæããŸãã
import os
import pickle
import requests
import numpy as np
import vertexai
from google import genai
from google.cloud import storage
from google.genai import types
from IPython.display import Markdown, display
# ãããžã§ã¯ãèšå®
[PROJECT_ID] = !gcloud config list --format 'value(core.project)'
LOCATION = 'us-central1'
# Vertex AI ãš Google GenAI ã® SDK ã¯ã©ã€ã¢ã³ããåæå
vertexai.init(project=PROJECT_ID, location=LOCATION)
client = genai.Client(vertexai=True, project=PROJECT_ID, location=LOCATION)
# PDF ãä¿åãããã±ãããäœæ
BUCKET = f'{PROJECT_ID}_ragdata'
!gsutil ls -b gs://{BUCKET} 2>/dev/null || \
gsutil mb -l {LOCATION} gs://{BUCKET}
ãæ°å®¿åºãããã®ã¬ã€ããã«å«ãŸãã PDF ãã¡ã€ã«ã®ã¿ã€ãã«ãšãã¡ã€ã«åãå®çŸ©ããŸãã
pdf_dict = {
'åºé·ã®æšæ¶': '000391171.pdf',
'åŒã£è¶ããããšã': '000391172.pdf',
'ããã': '000391174.pdf',
'ãããšãããšãã«åããŠ': '000391175.pdf',
'ãšãªã¢ã·ãã£ãŠã©ãŒã¯': '000391176.pdf',
'å
¬çæœèšçäžèЧ': '000391178.pdf',
'äž»ãªåºç«æœèšã®èšåäžèЧ': '000391179.pdf',
'çžè«': '000391180.pdf',
'åºåœ¹æãšç¹å¥åºåŒµæ': '000394761.pdf',
'ç·æ¥ã®ãšãïŒå®å¿å®å
š': '000391182.pdf',
'æç¶ãïŒå±åº': '000391183.pdf',
'å¥åº·ïŒè¡ç': '000391184.pdf',
'é«éœ¢è
çŠç¥': '000391185.pdf',
'ä»è·ä¿éº': '000391187.pdf',
'é害è
çŠç¥': '000391189.pdf',
'ãã®ä»ã®çŠç¥': '000391192.pdf',
'åã©ãïŒæè²': '000391194.pdf',
'æåïŒã¹ããŒã': '000391197.pdf',
'ãã¿ïŒç°å¢ïŒãªãµã€ã¯ã«': '000391199.pdf',
'çæŽ»ç°å¢': '000391201.pdf',
'äœå®
ïŒãŸã¡ã¥ãã': '000391203.pdf',
'ä»äºïŒçµå¶': '000391205.pdf',
'ååïŒèº«è¿ãªè¡æ¿': '000391206.pdf',
'ãããã®äŸ¿å©åž³2024幎çãããããïŒçŽ¢åŒïŒ': '000391177.pdf',
'å»çæ©é¢ãªã¹ã': '000391207.pdf'
}
å®çŸ©ãããã¡ã€ã«ãããŠã³ããŒãããŠãã¹ãã¬ãŒãžãã±ããã«ä¿åããŸãã
# Storage ã¯ã©ã€ã¢ã³ããšãã±ããã®æºå
storage_client = storage.Client()
bucket = storage_client.bucket(BUCKET)
print(f'Starting download and upload to gs://{BUCKET}/pdf/ ...')
for title, filename in pdf_dict.items():
url = f'https://www.city.shinjuku.lg.jp/content/{filename}'
try:
# PDFãããŠã³ããŒã
response = requests.get(url)
response.raise_for_status() # ãšã©ãŒãããã°äŸå€ãçºçããã
# ä¿åå
ã®ãã¹ãæå®
blob = bucket.blob(f'pdf/{filename}')
# ã¡ã¢ãªäžã®ã³ã³ãã³ããçŽæ¥ã¢ããããŒã
blob.upload_from_string(response.content, content_type='application/pdf')
print(f'Succeeded: {title} ({filename})')
except Exception as e:
print(f'Failed: {title} ({filename}) - Reason: {e}')
print('\nAll processes are complete.')
[åºåçµæ]
Starting download and upload to gs://your_project_ragdata/pdf/ ...
Succeeded: åºé·ã®æšæ¶ (000391171.pdf)
Succeeded: åŒã£è¶ããããšã (000391172.pdf)
Succeeded: ããã (000391174.pdf)
...ïŒäžç¥ïŒ...
Succeeded: å»çæ©é¢ãªã¹ã (000391207.pdf)
All processes are complete.
ããã¥ã¡ã³ãã®åã蟌ã¿ãã¯ãã«ãçæ
Gemini 2.5 Flash ãçšããŠãããããã® PDF ãã¡ã€ã«ã®ãµããªãŒããã¹ããçæããŸãã
# ä¿åçšãã¡ã€ã«å
PICKLE_FILE = 'summary_results.pkl'
if os.path.exists(PICKLE_FILE):
# --- ãã¡ã€ã«ãååšããå Žåã¯åŸ©å
---
print(f'Loading existing summary results from {PICKLE_FILE}...')
with open(PICKLE_FILE, 'rb') as f:
summary_results = pickle.load(f)
print(f'Successfully loaded {len(summary_results)} items.')
else:
# --- ãã¡ã€ã«ãååšããªãå Žåã¯çæ ---
print(f'{PICKLE_FILE} not found. Starting summarization with Gemini...')
summary_results = {}
for title, filename in pdf_dict.items():
gcs_uri = f'gs://{BUCKET}/pdf/{filename}'
system_instruction = f'''
ããªãã¯èªæ²»äœã®æ¡å
ä¿ã§ããæäŸãããPDFææžã®å
容ããåŸã§æ€çŽ¢ïŒRAGïŒã«å©çšããããã®ãµããªãŒãšããŠãŸãšããŠãã ããã
* 以äžã®ã¬ã€ãã©ã€ã³ã«åŸã£ãŠãã ããïŒ
1. ææžã®äž»èŠãªç®çãšå¯Ÿè±¡è
ãæç¢ºã«ããã
2. æç¶ããå¿
èŠãªå Žåã¯ããã®åç§°ãå Žæãå¿
èŠãªãã®ãããŒã¯ãŒããšããŠå«ããã
3. äœæ°ããã®ææžãæ¢ãéã«äœ¿ããããªæ€çŽ¢ã¯ãšãªïŒããŒã¯ãŒãïŒãæœåºããŠåºåããã
4. 以äžã®åœ¢åŒã§500æåçšåºŠã§åºåãããïŒãïŒãã®çŽåŸã¯æ¹è¡ããªãã3ã€ã®é
ç®ã®éã¯ç©ºè¡ã1è¡å
¥ãããïŒ
ææžã¿ã€ãã«ïŒ<ææžã¿ã€ãã«>
ææžãµããªãŒïŒ<ææžã®ãµããªãŒ>
æ€çŽ¢ããŒã¯ãŒãïŒ<ããŒã¯ãŒãããããã§åºåã£ãŠäžŠã¹ã>
'''
try:
response = client.models.generate_content(
model='gemini-2.5-flash',
contents=[
f'ææžã¿ã€ãã«: {title}',
types.Part.from_uri(file_uri=gcs_uri, mime_type='application/pdf'),
],
config=types.GenerateContentConfig(
system_instruction=system_instruction,
temperature=0.2
)
)
summary_results[title] = {
'filename': filename,
'summary': response.text
}
print(f'Succeeded: {title}')
except Exception as e:
print(f'Failed: {title} - Reason: {e}')
# çæããçµæãä¿å
with open(PICKLE_FILE, 'wb') as f:
pickle.dump(summary_results, f)
print(f'\nAll summarization processes are complete and saved to {PICKLE_FILE}.')
[åºåçµæ]
summary_results.pkl not found. Starting summarization with Gemini...
Succeeded: åºé·ã®æšæ¶
Succeeded: åŒã£è¶ããããšã
Succeeded: ããã
...ïŒäžç¥ïŒ...
Succeeded: å»çæ©é¢ãªã¹ã
All summarization processes are complete and saved to summary_results.pkl.
ããã§ã¯ãçæããçµæããã¡ã€ã« summary_results.pkl ã«ä¿åããŠããããã§ã«ãã®ãã¡ã€ã«ãããå Žåã¯ãå床çæããã®ã§ã¯ãªãããã¡ã€ã«ããå
容ã埩å
ããããã«ããŠãããŸãããããŠåçæããå Žåã¯ã次ã®ã³ãã³ãã§ãã¡ã€ã« summary_results.pkl ãåé€ããäžã§äžèšã®ã³ãŒããå®è¡ããŠãã ããã
os.remove('summary_results.pkl')
æåã®3ä»¶ã«ã€ããŠãçæãããå 容ã衚瀺ããŠç¢ºèªããŸãã
# å
容ã®ç¢ºèªïŒæåã®3ä»¶ã衚瀺ïŒ
for title in list(summary_results.keys())[:3]:
print('\n' + '-' * 30)
print(f'Summary text: {title}')
print('-' * 30)
print(summary_results[title]['summary'])
[åºåçµæ]
------------------------------
Summary text: åºé·ã®æšæ¶
------------------------------
ææžã¿ã€ãã«ïŒæ°å®¿åºãããã®ã¬ã€ã 2024幎çïŒåºé·æšæ¶ã»æŠèŠïŒ
ææžãµããªãŒïŒãã®ææžã¯ãæ°å®¿åºãããã®ã¬ã€ã 2024幎çãã®åé ããŒãžã§ãæ°å®¿åºé·
åäœå¥äžæ°ããã®æšæ¶ãšãã¬ã€ãã®æŠèŠãæ°å®¿åºã®åºæ¬æ
å ±ãç·æ¥é£çµ¡å
ãå¹³åéœåžå®£èšã
æ²èŒããŠããŸããã¬ã€ãã¯ãè¡æ¿ãµãŒãã¹ãå»çæ©é¢ãé²çœæ
å ±ãåºå
ã®æ£çã³ãŒã¹
ããšãªã¢ã·ãã£ãŠã©ãŒã¯ããªã©ãåºæ°ã®æ®ããã«åœ¹ç«ã€æ
å ±ã2幎ããšã«æŽæ°ããŠæäŸãç¹ã«
é²çœæ
å ±ã§ã¯ã倧éšã»å°é¢šãå°éãžã®åããçœå®³æ
å ±ã®å
¥ææ¹æ³ãçºçœæã®è¡åã解説ãã
ãšãªã¢ã·ãã£ãŠã©ãŒã¯ã§ã¯æ°å®¿åºã®é
åçãª12ã³ãŒã¹ã玹ä»ããŠããŸããåºã®çŽç« ãåºã®æš
ïŒãããïŒãåºã®è±ïŒã€ã€ãïŒãšãã£ãã·ã³ãã«ããèŠå¯ãæ¶é²ãææ¥çžè«ã»ã³ã¿ãŒãªã©ã®
ç·æ¥é£çµ¡å
ãæ²èŒãããŠãããåºæ°ãæ¥ã
ã®ç掻ãç·æ¥æã«æŽ»çšã§ããããä¿ããŠããŸãã
æ€çŽ¢ããŒã¯ãŒãïŒæ°å®¿åºããããã®ã¬ã€ããåºé·æšæ¶ãåäœå¥äžãé²çœæ
å ±ããšãªã¢ã·ãã£
ãŠã©ãŒã¯ãç·æ¥é£çµ¡å
ãå¹³åéœåžå®£èšãè¡æ¿ãµãŒãã¹ãå»çæ©é¢ãæ£çã³ãŒã¹ãæ°å®¿åºã®é
åã
çŽç« ãåºã®æšãåºã®è±
...ïŒä»¥äžçç¥ïŒ...
ç¶ããŠãåã蟌ã¿ã¢ãã« gemini-embedding-001 ãçšããŠãçæãããµããªãŒããã¹ãããåã蟌ã¿ãã¯ãã«ãçæããŸãã
# ä¿åçšãã¡ã€ã«å
EMB_PICKLE_FILE = 'embeddings_dict.pkl'
if os.path.exists(EMB_PICKLE_FILE):
# --- ãã¡ã€ã«ãååšããå Žåã¯åŸ©å
---
print(f'Loading existing embeddings from {EMB_PICKLE_FILE}...')
with open(EMB_PICKLE_FILE, 'rb') as f:
embeddings_dict = pickle.load(f)
print(f'Successfully loaded embeddings for {len(embeddings_dict)} documents.')
else:
# --- ãã¡ã€ã«ãååšããªãå Žåã¯çæ ---
print('Generating embeddings using gemini-embedding-001...')
embeddings_dict = {}
for title, data in summary_results.items():
summary_text = data['summary']
try:
# gemini-embedding-001 ã䜿çšããŠãã¯ãã«å
# task_type='RETRIEVAL_DOCUMENT' ãæå®
res = client.models.embed_content(
model='gemini-embedding-001',
contents=summary_text,
config=types.EmbedContentConfig(task_type='RETRIEVAL_DOCUMENT')
)
# ãã¯ãã«ïŒæ°å€é
åïŒãåãåºã
vector = res.embeddings[0].values
embeddings_dict[title] = {
'filename': data['filename'],
'embedding': vector
}
print(f'Succeeded: {title}')
except Exception as e:
print(f'Failed: {title} - Reason: {e}')
# çæããçµæãä¿å
with open(EMB_PICKLE_FILE, 'wb') as f:
pickle.dump(embeddings_dict, f)
print(f'\nAll embedding processes are complete and saved to {EMB_PICKLE_FILE}.')
[åºåçµæ]
Generating embeddings using gemini-embedding-001...
Succeeded: åºé·ã®æšæ¶
Succeeded: åŒã£è¶ããããšã
Succeeded: ããã
...ïŒäžç¥ïŒ...
Succeeded: å»çæ©é¢ãªã¹ã
All embedding processes are complete and saved to embeddings_dict.pkl.
ããã§ã¯ãçæããçµæããã¡ã€ã« embeddings_dict.pkl ã«ä¿åããŠããããã§ã«ãã®ãã¡ã€ã«ãããå Žåã¯ãå床çæããã®ã§ã¯ãªãããã¡ã€ã«ããå
容ã埩å
ããããã«ããŠãããŸãããããŠåçæããå Žåã¯ã次ã®ã³ãã³ãã§ãã¡ã€ã« embeddings_dict.pkl ãåé€ããäžã§äžèšã®ã³ãŒããå®è¡ããŠãã ããã
os.remove('embeddings_dict.pkl')
æåã®3ä»¶ã«ã€ããŠãçæãããåã蟌ã¿ãã¯ãã«ã衚瀺ããŠç¢ºèªããŸãã
# ããŒã¿ã®è©³çްã確èªïŒæåã®3ä»¶ã衚瀺ïŒ
for title in list(embeddings_dict.keys())[:3]:
sample_vector = embeddings_dict[title]['embedding']
print('-' * 30)
print(f'Document Title: {title}')
print(f'Vector Dimension: {len(sample_vector)}')
print(f'Vector (first 10 elements): {sample_vector[:10]}')
[åºåçµæ]
------------------------------
Document Title: åºé·ã®æšæ¶
Vector Dimension: 3072
Vector (first 10 elements): [-0.02220349758863449, -0.01842305436730385, 0.016044966876506805, -0.03509635105729103, -0.008716683834791183, 0.007425079122185707, -0.0057008275762200356, 0.007034968584775925, 0.0024815215729177, -0.009867820888757706]
------------------------------
Document Title: åŒã£è¶ããããšã
Vector Dimension: 3072
Vector (first 10 elements): [-0.01779654063284397, -0.01505563035607338, 0.017976151779294014, -0.025311468169093132, 0.00982920452952385, 0.003563973354175687, 0.016740581020712852, 0.012617745436728, 0.01656181551516056, -0.010555865243077278]
------------------------------
Document Title: ããã
Vector Dimension: 3072
Vector (first 10 elements): [-0.021430017426609993, -0.021420052275061607, 0.012420736253261566, -0.03364516794681549, -0.009396692737936974, 0.01008770801126957, -0.001109318109229207, 0.008338133804500103, 0.007491908501833677, -0.023767635226249695]
ããã§ã質åã®åçã«å¿ èŠãªåèæ å ±ïŒPDF ãã¡ã€ã«ãšæ€çŽ¢çšã®åã蟌ã¿ãã¯ãã«ïŒãçšæã§ããŸãããããããã¯ãäžãããã質åæããåèã«ãªã PDF ãã¡ã€ã«ãæ€çŽ¢ããäžã§åçãçæãããRAG ã®ä»çµã¿ãå®è£ ããŠãããŸãã
ããã¥ã¡ã³ãæ€çŽ¢æ©èœãå®è£
ãŸãã¯ã質åæã«åºã¥ããŠãåèã«ãªã PDF ãã¡ã€ã«ãæ€çŽ¢ãã颿°ãå®çŸ©ããŸãã
def search_relevant_documents(user_query, top_k=3):
# 1. Search query ãçæ
system_instruction = f'''
ãŠãŒã¶ãŒã®è³ªåã«å¯ŸããŠãèªæ²»äœã®ã¬ã€ãããã¯ããã©ã®ãããªæ
å ±ãæ¢ãã¹ããã
åçã«å«ãŸããã¹ãå
·äœçãªããŒã¯ãŒããå
容ã300æåçšåºŠã§æžãåºããŠãã ããã
ããã¯æ€çŽ¢çšã®ã¯ãšãªãšããŠäœ¿çšããŸãã
ããŒã¯ããŠã³ã䜿çšããªããã¬ã€ã³ããã¹ãã§åºåããããšã
'''
user_prompt = f'ãŠãŒã¶ãŒã®è³ªå: {user_query}'
response = client.models.generate_content(
model='gemini-2.5-flash',
contents=user_prompt,
config=types.GenerateContentConfig(
system_instruction=system_instruction,
temperature=0.2
)
)
search_query = response.text
# 2. search_query ããã¯ãã«å (RETRIEVAL_QUERY)
res = client.models.embed_content(
model='gemini-embedding-001',
contents=search_query,
config=types.EmbedContentConfig(task_type='RETRIEVAL_QUERY')
)
query_vector = np.array(res.embeddings[0].values)
# 3. ã³ãµã€ã³é¡äŒŒåºŠã®èšç®
similarities = []
for title, data in embeddings_dict.items():
doc_vector = np.array(data['embedding'])
# ã³ãµã€ã³é¡äŒŒåºŠã®æ°åŒ: (Aã»B) / (|A|*|B|)
score = np.dot(query_vector, doc_vector) / (np.linalg.norm(query_vector) * np.linalg.norm(doc_vector))
similarities.append((title, score))
# 4. ã¹ã³ã¢ã®é«ãé ã«ãœãŒã
sorted_similarities = sorted(similarities, key=lambda x: x[1], reverse=True)
return search_query, sorted_similarities[:top_k]
ããã§ã¯ã次ã®ã¹ãããã§åç §ãã PDF ãã¡ã€ã«ã3ã€éžãã§ããŸãã
- ã¹ããã1ïŒè³ªåæãããæ€çŽ¢çšã¯ãšãªãŒããçæãã
- ã¹ããã2ïŒæ€çŽ¢çšã¯ãšãªãŒããåã蟌ã¿ãã¯ãã«ãçæãã
- ã¹ããã3ïŒåã蟌ã¿ãã¯ãã«ã®é¡äŒŒåºŠã¹ã³ã¢ïŒã³ãµã€ã³é¡äŒŒåºŠïŒãèšç®ãã
- ã¹ããã4ïŒã¹ã³ã¢ã®é«ãé ã«ãœãŒãããŠãäžäœ3ä»¶ãéžæãã
ã¹ããã3ã§ã¯ãæ€çŽ¢çšã¯ãšãªãŒã®åã蟌ã¿ãã¯ãã«ïŒã¯ãšãªãŒãã¯ãã«ïŒã«å¯ŸããŠãå PDF ãã¡ã€ã«ã®ãµããªãŒããã¹ãã®åã蟌ã¿ãã¯ãã«ïŒãµããªãŒãã¯ãã«ïŒãšã®é¡äŒŒåºŠã¹ã³ã¢ãèšç®ããŠããŸããä»åã¯ãPDF ãã¡ã€ã«ã20åçšåºŠãªã®ã§ããã¹ãŠã®ãã¡ã€ã«ã«å¯Ÿããã¹ã³ã¢ãèšç®ããŠãããã»ã©æéã¯ããããŸããããæ€çŽ¢å¯Ÿè±¡ã®ãã¡ã€ã«æ°ãå¢ãããšãã®æ¹æ³ã§ã¯æéããããéããŸãããããŸã§ããã³ãºãªã³çšã®ç°¡æå®è£ ãšããŠçè§£ããŠãã ããã
é©åãªãã¡ã€ã«ãéžæãããããç°¡åãªè³ªåæã§è©ŠããŠã¿ãŸãããã
# --- ãã¹ãå®è¡ ---
question = 'æè¿åŒã£è¶ããŠããã®ã§ãããå€ãé»åã¬ã³ãžãæšãŠãã«ã¯ã©ãããã°ããã§ããïŒ'
print(f'User input: {question}')
search_query, results = search_relevant_documents(question)
print('\n--- Search query ---')
print(search_query)
print('\n--- Search result (top 3) ---')
for i, (title, score) in enumerate(results):
filename = embeddings_dict[title]['filename']
print(f'{i+1}. {title} (Score: {score:.4f}) - ãã¡ã€ã«: {filename}')
[åºåçµæ]
User input: æè¿åŒã£è¶ããŠããã®ã§ãããå€ãé»åã¬ã³ãžãæšãŠãã«ã¯ã©ãããã°ããã§ããïŒ
--- Search query ---
é»åã¬ã³ãžã®åŠåæ¹æ³ããã¿åå¥åºåãç²å€§ãã¿ãšããŠã®åºãæ¹ãå°åå®¶é»ãªãµã€ã¯ã«å¯Ÿè±¡ãã
æž
æã»ã³ã¿ãŒãžã®æã¡èŸŒã¿å¯åŠãææ°æãç³ãèŸŒã¿æ¹æ³ãå鿥ãåéå Žæãç²å€§ãã¿åŠçåžã®
賌å
¥å Žæãäžçšåå忥è
ã®å©çšæ¡å
ãå®¶é»ãªãµã€ã¯ã«æ³ã®å¯Ÿè±¡å€ã§ããããšã®ç¢ºèªã
é»åã¬ã³ãžã®ãµã€ãºãéãã«ããåé¡åºæºãæåºå Žæã®æå®ãäºåé£çµ¡ã®èŠåŠã
--- Search result (top 3) ---
1. ãã¿ïŒç°å¢ïŒãªãµã€ã¯ã« (Score: 0.7038) - ãã¡ã€ã«: 000391199.pdf
2. çæŽ»ç°å¢ (Score: 0.6162) - ãã¡ã€ã«: 000391201.pdf
3. ããã (Score: 0.6049) - ãã¡ã€ã«: 000391174.pdf
ããã¿ïŒç°å¢ïŒãªãµã€ã¯ã«ããçæŽ»ç°å¢ããªã©ããŽãã®åºãæ¹ã«é¢é£ããããã¥ã¡ã³ããéžæãããããšãããããŸãã
ããã§ãRAG ã·ã¹ãã ã®èŠãšãªãæ€çŽ¢æ©èœãå®è£ ã§ããŸãããæ¬¡ã¯ããããå©çšãããã³ã³ã·ã§ã«ãžã¥ AIããå®è£ ããŸãã
ã³ã³ã·ã§ã«ãžã¥ AI ãå®è£
質åæãšïŒå ã»ã©å®è£ ããæ€çŽ¢æ©èœã§éžã°ããïŒPDF ãã¡ã€ã«ãå ã«ããŠãåçãçæãã颿°ãå®è£ ããŸãã
def generate_final_answer(user_query, search_results):
# 1. ã³ã³ããã¹ããšããŠæž¡ã PDF ã® Part ãªã¹ããäœæ
# æ€çŽ¢çµæïŒäžäœ3ä»¶ïŒãããã¡ã€ã«åãåãåºããGCS URI ãäœæ
content_parts = []
found_titles = []
for title, score in search_results:
filename = embeddings_dict[title]['filename']
gcs_uri = f'gs://{BUCKET}/pdf/{filename}'
# PDF ã Part ãšããŠè¿œå
content_parts.append(
types.Part.from_uri(file_uri=gcs_uri, mime_type='application/pdf')
)
found_titles.append(title)
# 2. æçµåççšã®ããã³ãããäœæ
system_instruction = f'''
ããªãã¯èªæ²»äœã®èŠªåãªæ¡å
ä¿ã§ããæäŸããã{len(found_titles)}ã€ã®PDFè³æïŒ{", ".join(found_titles)}ïŒ
ã®å
容ã«åºã¥ããŠããŠãŒã¶ãŒã®è³ªåã«æ£ç¢ºã«ããã€åãããããçããŠãã ããã
çŽæ¥ã®åç以å€ã«ãåèã«ãªããããªæ
å ±ãè£è¶³ããŠãã ããã
å¶çŽäºé
ïŒ
- è³æã«èšèŒãããŠããå
容ã®ã¿ã«åºã¥ããŠåçããŠãã ãããåçå
ã«ãæäŸãããè³æã«ãããšããªã©ã®æèšã¯äžèŠã§ãã
- è³æã«æ
å ±ããªãå Žåã¯ãæäŸãããè³æã®äžã«ã¯ããã®è³ªåã«é¢ããæ
å ±ãèŠåœãããŸããã§ããããšæ£çŽã«çããŠãã ããã
- ã©ã®è³æãåèã«ããããæåŸã«ä»ãå ããŠãã ããã
'''
# 質åæãæåŸã«è¿œå
content_parts.append(f'\n質åïŒ{user_query}')
# 3. Gemini 2.5 Flash ã«ããæçµåçã®çæ
try:
response = client.models.generate_content(
model='gemini-2.5-flash',
contents=content_parts,
config=types.GenerateContentConfig(
system_instruction=system_instruction,
temperature=0.2
)
)
return response.text
except Exception as e:
return f'åççæäžã«ãšã©ãŒãçºçããŸãã: {e}'
ããã§ã¯ã次ã®ã¹ãããã§åçãçæããŠããŸãã
- ã¹ããã1ïŒæå®ããã PDF ãã¡ã€ã«ã URI æå®ã§ããã³ããã«åã蟌ã
- ã¹ããã2ïŒåççæçšã®ããã³ãããæ§æãã
- ã¹ããã3ïŒGemini 2.5 Flash ã§åçãçæãã
Google Cloud ã®ç°å¢ã§ Gemini API ã䜿çšããéã¯ãCloud Storage ã«ä¿åãããã¡ã€ã«ã gs://... ãšãã圢åŒã® URI ã§ããã³ããã«åã蟌ãããšãã§ããã®ã§ãã¹ããã1ã§ã¯ãã®æ©èœãå©çšããŠããŸãã
ãããŸã§ã«çšæãã颿°ãçµã¿åãããŠãå ·äœçãªè³ªåããåçãçæããŠã¿ãŸãããã
# --- å
šè¡çšãçµ±åããå®è¡ãã¹ã ---
# 質åäŸ
question = 'æè¿åŒã£è¶ããŠããã®ã§ãããå€ãé»åã¬ã³ãžãæšãŠãã«ã¯ã©ãããã°ããã§ããïŒ'
print(f'User input: {question}')
# ã¹ããã1: é¢é£ããã¥ã¡ã³ãã®æ€çŽ¢ïŒäžäœ3ä»¶ïŒ
search_query, search_results = search_relevant_documents(question, top_k=3)
# ã¹ããã2: æçµåçã®çæ
final_answer = generate_final_answer(question, search_results)
print('\n--- Search query ---')
print(search_query)
print('\n--- Search result ---')
for i, (title, score) in enumerate(search_results):
filename = embeddings_dict[title]['filename']
print(f'{i+1}. {title} (Score: {score:.4f}) - ãã¡ã€ã«: {filename}')
# --- æŽåœ¢ããŠè¡šç€º ---
print('\n--- Final answer ---')
display(Markdown(final_answer))
[åºåçµæ]
User input: æè¿åŒã£è¶ããŠããã®ã§ãããå€ãé»åã¬ã³ãžãæšãŠãã«ã¯ã©ãããã°ããã§ããïŒ
--- Search query ---
é»åã¬ã³ãžã®åŠåæ¹æ³ã«ã€ããŠãèªæ²»äœã®ã¬ã€ãããã¯ãã以äžã®æ
å ±ãæ¢ããŸãããŸãã
é»åã¬ã³ãžããç²å€§ãã¿ããŸãã¯ãå°åå®¶é»ãªãµã€ã¯ã«ãã®ã©ã¡ãã«åé¡ããããã確èª
ããŸããç²å€§ãã¿ã®å Žåãç³ãèŸŒã¿æ¹æ³ïŒé»è©±ãã€ã³ã¿ãŒãããïŒãå鿥ãåéå Žæã
ææ°æãç²å€§ãã¿åŠçåžã®è³Œå
¥å Žæãšè²Œãæ¹ãå°åå®¶é»ãªãµã€ã¯ã«å¯Ÿè±¡ã®å Žåã¯ãåå
ããã¯ã¹ã®èšçœ®å Žæãšåå察象åç®ããŸããæž
æã»ã³ã¿ãŒãåŠçæœèšãžã®çŽæ¥æã¡èŸŒã¿ã®
å¯åŠãæã¡èŸŒã¿æ¹æ³ãææ°æãå®¶é»ãªãµã€ã¯ã«æ³å¯Ÿè±¡åç®ã§ã¯ãªãããšã®ç¢ºèªãäžçšååå
æ¥è
ãå©çšããå Žåã®æ³šæç¹ãæšå¥šæ¥è
ãªã¹ãã確èªããŸãã
--- Search result ---
1. ãã¿ïŒç°å¢ïŒãªãµã€ã¯ã« (Score: 0.7349) - ãã¡ã€ã«: 000391199.pdf
2. ããã (Score: 0.6724) - ãã¡ã€ã«: 000391174.pdf
3. äœå®
ïŒãŸã¡ã¥ãã (Score: 0.6690) - ãã¡ã€ã«: 000391203.pdf
--- Final answer ---
<æŽåœ¢è¡šç€ºãããæçµåç>
æåŸã® <æŽåœ¢è¡šç€ºãããæçµåç> ã«ã¯ã次ã®ããã«ããŒã¯ããŠã³ãæŽåœ¢è¡šç€ºããçµæã瀺ãããŸãã

ããŒãœãã©ã€ãŒãŒã·ã§ã³æ©èœã®è¿œå
å ã»ã©äœæãã颿°ããŠãŒã¶ãŒãããã¡ã€ã«ãšéå»ã®è³ªåå±¥æŽãå ¥åã§ããããã«æ¡åŒµããŸãã
def generate_personalized_answer(user_query, search_results, user_profile, past_history):
# 1. ã³ã³ããã¹ãã®æ§ç¯ïŒPDFããããã¡ã€ã«ãå±¥æŽããŸãšããïŒ
content_parts = []
# ãŠãŒã¶ãŒã®ãããã¡ã€ã«ãšå±¥æŽãããã¹ãããŒããšããŠè¿œå
user_context_text = f'''
# ãŠãŒã¶ãŒãããã¡ã€ã«:
{user_profile}
# éå»ã®è³ªåå±¥æŽ:
{past_history}
'''
content_parts.append(user_context_text)
# æ€çŽ¢ã§ããããã PDF ã远å
found_titles = []
for title, score in search_results:
filename = embeddings_dict[title]['filename']
gcs_uri = f'gs://{BUCKET}/pdf/{filename}'
content_parts.append(
types.Part.from_uri(file_uri=gcs_uri, mime_type='application/pdf')
)
found_titles.append(title)
# ãŠãŒã¶ãŒã®è³ªåã远å
content_parts.append(f'\n質åïŒ{user_query}')
# 2. ã·ã¹ãã æç€ºã®æŽæ°
system_instruction = f'''
ããªãã¯èªæ²»äœã®èŠªåãªæ¡å
ä¿ã§ãã以äžã®æé ã§åçãäœæããŠãã ããã
1. å°å
¥ã¡ãã»ãŒãžïŒæšæ¶ïŒ:
ãŠãŒã¶ãŒãããã¡ã€ã«ãšéå»ã®è³ªåå±¥æŽã確èªããåé ã§ãŠãŒã¶ãŒã«åããã芪ãã¿ãããæšæ¶ãè¡ã£ãŠãã ããã
ïŒäŸïŒä»¥åã®çžè«å
容ã«è§ŠããããŠãŒã¶ãŒã®ç¶æ³ãæ°é£ããªã©ïŒ
ãã ããäžèªç¶ã«ãªããªãããããã€å人æ
å ±ã«é
æ
®ããäžå¯§ãªããŒã³ãç¶æããŠãã ããã
2. æ¬é¡ã®åç:
æäŸããã{len(found_titles)}ã€ã®PDFè³æïŒ{", ".join(found_titles)}ïŒã«åºã¥ãã
質åã«æ£ç¢ºã«ããã€åãããããçããŠãã ãããçŽæ¥ã®åç以å€ã«ãåèã«ãªããããªæ
å ±ãè£è¶³ããŠãã ããã
å¶çŽäºé
ïŒ
- è³æã«èšèŒãããŠããå
容ã®ã¿ã«åºã¥ããŠåçããŠãã ãããåçå
ã«ãæäŸãããè³æã«ãããšããªã©ã®æèšã¯äžèŠã§ãã
- è³æã«æ
å ±ããªãå Žåã¯ãæäŸãããè³æã®äžã«ã¯ããã®è³ªåã«é¢ããæ
å ±ãèŠåœãããŸããã§ããããšæ£çŽã«çããŠãã ããã
3. åºå
žã®æèš:
æåŸã«åç
§ããè³æåãèšèŒããŠãã ããã
'''
# 3. Gemini ã«ããçæ
response = client.models.generate_content(
model='gemini-2.5-flash',
contents=content_parts,
config=types.GenerateContentConfig(
system_instruction=system_instruction,
temperature=0.2
)
)
return response.text
ããã§ã¯ã質åã®åçãçæããéã«ããŠãŒã¶ãŒãããã¡ã€ã«ãšéå»ã®è³ªåå±¥æŽã«å¿ããæšæ¶ã远å ããããã«æç€ºããŠããŸãããµã³ãã«ããŒã¿ãçšããŠåçãçæããŠã¿ãŸãããã
# --- å®è¡ã€ã¡ãŒãž ---
# ãµã³ãã«ããŒã¿ïŒå®é㯠DB ããã¡ã€ã«ããèªã¿èŸŒãæ³å®ïŒ
user_profile = '''
æ±äº¬åšäœ30ä»£ç·æ§
åºèº«å°ïŒå€§éª
ååïŒå
·ã
é¡ èµäºº
è·æ¥ïŒITäŒæ¥ã«å€ãããšã³ãžãã¢ã
å®¶æïŒåŠ»ãšå°åŠçã®åšãäžäººããã
'''
past_history = '''
- 2024-12-10: ãæ°å®¿åºå
ã«ã¯è¶£å³ã§PythonãåŠã¹ããããªå匷äŒãã³ãã¥ããã£ã¯ãããŸããïŒã
- 2025-01-15: ãå°åŠçã®åäŸã«ã€ããŠãæ°å®¿åºã§å©çšã§ããæè²æåœã婿éãæããŠãã
'''
question = 'å€äŒã¿ã«åšãšåºãããåºå
ã®ã¹ããããæããŠã'
print(f'User input: {question}')
# æ€çŽ¢ã®å®è¡
search_query, search_results = search_relevant_documents(question, top_k=3)
# ããŒãœãã©ã€ãºãããåçã®çæ
final_answer = generate_personalized_answer(question, search_results, user_profile, past_history)
# çµæã衚瀺
print('\n--- Search query ---')
print(search_query)
print('\n--- Search result ---')
for i, (title, score) in enumerate(search_results):
filename = embeddings_dict[title]['filename']
print(f'{i+1}. {title} (Score: {score:.4f}) - ãã¡ã€ã«: {filename}')
print('\n--- Final answer ---')
display(Markdown(final_answer))
[åºåçµæ]
User input: å€äŒã¿ã«åšãšåºãããåºå
ã®ã¹ããããæããŠã
--- Search query ---
èªæ²»äœã®ã¬ã€ãããã¯ã§ãå€äŒã¿ããåäŸåããã芪åããå®¶æããã€ãã³ãããã¹ãããã
ãéã³å Žããäžå¿ã«ãç®æ¬¡ã玢åŒãæ¬æãæ€çŽ¢ããŸããå
·äœçã«ã¯ããå€å£éå®ã€ãã³ãã
ãæ°Žéã³ãã§ããå
¬åããããŒã«éæŸæ
å ±ããæ¶Œããå±å
æœèšïŒåç©é€šãç§åŠé€šã峿žé€šãªã©ïŒã
ãäœéšåŠç¿ããã¯ãŒã¯ã·ã§ããããå€ç¥ãããåç©åããæ°Žæé€šããšãã£ãé
ç®ã確èªããŸãã
éšã®æ¥ã§ã楜ãããå Žæããç¡æã§å©çšã§ããæœèšãæ¢ããšè¯ãã§ããããåæœèšã®é通æéã
äŒé€šæ¥ãæéã察象幎霢ãäºåäºçŽã®èŠäžèŠãåãããŠç¢ºèªããåšãããšäžç·ã«æ¥œãããå Žæã
èŠã€ããŸãã
--- Search result ---
1. ããã (Score: 0.7149) - ãã¡ã€ã«: 000391174.pdf
2. åã©ãïŒæè² (Score: 0.7096) - ãã¡ã€ã«: 000391194.pdf
3. æåïŒã¹ããŒã (Score: 0.7027) - ãã¡ã€ã«: 000391197.pdf
--- Final answer ---
<æŽåœ¢è¡šç€ºãããæçµåç>
<æŽåœ¢è¡šç€ºãããæçµåç> ã«ã¯ã次ã®ããã«ããŒã¯ããŠã³ãæŽåœ¢è¡šç€ºããçµæã瀺ãããŸãã

質åæã§ã¯ãåšããšããèšã£ãŠãŸãããããããã¡ã€ã«æ å ±ããå°åŠçã®åšã§ããããšãçè§£ããäžã§ã®åçãçæãããŸããã
æ¬çªã·ã¹ãã ã«åããèæ ®ç¹
ä»åã®ãã³ãºãªã³ã§ã¯ãRAG ã®ä»çµã¿ãçè§£ããããã«ããæäœã RAG ã·ã¹ãã ããæ§ç¯ããŸããããã®ä»çµã¿ãå®éã®ãµãŒãã¹ãšããŠå ¬éããéã¯ãã¹ã±ãŒã©ããªãã£ãšã»ãã¥ãªãã£ãžã®å¯Ÿå¿ããããŠãåçã®å質ãç¶ç¶çã«ç¶æããä»çµã¿ãå¿ èŠã§ããããã§ã¯ããããã®èгç¹ã§ã®èæ ®ç¹ãæŽçããŠãããŸãã
ã¹ã±ãŒã©ããªãã£ãšããŒã¿ç®¡çã®èªåå
ä»åã®æ§æã§ã¯ãåã蟌ã¿ãã¯ãã«ã®ããŒã¿ã®ãã¹ãŠã Python ã®ãã£ã¯ã·ã§ããªãŒã«ä¿åããŠå©çšããŸããããå®éçšã§å€§éã®ããã¥ã¡ã³ããæ±ãéã¯ã次ã®ãããªèæ ®ãå¿ èŠã§ãã
-
ãã¯ãã«æ€çŽ¢ãšã³ãžã³ã®å©çšïŒå€§èŠæš¡ãªããŒã¿ããããªç§åäœã§é¡äŒŒåºŠæ€çŽ¢ãè¡ãã«ã¯ãVertex AI Vector Search ã®ãããªãè¿åæ¢çŽ¢ã«ç¹åãããããŒãžããµãŒãã¹ãæå¹ã§ãã
-
ããŒã¿æŽæ°ã®ãã€ãã©ã€ã³åïŒPDF ãã¡ã€ã«ã远å ã»æŽæ°ããããã³ã«æåã§åã蟌ã¿ãã¯ãã«ãçæããã®ã§ã¯ãªããCloud Storage ãžã®ã¢ããããŒããããªã¬ãŒã«åã蟌ã¿ãã¯ãã«ãèªåçæããä»çµã¿ãå¿ èŠã§ãã
-
ãã«ãããŒãžã㪠RAG ãµãŒãã¹ãžã®ç§»è¡ïŒæ€çŽ¢ç²ŸåºŠãéçšã®æéãèãããšãæäœãã·ã¹ãã ãããVertex AI Search ãžåãæ¿ããæ¹æ³ããããŸããããã¥ã¡ã³ãã®ããŒã¹ããã£ã³ã¯åå²ãåã蟌ã¿ãã¯ãã«ã®çæãæ€çŽ¢ãšãã£ãäžé£ã®åŠçãèªååã§ããŸãã
ã»ãã¥ãªãã£ãšã¬ããã³ã¹ã®ç¢ºä¿
èªæ²»äœãäŒæ¥ã®ããŒã¿ãæ±ãå Žåã¯ãæ å ±ã®ä¿è·ã«ãèæ ®ãå¿ èŠã§ãããæäœã RAG ã·ã¹ãã ãã«ã¯å«ãŸããªããæ¬¡ã®ãããªèгç¹ã«ã泚æãå¿ èŠã§ãã
-
èªèšŒã»èªå¯ã®å³æ ŒåïŒã·ã¹ãã ãžã®ã¢ã¯ã»ã¹æš©éã¯ãã¡ããããã©ã®ãŠãŒã¶ãŒãã©ã®ææžãé²èЧã§ãããããšãããã¡ã€ã«åäœã®ã»ãã¥ãªãã£å¶åŸ¡ãèæ ®ãå¿ èŠã§ãã
-
å人æ å ±ïŒPIIïŒã®ä¿è·ïŒããŒãœãã©ã€ãŒãŒã·ã§ã³ã§å©çšããããŠãŒã¶ãŒãããã¡ã€ã«ããã質åå±¥æŽãã«ã¯ãæ©å¯æ§ã®é«ãæ å ±ãå«ãŸããå¯èœæ§ããããŸããCloud DLP ãå©çšããŠãæ©å¯æ å ±ãèªåã§å¿ååã»ãã¹ãã³ã°ããä»çµã¿ãæ€èšãããšããã§ãããã
-
ãããã¯ãŒã¯å¢çã®ä¿è·ïŒããŒã¿ãå€éšãžæŒæŽ©ãããªã¹ã¯ãæå°éã«æãããããVPC Service Controls ãå©çšããŠãã·ã¹ãã ã䜿çšãããªãœãŒã¹ããã©ã€ããŒããªãããã¯ãŒã¯å ã«éã蟌ããŸãã
åçå質ã®è©äŸ¡ãšãªãã¶ãŒãããªãã£
RAG ã·ã¹ãã ã§ã¯ãåçé床ãåçã®è³ªã客芳çã«è©äŸ¡ããŠãç¶ç¶çã«ã¢ãã¿ãªã³ã°ããä»çµã¿ãå¿ èŠã§ãã
-
RAG ã«ç¹åããææšã«ããè©äŸ¡ïŒãåçã«ãã«ã·ããŒã·ã§ã³ãå«ãŸããŠããªããïŒå¿ 宿§ïŒãã質åã«å¯ŸããŠé©åãªæ€çŽ¢ãã§ããŠãããïŒé¢é£æ§ïŒããšãã£ã芳ç¹ããGen AI Evaluation Service ãªã©ãçšããŠå®éçã«æž¬å®ããŸãã
-
ã³ã¹ããšã¬ã€ãã³ã·ã®æé©åïŒGemini 2.5 ProïŒé«ç²ŸåºŠïŒãš Gemini 2.5 FlashïŒé«éã»å®äŸ¡ïŒãã¿ã¹ã¯ã®é£æåºŠã«å¿ããŠäœ¿ãåããã«ãŒãã£ã³ã°åŠçãå°å ¥ããŠããŠãŒã¶ãŒäœéšãšã³ã¹ãããã©ãŒãã³ã¹ãäž¡ç«ããŸãã
-
æ ¹æ ã®æç€ºïŒã°ã©ãŠã³ãã£ã³ã°ïŒïŒãŠãŒã¶ãŒãåçã®æ å ±æºã確èªã§ããããã«ãçæãããåçããPDF ã®ã©ã®ç®æã«åºã¥ããŠãããããåŒçšå ãšããŠæç€ºããã¯ã³ã¯ãªãã¯ã§äžæ¬¡ãœãŒã¹ã確èªã§ãã UI ãæäŸããŸãã
ãŸãšã
ãã®èšäºã§ã¯ãVertex AI Search ãªã©ã®ãããŒãžããµãŒãã¹ã䜿ããã«ãPython ãš Gemini API ãçµã¿åããããæäœã RAG ã·ã¹ãã ããæ§ç¯ããŸããããã®ãã³ãºãªã³ãéããŠã次ã®ãã€ã³ãã確èªã§ããŸããã
-
RAG ã¯ãæ€çŽ¢ããšãçæãã®çµã¿åãã
粟床ã®é«ãåçãåŸãã«ã¯ãLLM ã®æ§èœã«é Œãã ãã§ã¯ãªããããã«é©åãªã³ã³ããã¹ãïŒè³æïŒãèŠã€ãåºãããšããæ€çŽ¢ããã»ã¹ã®èšèšãéèŠã§ãã -
LLM ã«ãããååŠçãã®å¹æ
ä»åã¯ãããã¥ã¡ã³ãããã£ã³ã¯ã«åå²ããã®ã§ã¯ãªããããã¥ã¡ã³ãåäœã§æ€çŽ¢ããŠãåççæã®ããã³ããã«å ¥åããææ³ãæ¡çšããŸããããã®éãããã¥ã¡ã³ãããã®ãŸãŸãã¯ãã«åããã®ã§ã¯ãªããLLM ã§ãµããªãŒãããŒã¯ãŒããæœåºããããšã§ãæ€çŽ¢ç²ŸåºŠãåäžããããšã説æããŸãããããã¯ããã³ã°ã³ã³ããã¹ããæŽ»çšãããçŸä»£ç㪠RAG ã®ææ³ãšèšããŸãã -
ããŒãœãã©ã€ãºã®å¿çš
ãŠãŒã¶ãŒã®ãããã¡ã€ã«ãéå»ã®æèãããã³ããã«è¿œå ããããšã§ãããŒãœãã©ã€ãºãããåçãçæã§ããããšã確èªããŸããã
å®éã®æ¥åã·ã¹ãã ã§ã¯ãããããããã«ããã€ããªããæ€çŽ¢ïŒãã¯ãã«æ€çŽ¢ + ããŒã¯ãŒãæ€çŽ¢ïŒã®å°å ¥ãæ€çŽ¢çµæã®ãªã©ã³ãã³ã°ãªã©ã«ãããæ€çŽ¢ç²ŸåºŠãããã«åäžãã工倫ãããããšããããŸããä»åã®ãã³ãºãªã³ã§ RAG ã®è£åŽã«ããããžãã¯ãçè§£ããŠããã°ãGoogle Cloud ã®åçš®ãããŒãžããµãŒãã¹ãå©çšããéããããããäžã§äœãããŠããã®ãããçè§£ããŠãããé«åºŠãªãã¥ãŒãã³ã°ãã§ããããã«ãªãã§ãããã
Discussion