1. مقدمة
في هذا الدرس التطبيقي حول الترميز، سننشئ GlowUp، وهي أداة لاستعادة الصور. يستخدم تطبيق GlowUp الذكاء الاصطناعي لترميم الصور القديمة أو التالفة أو المعروضة بالأبيض والأسود، وإنشاء صور ملونة عالية الجودة بدقة 4K. يمكنك استخدام هذه الأداة لإضفاء الحيوية على صور عائلتك، أو حتى تكييفها لاستعادة الصور التوضيحية أو الرسومات أو اللوحات أو غيرها من أشكال الصور التالفة.
ستستخدم Genkit Go لتنفيذ منطق التطبيق وGemini 3 Pro Image (المعروف أيضًا باسم Nano Banana Pro) كنموذج لمعالجة الصور.
المتطلبات الأساسية
- معرفة أساسية بلغة Go البرمجية
- معرفة أساسية بوحدة تحكّم Google Cloud
أهداف الدورة التعليمية
- كيفية تطوير تطبيقات Genkit في Go
- مفاهيم Genkit الأساسية، مثل المسارات والمكوّنات الإضافية والطلبات
- كيفية كتابة الطلبات باستخدام نماذج Handlebar
- كيفية الحصول على بيانات الصور من ردود النماذج
المتطلبات
يمكن إجراء ورشة العمل هذه بالكامل ضمن Google Cloud Shell، الذي يتضمّن جميع التبعيات اللازمة (gcloud CLI، وأداة تعديل الرموز، وGo، وGemini CLI) مثبّتة مسبقًا.
بدلاً من ذلك، إذا كنت تفضّل العمل على جهازك الخاص، ستحتاج إلى ما يلي:
- سلسلة أدوات Go (الإصدار 1.24 أو إصدار أحدث)
- Node.js الإصدار 20 أو إصدار أحدث (لأداة
genkitCLI) - وحدة طرفية مثبَّت عليها
gcloudCLI - بيئة تطوير متكاملة لتعديل الرمز البرمجي، مثل VS Code أو ما شابه
- ننصحك باستخدام: وكيل ترميز، مثل Gemini CLI أو Antigravity
التقنيات الرئيسية
يمكنك هنا العثور على مزيد من المعلومات حول التكنولوجيات التي سنستخدمها:
- Gemini Nano Banana Pro (صورة Gemini 3 Pro): النموذج الذي يستند إليه تطبيقنا في عملية استعادة الصور
- Genkit Go: مجموعة الأدوات التي نقدّمها لتنظيم طلبات النماذج
2. إعداد البيئة
اختَر أحد الخيارَين التاليَين: إعداد بيئة ذاتية السرعة إذا كنت تريد تشغيل هذا الدرس التطبيقي حول الترميز على جهازك، أو بدء Cloud Shell إذا كنت تريد تشغيل هذا الدرس التطبيقي حول الترميز بالكامل على السحابة الإلكترونية.
إعداد البيئة بالسرعة التي تناسبك
- سجِّل الدخول إلى Google Cloud Console وأنشِئ مشروعًا جديدًا أو أعِد استخدام مشروع حالي. إذا لم يكن لديك حساب على Gmail أو Google Workspace، عليك إنشاء حساب.



