
مختبر أبحاث أمني يعيد إنتاج CVE-2023-6572 (GHSA-gqvf-3hgp-5hxv): حقن أوامر في معالجة workflow_run لتطبيق gradio-app/gradio لملف generate-changeset.yml
أداة بحث آلية — ليست المشروع الأصلي.
هذا المستودع هو مختبر مؤقت تم بناؤه بواسطة نظام آلي لأطروحة ماجستير في جامعة لافال حول إعادة إنتاج ثغرات سير عمل GitHub Actions المنشورة. وهو لقطة حرفية من
gradio-app/gradioعند الالتزام1d986217f6f4fc1829e528d2afe365635788204f(2023-11-03)، معاد توزيعه بموجب ترخيص المشروع الأصلي نفسه، الذي تم تضمين ملفه دون تغيير في هذه اللقطة.المشروع الأصلي ليس مشاركًا، ولا يُستهدف أبدًا، والثغرة المدروسة هنا معلنة بالفعل. كل سر ومتغير في هذا المستودع هو قيمة وهمية مولدة عشوائيًا — لا توجد أي بيانات اعتماد حقيقية. مراجع الإجراءات وصور المشغلات مثبتة على ما تم حله في 2023-11-03؛ راجع
pinning.mdفي مخرجات النظام الآلي لكل تغيير تم إجراؤه على اللقطة.الأسئلة أو الاعتراضات: [email protected]
Gradio هي مكتبة Python مفتوحة المصدر تُستخدم لبناء عروض توضيحية وتطبيقات ويب للتعلم الآلي وعلوم البيانات.
باستخدام Gradio، يمكنك بسرعة إنشاء واجهة مستخدم جميلة حول نماذج التعلم الآلي أو سير عمل علوم البيانات الخاصة بك والسماح للأشخاص "بتجربتها" عن طريق سحب وإفلات صورهم الخاصة، ولصق النصوص، وتسجيل أصواتهم، والتفاعل مع العرض التوضيحي الخاص بك، كل ذلك من خلال المتصفح.

Gradio مفيد من أجل:
عرض نماذج التعلم الآلي الخاصة بك للعملاء/المتعاونين/المستخدمين/الطلاب.
نشر نماذجك بسرعة مع روابط قابلة للمشاركة تلقائيًا والحصول على ملاحظات حول أداء النموذج.
تصحيح أخطاء نموذجك بشكل تفاعلي أثناء التطوير باستخدام أدوات معالجة الإدخال المدمجة.
المتطلب الأساسي: يتطلب Gradio Python 3.8 أو أعلى، هذا كل شيء!
من أفضل الطرق لمشاركة نموذج التعلم الآلي أو API أو سير عمل علوم البيانات الخاص بك مع الآخرين هو إنشاء تطبيق تفاعلي يسمح لمستخدميك أو زملائك بتجربة العرض التوضيحي في متصفحاتهم.
يتيح لك Gradio بناء العروض التوضيحية ومشاركتها، كل ذلك في Python. وعادةً في بضعة أسطر فقط من التعليمات البرمجية! لذا دعنا نبدأ.
لتشغيل Gradio بمثال بسيط "Hello, World"، اتبع هذه الخطوات الثلاث:
1. قم بتثبيت Gradio باستخدام pip:
pip install gradio
2. قم بتشغيل الكود أدناه كسكربت Python أو في Jupyter Notebook (أو Google Colab):
import gradio as gr
def greet(name):
return "Hello " + name + "!"
demo = gr.Interface(fn=greet, inputs="text", outputs="text")
demo.launch()
نختصر الاسم المستورد إلى gr لتحسين قابلية قراءة الكود باستخدام Gradio. هذه اصطلاح معتمد على نطاق واسع يجب عليك اتباعه حتى يتمكن أي شخص يعمل مع الكود الخاص بك من فهمه بسهولة.
3. سيظهر العرض التوضيحي أدناه تلقائيًا داخل Jupyter Notebook، أو في متصفح على http://localhost:7860 إذا تم تشغيله من سكربت:

