اذهب إلى المحتوى

نشرح في مقال اليوم الخطوات الأساسية لدمج نماذج الذكاء الاصطناعي التي توفرها شركة OpenAI في تطبيق جانغو Django، ففي الآونة الأخيرة ازادت شعبية نماذج  OpenAI أو ما يعرف بنماذج  GPT OpenAI بشكل كبير بفضل قدرتها على توليد محتوى نصي عالي الجودة في مختلف المجالات سواء كتابة رسائل البريد الإلكتروني والقصص، أو الإجابة على استفسارات العملاء، أو ترجمة المحتوى من لغة لأخرى.

تُستخدم نماذج جي بي تي GPT models من  قبل المستخدمين من خلال روبوت الدردشة تشات جي بي تي ChatGPT، وهو نظام محادثة ذكي أطلقته OpenAI، لكن يمكن للمطورين الاستفادة من هذه النماذج في تطوير تطبيقاتهم الخاصة باستعمال واجهة برمجة التطبيقات API التي وفرتها OpenAI لتوفير مرونة أكبر في التعامل مع هذه النماذج. وسنوضح في الفقرات التالية خطوات إنشاء تطبيق جانغو يستخدم هذه الواجهة البرمجية، وبالتحديد الواجهة البرمجية لنموذج إكمال المحادثة ChatCompletion API من أجل توليد قصة قصيرة ونتعرف على طريقة تخصص معاملات النموذج المختلفة، وتنسيق ردوده واستجاباته.

متطلبات العمل

كي نتمكن من إكمال هذه المقالة، سوف تحتاج الآتي:

  1. إطار جانغو Django مثبت على بيئة افتراضية env  ضمن حاسوبنا
  2. إنشاء حساب على منصة OpenAI
  3. توليد مفتاح الواجهة البرمجية OpenAI API key من لوحة تحكم الحساب في منصة OpenAI
  4. تثبيت حزمة OpenAI Package الخاصة بلغة بايثون ضمن البيئة الافتراضية كما سنشرح في الخطوة التالية

تثبيت مكتبة OpenAI في جانغو

لنفترض أننا ثبَّتنا جانغو في البيئة افتراضية ضمن مجلد باسم django-apps. علينا التأكد من تفعيل البيئة الافتراضية وظهور اسمها داخل قوسين() في سطر الأوامر Terminal.
إذا لم تكن البيئة الافتراضية مفعّلة فيمكننا تفعيلها يدويًا بالانتقال للمجلد django-apps  في سطر الأوامر وكتابة الأمر التالي:

hasoub-academy@ubuntu:$ .env/bin/activate 

بمجرد تفعيل البيئة الافتراضية، نشغل الأمر التالي لتنزيل حزمة OpenAI Package الخاصة بلغة بايثون:

(env)hasoub-academy@ubuntu:$ pip install openai

نحن الآن جاهزون للبدء بتطوير تطبيق جانغو الخاص بنا كما سنوضح في الخطوات التالية.

 إرسال الطلبات للواجهة البرمجية OpenAI API

نحتاج بداية لإضافة مفتاح الواجهة البرمجية OpenAI API key لتطبيقنا كي نتمكن من إرسال الطلبات للواجهة البرمجية ChatCompletion API. واختبار الرد الذي نحصل عليه منها.

لنكتب الأمر التالي لتشغيل بايثون داخل البيئة الافتراضية:

(env)hasoub-academy@ubuntu:$ python

نستورد بعدها المكتبة OpenAI ونعرًف العميل client المخصص للتفاعل مع الواجهة البرمجية كما يلي:

import openai
client = OpenAI(api_key="your-api-key")

ملاحظة: نحتاج لاستبدالyour-api-key بمفتاح الواجهة البرمجية الخاص بنا وهو شبيه للتالي  sk-abdfhghlisciodfop.

بعدها نرسل طلب للواجهة البرمجية ChatCompletion API باستخدم الدالة chat.completions.create:

response = client.chat.completions.create(
    model="gpt-3.5-turbo", 
    messages=[
        {"role": "user", "content": "عد من 1 إلى 10"}
    ]
)

