Python में AI इमेज जनरेटर बनाएँ (स्टेप-दर-स्टेप)

एक Python स्क्रिप्ट लिखें जो टेक्स्ट प्रॉम्प्ट को इमेज मॉडल पर भेजे, जॉब पूरा होने का इंतज़ार करे और तस्वीर सेव करे। इसे चार स्टेप में बनाएँ, फिर कमांड लाइन, थ्रेडेड बैच, Flask रूट और आपके सामने आने वाली एरर के समाधान जोड़ें।

Python में AI इमेज जनरेटर बनाएँ (स्टेप-दर-स्टेप)
Cristian Da Conceicao
Picasso IA के संस्थापक

AI इमेज के ज़्यादातर ट्यूटोरियल "किसी वेबसाइट पर प्रॉम्प्ट चिपकाएँ" पर खत्म हो जाते हैं। एक तस्वीर के लिए यह ठीक है। लेकिन जैसे ही आपको पचास प्रोडक्ट शॉट, रात भर चलने वाले ब्लॉग थंबनेल का बैच, या कोई छोटा ऐप चाहिए जहाँ विज़िटर एक वाक्य लिखे और बदले में फ़ोटो पाए, यह तरीका टूट जाता है। इसके लिए कोड चाहिए, और अच्छी बात यह है कि Python में एक काम करने वाला इमेज जनरेटर लगभग 60 लाइनों में आ जाता है।

यह ट्यूटोरियल इसे चार छोटे स्टेप में बनाता है: होस्ट किए गए मॉडल को प्रॉम्प्ट भेजना, जॉब खत्म होने का इंतज़ार करना, फ़ाइल डाउनलोड करना, और फिर सब कुछ एक कमांड लाइन टूल में लपेटना जो बैच चलाता है। हर स्टेप के अंत में एक त्वरित जाँच है, ताकि आगे बढ़ने से पहले आप जान सकें कि सब काम कर रहा है।

💡 त्वरित उत्तर: Python में AI इमेज जनरेटर एक ऐसी स्क्रिप्ट है जो HTTP के ज़रिए मॉडल को टेक्स्ट प्रॉम्प्ट भेजती है, तैयार होने तक पोल करती है, फिर फ़ाइल सेव करती है। मॉडल किसी और के GPU पर चलता है। आपके कोड को requests, एक सीक्रेट टोकन और एक लूप चाहिए।

कोड लिखने से पहले

लैपटॉप पर Python कोड टाइप करते डेवलपर के हाथ, लकड़ी की मेज़ पर

आपको तीन चीज़ें चाहिए: Python 3.10 या नया, एक टर्मिनल, और इमेज सेवा के लिए एक सीक्रेट टोकन। नीचे दिया कोड सादे HTTP पर PicassoIA API से बात करता है, इसलिए कोई GPU ड्राइवर इंस्टॉल नहीं करना पड़ता और न ही कोई मॉडल फ़ाइल डाउनलोड करनी पड़ती है।

प्रोजेक्ट सेट अप करें

एक फ़ोल्डर, एक वर्चुअल एनवायरनमेंट बनाएँ और एक पैकेज इंस्टॉल करें:

mkdir ai-image-generator && cd ai-image-generator
python -m venv .venv
source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install requests

इसके बाद API पेज पर एक टोकन बनाएँ और उसे सोर्स फ़ाइल में लिखने के बजाय एक एनवायरनमेंट वेरिएबल में सहेजें। एक अकाउंट में एक समय पर अधिकतम दो टोकन हो सकते हैं।

export PICASSOIA_API_TOKEN="pia_sk_your_token_here"

Windows PowerShell पर वही लाइन $env:PICASSOIA_API_TOKEN = "pia_sk_your_token_here" है।

⚠️ टोकन को कभी अपनी स्क्रिप्ट में न चिपकाएँ। git में कमिट की गई कोई भी चीज़ इतिहास में रहती है, भले ही आप उसे बाद में मिटा दें। एनवायरनमेंट वेरिएबल सीक्रेट को रिपॉज़िटरी से बाहर रखता है।

पहले मॉडल चुनें