عند التطوير محليًا، إذا كنت تريد تشغيل الكود كسكربت Python، يمكنك استخدام واجهة سطر الأوامر Gradio CLI لتشغيل التطبيق في وضع إعادة التحميل، والذي سيوفر تطويرًا سلسًا وسريعًا. تعرف على المزيد حول إعادة التحميل في دليل إعادة التحميل التلقائي.
gradio app.py
ملاحظة: يمكنك أيضًا تنفيذ python app.py، لكنه لن يوفر آلية إعادة التحميل التلقائية.
Interfaceستلاحظ أنه من أجل إنشاء العرض التوضيحي، قمنا بإنشاء gr.Interface. يمكن لهذه الفئة Interface تغليف أي دالة Python بواجهة مستخدم. في المثال أعلاه، رأينا دالة نصية بسيطة، لكن الدالة يمكن أن تكون أي شيء من مولّد موسيقى إلى حاسبة ضرائب إلى دالة التنبؤ لنموذج تعلم آلي مُدرّب مسبقًا.
يتم تهيئة فئة Interface الأساسية بثلاث معاملات مطلوبة:
fn: الدالة التي سيتم تغليف واجهة مستخدم حولهاinputs: المكون(ات) التي سيتم استخدامها للإدخال (مثل "text" أو "image" أو "audio")outputs: المكون(ات) التي سيتم استخدامها للإخراج (مثل "text" أو "image" أو "label")دعنا نلقي نظرة أقرب على هذه المكونات المستخدمة لتوفير الإدخال والإخراج.
رأينا بعض مكونات Textbox البسيطة في الأمثلة السابقة، ولكن ماذا لو أردت تغيير شكل أو سلوك مكونات واجهة المستخدم؟
لنفترض أنك تريد تخصيص حقل إدخال النص — على سبيل المثال، تريده أكبر حجمًا وأن يحتوي على نص placeholder. إذا استخدمنا الفئة الفعلية لـ Textbox بدلاً من استخدام الاختصار النصي، فستتمكن من الوصول إلى تخصيص أكبر بكثير من خلال خصائص المكونات.
import gradio as gr
def greet(name):
return "Hello " + name + "!"
demo = gr.Interface(
fn=greet,
inputs=gr.Textbox(lines=2, placeholder="Name Here..."),
outputs="text",
)
demo.launch()

لنفترض أن لديك دالة أكثر تعقيدًا، مع مدخلات ومخرجات متعددة. في المثال أدناه، نعرّف دالة تأخذ سلسلة نصية وقيمة منطقية ورقمًا، وتُرجع سلسلة نصية ورقمًا. لاحظ كيف تمرر قائمة من مكونات الإدخال والإخراج.
import gradio as gr
def greet(name, is_morning, temperature):
salutation = "Good morning" if is_morning else "Good evening"
greeting = f"{salutation} {name}. It is {temperature} degrees today"
celsius = (temperature - 32) * 5 / 9
return greeting, round(celsius, 2)
demo = gr.Interface(
fn=greet,
inputs=["text", "checkbox", gr.Slider(0, 100)],
outputs=["text", "number"],
)
demo.launch()

كل ما عليك فعله هو تغليف المكونات في قائمة. كل مكون في قائمة inputs يتوافق مع أحد معاملات الدالة، بالترتيب. كل مكون في قائمة outputs يتوافق مع إحدى القيم التي تُرجعها الدالة، أيضًا بالترتيب.
يدعم Gradio أنواعًا عديدة من المكونات، مثل Image وDataFrame وVideo أو Label. لنجرب دالة تحويل صورة إلى صورة لنشعر بهذه المكونات!
import numpy as np
import gradio as gr
def sepia(input_img):
sepia_filter = np.array([
[0.393, 0.769, 0.189],
[0.349, 0.686, 0.168],
[0.272, 0.534, 0.131]
])
sepia_img = input_img.dot(sepia_filter.T)
sepia_img /= sepia_img.max()
return sepia_img
demo = gr.Interface(sepia, gr.Image(width=200, height=200), "image")
demo.launch()

عند استخدام مكون Image كإدخال، ستستقبل الدالة مصفوفة NumPy بالشكل (height, width, 3)، حيث يمثل البعد الأخير قيم RGB. سنُرجع صورة أيضًا في شكل مصفوفة NumPy.
يمكنك أيضًا تعيين نوع البيانات المستخدم بواسطة المكون باستخدام وسيطة الكلمة المفتاحية type=. على سبيل المثال، إذا أردت أن تأخذ الدالة مسار ملف لصورة بدلاً من مصفوفة NumPy، يمكن كتابة مكون الإدخال Image على النحو التالي:
gr.Image(type="filepath", shape=...)
لاحظ أيضًا أن مكون الإدخال Image يأتي مع زر تحرير 🖉، والذي يسمح بقص الصور وتكبيرها. يمكن أن يساعد التلاعب بالصور بهذه الطريقة في كشف التحيزات أو العيوب الخفية في نموذج التعلم الآلي!
يمكنك قراءة المزيد حول المكونات العديدة وكيفية استخدامها في وثائق Gradio.
يتضمن Gradio فئة عالية المستوى، gr.ChatInterface، والتي تشبه gr.Interface، ولكنها مصممة خصيصًا لواجهات روبوتات المحادثة. تقوم فئة gr.ChatInterface أيضًا بتغليف دالة، ولكن يجب أن تحتوي هذه الدالة على توقيع محدد. يجب أن تأخذ الدالة وسيطين: message ثم history (يمكن تسمية الوسيطات بأي اسم، ولكن يجب أن تكون بهذا الترتيب)
message: سلسلة نصية str تمثل إدخال المستخدمhistory: قائمة list من القوائم list تمثل المحادثات حتى تلك النقطة. تتكون كل قائمة داخلية من سلسلتين نصيتين str تمثلان زوجًا: [إدخال المستخدم، استجابة الروبوت].يجب أن تُرجع الدالة استجابة سلسلة نصية واحدة، وهي استجابة الروبوت لإدخال المستخدم المحدد message.
بخلاف ذلك، لا يحتوي gr.ChatInterface على معاملات مطلوبة (على الرغم من توفر العديد منها لتخصيص واجهة المستخدم).
إليك مثال تجريبي:
import random
import gradio as gr
def random_response(message, history):
return random.choice(["Yes", "No"])
demo = gr.ChatInterface(random_response)
demo.launch()