حددنا في الكود السابق النموذج الذي نحتاج لاستخدامه في تطبيقنا ليكون gpt-3.5-turbo، وأضفنا كائن رسالة واحد يحتوي على الدور مستخدم user، ومرّرنا مُوجّه prompt بسيط سنرسل لاختبار الواجهة البرمجية وهو في حالتنا طلب العد من واحد إلى عشرة.

ملاحظة1: عند التفاعل مع نموذج GPT  سنتعامل مع ثلاثة أدوار رئيسية وهي: دور المستخدم user الذي يطرح الأسئلة أو يطلب المساعدة من النموذج، ودور النظام system الذي يتضمن القواعد والتعليمات التي توجّه للنموذج، ودور المساعد assistance الذي يمثل نموذج الذكاء الاصطناعي نفسه والذي سنستخدمة للإجابة على أسئلة المستخدم أو تنفيذ الأوامر التي يطلبها منه.

ملاحظة2: من المهم دائمًا الرجوع إلى التوثيق الرسمي لمنصة OpenAI للحصول على تعليمات دقيقة وشاملة حول كيفية استخدام نماذج GPT في تطبيقاتك، فهذه النماذج تتعدل وتتغير مع مرور الوقت.

لنطبع الآن الرد المستلم من الواجهة البرمجية API والذي يتضمن عرض الأعداد من واحد إلى عشرة على شكل قائمة من خلال الأمر التالي:

print(response.choices[0].message.content)

سنحصل على النتيجة التالية:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10

بهذا نكون قد نجحنا بإرسال طلب بسيط إلى الواجهة البرمجية، واستلمنا منها الرد، وتأكدنا أن كل شيء يسير على ما يرام. نحن جاهزون الآن لاستخدام الواجهة البرمجية لإرسال مُوجّه prompt أكثر صعوبة ونطلب من النموذج كتابة محتوى قصة قصيرة.

ضبط معاملات النموذج Parameters

بعد أن نجنا في إرسال طلب API بسيط إلى الواجهة البرمجية لإكمال المحادثة ChatCompletion API، لنتعرف على طريقة ضبط معاملات النموذج للتحكم بسلوك هذا النموذج. فهنالك العديد من المعاملات المتاحة للتحكم في النص المولد، سنوضح ثلاثة منها.

1. درجة الحرارة Temperature

يتحكم هذا المعامل في مدى عشوائية الردود المولَّدة من قبل النموذج، ويأخذ قيمة بين الصفر والواحد، فكلما ارتفعت قيمته سنحصل على تنوع وإبداع في الردود والعكس صحيح.

response = client.chat.completions.create(
    model="gpt-3.5-turbo", 
    messages=[{"role": "user", "content": "اذكر خمس كلمات"}], 
    temperature=0.1
)
print(response.choices[0].message.content)
المخرجــــات
1. تفاح
2. سيارة
3. كتاب
4. شمس
5. شجرة

لنجرب منحه قيمة قريبة من الصفر مثل 0.1 ونرى كيف ستولد الكلمات:

response = client.chat.completions.create(
    model="gpt-3.5-turbo", 
    messages=[{"role": "user", "content": "اذكر خمس كلمات"}], 
    temperature=0.1
)
print(response.choices[0].message.content)
المخرجــــات
1. تفاح
2. فيل
3. ضوء الشمس
4. مغامرة
5. سكون

نلاحظ بالتجربة أننا عندما نطلب من النموذج أن يذكر خمس كلمات عدة مرات عند ضبط البرامتر بالقيمة 0.1 فسوف نحصل على نفس الكلمات في كل مرة، أما عندما نضبط قيمته إلى 0.8 ونجرب الطلب عدة مرات فسنلاحظ تغيّر النتائج التي نحصل عليها كل مرة:

response = client.chat.completions.create(
    model="gpt-3.5-turbo", 
    messages=[{"role": "user", "content": "اذكر خمس كلمات باللغة العربية"}], 
    temperature=0.8
)
print(response.choices[0].message.content)
المخرجــــات
1. تفاح
2. ضوء الشمس
3. سعادة
4. صداقة
5. تقنية

2. العدد الأقصى للوحدات النصية Max Token

يسمح لنا هذا المعامل بتحديد طول النص المولد، فعند ضبطع بقيمة معينة سيضمن لنا أن الردود لن تتجاوز الرقم الذي حددناه في الوحدات النصية tokens، على سبيل المثال عندما نضبط قيمة max-token إلى 10:

response = client.chat.completions.create(
    model="gpt-3.5-turbo", 
    messages=[{"role": "user", "content": "اذكر خمس كلمات"}], 
    max_tokens=10
)
print(response.choices[0].message.content)

سنحصل على النتائج التالية:

المخرجــــات
1. تفاحة
2. سيارة

وعندما نضبط قيمة max-token إلى 20:

response = client.chat.completions.create(
    model="gpt-3.5-turbo", 
    messages=[{"role": "user", "content": "اذكر خمس كلمات"}], 
    max_tokens=20
)
print(response.choices[0].message.content)

سنحصل على النتائج التالية:

المخرجــــات
1. تفاح
2. سيارة
3. موسيقى
4. محيط
5. صداقة

3. التدفق Stream

يحدد هذا المعامل هل نريد أن تتدفق الردود على دفعات streams أو تعود لنا دفعة واحدة، فعند ضبطه بالقيمة True، سنستلم الرد بشكل متدفق، أي على دفعات خلال عملية توليدها. هذا يفيدنا في المحادثات الطويلة وفي تطبيقات الزمن الحقيقي التفاعلية.

response = client.chat.completions.create(
    model="gpt-3.5-turbo", 
    messages=[{"role": "user", "content": "اذكر خمس كلمات"}], 
    stream=True
)

collected_messages = []
for chunk in response:
    chunk_message = chunk.choices[0].delta.content
    if chunk_message is not None:
        collected_messages.append(chunk_message)

print(collected_messages)
المخرجــــات
['', 'قطة', '\n', 'كتاب', '\n', 'حاسوب', '\n', 'شمس', '\n', 'ماء']

سيحتفظ المتغير chunk_message بكل جزء من الرسالة المتدفقة بشكل مؤقت أثناء استلامها من الواجهة البرمجية، بعد ذلك، ستضاف هذه الأجزاء إلى القائمة collected_messages التي تُجمع فيها كل الرسائل. يجب علينا التأكد من أن الجزء المتدفق ليس None، لأن هذه القيمة تدل على انتهاء تدفق الردود وتستخدم كشرط للخروج من الحلقة التكرارية.

صياغة مُوجِّه نظام System Prompt مخصص

في هذه الخطوة، سنستخدم كل ما تعلمناه من مفاهيم أساسية لكتابة مُوجِّه نظام مخصص system prompt وتوفير السياق الذي يحتاجه نموذج GPT لفهم المطلوب منه ضمن تطبيق جانغو، وسنحدد القواعد التي يجب أن يتبعها النموذج لتوليد المحتوى.

ننشئ بداية وحدة بايثون تحتوي على دالة تتولى المهمة المطلوبة. لذا ننشئ ملفًا جديدًا باسم story_generator.py داخل مجلد مشروع جانغو بكتابة الأمر التالي:

(env)hasoub-academy@ubuntu:$ touch ~/my_blog_app/blog/blogsite/story_generator.py

ثم نضيف مفتاح الواجهة البرمجية OpenAI API key إلى متغيرات البيئة environmental variables، فلا نضيفها في ملف بايثون مباشرة لحماية المفتاح:

(env)hasoub-academy@ubuntu:$ export OPENAI_KEY="your-api-key"

نفتح الآن الملف story_generator.py وننشئ بداخله عميل OpenAI client ونعرف دالة باسم generate_story وظيفتها توليد محتوى قصة بناءً على مجموعة من الكلمات التي يحددها المستخدم:

import os
from openai import OpenAI
client = OpenAI(api_key=os.environ["OPENAI_KEY"])

def generate_story(words):
    # استدعاء واجهة برمجة التطبيقات من OpenAI لتوليد القصة
    response = get_short_story(words)
    
    # تنسيق الاستجابة وإرجاعها
    return format_response(response)

لتنظيم الكود البرمجي، سنستدعي ضمن هذه الدالة البرمجية دالة منفصلة باسم get_short_story تطلب توليد القصة من الواجهة البرمجية OpenAI API، ودالة أخرى باسم format_response تنسِّق الرد المستلم من الواجهة البرمجية.

