🤖 āĻ—ā§āϰāĻžāĻĢ RAG, ADK āĻāĻŦāĻ‚ āĻŽā§‡āĻŽā§‹āϰāĻŋ āĻŦā§āϝāĻžāĻ‚āĻ• āĻĻāĻŋāϝāĻŧ⧇ āĻāĻ•āϟāĻŋ āĻŽāĻžāĻ˛ā§āϟāĻŋāĻŽā§‹āĻĄāĻžāϞ AI āĻāĻœā§‡āĻ¨ā§āϟ āϤ⧈āϰāĻŋ āĻ•āϰ⧁āύ

1. āĻ­ā§‚āĻŽāĻŋāĻ•āĻž

āφāĻŦāϰāĻŖ

ā§§. āĻšā§āϝāĻžāϞ⧇āĻžā§āϜ

āĻĻ⧁āĻ°ā§āϝ⧋āĻ— āĻŽā§‹āĻ•āĻžāĻŦ⧇āϞāĻžāϰ āĻĒāϰāĻŋāĻ¸ā§āĻĨāĻŋāϤāĻŋāϤ⧇, āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āύ āĻ¸ā§āĻĨāĻžāύ⧇ āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āύ āĻĻāĻ•ā§āώāϤāĻž, āϏāĻŽā§āĻĒāĻĻ āĻāĻŦāĻ‚ āϚāĻžāĻšāĻŋāĻĻāĻžāϰ āϏāĻžāĻĨ⧇ āĻŦ⧇āρāĻšā§‡ āĻĨāĻžāĻ•āĻž āĻŦā§āϝāĻ•ā§āϤāĻŋāĻĻ⧇āϰ āϏāĻŽāĻ¨ā§āĻŦāϝāĻŧ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻŦ⧁āĻĻā§āϧāĻŋāĻŽāĻžāύ āĻĄā§‡āϟāĻž āĻŦā§āϝāĻŦāĻ¸ā§āĻĨāĻžāĻĒāύāĻž āĻāĻŦāĻ‚ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻ•ā§āώāĻŽāϤāĻž āĻĒā§āϰāϝāĻŧā§‹āϜāύāĨ¤ āĻāχ āĻ•āĻ°ā§āĻŽāĻļāĻžāϞāĻž āφāĻĒāύāĻžāϕ⧇ āĻāĻ•āϟāĻŋ āĻ‰ā§ŽāĻĒāĻžāĻĻāύ āĻ•ā§ƒāĻ¤ā§āϰāĻŋāĻŽ āĻŦ⧁āĻĻā§āϧāĻŋāĻŽāĻ¤ā§āϤāĻž āĻŦā§āϝāĻŦāĻ¸ā§āĻĨāĻž āϤ⧈āϰāĻŋ āĻ•āϰāϤ⧇ āĻļ⧇āĻ–āĻžāϝāĻŧ āϝāĻž āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āĻŦāĻŋāώāϝāĻŧāϗ⧁āϞāĻŋāϕ⧇ āĻāĻ•āĻ¤ā§āϰāĻŋāϤ āĻ•āϰ⧇:

  1. đŸ—„ī¸ āĻ—ā§āϰāĻžāĻĢ āĻĄāĻžāϟāĻžāĻŦ⧇āϏ (āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ) : āĻŦ⧇āρāĻšā§‡ āĻĨāĻžāĻ•āĻž āĻŦā§āϝāĻ•ā§āϤāĻŋ, āĻĻāĻ•ā§āώāϤāĻž āĻāĻŦāĻ‚ āϏāĻŽā§āĻĒāĻĻ⧇āϰ āĻŽāĻ§ā§āϝ⧇ āϜāϟāĻŋāϞ āϏāĻŽā§āĻĒāĻ°ā§āĻ• āϏāĻ‚āϰāĻ•ā§āώāĻŖ āĻ•āϰ⧁āύ
  2. 🔍 āĻāφāχ-āϚāĻžāϞāĻŋāϤ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ : āĻāĻŽā§āĻŦ⧇āĻĄāĻŋāĻ‚ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āĻļāĻŦā§āĻĻāĻžāĻ°ā§āĻĨāĻŋāĻ• + āϕ⧀āĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ āĻšāĻžāχāĻŦā§āϰāĻŋāĻĄ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ
  3. 📸 āĻŽāĻžāĻ˛ā§āϟāĻŋāĻŽā§‹āĻĄāĻžāϞ āĻĒā§āϰāϏ⧇āϏāĻŋāĻ‚ : āĻ›āĻŦāĻŋ, āĻŸā§‡āĻ•ā§āϏāϟ āĻāĻŦāĻ‚ āĻ­āĻŋāĻĄāĻŋāĻ“ āĻĨ⧇āϕ⧇ āĻ¸ā§āĻŸā§āϰāĻžāĻ•āϚāĻžāĻ°ā§āĻĄ āĻĄā§‡āϟāĻž āĻŦ⧇āϰ āĻ•āϰ⧁āύ
  4. 🤖 āĻŽāĻžāĻ˛ā§āϟāĻŋ-āĻāĻœā§‡āĻ¨ā§āϟ āĻ…āĻ°ā§āϕ⧇āĻ¸ā§āĻŸā§āϰ⧇āĻļāύ : āϜāϟāĻŋāϞ āĻ•āĻ°ā§āĻŽāĻĒā§āϰāĻŦāĻžāĻšā§‡āϰ āϜāĻ¨ā§āϝ āĻŦāĻŋāĻļ⧇āώāĻžāϝāĻŧāĻŋāϤ āĻāĻœā§‡āĻ¨ā§āϟāĻĻ⧇āϰ āϏāĻŽāĻ¨ā§āĻŦāϝāĻŧ āĻ•āϰ⧁āύ
  5. 🧠 āĻĻā§€āĻ°ā§āϘāĻŽā§‡āϝāĻŧāĻžāĻĻā§€ āĻ¸ā§āĻŽā§ƒāϤāĻŋ : āĻ­āĻžāĻ°ā§āĻŸā§‡āĻ•ā§āϏ āĻāφāχ āĻŽā§‡āĻŽā§‹āϰāĻŋ āĻŦā§āϝāĻžāĻ‚āϕ⧇āϰ āϏāĻžāĻšāĻžāĻ¯ā§āϝ⧇ āĻŦā§āϝāĻ•ā§āϤāĻŋāĻ—āϤāĻ•āϰāĻŖ

āĻ•āĻĨā§‹āĻĒāĻ•āĻĨāύ

⧍. āϤ⧁āĻŽāĻŋ āϕ⧀ āϤ⧈āϰāĻŋ āĻ•āϰāĻŦ⧇

āĻāĻ•āϟāĻŋ āϏāĻžāϰāĻ­āĻžāχāĻ­āĻžāϰ āύ⧇āϟāĻ“āϝāĻŧāĻžāĻ°ā§āĻ• āĻ—ā§āϰāĻžāĻĢ āĻĄāĻžāϟāĻžāĻŦ⧇āϏ āϝāĻžāϰ āϏāĻžāĻĨ⧇:

  • đŸ—ēī¸ āĻŦ⧇āρāĻšā§‡ āĻĨāĻžāĻ•āĻž āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇āϰ 3D āχāĻ¨ā§āϟāĻžāϰ⧇āĻ•ā§āϟāĻŋāĻ­ āĻ—ā§āϰāĻžāĻĢ āĻ­āĻŋāĻœā§āϝ⧁āϝāĻŧāĻžāϞāĻžāχāĻœā§‡āĻļāύ
  • 🔍 āĻŦ⧁āĻĻā§āϧāĻŋāĻŽāĻžāύ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ (āϕ⧀āĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ, āĻļāĻŦā§āĻĻāĻžāĻ°ā§āĻĨāĻŋāĻ• āĻāĻŦāĻ‚ āĻšāĻžāχāĻŦā§āϰāĻŋāĻĄ)
  • 📸 āĻŽāĻžāĻ˛ā§āϟāĻŋāĻŽā§‹āĻĄāĻžāϞ āφāĻĒāϞ⧋āĻĄ āĻĒāĻžāχāĻĒāϞāĻžāχāύ (āĻ›āĻŦāĻŋ/āĻ­āĻŋāĻĄāĻŋāĻ“ āĻĨ⧇āϕ⧇ āϏāĻ¤ā§āϤāĻž āĻŦ⧇āϰ āĻ•āϰ⧁āύ)
  • 🤖 āϜāϟāĻŋāϞ āĻ•āĻžāĻœā§‡āϰ āϜāĻ¨ā§āϝ āĻŽāĻžāĻ˛ā§āϟāĻŋ-āĻāĻœā§‡āĻ¨ā§āϟ āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽ
  • 🧠 āĻŦā§āϝāĻ•ā§āϤāĻŋāĻ—āϤāĻ•ā§ƒāϤ āĻŽāĻŋāĻĨāĻ¸ā§āĻ•ā§āϰāĻŋāϝāĻŧāĻžāϰ āϜāĻ¨ā§āϝ āĻŽā§‡āĻŽā§‹āϰāĻŋ āĻŦā§āϝāĻžāĻ‚āĻ• āχāĻ¨ā§āϟāĻŋāĻ—ā§āϰ⧇āĻļāύ

ā§Š. āĻŽā§‚āϞ āĻĒā§āϰāϝ⧁āĻ•ā§āϤāĻŋ

āωāĻĒāĻžāĻĻāĻžāύ

āĻĒā§āϰāϝ⧁āĻ•ā§āϤāĻŋ

āωāĻĻā§āĻĻ⧇āĻļā§āϝ

āĻĄāĻžāϟāĻžāĻŦ⧇āϏ

āĻ•ā§āϞāĻžāωāĻĄ āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ āĻ—ā§āϰāĻžāĻĢ

āĻ¸ā§āĻŸā§‹āϰ āύ⧋āĻĄ (āĻŦ⧇āρāĻšā§‡ āĻĨāĻžāĻ•āĻž āĻŦā§āϝāĻ•ā§āϤāĻŋ, āĻĻāĻ•ā§āώāϤāĻž) āĻāĻŦāĻ‚ āĻĒā§āϰāĻžāĻ¨ā§āϤ (āϏāĻŽā§āĻĒāĻ°ā§āĻ•)

āĻāφāχ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ

āĻŽāĻŋāĻĨ⧁āύ + āĻāĻŽā§āĻŦ⧇āĻĄāĻŋāĻ‚

āĻļāĻŦā§āĻĻāĻžāĻ°ā§āĻĨāĻŋāĻ• āĻŦā§‹āϧāĻ—āĻŽā§āϝāϤāĻž + āϏāĻžāĻĻ⧃āĻļā§āϝ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ

āĻāĻœā§‡āĻ¨ā§āϟ āĻĢā§āϰ⧇āĻŽāĻ“āϝāĻŧāĻžāĻ°ā§āĻ•

ADK (āĻāĻœā§‡āĻ¨ā§āϟ āĻĄā§‡āϭ⧇āϞāĻĒāĻŽā§‡āĻ¨ā§āϟ āĻ•āĻŋāϟ)

āĻāφāχ āĻ•āĻ°ā§āĻŽāĻĒā§āϰāĻŦāĻžāĻšā§‡āϰ āĻŦā§āϝāĻŦāĻ¸ā§āĻĨāĻž āĻ•āϰ⧁āύ

āĻ¸ā§āĻŽā§ƒāϤāĻŋ

āĻ­āĻžāĻ°ā§āĻŸā§‡āĻ•ā§āϏ āĻāφāχ āĻŽā§‡āĻŽā§‹āϰāĻŋ āĻŦā§āϝāĻžāĻ‚āĻ•

āĻĻā§€āĻ°ā§āϘāĻŽā§‡āϝāĻŧāĻžāĻĻā§€ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āĻĒāĻ›āĻ¨ā§āĻĻ⧇āϰ āϏāĻžā§āϚāϝāĻŧāĻ¸ā§āĻĨāĻžāύ

āĻĢā§āϰāĻ¨ā§āϟāĻāĻ¨ā§āĻĄ

āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋāϝāĻŧāĻž + āĻĨā§āϰāĻŋ.āĻœā§‡āĻāϏ

āχāĻ¨ā§āϟāĻžāϰ⧇āĻ•ā§āϟāĻŋāĻ­ 3D āĻ—ā§āϰāĻžāĻĢ āĻ­āĻŋāĻœā§āϝ⧁āϝāĻŧāĻžāϞāĻžāχāĻœā§‡āĻļāύ

⧍. āĻĒāϰāĻŋāĻŦ⧇āĻļāĻ—āϤ āĻĒā§āϰāĻ¸ā§āϤ⧁āϤāĻŋ (āĻ•āĻ°ā§āĻŽāĻļāĻžāϞāĻžāϝāĻŧ āĻĨāĻžāĻ•āϞ⧇ āĻāĻĄāĻŧāĻŋāϝāĻŧ⧇ āϝāĻžāύ)

āĻĒā§āϰāĻĨāĻŽ āĻ…āĻ‚āĻļ: āĻŦāĻŋāϞāĻŋāĻ‚ āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āϟ āϏāĻ•ā§āώāĻŽ āĻ•āϰ⧁āύ

  • ā§Ģ āĻĄāϞāĻžāϰ āĻ•ā§āϰ⧇āĻĄāĻŋāϟ āĻĻāĻŋā§Ÿā§‡ āφāĻĒāύāĻžāϰ āĻŦāĻŋāϞāĻŋāĻ‚ āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āϟ āĻĻāĻžāĻŦāĻŋ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ, āφāĻĒāύāĻžāϰ āĻāϟāĻŋ āĻ¸ā§āĻĨāĻžāĻĒāύ⧇āϰ āϜāĻ¨ā§āϝ āĻĒā§āϰāϝāĻŧā§‹āϜāύ āĻšāĻŦ⧇āĨ¤ āφāĻĒāύāĻžāϰ āϜāĻŋāĻŽā§‡āχāϞ āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āϟāϟāĻŋ āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰ⧁āύāĨ¤

āĻĻā§āĻŦāĻŋāϤ⧀āϝāĻŧ āĻ…āĻ‚āĻļ: āωāĻ¨ā§āĻŽā§āĻ•ā§āϤ āĻĒāϰāĻŋāĻŦ⧇āĻļ

  1. 👉 āϏāϰāĻžāϏāϰāĻŋ āĻ•ā§āϞāĻžāωāĻĄ āĻļ⧇āϞ āĻāĻĄāĻŋāϟāϰ⧇ āϝ⧇āϤ⧇ āĻāχ āϞāĻŋāĻ™ā§āϕ⧇ āĻ•ā§āϞāĻŋāĻ• āĻ•āϰ⧁āύāĨ¤
  2. 👉 āφāϜāχ āϝāĻĻāĻŋ āϝ⧇āϕ⧋āύ⧋ āϏāĻŽāϝāĻŧ āĻ…āύ⧁āĻŽā§‹āĻĻāύ⧇āϰ āĻ…āύ⧁āϰ⧋āϧ āϜāĻžāύāĻžāύ⧋ āĻšāϝāĻŧ, āϤāĻžāĻšāϞ⧇ āϚāĻžāϞāĻŋāϝāĻŧ⧇ āϝ⧇āϤ⧇ āĻ…āύ⧁āĻŽā§‹āĻĻāύ⧇ āĻ•ā§āϞāĻŋāĻ• āĻ•āϰ⧁āύāĨ¤ āĻ•ā§āϞāĻžāωāĻĄ āĻļ⧇āϞ āĻ…āύ⧁āĻŽā§‹āĻĻāύ āĻ•āϰāϤ⧇ āĻ•ā§āϞāĻŋāĻ• āĻ•āϰ⧁āύ
  3. 👉 āϝāĻĻāĻŋ āĻ¸ā§āĻ•ā§āϰāĻŋāύ⧇āϰ āύ⧀āĻšā§‡ āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞāϟāĻŋ āύāĻž āĻĻ⧇āĻ–āĻž āϝāĻžā§Ÿ, āϤāĻžāĻšāϞ⧇ āĻāϟāĻŋ āϖ⧁āϞ⧁āύ:
    • āĻ­āĻŋāω āĻ•ā§āϞāĻŋāĻ• āĻ•āϰ⧁āύ
    • āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ āĻ•ā§āϞāĻŋāĻ• āĻ•āϰ⧁āύ āĻ•ā§āϞāĻžāωāĻĄ āĻļ⧇āϞ āĻāĻĄāĻŋāϟāϰ⧇ āύāϤ⧁āύ āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ āϖ⧁āϞ⧁āύ
  4. 👉đŸ’ģ āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ⧇, āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āĻ•āĻŽāĻžāĻ¨ā§āĻĄ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āϝāĻžāϚāĻžāχ āĻ•āϰ⧁āύ āϝ⧇ āφāĻĒāύāĻŋ āχāϤāĻŋāĻŽāĻ§ā§āϝ⧇āχ āĻĒā§āϰāĻŽāĻžāĻŖā§€āĻ•āϰāĻŖāĻĒā§āϰāĻžāĻĒā§āϤ āĻāĻŦāĻ‚ āĻĒā§āϰāĻ•āĻ˛ā§āĻĒāϟāĻŋ āφāĻĒāύāĻžāϰ āĻĒā§āϰāĻ•āĻ˛ā§āĻĒ āφāχāĻĄāĻŋāϤ⧇ āϏ⧇āϟ āĻ•āϰāĻž āφāϛ⧇:
    gcloud auth list
    
  5. 👉đŸ’ģ GitHub āĻĨ⧇āϕ⧇ āĻŦ⧁āϟāĻ¸ā§āĻŸā§āĻ°ā§āϝāĻžāĻĒ āĻĒā§āϰāĻ•āĻ˛ā§āĻĒāϟāĻŋ āĻ•ā§āϞ⧋āύ āĻ•āϰ⧁āύ:
    git clone https://github.com/google-americas/way-back-home.git
    

3. āĻĒāϰāĻŋāĻŦ⧇āĻļ āϏ⧇āϟāφāĻĒ

ā§§. āφāϰāĻŽā§āĻ­ āĻ•āϰ⧁āύ

āĻ•ā§āϞāĻžāωāĻĄ āĻļ⧇āϞ āĻāĻĄāĻŋāϟāϰ āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ⧇, āϝāĻĻāĻŋ āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞāϟāĻŋ āĻ¸ā§āĻ•ā§āϰāĻŋāύ⧇āϰ āύ⧀āĻšā§‡ āύāĻž āĻĻ⧇āĻ–āĻž āϝāĻžāϝāĻŧ, āϤāĻžāĻšāϞ⧇ āĻāϟāĻŋ āϖ⧁āϞ⧁āύ:

  • āĻ­āĻŋāω āĻ•ā§āϞāĻŋāĻ• āĻ•āϰ⧁āύ
  • āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ āĻ•ā§āϞāĻŋāĻ• āĻ•āϰ⧁āύ

āĻ•ā§āϞāĻžāωāĻĄ āĻļ⧇āϞ āĻāĻĄāĻŋāϟāϰ⧇ āύāϤ⧁āύ āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ āϖ⧁āϞ⧁āύ

👉đŸ’ģ āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ⧇, init āĻ¸ā§āĻ•ā§āϰāĻŋāĻĒā§āϟāϟāĻŋ āĻāĻ•ā§āϏāĻŋāĻ•āĻŋāωāĻŸā§‡āĻŦāϞ āĻ•āϰ⧁āύ āĻāĻŦāĻ‚ āĻāϟāĻŋ āϚāĻžāϞāĻžāύ:

cd ~/way-back-home/level_2
./init.sh

2. āĻĒā§āϰāĻ•āĻ˛ā§āĻĒ āĻ•āύāĻĢāĻŋāĻ—āĻžāϰ āĻ•āϰ⧁āύ

👉đŸ’ģ āφāĻĒāύāĻžāϰ āĻĒā§āϰ⧋āĻœā§‡āĻ•ā§āϟ āφāχāĻĄāĻŋ āϏ⧇āϟ āĻ•āϰ⧁āύ:

gcloud config set project $(cat ~/project_id.txt) --quiet

👉đŸ’ģ āĻĒā§āĻ°ā§Ÿā§‹āϜāĻ¨ā§€ā§Ÿ API āϗ⧁āϞāĻŋ āϏāĻ•ā§āώāĻŽ āĻ•āϰ⧁āύ (āĻāϤ⧇ ~⧍-ā§Š āĻŽāĻŋāύāĻŋāϟ āϏāĻŽāϝāĻŧ āϞāĻžāϗ⧇):

gcloud services enable compute.googleapis.com \
                       aiplatform.googleapis.com \
                       run.googleapis.com \
                       cloudbuild.googleapis.com \
                       artifactregistry.googleapis.com \
                       spanner.googleapis.com \
                       storage.googleapis.com

ā§Š. āϏ⧇āϟāφāĻĒ āĻ¸ā§āĻ•ā§āϰāĻŋāĻĒā§āϟ āϚāĻžāϞāĻžāύ

👉đŸ’ģ āϏ⧇āϟāφāĻĒ āĻ¸ā§āĻ•ā§āϰāĻŋāĻĒā§āϟāϟāĻŋ āĻ•āĻžāĻ°ā§āϝāĻ•āϰ āĻ•āϰ⧁āύ:

cd ~/way-back-home/level_2
./setup.sh

