मुख्य सामग्री पर जाएँ

Gemini 2.5 Computer Use गाइड व डेमो प्रोजेक्ट: जॉब सर्च एजेंट बनाएं

जानें कि Gemini 2.5 Computer Use का उपयोग करके AI-संचालित जॉब सर्च एजेंट कैसे बनाएं। यह हैंड्स-ऑन ट्यूटोरियल Playwright और Streamlit के साथ ब्राउज़र ऑटोमेशन सिखाता है, किसी API की आवश्यकता नहीं।
· 8 मि॰ पढ़ें

AI के साथ खोजें

हाल ही में Gemini टीम ने पेश किया Gemini 2.5 Computer Use, एक विशेष मॉडल जो लाइव स्क्रीन देख सकता है और उस पर मानव ऑपरेटर की तरह क्लिक, टाइप, स्क्रोल और वेब नेविगेट कर सकता है।

इस गाइड में, हम अमूर्त बेंचमार्क्स छोड़कर कुछ व्यावहारिक बनाएंगे—एक Streamlit ऐप जो Computer Use के जरिए असली ब्राउज़र को कंट्रोल करता है, Google पर जॉब पोस्टिंग्स खोजता है, फ़िल्टर लगाता है, और बिना किसी थर्ड-पार्टी सर्च API के नतीजों को CSV में एक्सपोर्ट करता है।

इस ट्यूटोरियल में, आप सीखेंगे कि:

  • Gemini 2.5 Computer Use लूप को कैसे कॉन्फ़िगर करें
  • Playwright (Chromium) के साथ एजेंट कैसे चलाएं, allowlist और जोखिमपूर्ण चरणों के लिए वैकल्पिक मानव पुष्टि का उपयोग करते हुए।
  • हर टर्न के बाद लाइव एक्शन लॉग और स्क्रीनशॉट्स के साथ Streamlit UI कैसे बनाएं।
  • ऑर्गेनिक नतीजे कैसे स्क्रैप करें और CSV डाउनलोड करें।

अंत तक, आपके पास एक जॉब सर्च एजेंट होगा जो आपके लिए सटीक जॉब पोस्टिंग्स क्यूरेट करेगा।

डेमो इमेज

अगर आप Gemini 2.5 के बारे में और जानना चाहते हैं, तो हमारा Gemini 2.5 Pro ट्यूटोरियल देखें, जिसमें फीचर्स, टेस्ट, एक्सेस, बेंचमार्क्स और अधिक शामिल हैं। आपको Gemini 3 Pro—Google का नवीनतम मॉडल—के बारे में भी सीखना चाहिए।

Gemini 2.5 Computer Use क्या है?

Gemini 2.5 Computer Use, Gemini API में एक विशेष (प्रिव्यू) मॉडल और टूल है जो आपको ब्राउज़र-कंट्रोल एजेंट बनाने देता है। साइट-विशिष्ट APIs कॉल करने के बजाय, मॉडल स्क्रीनशॉट्स से काम करता है। यह पेज पर क्या है उसे देख सकता है और फिर navigate, click_at, scroll_document जैसी UI क्रियाएं जारी कर कार्य कर सकता है।  

क्लाइंट कोड इन प्रस्तावित क्रियाओं को प्राप्त करता है, उन्हें निष्पादित करता है, और मॉडल को अगला कदम तय करने के लिए एक नया स्क्रीनशॉट और URL का संयोजन वापस भेजता है। 

Computer Use लूप कैसे काम करता है

एजेंट लूप

स्रोत: Gemini Documentation