मॉडल तय करता है कि आपकी इमेज कैसी दिखेंगी और कितनी तेज़ी से आएँगी। इस ट्यूटोरियल की स्क्रिप्ट API के ज़रिए picassoia/picassoia-image को कॉल करती है। नीचे की टेबल के सभी मॉडल PicassoIA पर ब्राउज़र में उपलब्ध हैं, जिससे कोड में कुछ जोड़ने से पहले प्रॉम्प्ट टेस्ट करना आसान हो जाता है।

मॉडलसबसे अच्छा उपयोग
P Imageतेज़ फोटोरियलिस्टिक ड्राफ़्ट, प्रति इमेज लगभग एक सेकंड
Flux 2 Proटेक्स्ट या रेफ़रेंस फ़ोटो से विस्तृत इमेज
Flux Devफ़ोटोरियलिस्टिक दृश्य और पोर्ट्रेट
Stable Diffusion 3.5 Largeसाफ़ और बारीक डिटेल वाली HD इमेज
Imagen 4 Fastकुछ सेकंड में जल्दी नतीजे
Seedream 4.54K तक हाई रिज़ॉल्यूशन आउटपुट
SDXL Lightning 4Stepबहुत तेज़ प्रीव्यू

टेक्स्ट कैसे तस्वीर बनता है

डिफ़्यूज़न मॉडल रैंडम नॉइज़ से शुरू होता है और उसे कई छोटे चरणों में हटाता है, और हर चरण में आपका प्रॉम्प्ट उसे एक दिशा देता है। हर चरण एक बड़े न्यूरल नेटवर्क पर भारी गणना है। इसीलिए इमेज जनरेशन को शक्तिशाली GPU चाहिए, और इसी वजह से आपके Python प्रोजेक्ट का पहला डिज़ाइन फ़ैसला यह है कि वह GPU कहाँ रहेगा।

एक शांत डेटा सेंटर गलियारे में काले सर्वर रैक की कतारें

लोकल GPU या होस्टेड API। अपनी मशीन पर मॉडल चलाने से आपको पूरा नियंत्रण मिलता है, लेकिन इसका मतलब ड्राइवरों और सॉफ़्टवेयर का सेट, दसियों गीगाबाइट के वेट्स और काफ़ी मेमोरी वाला कार्ड भी है। होस्टेड API उस नियंत्रण का कुछ हिस्सा छोड़कर ऐसा सेटअप देता है जो मिनटों में हो जाता है।

खुले PC केस के अंदर तांबे की हीट पाइप वाले डेस्कटॉप ग्राफ़िक्स कार्ड का क्लोज़-अप

पहलूलोकल GPUहोस्टेड API
सेटअप का समयघंटेमिनट
हार्डवेयर12 GB या उससे ज़्यादा मेमोरी वाला नया ग्राफ़िक्स कार्डकोई भी लैपटॉप
मॉडल चुनावजो आप डाउनलोड करेंजो सेवा सूची में दे
स्केलिंगदूसरा कार्ड खरीदेंकंकरेंसी बढ़ाएँ
Python डिपेंडेंसीभारीकेवल requests

जॉब असिंक्रोनस क्यों हैं। मॉडल के हिसाब से एक इमेज बनने में एक सेकंड से कम से लेकर लगभग एक मिनट तक लग सकता है। इतनी देर तक एक HTTP कनेक्शन खुला रखना नाज़ुक है, इसलिए API तीन चरणों में काम करता है: जॉब बनाना, उसका स्टेटस पोल करना, और स्टेटस succeeded दिखाए तब आउटपुट लाना। आपका कोड अगले सेक्शन में इन्हीं तीन चरणों को दोहराता है।

स्टेप-दर-स्टेप: पहली स्क्रिप्ट

सब कुछ generate.py नाम की एक फ़ाइल में रखें। नीचे के चार स्टेप इसे ऊपर से नीचे तक बनाते हैं।

स्टेप 1: रिक्वेस्ट सेट अप करें

API Replicate-शैली का है: एक बेस URL, पाथ में मॉडल का नाम, और हेडर में Bearer टोकन।

import os
import time
from pathlib import Path

import requests

