واجهة Gemini API لتوليد الصور في Python: مثال برمجي
شرح عملي بلغة Python لواجهة Gemini API لتوليد الصور باستخدام نموذج gemini-3.1-flash-image الحالي وواجهة Interactions API. ولّد أول صورة لك، واضبط نسبة العرض إلى الارتفاع والدقة، وعدّل الصور، وأعد المحاولة عند فشل الاستدعاءات، وقدّر التكلفة الفعلية لكل صورة.
تستخدم معظم دروس توليد الصور بواسطة Gemini ما يزال gemini-2.5-flash-image، وتدرج صفحة التسعير لدى Google هذا النموذج على أنه مهجور بتاريخ إيقاف هو 2 أكتوبر 2026. وقد مضى هذا التاريخ، لذا ينبغي اعتبار المقتطفات المبنية عليه معطّلة. تستخدم هذه الصفحة النموذج الحالي، gemini-3.1-flash-image، وواجهة Interactions API التي تقدّمها وثائق Google الرسمية الآن بوصفها الخيار الأول.
ستنتقل من مجلد فارغ إلى سكربت يعمل يولّد صورة، ويتحكم في حجمها، ويعدّل صورة فوتوغرافية موجودة، ويحفظ مخرجات مختلطة من نص وصورة، ويصمد أمام حدود معدل الطلبات. كل مقتطف قصير بما يكفي لنسخه في ملف وتشغيله. تكلّف صورة واحدة بدقة 1K على نموذج Flash القياسي حوالي $0.067، لذا يبقى الاختبار رخيصًا.
ما تحتاجه قبل البرمجة
ثلاثة أشياء تحول بينك وبين أول صورة لك: تثبيت حديث لـ Python 3، وبيانات اعتماد من Google AI Studio، ومشروع مفعّل فيه الفوترة. وتُظهر صفحة التسعير لدى Google عدم وجود مستوى مجاني لأي من نماذج Gemini لتوليد الصور، لذا من المرجح أن يُرفض أول استدعاء من مشروع غير مفوتر.
تثبيت SDK
حزمة واحدة تتكفّل بكل شيء:
pip install -U google-genai
تحتاج واجهة Interactions API إلى google-genai2.3.0 أو أحدث، ولهذا يكون العلم -U مهمًا. شغّل pip show google-genai إذا فشل أحد المقتطفات أدناه برسالة خطأ في الخاصية على client.interactions.
اضبط بيانات الاعتماد
أنشئ بيانات اعتماد في Google AI Studio، ثم صدّرها كمتغير بيئة باسم المتغير الموضّح أدناه. تقرأ الحزمة هذا المتغير من تلقاء نفسها، فلا يحتاج سكربتك إلى احتواء السر نفسه.
في Windows PowerShell يكون السطر نفسه $env:GEMINI_API_KEY = "paste-your-credential-here".
💡 لا تلصق بيانات الاعتماد أبدًا في سكربت سيُرفع إلى Git. احتفظ بها في متغير بيئة أو في ملف .env يستثنيه .gitignore أصلًا.
اختر نموذجًا
تسرد Google الآن أربعة نماذج لتوليد الصور. ثلاثة منها حالية، والرابع متقاعد.
معرّف النموذج
الأحجام
السعر لكل صورة
الأفضل لـ
gemini-3.1-flash-lite-image
1K فقط
حوالي $0.034
المهام الجماعية، الصور المصغّرة
gemini-3.1-flash-image
0.5K، 1K، 2K، 4K
$0.045، $0.067، $0.101، $0.151
الخيار الافتراضي لمعظم السكربتات
gemini-3-pro-image
1K، 2K، 4K
$0.134 (1K و2K)، $0.24 (4K)
الأوامر النصية المعقدة متعددة الأجزاء
gemini-2.5-flash-image
غير متاح
$0.039
متقاعد، لا تستخدمه
الأسعار مأخوذة من صفحة التسعير لدى Google وقت كتابة هذا المقال. راجعها مرة أخرى قبل أي تشغيل كبير.
كيف تختار؟ ابدأ بـ gemini-3.1-flash-image. فهو النموذج الحالي الوحيد الذي يقدم الأحجام الأربعة جميعها، لذا يخدم مسار شيفرة واحد الصور المصغّرة وملفات الطباعة معًا. انتقل إلى Flash Lite عندما تولّد آلاف الصور الصغيرة ويهمّك كل سنت لكل صورة. واستخدم Pro عندما يتكون الأمر النصي من أجزاء كثيرة، مثل تخطيط ملصق يضم عدة عناصر مُسمّاة، ويواصل نموذج أرخص إسقاط التفاصيل. ولأن النماذج الحالية الثلاثة تشترك في شكل الاستدعاء نفسه، فإن تغيير النموذج لاحقًا يعني تعديل سلسلة نصية واحدة فقط.
ولّد أول صورة لك
احفظ هذا الكود باسم first_image.py:
import base64
from google import genai
client = genai.Client()
interaction = client.interactions.create(
model="gemini-3.1-flash-image",
input="A photograph of a bowl of oranges on a linen cloth, soft window light",
)
with open("oranges.png", "wb") as f:
f.write(base64.b64decode(interaction.output_image.data))
شغّل python first_image.py فيظهر ملف oranges.png بجوار السكربت. هذه هي الدورة الكاملة: أمر نصي يدخل، وسلسلة base64 تخرج، وبايتات تُكتب على القرص.
عندما تولّد أكثر من صورة، يستبدل اسم الملف الثابت نتيجتك السابقة. لذا ابنِ الاسم من طابع زمني، مثل f"image_{int(time.time())}.png"، فيترك كل تشغيل ملفه الخاص. وبعد ذلك يمكنك مقارنة اثني عشر تنويعًا من أمر نصي واحد جنبًا إلى جنب.
ما تفعله كل سطر
genai.Client() ينشئ عميلًا ويسحب بيانات الاعتماد من متغير البيئة الذي صدّرته سابقًا، فلا يوجد شيء حساس داخل الملف.
client.interactions.create() يرسل الأمر النصي ويعيد كائن Interaction يحمل id، وخطوات المخرجات، واختصارات مثل output_image.
interaction.output_image.data يحتوي الصورة كـسلسلة base64. يجب فك ترميزها قبل الكتابة، وإلا فسيكون الملف نصًا لا صورة.
اكتب أوامر نصية تعمل
يستجيب النموذج بأفضل شكل لأوصاف المشاهد، لا لقائمة من الوسوم المتفرقة. فالأمر النصي الذي يُقرأ كقائمة لقطات مصوّر يمنحك تحكمًا أكبر من قائمة صفات.
حدّد العنصر الرئيسي والفعل. "خباز ينثر الدقيق فوق رغيف" أفضل من "مخبز".
صِف الإضاءة. ضوء النافذة، أو سماء غائمة، أو الساعة الذهبية، أو شمس الظهيرة القاسية.
أضِف العدسة والمسافة. "صورة شخصية بعدسة 85mm، وعمق ميدان ضحل" أو "لقطة جوية واسعة بعدسة 24mm".
حدّد ما يُستبعد. جملة قصيرة واحدة، مثل "لا يوجد نص في الصورة".
💡 احتفظ بأوامرك النصية في قائمة Python أو في ملف نصي. عندما تفاجئك نتيجة ما، يمكنك تغيير متغير واحد والمقارنة، وهذا أفضل من إعادة الكتابة من الذاكرة.
تحكّم في الحجم ونسبة العرض إلى الارتفاع
يعيش الحجم والشكل داخل قاموس response_format. وهذا يربك كثيرين، لأن الشيفرة القديمة كانت تضع إعدادات الصورة في generation_config.
interaction = client.interactions.create(
model="gemini-3.1-flash-image",
input="A wide photograph of a coastal road at dawn, 35mm lens, film grain",
response_format={
"type": "image",
"mime_type": "image/jpeg",
"aspect_ratio": "16:9",
"image_size": "2K",
},
)
with open("coast.jpg", "wb") as f:
f.write(base64.b64decode(interaction.output_image.data))
بما أن mime_type المطلوب بصيغة JPEG، يحصل الملف على امتداد .jpg. طابق الامتداد مع النوع الذي تطلبه، فلن يشتكي عارض الصور لديك أبدًا.
نسب العرض إلى الارتفاع التي يمكنك طلبها
تسرد وثائق Google عشر نسب: 1:1، 3:2، 2:3، 3:4، 4:3، 4:5، 5:4، 9:16، 16:9، و 21:9.
النسبة
الاستخدام المعتاد
1:1
الصور الشخصية، بطاقات المنتجات
4:5
منشورات الخلاصة في وسائل التواصل
9:16
القصص والصور المصغّرة للفيديو العمودي
16:9
ترويسات المدونات، والصور المصغّرة للفيديو
21:9
اللافتات فائقة العرض
3:2
مطبوعات الصور الكلاسيكية
اختر الدقة
تعتمد قيمة image_size على النموذج. يقدّم Flash Lite 1K فقط. ويقدّم Flash القيم 0.5K و1K و2K و4K. ويقدّم Pro القيم 1K و2K و4K. استخدم K بحرف كبير داخل القيمة.
قاعدة بسيطة تُبقي التكاليف معقولة: 1K للمسودات، و2K لصفحات الويب، و4K للطباعة فقط. تكلّف صورة 4K على Flash مبلغ $0.151 مقابل $0.067 عند 1K، أي نحو 2.25 مرة أكثر، لذا فعادة "الأقصى دائمًا" تتراكم بسرعة.
عدّل صورة بأوامر نصية
تعدّل نقطة النهاية نفسها الصور أيضًا. فبدلًا من سلسلة نصية بسيطة، يصبح input قائمة تخلط كتلًا نصية وكتلًا للصور. تُرسل الصورة كسلسلة base64 مع نوع MIME الخاص بها.
import base64
from google import genai
client = genai.Client()
with open("portrait.png", "rb") as f:
encoded = base64.b64encode(f.read()).decode("utf-8")
interaction = client.interactions.create(
model="gemini-3.1-flash-image",
input=[
{
"type": "text",
"text": "Replace the background with a sunlit brick wall. Keep the person unchanged.",
},
{"type": "image", "data": encoded, "mime_type": "image/png"},
],
)
with open("portrait_edit.png", "wb") as f:
f.write(base64.b64decode(interaction.output_image.data))
لاحظ صياغة أمر التعديل. فهو يذكر ما يتغيّر (الخلفية) وما يبقى (الشخص). ومن دون الجزء الثاني يكون النموذج حرًا في إعادة تصميم الإطار كله.
سلسل التعديلات في محادثة
لا تحتاج إلى إعادة إرسال الصورة مع كل تعديل صغير. مرّر id الخاص بالتفاعل السابق، وسيتذكر النموذج الصورة التي أنشأها للتو:
second = client.interactions.create(
model="gemini-3.1-flash-image",
input="Make the light warmer, like late afternoon.",
previous_interaction_id=interaction.id,
response_format={
"type": "image",
"mime_type": "image/jpeg",
"aspect_ratio": "4:5",
"image_size": "2K",
},
)
حافظ على نفس نسبة العرض إلى الارتفاع كما في الصورة الأولى، وإلا فقد يقصّ النموذج أطراف المشهد أو يمدّه. واحفظ كل interaction.id في قاعدة بياناتك، وستتمكن من الرجوع إلى أي خطوة سابقة في الجلسة، وهذا مفيد في أعمال العملاء حيث يتكرر طلب "ارجع إلى النسخة الثانية" كثيرًا.
اقرأ الاستجابات المختلطة وأضف البحث
يرد النموذج أحيانًا بجملة من النص و صورة. اختصار output_image مناسب للسكربتات البسيطة، لكن دالة مساعدة تمر على قائمة steps تتعامل مع كل الحالات:
def save_outputs(interaction, prefix="gemini", ext="png"):
saved = []
for step in interaction.steps:
if step.type != "model_output":
continue
for block in step.content:
if block.type == "text":
print(block.text)
elif block.type == "image":
path = f"{prefix}_{len(saved) + 1}.{ext}"
with open(path, "wb") as f:
f.write(base64.b64decode(block.data))
saved.append(path)
return saved
تعيد الدالة قائمة بمسارات الملفات. القائمة الفارغة تعني أن النموذج أرسل نصًا فقط، وهذا ليس استثناءً، لذا تحقّق منها قبل أن تفترض وجود ملف.
أسِّس الأوامر النصية على البحث
بعض الصور تعتمد على حقائق تتغير يوميًا: رسم بياني للطقس، أو بطاقة نتائج، أو مخطط أسعار. فعّل Google Search وسيتمكن النموذج من سحب بيانات مباشرة قبل أن يرسم:
interaction = client.interactions.create(
model="gemini-3.1-flash-image",
input="Create an infographic of this week's weather in Chicago",
tools=[{"type": "google_search"}],
generation_config={"thinking_level": "high"},
)
يقبل إعداد thinking_level القيمة "minimal" أو "high". استخدم minimal عندما تكون السرعة مهمة والتخطيط بسيطًا. واستخدم high عندما يطلب الأمر النصي تخطيطًا منظمًا من عدة أجزاء.
💡 كل صورة تعيدها الواجهة تحمل علامة مائية SynthID، وهي علامة غير مرئية تضيفها Google حتى يمكن التعرف على الصورة بوصفها مولّدة بالذكاء الاصطناعي. لا تحتاج إلى إضافة واحدة بنفسك.
عالج الأخطاء قبل الإنتاج
تميل استدعاءات الصور إلى الاستغراق وقتًا أطول من استدعاءات النص، ويمكن لموجات الطلبات المتتالية أن تفعّل حدود المعدل. يجنّبك غلاف صغير لإعادة المحاولة معظم المتاعب. يعيد المحاولة عند رموز HTTP 429 و500 و503، ويزيد زمن الانتظار بعد كل فشل:
import time
def generate_with_retry(prompt, retries=4, **kwargs):
for attempt in range(retries):
try:
return client.interactions.create(
model="gemini-3.1-flash-image",
input=prompt,
**kwargs,
)
except Exception as exc:
status = getattr(exc, "status_code", None) or getattr(exc, "code", None)
if status not in (429, 500, 503) or attempt == retries - 1:
raise
time.sleep(2 ** attempt)
حسب إصدار الحزمة، تظهر حالة HTTP على status_code أو على code، لذا تتحقق الدالة من الاثنين. أي خطأ غير قابل لإعادة المحاولة، مثل طلب سيئ، يُرفع فورًا حتى ترى الرسالة الحقيقية.
لمعالجة قائمة من الأوامر النصية، شغّل عددًا قليلًا منها في وقت واحد:
from multiprocessing.pool import ThreadPool
prompts = ["A bowl of oranges", "A lighthouse at dusk", "A forest road in fog"]
with ThreadPool(4) as pool:
results = pool.map(generate_with_retry, prompts)
ابدأ بأربعة عمال. وإذا استمرت دالة إعادة المحاولة في العمل، فانزل إلى اثنين قبل أن ترفع أي حصة.
تحتاج الأوامر النصية المرفوضة إلى عادة مختلفة. تشير وثائق Google إلى أن إعدادات الأمان المخصصة غير مدعومة في واجهة Interactions API، لذا لا يمكنك تخفيف المرشحات من الشيفرة. عندما ترد استجابة فيها نص دون صورة، سجّل الأمر النصي والنص معًا، ثم أعد كتابة الأمر بوصف أهدأ وأكثر تحديدًا. وإعادة إرسال الأمر نفسه نادرًا ما تغيّر الإجابة، وتهدر الوقت فقط.
3 أخطاء شائعة
استدعاء نموذج متقاعد. أي مقتطف يحتوي gemini-2.5-flash-image يحتاج إلى استبدال سلسلة النموذج بنموذج حالي.
وضع aspect_ratio في generation_config. مكانه في response_format، بجوار image_size.
كتابة سلسلة base64 على القرص. شغّل base64.b64decode() أولًا دائمًا، وإلا فلن يُفتح الملف.
إذا كان لديك لا يزال شيفرة قديمة تستدعي generate_content، فتقول Google إن هذه الواجهة ما زالت مدعومة، وأصبحت مصنّفة بوصفها قديمة (legacy). وبالنسبة للمشاريع الجديدة، فواجهة Interactions API هي التي توصي بها وثائق Google.
راقب التكاليف
تتناسب التكاليف مع الحجم، لذا احسب الأرقام قبل أي حلقة كبيرة. تكلّف خمسمائة صورة بدقة 2K على Flash مبلغ 500 x $0.101، أي $50.50. وتقدم Google أيضًا تسعيرًا جماعيًا بنحو نصف السعر القياسي للمهام التي يمكنها أن تنتظر:
الدقة
القياسي
الجماعي
0.5K
$0.045
$0.022
1K
$0.067
$0.034
2K
$0.101
$0.050
4K
$0.151
$0.076
نفس الصور الـ500 بدقة 2K عبر الدفعات تكلّف نحو $25. وإذا لم ينتظر أحد النتيجة، كتحديث كتالوج ليلي، فالدفعات هي الخيار الأرخص.
استخدم Nano Banana Pro على PicassoIA
ليست كل صورة تحتاج إلى سكربت. إذا أردت اختبار أمر نصي قبل إنفاق رصيد API، أو أردت تسليم المهمة إلى زميل لا يكتب Python، فإن Nano Banana Pro على PicassoIA وسيلة بلا برمجة للحصول على مخرجات تصل إلى 4K من عائلة النماذج نفسها التابعة لـ Google.
اكتب أمرك النصي. استخدم أسلوب قائمة اللقطات نفسه الذي سبق: الشخص أو الموضوع، والضوء، والعدسة.
أضف صور مرجعية (اختياري). يقبل حقل Image Input ما يصل إلى 14 صورة توجّه الأسلوب أو التكوين أو الموضوع.
اختر نسبة العرض إلى الارتفاع. اختر من بين 11 إعدادًا مسبقًا، بما في ذلك 16:9، و 9:16، و 4:5، و 21:9، و match_input_image.
اختر الدقة.1K، أو 2K (الافتراضي)، أو 4K.
اختر الصيغة. JPG (الافتراضي) أو PNG.
اضبط مرشح الأمان.block_only_high هو الافتراضي وهو الأكثر تساهلًا، بينما block_low_and_above هو الأشد صرامة.
ولّد ونزّل. أعد التشغيل بأمر نصي معدّل للمقارنة بين النسخ.
طابق إعدادات API مع حقول الصفحة
إذا جرّبت على الصفحة ثم انتقلت إلى الشيفرة، فالإعدادات تتطابق تقريبًا واحدًا لواحد:
حقل PicassoIA
المكافئ في Python API
الأمر النصي
input (كتلة نصية)
Image Input
input (كتل صور، base64)
aspect_ratio
response_format["aspect_ratio"]
resolution
response_format["image_size"]
output_format
response_format["mime_type"]
تضم عائلة Google على PicassoIA أكثر من نموذج واحد. يتولى Nano Banana التعديلات السريعة، ويركّز Nano Banana 2 Lite على السرعة، بينما يركّز Imagen 4 و Imagen 4 Ultra على التفاصيل الواقعية كالصور الفوتوغرافية. وتشغيل الأمر النصي نفسه عبر اثنين منها يستغرق دقيقة، ويبيّن أي أسلوب يناسب مشروعك قبل أن تكتب سطرًا واحدًا من شيفرة التكامل.
أنشئ صورك الخاصة اليوم
صار لديك كل شيء: تثبيت يعمل، وأول صورة، والتحكم في الحجم والنسبة، والتعديلات، وطريقة آمنة لقراءة المخرجات المختلطة، وغلاف لإعادة المحاولة، وتقدير للتكلفة يمكنك الوثوق به. اختر مهمة صغيرة واحدة، مثل ترويسة مدونة أو بطاقة منتج، ونفّذها من البداية إلى النهاية بعد ظهر اليوم.
إذا كنت تفضل رؤية النتائج قبل أن تلمس الطرفية، فافتح Picasso IA، واختر نموذجًا مثل Nano Banana Pro، واكتب الأمر النصي الذي كتبته للتو لسكربتك. جرّب ثلاث نسخ، وغيّر نسبة العرض إلى الارتفاع، وقارن. وأفضل أمر نصي تجده هناك يدخل مباشرة في شيفرة Python أعلاه.
هذه الحلقة، أي الاختبار على الصفحة ثم الإطلاق في الشيفرة، هي أسرع طريقة لتحديد الشكل النهائي دون دفع ثمن كل تجربة. افتح Picasso IA، وشغّل أول أمر نصي لك، وشاهد ما يمكنك إنشاءه قبل أن ينتهي بعد الظهر.