ऊपर दिया गया एजेंट लूप एंड-टू-एंड इस प्रकार काम करता है:

  1. अनुरोध भेजें: शुरुआत में एक अनुरोध भेजें जिसमें Computer Use टूल, एक लक्ष्य प्रॉम्प्ट, और यूज़र इंटरफ़ेस का प्रारंभिक स्क्रीनशॉट शामिल हो।
  2. प्रतिक्रिया प्राप्त करें: मॉडल नैरेशन और एक या अधिक फ़ंक्शन कॉल्स (जैसे click_at या type_text_at) और एक सेफ़्टी निर्णय के साथ प्रतिक्रिया देता है।
  3. निष्पादन: फिर प्रस्तावित क्रियाओं को निष्पादित करें, यानी अगर क्रिया नियमित/अनुमत चिह्नित है तो हम उसे चलाते हैं; अगर उसे पुष्टि की आवश्यकता है, तो हम उपयोगकर्ता को प्रॉम्प्ट करते हैं और केवल स्पष्ट स्वीकृति पर आगे बढ़ते हैं।
  4. स्टेट लौटाएं: क्रिया के बाद, हम एक FunctionResponse भेजकर मॉडल को स्टेट लौटाते हैं जिसमें नया स्क्रीनशॉट और मौजूदा URL होता है।
  5. दोहराएं: हम यह see–decide–act–observe चक्र तब तक दोहराते हैं जब तक कार्य पूरा न हो जाए, कोई त्रुटि न हो, या उपयोगकर्ता/मॉडल रुकने का निर्णय न ले।

Gemini 2.5 Computer Use और Streamlit के साथ जॉब्स सर्च एजेंट बनाएं

इस खंड में, हम एक Streamlit-संचालित जॉब्स सर्च एजेंट बनाएंगे जो Gemini 2.5 Computer Use और Playwright का उपयोग कर असली ब्राउज़र चलाता है, फिर नतीजों को CSV में एक्सपोर्ट करता है।

यह ऐसे काम करता है:

  • उपयोगकर्ता Streamlit साइडबार में जॉब कीवर्ड्स की सूची दर्ज करता है।
  • एजेंट Gemini को Google खोलने, प्रत्येक क्वेरी चलाने और टाइम फ़िल्टर लगाने का निर्देश देता है।
  • एजेंट ऑर्गेनिक नतीजों के पहले पेज पर रुकता है और हर टर्न पर एक्शन लॉग्स के साथ लाइव स्क्रीनशॉट दिखाता है।
  • इसके बाद यह पेज-1 से शीर्षक, लिंक और स्निपेट स्क्रैप करता है और उन्हें सभी कीवर्ड्स के पार इकट्ठा करता है।
  • अंत में, यह नतीजों की तालिका रेंडर करता है और साथ ही एक डाउनलोड करने योग्य CSV फ़ाइल देता है।

पर्दे के पीछे, ऐप सुरक्षित नेविगेशन के लिए allowlisted डोमेन लागू करता है, जोखिमपूर्ण चरणों के लिए वैकल्पिक मानव पुष्टि को सपोर्ट करता है, और आसान डीबगिंग के लिए Computer Use लूप का उपयोग करता है।

शुरू करने से पहले: 

कुछ ज़िम्मेदार उपयोग मामले और साइट नीतियां:

  • ऑटोमेशन का दायरा: यह डेमो केवल Google Search (allowlisted) को ऑटोमेट करता है और पेज-1 के ऑर्गेनिक नतीजे स्क्रैप करता है।
  • साइट की शर्तों का सम्मान करें: उन साइटों को ऑटोमेट न करें जिनकी सेवा शर्तें प्रतिबंधात्मक हैं, और कभी भी CAPTCHA को बायपास करने का प्रयास न करें। यदि CAPTCHA आता है, तो उसे मैन्युअल रूप से पूरा करें, फिर मॉडल को जारी रखने दें।
  • ह्यूमन-इन-द-लूप सेफ़्टी: यदि Gemini कोई जोखिमपूर्ण क्रिया प्रस्तावित करता है (जैसे CAPTCHA इंटरैक्शन, खरीद), तो ऐप डिफ़ॉल्ट रूप से रुक जाता है। यह तभी आगे बढ़ेगा जब आप स्पष्ट रूप से ऑटो-कन्फर्म सक्षम करेंगे।

स्टेप 1: पूर्वापेक्षाएँ

  • Python 3.10+
  • एक Gemini API कुंजी Google AI Studio
  • macOS / Windows / Linux जिसमें Playwright Chromium इंस्टॉल हो

स्टेप 1.1: इम्पोर्ट्स 