API_BASE = "https://api.picassoia.com/v1"
MODEL = "picassoia/picassoia-image"
TOKEN = os.environ["PICASSOIA_API_TOKEN"]
HEADERS = {
    "Authorization": f"Bearer {TOKEN}",
    "Content-Type": "application/json",
}

अगर वेरिएबल मौजूद नहीं है, तो Python यहीं एरर के साथ रुक जाता है, और ठीक यही आप चाहते हैं। फ़ाइल की शुरुआत में ज़ोरदार फ़ेल होना बाद में आने वाले उलझन भरे 401 से बेहतर है।

स्टेप 2: प्रॉम्प्ट भेजें

def create_prediction(prompt: str) -> str:
    url = f"{API_BASE}/models/{MODEL}/predictions"
    payload = {"input": {"prompt": prompt}}
    response = requests.post(url, headers=HEADERS, json=payload, timeout=30)
    response.raise_for_status()
    return response.json()["id"]

फ़ंक्शन इमेज नहीं, एक जॉब ID लौटाता है। प्रॉम्प्ट 4,000 अक्षरों तक हो सकते हैं, जो आपकी ज़रूरत से कहीं ज़्यादा है।

स्टेप 3: खत्म होने तक पोल करें

def wait_for_result(job_id: str, poll_every: float = 2.0, limit: float = 300.0) -> str:
    url = f"{API_BASE}/predictions/{job_id}"
    deadline = time.time() + limit
    while time.time() < deadline:
        response = requests.get(url, headers=HEADERS, timeout=30)
        response.raise_for_status()
        data = response.json()
        status = data["status"]
        if status == "succeeded":
            output = data["output"]
            return output[0] if isinstance(output, list) else output
        if status in ("failed", "canceled"):
            raise RuntimeError(f"Job {job_id} ended as {status}: {data.get('error')}")
        time.sleep(poll_every)
    raise TimeoutError(f"Job {job_id} did not finish within {limit} seconds")

💡 टिप: फ़ील्ड के नाम Replicate-शैली के फ़ॉर्मेट का पालन करते हैं। अगर कभी रिस्पॉन्स अलग दिखे, तो response.json() को एक बार प्रिंट करें और उन दो लाइनों को ठीक करें जिनमें status और output लिखा है। लूप अपनी डेडलाइन भी खुद तय करता है, इसलिए अटका हुआ जॉब आपकी स्क्रिप्ट को कभी फ़्रीज़ नहीं करता।

स्टेप 4: फ़ाइल सेव करें

def download(image_url: str, folder: str = "output") -> Path:
    Path(folder).mkdir(exist_ok=True)
    name = image_url.split("/")[-1].split("?")[0] or f"image-{int(time.time())}.png"
    target = Path(folder) / name
    response = requests.get(image_url, timeout=60)
    response.raise_for_status()
    target.write_bytes(response.content)
    return target


if __name__ == "__main__":
    prompt = "A misty mountain lake at sunrise, 35mm photograph, soft natural light, fine film grain"
    job_id = create_prediction(prompt)
    image_url = wait_for_result(job_id)
    print("Saved", download(image_url))

गोल्डन आवर में समुद्र तट की फ़ोटो के बगल में टर्मिनल विंडो का कंधे के ऊपर से दृश्य

python generate.py चलाएँ। कुछ सेकंड बाद आपको Saved output/... दिखना चाहिए और output फ़ोल्डर में एक नई फ़ाइल। चेकपॉइंट: अगर आप वह इमेज खोल पा रहे हैं, तो स्टेप 1 से 4 तक सब काम कर रहा है, और इसके बाद का हर काम केवल पैकेजिंग है।

स्क्रिप्ट को टूल में बदलें

कमांड लाइन जोड़ें

फ़ाइल के निचले हिस्से को argparse एंट्री पॉइंट से बदलें, ताकि आप टर्मिनल से प्रॉम्प्ट दे सकें:

import argparse


def main() -> None:
    parser = argparse.ArgumentParser(description="Generate an image from a text prompt")
    parser.add_argument("prompt", help="what the image should show")
    parser.add_argument("--out", default="output", help="folder for saved files")
    args = parser.parse_args()

    image_url = wait_for_result(create_prediction(args.prompt))
    print(download(image_url, args.out))


if __name__ == "__main__":
    main()