- اسم المشروع هو الاسم المعروض للمشاركين في هذا المشروع. وهي سلسلة أحرف لا تستخدمها Google APIs. ويمكنك تعديلها في أي وقت.
- رقم تعريف المشروع هو معرّف فريد في جميع مشاريع Google Cloud ولا يمكن تغييره بعد ضبطه. تنشئ Cloud Console تلقائيًا سلسلة فريدة، ولا يهمّك عادةً ما هي. في معظم دروس البرمجة، عليك الرجوع إلى رقم تعريف مشروعك (يُشار إليه عادةً باسم
PROJECT_ID). إذا لم يعجبك رقم التعريف الذي تم إنشاؤه، يمكنك إنشاء رقم تعريف عشوائي آخر. يمكنك بدلاً من ذلك تجربة اسم مستخدم من اختيارك ومعرفة ما إذا كان متاحًا. لا يمكن تغيير هذا الخيار بعد هذه الخطوة وسيظل ساريًا طوال مدة المشروع. - للعلم، هناك قيمة ثالثة، وهي رقم المشروع، تستخدمها بعض واجهات برمجة التطبيقات. يمكنك الاطّلاع على مزيد من المعلومات عن كل هذه القيم الثلاث في المستندات.
- بعد ذلك، عليك تفعيل الفوترة في Cloud Console لاستخدام موارد/واجهات برمجة تطبيقات Cloud. لن تكلفك تجربة هذا الدرس التطبيقي حول الترميز الكثير، إن وُجدت أي تكلفة على الإطلاق. لإيقاف الموارد وتجنُّب تحمّل تكاليف تتجاوز هذا البرنامج التعليمي، يمكنك حذف الموارد التي أنشأتها أو حذف المشروع. يمكن لمستخدمي Google Cloud الجدد الاستفادة من برنامج الفترة التجريبية المجانية بقيمة 300 دولار أمريكي.
بدء Cloud Shell
على الرغم من إمكانية تشغيل Google Cloud عن بُعد من الكمبيوتر المحمول، ستستخدم في هذا الدرس العملي Google Cloud Shell، وهي بيئة سطر أوامر تعمل في السحابة الإلكترونية.
من Google Cloud Console، انقر على رمز Cloud Shell في شريط الأدوات أعلى يسار الصفحة:

لن يستغرق توفير البيئة والاتصال بها سوى بضع لحظات. عند الانتهاء، من المفترض أن يظهر لك ما يلي:

يتم تحميل هذه الآلة الافتراضية مزوّدة بكل أدوات التطوير التي ستحتاج إليها. توفّر هذه الخدمة دليلًا منزليًا ثابتًا بسعة 5 غيغابايت، وتعمل على Google Cloud، ما يؤدي إلى تحسين أداء الشبكة والمصادقة بشكل كبير. يمكن إكمال جميع المهام في هذا الدرس العملي ضمن المتصفّح. لست بحاجة إلى تثبيت أي تطبيق.
3- إعداد المشروع
إنشاء المشروع
أولاً، علينا إنشاء دليل جديد لمشروعك وتهيئة وحدة Go. في الوحدة الطرفية، شغِّل الأوامر التالية:
mkdir -p glowup && cd glowup
go mod init glowup
تثبيت Genkit CLI
الآن، علينا تثبيت Genkit CLI. يمنحك ذلك إمكانية الوصول إلى أدوات المطوّرين المحلية، بما في ذلك واجهة مستخدم المطوّرين. في نافذة المحطة الطرفية، اكتب ما يلي:
curl -sL cli.genkit.dev | bash
ضبط متغيرات البيئة
تأكَّد من إعداد بيانات اعتماد Google Cloud الصحيحة. استبدِل your-project-id برقم تعريف مشروعك الفعلي. يجب أن يكون الموقع الجغرافي global عند استخدام نماذج "النسخة الحصرية" من Gemini 3 Pro (أحدها هو Nano Banana Pro).
export GOOGLE_CLOUD_PROJECT=$(gcloud config get project)
export GOOGLE_CLOUD_LOCATION=global
نفِّذ الأمر التالي في وضع shell لتفعيل Vertex AI API:
gcloud services enable aiplatform.googleapis.com
إذا كنت تنفّذ الأمر من جهازك المحلي (وليس على CloudShell)، عليك المصادقة باستخدام أمر gcloud:
gcloud auth application-default login
4. إنشاء تطبيق Genkit الأول
Genkit هو إطار عمل مفتوح المصدر مصمَّم لمساعدة المطوّرين في إنشاء تطبيقات مستنِدة إلى الذكاء الاصطناعي وجاهزة للإنتاج ونشرها ومراقبتها. في هذا القسم، سننشئ تطبيقًا بسيطًا باسم "Hello World" لمساعدتك في التعرّف على إطار العمل قبل أن نتعمّق في منطق استعادة الصور.
مصطلحات Genkit
قبل البدء في استخدام Genkit، من المهم فهم بعض المصطلحات الأساسية:
- المكوّنات الإضافية: تُستخدَم لتوسيع إمكانات Genkit. ومن خلال المكوّنات الإضافية، يمكنك تسجيل نماذج الذكاء الاصطناعي لتشغيل تطبيقك.
- عمليات التنفيذ: هي المكوّن المعماري الرئيسي في Genkit. تتلقّى العملية النموذجية إدخالاً وتعالجه وتعرض إخراجًا. لا يتطلّب ذلك بالضرورة استخدام نموذج، ولكن في معظم الأحيان ستستخدم نماذج داخل تدفقاتك.
- الطلبات: نماذج التفاعل المخزّنة بتنسيق dotprompt (المحفوظة كملفات
*.prompt). لا تحتوي هذه الملفات على تعليمات النموذج فحسب، بل تحتوي أيضًا على إعدادات مثل اسم النموذج ومعلَمات النموذج والمدخلات والمخرجات.
التواصل مع نماذج الذكاء الاصطناعي
يستخدم Genkit المكوّنات الإضافية لربط الرمز بمزوّدي النماذج. تتوفّر مكوّنات إضافية لجميع موفّري النماذج الرئيسيين، بما في ذلك Google وAnthropic وOpenAI. يمكنك أيضًا استخدام المكوّنات الإضافية للاتصال بنماذج محلية (مثل استخدام Ollama) أو لتوسيع إمكانات Genkit (مثل الاتصال بخوادم MCP).
للوصول إلى نماذج Google، عليك استخدام المكوّن الإضافي googlegenai. تتوافق مع نظامَي خلفية:
- Google AI: الأفضل لإنشاء نماذج أوّلية يستخدم مفتاح واجهة برمجة تطبيقات.
- Vertex AI (Google Cloud): يُنصح باستخدامه في مرحلة الإنتاج. يستخدم رقم تعريف المشروع والموقع الجغرافي.
في هذا الدرس التطبيقي حول الترميز، سنستخدم مصادقة Vertex AI بالإشارة إلى المشروع الذي أنشأته في بداية الدرس.
إنشاء سير عمل لرسالة ترحيب
قبل التعمّق في مسار استعادة الصور باستخدام Glow Up، لننشئ مسارًا أساسيًا للتعرّف على المفاهيم والتأكّد من أنّ عملية الإعداد تعمل بشكلٍ سليم.
التدفّق هو دالة خاصة في Genkit تعمل على تضمين منطق الذكاء الاصطناعي لتقديم ما يلي:
- عمليات إدخال وإخراج آمنة من حيث النوع: تحديد المخططات باستخدام بنى Go للتحقّق الثابت وفي وقت التشغيل
- إتاحة البث: بث ردود جزئية أو بيانات مخصّصة
- دمج واجهة مستخدم المطوّرين: اختبار مسارات التصحيح وتصحيح الأخطاء باستخدام عمليات التتبُّع المرئية
- سهولة النشر: يمكن نشرها كنقاط نهاية HTTP على أي منصة
افتح بيئة التطوير المتكاملة (IDE) وأنشئ ملف main.go في دليل مشروعك. في حال استخدام Cloud Shell، يمكنك استخدام الأمر التالي:
cloudshell edit main.go
بعد ذلك، أضِف الرمز التالي:
main.go
package main
import (
"context"
"log"
"os"
"os/signal"
"syscall"
"github.com/firebase/genkit/go/genkit"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/plugins/googlegenai"
)
func main() {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
// Initialize Genkit with the Vertex AI plugin
g := genkit.Init(ctx,
genkit.WithPlugins(&googlegenai.VertexAI{}),
)
// Define the greeter flow
genkit.DefineFlow(g, "greeter", func(ctx context.Context, name string) (string, error) {
text, err := genkit.GenerateText(ctx, g,
ai.WithModelName("vertexai/gemini-2.5-pro"),
ai.WithPrompt("Say a warm and creative hello to %s", name),
)
if err != nil {
return "", err
}
return text, nil
})
// Register the flow here in the next steps
log.Println("GlowUp initialized. Ready for flows.")
<-ctx.Done()
}
احفظ الملف ثم شغِّل go mod tidy لتعديل التبعيات:
go mod tidy
تعمل التعليمة البرمجية أعلاه على تهيئة Genkit باستخدام مكوّن VertexAI الإضافي، وتحديد مسار باسم "greeter"، ثم الانتظار إلى الأبد على <-ctx.Done(). نحن نوقف التنفيذ مؤقتًا حتى لا يتوقف هذا البرنامج على الفور، لأنّنا لا نعطيه أي تعليمات لتنفيذ التسلسل فعليًا.
وهذا يعني أنّه إذا شغّلت هذا البرنامج كما هو الآن، لن يفعل الكثير من تلقاء نفسه، بل علينا استدعاء المسار بطريقة ما. في تطبيق إنتاج حقيقي، سنضمّن هذا المسار في خادم ويب أو تطبيق واجهة سطر أوامر، ولكن أثناء التطوير، يمكننا استخدام واجهة سطر الأوامر genkit لمساعدتنا في تطوير المسار وتحسينه.
تم تطوير واجهة سطر الأوامر genkit لمساعدتنا في اختبار النماذج والطلبات والتدفقات والمكوّنات الأخرى في حزمة Genkit. يتوافق أيضًا بشكل كامل مع عمليات التتبُّع، ما يسهّل عليك فهم طريقة عمل التطبيق. لتشغيل مسار الترحيب باستخدام واجهة سطر الأوامر genkit، نفِّذ الأمر التالي:
genkit start -- go run main.go
سيؤدي ذلك إلى تشغيل نقاط نهاية Telemetry API وDeveloper UI. ينبغي أن تظهر لك على النحو التالي:
$ genkit start -- go run main.go Telemetry API running on http://localhost:4033 Project root: /home/daniela/glowup Genkit Developer UI: http://localhost:4000
إذا فتحت localhost:4000 على المتصفّح لتشغيل Dev-UI. من المفترض أن تظهر لك شاشة على النحو التالي:

خصِّص وقتًا كافيًا لاستكشاف واجهة مستخدم المطوّرين. يمكنك تشغيل مسار "المرحّب" مرة واحدة فقط لمعرفة طريقة عمله.
استخدام نماذج الطلبات
مع أنّه يمكنك ترميز طلباتك بشكل ثابت في استدعاءات النماذج كما فعلنا في المثال السابق، إلا أنّ الأسلوب الأفضل هو إنشاء نماذج طلبات لتخزين جميع طلبات تطبيقك بطريقة مركزية. لا يسهّل ذلك العثور عليها عند إجراء صيانة للرمز البرمجي فحسب، بل يتيح لك أيضًا تجربة الطلبات بشكل مستقل عن مسارات العمل.
لتحديد نماذج الطلبات، يستخدم Genkit تنسيق dotprompt المفتوح المصدر، ويتم حفظه كملفات *.prompt. يتألف ملف .prompt من جزأين:
- Frontmatter: هي مجموعة من البيانات بتنسيق YAML تحدّد النموذج ومعاملات النموذج ومخططَي الإدخال والإخراج.
- النص الأساسي: نص الطلب نفسه، ويمكن إنشاء نموذج له باستخدام بنية "handlebars". على سبيل المثال، إذا حدّدت إدخالاً باسم
variable-name، يمكنك الرجوع إليه في النص الأساسي كـ{{variable-name}}.
ستبدو بنية الدليل الخاص بالمشروع على النحو التالي:
glowup/
├── main.go
└── prompts/
└── greeter.prompt
لِنطّلع على مثال عملي على ذلك. أنشئ أولاً المجلد لتخزين الطلبات:
mkdir -p prompts
بعد ذلك، أنشِئ ملف greeter.prompt باتّباع الخطوات التالية:
cloudshell edit prompts/greeter.prompt
وأدرِج المحتوى التالي:
greeter.prompt

