استدعاء الأدوات باستخدام Ollama

مؤلف

Joshua Noble

Data Scientist

استدعاء الأدوات باستخدام Ollama

استدعاء الأدوات في النماذج اللغوية الكبيرة (LLMs) هو قدرة النموذج على التفاعل مع الأدوات أو الخدمات أو واجهات برمجة التطبيقات الخارجية لأداء المهام. ويُتيح هذا لنماذج LLM توسيع وظائفها، ما يعزز قدرتها على التعامل مع المهام الواقعية التي قد تتطلب الوصول إلى بيانات خارجية أو معلومات في الوقت الفعلي أو تطبيقات محددة. عندما يستخدم نموذج LLM أداة بحث على الويب، يمكنه استدعاء الويب لجلب البيانات غير المتوفرة في بيانات تدريب النموذج في الوقت الفعلي. قد تشمل أنواع الأدوات الأخرى لغة Python لإجراء الحسابات أو تحليل البيانات أو تصوُّرها، أو الاتصال بنقطة نهاية الخدمة للحصول على البيانات. يمكن لاستدعاء الأدوات أن يجعل روبوت المحادثة أكثر ديناميكية ومرونة، ما يمكِّنه من تقديم ردود أكثر دقة وملاءمة وتفصيلًا استنادًا إلى بيانات مباشرة أو مهام متخصصة خارج نطاق معرفته الفورية. من أطر العمل الشائعة في استدعاء الأدوات: Langchain وollama حاليًا.

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

في هذا البرنامج التعليمي، ستتعرَّف على كيفية إعداد استدعاء الأدوات باستخدام ollama للبحث في نظام الملفات المحلي، وهي مهمة يصعب القيام بها باستخدام نموذج لغوي كبير عن بُعد. تتوفر العديد من نماذج ollama لاستدعاء الأدوات وبناء وكلاء الذكاء الاصطناعي مثل Mistral وLlama 3.2، وتتوفر قائمة كاملة على موقع ollama الإلكتروني. في هذه الحالة سنستخدم IBM Granite 3.2 Dense الذي يدعم الأدوات. النموذجان 2B و8B هما نموذجان لغويان كبيران كثيفان يعتمدان ع على النصوص فقط، وقد تم تدريبهما لدعم حالات الاستخدام القائمة على الأدوات، وكذلك لتعزيز التوليد المعزز بالاسترجاع (RAG)، ما يجعل من السهل توليد الأكواد، والترجمة، وتصحيح الأخطاء.

يمكن تنزيل دفتر الملاحظات لهذا البرنامج التعليمي من Github هنا.

الخطوة 1: تثبيت Ollama

أولًا ستقوم بتنزيل ollama من https://ollama.com/download وتثبيته على نظام التشغيل لديك. على نظام OSX يتم ذلك من خلال ملف ‎.dmg، وعلى نظام Linux عبر أمر واحد في سطر الأوامر، وعلى Windows باستخدام برنامج التثبيت. قد تحتاج إلى صلاحيات المسؤول على جهازك لتشغيل برنامج التثبيت.

يمكنك التحقق من تثبيت ollama بشكل صحيح عن طريق فتح محطة طرفية أو موجِّه أوامر وإدخال:

ollama -v 

 

الخطوة 2: تثبيت المكتبات

بعد ذلك، ستضيف عمليات الاستيراد الأوَّلية. سيستخدم هذا العرض التوضيحي مكتبة ollama في Python للتواصل مع ollama، ومكتبة pymupdf لقراءة ملفات PDF في نظام الملفات.

!pip install pymupdf

import ollama
import os
import pymupdf

 

بعد ذلك ستسحب النموذج الذي ستستخدمه خلال هذا البرنامج التعليمي. يؤدي هذا إلى تنزيل أوزان النموذج من ollama إلى جهازك المحلي وتخزينها للاستخدام لاحقًا دون الحاجة إلى إجراء أي استدعاءات عن بُعد لواجهة برمجة التطبيقات لاحقًا.

!ollama pull granite3.2
!ollama pull granite3.2-vision

الخطوة 3: تحديد الأدوات