पहले सुनिश्चित करें कि आपके पास निम्न इम्पोर्ट्स इंस्टॉल हैं:

python -m venv .venv && source .venv/bin/activate
pip install streamlit google-genai playwright python-dotenv
playwright install chromium

ऊपर दिए गए कमांड एक वर्चुअल एन्वायरनमेंट सेट करते हैं और ऐप बनाने के लिए सभी कोर डिपेंडेंसीज़ इंस्टॉल करते हैं, यानी  Streamlit UI के लिए, google-genai Gemini API कॉल करने के लिए, Playwright ब्राउज़र ऑटोमेशन के लिए, और python-dotenv एन्वायरनमेंट वेरिएबल्स लोड करने के लिए, तथा Chromium Playwright के लिए।

स्टेप 1.2: Gemini API कुंजी सेट करना 

अब जब डिपेंडेंसीज़ इंस्टॉल हो गई हैं, अगला कदम AI Studio से Gemini API Key सेट करना है। 

  • AI Studio में लॉग इन करें और “Get API Key” खोजें
  • Create API key पर क्लिक करें
  • मौजूदा Google Cloud प्रोजेक्ट चुनें या बिलिंग सक्षम करके नया बनाएं।

API कुंजी बनाएं

  • बस link a billing account पर क्लिक करें और सत्यापन के लिए अपने कार्ड विवरण जोड़ें।
  • अंत में, AI Studio से API Key कॉपी करें और सुरक्षित रखें।

अब अपने प्रोजेक्ट फ़ोल्डर में एक .env फ़ाइल बनाएं और अपनी API Key वहाँ जोड़ें:

GOOGLE_API_KEY=YOUR_REAL_KEY
ALLOWED_HOSTS=google.com

python-dotenv पैकेज रनटाइम पर GOOGLE_API_KEY लोड कर देगा ताकि ऐप Gemini 2.5 Computer Use मॉडल को कॉल कर सके।

स्टेप 2: मॉडल कॉन्फ़िगरेशन सेट करना

अब रनटाइम की तैयारी करें, जिसमें इम्पोर्ट्स, कॉन्स्टेंट्स, मॉडल ID, और ऑथेंटिकेशन शामिल हैं। इससे सुनिश्चित होता है कि ऐप Gemini से बात करता है और नेविगेशन allowlisted डोमेन के भीतर सुरक्षित रहता है।

import os, io, time, csv, base64, urllib.parse
from typing import List, Dict, Tuple
import streamlit as st
from dotenv import load_dotenv
from playwright.sync_api import sync_playwright
from google import genai
from google.genai import types
from google.genai.types import Content, Part
W, H = 1440, 900
MODEL = "gemini-2.5-computer-use-preview-10-2025"  
load_dotenv()
API_KEY = os.getenv("GOOGLE_API_KEY")
if not API_KEY:
    st.stop()
ALLOWED_HOSTS = {h.strip().lower() for h in os.getenv("ALLOWED_HOSTS", "google.com").split(",") if h.strip()}
client = genai.Client(api_key=API_KEY)

हम Streamlit, Playwright, google-genai और छोटी यूटिलिटीज़ (dotenv, os, io, csv, time, urllib) जैसे कोर लाइब्रेरीज़ इम्पोर्ट करके शुरू करते हैं ताकि कॉन्फ़िगरेशन और I/O हो सके।

फिक्स्ड व्यूपोर्ट (W, H = 1440 × 900) Computer Use के लिए स्क्रीनशॉट्स और कोऑर्डिनेट मैपिंग को सुसंगत रखता है, और प्रिव्यू मॉडल gemini-2.5-computer-use-preview-10-2025 सेट है। 

API कुंजी load_dotenv() और os.getenv("GOOGLE_API_KEY") से लोड होती है। नेविगेशन सुरक्षा के लिए allowlist (डिफ़ॉल्ट google.com) से सेट किया गया है। 

अंत में, genai.Client(api_key=API_KEY) Gemini SDK को इनिशियलाइज़ करता है ताकि ऐप एजेंट लूप चला सके और Streamlit में नतीजे रेंडर कर सके।