لنركز الآن على دالة توليد القصة get_short_story حيث سنضيف الكود الخاص بها في نهاية الملف story_generator.py كما يلي:

def get_short_story(words):
    # إنشاء موجه النظام
    system_prompt = f"""أنت مولد قصص قصيرة.
    اكتب قصة قصيرة باستخدام الكلمات التالية: {words}.
    لا تتجاوز فقرة واحدة."""

    #  الاتصال بواجهة برمجة التطبيقات
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[{
            "role": "user",
            "content": system_prompt
        }],
        temperature=0.8,
        max_tokens=1000
    )

    # إرجاع استجابة الواجهة البرمجية
    return response

كما نلاحظ فقد ضبطنا هنا مُوجِّه النظام system prompt كي يخبر النموذج ما هو، وما هي المهمة التي عليه تأديتها، وحددنا في الموجّه حجم القصة المطلوبة، ثم مررنا هذا الموجّه للواجهة البرمجية ChatCompletion API.

أخيرًا نكتب كود دالة التنسيق format_response  في نهاية الملف story_generator.py:

def format_response(response):
    # استخرج القصة المولدة من الاستجابة
    story = response.choices[0].message.content
    
    # إزالة أي نص أو تنسيقات غير مرغوبة   
    story = story.strip()
    
    # إرجاع القصة المنسقة
    return story

لاختبار هذه الدوال سنستدعي الدالة generate_story ونمرر لها مجموعة كلمات كمعاملات، ثم نطبع الرد الذي تعيده لنا من خلال إضافة سطر الكود التالي للملف:

print(generate_story("قطة، كتاب، حاسوب شمس، ماء"))

لنحفظ الملف ونغلقه، ونشغًله من داخل سطر الأوامر كما يلي:


(env) sammy@ubuntu:$ python ~/my_blog_app/blog/blogsite/story_generator.py

يجب أن نحصل على قصة تشابه القصة التالية:

في زاوية مريحة من غرفة مشمسة، كانت هناك قطة ذات فرو ناعم تُدعى "مشمش"، تتمدد بكسل بجانب رف كتب شاهق. بين صفوف الكتب، كان حاسوب فضولي يهمس بهدوء. بينما كانت أشعة الشمس تتسلل عبر النافذة، مُلَقيةً ضوءًا دافئًا، لاحظت "مشمش" بقعة ماء صغيرة على الرف. مدفوعةً بالفضول، دفعت القطة الكتاب الأقرب إلى البقعة، ليُفتح الكتاب ويكشف عن مكان مخفي يحتوي على عقد ماسي متلألئ. مع اكتشاف السر، بدأت "مشمش" مغامرة غير متوقعة، حيث امتزجت أشعة الشمس، والماء، وقوة المعرفة لتنسج قصة مثيرة من الغموض والاكتشاف.

بعد أن تأكدنا من عمل الدالة generate_story وتوليد القصة بشكل صحيح، لنغير طريقة تنفيذ الكود وبدلاً من طباعة القصة مباشرة في سطر الأوامر، سنستدعي الدالة من خلال عرض جانغو Django view لعرض القصة على واجهة المستخدم.

print(generate_story("قطة، كتاب، حاسوب شمس، ماء"))

يمكن تجربة تعديل مُوجّه النظام system prompt بما يناسبنا لتوليد محتوى أفضل. سنلاحظ بالتجربة أن بإمكاننا دائمًا تحسين النتائج بما يتناسب مع احتياجاتنا.

لننتقل إلى الخطوة التالية، حيث سندمج الوحدة التي عرفناها في ملف story_generator.py مع  مشروع جانغو الخاص بنا.

دمج وحدة بايثون مع جانغو في الواجهة الخلفية

لدمج وحدة story_generator مع مشروع جانغو في الواجهة الخلفية، علينا تنفيذ عدة خطوات بسيطة، سنبدأ أولاً بإنشاء عرض view جديد في جانغو لاستقبال الكلمات من المستخدم، ثم سنستخدم الدالة generate_story لتوليد القصة بناءً على تلك الكلمات، وفي النهاية سنعرض النتيجة للمستخدم عبر المتصفح.

