|
|
التشغيل في Google Colab
|
|
|
عرض المصدر على GitHub
|
عند استخدام نموذج ذكاء اصطناعي توليدي، مثل Gemma، قد تحتاج إلى استخدام النموذج لتشغيل واجهات برمجة التطبيقات من أجل إكمال المهام أو الإجابة عن الأسئلة. يُطلق على توجيه نموذج من خلال تحديد واجهة برمجة ثم تقديم طلب يستخدم هذه الواجهة اسم استدعاء الدالة.
يوضّح هذا الدليل عملية استخدام Gemma 4 ضمن نظام Hugging Face المتكامل.
سيتم تشغيل ورقة الملاحظات هذه على وحدة معالجة الرسومات T4.
تثبيت حِزم Python
ثبِّت مكتبات Hugging Face المطلوبة لتشغيل نموذج Gemma وتقديم الطلبات.
# Install PyTorch & other librariespip install torch accelerate# Install the transformers librarypip install transformers
تحميل النموذج
استخدِم مكتبات transformers لإنشاء مثيل من processor وmodel باستخدام الفئتَين AutoProcessor وAutoModelForImageTextToText كما هو موضّح في مثال الرمز البرمجي التالي:
MODEL_ID = "google/gemma-4-E2B-it" # @param ["google/gemma-4-E2B-it","google/gemma-4-E4B-it", "google/gemma-4-31B-it", "google/gemma-4-26B-A4B-it"]
from transformers import AutoProcessor, AutoModelForMultimodalLM
model = AutoModelForMultimodalLM.from_pretrained(MODEL_ID, dtype="auto", device_map="auto")
processor = AutoProcessor.from_pretrained(MODEL_ID)
Loading weights: 0%| | 0/2011 [00:00<?, ?it/s]
أدوات التمرير
يمكنك تمرير الأدوات إلى النموذج باستخدام الدالة apply_chat_template() من خلال الوسيطة tools. هناك طريقتان لتحديد هذه الأدوات:
- مخطّط JSON: يمكنك إنشاء قاموس JSON يدويًا يحدّد اسم الدالة ووصفها ومَعلماتها (بما في ذلك الأنواع والحقول المطلوبة).
- دوال Python الأولية: يمكنك تمرير دوال Python الفعلية. ينشئ النظام تلقائيًا مخطّط JSON المطلوب من خلال تحليل تلميحات النوع والوسيطات وسلاسل المستندات الخاصة بالدالة. للحصول على أفضل النتائج، يجب أن تلتزم سلاسل المستندات بدليل أسلوب Google Python.
في ما يلي مثال على مخطط JSON.
from transformers import TextStreamer
weather_function_schema = {
"type": "function",
"function": {
"name": "get_current_temperature",
"description": "Gets the current temperature for a given location.",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city name, e.g. San Francisco",
},
},
"required": ["location"],
},
}
}
message = [
{
"role": "system", "content": "You are a helpful assistant."
},
{
"role": "user", "content": "What's the temperature in London?"
}
]
text = processor.apply_chat_template(message, tools=[weather_function_schema], tokenize=False, add_generation_prompt=True)
inputs = processor(text=text, return_tensors="pt").to(model.device)
streamer = TextStreamer(processor)
outputs = model.generate(**inputs, streamer=streamer, max_new_tokens=64)
<bos><|turn>system
You are a helpful assistant.<|tool>declaration:get_current_temperature{description:<|"|>Gets the current temperature for a given location.<|"|>,parameters:{properties:{location:{description:<|"|>The city name, e.g. San Francisco<|"|>,type:<|"|>STRING<|"|>} },required:[<|"|>location<|"|>],type:<|"|>OBJECT<|"|>} }<tool|><turn|>
<|turn>user
What's the temperature in London?<turn|>
<|turn>model
<|tool_call>call:get_current_temperature{location:<|"|>London<|"|>}<tool_call|><|tool_response>
والآن، إليك المثال نفسه مع دالة Python الأولية.
from transformers.utils import get_json_schema
def get_current_temperature(location: str):
"""
Gets the current temperature for a given location.
Args:
location: The city name, e.g. San Francisco
"""
return "15°C"
message = [
{
"role": "user", "content": "What's the temperature in London?"
}
]
text = processor.apply_chat_template(message, tools=[get_json_schema(get_current_temperature)], tokenize=False, add_generation_prompt=True)
inputs = processor(text=text, return_tensors="pt").to(model.device)
streamer = TextStreamer(processor)
outputs = model.generate(**inputs, streamer=streamer, max_new_tokens=256)
<bos><|turn>system
<|tool>declaration:get_current_temperature{description:<|"|>Gets the current temperature for a given location.<|"|>,parameters:{properties:{location:{description:<|"|>The city name, e.g. San Francisco<|"|>,type:<|"|>STRING<|"|>} },required:[<|"|>location<|"|>],type:<|"|>OBJECT<|"|>} }<tool|><turn|>
<|turn>user
What's the temperature in London?<turn|>
<|turn>model
<|tool_call>call:get_current_temperature{location:<|"|>London<|"|>}<tool_call|><|tool_response>
تسلسل استدعاء الدالة الكامل
يوضّح هذا القسم دورة من ثلاث مراحل لربط النموذج بالأدوات الخارجية: دور النموذج لإنشاء عناصر استدعاء الدوال، ودور المطوّر لتحليل الرمز البرمجي وتنفيذه (مثل واجهة برمجة تطبيقات خاصة بالطقس)، والردّ النهائي حيث يستخدم النموذج ناتج الأداة للإجابة عن سؤال المستخدم.
دور النموذج
إليك طلب المستخدم "Hey, what's the weather in Tokyo right now?" والأداة [get_current_weather]. تنشئ Gemma عنصر استدعاء دالة على النحو التالي.
# Define a function that our model can use.
def get_current_weather(location: str, unit: str = "celsius"):
"""
Gets the current weather in a given location.
Args:
location: The city and state, e.g. "San Francisco, CA" or "Tokyo, JP"
unit: The unit to return the temperature in. (choices: ["celsius", "fahrenheit"])
Returns:
temperature: The current temperature in the given location
weather: The current weather in the given location
"""
return {"temperature": 15, "weather": "sunny"}
prompt = "Hey, what's the weather in Tokyo right now?"
tools = [get_current_weather]
message = [
{
"role": "system", "content": "You are a helpful assistant."
},
{
"role": "user", "content": prompt
},
]
text = processor.apply_chat_template(message, tools=tools, tokenize=False, add_generation_prompt=True)
inputs = processor(text=text, return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=128)
generated_tokens = out[0][len(inputs["input_ids"][0]):]
output = processor.decode(generated_tokens, skip_special_tokens=False)
print(f"Prompt: {prompt}")
print(f"Tools: {tools}")
print(f"Output: {output}")
Prompt: Hey, what's the weather in Tokyo right now?
Tools: [<function get_current_weather at 0x7cef824ece00>]
Output: <|tool_call>call:get_current_weather{location:<|"|>Tokyo, JP<|"|>}<tool_call|><|tool_response>
دور المطوّر
يجب أن يحلّل تطبيقك ردّ النموذج لاستخراج اسم الدالة ووسيطاتها، وإضافة tool_calls وtool_responses مع الدور assistant.
import re
import json
def extract_tool_calls(text):
def cast(v):
try: return int(v)
except:
try: return float(v)
except: return {'true': True, 'false': False}.get(v.lower(), v.strip("'\""))
return [{
"name": name,
"arguments": {
k: cast((v1 or v2).strip())
for k, v1, v2 in re.findall(r'(\w+):(?:<\|"\|>(.*?)<\|"\|>|([^,}]*))', args)
}
} for name, args in re.findall(r"<\|tool_call>call:(\w+)\{(.*?)\}<tool_call\|>", text, re.DOTALL)]
calls = extract_tool_calls(output)
if calls:
# Call the function and get the result
#####################################
# WARNING: This is a demonstration. #
#####################################
# Using globals() to call functions dynamically can be dangerous in
# production. In a real application, you should implement a secure way to
# map function names to actual function calls, such as a predefined
# dictionary of allowed tools and their implementations.
results = [
{"name": c['name'], "response": globals()[c['name']](**c['arguments'])}
for c in calls
]
message.append({
"role": "assistant",
"tool_calls": [
{"function": call} for call in calls
],
"tool_responses": results
})
print(json.dumps(message[-1], indent=2))
{
"role": "assistant",
"tool_calls": [
{
"function": {
"name": "get_current_weather",
"arguments": {
"location": "Tokyo, JP"
}
}
}
],
"tool_responses": [
{
"name": "get_current_weather",
"response": {
"temperature": 15,
"weather": "sunny"
}
}
]
}
"tool_responses": [
{
"name": function_name,
"response": function_response
}
]
في حال تقديم طلبات مستقلة متعددة:
"tool_responses": [
{
"name": function_name_1,
"response": function_response_1
},
{
"name": function_name_2,
"response": function_response_2
}
]
الردّ النهائي
أخيرًا، تقرأ Gemma رد الأداة وتجيب على المستخدم.
text = processor.apply_chat_template(message, tools=tools, tokenize=False, add_generation_prompt=True)
inputs = processor(text=text, return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=128)
generated_tokens = out[0][len(inputs["input_ids"][0]):]
output = processor.decode(generated_tokens, skip_special_tokens=True)
print(f"Output: {output}")
message[-1]["content"] = output
Output: The current weather in Tokyo is 15 degrees and sunny.
يمكنك الاطّلاع على سجلّ المحادثات الكامل أدناه.
# full history
print(json.dumps(message, indent=2))
print("-"*80)
output = processor.decode(out[0], skip_special_tokens=False)
print(f"Output: {output}")
[
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": "Hey, what's the weather in Tokyo right now?"
},
{
"role": "assistant",
"tool_calls": [
{
"function": {
"name": "get_current_weather",
"arguments": {
"location": "Tokyo, JP"
}
}
}
],
"tool_responses": [
{
"name": "get_current_weather",
"response": {
"temperature": 15,
"weather": "sunny"
}
}
],
"content": "The current weather in Tokyo is 15 degrees and sunny."
}
]
--------------------------------------------------------------------------------
Output: <bos><|turn>system
You are a helpful assistant.<|tool>declaration:get_current_weather{description:<|"|>Gets the current weather in a given location.<|"|>,parameters:{properties:{location:{description:<|"|>The city and state, e.g. "San Francisco, CA" or "Tokyo, JP"<|"|>,type:<|"|>STRING<|"|>},unit:{description:<|"|>The unit to return the temperature in.<|"|>,enum:[<|"|>celsius<|"|>,<|"|>fahrenheit<|"|>],type:<|"|>STRING<|"|>} },required:[<|"|>location<|"|>],type:<|"|>OBJECT<|"|>} }<tool|><turn|>
<|turn>user
Hey, what's the weather in Tokyo right now?<turn|>
<|turn>model
<|tool_call>call:get_current_weather{location:<|"|>Tokyo, JP<|"|>}<tool_call|><|tool_response>response:get_current_weather{temperature:15,weather:<|"|>sunny<|"|>}<tool_response|>The current weather in Tokyo is 15 degrees and sunny.<turn|>
استدعاء الدالة باستخدام "المفكّر"
من خلال استخدام عملية استدلال داخلية، يحسّن النموذج دقّة استدعاء الدوال بشكل كبير. يتيح ذلك اتّخاذ قرارات أكثر دقةً بشأن وقت تفعيل أداة وكيفية تحديد مَعلماتها.
prompt = "Hey, I'm in Seoul. Is it good for running now?"
message = [
{
"role": "system", "content": "You are a helpful assistant."
},
{
"role": "user", "content": prompt
},
]
text = processor.apply_chat_template(message, tools=tools, tokenize=False, add_generation_prompt=True, enable_thinking=True)
inputs = processor(text=text, return_tensors="pt").to(model.device)
input_len = inputs["input_ids"].shape[-1]
out = model.generate(**inputs, max_new_tokens=1024)
output = processor.decode(out[0][input_len:], skip_special_tokens=False)
result = processor.parse_response(output)
for key, value in result.items():
if key == "role":
print(f"Role: {value}")
elif key == "thinking":
print(f"\n=== Thoughts ===\n{value}")
elif key == "content":
print(f"\n=== Answer ===\n{value}")
elif key == "tool_calls":
print(f"\n=== Tool Calls ===\n{value}")
else:
print(f"\n{key}: {value}...\n")
Role: assistant
=== Thoughts ===
1. **Analyze the Request:** The user is asking if it's "good for running now" in "Seoul".
2. **Identify Necessary Information:** To determine if it's good for running, I need current weather information (temperature, precipitation, etc.) for Seoul.
3. **Examine Available Tools:** The available tool is `get_current_weather(location, unit)`.
4. **Determine Tool Arguments:**
* `location`: The user specified "Seoul".
* `unit`: The user did not specify a unit (Celsius or Fahrenheit).
5. **Formulate the Tool Call:** I need to call `get_current_weather` with the location. Since the user didn't specify a unit, I can either omit it (if the tool defaults are acceptable) or choose a common one. However, the tool definition requires `location` but `unit` is optional.
6. **Construct the Response Strategy:**
* Call the tool to get the weather data for Seoul.
* Once the data is received, I can advise the user on whether it's suitable for running.
7. **Generate Tool Call:**
```json
{
"toolSpec": {
"name": "get_current_weather",
"args": {
"location": "Seoul"
}
}
}
```
(Self-correction: The `unit` parameter is optional in the definition, so just providing the location is sufficient to proceed.)
8. **Final Output Generation:** Present the tool call to the user/system.
=== Tool Calls ===
[{'type': 'function', 'function': {'name': 'get_current_weather', 'arguments': {'location': 'Seoul'} } }]
معالجة طلب الأداة والحصول على الإجابة النهائية
calls = extract_tool_calls(output)
if calls:
# Call the function and get the result
#####################################
# WARNING: This is a demonstration. #
#####################################
# Using globals() to call functions dynamically can be dangerous in
# production. In a real application, you should implement a secure way to
# map function names to actual function calls, such as a predefined
# dictionary of allowed tools and their implementations.
results = [
{"name": c['name'], "response": globals()[c['name']](**c['arguments'])}
for c in calls
]
message.append({
"role": "assistant",
"tool_calls": [
{"function": call} for call in calls
],
"tool_responses": results
})
text = processor.apply_chat_template(message, tools=tools, tokenize=False, add_generation_prompt=True)
inputs = processor(text=text, return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=128)
generated_tokens = out[0][len(inputs["input_ids"][0]):]
output = processor.decode(generated_tokens, skip_special_tokens=True)
print(f"Output: {output}")
message[-1]["content"] = output
print("-"*80)
print("Full History")
print("-"*80)
print(json.dumps(message, indent=2))
Output: The current weather in Seoul is 15 degrees Celsius and sunny. That sounds like great weather for a run!
--------------------------------------------------------------------------------
Full History
--------------------------------------------------------------------------------
[
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": "Hey, I'm in Seoul. Is it good for running now?"
},
{
"role": "assistant",
"tool_calls": [
{
"function": {
"name": "get_current_weather",
"arguments": {
"location": "Seoul"
}
}
}
],
"tool_responses": [
{
"name": "get_current_weather",
"response": {
"temperature": 15,
"weather": "sunny"
}
}
],
"content": "The current weather in Seoul is 15 degrees Celsius and sunny. That sounds like great weather for a run!"
}
]
ملاحظة مهمة: المخططات التلقائية مقابل المخططات اليدوية
عند الاعتماد على التحويل التلقائي من دوال Python إلى مخطط JSON، قد لا يلبي الناتج الذي تم إنشاؤه دائمًا توقّعات محدّدة بشأن المَعلمات المعقّدة.
إذا كانت إحدى الدوال تستخدم عنصرًا مخصّصًا (مثل فئة Config) كوسيطة، قد يصفها المحوّل التلقائي ببساطة بأنّها "عنصر" عام بدون تفصيل خصائصه الداخلية.
في هذه الحالات، يُفضَّل تحديد مخطّط JSON يدويًا لضمان تحديد الخصائص المتداخلة (مثل theme أو font_size ضمن عنصر config) بشكل صريح للنموذج.
import json
from transformers.utils import get_json_schema
class Config:
def __init__(self):
self.theme = "light"
self.font_size = 14
def update_config(config: Config):
"""
Updates the configuration of the system.
Args:
config: A Config object
Returns:
True if the configuration was successfully updated, False otherwise.
"""
update_config_schema = {
"type": "function",
"function": {
"name": "update_config",
"description": "Updates the configuration of the system.",
"parameters": {
"type": "object",
"properties": {
"config": {
"type": "object",
"description": "A Config object",
"properties": {"theme": {"type": "string"}, "font_size": {"type": "number"} },
},
},
"required": ["config"],
},
},
}
print(f"--- [Automatic] ---")
print(json.dumps(get_json_schema(update_config), indent=2))
print(f"\n--- [Manual Schemas] ---")
print(json.dumps(update_config_schema, indent=2))
--- [Automatic] ---
{
"type": "function",
"function": {
"name": "update_config",
"description": "Updates the configuration of the system.",
"parameters": {
"type": "object",
"properties": {
"config": {
"type": "object",
"description": "A Config object"
}
},
"required": [
"config"
]
}
}
}
--- [Manual Schemas] ---
{
"type": "function",
"function": {
"name": "update_config",
"description": "Updates the configuration of the system.",
"parameters": {
"type": "object",
"properties": {
"config": {
"type": "object",
"description": "A Config object",
"properties": {
"theme": {
"type": "string"
},
"font_size": {
"type": "number"
}
}
}
},
"required": [
"config"
]
}
}
}
الملخّص والخطوات التالية
لقد حدّدت كيفية إنشاء تطبيق يمكنه استدعاء الدوال باستخدام Gemma 4. يتم إنشاء سير العمل من خلال دورة من أربع مراحل:
- تحديد الأدوات: أنشئ الدوال التي يمكن أن يستخدمها النموذج، مع تحديد الوسيطات والأوصاف (مثل دالة البحث عن حالة الطقس).
- دور النموذج: يتلقّى النموذج طلب المستخدم وقائمة بالأدوات المتاحة، ويعرض كائنًا منظَّمًا لاستدعاء الدالة بدلاً من نص عادي.
- دور المطوّر: يحلّل المطوّر هذا الناتج باستخدام التعبيرات العادية لاستخراج أسماء الدوال ووسيطاتها، وينفّذ رمز Python الفعلي، ويضيف النتائج إلى سجلّ المحادثات باستخدام دور الأداة المحدّد.
- الرد النهائي: يعالج النموذج نتيجة تنفيذ الأداة لإنشاء رد نهائي بلغة طبيعية للمستخدم.
يمكنك الاطّلاع على المستندات التالية لمزيد من المعلومات.
التشغيل في Google Colab
عرض المصدر على GitHub