āĻāϟāĻŋ āφāĻĒāύāĻžāϰ āϜāĻ¨ā§āϝ .env āϤ⧈āϰāĻŋ āĻ•āϰāĻŦ⧇āĨ¤ āφāĻĒāύāĻžāϰ āĻ•ā§āϞāĻžāωāĻĄāĻļ⧇āϞ⧇, way_back_home āĻĒā§āϰāĻœā§‡āĻ•ā§āϟ āϖ⧁āϞ⧁āύāĨ¤ level_2 āĻĢā§‹āĻ˛ā§āĻĄāĻžāϰ⧇āϰ āĻ…āϧ⧀āύ⧇, āφāĻĒāύāĻŋ āĻĻ⧇āĻ–āϤ⧇ āĻĒāĻžāĻŦ⧇āύ āϝ⧇ .env āĻĢāĻžāχāϞāϟāĻŋ āφāĻĒāύāĻžāϰ āϜāĻ¨ā§āϝ āϤ⧈āϰāĻŋ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇āĨ¤ āϝāĻĻāĻŋ āφāĻĒāύāĻŋ āĻāϟāĻŋ āϖ⧁āρāĻœā§‡ āύāĻž āĻĒāĻžāύ, āϤāĻžāĻšāϞ⧇ āφāĻĒāύāĻŋ āĻāϟāĻŋ āĻĻ⧇āĻ–āϤ⧇ View -> Toggle Hidden File āĻ•ā§āϞāĻŋāĻ• āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤ āĻ“āĻĒ⧇āύ_āĻĒā§āϰāĻœā§‡āĻ•ā§āϟ

ā§Ē. āύāĻŽā§āύāĻž āĻĄā§‡āϟāĻž āϞ⧋āĻĄ āĻ•āϰ⧁āύ

👉đŸ’ģ āĻŦā§āϝāĻžāĻ•āĻāĻ¨ā§āĻĄā§‡ āύ⧇āĻ­āĻŋāϗ⧇āϟ āĻ•āϰ⧁āύ āĻāĻŦāĻ‚ āύāĻŋāĻ°ā§āĻ­āϰāϤāĻž āχāύāĻ¸ā§āϟāϞ āĻ•āϰ⧁āύ:

cd ~/way-back-home/level_2/backend
uv sync

👉đŸ’ģ āĻĒā§āϰāĻžāĻĨāĻŽāĻŋāĻ• āĻŦ⧇āρāĻšā§‡ āĻĨāĻžāĻ•āĻž āϤāĻĨā§āϝ āϞ⧋āĻĄ āĻ•āϰ⧁āύ:

uv run python ~/way-back-home/level_2/backend/setup_data.py

āĻāϟāĻŋ āϤ⧈āϰāĻŋ āĻ•āϰ⧇:

  • āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ āχāύāĻ¸ā§āĻŸā§āϝāĻžāĻ¨ā§āϏ ( survivor-network )
  • āĻĄāĻžāϟāĻžāĻŦ⧇āϏ ( graph-db )
  • āϏāĻ•āϞ āύ⧋āĻĄ āĻāĻŦāĻ‚ āĻāϜ āĻŸā§‡āĻŦāĻŋāϞ
  • āϕ⧋āϝāĻŧ⧇āϰāĻŋ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āϏāĻŽā§āĻĒāĻ¤ā§āϤāĻŋ āĻ—ā§āϰāĻžāĻĢ āĻĒā§āϰāĻ¤ā§āϝāĻžāĻļāĻŋāϤ āφāωāϟāĻĒ⧁āϟ :
============================================================
SUCCESS! Database setup complete.
============================================================

Instance:  survivor-network
Database:  graph-db
Graph:     SurvivorGraph

Access your database at:
https://console.cloud.google.com/spanner/instances/survivor-network/databases/graph-db?project=waybackhome

āφāωāϟāĻĒ⧁āĻŸā§‡ Access your database at āĻĒāϰ⧇ āϞāĻŋāĻ™ā§āϕ⧇ āĻ•ā§āϞāĻŋāĻ• āĻ•āϰāϞ⧇, āφāĻĒāύāĻŋ Google Cloud Console Spanner āϖ⧁āϞāϤ⧇ āĻĒāĻžāϰāĻŦ⧇āύāĨ¤

āĻ“āĻĒ⧇āύ_āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ

āφāϰ āϤ⧁āĻŽāĻŋ āϗ⧁āĻ—āϞ āĻ•ā§āϞāĻžāωāĻĄ āĻ•āύāϏ⧋āϞ⧇ āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ āĻĻ⧇āĻ–āϤ⧇ āĻĒāĻžāĻŦ⧇!

āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ

ā§Ē. āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ āĻ¸ā§āϟ⧁āĻĄāĻŋāĻ“āϤ⧇ āĻ—ā§āϰāĻžāĻĢ āĻĄā§‡āϟāĻž āĻ­āĻŋāĻœā§āϝ⧁āϝāĻŧāĻžāϞāĻžāχāϜ āĻ•āϰāĻž

āĻāχ āύāĻŋāĻ°ā§āĻĻ⧇āĻļāĻŋāĻ•āĻžāϟāĻŋ āφāĻĒāύāĻžāϕ⧇ āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ āĻ¸ā§āϟ⧁āĻĄāĻŋāĻ“ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āϗ⧁āĻ—āϞ āĻ•ā§āϞāĻžāωāĻĄ āĻ•āύāϏ⧋āϞ⧇ āϏāϰāĻžāϏāϰāĻŋ āϏāĻžāϰāĻ­āĻžāχāĻ­āĻžāϰ āύ⧇āϟāĻ“āϝāĻŧāĻžāĻ°ā§āĻ• āĻ—ā§āϰāĻžāĻĢ āĻĄā§‡āϟāĻž āĻ•āĻ˛ā§āĻĒāύāĻž āĻ•āϰāϤ⧇ āĻāĻŦāĻ‚ āϤāĻžāϰ āϏāĻžāĻĨ⧇ āχāĻ¨ā§āϟāĻžāϰāĻ…ā§āϝāĻžāĻ•ā§āϟ āĻ•āϰāϤ⧇ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰ⧇āĨ¤ āφāĻĒāύāĻžāϰ āĻāφāχ āĻāĻœā§‡āĻ¨ā§āϟ āϤ⧈āϰāĻŋ āĻ•āϰāĻžāϰ āφāϗ⧇ āφāĻĒāύāĻžāϰ āĻĄā§‡āϟāĻž āϝāĻžāϚāĻžāχ āĻ•āϰāĻžāϰ āĻāĻŦāĻ‚ āĻ—ā§āϰāĻžāĻĢ āĻ•āĻžāĻ āĻžāĻŽā§‹ āĻŦā§‹āĻāĻžāϰ āĻāϟāĻŋ āĻāĻ•āϟāĻŋ āĻĻ⧁āĻ°ā§āĻĻāĻžāĻ¨ā§āϤ āωāĻĒāĻžāϝāĻŧāĨ¤

ā§§. āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ āĻ¸ā§āϟ⧁āĻĄāĻŋāĻ“ āĻ…ā§āϝāĻžāĻ•ā§āϏ⧇āϏ āĻ•āϰ⧁āύ

  1. āĻļ⧇āώ āϧāĻžāĻĒ⧇, āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰ⧁āύ āϝ⧇ āφāĻĒāύāĻŋ āϞāĻŋāĻ™ā§āĻ•āϟāĻŋāϤ⧇ āĻ•ā§āϞāĻŋāĻ• āĻ•āϰ⧇āϛ⧇āύ āĻāĻŦāĻ‚ āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ āĻ¸ā§āϟ⧁āĻĄāĻŋāĻ“āϟāĻŋ āϖ⧁āϞāϛ⧇āύāĨ¤

āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ_āĻ¸ā§āϟ⧁āĻĄāĻŋāĻ“

2. āĻ—ā§āϰāĻžāĻĢ āĻ•āĻžāĻ āĻžāĻŽā§‹ āĻŦā§‹āĻāĻž ("āĻŦāĻĄāĻŧ āĻ›āĻŦāĻŋ")

āϏāĻžāϰāĻ­āĻžāχāĻ­āĻžāϰ āύ⧇āϟāĻ“āϝāĻŧāĻžāĻ°ā§āĻ• āĻĄā§‡āϟāĻžāϏ⧇āϟāϕ⧇ āĻāĻ•āϟāĻŋ āϞāϜāĻŋāĻ• āĻĒāĻžāϜāϞ āĻŦāĻž āĻāĻ•āϟāĻŋ āϗ⧇āĻŽ āĻ¸ā§āĻŸā§‡āϟ āĻšāĻŋāϏ⧇āĻŦ⧇ āĻ­āĻžāĻŦ⧁āύ:

āϏāĻ¤ā§āϤāĻž

āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽā§‡ āĻ­ā§‚āĻŽāĻŋāĻ•āĻž

āωāĻĒāĻŽāĻž

āĻŦ⧇āρāĻšā§‡ āĻĨāĻžāĻ•āĻž āĻŦā§āϝāĻ•ā§āϤāĻŋāϰāĻž

āĻāĻœā§‡āĻ¨ā§āϟ/āϖ⧇āϞ⧋āϝāĻŧāĻžāĻĄāĻŧāϰāĻž

āϖ⧇āϞ⧋āϝāĻŧāĻžāĻĄāĻŧāϰāĻž

āĻŦāĻžāϝāĻŧā§‹āĻŽ

āϤāĻžāϰāĻž āϕ⧋āĻĨāĻžāϝāĻŧ āĻ…āĻŦāĻ¸ā§āĻĨāĻŋāϤ

āĻŽāĻžāύāϚāĻŋāĻ¤ā§āϰ āĻ…āĻžā§āϚāϞ

āĻĻāĻ•ā§āώāϤāĻž

āϤāĻžāϰāĻž āĻ•āĻŋ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇

āĻ•ā§āώāĻŽāϤāĻž

āϚāĻžāĻšāĻŋāĻĻāĻž

āϤāĻžāĻĻ⧇āϰ āϕ⧀ āĻ…āĻ­āĻžāĻŦ (āϏāĻ™ā§āĻ•āϟ)

āϕ⧋āϝāĻŧ⧇āĻ¸ā§āϟ/āĻŽāĻŋāĻļāύ

āϰāĻŋāϏ⧋āĻ°ā§āϏ

āĻĒ⧃āĻĨāĻŋāĻŦā§€āϤ⧇ āĻĒāĻžāĻ“āϝāĻŧāĻž āϜāĻŋāύāĻŋāϏāĻĒāĻ¤ā§āϰ

āϞ⧁āϟ

āϞāĻ•ā§āĻˇā§āϝ : āĻāφāχ āĻāĻœā§‡āĻ¨ā§āĻŸā§‡āϰ āĻ•āĻžāϜ āĻšāϞ āĻĻāĻ•ā§āώāϤāĻž (āϏāĻŽāĻžāϧāĻžāύ) āϕ⧇ āϚāĻžāĻšāĻŋāĻĻāĻž (āϏāĻŽāĻ¸ā§āϝāĻž) āĻāϰ āϏāĻžāĻĨ⧇ āϏāĻ‚āϝ⧁āĻ•ā§āϤ āĻ•āϰāĻž, āϜ⧈āĻŦāĻŋāĻ• (āĻ…āĻŦāĻ¸ā§āĻĨāĻžāύ⧇āϰ āϏ⧀āĻŽāĻžāĻŦāĻĻā§āϧāϤāĻž) āĻŦāĻŋāĻŦ⧇āϚāύāĻž āĻ•āϰ⧇āĨ¤

🔗 āĻĒā§āϰāĻžāĻ¨ā§āϤ (āϏāĻŽā§āĻĒāĻ°ā§āĻ•):

  • SurvivorInBiome : āĻ…āĻŦāĻ¸ā§āĻĨāĻžāύ āĻŸā§āĻ°ā§āϝāĻžāĻ•āĻŋāĻ‚
  • SurvivorHasSkill : āĻĻāĻ•ā§āώāϤāĻžāϰ āϤāĻžāϞāĻŋāĻ•āĻž
  • SurvivorHasNeed : āϏāĻ•ā§āϰāĻŋāϝāĻŧ āϏāĻŽāĻ¸ā§āϝāĻžāϰ āϤāĻžāϞāĻŋāĻ•āĻž
  • SurvivorFoundResource : āφāχāĻŸā§‡āĻŽā§‡āϰ āϤāĻžāϞāĻŋāĻ•āĻž
  • SurvivorCanHelp : āĻ…āύ⧁āĻŽāĻžāύāĻ•ā§ƒāϤ āϏāĻŽā§āĻĒāĻ°ā§āĻ• (āĻāφāχ āĻāϟāĻŋ āĻ—āĻŖāύāĻž āĻ•āϰ⧇!)

ā§Š. āĻ—ā§āϰāĻžāĻĢāϟāĻŋ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻ•āϰāĻž

āĻĄā§‡āϟāĻžāϤ⧇ "āĻ—āĻ˛ā§āĻĒ" āĻĻ⧇āĻ–āĻžāϰ āϜāĻ¨ā§āϝ āĻ•āϝāĻŧ⧇āĻ•āϟāĻŋ āϕ⧋āϝāĻŧ⧇āϰāĻŋ āϰāĻžāύ āĻ•āϰāĻž āϝāĻžāĻ•āĨ¤

āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ āĻ—ā§āϰāĻžāĻĢ GQL (āĻ—ā§āϰāĻžāĻĢ āϕ⧋āϝāĻŧ⧇āϰāĻŋ āĻ˛ā§āϝāĻžāĻ™ā§āϗ⧁āϝāĻŧ⧇āϜ) āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇āĨ¤ āĻāĻ•āϟāĻŋ āϕ⧋āϝāĻŧ⧇āϰāĻŋ āϚāĻžāϞāĻžāύ⧋āϰ āϜāĻ¨ā§āϝ, GRAPH SurvivorNetwork āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύ āĻāĻŦāĻ‚ āϤāĻžāϰāĻĒāϰ⧇ āφāĻĒāύāĻžāϰ āĻŽā§āϝāĻžāϚ āĻĒā§āϝāĻžāϟāĻžāĻ°ā§āύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύāĨ¤

👉 āĻĒā§āϰāĻļā§āύ ā§§: āĻ—ā§āϞ⧋āĻŦāĻžāϞ āϰ⧋āĻ¸ā§āϟāĻžāϰ (āϕ⧇ āϕ⧋āĻĨāĻžāϝāĻŧ?) āĻāϟāĻŋ āφāĻĒāύāĻžāϰ āĻ­āĻŋāĻ¤ā§āϤāĻŋ - āωāĻĻā§āϧāĻžāϰ āĻ…āĻ­āĻŋāϝāĻžāύ⧇āϰ āϜāĻ¨ā§āϝ āĻ…āĻŦāĻ¸ā§āĻĨāĻžāύ āĻŦā§‹āĻāĻž āĻ…āĻ¤ā§āϝāĻ¨ā§āϤ āϗ⧁āϰ⧁āĻ¤ā§āĻŦāĻĒā§‚āĻ°ā§āĻŖāĨ¤

GRAPH SurvivorNetwork
MATCH result = (s:Survivors)-[:SurvivorInBiome]->(b:Biomes)
RETURN TO_JSON(result) AS json_result

āύ⧀āĻšā§‡āϰ āĻŽāϤ āĻĢāϞāĻžāĻĢāϞ āĻĻ⧇āĻ–āϤ⧇ āφāĻļāĻž āĻ•āϰāĻŋ: āĻ•ā§āϝ⧋āϝāĻŧāĻžāϰ⧀⧧

👉 āĻĒā§āϰāĻļā§āύ ⧍: āĻĻāĻ•ā§āώāϤāĻž āĻŽā§āϝāĻžāĻŸā§āϰāĻŋāĻ•ā§āϏ (āĻ•ā§āώāĻŽāϤāĻž) āĻāĻ–āύ āφāĻĒāύāĻŋ āϜāĻžāύ⧇āύ āϝ⧇ āϏāĻŦāĻžāχ āϕ⧋āĻĨāĻžāϝāĻŧ , āϤāĻžāϰāĻž āϕ⧀ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇ āϤāĻž āϖ⧁āρāĻœā§‡ āĻŦ⧇āϰ āĻ•āϰ⧁āύāĨ¤

GRAPH SurvivorNetwork
MATCH result = (s:Survivors)-[h:SurvivorHasSkill]->(k:Skills)
RETURN TO_JSON(result) AS json_result

āύ⧀āĻšā§‡āϰ āĻŽāϤ āĻĢāϞāĻžāĻĢāϞ āĻĻ⧇āĻ–āϤ⧇ āφāĻļāĻž āĻ•āϰāĻŋ: āĻ•ā§āϝ⧋āϝāĻŧāĻžāϰ⧀⧍

👉 āĻĒā§āϰāĻļā§āύ ā§Š: āĻ•āĻžāϰāĻž āϏāĻ‚āĻ•āĻŸā§‡ āφāϛ⧇āύ? ("āĻŽāĻŋāĻļāύ āĻŦā§‹āĻ°ā§āĻĄ") āĻŦ⧇āρāĻšā§‡ āĻĨāĻžāĻ•āĻž āĻŦā§āϝāĻ•ā§āϤāĻŋāĻĻ⧇āϰ āĻĻ⧇āϖ⧁āύ āϝāĻžāĻĻ⧇āϰ āϏāĻžāĻšāĻžāĻ¯ā§āϝ⧇āϰ āĻĒā§āϰāϝāĻŧā§‹āϜāύ āĻāĻŦāĻ‚ āϤāĻžāĻĻ⧇āϰ āϕ⧀ āĻĒā§āϰāϝāĻŧā§‹āϜāύāĨ¤

GRAPH SurvivorNetwork
MATCH result = (s:Survivors)-[h:SurvivorHasNeed]->(n:Needs)
RETURN TO_JSON(result) AS json_result

āύ⧀āĻšā§‡āϰ āĻŽāϤ āĻĢāϞāĻžāĻĢāϞ āĻĻ⧇āĻ–āϤ⧇ āφāĻļāĻž āĻ•āϰāĻŋ: āĻ•ā§āϝ⧋āϝāĻŧāĻžāĻ°ā§€ā§Š

🔎 āωāĻ¨ā§āύāϤ: āĻŽā§āϝāĻžāϚāĻŽā§‡āĻ•āĻŋāĻ‚ - āϕ⧇ āĻ•āĻžāϕ⧇ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇?

āĻāĻ–āĻžāύ⧇āχ āĻ—ā§āϰāĻžāĻĢāϟāĻŋ āĻļāĻ•ā§āϤāĻŋāĻļāĻžāϞ⧀ āĻšāϝāĻŧ⧇ āĻ“āϠ⧇! āĻāχ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ⧇ āĻāĻŽāύ āĻœā§€āĻŦāĻŋāϤāĻĻ⧇āϰ āϖ⧁āρāĻœā§‡ āĻŦ⧇āϰ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇ āϝāĻžāĻĻ⧇āϰ āĻĻāĻ•ā§āώāϤāĻž āϰāϝāĻŧ⧇āϛ⧇ āϝāĻž āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ āĻœā§€āĻŦāĻŋāϤāĻĻ⧇āϰ āϚāĻžāĻšāĻŋāĻĻāĻž āĻŽā§‡āϟāĻžāϤ⧇ āĻĒāĻžāϰ⧇ āĨ¤

GRAPH SurvivorNetwork
MATCH result = (helper:Survivors)-[:SurvivorHasSkill]->(skill:Skills)-[:SkillTreatsNeed]->(need:Needs)<-[:SurvivorHasNeed]-(helpee:Survivors)
RETURN TO_JSON(result) AS json_result

āύ⧀āĻšā§‡āϰ āĻŽāϤ āĻĢāϞāĻžāĻĢāϞ āĻĻ⧇āĻ–āϤ⧇ āφāĻļāĻž āĻ•āϰāĻŋ: āĻ•ā§āϝ⧋āϝāĻŧāĻžāϰ⧀ā§Ē

āχāϤāĻŋāĻŦāĻžāϚāĻ• āĻĻāĻŋāĻ• āĻšāϞ⧋ , āĻāχ āϕ⧋āϝāĻŧ⧇āϰāĻŋāϟāĻŋ āϕ⧀ āĻ•āϰ⧇:

"āĻĒā§āϰāĻžāĻĨāĻŽāĻŋāĻ• āϚāĻŋāĻ•āĻŋā§ŽāϏāĻžāϝāĻŧ āĻĒā§‹āĻĄāĻŧāĻžāϰ āϚāĻŋāĻ•āĻŋā§ŽāϏāĻž āĻ•āϰāĻž āĻšāϝāĻŧ" āĻĻ⧇āĻ–āĻžāύ⧋āϰ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤ⧇ (āϝāĻž āĻ¸ā§āĻ•āĻŋāĻŽāĻž āĻĨ⧇āϕ⧇ āĻ¸ā§āĻĒāĻˇā§āϟ), āĻāχ āϕ⧋āϝāĻŧ⧇āϰāĻŋāϟāĻŋ āϖ⧁āρāĻœā§‡ āĻĒāĻžāϝāĻŧ:

  • āĻĄāĻžāσ āĻāϞ⧇āύāĻž āĻĢā§āϰāĻ¸ā§āϟ (āϝāĻžāϰ āϚāĻŋāĻ•āĻŋā§ŽāϏāĻž āĻĒā§āϰāĻļāĻŋāĻ•ā§āώāĻŖ āφāϛ⧇) → āϚāĻŋāĻ•āĻŋā§ŽāϏāĻž āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ → āĻ•ā§āϝāĻžāĻĒā§āĻŸā§‡āύ āϤāĻžāύāĻžāĻ•āĻž (āϝāĻžāϰ āĻĒā§‹āĻĄāĻŧāĻž)
  • āĻĄā§‡āĻ­āĻŋāĻĄ āĻšā§‡āύ (āϝāĻžāϰ āĻĒā§āϰāĻžāĻĨāĻŽāĻŋāĻ• āϚāĻŋāĻ•āĻŋā§ŽāϏāĻž āφāϛ⧇) → āϚāĻŋāĻ•āĻŋā§ŽāϏāĻž āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ → āϞ⧇āĻĢāĻŸā§‡āĻ¨ā§āϝāĻžāĻ¨ā§āϟ āĻĒāĻžāĻ°ā§āĻ• (āϝāĻžāϰ āĻ—ā§‹āĻĄāĻŧāĻžāϞāĻŋ āĻŽāϚāϕ⧇ āϗ⧇āϛ⧇)

