Transformers documentation

استخدام الأدوات

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

استخدام الأدوات

تُدرَّب نماذج المحادثة بشكل شائع مع دعم ميزة «استدعاء الدوال» أو «استخدام الأدوات». الأدوات هي دوال يوفّرها المستخدم، ويمكن للنموذج اختيار استدعائها كجزء من استجابته. على سبيل المثال، يمكن أن يكون لدى النماذج وصول إلى أداة حاسبة لتنفيذ العمليات الحسابية دون الحاجة إلى إجراء الحساب داخليًا.

ستوضح هذه الدليل كيفية تعريف الأدوات، وكيفية تمريرها إلى نموذج المحادثة، وكيفية معالجة مخرجات النموذج عند استدعائه لأداة.

تمرير الأدوات

عندما يدعم النموذج استخدام الأدوات، مرّر الدوال إلى معامل tools في apply_chat_template(). تُمرَّر الأدوات إما كـمخطط JSON أو كدوال Python. إذا مرّرت دوال Python، فسيتم تحليل المعاملات وأنواع المعاملات ووصف الدالة (docstring) لتوليد مخطط JSON تلقائيًا.

على الرغم من أن تمرير دوال بايثون مريح للغاية، إلا أن محلل النصوص يتعامل فقط مع سطور التوثيق بأسلوب Google. راجع الأمثلة أدناه لمعرفة كيفية تنسيق دالة جاهزة للاستخدام كأداة.

def get_current_temperature(location: str, unit: str):
    """
    Get the current temperature at a location.

    Args:
        location: The location to get the temperature for, in the format "City, Country"
        unit: The unit to return the temperature in. (choices: ["celsius", "fahrenheit"])
    """
    return 22.  # A real function should probably actually get the temperature!

def get_current_wind_speed(location: str):
    """
    Get the current wind speed in km/h at a given location.

    Args:
        location: The location to get the wind speed for, in the format "City, Country"
    """
    return 6.  # A real function should probably actually get the wind speed!

tools = [get_current_temperature, get_current_wind_speed]

يمكنك اختيارياً إضافة كتلة Returns: إلى سلسلة التوثيق وإضافة نوع الإرجاع إلى ترويسة الدالة، لكن معظم النماذج لن تستخدم هذه المعلومات. كما سيتجاهل المحلل الكود الفعلي داخل الدالة!

ما يهم حقًا هو اسم الدالة، وأسماء المعاملات، وأنواع المعاملات، وسلسلة التوثيق التي تصف الغرض من الدالة والغرض من معاملاتها. هذه العناصر هي التي تُشكّل «التوقيع» الذي ستستخدمه النموذج لتحديد ما إذا كان سيقوم باستدعاء الأداة أم لا.

مثال على استدعاء الأدوات

حمّل نموذجًا ومُرمِّزًا يدعم استخدام الأدوات مثل NousResearch/Hermes-2-Pro-Llama-3-8B، لكن يمكنك أيضًا النظر في نموذج أكبر مثل Command-R و Mixtral-8x22B إذا كان جهازك يدعم ذلك.

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

checkpoint = "NousResearch/Hermes-2-Pro-Llama-3-8B"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForCausalLM.from_pretrained(checkpoint, dtype="auto", device_map="auto")

أنشئ سجل محادثة.

messages = [
  {"role": "system", "content": "You are a bot that responds to weather queries. You should reply with the unit used in the queried location."},
  {"role": "user", "content": "Hey, what's the temperature in Paris right now?"}
]

في الخطوة التالية، مرّر messages وقائمة بالأدوات إلى apply_chat_template(). ثم قم بتجزئة المحادثة وتوليد استجابة.

inputs = tokenizer.apply_chat_template(messages, tools=tools, add_generation_prompt=True, return_dict=True, return_tensors="pt")
outputs = model.generate(**inputs.to(model.device), max_new_tokens=128)
print(tokenizer.decode(outputs[0][len(inputs["input_ids"][0]):]))
<tool_call>
{"arguments": {"location": "Paris, France", "unit": "celsius"}, "name": "get_current_temperature"}
</tool_call><|im_end|>