ستحدِّد الآن الأدوات التي سيتمكن مثيل أدوات ollama من الوصول إليها. نظرًا لأن الهدف من الأدوات هو قراءة الملفات والبحث في الصور في نظام الملفات المحلي، ستُنشئ دالتَين من أدوات python لكلٍّ من هذه الأدوات. الدالة الأولى اسمهاsearch_text_files ويتطلب الأمر كلمة رئيسية للبحث عنها في الملفات المحلية. لأغراض هذا العرض التوضيحي، يبحث الكود فقط عن الملفات في مجلد محدد، لكنه يمكن أن يمتد ليشمل مَعلمة ثانية تحدِّد المجلد الذي ستبحث فيه الأداة.

يمكنك استخدام مطابقة سلسلة نصية بسيطة للتحقق مما إذا كانت الكلمة الرئيسية موجودة في المستند، ولكن نظرًا لأن ollama يسهِّل استدعاء النماذج اللغوية الكبيرة المحلية،search_text_files فسنستخدم Granite 3.2 لتحديد إذا ما كانت الكلمة الرئيسية تَصِف نص المستند. ويتم ذلك عن طريق قراءة المستند في سلسلة تُعرَف باسمdocument_text . تستدعي الدالة بعد ذلك ollama.chat وتوجِّه النموذج بما يلي:

"Respond only 'yes' or 'no', do not add any additional information. Is the following text about " + keyword + "? " + document_text 

إذا استجاب النموذج بـ "نعم"، تُظهر الدالة اسم الملف الذي يحتوي على الكلمة الرئيسية التي أشار إليها المستخدم في الموجِّه. إذا لم يظهر أن أيًا من الملفات يحتوي على المعلومات، فإن الدالة تُظهِر "None" كسلسلة نصية.

قد تعمل هذه الدالة ببطء في المرة الأولى؛ لأن ollama سيقوم بتنزيل Granite 3.2 Dense. 

def search_text_files(keyword: str) -> str:
  
  directory = os.listdir("./files/")
  for fname in directory:
    
    # look through all the files in our directory that aren't hidden files
    if os.path.isfile("./files/" + fname) and not fname.startswith('.'):

        if(fname.endswith(".pdf")):
           
           document_text = ""
           doc = pymupdf.open("./files/" + fname)

           for page in doc: # iterate the document pages
               document_text += page.get_text() # get plain text (is in UTF-8)
               
           doc.close()

           prompt = "Respond only 'yes' or 'no', do not add any additional information. Is the following text about " + keyword + "? " + document_text 

           res = ollama.chat(
                model="granite3.2:8b",
                messages=[{'role': 'user', 'content': prompt}]
            )

           if 'Yes' in res['message']['content']:
                return "./files/" + fname

        elif(fname.endswith(".txt")):

            f = open("./files/" + fname, 'r')
            file_content = f.read()
            
            prompt = "Respond only 'yes' or 'no', do not add any additional information. Is the following text about " + keyword + "? " + file_content 

            res = ollama.chat(
                model="granite3.2:8b",
                messages=[{'role': 'user', 'content': prompt}]
            )
           
            if 'Yes' in res['message']['content']:
                f.close()
                return "./files/" + fname

  return "None"

الأداة الثانية تُسمَّى search_image_files  ويتطلب الأمر كلمة رئيسية للبحث عنها في الصور المحلية. يتم إجراء البحث باستخدام نموذج وصف الصور Granite 3.2 Vision عبر ollama. سيعرض هذا النموذج وصفًا نصيًا لكل ملف صورة في المجلد، ثم يبحث عن الكلمة الرئيسية داخل الوصف. تتمثل إحدى نقاط القوة في استخدام ollama في أنه يمكن بسهولة بناء أنظمة متعددة الوكلاء لاستدعاء نموذج مكان نموذج آخر.

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

def search_image_files(keyword:str) -> str:

    directory = os.listdir("./files/")
    image_file_types = ("jpg", "png", "jpeg")

    for fname in directory:

        if os.path.isfile("./files/" + fname) and not fname.startswith('.') and fname.endswith(image_file_types):
            res = ollama.chat(
                model="granite3.2-vision",
                messages=[
                    {
                        'role': 'user',
                        'content': 'Describe this image in short sentences. Use simple phrases first and then describe it more fully.',
                        'images': ["./files/" + fname]
                    }
                ]
            )

            if keyword in res['message']['content']:
                return "./files/" + fname
    
    return "None"

الخطوة 4: تحديد أدوات ollama