āϕ⧇āύ āĻāϟāĻŋ āĻļāĻ•ā§āϤāĻŋāĻļāĻžāϞ⧀:

āφāĻĒāύāĻžāϰ āĻāφāχ āĻāĻœā§‡āĻ¨ā§āϟ āϕ⧀ āĻ•āϰāĻŦ⧇:

āϝāĻ–āύ āĻāĻ•āϜāύ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀ āϜāĻŋāĻœā§āĻžāĻžāϏāĻž āĻ•āϰ⧇āύ "āĻĒā§‹āĻĄāĻŧāĻžāϰ āϚāĻŋāĻ•āĻŋā§ŽāϏāĻž āϕ⧇ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇?" , āϤāĻ–āύ āĻāĻœā§‡āĻ¨ā§āϟ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤāϗ⧁āϞāĻŋ āĻ•āϰāĻŦ⧇āύ:

  1. āĻāĻ•āχ āϧāϰāϪ⧇āϰ āĻ—ā§āϰāĻžāĻĢ āϕ⧋āϝāĻŧ⧇āϰāĻŋ āϚāĻžāϞāĻžāύ
  2. āĻĒā§āϰāĻ¤ā§āϝāĻžāĻŦāĻ°ā§āϤāύ: "āĻĄāσ āĻĢā§āϰāĻ¸ā§āĻŸā§‡āϰ āϚāĻŋāĻ•āĻŋā§ŽāϏāĻž āĻĒā§āϰāĻļāĻŋāĻ•ā§āώāĻŖ āφāϛ⧇ āĻāĻŦāĻ‚ āϤāĻŋāύāĻŋ āĻ•ā§āϝāĻžāĻĒā§āĻŸā§‡āύ āϤāĻžāύāĻžāĻ•āĻžāϕ⧇ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ"
  3. āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āĻŽāĻ§ā§āϝāĻŦāĻ°ā§āϤ⧀ āĻŸā§‡āĻŦāĻŋāϞ āĻŦāĻž āϏāĻŽā§āĻĒāĻ°ā§āĻ• āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ āϜāĻžāύāĻžāϰ āĻĻāϰāĻ•āĻžāϰ āύ⧇āχ!

ā§Ģ. āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ⧇ āĻāφāχ-āϚāĻžāϞāĻŋāϤ āĻāĻŽāĻŦ⧇āĻĄāĻŋāĻ‚

ā§§. āϕ⧇āύ āĻāĻŽā§āĻŦ⧇āĻĄāĻŋāĻ‚? (āϕ⧋āύāĻ“ āĻĒāĻĻāĻ•ā§āώ⧇āĻĒ āύ⧇āχ, āϕ⧇āĻŦāϞ āĻĒāĻ āύāϝ⧋āĻ—ā§āϝ)

āĻŦ⧇āρāĻšā§‡ āĻĨāĻžāĻ•āĻžāϰ āĻ•ā§āώ⧇āĻ¤ā§āϰ⧇, āϏāĻŽāϝāĻŧ āĻ…āĻ¤ā§āϝāĻ¨ā§āϤ āϗ⧁āϰ⧁āĻ¤ā§āĻŦāĻĒā§‚āĻ°ā§āĻŖ āĨ¤ āϝāĻ–āύ āĻāĻ•āϜāύ āĻŦ⧇āρāĻšā§‡ āĻĨāĻžāĻ•āĻž āĻŦā§āϝāĻ•ā§āϤāĻŋ āϜāϰ⧁āϰāĻŋ āĻ…āĻŦāĻ¸ā§āĻĨāĻžāϰ āĻ•āĻĨāĻž āϜāĻžāύāĻžāϝāĻŧ, āϝ⧇āĻŽāύ I need someone who can treat burns āĻ…āĻĨāĻŦāĻž Looking for a medic , āϤāĻ–āύ āϤāĻžāϰāĻž āĻĄāĻžāϟāĻžāĻŦ⧇āϏ⧇ āϏāĻ āĻŋāĻ• āĻĻāĻ•ā§āώāϤāĻžāϰ āύāĻžāĻŽ āĻ…āύ⧁āĻŽāĻžāύ āĻ•āϰ⧇ āϏāĻŽāϝāĻŧ āύāĻˇā§āϟ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇ āύāĻžāĨ¤

āφāϏāϞ āĻĻ⧃āĻļā§āϝ : āĻŦ⧇āρāĻšā§‡ āĻĨāĻžāĻ•āĻž āĻŦā§āϝāĻ•ā§āϤāĻŋ: Captain Tanaka has burns—we need medical help NOW!

"medic" āĻāϰ āϜāĻ¨ā§āϝ āϐāϤāĻŋāĻšā§āϝāĻŦāĻžāĻšā§€ āϕ⧀āĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ → 0 āĻĢāϞāĻžāĻĢāϞ ❌

āĻāĻŽā§āĻŦ⧇āĻĄāĻŋāĻ‚ āϏāĻš āĻļāĻŦā§āĻĻāĻžāĻ°ā§āĻĨāĻŋāĻ• āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ → "āϚāĻŋāĻ•āĻŋā§ŽāϏāĻž āĻĒā§āϰāĻļāĻŋāĻ•ā§āώāĻŖ", "āĻĒā§āϰāĻžāĻĨāĻŽāĻŋāĻ• āϚāĻŋāĻ•āĻŋā§ŽāϏāĻž" āϖ⧁āρāĻœā§‡ āĻŦ⧇āϰ āĻ•āϰ⧇ ✅

āĻāĻœā§‡āĻ¨ā§āϟāĻĻ⧇āϰ āĻ āĻŋāĻ• āĻāϟāĻžāχ āĻĒā§āĻ°ā§Ÿā§‹āϜāύ: āĻŦ⧁āĻĻā§āϧāĻŋāĻŽāĻžāύ, āĻŽāĻžāύ⧁āώ⧇āϰ āĻŽāϤ⧋ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āϝāĻž āϕ⧇āĻŦāϞ āϕ⧀āĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ āύāϝāĻŧ, āωāĻĻā§āĻĻ⧇āĻļā§āϝ āĻŦā§‹āĻā§‡āĨ¤

2. āĻāĻŽā§āĻŦ⧇āĻĄāĻŋāĻ‚ āĻŽāĻĄā§‡āϞ āϤ⧈āϰāĻŋ āĻ•āϰ⧁āύ

āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ_āĻāĻŽā§āĻŦ⧇āĻĄāĻŋāĻ‚

āĻāĻ–āύ āφāϏ⧁āύ āĻāĻŽāύ āĻāĻ•āϟāĻŋ āĻŽāĻĄā§‡āϞ āϤ⧈āϰāĻŋ āĻ•āϰāĻŋ āϝāĻž āϗ⧁āĻ—āϞ⧇āϰ text-embedding-004 āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āĻŸā§‡āĻ•ā§āϏāϟāϕ⧇ āĻāĻŽā§āĻŦ⧇āĻĄāĻŋāĻ‚āϝāĻŧ⧇ āϰ⧂āĻĒāĻžāĻ¨ā§āϤāϰ āĻ•āϰ⧇āĨ¤

👉 āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ āĻ¸ā§āϟ⧁āĻĄāĻŋāĻ“āϤ⧇, āĻāχ SQL āϚāĻžāϞāĻžāύ ( $YOUR_PROJECT_ID āφāĻĒāύāĻžāϰ āĻĒā§āϰāĻ•ā§ƒāϤ āĻĒā§āϰāĻœā§‡āĻ•ā§āϟ āφāχāĻĄāĻŋ āĻĻāĻŋāϝāĻŧ⧇ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ):

â€ŧī¸ āĻ•ā§āϞāĻžāωāĻĄ āĻļ⧇āϞ āĻāĻĄāĻŋāϟāϰ⧇ , āĻĒ⧁āϰ⧋ āĻĒā§āϰāĻ•āĻ˛ā§āĻĒāϟāĻŋ āĻĻ⧇āĻ–āϤ⧇ File -> Open Folder -> way-back-home/level_2 āϖ⧁āϞ⧁āύāĨ¤

āĻĒā§āϰāĻœā§‡āĻ•ā§āϟ_āφāχāĻĄāĻŋ

👉 āύāĻŋāĻšā§‡āϰ āϕ⧋āϝāĻŧ⧇āϰāĻŋāϟāĻŋ āĻ•āĻĒāĻŋ āĻ•āϰ⧇ āĻĒ⧇āĻ¸ā§āϟ āĻ•āϰ⧇ āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ āĻ¸ā§āϟ⧁āĻĄāĻŋāĻ“āϤ⧇ āĻāχ āϕ⧋āϝāĻŧ⧇āϰāĻŋāϟāĻŋ āϚāĻžāϞāĻžāύ, āĻāĻŦāĻ‚ āϤāĻžāϰāĻĒāϰ āϰāĻžāύ āĻŦā§‹āϤāĻžāĻŽā§‡ āĻ•ā§āϞāĻŋāĻ• āĻ•āϰ⧁āύ:

CREATE MODEL TextEmbeddings
INPUT(content STRING(MAX))
OUTPUT(embeddings STRUCT<values ARRAY<FLOAT32>>)
REMOTE OPTIONS (
    endpoint = '//aiplatform.googleapis.com/projects/$YOUR_PROJECT_ID/locations/us-central1/publishers/google/models/text-embedding-004'
);

āĻāϰ āĻ•āĻžāϜ āϕ⧀ :

  • āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ⧇ āĻāĻ•āϟāĻŋ āĻ­āĻžāĻ°ā§āϚ⧁āϝāĻŧāĻžāϞ āĻŽāĻĄā§‡āϞ āϤ⧈āϰāĻŋ āĻ•āϰ⧇ (āĻ¸ā§āĻĨāĻžāύ⧀āϝāĻŧāĻ­āĻžāĻŦ⧇ āϕ⧋āύāĻ“ āĻŽāĻĄā§‡āϞ āĻ“āϜāύ āϏāĻ‚āϰāĻ•ā§āώāĻŖ āĻ•āϰāĻž āĻšāϝāĻŧ āύāĻž)
  • Vertex AI-āϤ⧇ Google-āĻāϰ text-embedding-004 āĻĻāĻŋāϕ⧇ āχāĻ™ā§āĻ—āĻŋāϤ āĻ•āϰāĻž āĻšāĻšā§āϛ⧇
  • āϚ⧁āĻ•ā§āϤāĻŋ āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ āĻ•āϰ⧇: āχāύāĻĒ⧁āϟ āĻšāϞ āĻŸā§‡āĻ•ā§āϏāϟ, āφāωāϟāĻĒ⧁āϟ āĻšāϞ āĻāĻ•āϟāĻŋ 768-āĻŽāĻžāĻ¤ā§āϰāĻž āĻĢā§āϞ⧋āϟ āĻ…ā§āϝāĻžāϰ⧇

"āϰāĻŋāĻŽā§‹āϟ āĻ…āĻĒāĻļāύ" āϕ⧇āύ?

  • āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ āύāĻŋāĻœā§‡āχ āĻŽāĻĄā§‡āϞāϟāĻŋ āϚāĻžāϞāĻžāϝāĻŧ āύāĻžāĨ¤
  • ML.PREDICT āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻāϟāĻŋ API āĻāϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ Vertex AI āĻ•āϞ āĻ•āϰ⧇āĨ¤
  • āϜāĻŋāϰ⧋-āχāϟāĻŋāĻāϞ : āĻĒāĻžāχāĻĨāύ⧇ āĻĄā§‡āϟāĻž āϰāĻĒā§āϤāĻžāύāĻŋ, āĻĒā§āϰāĻ•ā§āϰāĻŋāϝāĻŧāĻžāĻ•āϰāĻŖ āĻāĻŦāĻ‚ āĻĒ⧁āύāϰāĻžāϝāĻŧ āφāĻŽāĻĻāĻžāύāĻŋ āĻ•āϰāĻžāϰ āĻĒā§āϰāϝāĻŧā§‹āϜāύ āύ⧇āχāĨ¤

Run āĻŦāĻžāϟāύ⧇ āĻ•ā§āϞāĻŋāĻ• āĻ•āϰ⧁āύ, āĻāĻ•āĻŦāĻžāϰ āĻāϟāĻŋ āϏāĻĢāϞ āĻšāϝāĻŧ⧇ āϗ⧇āϞ⧇, āφāĻĒāύāĻŋ āύ⧀āĻšā§‡āϰ āĻŽāϤ āĻĢāϞāĻžāĻĢāϞ āĻĻ⧇āĻ–āϤ⧇ āĻĒāĻžāĻŦ⧇āύ:

āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ_āϰ⧇āϜāĻžāĻ˛ā§āϟ

ā§Š. āĻāĻŽā§āĻŦ⧇āĻĄāĻŋāĻ‚ āĻ•āϞāĻžāĻŽ āϝ⧋āĻ— āĻ•āϰ⧁āύ

👉 āĻāĻŽā§āĻŦ⧇āĻĄāĻŋāĻ‚ āϏāĻ‚āϰāĻ•ā§āώāĻŖ āĻ•āϰāϤ⧇ āĻāĻ•āϟāĻŋ āĻ•āϞāĻžāĻŽ āϝ⧋āĻ— āĻ•āϰ⧁āύ:

ALTER TABLE Skills ADD COLUMN skill_embedding ARRAY<FLOAT32>;

Run āĻŦāĻžāϟāύ⧇ āĻ•ā§āϞāĻŋāĻ• āĻ•āϰ⧁āύ, āĻāĻ•āĻŦāĻžāϰ āĻāϟāĻŋ āϏāĻĢāϞ āĻšāϝāĻŧ⧇ āϗ⧇āϞ⧇, āφāĻĒāύāĻŋ āύ⧀āĻšā§‡āϰ āĻŽāϤ āĻĢāϞāĻžāĻĢāϞ āĻĻ⧇āĻ–āϤ⧇ āĻĒāĻžāĻŦ⧇āύ:

āĻāĻŽā§āĻŦ⧇āĻĄāĻŋāĻ‚_āϰ⧇āϜāĻžāĻ˛ā§āϟ

ā§Ē. āĻāĻŽā§āĻŦ⧇āĻĄāĻŋāĻ‚ āϤ⧈āϰāĻŋ āĻ•āϰ⧁āύ

👉 āĻĒā§āϰāϤāĻŋāϟāĻŋ āĻĻāĻ•ā§āώāϤāĻžāϰ āϜāĻ¨ā§āϝ āϭ⧇āĻ•ā§āϟāϰ āĻāĻŽā§āĻŦ⧇āĻĄāĻŋāĻ‚ āϤ⧈āϰāĻŋ āĻ•āϰāϤ⧇ AI āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύ:

UPDATE Skills
SET skill_embedding = (
    SELECT embeddings.values
    FROM ML.PREDICT(
        MODEL TextEmbeddings,
        (SELECT name AS content)
    )
)
WHERE skill_embedding IS NULL;

Run āĻŦāĻžāϟāύ⧇ āĻ•ā§āϞāĻŋāĻ• āĻ•āϰ⧁āύ, āĻāĻ•āĻŦāĻžāϰ āĻāϟāĻŋ āϏāĻĢāϞ āĻšāϝāĻŧ⧇ āϗ⧇āϞ⧇, āφāĻĒāύāĻŋ āύ⧀āĻšā§‡āϰ āĻŽāϤ āĻĢāϞāĻžāĻĢāϞ āĻĻ⧇āĻ–āϤ⧇ āĻĒāĻžāĻŦ⧇āύ:

āĻĻāĻ•ā§āώāϤāĻž_āĻĢāϞāĻžāĻĢāϞ

āϕ⧀ āϘāĻŸā§‡ : āĻĒā§āϰāϤāĻŋāϟāĻŋ āĻĻāĻ•ā§āώāϤāĻžāϰ āύāĻžāĻŽ (āϝ⧇āĻŽāύ, "āĻĒā§āϰāĻžāĻĨāĻŽāĻŋāĻ• āϚāĻŋāĻ•āĻŋā§ŽāϏāĻž") āĻāĻ•āϟāĻŋ 768-āĻŽāĻžāĻ¤ā§āϰāĻžāϰ āϭ⧇āĻ•ā§āϟāϰ⧇ āϰ⧂āĻĒāĻžāĻ¨ā§āϤāϰāĻŋāϤ āĻšāϝāĻŧ āϝāĻž āĻāϰ āĻļāĻŦā§āĻĻāĻžāĻ°ā§āĻĨāĻŋāĻ• āĻ…āĻ°ā§āĻĨ āωāĻĒāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧇āĨ¤

ā§Ģ. āĻāĻŽā§āĻŦ⧇āĻĄāĻŋāĻ‚ āϝāĻžāϚāĻžāχ āĻ•āϰ⧁āύ

👉 āĻāĻŽā§āĻŦ⧇āĻĄāĻŋāĻ‚ āϤ⧈āϰāĻŋ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇ āĻ•āĻŋāύāĻž āϤāĻž āĻĒāϰ⧀āĻ•ā§āώāĻž āĻ•āϰ⧁āύ:

SELECT 
    skill_id,
    name,
    ARRAY_LENGTH(skill_embedding) AS embedding_dimensions
FROM Skills
LIMIT 5;

āĻĒā§āϰāĻ¤ā§āϝāĻžāĻļāĻŋāϤ āφāωāϟāĻĒ⧁āϟ :

āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ_āϰ⧇āϜāĻžāĻ˛ā§āϟ

āĻāĻ–āύ āφāĻŽāϰāĻž āφāĻŽāĻžāĻĻ⧇āϰ āĻĒāϰāĻŋāĻ¸ā§āĻĨāĻŋāϤāĻŋ āĻĨ⧇āϕ⧇ āϏāĻ āĻŋāĻ• āĻŦā§āϝāĻŦāĻšāĻžāϰ⧇āϰ āĻ•ā§āώ⧇āĻ¤ā§āϰ⧇ āĻĒāϰ⧀āĻ•ā§āώāĻž āĻ•āϰāĻŦ : "āϚāĻŋāĻ•āĻŋā§ŽāϏāĻ•" āĻļāĻŦā§āĻĻāϟāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āϚāĻŋāĻ•āĻŋā§ŽāϏāĻž āĻĻāĻ•ā§āώāϤāĻž āϖ⧁āρāĻœā§‡ āĻŦ⧇āϰ āĻ•āϰāĻžāĨ¤

👉 "āϚāĻŋāĻ•āĻŋā§ŽāϏāĻ•" āĻāϰ āĻŽāϤ⧋ āĻĻāĻ•ā§āώāϤāĻž āϖ⧁āρāϜ⧁āύ:

WITH query_embedding AS (
    SELECT embeddings.values AS val
    FROM ML.PREDICT(MODEL TextEmbeddings, (SELECT "medic" AS content))
)
SELECT
    s.name AS skill_name,
    s.category,
    COSINE_DISTANCE(s.skill_embedding, (SELECT val FROM query_embedding)) AS distance
FROM Skills AS s
WHERE s.skill_embedding IS NOT NULL
ORDER BY distance ASC
LIMIT 10;
  • āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻļāĻŦā§āĻĻ "medic" āϕ⧇ āĻāĻ•āϟāĻŋ āĻāĻŽā§āĻŦ⧇āĻĄāĻŋāĻ‚āϝāĻŧ⧇ āϰ⧂āĻĒāĻžāĻ¨ā§āϤāϰāĻŋāϤ āĻ•āϰ⧇
  • āĻāϟāĻŋāϕ⧇ query_embedding āĻ…āĻ¸ā§āĻĨāĻžāϝāĻŧā§€ āĻŸā§‡āĻŦāĻŋāϞ⧇ āϏāĻ‚āϰāĻ•ā§āώāĻŖ āĻ•āϰ⧇āĨ¤

āĻĒā§āϰāĻ¤ā§āϝāĻžāĻļāĻŋāϤ āĻĢāϞāĻžāĻĢāϞ (āĻ•āĻŽ āĻĻā§‚āϰāĻ¤ā§āĻŦ = āφāϰāĻ“ āĻ…āύ⧁āϰ⧂āĻĒ):

āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ_āϰ⧇āϜāĻžāĻ˛ā§āϟ

ā§­. āĻŦāĻŋāĻļā§āϞ⧇āώāϪ⧇āϰ āϜāĻ¨ā§āϝ āĻŽāĻŋāĻĨ⧁āύ āĻŽāĻĄā§‡āϞ āϤ⧈āϰāĻŋ āĻ•āϰ⧁āύ

āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ_āĻœā§‡āĻŽāĻŋāύāĻŋ

👉 āĻāĻ•āϟāĻŋ āĻœā§‡āύāĻžāϰ⧇āϟāĻŋāĻ­ āĻāφāχ āĻŽāĻĄā§‡āϞ āϰ⧇āĻĢāĻžāϰ⧇āĻ¨ā§āϏ āϤ⧈āϰāĻŋ āĻ•āϰ⧁āύ ( $YOUR_PROJECT_ID āφāĻĒāύāĻžāϰ āĻĒā§āϰāĻ•ā§ƒāϤ āĻĒā§āϰāĻœā§‡āĻ•ā§āϟ āφāχāĻĄāĻŋ āĻĻāĻŋāϝāĻŧ⧇ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ):