استدعى نموذج الدردشة أداة get_current_temperature باستخدام المعاملات الصحيحة من docstring. استنتج أن الموقع هو فرنسا بناءً على باريس، وأن عليه استخدام الدرجة المئوية (Celsius) لوحدات قياس درجة الحرارة.

لا يمكن للنموذج استدعاء الأداة بنفسه فعليًا. بل يطلب استدعاء الأداة، ومن مسؤوليتك معالجة هذا الاستدعاء وإضافته مع النتيجة إلى سجل المحادثة. بالنسبة للنماذج التي تدعم تحليل الاستجابة، يتم التعامل مع تحليل الاستجابة تلقائيًا، ويمكنك ببساطة استخدام parse_response() لاستخراج استدعاء الأداة. أما بالنسبة للنماذج الأخرى، فستحتاج إلى ترجمة سلسلة الإخراج يدويًا إلى قاموس استدعاء أداة.

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

على الرغم من أن tool_calls يشبه واجهة OpenAI API، فإن واجهة OpenAI API تستخدم سلسلة JSON كصيغة لـ tool_calls. قد يؤدي ذلك إلى أخطاء أو سلوك غير متوقع للنموذج عند استخدامه في Transformers، حيث يتوقع قاموسًا (dict).

tool_call = {"name": "get_current_temperature", "arguments": {"location": "Paris, France", "unit": "celsius"}}
messages.append({"role": "assistant", "tool_calls": [{"type": "function", "function": tool_call}]})

أضف استجابة الأداة إلى سجل المحادثة بدور tool.

messages.append({"role": "tool", "content": "22"})  # Note that the returned content is always a string!

أخيرًا، اسمح للنموذج بقراءة استجابة الأداة والرد على المستخدم.

inputs = tokenizer.apply_chat_template(messages, tools=tools, add_generation_prompt=True, return_dict=True, return_tensors="pt")
out = model.generate(**inputs.to(model.device), max_new_tokens=128)
print(tokenizer.decode(out[0][len(inputs["input_ids"][0]):]))
The temperature in Paris, France right now is 22°C.<|im_end|>

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

مخططات JSON

طريقة أخرى لتعريف الأدوات هي تمرير مخطط JSON.

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

تستخدم طريقة apply_chat_template() الدالة get_json_schema لتحويل الدوال القابلة للاستدعاء في بايثون إلى مخطط JSON. وتشمل ذلك: تُعامل self وcls كحجج مستقبلة ضمنية وتُتجاهل.

from transformers.utils import get_json_schema

def multiply(a: float, b: float):
    """
    A function that multiplies two numbers

    Args:
        a: The first number to multiply
        b: The second number to multiply
    """
    return a * b

schema = get_json_schema(multiply)
print(schema)
{
  "type": "function",
  "function": {
    "name": "multiply",
    "description": "A function that multiplies two numbers",
    "parameters": {
      "type": "object",
      "properties": {
        "a": {
          "type": "number",
          "description": "The first number to multiply"
        },
        "b": {
          "type": "number",
          "description": "The second number to multiply"
        }
      },
      "required": ["a", "b"]
    }
  }
}

لن نتناول هنا تفاصيل مخطط JSON بحد ذاته، إذ إنه موثّق بشكل جيد جدًا في أماكن أخرى. ومع ذلك، نشير إلى أنه يمكنك تمرير قواميس مخطط JSON إلى معامل tools الخاص بـ apply_chat_template() بدلاً من دوال بايثون:

# A simple function that takes no arguments
current_time = {
  "type": "function",
  "function": {
    "name": "current_time",
    "description": "Get the current local time as a string.",
    "parameters": {
      'type': 'object',
      'properties': {}
    }
  }
}

# A more complete function that takes two numerical arguments
multiply = {
  'type': 'function',
  'function': {
    'name': 'multiply',
    'description': 'A function that multiplies two numbers',
    'parameters': {
      'type': 'object',
      'properties': {
        'a': {
          'type': 'number',
          'description': 'The first number to multiply'
        },
        'b': {
          'type': 'number', 'description': 'The second number to multiply'
        }
      },
      'required': ['a', 'b']
    }
  }
}

model_input = tokenizer.apply_chat_template(
    messages,
    tools = [current_time, multiply]
)
Update on GitHub