स्टेप 3: हेल्पर फ़ंक्शंस बनाना

ऐप के मूल भाग पर जाने से पहले, हमें कुछ हेल्पर फ़ंक्शंस सेट करने होंगे। ये सुरक्षा जांच, कोऑर्डिनेट कन्वर्ज़न, Gemini के फ़ंक्शन कॉल्स के लिए एक्शंस निष्पादित करना, SERP स्क्रैपिंग, और नतीजों को CSV में एक्सपोर्ट करने में मदद करते हैं। 

स्टेप 3.1: सेफ़्टी और एक्शन निष्पादन

हम सुरक्षित ब्राउज़र कंट्रोल के लिए एक बैकएंड हेल्पर जोड़कर शुरू करते हैं। इसमें नेविगेशन को सीमित करने के लिए डोमेन allowlist चेक फ़ंक्शन, मॉडल के 0–999 ग्रिड को फिक्स्ड व्यूपोर्ट पर मैप करने के लिए कोऑर्डिनेट कन्वर्टर, और Computer Use फ़ंक्शन कॉल्स की व्याख्या कर उन्हें Playwright के जरिए निष्पादित करने के लिए एक्शन डिस्पैचर फ़ंक्शन शामिल है।

def host_allowed(url: str) -> bool:
    try:
        netloc = urllib.parse.urlparse(url).netloc.lower()
        return any(netloc.endswith(allowed) for allowed in ALLOWED_HOSTS)
    except Exception:
        return False
def denorm(v: int, size: int) -> int:
    return int(v/1000*size)
def exec_calls(candidate, page, viewport, *, approve_all=False) -> List[Tuple[str, Dict]]:
    W, H = viewport
    results = []
    for part in candidate.content.parts:
        fc = getattr(part, "function_call", None)
        if not fc:
            continue
        name, args = fc.name, (fc.args or {})
        sd = args.get("safety_decision")
        if sd and sd.get("decision") == "require_confirmation":
            reason = sd.get("explanation", "Model flagged a risky action.")
            log_box.warning(f"[SAFETY requires confirmation] {reason}")
            if not approve_all:
                st.stop()
            results.append((name, {"safety_acknowledgement": "true"}))
        if name == "navigate":
            target = args.get("url", "")
            if target and not host_allowed(target):
                log_box.error(f"[BLOCKED] Non-allowlisted host: {target}")
                results.append((name, {"error": "blocked_by_allowlist"}))
                continue
        try:
            if name == "open_web_browser":
                pass
            elif name == "navigate":
                page.goto(args["url"], timeout=30000)
            elif name == "search":
                page.goto("https://www.google.com", timeout=30000)
            elif name == "click_at":
                page.mouse.click(denorm(args["x"], W), denorm(args["y"], H))
            elif name == "hover_at":
                page.mouse.move(denorm(args["x"], W), denorm(args["y"], H))
            elif name == "type_text_at":
                x, y = denorm(args["x"], W), denorm(args["y"], H)
                page.mouse.click(x, y)
                if args.get("clear_before_typing", True):
                    page.keyboard.press("Meta+A"); page.keyboard.press("Backspace")
                page.keyboard.type(args["text"])
                if args.get("press_enter", True):
                    page.keyboard.press("Enter")
            elif name == "scroll_document":
                page.mouse.wheel(0, 800 if args["direction"] == "down" else -800)
            elif name == "key_combination":
                page.keyboard.press(args["keys"])
            page.wait_for_load_state("networkidle", timeout=10000)
            results.append((name, {}))
            time.sleep(0.6)
        except Exception as e:
            results.append((name, {"error": str(e)}))
    return results

