एक Python स्क्रिप्ट लिखें जो टेक्स्ट प्रॉम्प्ट को इमेज मॉडल पर भेजे, जॉब पूरा होने का इंतज़ार करे और तस्वीर सेव करे। इसे चार स्टेप में बनाएँ, फिर कमांड लाइन, थ्रेडेड बैच, Flask रूट और आपके सामने आने वाली एरर के समाधान जोड़ें।
AI इमेज के ज़्यादातर ट्यूटोरियल "किसी वेबसाइट पर प्रॉम्प्ट चिपकाएँ" पर खत्म हो जाते हैं। एक तस्वीर के लिए यह ठीक है। लेकिन जैसे ही आपको पचास प्रोडक्ट शॉट, रात भर चलने वाले ब्लॉग थंबनेल का बैच, या कोई छोटा ऐप चाहिए जहाँ विज़िटर एक वाक्य लिखे और बदले में फ़ोटो पाए, यह तरीका टूट जाता है। इसके लिए कोड चाहिए, और अच्छी बात यह है कि Python में एक काम करने वाला इमेज जनरेटर लगभग 60 लाइनों में आ जाता है।
यह ट्यूटोरियल इसे चार छोटे स्टेप में बनाता है: होस्ट किए गए मॉडल को प्रॉम्प्ट भेजना, जॉब खत्म होने का इंतज़ार करना, फ़ाइल डाउनलोड करना, और फिर सब कुछ एक कमांड लाइन टूल में लपेटना जो बैच चलाता है। हर स्टेप के अंत में एक त्वरित जाँच है, ताकि आगे बढ़ने से पहले आप जान सकें कि सब काम कर रहा है।
💡 त्वरित उत्तर: Python में AI इमेज जनरेटर एक ऐसी स्क्रिप्ट है जो HTTP के ज़रिए मॉडल को टेक्स्ट प्रॉम्प्ट भेजती है, तैयार होने तक पोल करती है, फिर फ़ाइल सेव करती है। मॉडल किसी और के GPU पर चलता है। आपके कोड को requests, एक सीक्रेट टोकन और एक लूप चाहिए।
कोड लिखने से पहले
आपको तीन चीज़ें चाहिए: Python 3.10 या नया, एक टर्मिनल, और इमेज सेवा के लिए एक सीक्रेट टोकन। नीचे दिया कोड सादे HTTP पर PicassoIA API से बात करता है, इसलिए कोई GPU ड्राइवर इंस्टॉल नहीं करना पड़ता और न ही कोई मॉडल फ़ाइल डाउनलोड करनी पड़ती है।
प्रोजेक्ट सेट अप करें
एक फ़ोल्डर, एक वर्चुअल एनवायरनमेंट बनाएँ और एक पैकेज इंस्टॉल करें:
इसके बाद API पेज पर एक टोकन बनाएँ और उसे सोर्स फ़ाइल में लिखने के बजाय एक एनवायरनमेंट वेरिएबल में सहेजें। एक अकाउंट में एक समय पर अधिकतम दो टोकन हो सकते हैं।
Windows PowerShell पर वही लाइन $env:PICASSOIA_API_TOKEN = "pia_sk_your_token_here" है।
⚠️ टोकन को कभी अपनी स्क्रिप्ट में न चिपकाएँ। git में कमिट की गई कोई भी चीज़ इतिहास में रहती है, भले ही आप उसे बाद में मिटा दें। एनवायरनमेंट वेरिएबल सीक्रेट को रिपॉज़िटरी से बाहर रखता है।
पहले मॉडल चुनें
मॉडल तय करता है कि आपकी इमेज कैसी दिखेंगी और कितनी तेज़ी से आएँगी। इस ट्यूटोरियल की स्क्रिप्ट API के ज़रिए picassoia/picassoia-image को कॉल करती है। नीचे की टेबल के सभी मॉडल PicassoIA पर ब्राउज़र में उपलब्ध हैं, जिससे कोड में कुछ जोड़ने से पहले प्रॉम्प्ट टेस्ट करना आसान हो जाता है।
डिफ़्यूज़न मॉडल रैंडम नॉइज़ से शुरू होता है और उसे कई छोटे चरणों में हटाता है, और हर चरण में आपका प्रॉम्प्ट उसे एक दिशा देता है। हर चरण एक बड़े न्यूरल नेटवर्क पर भारी गणना है। इसीलिए इमेज जनरेशन को शक्तिशाली GPU चाहिए, और इसी वजह से आपके Python प्रोजेक्ट का पहला डिज़ाइन फ़ैसला यह है कि वह GPU कहाँ रहेगा।
लोकल GPU या होस्टेड API। अपनी मशीन पर मॉडल चलाने से आपको पूरा नियंत्रण मिलता है, लेकिन इसका मतलब ड्राइवरों और सॉफ़्टवेयर का सेट, दसियों गीगाबाइट के वेट्स और काफ़ी मेमोरी वाला कार्ड भी है। होस्टेड API उस नियंत्रण का कुछ हिस्सा छोड़कर ऐसा सेटअप देता है जो मिनटों में हो जाता है।
पहलू
लोकल 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 से बेहतर है।
फ़ंक्शन इमेज नहीं, एक जॉब 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 के अंदर कॉल करें:
छह हफ़्ते बाद, जब कोई पूछेगा कि सूर्योदय वाली तस्वीर किस प्रॉम्प्ट से बनी थी, तो वह फ़ाइल कुछ ही सेकंड में जवाब दे देगी।
इसे वेब रूट के रूप में दें
टीमों को अक्सर टर्मिनल नहीं चाहिए। एक छोटा Flask ऐप किसी को भी एक पेज से प्रॉम्प्ट भेजने देता है। ध्यान दें कि रूट तुरंत जॉब ID लौटाता है और एक दूसरा रूट प्रगति बताता है, इसलिए कोई वेब रिक्वेस्ट एक मिनट तक नहीं अटकती।
आपका फ़्रंट एंड /generate को कॉल करता है, फिर हर दो सेकंड में /status/<id> से पूछता है जब तक statussucceeded न हो जाए। टोकन सर्वर पर रहता है, कभी ब्राउज़र के कोड में नहीं।
ऐसे प्रॉम्प्ट लिखें जो ठीक काम करें
हिस्सों से प्रॉम्प्ट बनाएँ
अस्पष्ट प्रॉम्प्ट से अस्पष्ट तस्वीरें मिलती हैं। सब्जेक्ट, जगह, रोशनी का स्रोत और लेंस वाला प्रॉम्प्ट कुछ ऐसा देता है जिसे दोहराया जा सके। यह ढाँचा एक फ़ंक्शन में रखें, ताकि बैच की हर इमेज उसी का पालन करे:
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 लगभग एक सेकंड में जवाब देता है, तो एक धीमे मॉडल के एक नतीजे को रेंडर करने में लगने वाले समय में आप दस वैरिएशन आज़मा सकते हैं।
मॉडल पेज खोलें और प्रॉम्प्ट बॉक्स ढूँढें।
एक प्रॉम्प्ट चिपकाएँ जो पिछले सेक्शन के सब्जेक्ट, सेटिंग, रोशनी, लेंस के ढाँचे से बना हो।
लेख की इमेज के लिए 16:9 रेशियो चुनें, या थंबनेल के लिए 1:1।
तीन वैरिएशन बनाएँ और उनके बीच केवल एक डिटेल बदलें। इससे पता चलता है कि कौन सा शब्द असर कर रहा था।
सबसे असरदार शब्द को 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 पेज पर एंडपॉइंट की सूची है, और पूरी मॉडल सूची में वे टेक्स्ट-टू-इमेज, वीडियो और स्पीच मॉडल हैं जिन्हें आप आगे आज़मा सकते हैं। वही क्रिएट, पोल और डाउनलोड वाला लूप वीडियो जॉब पर भी काम करता है, इसलिए आज लिखी स्क्रिप्ट कल के क्लिप जनरेटर का आधार बन सकती है। एक प्रॉम्प्ट चुनें, स्क्रिप्ट चलाएँ, और देखें कि आपके आउटपुट फ़ोल्डर में क्या आता है।