CREATE MODEL GeminiPro
INPUT(prompt STRING(MAX))
OUTPUT(content STRING(MAX))
REMOTE OPTIONS (
    endpoint = '//aiplatform.googleapis.com/projects/$YOUR_PROJECT_ID/locations/us-central1/publishers/google/models/gemini-2.5-pro',
    default_batch_size = 1
);

āĻāĻŽā§āĻŦ⧇āĻĄāĻŋāĻ‚ āĻŽāĻĄā§‡āϞ āĻĨ⧇āϕ⧇ āĻĒāĻžāĻ°ā§āĻĨāĻ•ā§āϝ :

  • āĻāĻŽā§āĻŦ⧇āĻĄāĻŋāĻ‚ : āĻŸā§‡āĻ•ā§āϏāϟ → āϭ⧇āĻ•ā§āϟāϰ (āϏāĻžāĻĻ⧃āĻļā§āϝ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ⧇āϰ āϜāĻ¨ā§āϝ)
  • āĻŽāĻŋāĻĨ⧁āύ : āĻŸā§‡āĻ•ā§āϏāϟ → āĻœā§‡āύāĻžāϰ⧇āĻŸā§‡āĻĄ āĻŸā§‡āĻ•ā§āϏāϟ (āϝ⧁āĻ•ā§āϤāĻŋ/āĻŦāĻŋāĻļā§āϞ⧇āώāϪ⧇āϰ āϜāĻ¨ā§āϝ)

āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ_āϰ⧇āϜāĻžāĻ˛ā§āϟ

ā§Ž. āϏāĻžāĻŽāĻžā§āϜāĻ¸ā§āϝ āĻŦāĻŋāĻļā§āϞ⧇āώāϪ⧇āϰ āϜāĻ¨ā§āϝ āĻœā§‡āĻŽāĻŋāύāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύ

👉 āĻŽāĻŋāĻļāύ⧇āϰ āϏāĻžāĻŽāĻžā§āϜāĻ¸ā§āϝ⧇āϰ āϜāĻ¨ā§āϝ āĻŦ⧇āρāĻšā§‡ āĻĨāĻžāĻ•āĻž āĻœā§‹āĻĄāĻŧāĻž āĻŦāĻŋāĻļā§āϞ⧇āώāĻŖ āĻ•āϰ⧁āύ:

WITH PairData AS (
    SELECT
        s1.name AS Name_A,
        s2.name AS Name_B,
        CONCAT(
            "Assess compatibility of these two survivors for a resource-gathering mission. ",
            "Survivor 1: ", s1.name, ". ",
            "Survivor 2: ", s2.name, ". ",
            "Give a score from 1-10 and a 1-sentence reason."
        ) AS prompt
    FROM Survivors s1
    JOIN Survivors s2 ON s1.survivor_id < s2.survivor_id
    LIMIT 1
)
SELECT
    Name_A,
    Name_B,
    content AS ai_assessment
FROM ML.PREDICT(
    MODEL GeminiPro,
    (SELECT Name_A, Name_B, prompt FROM PairData)
);

āĻĒā§āϰāĻ¤ā§āϝāĻžāĻļāĻŋāϤ āφāωāϟāĻĒ⧁āϟ :

Name_A          | Name_B            | ai_assessment
----------------|-------------------|----------------
"David Chen"    | "Dr. Elena Frost" | "**Score: 9/10** Their compatibility is extremely high as David's practical, hands-on scavenging skills are perfectly complemented by Dr. Frost's specialized knowledge to identify critical medical supplies and avoid biological hazards."

ā§Ŧ. āĻšāĻžāχāĻŦā§āϰāĻŋāĻĄ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ⧇āϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āφāĻĒāύāĻžāϰ āĻ—ā§āϰāĻžāĻĢ RAG āĻāĻœā§‡āĻ¨ā§āϟ āϤ⧈āϰāĻŋ āĻ•āϰāĻž

ā§§. āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽ āφāĻ°ā§āĻ•āĻŋāĻŸā§‡āĻ•āϚāĻžāϰ āĻ“āĻ­āĻžāϰāĻ­āĻŋāω

āĻāχ āĻŦāĻŋāĻ­āĻžāĻ—āϟāĻŋ āĻāĻ•āϟāĻŋ āĻŦāĻšā§-āĻĒāĻĻā§āϧāϤāĻŋāĻ—āϤ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻŦā§āϝāĻŦāĻ¸ā§āĻĨāĻž āϤ⧈āϰāĻŋ āĻ•āϰ⧇ āϝāĻž āφāĻĒāύāĻžāϰ āĻāĻœā§‡āĻ¨ā§āϟāϕ⧇ āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āύ āϧāϰāϪ⧇āϰ āĻĒā§āϰāĻļā§āύ āĻĒāϰāĻŋāϚāĻžāϞāύāĻž āĻ•āϰāĻžāϰ āύāĻŽāύ⧀āϝāĻŧāϤāĻž āĻĻ⧇āϝāĻŧāĨ¤ āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽāϟāĻŋāϤ⧇ āϤāĻŋāύāϟāĻŋ āĻ¸ā§āϤāϰ āϰāϝāĻŧ⧇āϛ⧇: āĻāĻœā§‡āĻ¨ā§āϟ āĻ¸ā§āϤāϰ , āϏāϰāĻžā§āϜāĻžāĻŽ āĻ¸ā§āϤāϰ , āĻĒāϰāĻŋāώ⧇āĻŦāĻž āĻ¸ā§āϤāϰ āĨ¤

āĻ¸ā§āĻĨāĻžāĻĒāĻ¤ā§āϝ_āϏāĻ‚āĻ•āϰ_āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ

āϤāĻŋāύ āĻ¸ā§āϤāϰ āϕ⧇āύ?

  • āωāĻĻā§āĻŦ⧇āϗ⧇āϰ āĻŦāĻŋāĻšā§āϛ⧇āĻĻ : āĻāĻœā§‡āĻ¨ā§āϟ āωāĻĻā§āĻĻ⧇āĻļā§āϝ⧇āϰ āωāĻĒāϰ, āϏāϰāĻžā§āϜāĻžāĻŽāϗ⧁āϞāĻŋāϰ āωāĻĒāϰ āχāĻ¨ā§āϟāĻžāϰāĻĢ⧇āϏ, āĻĒāϰāĻŋāώ⧇āĻŦāĻž āĻŦāĻžāĻ¸ā§āϤāĻŦāĻžāϝāĻŧāύ⧇āϰ āωāĻĒāϰ āĻĻ⧃āĻˇā§āϟāĻŋ āύāĻŋāĻŦāĻĻā§āϧ āĻ•āϰ⧇
  • āύāĻŽāύ⧀āϝāĻŧāϤāĻž : āĻāĻœā§‡āĻ¨ā§āϟ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻĒāĻĻā§āϧāϤāĻŋ āĻœā§‹āϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇ āĻ…āĻĨāĻŦāĻž AI-āϕ⧇ āĻ¸ā§āĻŦāϝāĻŧāĻ‚āĻ•ā§āϰāĻŋāϝāĻŧāĻ­āĻžāĻŦ⧇ āϰ⧁āϟ āĻ•āϰāϤ⧇ āĻĻāĻŋāϤ⧇ āĻĒāĻžāϰ⧇
  • āĻ…āĻĒā§āϟāĻŋāĻŽāĻžāχāĻœā§‡āĻļāύ : āĻĒāĻĻā§āϧāϤāĻŋ āϜāĻžāύāĻž āĻĨāĻžāĻ•āϞ⧇ āĻŦā§āϝāϝāĻŧāĻŦāĻšā§āϞ āĻāφāχ āĻŦāĻŋāĻļā§āϞ⧇āώāĻŖ āĻāĻĄāĻŧāĻŋāϝāĻŧ⧇ āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇

āĻāχ āĻŦāĻŋāĻ­āĻžāϗ⧇, āφāĻĒāύāĻŋ āĻĒā§āϰāĻžāĻĨāĻŽāĻŋāĻ•āĻ­āĻžāĻŦ⧇ āĻļāĻŦā§āĻĻāĻžāĻ°ā§āĻĨāĻŋāĻ• āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ (RAG) āĻŦāĻžāĻ¸ā§āϤāĻŦāĻžāϝāĻŧāύ āĻ•āϰāĻŦ⧇āύ - āϕ⧇āĻŦāϞ āϕ⧀āĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ āύāϝāĻŧ, āĻ…āĻ°ā§āĻĨ āĻĻāĻŋāϝāĻŧ⧇ āĻĢāϞāĻžāĻĢāϞ āϖ⧁āρāĻœā§‡ āĻŦ⧇āϰ āĻ•āϰāĻžāĨ¤ āĻĒāϰ⧇, āφāĻŽāϰāĻž āĻŦā§āϝāĻžāĻ–ā§āϝāĻž āĻ•āϰāĻŦ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ āĻšāĻžāχāĻŦā§āϰāĻŋāĻĄ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻāĻ•āĻžāϧāĻŋāĻ• āĻĒāĻĻā§āϧāϤāĻŋāϕ⧇ āĻāĻ•āĻ¤ā§āϰāĻŋāϤ āĻ•āϰ⧇āĨ¤

⧍. āφāϰāĻāϜāĻŋ āĻĒāϰāĻŋāώ⧇āĻŦāĻž āĻŦāĻžāĻ¸ā§āϤāĻŦāĻžāϝāĻŧāύ

👉đŸ’ģ āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ⧇, āĻ•ā§āϞāĻžāωāĻĄ āĻļ⧇āϞ āĻāĻĄāĻŋāϟāϰ⧇ āĻĢāĻžāχāϞāϟāĻŋ āϖ⧁āϞ⧁āύ:

cloudshell edit ~/way-back-home/level_2/backend/services/hybrid_search_service.py

āĻŽāĻ¨ā§āϤāĻŦā§āϝāϟāĻŋ āϏāύāĻžāĻ•ā§āϤ āĻ•āϰ⧁āύ # TODO: REPLACE_SQL

āĻāχ āĻĒ⧁āϰ⧋ āϞāĻžāχāύāϟāĻŋ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āϕ⧋āĻĄ āĻĻāĻŋāϝāĻŧ⧇ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ :

        # This is your working query from the successful run!
        sql = """
            WITH query_embedding AS (
                SELECT embeddings.values AS val
                FROM ML.PREDICT(
                    MODEL TextEmbeddings,
                    (SELECT @query AS content)
                )
            )
            SELECT
                s.survivor_id,
                s.name AS survivor_name,
                s.biome,
                sk.skill_id,
                sk.name AS skill_name,
                sk.category,
                COSINE_DISTANCE(
                    sk.skill_embedding, 
                    (SELECT val FROM query_embedding)
                ) AS distance
            FROM Survivors s
            JOIN SurvivorHasSkill shs ON s.survivor_id = shs.survivor_id
            JOIN Skills sk ON shs.skill_id = sk.skill_id
            WHERE sk.skill_embedding IS NOT NULL
            ORDER BY distance ASC
            LIMIT @limit
        """

ā§Š. āĻļāĻŦā§āĻĻāĻžāĻ°ā§āĻĨāĻŋāĻ• āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āϏāϰāĻžā§āϜāĻžāĻŽā§‡āϰ āϏāĻ‚āĻœā§āĻžāĻž

👉đŸ’ģ āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ⧇, āĻ•ā§āϞāĻžāωāĻĄ āĻļ⧇āϞ āĻāĻĄāĻŋāϟāϰ⧇ āĻĢāĻžāχāϞāϟāĻŋ āϖ⧁āϞ⧁āύ:

cloudshell edit ~/way-back-home/level_2/backend/agent/tools/hybrid_search_tools.py

hybrid_search_tools.py āϤ⧇, āĻŽāĻ¨ā§āϤāĻŦā§āϝāϟāĻŋ āϏāύāĻžāĻ•ā§āϤ āĻ•āϰ⧁āύ # TODO: REPLACE_SEMANTIC_SEARCH_TOOL

👉 āĻāχ āĻĒ⧁āϰ⧋ āϞāĻžāχāύāϟāĻŋ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āϕ⧋āĻĄ āĻĻāĻŋāϝāĻŧ⧇ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ :

async def semantic_search(query: str, limit: int = 10) -> str:
    """
    Force semantic (RAG) search using embeddings.
    
    Use this when you specifically want to find things by MEANING,
    not just matching keywords. Great for:
    - Finding conceptually similar items
    - Handling vague or abstract queries
    - When exact terms are unknown
    
    Example: "healing abilities" will find "first aid", "surgery", 
    "herbalism" even though no keywords match exactly.
    
    Args:
        query: What you're looking for (describe the concept)
        limit: Maximum results
        
    Returns:
        Semantically similar results ranked by relevance
    """
    try:
        service = _get_service()
        result = service.smart_search(
            query, 
            force_method=SearchMethod.RAG,
            limit=limit
        )
        
        return _format_results(
            result["results"],
            result["analysis"],
            show_analysis=True
        )
        
    except Exception as e:
        return f"Error in semantic search: {str(e)}"

āϝāĻ–āύ āĻāĻœā§‡āĻ¨ā§āϟ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ :

  • āϏāĻžāĻĻ⧃āĻļā§āϝ⧇āϰ āϜāĻ¨ā§āϝ āϜāĻŋāĻœā§āĻžāĻžāϏāĻž āĻ•āϰāĻž āĻĒā§āϰāĻļā§āύ ("X āĻāϰ āĻ…āύ⧁āϰ⧂āĻĒ āϖ⧁āρāϜ⧁āύ")
  • āϧāĻžāϰāĻŖāĻžāĻ—āϤ āĻĒā§āϰāĻļā§āύ ("āύāĻŋāϰāĻžāĻŽāϝāĻŧ āĻ•ā§āώāĻŽāϤāĻž")
  • āϝāĻ–āύ āĻ…āĻ°ā§āĻĨ āĻŦā§‹āĻāĻž āĻ…āĻ¤ā§āϝāĻ¨ā§āϤ āϗ⧁āϰ⧁āĻ¤ā§āĻŦāĻĒā§‚āĻ°ā§āĻŖ

ā§Ē. āĻāĻœā§‡āĻ¨ā§āϟ āϏāĻŋāĻĻā§āϧāĻžāĻ¨ā§āϤ āύāĻŋāĻ°ā§āĻĻ⧇āĻļāĻŋāĻ•āĻž (āύāĻŋāĻ°ā§āĻĻ⧇āĻļāύāĻž)

āĻāĻœā§‡āĻ¨ā§āϟ āϏāĻ‚āĻœā§āĻžāĻžā§Ÿ, āύāĻŋāĻ°ā§āĻĻ⧇āĻļ⧇āϰ āϏāĻžāĻĨ⧇ āĻļāĻŦā§āĻĻāĻžāĻ°ā§āĻĨāĻŋāĻ• āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ āĻ…āĻ‚āĻļāϟāĻŋ āĻ•āĻĒāĻŋ āĻĒ⧇āĻ¸ā§āϟ āĻ•āϰ⧁āύāĨ¤

👉đŸ’ģ āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ⧇, āĻ•ā§āϞāĻžāωāĻĄ āĻļ⧇āϞ āĻāĻĄāĻŋāϟāϰ⧇ āĻĢāĻžāχāϞāϟāĻŋ āϖ⧁āϞ⧁āύ:

cloudshell edit ~/way-back-home/level_2/backend/agent/agent.py

āĻāĻœā§‡āĻ¨ā§āϟ āϏāĻ āĻŋāĻ• āϟ⧁āϞāϟāĻŋ āύāĻŋāĻ°ā§āĻŦāĻžāϚāύ āĻ•āϰāϤ⧇ āĻāχ āύāĻŋāĻ°ā§āĻĻ⧇āĻļāĻŋāĻ•āĻžāϟāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇:

agent.py āĻĢāĻžāχāϞ⧇, āĻŽāĻ¨ā§āϤāĻŦā§āϝāϟāĻŋ āϏāύāĻžāĻ•ā§āϤ āĻ•āϰ⧁āύ # TODO: REPLACE_SEARCH_LOGIC , āĻāχ āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āϞāĻžāχāύāϟāĻŋ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āϕ⧋āĻĄ āĻĻāĻŋāϝāĻŧ⧇ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ :

- `semantic_search`: Force RAG/embedding search
  Use for: "Find similar to X", conceptual queries, unknown terminology
  Example: "Find skills related to healing"

👉āĻŽāĻ¨ā§āϤāĻŦā§āϝāϟāĻŋ āϏāύāĻžāĻ•ā§āϤ āĻ•āϰ⧁āύ # TODO: ADD_SEARCH_TOOL āĻāχ āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āϞāĻžāχāύāϟāĻŋ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āϕ⧋āĻĄ āĻĻāĻŋāϝāĻŧ⧇ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ :

    semantic_search,         # Force RAG

ā§Ģ. āĻšāĻžāχāĻŦā§āϰāĻŋāĻĄ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āϕ⧀āĻ­āĻžāĻŦ⧇ āĻ•āĻžāϜ āĻ•āϰ⧇ āϤāĻž āĻŦā§‹āĻāĻž (āϕ⧇āĻŦāϞāĻŽāĻžāĻ¤ā§āϰ āĻĒāĻ āύāϝ⧋āĻ—ā§āϝ, āϕ⧋āύāĻ“ āĻĒāĻĻāĻ•ā§āώ⧇āĻĒ⧇āϰ āĻĒā§āϰāϝāĻŧā§‹āϜāύ āύ⧇āχ)

āϧāĻžāĻĒ ā§¨-ā§Ē-āĻ, āφāĻĒāύāĻŋ āĻļāĻŦā§āĻĻāĻžāĻ°ā§āĻĨāĻŋāĻ• āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ (RAG) āĻĒā§āϰāϝāĻŧā§‹āĻ— āĻ•āϰ⧇āϛ⧇āύ, āĻŽā§‚āϞ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻĒāĻĻā§āϧāϤāĻŋ āϝāĻž āĻ…āĻ°ā§āĻĨ āĻ…āύ⧁āϏāĻžāϰ⧇ āĻĢāϞāĻžāĻĢāϞ āϖ⧁āρāĻœā§‡ āĻŦ⧇āϰ āĻ•āϰ⧇āĨ¤ āĻ•āĻŋāĻ¨ā§āϤ⧁ āφāĻĒāύāĻŋ āĻšāϝāĻŧāϤ⧋ āϞāĻ•ā§āĻˇā§āϝ āĻ•āϰ⧇āϛ⧇āύ āϝ⧇ āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽāϟāĻŋāϕ⧇ "āĻšāĻžāχāĻŦā§āϰāĻŋāĻĄ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ" āĻŦāϞāĻž āĻšāϝāĻŧāĨ¤ āĻāĻ–āĻžāύ⧇ āϏāĻŦāĻ•āĻŋāϛ⧁ āĻāĻ•āϏāĻžāĻĨ⧇ āϕ⧀āĻ­āĻžāĻŦ⧇ āĻ–āĻžāĻĒ āĻ–āĻžāϝāĻŧ:

āĻšāĻžāχāĻŦā§āϰāĻŋāĻĄ āĻŽāĻžāĻ°ā§āϜ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ āĻ•āĻžāϜ āĻ•āϰ⧇ :

way-back-home/level_2/backend/services/hybrid_search_service.py āĻĢāĻžāχāϞ⧇, āϝāĻ–āύ hybrid_search() āĻ•āϞ āĻ•āϰāĻž āĻšāϝāĻŧ, āϤāĻ–āύ āĻĒāϰāĻŋāώ⧇āĻŦāĻžāϟāĻŋ āωāĻ­āϝāĻŧ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āϚāĻžāϞāĻžāϝāĻŧ āĻāĻŦāĻ‚ āĻĢāϞāĻžāĻĢāϞ āĻāĻ•āĻ¤ā§āϰāĻŋāϤ āĻ•āϰ⧇:

# Location: backend/services/hybrid_search_service.py

    rank_kw = keyword_ranks.get(surv_id, float('inf'))
    rank_rag = rag_ranks.get(surv_id, float('inf'))

    rrf_score = 0.0
    if rank_kw != float('inf'):
        rrf_score += 1.0 / (K + rank_kw)
    if rank_rag != float('inf'):
        rrf_score += 1.0 / (K + rank_rag)

    combined_score = rrf_score

āĻāχ āϕ⧋āĻĄāĻ˛ā§āϝāĻžāĻŦ⧇āϰ āϜāĻ¨ā§āϝ , āφāĻĒāύāĻŋ āϏāĻŋāĻŽā§‡āĻ¨ā§āϟāĻŋāĻ• āϏāĻžāĻ°ā§āϚ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ (RAG) āĻŦāĻžāĻ¸ā§āϤāĻŦāĻžāϝāĻŧāύ āĻ•āϰ⧇āϛ⧇āύ, āϝāĻž āĻ­āĻŋāĻ¤ā§āϤāĻŋāĨ¤ āϕ⧀āĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ āĻāĻŦāĻ‚ āĻšāĻžāχāĻŦā§āϰāĻŋāĻĄ āĻĒāĻĻā§āϧāϤāĻŋāϗ⧁āϞāĻŋ āχāϤāĻŋāĻŽāĻ§ā§āϝ⧇āχ āĻĒāϰāĻŋāώ⧇āĻŦāĻžāϟāĻŋāϤ⧇ āĻĒā§āϰāϝāĻŧā§‹āĻ— āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇ - āφāĻĒāύāĻžāϰ āĻāĻœā§‡āĻ¨ā§āϟ āϤāĻŋāύāϟāĻŋāχ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇!