आइए देखें कि प्रत्येक फ़ंक्शन पाइपलाइन में कैसे फिट बैठता है:

  • host_allowed() फ़ंक्शन: यह लक्ष्य URL को पार्स करता है, होस्टनेम को लोअरकेस में सामान्यीकृत करता है, और जांचता है कि क्या यह .env फ़ाइल में सूचीबद्ध ALLOWED_HOSTS के किसी डोमेन पर समाप्त होता है। 
  • denorm() फ़ंक्शन: यह यूटिलिटी पॉइंटर कोऑर्डिनेट्स को मौजूदा व्यूपोर्ट के वास्तविक पिक्सल यूनिट्स में बदलती है। सटीक क्लिक्स, होवर्स और टाइपिंग के लिए यह अहम है, खासकर जब आप स्क्रीन साइज बदलते हैं या हेडलेस मोड में चलाते हैं।
  • exec_calls() फ़ंक्शन: अंततः, यह एक्सीक्यूट कॉल्स फ़ंक्शन मॉडल की प्रतिक्रिया में फ़ंक्शन कॉल्स को स्कैन करता है और प्रत्येक को Playwright को डिस्पैच करता है। यह non-allowlisted होस्ट्स पर नेविगेट कॉल्स को ब्लॉक करता है, समर्थित क्रियाओं को निष्पादित करता है, पेज को स्थिर करने के लिए नेटवर्क आइडल का इंतज़ार करता है, और प्रति-एक्शन आउटकम (त्रुटियों सहित) दर्ज करता है। इन नतीजों का उपयोग अगले चरण में FunctionResponses बनाने के लिए किया जाता है।

मिलकर, ये फ़ंक्शंस सीमाएं लागू करते हैं, पॉइंटर गणना सटीक रखते हैं, और सूक्ष्म स्तर के नतीजे लॉग करते हैं।

स्टेप 3.2: पोस्ट-एक्शन फ़ीडबैक और डाटा कैप्चर

क्रियाएं निष्पादित करने के बाद, एजेंट को अगला कदम तय करने और उपयोगी आउटपुट लौटाने के लिए फ़ीडबैक चाहिए। यह चरण तीन हेल्पर फ़ंक्शंस प्रदान करता है:

def fr_from(page, results):
    shot = page.screenshot(type="png")
    url = page.url
    frs = []
    for name, result in results:
        frs.append(types.FunctionResponse(
            name=name,
            response={"url": url, **result},
            parts=[types.FunctionResponsePart(
                inline_data=types.FunctionResponseBlob(mime_type="image/png", data=shot)
            )]
        ))
    return frs, shot
def scrape_google_serp(page, max_items=10):
    items = []
    anchors = page.locator('div#search a:has(h3)')
    count = min(anchors.count(), max_items)
    for i in range(count):
        a = anchors.nth(i)
        title = a.locator('h3').inner_text()
        link = a.get_attribute('href')
        snippet = ""
        snips = page.locator('div#search .VwiC3b')
        if snips.count() > i:
            snippet = snips.nth(i).inner_text()
        items.append({"title": title, "link": link, "snippet": snippet})
    return items
def to_csv_download(rows: List[Dict], name="results.csv"):
    if not rows:
        return None
    out = io.StringIO()
    writer = csv.DictWriter(out, fieldnames=["keyword", "title", "link", "snippet"])
    writer.writeheader(); writer.writerows(rows)
    b = out.getvalue().encode("utf-8")
    href = f"data:text/csv;base64,{base64.b64encode(b).decode()}"
    st.download_button("Download CSV", data=b, file_name=name, mime="text/csv")

आइए देखें कि प्रत्येक पोस्ट-एक्शन हेल्पर फ़ंक्शन कैसे काम करता है:

  • fr_from() फ़ंक्शन: यह नया PNG स्क्रीनशॉट और मौजूदा URL कैप्चर करता है, फिर हर निष्पादित क्रिया के लिए FunctionResponse बनाता है। यह अगले इंफ़रेंस टर्न के लिए विज़ुअल संदर्भ एम्बेड करता है और जो हुआ उसका ऑडिटेबल ट्रेल संरक्षित करता है।
  • scrape_google_serp() फ़ंक्शन: इसके बाद हम Google के पहले नतीजों के पेज से शीर्षक, लिंक और स्निपेट निकालते हैं, जहाँ a:has(h3) जैसे रेज़िलिएंट सेलेक्टर्स टाइटल/लिंक के लिए और .VwiC3b स्निपेट्स के लिए उपयोग होते हैं। स्क्रैपर max_items पर नतीजों को सीमित करता है और विश्लेषण या एक्सपोर्ट के लिए साफ़, संरचित पंक्तियाँ लौटाता है।
  • to_csv_download() फ़ंक्शन: यह फ़ंक्शन सुसंगत हेडर्स के साथ इन-मेमाेरी CSV बनाता है और उसे Streamlit के download_button() फ़ंक्शन के जरिए उपलब्ध कराता है।