अब python generate.py "a red bicycle leaning on a brick wall, 50mm photo" --out bikes एक ही लाइन में पूरा काम कर देता है।

सीमाओं के भीतर बैच चलाएँ

हर इमेज का एक-एक करके इंतज़ार करने वाला लूप धीमा है। थ्रेड इसे ठीक करते हैं, क्योंकि स्क्रिप्ट का लगभग सारा समय नेटवर्क के जवाब के इंतज़ार में जाता है। API हर अकाउंट के लिए 5 एक साथ चलने वाले प्रेडिक्शन की अनुमति देता है, जो आपके सभी टोकन और जुड़े ऐप्स में बँटते हैं, इसलिए पाँच वर्कर सबसे ऊपरी सीमा हैं।

from multiprocessing.pool import ThreadPool


def generate(prompt: str) -> Path:
    return download(wait_for_result(create_prediction(prompt)))


def run_batch(prompts: list[str]) -> list[Path]:
    with ThreadPool(5) as pool:
        return pool.map(generate, prompts)

छोटे लैंडस्केप और पोर्ट्रेट फ़्रेम की प्रिंट की हुई कॉन्टैक्ट शीट देखते फ़ोटोग्राफ़र

अगर बैच चलते समय आप वेबसाइट भी इस्तेमाल करते हैं, तो दोनों को एक ही पाँच स्लॉट के लिए न लड़ाने के लिए वर्कर घटाकर तीन कर दें। एक फ़ेल प्रॉम्प्ट pool.map के अंदर एरर उठाता है, इसलिए generate को try ब्लॉक में लपेटें, जो प्रॉम्प्ट को लॉग करे और जब आप सैकड़ों एक साथ चलाएँ तब None लौटाए।

रिकॉर्ड रखें। हर प्रॉम्प्ट और फ़ाइल नाम को log.jsonl फ़ाइल में जोड़ते जाएँ, ताकि किसी भी तस्वीर को उन शब्दों तक वापस ट्रेस कर सकें जिन्होंने उसे बनाया। इस हेल्पर को download के ठीक बाद generate के अंदर कॉल करें:

import json


def log_result(prompt: str, path: Path) -> None:
    with open("log.jsonl", "a", encoding="utf-8") as log:
        log.write(json.dumps({"prompt": prompt, "file": str(path)}) + "\n")

छह हफ़्ते बाद, जब कोई पूछेगा कि सूर्योदय वाली तस्वीर किस प्रॉम्प्ट से बनी थी, तो वह फ़ाइल कुछ ही सेकंड में जवाब दे देगी।

इसे वेब रूट के रूप में दें

टीमों को अक्सर टर्मिनल नहीं चाहिए। एक छोटा Flask ऐप किसी को भी एक पेज से प्रॉम्प्ट भेजने देता है। ध्यान दें कि रूट तुरंत जॉब ID लौटाता है और एक दूसरा रूट प्रगति बताता है, इसलिए कोई वेब रिक्वेस्ट एक मिनट तक नहीं अटकती।

from flask import Flask, jsonify, request

app = Flask(__name__)


@app.post("/generate")
def start():
    prompt = request.get_json()["prompt"]
    return jsonify(id=create_prediction(prompt))


@app.get("/status/<job_id>")
def status(job_id):
    url = f"{API_BASE}/predictions/{job_id}"
    data = requests.get(url, headers=HEADERS, timeout=30).json()
    return jsonify(status=data["status"], output=data.get("output"))

एक मॉनिटर पर फ़ोटो थंबनेल के ग्रिड के सामने इकट्ठा तीन सहकर्मी

आपका फ़्रंट एंड /generate को कॉल करता है, फिर हर दो सेकंड में /status/<id> से पूछता है जब तक status succeeded न हो जाए। टोकन सर्वर पर रहता है, कभी ब्राउज़र के कोड में नहीं।

ऐसे प्रॉम्प्ट लिखें जो ठीक काम करें

लैपटॉप, नोटबुक स्केच और प्रिंट की हुई फ़ोटो के साथ मेज़ का ऊपर से दृश्य

हिस्सों से प्रॉम्प्ट बनाएँ