يقدم Gradio نهجين لبناء التطبيقات:
1. Interface وChatInterface، اللذان يوفران تجريدًا عالي المستوى لإنشاء العروض التوضيحية التي ناقشناها حتى الآن.
2. Blocks، وهي واجهة برمجة تطبيقات منخفضة المستوى لتصميم تطبيقات ويب بتخطيطات وتدفقات بيانات أكثر مرونة. تتيح لك Blocks القيام بأشياء مثل توفير تدفقات بيانات وعروض توضيحية متعددة، والتحكم في مكان ظهور المكونات على الصفحة، والتعامل مع تدفقات البيانات المعقدة (مثل أن تكون المخرجات بمثابة مدخلات لدوال أخرى)، وتحديث الخصائص/الرؤية للمكونات بناءً على تفاعل المستخدم — كل ذلك في Python. إذا كانت هذه هي المرونة التي تحتاجها، جرب Blocks بدلاً من ذلك!
دعنا نلقي نظرة على مثال بسيط. لاحظ كيف يختلف API هنا عن Interface.
import gradio as gr
def greet(name):
return "Hello " + name + "!"
with gr.Blocks() as demo:
name = gr.Textbox(label="Name")
output = gr.Textbox(label="Output Box")
greet_btn = gr.Button("Greet")
greet_btn.click(fn=greet, inputs=name, outputs=output, api_name="greet")
demo.launch()

أشياء يجب ملاحظتها:
Blocks باستخدام عبارة with، وأي مكون يتم إنشاؤه داخل هذه العبارة يُضاف تلقائيًا إلى التطبيق.Button، ثم تمت إضافة مستمع حدث click إلى هذا الزر. يجب أن يبدو API لهذا مألوفًا! مثل Interface، تأخذ طريقة click دالة Python ومكونات الإدخال ومكونات الإخراج.إليك تطبيقًا ليعطيك فكرة عما هو ممكن باستخدام Blocks:
import numpy as np
import gradio as gr
def flip_text(x):
return x[::-1]
def flip_image(x):
return np.fliplr(x)
with gr.Blocks() as demo:
gr.Markdown("Flip text or image files using this demo.")
with gr.Tab("Flip Text"):
text_input = gr.Textbox()
text_output = gr.Textbox()
text_button = gr.Button("Flip")
with gr.Tab("Flip Image"):
with gr.Row():
image_input = gr.Image()
image_output = gr.Image()
image_button = gr.Button("Flip")
with gr.Accordion("Open for More!"):
gr.Markdown("Look at me...")
text_button.click(flip_text, inputs=text_input, outputs=text_output)
image_button.click(flip_image, inputs=image_input, outputs=image_output)
demo.launch()

هناك الكثير مما يحدث هنا! سنغطي كيفية إنشاء تطبيقات Blocks المعقدة مثل هذا في قسم البناء باستخدام blocks من أجلك.
تهانينا، أنت الآن على دراية بأساسيات Gradio! 🥳 انتقل إلى دليلنا التالي لمعرفة المزيد حول الميزات الرئيسية لـ Gradio.
تم بناء Gradio باستخدام العديد من مكتبات المصادر المفتوحة الرائعة، يرجى دعمها أيضًا!
Gradio مرخص بموجب رخصة Apache License 2.0 الموجودة في ملف LICENSE في الدليل الجذر لهذا المستودع.
تحقق أيضًا من الورقة البحثية Gradio: Hassle-Free Sharing and Testing of ML Models in the Wild, ICML HILL 2019، ويرجى الاستشهاد بها إذا كنت تستخدم Gradio في عملك.
@article{abid2019gradio,
title = {Gradio: Hassle-Free Sharing and Testing of ML Models in the Wild},
author = {Abid, Abubakar and Abdalla, Ali and Abid, Ali and Khan, Dawood and Alfozan, Abdulrahman and Zou, James},
journal = {arXiv preprint arXiv:1906.02569},
year = {2019},
}