āĻ…āĻ­āĻŋāύāĻ¨ā§āĻĻāύ! āφāĻĒāύāĻŋ āĻšāĻžāχāĻŦā§āϰāĻŋāĻĄ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ⧇āϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āφāĻĒāύāĻžāϰ āĻ—ā§āϰāĻžāĻĢ āφāϰāĻāϜāĻŋ āĻāĻœā§‡āĻ¨ā§āϟ āϏāĻĢāϞāĻ­āĻžāĻŦ⧇ āĻļ⧇āώ āĻ•āϰ⧇āϛ⧇āύ!

ā§­. ADK āĻ“āϝāĻŧ⧇āĻŦ⧇āϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āφāĻĒāύāĻžāϰ āĻāĻœā§‡āĻ¨ā§āĻŸā§‡āϰ āĻĒāϰ⧀āĻ•ā§āώāĻž āĻ•āϰāĻž

āφāĻĒāύāĻžāϰ āĻāĻœā§‡āĻ¨ā§āϟ āĻĒāϰ⧀āĻ•ā§āώāĻž āĻ•āϰāĻžāϰ āϏāĻŦāĻšā§‡āϝāĻŧ⧇ āϏāĻšāϜ āωāĻĒāĻžāϝāĻŧ āĻšāϞ adk web āĻ•āĻŽāĻžāĻ¨ā§āĻĄ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž, āϝāĻž āφāĻĒāύāĻžāϰ āĻāĻœā§‡āĻ¨ā§āϟāϕ⧇ āĻāĻ•āϟāĻŋ āĻ…āĻ¨ā§āϤāĻ°ā§āύāĻŋāĻ°ā§āĻŽāĻŋāϤ āĻšā§āϝāĻžāϟ āχāĻ¨ā§āϟāĻžāϰāĻĢ⧇āϏ⧇āϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āϚāĻžāϞ⧁ āĻ•āϰ⧇āĨ¤

ā§§. āĻāĻœā§‡āĻ¨ā§āϟ āĻĒāϰāĻŋāϚāĻžāϞāύāĻž

👉đŸ’ģ āĻŦā§āϝāĻžāĻ•āĻāĻ¨ā§āĻĄ āĻĄāĻŋāϰ⧇āĻ•ā§āϟāϰāĻŋāϤ⧇ āύ⧇āĻ­āĻŋāϗ⧇āϟ āĻ•āϰ⧁āύ (āϝ⧇āĻ–āĻžāύ⧇ āφāĻĒāύāĻžāϰ āĻāĻœā§‡āĻ¨ā§āϟ āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ) āĻāĻŦāĻ‚ āĻ“āϝāĻŧ⧇āĻŦ āχāĻ¨ā§āϟāĻžāϰāĻĢ⧇āϏ āϚāĻžāϞ⧁ āĻ•āϰ⧁āύ::

cd ~/way-back-home/level_2/backend
uv run adk web

āĻāχ āĻ•āĻŽāĻžāĻ¨ā§āĻĄāϟāĻŋ āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ āĻāĻœā§‡āĻ¨ā§āϟ āĻļ⧁āϰ⧁ āĻ•āϰ⧇

agent/agent.py

āĻāĻŦāĻ‚ āĻĒāϰ⧀āĻ•ā§āώāĻžāϰ āϜāĻ¨ā§āϝ āĻāĻ•āϟāĻŋ āĻ“āϝāĻŧ⧇āĻŦ āχāĻ¨ā§āϟāĻžāϰāĻĢ⧇āϏ āĻ–ā§‹āϞ⧇āĨ¤

👉 URL āϖ⧁āϞ⧁āύ:

āĻ•āĻŽāĻžāĻ¨ā§āĻĄāϟāĻŋ āĻāĻ•āϟāĻŋ āĻ¸ā§āĻĨāĻžāύ⧀āϝāĻŧ URL āφāωāϟāĻĒ⧁āϟ āĻ•āϰāĻŦ⧇ (āϏāĻžāϧāĻžāϰāĻŖāϤ http://127.0.0.1:8000 āĻŦāĻž āĻ…āύ⧁āϰ⧂āĻĒ)āĨ¤ āĻāϟāĻŋ āφāĻĒāύāĻžāϰ āĻŦā§āϰāĻžāωāϜāĻžāϰ⧇ āϖ⧁āϞ⧁āύāĨ¤

āĻ…ā§āϝāĻžāĻĄāϕ⧇ āĻ“āϝāĻŧ⧇āĻŦ

URL-āĻ āĻ•ā§āϞāĻŋāĻ• āĻ•āϰāĻžāϰ āĻĒāϰ, āφāĻĒāύāĻŋ ADK āĻ“āϝāĻŧ⧇āĻŦ UI āĻĻ⧇āĻ–āϤ⧇ āĻĒāĻžāĻŦ⧇āύāĨ¤ āωāĻĒāϰ⧇āϰ āĻŦāĻžāĻŽ āϕ⧋āĻŖ āĻĨ⧇āϕ⧇ "āĻāĻœā§‡āĻ¨ā§āϟ" āύāĻŋāĻ°ā§āĻŦāĻžāϚāύ āĻ•āϰ⧁āύāĨ¤

āĻ…ā§āϝāĻžāĻĄāϕ⧇_āχāωāφāχ

2. āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻ•ā§āώāĻŽāϤāĻž āĻĒāϰ⧀āĻ•ā§āώāĻž āĻ•āϰāĻž

āĻāĻœā§‡āĻ¨ā§āϟāϟāĻŋ āφāĻĒāύāĻžāϰ āĻĒā§āϰāĻļā§āύ⧇āϰ āĻŦ⧁āĻĻā§āϧāĻŋāĻŽāĻ¤ā§āϤāĻžāϰ āϏāĻžāĻĨ⧇ āϏāĻŽāĻžāϧāĻžāύ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻĄāĻŋāϜāĻžāχāύ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇āĨ¤ āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āύ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻĒāĻĻā§āϧāϤāĻŋ āĻ•āĻžāĻ°ā§āϝāĻ•āϰāĻ­āĻžāĻŦ⧇ āĻĻ⧇āĻ–āϤ⧇ āĻšā§āϝāĻžāϟ āωāχāĻ¨ā§āĻĄā§‹āϤ⧇ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āχāύāĻĒ⧁āϟāϗ⧁āϞāĻŋ āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰ⧁āύāĨ¤

āĻ…āĻ°ā§āĻĨ āĻāĻŦāĻ‚ āϧāĻžāϰāĻŖāĻžāϰ āωāĻĒāϰ āĻ­āĻŋāĻ¤ā§āϤāĻŋ āĻ•āϰ⧇ āφāχāĻŸā§‡āĻŽāϗ⧁āϞāĻŋ āϖ⧁āρāĻœā§‡ āĻŦ⧇āϰ āĻ•āϰ⧇, āĻāĻŽāύāĻ•āĻŋ āϝāĻĻāĻŋ āϕ⧀āĻ“āϝāĻŧāĻžāĻ°ā§āĻĄāϗ⧁āϞāĻŋ āĻŽāĻŋāϞ āύāĻžāĻ“ āĻšāϝāĻŧāĨ¤

āĻĒāϰ⧀āĻ•ā§āώāĻžāϰ āĻĒā§āϰāĻļā§āύ: (āύ⧀āĻšā§‡āϰ āϝ⧇āϕ⧋āύ⧋ āĻāĻ•āϟāĻŋ āĻŦ⧇āϛ⧇ āύāĻŋāύ)

Who can help with injuries?
What abilities are related to survival?

āϕ⧀ āϖ⧁āρāϜāĻŦ⧇āύ:

  • āϝ⧁āĻ•ā§āϤāĻŋāϤ⧇ āĻļāĻŦā§āĻĻāĻžāĻ°ā§āĻĨāĻŋāĻ• āĻŦāĻž RAG āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āωāĻ˛ā§āϞ⧇āĻ– āĻ•āϰāĻž āωāϚāĻŋāϤāĨ¤
  • āφāĻĒāύāĻžāϰ āϧāĻžāϰāĻŖāĻžāĻ—āϤāĻ­āĻžāĻŦ⧇ āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ āĻĢāϞāĻžāĻĢāϞ āĻĻ⧇āĻ–āϤ⧇ āĻĒāĻžāĻ“ā§ŸāĻž āωāϚāĻŋāϤ (āϝ⧇āĻŽāύ, "āĻĒā§āϰāĻžāĻĨāĻŽāĻŋāĻ• āϚāĻŋāĻ•āĻŋā§ŽāϏāĻž" āϜāĻŋāĻœā§āĻžāĻžāϏāĻž āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ "āĻ…āĻ¸ā§āĻ¤ā§āϰ⧋āĻĒāϚāĻžāϰ")āĨ¤
  • āĻĢāϞāĻžāĻĢāϞ⧇ đŸ§Ŧ āφāχāĻ•āύ āĻĨāĻžāĻ•āĻŦ⧇āĨ¤

āϜāϟāĻŋāϞ āĻĒā§āϰāĻļā§āύ⧇āϰ āϜāĻ¨ā§āϝ āĻļāĻŦā§āĻĻāĻžāĻ°ā§āĻĨāĻŋāĻ• āĻŦā§‹āĻāĻžāϰ āϏāĻžāĻĨ⧇ āϕ⧀āĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ āĻĢāĻŋāĻ˛ā§āϟāĻžāϰāϗ⧁āϞāĻŋāϕ⧇ āĻāĻ•āĻ¤ā§āϰāĻŋāϤ āĻ•āϰ⧇āĨ¤

āĻĒāϰ⧀āĻ•ā§āώāĻžāϰ āĻĒā§āϰāĻļā§āύ: (āύ⧀āĻšā§‡āϰ āϝ⧇āϕ⧋āύ⧋ āĻāĻ•āϟāĻŋ āĻŦ⧇āϛ⧇ āύāĻŋāύ)

Find someone who can ply a plane in the volcanic area
Who has healing abilities in the FOSSILIZED?
Who has healing abilities in the mountains?

āϕ⧀ āϖ⧁āρāϜāĻŦ⧇āύ:

  • āϝ⧁āĻ•ā§āϤāĻŋāϤ⧇ āĻšāĻžāχāĻŦā§āϰāĻŋāĻĄ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ⧇āϰ āĻ•āĻĨāĻž āωāĻ˛ā§āϞ⧇āĻ– āĻ•āϰāĻž āωāϚāĻŋāϤāĨ¤
  • āĻĢāϞāĻžāĻĢāϞ āωāĻ­āϝāĻŧ āĻŽāĻžāύāĻĻāĻŖā§āĻĄā§‡āϰ (āϧāĻžāϰāĻŖāĻž + āĻ…āĻŦāĻ¸ā§āĻĨāĻžāύ/āĻŦāĻŋāĻ­āĻžāĻ—) āϏāĻžāĻĨ⧇ āĻŽāĻŋāϞāĻŋāϤ āĻšāĻ“āϝāĻŧāĻž āωāϚāĻŋāϤāĨ¤
  • āωāĻ­āϝāĻŧ āĻĒāĻĻā§āϧāϤāĻŋāϤ⧇ āĻĒāĻžāĻ“āϝāĻŧāĻž āĻĢāϞāĻžāĻĢāϞ⧇ 🔀 āφāχāĻ•āύ āĻĨāĻžāĻ•āĻŦ⧇ āĻāĻŦāĻ‚ āϏāĻ°ā§āĻŦā§‹āĻšā§āϚ āĻ¸ā§āĻĨāĻžāύ āĻĒāĻžāĻŦ⧇āĨ¤

👉đŸ’ģ āĻĒāϰ⧀āĻ•ā§āώāĻž āĻļ⧇āώ āĻšāϞ⧇, āφāĻĒāύāĻžāϰ āĻ•āĻŽāĻžāĻ¨ā§āĻĄ āϞāĻžāχāύ⧇ Ctrl+C āϟāĻŋāĻĒ⧇ āĻĒā§āϰāĻ•ā§āϰāĻŋāϝāĻŧāĻžāϟāĻŋ āĻļ⧇āώ āĻ•āϰ⧁āύāĨ¤

ā§Ž. āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āφāĻŦ⧇āĻĻāύāĻĒāĻ¤ā§āϰ āϚāĻžāϞāĻžāύ⧋

āĻĢ⧁āϞ āĻ¸ā§āĻŸā§āϝāĻžāĻ• āφāĻ°ā§āĻ•āĻŋāĻŸā§‡āĻ•āϚāĻžāϰ āĻ“āĻ­āĻžāϰāĻ­āĻŋāω

āφāĻ°ā§āĻ•āĻŋāĻŸā§‡āĻ•āϚāĻžāϰ_āĻĢ⧁āϞāĻ¸ā§āĻŸā§āϝāĻžāĻ•

āϏ⧇āĻļāύ āϏāĻžāĻ°ā§āĻ­āĻŋāϏ āĻāĻŦāĻ‚ āϰāĻžāύāĻžāϰ āϝ⧋āĻ— āĻ•āϰ⧁āύ

👉đŸ’ģ āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ⧇, āĻ•ā§āϞāĻžāωāĻĄ āĻļ⧇āϞ āĻāĻĄāĻŋāϟāϰ⧇ chat.py āĻĢāĻžāχāϞāϟāĻŋ āϚāĻžāϞ⧁ āĻ•āϰ⧁āύ (āĻāĻ—āĻŋāϝāĻŧ⧇ āϝāĻžāĻ“āϝāĻŧāĻžāϰ āφāϗ⧇ āĻĒā§‚āĻ°ā§āĻŦāĻŦāĻ°ā§āϤ⧀ āĻĒā§āϰāĻ•ā§āϰāĻŋāϝāĻŧāĻžāϟāĻŋ āĻļ⧇āώ āĻ•āϰāϤ⧇ "ctrl+C" āĻ•āϰ⧇āϛ⧇āύ āĻ•āĻŋāύāĻž āϤāĻž āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰ⧁āύ):

cloudshell edit ~/way-back-home/level_2/backend/api/routes/chat.py

chat.py āĻĢāĻžāχāϞ⧇, āĻŽāĻ¨ā§āϤāĻŦā§āϝāϟāĻŋ āϖ⧁āρāϜ⧁āύ # TODO: REPLACE_INMEMORY_SERVICES , āĻāχ āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āϞāĻžāχāύāϟāĻŋ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āϕ⧋āĻĄ āĻĻāĻŋāϝāĻŧ⧇ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ :

    session_service = InMemorySessionService()
    memory_service = InMemoryMemoryService()

chat.py āĻĢāĻžāχāϞ⧇, āĻŽāĻ¨ā§āϤāĻŦā§āϝāϟāĻŋ āϏāύāĻžāĻ•ā§āϤ āĻ•āϰ⧁āύ # TODO: REPLACE_RUNNER , āĻāχ āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āϞāĻžāχāύāϟāĻŋ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āϕ⧋āĻĄ āĻĻāĻŋāϝāĻŧ⧇ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ :

runner = Runner(
    agent=root_agent, 
    session_service=session_service,
    memory_service=memory_service,
    app_name="survivor-network"
)

1. āφāĻŦ⧇āĻĻāύ āĻļ⧁āϰ⧁ āĻ•āϰ⧁āύ

āϝāĻĻāĻŋ āĻĒā§‚āĻ°ā§āĻŦāĻŦāĻ°ā§āϤ⧀ āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞāϟāĻŋ āĻāĻ–āύāĻ“ āϚāϞāĻŽāĻžāύ āĻĨāĻžāϕ⧇, āϤāĻžāĻšāϞ⧇ Ctrl+C āϟāĻŋāĻĒ⧇ āĻāϟāĻŋ āĻļ⧇āώ āĻ•āϰ⧁āύāĨ¤

👉đŸ’ģ āĻ…ā§āϝāĻžāĻĒ āĻļ⧁āϰ⧁ āĻ•āϰ⧁āύ:

cd ~/way-back-home/level_2/
./start_app.sh

āϝāĻ–āύ āĻāϟāĻŋ āϏāĻĢāϞāĻ­āĻžāĻŦ⧇ āĻŦā§āϝāĻžāĻ•āĻāĻ¨ā§āĻĄ āĻļ⧁āϰ⧁ āĻ•āϰāĻŦ⧇, āϤāĻ–āύ āφāĻĒāύāĻŋ āύ⧀āĻšā§‡āϰ āĻŽāϤ Local: http://localhost:5173/" āĻĻ⧇āĻ–āϤ⧇ āĻĒāĻžāĻŦ⧇āύ: āϏāĻžāĻŽāύ⧇āϰ āĻĻāĻŋāϕ⧇

👉 āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ āĻĨ⧇āϕ⧇ Local: http://localhost:5173/ āĻ āĻ•ā§āϞāĻŋāĻ• āĻ•āϰ⧁āύāĨ¤

āĻ•āĻĨā§‹āĻĒāĻ•āĻĨāύ

āĻĒā§āϰāĻļā§āύ :

Find skills similar to healing

āĻšā§āϝāĻžāϟ

āĻ•āĻŋ āĻšāϝāĻŧ :

  • āĻāĻœā§‡āĻ¨ā§āϟ āϏāĻžāĻĻ⧃āĻļā§āϝ āĻ…āύ⧁āϰ⧋āϧ āĻ¸ā§āĻŦā§€āĻ•ā§ƒāϤāĻŋ āĻĻ⧇āϝāĻŧ
  • "āύāĻŋāϰāĻžāĻŽāϝāĻŧ" āĻāϰ āϜāĻ¨ā§āϝ āĻāĻŽā§āĻŦ⧇āĻĄāĻŋāĻ‚ āϤ⧈āϰāĻŋ āĻ•āϰ⧇
  • āĻļāĻŦā§āĻĻāĻžāĻ°ā§āĻĨāĻ—āϤāĻ­āĻžāĻŦ⧇ āĻ…āύ⧁āϰ⧂āĻĒ āĻĻāĻ•ā§āώāϤāĻž āϖ⧁āρāĻœā§‡ āĻĒ⧇āϤ⧇ āϕ⧋āϏāĻžāχāύ āĻĻā§‚āϰāĻ¤ā§āĻŦ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇
  • āϰāĻŋāϟāĻžāĻ°ā§āύāϏ: āĻĒā§āϰāĻžāĻĨāĻŽāĻŋāĻ• āϚāĻŋāĻ•āĻŋā§ŽāϏāĻž (āϝāĻĻāĻŋāĻ“ āύāĻžāĻŽāϗ⧁āϞāĻŋ "āύāĻŋāϰāĻžāĻŽāϝāĻŧ" āĻāϰ āϏāĻžāĻĨ⧇ āĻŽā§‡āϞ⧇ āύāĻž)

āĻĒā§āϰāĻļā§āύ :

Find medical skills in the mountains

āĻ•āĻŋ āĻšāϝāĻŧ :

  1. āϕ⧀āĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ : category='medical' āĻāϰ āϜāĻ¨ā§āϝ āĻĢāĻŋāĻ˛ā§āϟāĻžāϰ āĻ•āϰ⧁āύ
  2. āĻļāĻŦā§āĻĻāĻžāĻ°ā§āĻĨāĻŋāĻ• āωāĻĒāĻžāĻĻāĻžāύ : "āϚāĻŋāĻ•āĻŋā§ŽāϏāĻž" āĻāĻŽā§āĻŦ⧇āĻĄ āĻ•āϰ⧁āύ āĻāĻŦāĻ‚ āϏāĻžāĻĻ⧃āĻļā§āϝ āĻ…āύ⧁āϏāĻžāϰ⧇ āĻ°â€Œā§āϝāĻžāĻ™ā§āĻ• āĻ•āϰ⧁āύ
  3. āĻŽāĻžāĻ°ā§āϜ āĻ•āϰ⧁āύ : āωāĻ­āϝāĻŧ āĻĒāĻĻā§āϧāϤāĻŋāϤ⧇ āĻĒāĻžāĻ“āϝāĻŧāĻž āĻĢāϞāĻžāĻĢāϞāϗ⧁āϞāĻŋāϕ⧇ āĻ…āĻ—ā§āϰāĻžāϧāĻŋāĻ•āĻžāϰ āĻĻāĻŋāϝāĻŧ⧇ āĻāĻ•āĻ¤ā§āϰāĻŋāϤ āĻ•āϰ⧁āύ 🔀

āĻĒā§āϰāĻļā§āύ (āϐāĻšā§āĻ›āĻŋāĻ•) :

Who is good at survival and in the forest?

āĻ•āĻŋ āĻšāϝāĻŧ :

  • āϕ⧀āĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ āϖ⧁āρāĻœā§‡ āĻĒāĻžā§Ÿ: biome='forest'
  • āĻļāĻŦā§āĻĻāĻžāĻ°ā§āĻĨāĻŋāĻ• āφāĻŦāĻŋāĻˇā§āĻ•āĻžāϰ: "āĻŦ⧇āρāĻšā§‡ āĻĨāĻžāĻ•āĻžāϰ" āĻŽāϤ⧋ āĻĻāĻ•ā§āώāϤāĻž
  • āĻšāĻžāχāĻŦā§āϰāĻŋāĻĄ āϏ⧇āϰāĻž āĻĢāϞāĻžāĻĢāϞ⧇āϰ āϜāĻ¨ā§āϝ āωāĻ­āϝāĻŧāϕ⧇āχ āĻāĻ•āĻ¤ā§āϰāĻŋāϤ āĻ•āϰ⧇

👉đŸ’ģ āϝāĻ–āύ āφāĻĒāύāĻŋ āĻĒāϰ⧀āĻ•ā§āώāĻž āĻļ⧇āώ āĻ•āϰāĻŦ⧇āύ, āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ⧇, Ctrl+C āϟāĻŋāĻĒ⧇ āĻāϟāĻŋ āĻļ⧇āώ āĻ•āϰ⧁āύāĨ¤

⧝. āĻŽāĻžāĻ˛ā§āϟāĻŋāĻŽā§‹āĻĄāĻžāϞ āĻĒāĻžāχāĻĒāϞāĻžāχāύ — āϟ⧁āϞāĻŋāĻ‚ āϞ⧇āϝāĻŧāĻžāϰ

āϕ⧇āύ āφāĻŽāĻžāĻĻ⧇āϰ āĻāĻ•āϟāĻŋ āĻŽāĻžāĻ˛ā§āϟāĻŋāĻŽā§‹āĻĄāĻžāϞ āĻĒāĻžāχāĻĒāϞāĻžāχāύ⧇āϰ āĻĒā§āϰāϝāĻŧā§‹āϜāύ?

āĻŦ⧇āρāĻšā§‡ āĻĨāĻžāĻ•āĻžāϰ āύ⧇āϟāĻ“āϝāĻŧāĻžāĻ°ā§āĻ• āϕ⧇āĻŦāϞ āĻŸā§‡āĻ•ā§āϏāϟ āύāϝāĻŧāĨ¤ āĻ•ā§āώ⧇āĻ¤ā§āϰ⧇āϰ āĻŦ⧇āρāĻšā§‡ āĻĨāĻžāĻ•āĻž āĻŦā§āϝāĻ•ā§āϤāĻŋāϰāĻž āϏāϰāĻžāϏāϰāĻŋ āĻšā§āϝāĻžāĻŸā§‡āϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āĻ…āϏāĻ‚āĻ—āĻ āĻŋāϤ āϤāĻĨā§āϝ āĻĒāĻžāĻ āĻžāύ:

  • 📸 āĻ›āĻŦāĻŋ : āϏāĻŽā§āĻĒāĻĻ, āĻŦāĻŋāĻĒāĻĻ, āĻŦāĻž āϏāϰāĻžā§āϜāĻžāĻŽā§‡āϰ āĻ›āĻŦāĻŋ
  • đŸŽĨ āĻ­āĻŋāĻĄāĻŋāĻ“ : āĻ¸ā§āĻŸā§āϝāĻžāϟāĻžāϏ āϰāĻŋāĻĒā§‹āĻ°ā§āϟ āĻŦāĻž SOS āϏāĻŽā§āĻĒā§āϰāϚāĻžāϰ
  • 📄 āĻŸā§‡āĻ•ā§āϏāϟ : āĻĢāĻŋāĻ˛ā§āĻĄ āύ⧋āϟ āĻŦāĻž āϞāĻ—

āφāĻŽāϰāĻž āϕ⧋āύ āĻĢāĻžāχāϞāϗ⧁āϞāĻŋ āĻĒā§āϰāĻ•ā§āϰāĻŋāϝāĻŧāĻž āĻ•āϰāĻ›āĻŋ?

āφāϗ⧇āϰ āϧāĻžāĻĒ⧇ āϝ⧇āĻ–āĻžāύ⧇ āφāĻŽāϰāĻž āĻŦāĻŋāĻĻā§āϝāĻŽāĻžāύ āĻĄā§‡āϟāĻž āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻ•āϰ⧇āĻ›āĻŋ, āϤāĻžāϰ āĻŦāĻŋāĻĒāϰ⧀āϤ⧇, āĻāĻ–āĻžāύ⧇ āφāĻŽāϰāĻž User-Uploaded Files āĻĒā§āϰāĻ•ā§āϰāĻŋāϝāĻŧāĻž āĻ•āϰāĻŋāĨ¤ chat.py āχāĻ¨ā§āϟāĻžāϰāĻĢ⧇āϏāϟāĻŋ āĻ—āϤāĻŋāĻļā§€āϞāĻ­āĻžāĻŦ⧇ āĻĢāĻžāχāϞ āϏāĻ‚āϝ⧁āĻ•ā§āϤāĻŋ āĻĒāϰāĻŋāϚāĻžāϞāύāĻž āĻ•āϰ⧇:

āĻ‰ā§ŽāϏ

āĻ•āĻ¨ā§āĻŸā§‡āĻ¨ā§āϟ

āϞāĻ•ā§āĻˇā§āϝ

āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āϏāĻ‚āϝ⧁āĻ•ā§āϤāĻŋ

āĻ›āĻŦāĻŋ/āĻ­āĻŋāĻĄāĻŋāĻ“/āĻŸā§‡āĻ•ā§āϏāϟ

āĻ—ā§āϰāĻžāĻĢ⧇ āϝ⧋āĻ— āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āϤāĻĨā§āϝ

āĻšā§āϝāĻžāϟ āĻĒā§āϰāϏāĻ™ā§āĻ—

"āĻāĻ–āĻžāύ⧇ āϏāϰāĻŦāϰāĻžāĻšā§‡āϰ āĻāĻ•āϟāĻŋ āĻ›āĻŦāĻŋ"

āωāĻĻā§āĻĻ⧇āĻļā§āϝ āĻāĻŦāĻ‚ āĻ…āϤāĻŋāϰāĻŋāĻ•ā§āϤ āĻŦāĻŋāĻŦāϰāĻŖ

āĻĒāϰāĻŋāĻ•āĻ˛ā§āĻĒāĻŋāϤ āĻĒāĻĻā§āϧāϤāĻŋ: āϏāĻŋāϕ⧋āϝāĻŧ⧇āĻ¨ā§āϏāĻŋāϝāĻŧāĻžāϞ āĻāĻœā§‡āĻ¨ā§āϟ āĻĒāĻžāχāĻĒāϞāĻžāχāύ

āφāĻŽāϰāĻž āĻāĻ•āϟāĻŋ āϏāĻŋāϕ⧋āϝāĻŧ⧇āĻ¨ā§āϏāĻŋāϝāĻŧāĻžāϞ āĻāĻœā§‡āĻ¨ā§āϟ ( multimedia_agent.py ) āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŋ āϝāĻž āĻŦāĻŋāĻļ⧇āώāĻžāϝāĻŧāĻŋāϤ āĻāĻœā§‡āĻ¨ā§āϟāĻĻ⧇āϰ āĻāĻ•āϏāĻžāĻĨ⧇ āĻļ⧃āĻ™ā§āĻ–āϞāĻŋāϤ āĻ•āϰ⧇:

āφāĻ°ā§āĻ•āĻŋāĻŸā§‡āĻ•āϚāĻžāϰ_āφāĻĒāϞ⧋āĻĄāĻŋāĻ‚

āĻāϟāĻŋāϕ⧇ backend/agent/multimedia_agent.py āϤ⧇ SequentialAgent āĻšāĻŋāϏ⧇āĻŦ⧇ āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇āĨ¤

āϟ⧁āϞāĻŋāĻ‚ āϞ⧇āϝāĻŧāĻžāϰāϟāĻŋ āĻāĻœā§‡āĻ¨ā§āϟāĻĻ⧇āϰ āϜāĻ¨ā§āϝ āĻĒā§āϰāϝāĻŧā§‹āϜāύ⧀āϝāĻŧ āĻ•ā§āώāĻŽāϤāĻž āĻĒā§āϰāĻĻāĻžāύ āĻ•āϰ⧇āĨ¤ āϟ⧁āϞāϗ⧁āϞāĻŋ "āϕ⧀āĻ­āĻžāĻŦ⧇" āĻĒāϰāĻŋāϚāĻžāϞāύāĻž āĻ•āϰ⧇ — āĻĢāĻžāχāϞ āφāĻĒāϞ⧋āĻĄ āĻ•āϰāĻž, āϏāĻ¤ā§āϤāĻž āĻŦ⧇āϰ āĻ•āϰāĻž āĻāĻŦāĻ‚ āĻĄāĻžāϟāĻžāĻŦ⧇āϏ⧇ āϏāĻ‚āϰāĻ•ā§āώāĻŖ āĻ•āϰāĻžāĨ¤

ā§§. āϟ⧁āϞāϏ āĻĢāĻžāχāϞāϟāĻŋ āϖ⧁āϞ⧁āύ

👉đŸ’ģ āĻāĻ•āϟāĻŋ āύāϤ⧁āύ āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ āϖ⧁āϞ⧁āύāĨ¤ āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ⧇, āĻ•ā§āϞāĻžāωāĻĄ āĻļ⧇āϞ āĻāĻĄāĻŋāϟāϰ⧇ āĻĢāĻžāχāϞāϟāĻŋ āϖ⧁āϞ⧁āύ:

cloudshell edit ~/way-back-home/level_2/backend/agent/tools/extraction_tools.py

2. upload_media āϟ⧁āϞāϟāĻŋ āĻŦāĻžāĻ¸ā§āϤāĻŦāĻžāϝāĻŧāύ āĻ•āϰ⧁āύ

āĻāχ āϟ⧁āϞāϟāĻŋ āϗ⧁āĻ—āϞ āĻ•ā§āϞāĻžāωāĻĄ āĻ¸ā§āĻŸā§‹āϰ⧇āĻœā§‡ āĻāĻ•āϟāĻŋ āĻ¸ā§āĻĨāĻžāύ⧀āϝāĻŧ āĻĢāĻžāχāϞ āφāĻĒāϞ⧋āĻĄ āĻ•āϰ⧇āĨ¤

👉 extraction_tools.py āϤ⧇, āĻŽāĻ¨ā§āϤāĻŦā§āϝ pass # TODO: REPLACE_UPLOAD_MEDIA_FUNCTION āĨ¤

āĻāχ āĻĒ⧁āϰ⧋ āϞāĻžāχāύāϟāĻŋ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āϕ⧋āĻĄ āĻĻāĻŋāϝāĻŧ⧇ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ :

    """
    Upload media file to GCS and detect its type.
    
    Args:
        file_path: Path to the local file
        survivor_id: Optional survivor ID to associate with upload
        
    Returns:
        Dict with gcs_uri, media_type, and status
    """
    try:
        if not file_path:
            return {"status": "error", "error": "No file path provided"}
        
        # Strip quotes if present
        file_path = file_path.strip().strip("'").strip('"')
        
        if not os.path.exists(file_path):
            return {"status": "error", "error": f"File not found: {file_path}"}
        
        gcs_uri, media_type, signed_url = gcs_service.upload_file(file_path, survivor_id)
        
        return {
            "status": "success",
            "gcs_uri": gcs_uri,
            "signed_url": signed_url,
            "media_type": media_type.value,
            "file_name": os.path.basename(file_path),
            "survivor_id": survivor_id
        }
    except Exception as e:
        logger.error(f"Upload failed: {e}")
        return {"status": "error", "error": str(e)}

ā§Š. extract_from_media āϟ⧁āϞāϟāĻŋ āĻŦāĻžāĻ¸ā§āϤāĻŦāĻžāϝāĻŧāύ āĻ•āϰ⧁āύ

āĻāχ āϟ⧁āϞāϟāĻŋ āĻāĻ•āϟāĻŋ āϰāĻžāωāϟāĻžāϰ — āĻāϟāĻŋ media_type āĻĒāϰ⧀āĻ•ā§āώāĻž āĻ•āϰ⧇ āĻāĻŦāĻ‚ āϏāĻ āĻŋāĻ• āĻāĻ•ā§āϏāĻŸā§āĻ°ā§āϝāĻžāĻ•ā§āϟāϰ⧇ (āĻŸā§‡āĻ•ā§āϏāϟ, āĻ›āĻŦāĻŋ, āĻŦāĻž āĻ­āĻŋāĻĄāĻŋāĻ“) āĻĒā§āϰ⧇āϰāĻŖ āĻ•āϰ⧇āĨ¤

extraction_tools.py āϤ⧇, āĻŽāĻ¨ā§āϤāĻŦā§āϝ pass # TODO: REPLACE_EXTRACT_FROM_MEDIA āĨ¤

āĻāχ āĻĒ⧁āϰ⧋ āϞāĻžāχāύāϟāĻŋ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āϕ⧋āĻĄ āĻĻāĻŋāϝāĻŧ⧇ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ :

    """
    Extract entities and relationships from uploaded media.
    
    Args:
        gcs_uri: GCS URI of the uploaded file
        media_type: Type of media (text/image/video)
        signed_url: Optional signed URL for public/temporary access
        
    Returns:
        Dict with extraction results
    """
    try:
        if not gcs_uri:
             return {"status": "error", "error": "No GCS URI provided"}

        # Select appropriate extractor
        if media_type == MediaType.TEXT.value or media_type == "text":
            result = await text_extractor.extract(gcs_uri)
        elif media_type == MediaType.IMAGE.value or media_type == "image":
            result = await image_extractor.extract(gcs_uri)
        elif media_type == MediaType.VIDEO.value or media_type == "video":
            result = await video_extractor.extract(gcs_uri)
        else:
            return {"status": "error", "error": f"Unsupported media type: {media_type}"}
            
        # Inject signed URL into broadcast info if present
        if signed_url:
            if not result.broadcast_info:
                result.broadcast_info = {}
            result.broadcast_info['thumbnail_url'] = signed_url
        
        return {
            "status": "success",
            "extraction_result": result.to_dict(), # Return valid JSON dict instead of object
            "summary": result.summary,
            "entities_count": len(result.entities),
            "relationships_count": len(result.relationships),
            "entities": [e.to_dict() for e in result.entities],
            "relationships": [r.to_dict() for r in result.relationships]
        }
    except Exception as e:
        logger.error(f"Extraction failed: {e}")
        return {"status": "error", "error": str(e)}

āĻŽā§‚āϞ āĻŦāĻžāĻ¸ā§āϤāĻŦāĻžāϝāĻŧāύ⧇āϰ āĻŦāĻŋāĻŦāϰāĻŖ:

  • āĻŽāĻžāĻ˛ā§āϟāĻŋāĻŽā§‹āĻĄāĻžāϞ āχāύāĻĒ⧁āϟ : āφāĻŽāϰāĻž āĻŸā§‡āĻ•ā§āϏāϟ āĻĒā§āϰāĻŽā§āĻĒāϟ ( _get_extraction_prompt() ) āĻāĻŦāĻ‚ āχāĻŽā§‡āϜ āĻ…āĻŦāĻœā§‡āĻ•ā§āϟ āωāĻ­āϝāĻŧāϕ⧇āχ generate_content āĻ āĻĒāĻžāϏ āĻ•āϰāĻŋāĨ¤
  • āĻ¸ā§āĻŸā§āϰāĻžāĻ•āϚāĻžāĻ°ā§āĻĄ āφāωāϟāĻĒ⧁āϟ : response_mime_type="application/json" āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰ⧇ āϝ⧇ LLM āĻŦ⧈āϧ JSON āĻĒā§āϰāĻĻāĻžāύ āĻ•āϰ⧇, āϝāĻž āĻĒāĻžāχāĻĒāϞāĻžāχāύ⧇āϰ āϜāĻ¨ā§āϝ āĻ…āĻ¤ā§āϝāĻ¨ā§āϤ āϗ⧁āϰ⧁āĻ¤ā§āĻŦāĻĒā§‚āĻ°ā§āĻŖāĨ¤
  • āĻ­āĻŋāĻœā§āϝ⧁āϝāĻŧāĻžāϞ āĻāĻ¨ā§āϟāĻŋāϟāĻŋ āϞāĻŋāĻ™ā§āĻ•āĻŋāĻ‚ : āĻĒā§āϰāĻŽā§āĻĒāĻŸā§‡ āĻĒāϰāĻŋāϚāĻŋāϤ āĻāĻ¨ā§āϟāĻŋāϟāĻŋ āĻ…āĻ¨ā§āϤāĻ°ā§āϭ⧁āĻ•ā§āϤ āĻĨāĻžāϕ⧇ āϝāĻžāϤ⧇ āĻŽāĻŋāĻĨ⧁āύ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻ…āĻ•ā§āώāϰ āϚāĻŋāύāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤

ā§Ē. save_to_spanner āϟ⧁āϞāϟāĻŋ āĻĒā§āϰāϝāĻŧā§‹āĻ— āĻ•āϰ⧁āύ

āĻāχ āϟ⧁āϞāϟāĻŋ āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ āĻ—ā§āϰāĻžāĻĢ āĻĄāĻŋāĻŦāĻŋāϤ⧇ āύāĻŋāĻˇā§āĻ•āĻžāĻļāĻŋāϤ āϏāĻ¤ā§āϤāĻž āĻāĻŦāĻ‚ āϏāĻŽā§āĻĒāĻ°ā§āĻ•āϗ⧁āϞāĻŋāϕ⧇ āϧāϰ⧇ āϰāĻžāϖ⧇āĨ¤

extraction_tools.py āϤ⧇, āĻŽāĻ¨ā§āϤāĻŦā§āϝ pass # TODO: REPLACE_SPANNER_AGENT āϏāύāĻžāĻ•ā§āϤ āĻ•āϰ⧁āύāĨ¤

āĻāχ āĻĒ⧁āϰ⧋ āϞāĻžāχāύāϟāĻŋ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āϕ⧋āĻĄ āĻĻāĻŋāϝāĻŧ⧇ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ :

    """
    Save extracted entities and relationships to Spanner Graph DB.
    
    Args:
        extraction_result: ExtractionResult object (or dict from previous step if passed as dict)
        survivor_id: Optional survivor ID to associate with the broadcast
        
    Returns:
        Dict with save statistics
    """
    try:
        # Handle if extraction_result is passed as the wrapper dict from extract_from_media
        result_obj = extraction_result
        if isinstance(extraction_result, dict) and 'extraction_result' in extraction_result:
             result_obj = extraction_result['extraction_result']
        
        # If result_obj is a dict (from to_dict()), reconstruct it
        if isinstance(result_obj, dict):
            from extractors.base_extractor import ExtractionResult
            result_obj = ExtractionResult.from_dict(result_obj)
        
        if not result_obj:
            return {"status": "error", "error": "No extraction result provided"}
            
        stats = spanner_service.save_extraction_result(result_obj, survivor_id)
        
        return {
            "status": "success",
            "entities_created": stats['entities_created'],
            "entities_existing": stats['entities_found_existing'],
            "relationships_created": stats['relationships_created'],
            "broadcast_id": stats['broadcast_id'],
            "errors": stats['errors'] if stats['errors'] else None
        }
    except Exception as e:
        logger.error(f"Spanner save failed: {e}")
        return {"status": "error", "error": str(e)}

āĻāĻœā§‡āĻ¨ā§āϟāĻĻ⧇āϰ āωāĻšā§āϚ-āĻ¸ā§āϤāϰ⧇āϰ āϏāϰāĻžā§āϜāĻžāĻŽ āĻĒā§āϰāĻĻāĻžāύ⧇āϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡, āφāĻŽāϰāĻž āĻāĻœā§‡āĻ¨ā§āĻŸā§‡āϰ āϝ⧁āĻ•ā§āϤāĻŋ āĻ•ā§āώāĻŽāϤāĻž āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āĻĄā§‡āϟāĻž āĻ…āĻ–āĻŖā§āĻĄāϤāĻž āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰāĻŋāĨ¤

ā§Ģ. GCS āĻĒāϰāĻŋāώ⧇āĻŦāĻž āφāĻĒāĻĄā§‡āϟ āĻ•āϰ⧁āύ

GCSService āϗ⧁āĻ—āϞ āĻ•ā§āϞāĻžāωāĻĄ āĻ¸ā§āĻŸā§‹āϰ⧇āĻœā§‡ āĻĒā§āϰāĻ•ā§ƒāϤ āĻĢāĻžāχāϞ āφāĻĒāϞ⧋āĻĄ āĻĒāϰāĻŋāϚāĻžāϞāύāĻž āĻ•āϰ⧇āĨ¤

👉đŸ’ģ āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ⧇, āĻ•ā§āϞāĻžāωāĻĄ āĻļ⧇āϞ āĻāĻĄāĻŋāϟāϰ⧇ āĻĢāĻžāχāϞāϟāĻŋ āϖ⧁āϞ⧁āύ:

cloudshell edit ~/way-back-home/level_2/backend/services/gcs_service.py

👉 gcs_service.py āĻĢāĻžāχāϞ⧇, upload_file āĻĢāĻžāĻ‚āĻļāύ⧇āϰ āĻ­āĻŋāϤāϰ⧇ # TODO: REPLACE_SAVE_TO_GCS āĻŽāĻ¨ā§āϤāĻŦā§āϝāϟāĻŋ āϖ⧁āρāϜ⧁āύāĨ¤

āĻāχ āĻĒ⧁āϰ⧋ āϞāĻžāχāύāϟāĻŋ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āϕ⧋āĻĄ āĻĻāĻŋāϝāĻŧ⧇ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ :

        blob = self.bucket.blob(blob_name)
        blob.upload_from_filename(file_path)

āĻāϟāĻŋāϕ⧇ āĻāĻ•āϟāĻŋ āĻĒāϰāĻŋāώ⧇āĻŦāĻžāϤ⧇ āϏāĻ‚āĻ•ā§āώ⧇āĻĒāĻŋāϤ āĻ•āϰ⧇, āĻāĻœā§‡āĻ¨ā§āϟāϕ⧇ GCS āĻŦāĻžāϕ⧇āϟ, āĻŦā§āϞāĻŦ āύāĻžāĻŽ, āĻ…āĻĨāĻŦāĻž āĻ¸ā§āĻŦāĻžāĻ•ā§āώāϰāĻŋāϤ URL āĻœā§‡āύāĻžāϰ⧇āĻļāύ āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ āϜāĻžāύāϤ⧇ āĻšāĻŦ⧇ āύāĻžāĨ¤ āĻāϟāĻŋ āϕ⧇āĻŦāϞ "āφāĻĒāϞ⧋āĻĄ" āĻ•āϰāϤ⧇ āĻŦāϞ⧇āĨ¤

ā§Ŧ. (āϕ⧇āĻŦāϞ āĻĒāĻ āύāϝ⧋āĻ—ā§āϝ) āϕ⧇āύ āĻāĻœā§‡āĻ¨ā§āϟāĻŋāĻ• āĻ•āĻ°ā§āĻŽāĻĒā§āϰāĻŦāĻžāĻš > āϐāϤāĻŋāĻšā§āϝāĻŦāĻžāĻšā§€ āĻĒāĻĻā§āϧāϤāĻŋ?

āĻāĻœā§‡āĻ¨ā§āϟāĻŋāĻ• āϏ⧁āĻŦāĻŋāϧāĻž:

āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝ

āĻŦā§āϝāĻžāϚ āĻĒāĻžāχāĻĒāϞāĻžāχāύ

āχāϭ⧇āĻ¨ā§āϟ-āϚāĻžāϞāĻŋāϤ

āĻāĻœā§‡āĻ¨ā§āϟāĻŋāĻ• āĻ•āĻ°ā§āĻŽāĻĒā§āϰāĻŦāĻžāĻš

āϜāϟāĻŋāϞāϤāĻž

āĻ•āĻŽ (ā§§āϟāĻŋ āĻ¸ā§āĻ•ā§āϰāĻŋāĻĒā§āϟ)

āωāĻšā§āϚ (ā§Ģ+ āĻĒāϰāĻŋāώ⧇āĻŦāĻž)

āύāĻŋāĻŽā§āύ (ā§§āϟāĻŋ āĻĒāĻžāχāĻĨāύ āĻĢāĻžāχāϞ: multimedia_agent.py )

āϰāĻžāĻœā§āϝ āĻŦā§āϝāĻŦāĻ¸ā§āĻĨāĻžāĻĒāύāĻž

āĻ—ā§āϞ⧋āĻŦāĻžāϞ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ

āĻļāĻ•ā§āϤ (āĻŦāĻŋāĻšā§āĻ›āĻŋāĻ¨ā§āύ)

āχāωāύāĻŋāĻĢāĻžāχāĻĄ (āĻāĻœā§‡āĻ¨ā§āϟ āĻ¸ā§āĻŸā§‡āϟ)

āĻ¤ā§āϰ⧁āϟāĻŋ āĻĒāϰāĻŋāϚāĻžāϞāύāĻž

āĻ•ā§āĻ°ā§āϝāĻžāĻļ

āύ⧀āϰāĻŦ āϞāĻ—

āχāĻ¨ā§āϟāĻžāϰ⧇āĻ•ā§āϟāĻŋāĻ­ ("āφāĻŽāĻŋ āϏ⧇āχ āĻĢāĻžāχāϞāϟāĻŋ āĻĒāĻĄāĻŧāϤ⧇ āĻĒāĻžāϰāĻŋāύāĻŋ")

āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋāϝāĻŧāĻž

āĻ•āύāϏ⧋āϞ āĻĒā§āϰāĻŋāĻ¨ā§āϟ

āĻĒā§‹āϞāĻŋāĻ‚ āĻĒā§āϰāϝāĻŧā§‹āϜāύ

āϤāĻžā§ŽāĻ•ā§āώāĻŖāĻŋāĻ• (āĻšā§āϝāĻžāĻŸā§‡āϰ āĻ…āĻ‚āĻļ)

āĻ…āĻ­āĻŋāϝ⧋āϜāύāϝ⧋āĻ—ā§āϝāϤāĻž

āĻ¸ā§āĻĨāĻŋāϰ āϝ⧁āĻ•ā§āϤāĻŋ

āĻ…āύāĻŽāύ⧀āϝāĻŧ āĻĢāĻžāĻ‚āĻļāύ

āĻŦ⧁āĻĻā§āϧāĻŋāĻŽāĻžāύ (āĻāϞāĻāϞāĻāĻŽ āĻĒāϰāĻŦāĻ°ā§āϤ⧀ āĻĒāĻĻāĻ•ā§āώ⧇āĻĒ āύāĻŋāĻ°ā§āϧāĻžāϰāĻŖ āĻ•āϰ⧇)

āĻĒā§āϰāϏāĻ™ā§āĻ— āϏāĻšā§‡āϤāύāϤāĻž

āϕ⧋āύāϟāĻŋāχ āύāϝāĻŧ

āϕ⧋āύāϟāĻŋāχ āύāϝāĻŧ

āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ (āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āωāĻĻā§āĻĻ⧇āĻļā§āϝ āϜāĻžāύ⧇)

āϕ⧇āύ āĻāϟāĻŋ āϗ⧁āϰ⧁āĻ¤ā§āĻŦāĻĒā§‚āĻ°ā§āĻŖ: multimedia_agent.py (ā§ĒāϟāĻŋ āϏāĻžāĻŦ-āĻāĻœā§‡āĻ¨ā§āϟ āϏāĻš āĻāĻ•āϟāĻŋ SequentialAgent: āφāĻĒāϞ⧋āĻĄ → āĻāĻ•ā§āϏāĻŸā§āĻ°ā§āϝāĻžāĻ•ā§āϟ → āϏāĻ‚āϰāĻ•ā§āώāĻŖ → āϏāĻžāϰāĻžāĻ‚āĻļ) āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇, āφāĻŽāϰāĻž āϜāϟāĻŋāϞ āĻ…āĻŦāĻ•āĻžāĻ āĻžāĻŽā§‹ āĻāĻŦāĻ‚ āĻ­āĻ™ā§āϗ⧁āϰ āĻ¸ā§āĻ•ā§āϰāĻŋāĻĒā§āϟāϗ⧁āϞāĻŋāϕ⧇ āĻŦ⧁āĻĻā§āϧāĻŋāĻŽāĻžāύ, āĻ•āĻĨā§‹āĻĒāĻ•āĻĨāύāĻŽā§‚āϞāĻ• āĻ…ā§āϝāĻžāĻĒā§āϞāĻŋāϕ⧇āĻļāύ āϞāϜāĻŋāĻ• āĻĻāĻŋāϝāĻŧ⧇ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰāĻŋāĨ¤

ā§§ā§Ļ. āĻŽāĻžāĻ˛ā§āϟāĻŋāĻŽā§‹āĻĄāĻžāϞ āĻĒāĻžāχāĻĒāϞāĻžāχāύ — āĻāĻœā§‡āĻ¨ā§āϟ āĻ¸ā§āϤāϰ

āĻāĻœā§‡āĻ¨ā§āϟ āĻ¸ā§āϤāϰāϟāĻŋ āĻŦ⧁āĻĻā§āϧāĻŋāĻŽāĻ¤ā§āϤāĻžāϕ⧇ āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ āĻ•āϰ⧇ — āĻāĻœā§‡āĻ¨ā§āϟāϰāĻž āĻ•āĻžāϜ āϏāĻŽā§āĻĒāĻ¨ā§āύ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āϏāϰāĻžā§āϜāĻžāĻŽ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇āĨ¤ āĻĒā§āϰāϤāĻŋāϟāĻŋ āĻāĻœā§‡āĻ¨ā§āĻŸā§‡āϰ āĻāĻ•āϟāĻŋ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻ­ā§‚āĻŽāĻŋāĻ•āĻž āĻĨāĻžāϕ⧇ āĻāĻŦāĻ‚ āĻĒā§āϰāϏāĻ™ā§āĻ—āϟāĻŋ āĻĒāϰāĻŦāĻ°ā§āϤ⧀āϟāĻŋāϤ⧇ āĻĒā§āϰ⧇āϰāĻŖ āĻ•āϰ⧇āĨ¤ āύ⧀āĻšā§‡ āĻŽāĻžāĻ˛ā§āϟāĻŋāĻāĻœā§‡āĻ¨ā§āϟ āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽā§‡āϰ āϜāĻ¨ā§āϝ āφāĻ°ā§āĻ•āĻŋāĻŸā§‡āĻ•āϚāĻžāϰ āĻĄāĻžāϝāĻŧāĻžāĻ—ā§āϰāĻžāĻŽ āĻĻ⧇āĻ“āϝāĻŧāĻž āĻšāϞāĨ¤

āĻāĻœā§‡āĻ¨ā§āϟ_āĻĄāĻžāϝāĻŧāĻžāĻ—ā§āϰāĻžāĻŽ

ā§§. āĻāĻœā§‡āĻ¨ā§āϟ āĻĢāĻžāχāϞāϟāĻŋ āϖ⧁āϞ⧁āύ

👉đŸ’ģ āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ⧇, āĻ•ā§āϞāĻžāωāĻĄ āĻļ⧇āϞ āĻāĻĄāĻŋāϟāϰ⧇ āĻĢāĻžāχāϞāϟāĻŋ āϖ⧁āϞ⧁āύ:

cloudshell edit ~/way-back-home/level_2/backend/agent/multimedia_agent.py

2. āφāĻĒāϞ⧋āĻĄ āĻāĻœā§‡āĻ¨ā§āĻŸā§‡āϰ āϏāĻ‚āĻœā§āĻžāĻž āĻĻāĻŋāύ

āĻāχ āĻāĻœā§‡āĻ¨ā§āϟ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āĻŦāĻžāĻ°ā§āϤāĻž āĻĨ⧇āϕ⧇ āĻāĻ•āϟāĻŋ āĻĢāĻžāχāϞ āĻĒāĻžāĻĨ āĻŦ⧇āϰ āĻ•āϰ⧇ āĻāĻŦāĻ‚ GCS-āĻ āφāĻĒāϞ⧋āĻĄ āĻ•āϰ⧇āĨ¤

multimedia_agent.py āĻĢāĻžāχāϞ⧇, # TODO: REPLACE_UPLOAD_AGENT āĻŽāĻ¨ā§āϤāĻŦā§āϝāϟāĻŋ āϖ⧁āρāϜ⧁āύāĨ¤

āĻāχ āĻĒ⧁āϰ⧋ āϞāĻžāχāύāϟāĻŋ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āϕ⧋āĻĄ āĻĻāĻŋāϝāĻŧ⧇ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ :

upload_agent = LlmAgent(
    name="UploadAgent",
    model="gemini-2.5-flash",
    instruction="""Extract the file path from the user's message and upload it.

Use `upload_media(file_path, survivor_id)` to upload the file.
The survivor_id is optional - include it if the user mentions a specific survivor (e.g., "survivor Sarah" -> "Sarah").
If the user provides a path like "/path/to/file", use that.

Return the upload result with gcs_uri and media_type.""",
    tools=[upload_media],
    output_key="upload_result"
)

ā§Š. āύāĻŋāĻˇā§āĻ•āĻžāĻļāύ āĻāĻœā§‡āĻ¨ā§āĻŸā§‡āϰ āϏāĻ‚āĻœā§āĻžāĻž āĻĻāĻžāĻ“

āĻāχ āĻāĻœā§‡āĻ¨ā§āϟ āφāĻĒāϞ⧋āĻĄ āĻ•āϰāĻž āĻŽāĻŋāĻĄāĻŋāϝāĻŧāĻž "āĻĻ⧇āϖ⧇" āĻāĻŦāĻ‚ āĻœā§‡āĻŽāĻŋāύāĻŋ āĻ­āĻŋāĻļāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āĻ¸ā§āĻŸā§āϰāĻžāĻ•āϚāĻžāĻ°ā§āĻĄ āĻĄā§‡āϟāĻž āĻŦ⧇āϰ āĻ•āϰ⧇āĨ¤

multimedia_agent.py āĻĢāĻžāχāϞ⧇, # TODO: REPLACE_EXTRACT_AGENT āĻŽāĻ¨ā§āϤāĻŦā§āϝāϟāĻŋ āϖ⧁āρāϜ⧁āύāĨ¤

āĻāχ āĻĒ⧁āϰ⧋ āϞāĻžāχāύāϟāĻŋ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āϕ⧋āĻĄ āĻĻāĻŋāϝāĻŧ⧇ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ :

extraction_agent = LlmAgent(
    name="ExtractionAgent", 
    model="gemini-2.5-flash",
    instruction="""Extract information from the uploaded media.

Previous step result: {upload_result}

Use `extract_from_media(gcs_uri, media_type, signed_url)` with the values from the upload result.
The gcs_uri is in upload_result['gcs_uri'], media_type in upload_result['media_type'], and signed_url in upload_result['signed_url'].

Return the extraction results including entities and relationships found.""",
    tools=[extract_from_media],
    output_key="extraction_result"
)

āϞāĻ•ā§āĻˇā§āϝ āĻ•āϰ⧁āύ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ instruction {upload_result} āωāĻ˛ā§āϞ⧇āĻ– āĻ•āϰ⧇ — ADK-āϤ⧇ āĻāĻœā§‡āĻ¨ā§āϟāĻĻ⧇āϰ āĻŽāĻ§ā§āϝ⧇ āĻāχāĻ­āĻžāĻŦ⧇ āĻ…āĻŦāĻ¸ā§āĻĨāĻž āĻĒā§āϰ⧇āϰāĻŖ āĻ•āϰāĻž āĻšāϝāĻŧ āĨ¤

ā§Ē. āĻ¸ā§āĻĒā§āϝāĻžāύāĻžāϰ āĻāĻœā§‡āĻ¨ā§āĻŸā§‡āϰ āϏāĻ‚āĻœā§āĻžāĻž āĻĻāĻžāĻ“

āĻāχ āĻāĻœā§‡āĻ¨ā§āϟāϟāĻŋ āĻāĻ•ā§āϏāĻŸā§āĻ°ā§āϝāĻžāĻ•ā§āϟ āĻ•āϰāĻž āϏāĻ¤ā§āϤāĻž āĻāĻŦāĻ‚ āϏāĻŽā§āĻĒāĻ°ā§āĻ•āϗ⧁āϞāĻŋāϕ⧇ āĻ—ā§āϰāĻžāĻĢ āĻĄāĻžāϟāĻžāĻŦ⧇āϏ⧇ āϏāĻ‚āϰāĻ•ā§āώāĻŖ āĻ•āϰ⧇āĨ¤

multimedia_agent.py āĻĢāĻžāχāϞ⧇, āĻŽāĻ¨ā§āϤāĻŦā§āϝāϟāĻŋ # TODO: REPLACE_SPANNER_AGENT āϖ⧁āρāϜ⧁āύāĨ¤

āĻāχ āĻĒ⧁āϰ⧋ āϞāĻžāχāύāϟāĻŋ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āϕ⧋āĻĄ āĻĻāĻŋāϝāĻŧ⧇ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ :

spanner_agent = LlmAgent(
    name="SpannerAgent",
    model="gemini-2.5-flash", 
    instruction="""Save the extracted information to the database.

Upload result: {upload_result}
Extraction result: {extraction_result}

Use `save_to_spanner(extraction_result, survivor_id)` to save to Spanner.
Pass the WHOLE `extraction_result` object/dict from the previous step.
Include survivor_id if it was provided in the upload step.

Return the save statistics.""",
    tools=[save_to_spanner],
    output_key="spanner_result"
)

āĻāχ āĻāĻœā§‡āĻ¨ā§āϟāϟāĻŋ āĻĒā§‚āĻ°ā§āĻŦāĻŦāĻ°ā§āϤ⧀ āωāĻ­āϝāĻŧ āϧāĻžāĻĒ ( upload_result āĻāĻŦāĻ‚ extraction_result ) āĻĨ⧇āϕ⧇ āĻĒā§āϰāϏāĻ™ā§āĻ— āĻ—ā§āϰāĻšāĻŖ āĻ•āϰ⧇āĨ¤

ā§Ģ. āϏāĻžāϰāĻžāĻ‚āĻļ āĻāĻœā§‡āĻ¨ā§āϟ āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ āĻ•āϰ⧁āύ

āĻāχ āĻāĻœā§‡āĻ¨ā§āϟāϟāĻŋ āĻĒā§‚āĻ°ā§āĻŦāĻŦāĻ°ā§āϤ⧀ āϏāĻŽāĻ¸ā§āϤ āĻĒāĻĻāĻ•ā§āώ⧇āĻĒ⧇āϰ āĻĢāϞāĻžāĻĢāϞāϗ⧁āϞāĻŋāϕ⧇ āĻāĻ•āϟāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀-āĻŦāĻžāĻ¨ā§āϧāĻŦ āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋāϝāĻŧāĻžāϝāĻŧ āϏāĻ‚āĻļā§āϞ⧇āώāĻŋāϤ āĻ•āϰ⧇āĨ¤

multimedia_agent.py āĻĢāĻžāχāϞ⧇, āĻŽāĻ¨ā§āϤāĻŦā§āϝ summary_instruction="" # TODO: REPLACE_SUMMARY_AGENT_PROMPT āĨ¤

āĻāχ āĻĒ⧁āϰ⧋ āϞāĻžāχāύāϟāĻŋ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āϕ⧋āĻĄ āĻĻāĻŋāϝāĻŧ⧇ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ :

USE_MEMORY_BANK = os.getenv("USE_MEMORY_BANK", "false").lower() == "true"
save_msg = "6. Mention that the data is also being synced to the memory bank." if USE_MEMORY_BANK else ""

summary_instruction = f"""Provide a user-friendly summary of the media processing.

Upload: {{upload_result}}
Extraction: {{extraction_result}}
Database: {{spanner_result}}

Summarize:
1. What file was processed (name and type)
2. Key information extracted (survivors, skills, needs, resources found) - list names and counts
3. Relationships identified
4. What was saved to the database (broadcast ID, number of entities)
5. Any issues encountered
{save_msg}

Be concise but informative."""

āĻāχ āĻāĻœā§‡āĻ¨ā§āĻŸā§‡āϰ āϕ⧋āύāĻ“ āϏāϰāĻžā§āϜāĻžāĻŽā§‡āϰ āĻĒā§āϰāϝāĻŧā§‹āϜāύ āύ⧇āχ - āĻāϟāĻŋ āϕ⧇āĻŦāϞ āĻ­āĻžāĻ— āĻ•āϰāĻž āĻĒā§āϰāϏāĻ™ā§āĻ—āϟāĻŋ āĻĒāĻĄāĻŧ⧇ āĻāĻŦāĻ‚ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āϜāĻ¨ā§āϝ āĻāĻ•āϟāĻŋ āĻĒāϰāĻŋāĻˇā§āĻ•āĻžāϰ āϏāĻžāϰāĻžāĻ‚āĻļ āϤ⧈āϰāĻŋ āĻ•āϰ⧇āĨ¤

🧠 āĻ¸ā§āĻĨāĻžāĻĒāĻ¤ā§āϝ⧇āϰ āϏāĻžāϰāĻžāĻ‚āĻļ

āĻ¸ā§āϤāϰ

āĻĢāĻžāχāϞ

āĻĻāĻžāϝāĻŧāĻŋāĻ¤ā§āĻŦ

āϟ⧁āϞāĻŋāĻ‚

extraction_tools.py + gcs_service.py

āĻ•āĻŋāĻ­āĻžāĻŦ⧇ — āφāĻĒāϞ⧋āĻĄ, āĻāĻ•ā§āϏāĻŸā§āĻ°ā§āϝāĻžāĻ•ā§āϟ, āϏāĻ‚āϰāĻ•ā§āώāĻŖ

āĻāĻœā§‡āĻ¨ā§āϟ

multimedia_agent.py

āϕ⧀ — āĻĒāĻžāχāĻĒāϞāĻžāχāύāϟāĻŋ āϏāĻžāϜāĻžāύ⧋

ā§§ā§§. āĻŽāĻžāĻ˛ā§āϟāĻŋāĻŽā§‹āĻĄāĻžāϞ āĻĄā§‡āϟāĻž āĻĒāĻžāχāĻĒāϞāĻžāχāύ — āĻ…āĻ°ā§āϕ⧇āĻ¸ā§āĻŸā§āϰ⧇āĻļāύ

āφāĻŽāĻžāĻĻ⧇āϰ āύāϤ⧁āύ āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽā§‡āϰ āĻŽā§‚āϞ āĻšāϞ⧋ backend/agent/multimedia_agent.py āϤ⧇ āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ MultimediaExtractionPipeline āĻĒāĻžāχāĻĒāϞāĻžāχāύāĨ¤ āĻāϟāĻŋ ADK (āĻāĻœā§‡āĻ¨ā§āϟ āĻĄā§‡āϭ⧇āϞāĻĒāĻŽā§‡āĻ¨ā§āϟ āĻ•āĻŋāϟ) āĻĨ⧇āϕ⧇ āϏāĻŋāϕ⧋āϝāĻŧ⧇āĻ¨ā§āϏāĻŋāϝāĻŧāĻžāϞ āĻāĻœā§‡āĻ¨ā§āϟ āĻĒā§āϝāĻžāϟāĻžāĻ°ā§āύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇āĨ¤

ā§§. āϕ⧇āύ āϏāĻŋāĻ•ā§‹ā§Ÿā§‡āύāĻļāĻŋ⧟āĻžāϞ?

āφāĻĒāϞ⧋āĻĄ āĻĒā§āϰāĻ•ā§āϰāĻŋāϝāĻŧāĻžāĻ•āϰāĻŖ āĻāĻ•āϟāĻŋ āϰ⧈āĻ–āĻŋāĻ• āύāĻŋāĻ°ā§āĻ­āϰāϤāĻž āĻļ⧃āĻ™ā§āĻ–āϞ:

  1. āĻĢāĻžāχāϞ (āφāĻĒāϞ⧋āĻĄ) āύāĻž āĻĒāĻžāĻ“āϝāĻŧāĻž āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āφāĻĒāύāĻŋ āĻĄā§‡āϟāĻž āĻŦ⧇āϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŦ⧇āύ āύāĻžāĨ¤
  2. āφāĻĒāύāĻŋ āĻĄā§‡āϟāĻž āĻāĻ•ā§āϏāĻŸā§āϰāĻžāĻ•ā§āϟ āύāĻž āĻ•āϰāĻž āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āϏāĻ‚āϰāĻ•ā§āώāĻŖ āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŦ⧇āύ āύāĻž (āĻāĻ•ā§āϏāĻŸā§āϰāĻžāĻ•āĻļāύ)āĨ¤
  3. āĻĢāϞāĻžāĻĢāϞ āύāĻž āĻĒāĻžāĻ“ā§ŸāĻž āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āϤ⧁āĻŽāĻŋ āϏāĻžāϰāϏāĻ‚āĻ•ā§āώ⧇āĻĒ āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŦ⧇ āύāĻž (āϏāĻ‚āϰāĻ•ā§āώāĻŖ āĻ•āϰ⧋)āĨ¤

āĻāϰ āϜāĻ¨ā§āϝ āĻāĻ•āϟāĻŋ SequentialAgent āωāĻĒāϝ⧁āĻ•ā§āϤāĨ¤ āĻāϟāĻŋ āĻāĻ•āϟāĻŋ āĻāĻœā§‡āĻ¨ā§āĻŸā§‡āϰ āφāωāϟāĻĒ⧁āϟāϕ⧇ āĻĒā§āϰāϏāĻ™ā§āĻ—/āχāύāĻĒ⧁āϟ āĻšāĻŋāϏ⧇āĻŦ⧇ āĻ…āĻ¨ā§āϝ āĻāĻœā§‡āĻ¨ā§āĻŸā§‡ āĻĒā§āϰ⧇āϰāĻŖ āĻ•āϰ⧇āĨ¤

2. āĻāĻœā§‡āĻ¨ā§āĻŸā§‡āϰ āϏāĻ‚āĻœā§āĻžāĻž

āϚāϞ⧁āύ āĻĻ⧇āĻ–āĻŋ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ multimedia_agent.py āĻāϰ āύ⧀āĻšā§‡ āĻĒāĻžāχāĻĒāϞāĻžāχāύāϟāĻŋ āĻāĻ•āĻ¤ā§āϰāĻŋāϤ āĻ•āϰāĻž āĻšāϝāĻŧ: 👉đŸ’ģ āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ⧇, āĻ•ā§āϞāĻžāωāĻĄ āĻļ⧇āϞ āĻāĻĄāĻŋāϟāϰ⧇ āĻĢāĻžāχāϞāϟāĻŋ āϖ⧁āϞ⧁āύ:

cloudshell edit ~/way-back-home/level_2/backend/agent/multimedia_agent.py

āĻāϟāĻŋ āĻĒā§‚āĻ°ā§āĻŦāĻŦāĻ°ā§āϤ⧀ āĻĻ⧁āϟāĻŋ āϧāĻžāĻĒ āĻĨ⧇āϕ⧇ āχāύāĻĒ⧁āϟ āĻ—ā§āϰāĻšāĻŖ āĻ•āϰ⧇āĨ¤ āĻŽāĻ¨ā§āϤāĻŦā§āϝāϟāĻŋ āϖ⧁āρāϜ⧁āύ # TODO: REPLACE_ORCHESTRATION āĨ¤ āĻāχ āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āϞāĻžāχāύāϟāĻŋ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āϕ⧋āĻĄ āĻĻāĻŋāϝāĻŧ⧇ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ :

    sub_agents=[upload_agent, extraction_agent, spanner_agent, summary_agent]

ā§Š. āϰ⧁āϟ āĻāĻœā§‡āĻ¨ā§āĻŸā§‡āϰ āϏāĻžāĻĨ⧇ āϏāĻ‚āϝ⧋āĻ— āĻ•āϰ⧁āύ

👉đŸ’ģ āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ⧇, āĻ•ā§āϞāĻžāωāĻĄ āĻļ⧇āϞ āĻāĻĄāĻŋāϟāϰ⧇ āĻĢāĻžāχāϞāϟāĻŋ āϖ⧁āϞ⧁āύ:

cloudshell edit ~/way-back-home/level_2/backend/agent/agent.py

āĻŽāĻ¨ā§āϤāĻŦā§āϝāϟāĻŋ āϏāύāĻžāĻ•ā§āϤ āĻ•āϰ⧁āύ # TODO: REPLACE_ADD_SUBAGENT āĨ¤ āĻāχ āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āϞāĻžāχāύāϟāĻŋ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ āϕ⧋āĻĄ āĻĻāĻŋāϝāĻŧ⧇ āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ :

    sub_agents=[multimedia_agent],

āĻāχ āĻāĻ•āĻ• āĻŦāĻ¸ā§āϤ⧁ āĻ•āĻžāĻ°ā§āϝāĻ•āϰāĻ­āĻžāĻŦ⧇ āϚāĻžāϰāϜāύ "āĻŦāĻŋāĻļ⧇āώāĻœā§āĻž" āϕ⧇ āĻāĻ•āϟāĻŋ āĻ•āϞāϝ⧋āĻ—ā§āϝ āϏāĻ¤ā§āϤāĻžāϝāĻŧ āĻāĻ•āĻ¤ā§āϰāĻŋāϤ āĻ•āϰ⧇āĨ¤

ā§Ē. āĻāĻœā§‡āĻ¨ā§āϟāĻĻ⧇āϰ āĻŽāĻ§ā§āϝ⧇ āϤāĻĨā§āϝ āĻĒā§āϰāĻŦāĻžāĻš

āĻĒā§āϰāϤāĻŋāϟāĻŋ āĻāĻœā§‡āĻ¨ā§āϟ āϤāĻžāϰ āφāωāϟāĻĒ⧁āϟ āĻāĻ•āϟāĻŋ āĻ­āĻžāĻ— āĻ•āϰāĻž āĻĒā§āϰāϏāĻ™ā§āϗ⧇ āϏāĻ‚āϰāĻ•ā§āώāĻŖ āĻ•āϰ⧇ āϝāĻž āĻĒāϰāĻŦāĻ°ā§āϤ⧀ āĻāĻœā§‡āĻ¨ā§āϟāϰāĻž āĻ…ā§āϝāĻžāĻ•ā§āϏ⧇āϏ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇:

āφāĻ°ā§āĻ•āĻŋāĻŸā§‡āĻ•āϚāĻžāϰ_āφāĻĒāϞ⧋āĻĄāĻŋāĻ‚

ā§Ģ. āĻ…ā§āϝāĻžāĻĒā§āϞāĻŋāϕ⧇āĻļāύ āϖ⧁āϞ⧁āύ (āĻ…ā§āϝāĻžāĻĒāϟāĻŋ āĻāĻ–āύāĻ“ āϚāĻžāϞ⧁ āĻĨāĻžāĻ•āϞ⧇ āĻāĻĄāĻŧāĻŋāϝāĻŧ⧇ āϝāĻžāύ)

👉đŸ’ģ āĻ…ā§āϝāĻžāĻĒ āĻļ⧁āϰ⧁ āĻ•āϰ⧁āύ:

cd ~/way-back-home/level_2/
./start_app.sh

👉 āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ āĻĨ⧇āϕ⧇ Local: http://localhost:5173/ āĻ āĻ•ā§āϞāĻŋāĻ• āĻ•āϰ⧁āύāĨ¤

ā§Ŧ. āĻĒāϰ⧀āĻ•ā§āώāĻžāĻŽā§‚āϞāĻ• āĻ›āĻŦāĻŋ āφāĻĒāϞ⧋āĻĄ

👉 āĻšā§āϝāĻžāϟ āχāĻ¨ā§āϟāĻžāϰāĻĢ⧇āϏ⧇, āĻāĻ–āĻžāύ āĻĨ⧇āϕ⧇ āϝ⧇āϕ⧋āύ⧋ āĻāĻ•āϟāĻŋ āĻ›āĻŦāĻŋ āĻŦ⧇āϛ⧇ āύāĻŋāύ āĻāĻŦāĻ‚ UI āϤ⧇ āφāĻĒāϞ⧋āĻĄ āĻ•āϰ⧁āύ:

āĻšā§āϝāĻžāϟ āχāĻ¨ā§āϟāĻžāϰāĻĢ⧇āϏ⧇, āĻāĻœā§‡āĻ¨ā§āϟāϕ⧇ āφāĻĒāύāĻžāϰ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻĒā§āϰ⧇āĻ•ā§āώāĻžāĻĒāϟ āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ āĻŦāϞ⧁āύ:

Here is the survivor note

āĻāĻŦāĻ‚ āϤāĻžāϰāĻĒāϰ āĻ›āĻŦāĻŋāϟāĻŋ āĻāĻ–āĻžāύ⧇ āϏāĻ‚āϝ⧁āĻ•ā§āϤ āĻ•āϰ⧁āύāĨ¤

āφāĻĒāϞ⧋āĻĄ_āχāύāĻĒ⧁āϟ

āφāĻĒāϞ⧋āĻĄ_āĻĢāϞāĻžāĻĢāϞ

👉đŸ’ģ āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ⧇, āĻĒāϰ⧀āĻ•ā§āώāĻž āĻļ⧇āώ āĻšāϞ⧇, āĻĒā§āϰāĻ•ā§āϰāĻŋāϝāĻŧāĻžāϟāĻŋ āĻļ⧇āώ āĻ•āϰāϤ⧇ "Ctrl+C" āϟāĻŋāĻĒ⧁āύāĨ¤

6. Verify Multimodal Uploading in GCS Bucket

gcs

  • Select your bucket and click into media .

āĻŽāĻŋāĻĄāĻŋāϝāĻŧāĻž

  • View your uploaded image here. uploaded_img

7. Verify Multimodal Uploading in Spanner (Optional)

Below is example output in UI for test_photo1 .

  • Open the Google Cloud Console Spanner .
  • Select your instance: Survivor Network
  • Select your database: graph-db
  • In the left sidebar, click Spanner Studio

👉 In Spanner Studio, query the new data:

SELECT 
  s.name AS Survivor,
  s.role AS Role,
  b.name AS Biome,
  r.name AS FoundResource,
  s.created_at
FROM Survivors s
LEFT JOIN SurvivorInBiome sib ON s.survivor_id = sib.survivor_id
LEFT JOIN Biomes b ON sib.biome_id = b.biome_id
LEFT JOIN SurvivorFoundResource sfr ON s.survivor_id = sfr.survivor_id
LEFT JOIN Resources r ON sfr.resource_id = r.resource_id
ORDER BY s.created_at DESC;

We can verify it by see the result below:

spanner_verify

12. Memory Bank with Agent Engine

1. How Memory Works

The system uses a dual-memory approach to handle both immediate context and long-term learning.

memory_bank

2. What Are Memory Topics?

Memory Topics define the categories of information the agent should remember across conversations. Think of them as filing cabinets for different types of user preferences.

Our 2 Topics:

  1. search_preferences : How the user likes to search
    • Do they prefer keyword or semantic search?
    • What skills/biomes do they search for often?
    • Example memory: "User prefers semantic search for medical skills"
  2. urgent_needs_context : What crises they're tracking
    • What resources are they monitoring?
    • Which survivors are they concerned about?
    • Example memory: "User is tracking medicine shortage in Northern Camp"

3. Setting Up Memory Topics

Custom memory topics define what the agent should remember. These are configured when deploying the Agent Engine.

👉đŸ’ģ In the terminal, open the file in the Cloud Shell Editor by running:

cloudshell edit ~/way-back-home/level_2/backend/deploy_agent.py

This opens ~/way-back-home/level_2/backend/deploy_agent.py in your editor.

We define structure MemoryTopic objects to guide the LLM on what information to extract and save.

👉In the file deploy_agent.py , replace the # TODO: SET_UP_TOPIC with the following:

# backend/deploy_agent.py

    custom_topics = [
        # Topic 1: Survivor Search Preferences
        MemoryTopic(
            custom_memory_topic=CustomMemoryTopic(
                label="search_preferences",
                description="""Extract the user's preferences for how they search for survivors. Include:
                - Preferred search methods (keyword, semantic, direct lookup)
                - Common filters used (biome, role, status)
                - Specific skills they value or frequently look for
                - Geographic areas of interest (e.g., "forest biome", "mountain outpost")
                
                Example: "User prefers semantic search for finding similar skills."
                Example: "User frequently checks for survivors in the Swamp Biome."
                """,
            )
        ),
        # Topic 2: Urgent Needs Context
        MemoryTopic(
            custom_memory_topic=CustomMemoryTopic(
                label="urgent_needs_context",
                description="""Track the user's focus on urgent needs and resource shortages. Include:
                - Specific resources they are monitoring (food, medicine, ammo)
                - Critical situations they are tracking
                - Survivors they are particularly concerned about
                
                Example: "User is monitoring the medicine shortage in the Northern Camp."
                Example: "User is looking for a doctor for the injured survivors."
                """,
            )
        )
    ]

4. Agent Integration

The agent code must be aware of the Memory Bank to save and retrieve information.

👉đŸ’ģ In the terminal, open the file in the Cloud Shell Editor by running:

cloudshell edit ~/way-back-home/level_2/backend/agent/agent.py

This opens ~/way-back-home/level_2/backend/agent/agent.py in your editor.

Agent Creation

When creating the agent, we pass the after_agent_callback to ensure sessions are saved to memory after interactions. The add_session_to_memory function runs asynchronously to avoid slowing down the chat response.

👉In the file agent.py , locate the comment # TODO: REPLACE_ADD_SESSION_MEMORY , Replace this whole line with the following code:

async def add_session_to_memory(
        callback_context: CallbackContext
) -> Optional[types.Content]:
    """Automatically save completed sessions to memory bank in the background"""
    if hasattr(callback_context, "_invocation_context"):
        invocation_context = callback_context._invocation_context
        if invocation_context.memory_service:
            # Use create_task to run this in the background without blocking the response
            asyncio.create_task(
                invocation_context.memory_service.add_session_to_memory(
                    invocation_context.session
                )
            )
            logger.info("Scheduled session save to memory bank in background")

Background Saving

👉In the file agent.py , locate the comment # TODO: REPLACE_ADD_MEMORY_BANK_TOOL , Replace this whole line with the following code:

if USE_MEMORY_BANK:
    agent_tools.append(PreloadMemoryTool())

👉In the file agent.py , locate the comment # TODO: REPLACE_ADD_CALLBACK , Replace this whole line with the following code:

    after_agent_callback=add_session_to_memory if USE_MEMORY_BANK else None

Set Up Vertex AI Session Service

👉đŸ’ģ In the terminal, open the file chat.py in the Cloud Shell Editor by running:

cloudshell edit ~/way-back-home/level_2/backend/api/routes/chat.py

👉In chat.py file, locate the comment # TODO: REPLACE_VERTEXAI_SERVICES , Replace this whole line with the following code:

    session_service = VertexAiSessionService(
        project=project_id,
        location=location,
        agent_engine_id=agent_engine_id
    )
    memory_service = VertexAiMemoryBankService(
        project=project_id,
        location=location,
        agent_engine_id=agent_engine_id
    )

4. Setup & Deployment

Before testing the memory features, you need to deploy the agent with the new memory topics and ensure your environment is configured correctly.

We have provided a convenience script to handle this process.

Running the Deployment Script

👉đŸ’ģ In the terminal, run the deployment script:

cd ~/way-back-home/level_2
./deploy_and_update_env.sh

This script performs the following actions:

  • Runs backend/deploy_agent.py to register the agent and memory topics with Vertex AI.
  • Captures the new Agent Engine ID .
  • Automatically updates your .env file with AGENT_ENGINE_ID .
  • Ensures USE_MEMORY_BANK=TRUE is set in your .env file.

[!IMPORTANT] If you make changes to custom_topics in deploy_agent.py , you must re-run this script to update the Agent Engine.

13. Verify Memory Bank with Multimodal Data

You can verify that the memory bank is working by teaching the agent a preference and checking if it persists across sessions.

1. Open the application (Skip this step if your application is already running)

Open the Application again by following the instruction below: If the previous terminal is still running, end it by pressing Ctrls+C .

👉đŸ’ģ Start App:

cd ~/way-back-home/level_2/
./start_app.sh

👉 Click Local: http://localhost:5173/ from the terminal.

2. Testing Memory Bank with Text

In the chat interface, tell the agent about your specific context:

"I'm planning a medical rescue mission in the mountains. I need survivors with first aid and climbing skills."

👉 Wait ~30 seconds for the memory to process in the background.

2. Start a New Session

Refresh the page to clear the current conversation history (short-term memory).

Ask a question that relies on the context you provided earlier:

"What kind of missions am I interested in?"

Expected Response :

"Based on your previous conversations, you're interested in:

  • Medical rescue missions
  • Mountain/high-altitude operations
  • Skills needed: first aid, climbing

Would you like me to find survivors matching these criteria?"

3. Test with Image Upload

Upload an image, and ask:

remember this

You can choose any of the photo here or your own and upload to the UI:

4. Verify in Vertex AI Agent Engine

Go to Google Cloud Console Agent Engine

  1. Make sure you select the project from top left project selector: project selector
  2. Verify the agent engine you just deployed from previous command use_memory_bank.sh : agent engine Click into the agent engine you just created.
  3. Click the Memories Tab in this deployed agent, you can view all the memory here. view memory

👉đŸ’ģ When you finish testing, in you terminal, click "Ctrl + C" to end the process.

🎉 Congratulations! You just attached the memory bank to your agent!

14. Deploy to Cloud Run

1. Run the Deployment Script

👉đŸ’ģ Run the deployment script:

cd ~/way-back-home/level_2
./deploy_cloud_run.sh

After it successfully deployed, you will have the url, this is deployed url for you! āĻŽā§‹āϤāĻžāϝāĻŧ⧇āύ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇

👉đŸ’ģ Before you grab the url, grant the permission by running:

source .env && gcloud run services add-iam-policy-binding survivor-frontend --region $REGION --member=allUsers --role=roles/run.invoker && gcloud run services add-iam-policy-binding survivor-backend --region $REGION --member=allUsers --role=roles/run.invoker

Go to the deployed url, and you will see you application live there!

2. Understanding the Build Pipeline

The cloudbuild.yaml file defines the following sequential steps:

  1. Backend Build : Builds the Docker image from backend/Dockerfile .
  2. Backend Deploy : Deploys the backend container to Cloud Run.
  3. Capture URL : Gets the new Backend URL.
  4. Frontend Build :
    • Installs dependencies.
    • Builds the React app, injecting VITE_API_URL= .
  5. Frontend Image : Builds the Docker image from frontend/Dockerfile (packaging the static assets).
  6. Frontend Deploy : Deploys the frontend container.

3. Verify Deployment

Once the build completes (check the logs link provided by the script), you can verify:

  1. Go to the Cloud Run Console .
  2. Find the survivor-frontend service.
  3. Click the URL to open the application.
  4. Perform a search query to ensure the frontend can talk to the backend.

4. (!ONLY FOR WORKSHOP ATTENDEE) Update your location

👉đŸ’ģ Run the completion script:

cd ~/way-back-home/level_2
./set_level_2.sh

Now open waybackhome.dev , and you will see your location has updated. Congratulations on finishing level 2!

final result

(OPTIONAL) 5. Manual Deployment

If you prefer to run the commands manually or understand the process better, here is how to use cloudbuild.yaml directly.

Writing cloudbuild.yaml

A cloudbuild.yaml file tells Google Cloud Build what steps to execute.

  • steps : A list of sequential actions. Each step runs in a container (eg, docker , gcloud , node , bash ).
  • substitutions : Variables that can be passed at build time (eg, $_REGION ).
  • workspace : A shared directory where steps can share files (like how we share backend_url.txt ).

Running the Deployment

To deploy manually without the script, use the gcloud builds submit command. You MUST pass the required substitution variables.

# Load your env vars first or replace these values manually
export PROJECT_ID=your-project-id
export REGION=us-central1

gcloud builds submit --config cloudbuild.yaml \
    --project "$PROJECT_ID" \
    --substitutions _REGION="us-central1",_GOOGLE_API_KEY="",_AGENT_ENGINE_ID="your-agent-id",_USE_MEMORY_BANK="TRUE",_GOOGLE_GENAI_USE_VERTEXAI="TRUE"

15. Conclusion

1. What You've Built

✅ Graph Database : Spanner with nodes (survivors, skills) and edges (relationships)
✅ AI Search : Keyword, semantic, and hybrid search with embeddings
✅ Multimodal Pipeline : Extract entities from images/video with Gemini
✅ Multi-Agent System : Coordinated workflow with ADK
✅ Memory Bank : Long-term personalization with Vertex AI
✅ Production Deployment : Cloud Run + Agent Engine

2. Architecture Summary

architecture_fullstack

3. Key Learnings

  1. Graph RAG : Combines graph database structure with semantic embeddings for intelligent search
  2. Multi-Agent Patterns : Sequential pipelines for complex, multi-step workflows
  3. Multimodal AI : Extract structured data from unstructured media (images/video)
  4. Stateful Agents : Memory Bank enables personalization across sessions

4. Workshop Content

5. Resources