अस्पष्ट प्रॉम्प्ट से अस्पष्ट तस्वीरें मिलती हैं। सब्जेक्ट, जगह, रोशनी का स्रोत और लेंस वाला प्रॉम्प्ट कुछ ऐसा देता है जिसे दोहराया जा सके। यह ढाँचा एक फ़ंक्शन में रखें, ताकि बैच की हर इमेज उसी का पालन करे:

def build_prompt(subject: str, setting: str, light: str, lens: str = "50mm f/1.8") -> str:
    return (
        f"{subject}, {setting}, {light}, shot on a {lens} lens, "
        "natural skin and surface texture, fine film grain, photorealistic"
    )


print(build_prompt("a ceramic mug of black coffee", "on an oak desk", "soft window light from the left"))

तीन आदतें नतीजों को ज़्यादा अनुमानित बनाती हैं:

  • हर प्रॉम्प्ट में एक दृश्य। ध्यान के लिए लड़ते दो सब्जेक्ट धुंधली तस्वीरें बनाते हैं।
  • रोशनी का नाम लें। "बाईं ओर से आती वॉल्यूमेट्रिक सुबह की रोशनी" "अच्छी लाइटिंग" से बेहतर काम करती है।
  • लेंस का नाम लें। 85mm और f/1.8 जैसे शब्द मॉडल को उथली डेप्थ ऑफ़ फ़ील्ड की ओर धकेलते हैं।

लैंग्वेज मॉडल के साथ विचार करें

हाथ से 50 प्रॉम्प्ट लिखना बारहवें प्रॉम्प्ट तक उबाऊ हो जाता है। एक लार्ज लैंग्वेज मॉडल इन्हें आपके लिए ड्राफ़्ट कर सकता है। Claude Sonnet 5 संरचित सूचियों को अच्छी तरह संभालता है, और Gemini 3.5 Flash जब आपको बस मात्रा चाहिए तब जल्दी ड्राफ़्ट लौटाता है। 20 प्रॉम्प्ट माँगें जो आपके सब्जेक्ट, सेटिंग, रोशनी, लेंस के ढाँचे का पालन करें, हर लाइन में एक, और जवाब को prompts.txt के रूप में सेव करें। फिर उस फ़ाइल को अपने बैच रनर में डालें:

prompts = [line.strip() for line in Path("prompts.txt").read_text().splitlines() if line.strip()]
run_batch(prompts)

PicassoIA पर P Image कैसे इस्तेमाल करें

कोड पर समय लगाने से पहले ब्राउज़र में अपने शब्दों को टेस्ट करें। P Image लगभग एक सेकंड में जवाब देता है, तो एक धीमे मॉडल के एक नतीजे को रेंडर करने में लगने वाले समय में आप दस वैरिएशन आज़मा सकते हैं।

  1. मॉडल पेज खोलें और प्रॉम्प्ट बॉक्स ढूँढें।
  2. एक प्रॉम्प्ट चिपकाएँ जो पिछले सेक्शन के सब्जेक्ट, सेटिंग, रोशनी, लेंस के ढाँचे से बना हो।
  3. लेख की इमेज के लिए 16:9 रेशियो चुनें, या थंबनेल के लिए 1:1।
  4. तीन वैरिएशन बनाएँ और उनके बीच केवल एक डिटेल बदलें। इससे पता चलता है कि कौन सा शब्द असर कर रहा था।
  5. सबसे असरदार शब्द को prompts.txt में या अपनी build_prompt कॉल में कॉपी करें।

💡 अगर सीड फ़ील्ड उपलब्ध है, तो शब्दों की तुलना करते समय सीड को फ़िक्स कर दें। सीड लॉक होने पर नतीजे में होने वाला कोई भी बदलाव आपके प्रॉम्प्ट से आता है, और किसी चीज़ से नहीं।

जब P Image सही फ़्रेमिंग दे लेकिन सही फ़िनिश नहीं, तो वही प्रॉम्प्ट Flux 2 Pro या Seedream 4.5 पर चलाएँ और नतीजों की साथ-साथ तुलना करें। हर मॉडल की अपनी आदतें होती हैं, और दस मिनट की टेस्टिंग बाद में घंटों की दोबारा लिखाई बचा देती है।

आने वाली एरर के समाधान