يعرض هذا الطلب بعض ميزات لغة النموذج. أولاً، نحدّد النموذج vertexai/gemini-2.5-flash في المقدمة. لتحديد نموذج، عليك استخدام التسمية المحدّدة في مستندات المكوّن الإضافي المعنيّ.
يتيح لنا قسم الإعدادات ضبط مَعلمات النموذج. نستخدم درجة العشوائية 1.9 للسماح للنموذج بأن يكون أكثر إبداعًا. تتراوح درجة العشوائية بين 0 (نتائج أكثر اتساقًا) و2 (نتائج أكثر إبداعًا). عادةً ما يتم نشر هذه المعلمة وغيرها من معلمات النموذج في ورقة نموذج النموذج. على سبيل المثال، إليك ورقة نموذج gemini-2.5-flash.
يتيح لنا قسم الإدخال تحديد وسيطات للطلب. في هذه الحالة، نحدّد الاسم كسلسلة. بعد المقدمة، لدينا نص الطلب. يحدّد المربّع الأول هنا طلب النظام، بينما يحدّد المربّع الثاني طلب المستخدم. تتيح كل هذه العناصر معًا بعض تقنيات الطلبات الفعّالة جدًا. يمكنك الاطّلاع على المستندات الكاملة حول dotprompt هنا.
الآن، لنعدّل مسار greeter لاستخدام الطلب الذي أنشأناه للتو:
main.go
package main
import (
"context"
"os"
"os/signal"
"syscall"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
"github.com/firebase/genkit/go/plugins/googlegenai"
)
func main() {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
// Initialize Genkit with the Vertex AI plugin
g := genkit.Init(ctx,
genkit.WithPlugins(&googlegenai.VertexAI{}),
genkit.WithDefaultModel("vertexai/gemini-2.5-flash"),
)
// Define the greeter flow
genkit.DefineFlow(g, "greeter", func(ctx context.Context, name *string) (string, error) {
prompt := genkit.LookupPrompt(g, "greeter")
input := map[string]any{
"name": name,
}
resp, err := prompt.Execute(ctx, ai.WithInput(input))
if err != nil {
return "", err
}
return resp.Text(), nil
})
<-ctx.Done()
}
جرِّب تشغيل سير العمل من سطر الأوامر، مع اسم وبدونه، لمعرفة الفرق. التشغيل بدون اسم:
genkit flow:run greeter
مثال على الناتج:
$ genkit flow:run greeter Telemetry API running on http://localhost:4035 Running '/flow/greeter' (stream=false)... Result: "Hello there, absolutely delightful human!\n\nThe very moment your message arrived, the day instantly sparkled a little brighter. It's not just nice, it's genuinely **wonderful** to meet you!\n\nMay your entire day be filled with unexpected pockets of joy, effortless triumphs, and all the happiness you truly deserve! We're thrilled to have you here!"
مع اسم:
genkit flow:run greeter '{"name":"Daniela"}'
مثال على الناتج:
$ genkit flow:run greeter '{"name":"Daniela"}'
Telemetry API running on http://localhost:4035
Running '/flow/greeter' (stream=false)...
Result:
"Well hello there, Daniela! What a truly beautiful name, and what an absolute pleasure it is to meet you!\n\nRight from this moment, I just know your day is going to be brimming with positive energy and wonderful surprises. May it be filled with brilliant ideas, joyful moments, and the delightful realization that you're an amazing person doing incredible things. So glad you're here!"
يمكنك ملاحظة أنّ النموذج عمل على النحو المتوقّع. نحن على استعداد للارتقاء بهذا المشروع إلى المستوى التالي.
5- استعادة الصور باستخدام Nano Banana Pro
طلب الاستعادة
بعد أن تعرّفت على اللبنات الأساسية في Genkit، حان الوقت لإنشاء طلب استعادة الصور.
أنشئ ملفًا باسم glowup.prompt في دليل الطلبات، والصِق فيه المحتوى التالي:
glowup.prompt