الآن وبعد تحديد الدوال التي يستطيع ollama استدعاءها، ستعمل على إعداد بيانات الأداة لـ ollama ذاته. الخطوة الأولى هي إنشاء كائن يربط اسم الأداة بالدوال الخاصة باستدعاء الدوال في ollama.

available_functions = {
  'Search inside text files':search_text_files,
  'Search inside image files':search_image_files
}

بعد ذلك، هيِّئ مصفوفة الأدوات لإخبار ollama بالأدوات التي سيكون له حق الوصول إليها والمتطلبات الخاصة بكل أداة. هذه مصفوفة تحتوي على مخطط كائن واحد لكل أداة تُخبر إطار عمل استدعاء الأدوات في ollama بكيفية استدعاء الأداة وبما تُعيده.

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

# tools don't need to be defined as an object but this helps pass the correct parameters
# to the tool call itself by giving the model a prompt of how the tool is to be used
ollama_tools=[
     {
      'type': 'function',
      'function': {
        'name': 'Search inside text files',
        'description': 'This tool searches in PDF or plaintext or text files in the local file system for descriptions or mentions of the keyword.',
        'parameters': {
          'type': 'object',
          'properties': {
            'keyword': {
              'type': 'string',
              'description': 'Generate one keyword from the user request to search for in text files',
            },
          },
          'required': ['keyword'],
        },
      },
    },
    {
      'type': 'function',
      'function': {
        'name': 'Search inside image files',
        'description': 'This tool searches for photos or image files in the local file system for the keyword.',
        'parameters': {
          'type': 'object',
          'properties': {
            'keyword': {
              'type': 'string',
              'description': 'Generate one keyword from the user request to search for in image files',
            },
          },
          'required': ['keyword'],
        },
      },
    },
  ]


ستستخدم تعريف الأدوات هذا عند استدعاء ollama بواسطة إدخال المستخدم.

الخطوة 5: تمرير إدخال المستخدم إلى ollama

حان الوقت الآن لتمرير إدخال المستخدم إلى ollama ليُعيد نتائج استدعاءات الأدوات. أولًا، تأكَّد من تشغيل ollama على نظامك:

# if ollama is not currently running, start it
import subprocess
subprocess.Popen(["ollama","serve"], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)

إذا كان Ollama قيد التشغيل، فسيُرجع هذا:

<Popen: returncode: None args: ['ollama', 'serve']>

الآن اطلب من المستخدم إدخال بيانات. يمكنك أيضًا تثبيت الإدخال بشكل صريح في الكود أو استرجاعه من واجهة محادثة، وذلك حسب كيفية تهيئتك للتطبيق. ستنتظر دالة input  إدخال المستخدم قبل الاستمرار.

# input
user_input = input("What would you like to search for?")
print(user_input)

على سبيل المثال، إذا أدخل المستخدم "معلومات عن الكلاب"، فستقوم هذه الخلية بطباعة:

Information about dogs

الآن، يتم تمرير استعلام المستخدم إلى ollama نفسه. تحتاج الرسائل إلى دور للمستخدم والمحتوى الذي يقوم المستخدم بإدخاله. يتم تمرير هذا إلى ollama باستخدام دالة chat . المَعلمة الأولى هي النموذج الذي تريد استخدامه، وفي هذه الحالة Granite 3.2 Dense، ثم تأتي الرسالة التي تحتوي على إدخال المستخدم، وأخيرًا مصفوفة الأدوات التي قمت بتهيئتها مسبقًا.

ستُنشئ الدالة chat مخرجات تحدِّد الأداة التي يجب استخدامها والمَعلمات التي ينبغي تمريرها لها في استدعاءات الأدوات اللاحقة.

messages = [{'role': 'user', 'content':user_input}]

response: ollama.ChatResponse = ollama.chat(
   
  # set which model we're using
  'granite3.2:8b',

  # use the message from the user
  messages=messages,

  tools=ollama_tools
)

الآن بعد أن أنشأ النموذج استدعاءات الأدوات ضمن المخرجات، قم بتشغيل جميع استدعاءات الأدوات بالمَعلمات التي أنشأها النموذج وتحقَّق من المخرجات. في هذا التطبيق، يتم استخدام Granite 3.2 Dense أيضًا لتوليد المخرجات النهائية، وبالتالي تتم إضافة نتائج استدعاءات الأداة إلى الإدخال الأوَّلي للمستخدم ثم تمريرها إلى النموذج.