ऑथेंटिकेशन एरर

401 या 403 का मतलब लगभग हमेशा होता है कि टोकन रिक्वेस्ट तक पहुँचा ही नहीं। जाँचें कि PICASSOIA_API_TOKEN उसी टर्मिनल में सेट है जिसमें Python चल रहा है, क्योंकि एक विंडो में एक्सपोर्ट किया वेरिएबल दूसरी विंडो में नहीं होता। वैल्यू में बेमतलब के कोट या आख़िर में आए स्पेस की भी जाँच करें।

लिमिट और अटके हुए जॉब

लक्षणसंभावित कारणसमाधान
429 रिस्पॉन्सएक साथ 5 से ज़्यादा जॉब चल रहे हैंThreadPool को 3 या 4 करें और थोड़ी देर स्लीप के बाद दोबारा कोशिश करें
400 रिस्पॉन्सप्रॉम्प्ट 4,000 अक्षरों से ज़्यादा है, या फ़ील्ड का नाम गलत हैप्रॉम्प्ट छोटा करें और एरर बॉडी प्रिंट करें
जॉब कभी खत्म नहीं होताभारी कतार या अटका हुआ जॉबlimit डेडलाइन रखें और एक बार दोबारा कोशिश करें
failed स्टेटसमॉडल ने प्रॉम्प्ट अस्वीकार कियाउसे सरल करें और असामान्य चिह्न हटाएँ

रिट्राई के लिए, हर फ़ेल होने के बाद थोड़ा लंबा इंतज़ार करें (2, 4, फिर 8 सेकंड) और तीन कोशिशों के बाद रुक जाएँ। API पर तुरंत रिट्राई बार-बार करने से आप बस लिमिट के ऊपर बने रहते हैं।

नरम या धुंधले नतीजे

एक ड्राफ़्टिंग टेबल पर बड़ी प्रिंट की हुई लैंडस्केप फ़ोटो देखती महिला

अगर फ़्रेमिंग सही है लेकिन डिटेल नरम है, तो कारण आम तौर पर रिज़ॉल्यूशन होता है, प्रॉम्प्ट नहीं। Seedream 4.5 जैसा हाई रिज़ॉल्यूशन आउटपुट देने वाला मॉडल चुनें, या तैयार इमेज को PicassoIA के किसी Super Resolution मॉडल से चलाकर 2x से 4x तक अपस्केल करें। यह भी जाँचें कि प्रॉम्प्ट में कैमरा और लेंस का नाम है, क्योंकि अकेला "photograph" शब्द बहुत कुछ खुला छोड़ देता है।

आज ही अपनी पहली इमेज बनाएँ

धूप वाले जंगल के रास्ते की फ़ोटो वाला टैबलेट पकड़े कैफ़े में बैठा चारकोल स्वेटर में आदमी

अब आपके पास एक ऐसी स्क्रिप्ट है जो एक वाक्य को फ़ोटो में बदलती है, एक बैच रनर है जो पाँच जॉब की सीमा का पालन करता है, और एक प्रॉम्प्ट टेम्पलेट है जिसे हर प्रोजेक्ट में दोबारा इस्तेमाल कर सकते हैं। सबसे तेज़ अगला कदम छोटा है: अपने ब्राउज़र में P Image खोलें, तीन प्रॉम्प्ट टेस्ट करें, सबसे अच्छे शब्द prompts.txt में चिपकाएँ, और बैच चलाएँ।

जब आप स्केल करना चाहें, तो PicassoIA API पेज पर एंडपॉइंट की सूची है, और पूरी मॉडल सूची में वे टेक्स्ट-टू-इमेज, वीडियो और स्पीच मॉडल हैं जिन्हें आप आगे आज़मा सकते हैं। वही क्रिएट, पोल और डाउनलोड वाला लूप वीडियो जॉब पर भी काम करता है, इसलिए आज लिखी स्क्रिप्ट कल के क्लिप जनरेटर का आधार बन सकती है। एक प्रॉम्प्ट चुनें, स्क्रिप्ट चलाएँ, और देखें कि आपके आउटपुट फ़ोल्डर में क्या आता है।

यह लेख शेयर करें

अपनी भाषा चुनें

संबंधित लेख