अब जब हमारे पास सभी हेल्पर फ़ंक्शंस हैं, अगला कदम उनके चारों ओर एक Streamlit एप्लिकेशन बनाना है।

स्टेप 4: Streamlit एप्लिकेशन बनाना

यह चरण Streamlit UI को Computer Use एजेंट लूप से जोड़ता है। यह इंटरफ़ेस रेंडर करता है, उपयोगकर्ता-एजेंट इंटरैक्शन को मैनेज करता है, और सुनिश्चित करता है कि आउटपुट उनकी जरूरतों से मेल खाए।

st.set_page_config(page_title="Jobs Search with Gemini Computer Use", layout="wide")
st.title("Jobs Search with Gemini 2.5 Computer Use")
with st.sidebar:
    st.markdown("**Search inputs**")
    default_kw = "data scientist remote\nml engineer \ngenai research india"
    kw_text = st.text_area("Job keywords", value=default_kw, height=120)
    query_mode = st.selectbox("Query style", ["<kw> jobs", 'site:linkedin.com/jobs "<kw>"'], index=0)
    use_past_week = st.checkbox('Ask agent to set "Past week" filter', value=True)
    turns = st.slider("Max agent turns per keyword", 3, 12, 6)
    auto_confirm = st.checkbox("Auto-approve risky actions", value=False, help="If model requests confirmation (e.g., CAPTCHA), auto-approve instead of pausing.")
    run_btn = st.button("Run search")
log_col, shot_col = st.columns([0.45, 0.55])
log_box = log_col.container(height=520)
shot_box = shot_col.container(height=520)
table_box = st.container()
if run_btn:
    keywords = [k.strip() for k in kw_text.splitlines() if k.strip()]
    all_rows = []
    log_box.write("Initializing browser...")
    pw = sync_playwright().start()
    browser = pw.chromium.launch(headless=False)
    ctx = browser.new_context(viewport={"width": W, "height": H})
    page = ctx.new_page()
    try:
        for kw in keywords:
            log_box.subheader(f"▶ {kw}")
            page.goto("https://www.google.com", timeout=30000)
            initial_shot = page.screenshot(type="png")
            base_query = f'{kw} jobs' if query_mode == "<kw> jobs" else f'site:linkedin.com/jobs "{kw}"'
            goal = (
                f'Search Google for "{base_query}". '
                f'{"Open Tools and set time filter to Past week. " if use_past_week else ""}'
                'Stop when first-page results are fully visible; do NOT open the Jobs panel.'
            )
            contents = [Content(role="user", parts=[Part(text=goal), Part.from_bytes(data=initial_shot, mime_type="image/png")])]
            cfg = types.GenerateContentConfig(
                tools=[types.Tool(computer_use=types.ComputerUse(
                    environment=types.Environment.ENVIRONMENT_BROWSER
                ))]
            )
            for turn in range(turns):
                log_box.caption(f"Turn {turn+1}: thinking…")
                resp = client.models.generate_content(model=MODEL, contents=contents, config=cfg)
                cand = resp.candidates[0]
                contents.append(cand.content)
                narr = " ".join([p.text for p in cand.content.parts if getattr(p, "text", None)])
                if narr:
                    log_box.info(narr[:400])
                fcs = [p.function_call for p in cand.content.parts if getattr(p, "function_call", None)]
                if not fcs:
                    log_box.success("Agent stopped proposing actions.")
                    break
                for fc in fcs:
                    log_box.write(f"→ {fc.name} {fc.args or {}}")
                results = exec_calls(cand, page, (W, H), approve_all=auto_confirm)
                frs, shot = fr_from(page, results)
                contents.append(Content(role="user", parts=[Part(function_response=fr) for fr in frs]))
                shot_box.image(shot, caption=page.url, width='stretch')
            rows = scrape_google_serp(page)
            for r in rows:
                r["keyword"] = kw
            all_rows.extend(rows)
            log_box.success(f"{kw}: collected {len(rows)} results")
        if all_rows:
            table_box.dataframe(all_rows, width='stretch')
            to_csv_download(all_rows, name="jobs_google_results.csv")
        else:
            st.warning("No rows collected. Try fewer keywords or fewer turns.")
    finally:
        browser.close()
        pw.stop()