قد تُرجع عدة استدعاءات أدوات متعددة ملفات متطابقة؛ لذا يتم تجميع الاستجابات في مصفوفة يتم تمريرها بعد ذلك إلى Granite 3.2 لتوليد استجابة. الموجِّه الذي يسبق البيانات يوجِّه النموذج بشأن كيفية الاستجابة.

If the tool output contains one or more file names, then give the user only the filename found. Do not add additional details. 
If the tool output is empty ask the user to try again. Here is the tool output: 

يتم بعد ذلك إنشاء المخرجات النهائية باستخدام أسماء الملفات التي تم إرجاعها أو 

# this is a place holder that to use to see whether the tools return anything 
output = []

if response.message.tool_calls:
  
  # There may be multiple tool calls in the response
  for tool_call in response.message.tool_calls:

    # Ensure the function is available, and then call it
    if function_to_call := available_functions.get(tool_call.function.name):
      print('Calling tool: ', tool_call.function.name, ' \n with arguments: ', tool_call.function.arguments)
      tool_res = function_to_call(**tool_call.function.arguments)

      print(" Tool response is " + str(tool_res))

      if(str(tool_res) != "None"):
        output.append(str(tool_res))
        print(tool_call.function.name, ' has output: ', output)
    else:
      print('Could not find ', tool_call.function.name)

  # Now chat with the model using the tool call results
  # Add the function response to messages for the model to use
  messages.append(response.message)

  prompt = '''
    If the tool output contains one or more file names, 
    then give the user only the filename found. Do not add additional details. 
    If the tool output is empty ask the user to try again. Here is the tool output: 
  '''

  messages.append({'role': 'tool', 'content': prompt + " " + ", ".join(str(x) for x in output)})
  
  # Get a response from model with function outputs
  final_response = ollama.chat('granite3.2:8b', messages=messages)
  print('Final response:', final_response.message.content)

else:

  # the model wasn't able to pick the correct tool from the prompt
  print('No tool calls returned from model')

باستخدام الملفات المقدَّمة لهذا البرنامج التعليمي، سيُعيد الموجِّه "معلومات عن الكلاب" ما يلي:

    Calling tool:  Search inside text files  
     with arguments:  {'keyword': 'dogs'}
     Tool response is ./files/File4.pdf
    Search inside text files  has output:  ['./files/File4.pdf']
    Calling tool:  Search inside image files  
     with arguments:  {'keyword': 'dogs'}
     Tool response is None
    Final response: The keyword "dogs" was found in File4.pdf.

يمكنك أن ترى أن Granite 3.2 اختار الكلمة الرئيسية الصحيحة من الإدخال، وهي "الكلاب"، وبحث في الملفات داخل المجلد ليجد الكلمة الرئيسية في ملف PDF. ونظرًا لأن نتائج النماذج اللغوية الكبيرة ليست حتمية بالكامل، فقد تحصل على نتائج مختلفة قليلًا مع نفس الموجِّه أو مع موجِّهات متشابهة جدًا.

حلول ذات صلة
وكلاء الذكاء الاصطناعي للأعمال

يمكنك إنشاء مساعدين ووكلاء ذكاء اصطناعي ووكلاء أقوياء يعملون على أتمتة مهام سير العمل والعمليات باستخدام الذكاء الاصطناعي التوليدي ونشرها وإدارتها.

    استكشف watsonx Orchestrate
    حلول وكلاء الذكاء الاصطناعي من IBM

    يمكنك بناء مستقبل عملك باستخدام حلول الذكاء الاصطناعي الجديرة بالثقة.

    استكشف حلول وكلاء الذكاء الاصطناعي
    خدمات الذكاء الاصطناعي لدى IBM Consulting

    تساعد خدمات IBM Consulting AI في إعادة تصور طريقة عمل الشركات باستخدام حلول الذكاء الاصطناعي من أجل النهوض بأعمالها.

    استكشف خدمات الذكاء الاصطناعي
    اتخِذ الخطوة التالية

    سواء اخترت تخصيص التطبيقات والمهارات المُعدّة مسبقًا أو إنشاء خدمات مخصصة مستندة إلى وكلاء ونشرها باستخدام استوديو الذكاء الاصطناعي، فإن منصة IBM watsonx تُلبي احتياجاتك.

    استكشف watsonx Orchestrate استكشف watsonx.ai