نفتح ملف views.py داخل مجلد مشروع جانغو، ونستورد الوحدات والحزم البرمجية اللازمة، ثم نضيف دالة عرض view باسم generate_story_from_words ونكتب ضمنها ما يلي:

from django.http import JsonResponse
from .story_generator import generate_story

def generate_story_from_words(request):
    words = request.GET.get('words')  # استخراج الكلمات المتوقعة من الطلب
    story = generate_story(words)  # استدعاء دالة generate_story باستخدام الكلمات المستخرجة
    return JsonResponse({'story': story})  # إرجاع القصة في استجابة JSON

بعدها نحتاج لربط الدالة بمسار URL في مشروع جانغو لتمكين المستخدمين من الوصول إليها عبر المتصفح. لنفتح الملف urls.py ونضيف نمط الرابط URL pattern للدالة generate_story_from_words كما يلي:

urlpatterns = [
    # أنماط URL الأخرى...
    path('generate-story/', views.generate_story_from_words, name='generate-story'),
]

الآن يمكننا إرسال الطلبات من خلال نقطة الوصول التالية/generate-story/ باستخدام المتصفح، وإرسال طلب من النوع GET لها وتمرير الكلمات المتوقعة كمعاملات للطلب، نفتح سطر الأوامر ونكتب الأمر curl بالشكل التالي:

(env)hasoub-academy@ubuntu:$ curl "http://your_domain/generate-story/?words=قطة,كتاب,حاسوب,شمس,ماء"

علينا استبدال http://your_domain بالعنوان الفعلي الذي يستضيف مشروعنا. تمثّل الكلمات الممررة عبر هذا الرابط مثل كتاب، وماء، وحاسوب ما هي الكلمات التي نريد استخدامها لتوليد محتوى القصة. يمكن بالطبع تغيير هذه الكلمات واستخدام كلمات أخرى حسب الحاجة.

بعد تشغيل أمر curl يجب أن نرى ردًا من الخادم يحتوي على القصة المولدة استنادًا إلى الكلمات التي قدمناها.

(env)hasoub-academy@ubuntu:$ curl "http://your_domain/generate-story/?words="قطة,كتاب,حاسوب,شمس,ماء"

وسنحصل على مخرجات قريبة للتالي:

{
  "story": "كان يا مكان، في كوخ صغير مريح يقع وسط غابة كثيفة، قطة فضولية تُدعى 'مشمش' تجلس بجانب النافذة، تستمتع بأشعة الشمس الدافئة. بينما كانت 'مشمش' تحرك ذيلها بكسل، لفت نظرها كتاب مغبر ملقى على رف قريب. بدافع الفضول، قفزت بعناية إلى الرف، مما أدى إلى سقوط مجموعة من الكتب، فتح أحدها ليكشف عن مكان مخفي. داخل هذا المكان، اكتشفت 'مشمش' حاسوبًا قديمًا، بدأ شاشته يومض عندما لمست زر الطاقة. مفتونةً بالشاشة المتوهجة، انطلقت 'مشمش' في عالم من المناظر الافتراضية، حيث تجولت بحرية، تطارد الأسماك الرقمية وتوقف للإعجاب بشلالات رائعة. ضائعة في هذه المغامرة الجديدة، اكتشفت 'مشمش' عجائب العوالم الملموسة والافتراضية معًا، مدركةً أن الاستكشاف الحقيقي لا يعرف حدودًا."
}

الخلاصة

إلى هنا نكون قد وصلنا لنهاية هذا المقال الذي وضحنا فيه الخطوات الأساسية التي نحتاجها لدمج  OpenAI modes داخل تطبيق جانغو Django باستخدام الواجهة البرمجية OpenAI API، وتعلمنا طريقة إرسال الطلبات للواجهة البرمجية ChatCompletion API والتحكم بسلوك النموذج عن طريق ضبط معاملاته المختلفة. لتحسين هذا المشروع وزيادة ميزاته، يمكننا استكشاف المزيد من مميزات الواجهة البرمجية OpenAI API وتجريب مُوجِّهات نظام system prompt مختلفة، وقيم معاملات متنوعة حتى نحصل على قصة مميزة وإبداعية.

ترجمة-وبتصرٌّف-للمقال How to Integrate OpenAI GPT Models in Your Django Project

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...