आइए इस पाइपलाइन को विस्तार से समझें:

  • ऐप चौड़े लेआउट के साथ पेज कॉन्फ़िगर करके और स्पष्ट शीर्षक सेट करके शुरू होता है ताकि उपयोगकर्ता तुरंत समझ जाएँ कि टूल क्या करता है। 
  • साइडबार में, उपयोगकर्ता जॉब कीवर्ड्स देते हैं, क्वेरी स्टाइल चुनते हैं, टाइम फ़िल्टर, प्रति कीवर्ड एजेंट के अधिकतम टर्न्स तय करते हैं, और जोखिमपूर्ण क्रियाओं के लिए ऑटो-कन्फर्म सक्षम/अक्षम करते हैं। फिर Run search बटन वर्कफ़्लो ट्रिगर करता है।
  • मुख्य क्षेत्र दो कॉलम में बँटा है—बाएँ “लॉग” कंटेनर जो पाठ्य अपडेट स्ट्रीम करता है और दाएँ “स्क्रीनशॉट” कंटेनर जो हर टर्न से लाइव इमेज दिखाता है। इनके नीचे अंतिम नतीजों की तालिका के लिए अलग कंटेनर है।
  • जब उपयोगकर्ता Run search क्लिक करते हैं, इंटरफ़ेस लॉग पैनल में प्रगति संदेश लिखता है, नए इमेज उपलब्ध होते ही स्क्रीनशॉट पैनल अपडेट करता है, और सभी कीवर्ड्स प्रोसेस होने के बाद एग्रीगेटेड नतीजों को डेटा फ़्रेम के रूप में रेंडर करता है। 

इस ऐप को चलाने के लिए, अपने टर्मिनल में निम्न bash कमांड चलाएँ:

python -m streamlit run app.py

टिप: “ModuleNotFoundError” समस्याओं से बचने के लिए हमेशा Streamlit को अपने venv से लॉन्च करें।

निष्कर्ष

इस ट्यूटोरियल में आपने देखा कि Gemini 2.5 Computer Use का उपयोग करके ब्राउज़र को नियंत्रित करने, फ़िल्टर लगाने, और Streamlit UI के माध्यम से नतीजे एक्सपोर्ट करने वाला एक विज़ुअल जॉब्स-सर्च एजेंट कैसे बनाया जाए। 

यहाँ से, आप वर्कफ़्लो को पेजिनेशन जोड़कर और पेजों तक बढ़ाकर, प्रकाशन तिथियाँ, लोकेशन और कंपनी नामों के साथ स्क्रैपर क्षमताओं का विस्तार करके, या किसी सैंडबॉक्स जॉब बोर्ड को allowlist करके विस्तृत कर सकते हैं। 

यदि आप कंप्यूटर यूज़ और एजेंटिक AI के बारे में अधिक सीखना चाहते हैं, तो Introduction to AI Agents कोर्स अवश्य देखें।

Aashi Dutt

लेखक

Aashi Dutt

मैं एमएल (Gen AI) में Google Developers Expert, Kaggle 3x Expert, और Women Techmakers एंबेसडर हूँ, तथा तकनीक क्षेत्र में 3+ वर्षों का अनुभव रखती हूँ। मैंने 2020 में एक हेल्थ-टेक स्टार्टअप की सह-स्थापना की और वर्तमान में Georgia Tech से कंप्यूटर विज्ञान में मास्टर कर रही हूँ, जिसमें मेरा विशेषज्ञता क्षेत्र मशीन लर्निंग है।

विषय