يتّبع طلب الاستعادة النمط نفسه الذي يتّبعه طلب "الترحيب"، مع بعض الاختلافات الملحوظة فقط:
- حجم الصورة: السمة
imageSizeالخاصة بـimageConfigهي مَعلم خاص بنموذج Nano Banana Pro. يتيح لنا تحديد حجم الإخراج على أنّه 1K أو 2K أو 4K. - إدخال الوسائط: نحن نستخدم النموذج
{{ media }}لإدراج الصورة في طلب المستخدم. تتيح لنا هذه التقنية إرسال طلبات متعددة الوسائط إلى النموذج (نص + صورة).
يمكنك اختبار هذا الطلب على واجهة مستخدم المطوّرين. يمكنك تعديلها لمعرفة تأثيرها في الناتج.
مسار استعادة الصورة
بعد أن أصبح طلب الاستعادة جاهزًا، لننشئ الآن تطبيق واجهة سطر الأوامر. استبدِل محتوى main.go بالرمز البرمجي أدناه:
main.go
package main
import (
"context"
"encoding/base64"
"errors"
"flag"
"fmt"
"log"
"mime"
"os"
"os/signal"
"strings"
"syscall"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
"github.com/firebase/genkit/go/plugins/googlegenai"
)
func main() {
url := flag.String("url", "", "url of the image to restore")
contentType := flag.String("contentType", "image/jpeg", "content type of the image (default: image/jpeg)")
flag.Parse()
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
// Initialize Genkit with the Vertex AI plugin
g := genkit.Init(ctx,
genkit.WithPlugins(&googlegenai.VertexAI{}),
)
// Input schema for the glowUp flow
type Input struct {
URL string `json:"url,omitempty"`
ContentType string `json:"contentType,omitempty"`
}
glowup := genkit.DefineFlow(g, "glowUp", func(ctx context.Context, input Input) (string, error) {
// 1. Retrieve prompt
prompt := genkit.LookupPrompt(g, "glowup")
if prompt == nil {
return "", errors.New("prompt 'glowup' not found")
}
resp, err := prompt.Execute(ctx, ai.WithInput(input))
if err != nil {
return "", fmt.Errorf("generation failed: %w", err)
}
return resp.Media(), nil
})
// triggers the flow and returns the encoded response from the model
out, err := glowup.Run(ctx, Input{URL: *url, ContentType: *contentType})
if err != nil {
log.Fatalln(err)
}
// decodes image data and returns the appropriate file extension
data, ext, err := decode(out)
if err != nil {
log.Fatalln(err)
}
// writes restored file to disk
filename := "restored" + ext
if err := os.WriteFile(filename, data, 0644); err != nil {
log.Fatalln(err)
}
}
// decode returns the decoded data and the file extension appropriate for the mime type
func decode(text string) ([]byte, string, error) {
if !strings.HasPrefix(text, "data:") {
return nil, "", errors.New("unsupported enconding format")
}
text = strings.TrimPrefix(text, "data:")
parts := strings.Split(text, ";base64,")
mimeType := parts[0]
decoded, err := base64.StdEncoding.DecodeString(parts[1])
if err != nil {
return nil, "", err
}
ext, err := mime.ExtensionsByType(mimeType)
if err != nil {
return nil, "", err
}
return decoded, ext[0], nil
}
يشبه الرمز البرمجي إلى حد كبير بنية مسار greeter، ولكن تم تعديله هذه المرة ليعمل كتطبيق مستقل لواجهة سطر الأوامر. بدلاً من الحظر نهائيًا، سيتم تنفيذ عملية glowUp وفك ترميز الناتج وحفظ البيانات الثنائية الناتجة على القرص.
علينا فك ترميز الناتج لأنّ النموذج يعرض بيانات الصورة بالتنسيق التالي:
data:<mime type>;base64,<base64 encoded image>
يمكنك أن ترى في الدالة decode أنّنا نستخدم معالجة السلسلة لتقسيم نوع MIME وأجزاء الصورة المشفرة. بعد ذلك، نستخدم الدالتَين mime.ExtensionByType وbase64.DecodeString لاستخراج المعلومات التي نحتاجها لحفظ الملف.
اختبار مسار الاستعادة
حان الوقت الآن لتنفيذ هذا المسار باستخدام صورة حقيقية. إذا لم تكن لديك أي صور قديمة بحاجة إلى بعض الترميم، يمكنك تجربة هذه الصورة المتاحة للجميع والتي تم استرجاعها من موقع مكتبة الكونغرس الإلكتروني:

إليك الرابط المباشر إلى الصورة الفوتوغرافية لتمريرها إلى المسار: https://tile.loc.gov/storage-services/service/pnp/fsa/8c01000/8c01700/8c01765v.jpg
export IMAGE_URL="https://tile.loc.gov/storage-services/service/pnp/fsa/8c01000/8c01700/8c01765v.jpg"
go run main.go --url $IMAGE_URL
إليك الصورة التي تم تجديدها وتلوينها:

اكتمال النقل بنجاح
6. نشر glowUp كخدمة ويب
إذا كنت تريد عرض مساراتك في خدمة ويب بدلاً من تطبيق سطر أوامر، يوفّر Genkit طريقة سهلة لتحويل المسارات إلى نقاط نهاية باستخدام محوّل genkit.Handler. يسجّل الرمز البرمجي أدناه عملية glowUp كنقطة نهاية glowUp باستخدام genkit.Handler.
يمكنك عرضها باستخدام خادم HTTP عادي كما تفعل عادةً باستخدام حزمة http من المكتبة العادية، ولكن يوفّر Genkit أيضًا مكوّنًا إضافيًا server يساعد في بعض التعليمات البرمجية الشائعة للخادم، مثل التعامل مع إشارات الإيقاف بشكل سليم.
استبدِل محتوى main.go بالرمز أدناه لإنشاء خادم الويب.
package main
import (
"context"
"errors"
"fmt"
"log"
"net/http"
"os"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
"github.com/firebase/genkit/go/plugins/googlegenai"
"github.com/firebase/genkit/go/plugins/server"
)
func main() {
ctx := context.Background()
PORT := os.Getenv("PORT")
if PORT == "" {
PORT = "8080"
}
listenAddr := ":" + PORT
// Initialize Genkit with the Vertex AI plugin
g := genkit.Init(ctx,
genkit.WithPlugins(&googlegenai.VertexAI{}),
)
// Input schema for the glowUp flow
type Input struct {
URL string `json:"url,omitempty"`
ContentType string `json:"contentType,omitempty"`
}
genkit.DefineFlow(g, "glowUp", func(ctx context.Context, input Input) (string, error) {
prompt := genkit.LookupPrompt(g, "glowup")
if prompt == nil {
return "", errors.New("prompt 'glowup' not found")
}
resp, err := prompt.Execute(ctx, ai.WithInput(input))
if err != nil {
return "", fmt.Errorf("generation failed: %w", err)
}
return resp.Media(), nil
})
log.Printf("GlowUp Flow Server started. Listening on %s", listenAddr)
mux := http.NewServeMux()
for _, flow := range genkit.ListFlows(g) {
mux.HandleFunc("POST /"+flow.Name(), genkit.Handler(flow))
}
if err := server.Start(ctx, listenAddr, mux); err != nil {
// Check if the error is due to context cancellation
if ctx.Err() != nil {
log.Println("GlowUp server shutting down gracefully...")
return
}
log.Fatal(err)
}
}
يمكنك تشغيل هذه الخدمة على الجهاز أو في السحابة الإلكترونية. لتشغيل التطبيق محليًا، يمكنك تشغيل الملف مباشرةً لأنّ البرنامج أصبح الآن كاملاً، وبالتالي لن نحتاج إلى تشغيله من خلال واجهة سطر الأوامر في Genkit. على سبيل المثال:
go run main.go
بما أنّ هذه العملية تحظر تنفيذ عمليات أخرى، عليك فتح نافذة Terminal ثانية لاختبارها. أسرع طريقة هي استخدام الأمر curl:
curl -sS -X POST http://localhost:8080/glowUp \
-H "Content-Type: application/json" \
-d '{"data":{"url": $IMAGE_URL, "contentType":"image/jpeg"}}' \
> result.json
بما أنّ هذه استجابة من الخادم، علينا فك تشفير صورة base64:
cat result.json | jq -r '.result' | awk -F ',' '{print $2}' | base64 -d > restored.png
نشر خدمة الويب على Cloud Run
لا بأس في أن يعمل هذا الخادم "على جهازي"، ولكن في الحالة المثالية، سننشره في مكان آخر يمكن لجميع المستخدمين الوصول إليه. من أسهل الطرق لنشر خدمات مثل هذه هي استخدام ميزة "النشر من المصدر" في Cloud Run. باستخدام هذه الميزة، لن تحتاج حتى إلى إنشاء الحاوية بنفسك، لأنّ كل شيء يتم تلقائيًا.
لنشر هذه الخدمة على Cloud Run باستخدام النشر من المصدر، نفِّذ الأمر التالي (استبدِل رقم تعريف المشروع برقم التعريف الخاص بك):
gcloud run deploy glowup --source . --region us-central1 --no-allow-unauthenticated --set-env-vars GOOGLE_GENAI_USE_VERTEXAI=True,GOOGLE_CLOUD_LOCATION=$GOOGLE_CLOUD_LOCATION,GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT
قد يستغرق إكمال عملية النشر بضع دقائق. بعد الانتهاء، يمكنك اختبار نقطة النهاية من خلال إرسال طلب آخر عبر curl:
GLOWUP_URL=$(gcloud run services describe glowup --region us-central1 --format='value(status.url)')
curl -X POST "$GLOWUP_URL/glowUp" \
-H "Authorization: Bearer $(gcloud auth print-identity-token)" \
-H "Content-Type: application/json" \
-d "{\"data\":{\"url\":\"$IMAGE_URL\", \"contentType\":\"image/jpeg\"} }" \
> result.json
مرة أخرى، علينا فك ترميز صورة base64:
cat result.json | jq -r '.result' | awk -F ',' '{print $2}' | base64 -d > restored_cloudrun.png
أصبح لدينا الآن خادم ويب يعمل بكامل طاقته لاستعادة الصور.
اختياري: "البرمجة الوصفية" لتطبيق عميل
كتابة الرموز يدويًا أمر ممتع، ولكنّه قد يكون صعبًا أيضًا إذا لم يسبق لك تنفيذ نوع معيّن من المشاريع. لحسن الحظ، لدينا اليوم وكلاء ترميز يمكنهم مساعدتنا في تسريع العملية.
في هذه الخطوة، بدلاً من كتابة الرمز بأنفسنا، سنطلب من Gemini CLI (أو وكيل الترميز المفضّل لديك) تنفيذ المهمة نيابةً عنا. استخدِم الطلب التالي:
GlowUp is a photo restoration service that takes a restoration request as input and returns a restored picture as output. Your task is to create a client application that uses this server to process image urls and save a restored file locally.
TODO:
- Write a CLI application that receives three arguments: an url (required), content type (optional, defaults to image/jpeg) and addr (server address, optional, defaults to localhost:8080)
- The CLI should send a POST request to the /glowUp endpoint in the server with the body '{"data":{"url": <url>, "contentType": <contentType>} }'
- The server response should be parsed by stripping the "data:" prefix. The remainder will have the format <mimeType>;base64,<encoded imageData>
- Extract the mime type and convert to a file extension using the mime package
- Extract the image data and decode it using the base64 package
Save a file named "restored" + the detected file extension
Acceptance Criteria:
- The client builds successfully
- Use the client to restore the image https://tile.loc.gov/storage-services/service/pnp/fsa/8c01000/8c01700/8c01765v.jpg
- Check that restored.png exists after processing the image above
قد يحتاج الوكيل إلى إعادة ترتيب الملفات قليلاً لأنّه لا يمكن أن تتضمّن الوحدة نفسها وظيفتَين باسم "main". شاهِدها وهي تعمل ووجِّهها نحو التنفيذ الصحيح من خلال تزويدها برمز الخادم أو المقتطفات إذا لزم الأمر.
التنظيف بعد انتهاء التجربة
7. الخاتمة
تهانينا! لقد أنشأت بنجاح تطبيقًا عالي الدقة لاستعادة الصور باستخدام Genkit وNano Banana Pro.
في هذا الدرس العملي، تعلّمت كيفية:
- ضبط بيئتك لتطوير تطبيقات Genkit Go
- إنشاء طلبات متعددة الوسائط باستخدام
dotprompt - إنشاء تدفّقات Genkit باستخدام نماذج الطلبات
- استخدام Nano Banana Pro لمعالجة الصور
- تعبئة مسارات Genkit كتطبيقات سطر أوامر وخدمات ويب
- نشر تطبيقات Genkit على Cloud Run
بعد الانتهاء من الاختبار، تذكَّر تنظيف البيئة.
الخطوات التالية
يمكنك مواصلة رحلة التعلّم من خلال استكشاف دروس تطبيقية أخرى حول الترميز في هذه المنصة، أو إجراء تحسينات على تطبيق glowUp بنفسك.
إذا كنت بحاجة إلى بعض الأفكار لتحسين الأداء، يمكنك تجربة ما يلي:
- تفعيل واجهة سطر الأوامر glowUp لاستعادة الملفات المخزَّنة على الجهاز
- إنشاء واجهة أمامية لخدمة GlowUp على الويب
- الرصد التلقائي لنوع MIME من البيانات
- إجراء أنواع أخرى من معالجة الصور (من صورة إلى رسم، ومن رسم إلى صورة، ومن رسم تخطيطي إلى عمل فني نهائي، وما إلى ذلك)
- إنشاء أو تحسين العميل (ربما إنشاء تطبيق على الهاتف الذكي؟)
الخيارات لا تحصى. إذا كنت تشعر بالقلق بشأن فكرة العمل بمفردك، يمكنك الاستعانة بأحد وكلاء الترميز، مثل Gemini CLI أو Antigravity. إذا أردت الاستفادة من المزيد من الميزات في Genkit، يمكن أن تسهّل عليك كثيرًا استخدام وكلاء الترميز مع خادم Genkit MCP.
أخيرًا، إذا أردت الوصول إلى الرمز الكامل لهذا المستودع، يمكنك العثور عليه هنا.
نتمنى لك التوفيق في الترميز.