Transformers documentation
Serve CLI
Serve CLI
يُعدّ سطر الأوامر transformers serve خياراً خفيفاً للخوادم المحلية أو المستضافة ذاتياً. فهو يتجنّب الأعباء التشغيلية وزمن التشغيل الإضافي المرتبط بمحركات الاستدلال المتخصصة مثل vLLM. استخدمه للتقييم والتجارب ونشر الأحمال المعتدلة. وتزيد ميزات مثل التجميع المستمر من الإنتاجية وتخفض زمن الاستجابة.
للاستخدامات الإنتاجية واسعة النطاق، استخدم vLLM أو SGLang مع نموذج Transformer كخلفية. تعرّف على المزيد في دليل خلفيات الاستدلال.
يُطلق الأمر transformers serve خادمًا محليًا متوافقًا مع OpenAI SDK. يعمل الخادم مع العديد من التطبيقات من أطراف ثالثة ويدعم واجهات برمجة التطبيقات REST التالية.
/v1/chat/completionsلطلبات النص والصورة والصوت والفيديو/v1/completionsلإكمال النصوص القديمة من موجه حر- يدعم
/v1/responsesواجهة Responses API /v1/audio/transcriptionsلتحويل الصوت إلى نص- يجيب
/v1/systemoneعلى الأسئلة المُدخلة (اختيار، تقييم، نعم/لا) مع احتمال لكل إجابة مسموح بها /v1/modelsيعرض النماذج المتاحة للتكاملات مع أطراف ثالثة- يُبثّ
/load_modelتقدّم تحميل النموذج عبر SSE
قم بتثبيت تبعيات الخدمة.
pip install transformers[serving]
شغّل transformers serve لإطلاق خادم. عنوان الخادم الافتراضي هو http://localhost:8000.
transformers serve
v1/chat/completions
تعتمد واجهة v1/chat/completions على Chat Completions API. وهي تدعم طلبات النص والصورة والصوت والفيديو لنماذج LLMs وVLMs والنماذج متعددة الوسائط. استخدمها مع curl أو InferenceClient أو عميل OpenAI.
إكمال النص
from huggingface_hub import InferenceClient
messages = [{"role": "user", "content": "What is the Transformers library known for?"}]
client = InferenceClient("http://localhost:8000")
result = client.chat_completion(messages, model="Qwen/Qwen2.5-0.5B-Instruct", max_tokens=256)
print(result.choices[0].message.content)يعيد InferenceClient نصًا مطبوعًا.
The Transformers library is primarily known for its ability to create and manipulate large-scale language models [...]
from huggingface_hub import InferenceClient
messages = [{"role": "user", "content": "What is the Transformers library known for?"}]
client = InferenceClient("http://localhost:8000")
stream = client.chat_completion(messages, model="Qwen/Qwen2.5-0.5B-Instruct", max_tokens=256, stream=True)
for chunk in stream:
token = chunk.choices[0].delta.content
if token:
print(token, end="")يعيد InferenceClient نصًا مطبوعًا.
The Transformers library is primarily known for its ability to create and manipulate large-scale language models [...]
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")
completion = client.chat.completions.create(
model="Qwen/Qwen2.5-0.5B-Instruct",
messages=[
{
"role": "user",
"content": "What is the Transformers library known for?"
}
],
)
print(completion.choices[0].message.content)يعيد عميل OpenAI نصاً مطبوعاً.
The Transformers library is primarily known for its ability to create and manipulate large-scale language models [...]
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")
completion = client.chat.completions.create(
model="Qwen/Qwen2.5-0.5B-Instruct",
messages=[
{
"role": "user",
"content": "What is the Transformers library known for?"
}
],
stream=True,
)
for chunk in completion:
token = chunk.choices[0].delta.content
if token:
print(token, end="")يعيد عميل OpenAI نصاً مطبوعاً.
The Transformers library is primarily known for its ability to create and manipulate large-scale language models [...]
curl -X POST http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-0.5B-Instruct",
"messages": [{"role": "user", "content": "What is the Transformers library known for?"}],
"temperature": 0.9,
"max_tokens": 256
}'يعيد الأمر نصًا بصيغة JSON.
{
"id": "ade3578d-e2c3-47ed-b651-c014991a92f6",
"choices": [
{
"finish_reason": "length",
"index": 0,
"message": {
"content": "The Transformers library is primarily known for its ability to create and manipulate large-scale language models [...]",
"role": "assistant"
}
}
],
"created": 1776184004,
"model": "Qwen/Qwen2.5-0.5B-Instruct@main",
"object": "chat.completion",
"usage": {
"completion_tokens": 256,
"prompt_tokens": 37,
"total_tokens": 293
}
}curl -X POST http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-0.5B-Instruct",
"messages": [{"role": "user", "content": "What is the Transformers library known for?"}],
"temperature": 0.9,
"max_tokens": 256,
"stream": true
}'يعيد الأمر تدفّقًا من المقاطع.
data: {"id":"596d3941-754d-43b4-8773-9bf9940049f5","choices":[{"delta":{"role":"assistant"},"index":0}],"created":1776183469,"model":"Qwen/Qwen2.5-0.5B-Instruct@main","object":"chat.completion.chunk","system_fingerprint":""}
data: {"id":"596d3941-754d-43b4-8773-9bf9940049f5","choices":[{"delta":{"content":"The"},"index":0}],"created":1776183469,"model":"Qwen/Qwen2.5-0.5B-Instruct@main","object":"chat.completion.chunk","system_fingerprint":""}
(...)إكمال بناءً على الصور
from huggingface_hub import InferenceClient
messages = [
{
"role": "user",
"content": [
{"type": "text", "text": "What's in this image?"},
{
"type": "image_url",
"image_url": {
"url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg",
}
},
],
}
]
client = InferenceClient("http://localhost:8000")
result = client.chat_completion(messages, model="Qwen/Qwen2.5-VL-7B-Instruct", max_tokens=256)
print(result.choices[0].message.content)يعيد InferenceClient نصًا مطبوعًا.
The image depicts an astronaut in a space suit standing on what appears to be the surface of the moon, given the barren, rocky landscape and the dark sky in the background. The astronaut is holding a large egg that has cracked open, revealing a small creature inside. The scene is imaginative and playful, combining elements of space exploration with a whimsical twist involving the egg and the creature.from huggingface_hub import InferenceClient
messages = [
{
"role": "user",
"content": [
{"type": "text", "text": "What's in this image?"},
{
"type": "image_url",
"image_url": {
"url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg",
}
},
],
}
]
client = InferenceClient("http://localhost:8000")
stream = client.chat_completion(messages, model="Qwen/Qwen2.5-VL-7B-Instruct", max_tokens=256, stream=True)
for chunk in stream:
token = chunk.choices[0].delta.content
if token:
print(token, end="")يعيد InferenceClient نصًا مطبوعًا.
The image depicts an astronaut in a space suit standing on what appears to be the surface of the moon, given the barren, rocky landscape and the dark sky in the background. The astronaut is holding a large egg that has cracked open, revealing a small creature inside. The scene is imaginative and playful, combining elements of space exploration with a whimsical twist involving the egg and the creature.from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")
completion = client.chat.completions.create(
model="Qwen/Qwen2.5-VL-7B-Instruct",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "What's in this image?"},
{
"type": "image_url",
"image_url": {
"url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg",
}
},
],
}
],
)
print(completion.choices[0].message.content)يعيد عميل OpenAI نصًا مطبوعًا.
The image depicts an astronaut in a space suit standing on what appears to be the surface of the moon, given the barren, rocky landscape and the dark sky in the background. The astronaut is holding a large egg that has cracked open, revealing a small creature inside. The scene is imaginative and playful, combining elements of space exploration with a whimsical twist involving the egg and the creature.from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")
completion = client.chat.completions.create(
model="Qwen/Qwen2.5-VL-7B-Instruct",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "What's in this image?"},
{
"type": "image_url",
"image_url": {
"url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg",
}
},
],
}
],
stream=True,
)
for chunk in completion:
token = chunk.choices[0].delta.content
if token:
print(token, end="")يعيد عميل OpenAI نصاً مطبوعاً.
The image depicts an astronaut in a space suit standing on what appears to be the surface of the moon, given the barren, rocky landscape and the dark sky in the background. The astronaut is holding a large egg that has cracked open, revealing a small creature inside. The scene is imaginative and playful, combining elements of space exploration with a whimsical twist involving the egg and the creature.curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-VL-7B-Instruct",
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "What's in this image?"
},
{
"type": "image_url",
"image_url": {
"url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg"
}
}
]
}
],
"max_tokens": 256
}'يعيد الأمر نصًا بصيغة JSON.
{
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"choices": [
{
"finish_reason": "stop",
"index": 0,
"message": {
"content": "The image depicts an astronaut in a space suit standing on what appears to be the surface of the moon [...]",
"role": "assistant"
}
}
],
"created": 1753366665,
"model": "Qwen/Qwen2.5-VL-7B-Instruct@main",
"object": "chat.completion",
"usage": {
"completion_tokens": 50,
"prompt_tokens": 120,
"total_tokens": 170
}
}curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-VL-7B-Instruct",
"stream": true,
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "What's in this image?"
},
{
"type": "image_url",
"image_url": {
"url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg"
}
}
]
}
],
"max_tokens": 256
}'يعيد الأمر تدفّقًا من المقاطع.
data: {"id":"f47ac10b-58cc-4372-a567-0e02b2c3d479","choices":[{"delta":{"role":"assistant"},"index":0}],"created":1753366665,"model":"Qwen/Qwen2.5-VL-7B-Instruct@main","object":"chat.completion.chunk","system_fingerprint":""}
data: {"id":"f47ac10b-58cc-4372-a567-0e02b2c3d479","choices":[{"delta":{"content":"The "},"index":0}],"created":1753366701,"model":"Qwen/Qwen2.5-VL-7B-Instruct@main","object":"chat.completion.chunk","system_fingerprint":""}
(...)إكمال بناءً على الصوت
تقبل النماذج متعددة الوسائط مثل Gemma 4 وQwen2.5-Omni مدخلات صوتية عبر نوع المحتوى input_audio في OpenAI. قم بتشفير الصوت باستخدام Base64 وحدد الصيغة (mp3 أو wav).
import base64
from huggingface_hub.utils import httpx
from huggingface_hub import InferenceClient
audio_url = "https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3"
audio_b64 = base64.b64encode(httpx.get(audio_url, follow_redirects=True).content).decode()
messages = [
{
"role": "user",
"content": [
{"type": "text", "text": "Transcribe this audio."},
{"type": "input_audio", "input_audio": {"data": audio_b64, "format": "mp3"}},
],
}
]
client = InferenceClient("http://localhost:8000")
result = client.chat_completion(messages, model="google/gemma-4-E2B-it", max_tokens=256)
print(result.choices[0].message.content)يعيد InferenceClient نصًا مطبوعًا.
This week, I traveled to Chicago to deliver my final farewell address to the nation, following in the tradition of presidents before me. It was an opportunity to say thank you. Whether we've seen eye to eye or rarely agreed at all, my conversations with you, the American people, in living rooms and schools, at farms and on factory floors, at diners, and on distant military outposts, all these conversations are what have kept me honest.import base64
from huggingface_hub.utils import httpx
from huggingface_hub import InferenceClient
audio_url = "https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3"
audio_b64 = base64.b64encode(httpx.get(audio_url, follow_redirects=True).content).decode()
messages = [
{
"role": "user",
"content": [
{"type": "text", "text": "Transcribe this audio."},
{"type": "input_audio", "input_audio": {"data": audio_b64, "format": "mp3"}},
],
}
]
client = InferenceClient("http://localhost:8000")
stream = client.chat_completion(messages, model="google/gemma-4-E2B-it", max_tokens=256, stream=True)
for chunk in stream:
token = chunk.choices[0].delta.content
if token:
print(token, end="")يعيد InferenceClient نصًا مطبوعًا.
This week, I traveled to Chicago to deliver my final farewell address to the nation, following in the tradition of presidents before me. It was an opportunity to say thank you. Whether we've seen eye to eye or rarely agreed at all, my conversations with you, the American people, in living rooms and schools, at farms and on factory floors, at diners, and on distant military outposts, all these conversations are what have kept me honest.import base64
from huggingface_hub.utils import httpx
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")
audio_url = "https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3"
audio_b64 = base64.b64encode(httpx.get(audio_url, follow_redirects=True).content).decode()
completion = client.chat.completions.create(
model="google/gemma-4-E2B-it",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "Transcribe this audio."},
{"type": "input_audio", "input_audio": {"data": audio_b64, "format": "mp3"}},
],
}
],
)
print(completion.choices[0].message.content)يعيد عميل OpenAI نصاً مطبوعاً.
This week, I traveled to Chicago to deliver my final farewell address to the nation, following in the tradition of presidents before me. It was an opportunity to say thank you. Whether we've seen eye to eye or rarely agreed at all, my conversations with you, the American people, in living rooms and schools, at farms and on factory floors, at diners, and on distant military outposts, all these conversations are what have kept me honest.import base64
from huggingface_hub.utils import httpx
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")
audio_url = "https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3"
audio_b64 = base64.b64encode(httpx.get(audio_url, follow_redirects=True).content).decode()
completion = client.chat.completions.create(
model="google/gemma-4-E2B-it",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "Transcribe this audio."},
{"type": "input_audio", "input_audio": {"data": audio_b64, "format": "mp3"}},
],
}
],
stream=True,
)
for chunk in completion:
token = chunk.choices[0].delta.content
if token:
print(token, end="")يعيد عميل OpenAI نصاً مطبوعاً.
This week, I traveled to Chicago to deliver my final farewell address to the nation, following in the tradition of presidents before me. It was an opportunity to say thank you. Whether we've seen eye to eye or rarely agreed at all, my conversations with you, the American people, in living rooms and schools, at farms and on factory floors, at diners, and on distant military outposts, all these conversations are what have kept me honest.# First, base64-encode the audio file and build the JSON payload
AUDIO_B64=$(curl -sL https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3 | base64 -w 0)
cat <<EOF > /tmp/audio_request.json
{
"model": "google/gemma-4-E2B-it",
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "Transcribe this audio."},
{"type": "input_audio", "input_audio": {"data": "$AUDIO_B64", "format": "mp3"}}
]
}
]
}
EOF
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d @/tmp/audio_request.jsonيعيد الأمر نصًا بصيغة JSON.
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"choices": [
{
"finish_reason": "stop",
"index": 0,
"message": {
"content": "This week, I traveled to Chicago to deliver my final farewell address to the nation [...]",
"role": "assistant"
}
}
],
"created": 1753366665,
"model": "google/gemma-4-E2B-it@main",
"object": "chat.completion",
"usage": {
"completion_tokens": 85,
"prompt_tokens": 200,
"total_tokens": 285
}
}# First, base64-encode the audio file and build the JSON payload
AUDIO_B64=$(curl -sL https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3 | base64 -w 0)
cat <<EOF > /tmp/audio_request.json
{
"model": "google/gemma-4-E2B-it",
"stream": true,
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "Transcribe this audio."},
{"type": "input_audio", "input_audio": {"data": "$AUDIO_B64", "format": "mp3"}}
]
}
]
}
EOF
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d @/tmp/audio_request.jsonيعيد الأمر تدفّقًا من المقاطع.
data: {"id":"cb997e1d-98b9-414a-be89-1880288610ef","choices":[{"delta":{"role":"assistant"},"index":0}],"created":1776254856,"model":"google/gemma-4-E2B-it@main","object":"chat.completion.chunk","system_fingerprint":""}
data: {"id":"cb997e1d-98b9-414a-be89-1880288610ef","choices":[{"delta":{"content":"This"},"index":0}],"created":1776254856,"model":"google/gemma-4-E2B-it@main","object":"chat.completion.chunk","system_fingerprint":""}
(...)نوع المحتوى
audio_urlهو امتداد لا يُعد جزءًا من معيار OpenAI وقد يتغير في الإصدارات المستقبلية.
يمكنك أيضًا تمرير الصوت عبر عنوان URL باستخدام نوع المحتوى audio_url لتجاوز الترميز base64.
completion = client.chat.completions.create(
model="google/gemma-4-E2B-it",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "Transcribe this audio."},
{"type": "audio_url", "audio_url": {"url": "https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3"}},
],
}
],
)إكمال بناءً على الفيديو
نوع المحتوى
video_urlهو امتداد لا يُعد جزءًا من معيار OpenAI وقد يتغير في الإصدارات المستقبلية.
استخدم نوع المحتوى video_url لإدخال الفيديو. إذا كان النموذج يدعم الصوت (مثل Gemma 4 وQwen2.5-Omni)، فسيستخرج الخادم المسار الصوتي من الفيديو ويعالجه مع الإطارات البصرية.
يتطلب معالجة الفيديو torchcodec. ثبّته باستخدام
pip install torchcodec.
from huggingface_hub import InferenceClient
messages = [
{
"role": "user",
"content": [
{"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}},
{"type": "text", "text": "What is happening in the video and what is the song about?"},
],
}
]
client = InferenceClient("http://localhost:8000")
result = client.chat_completion(messages, model="google/gemma-4-E2B-it", max_tokens=256)
print(result.choices[0].message.content)يعيد InferenceClient نصًا مطبوعًا.
The video captures a live music performance at a music festival or a large concert. There are several musicians on stage, including a central figure playing an acoustic guitar and singing. The foreground is filled with the backs of the audience, indicating a large crowd watching the show. The stage is dramatically lit with bright spotlights and blue and white stage lighting, with haze and smoke creating an immersive atmosphere.
The lyrics of the song are: "I don't care 'bout street, from that fresh street, 'cause there's no problem, another one I want to be, in the storm..."from huggingface_hub import InferenceClient
messages = [
{
"role": "user",
"content": [
{"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}},
{"type": "text", "text": "What is happening in the video and what is the song about?"},
],
}
]
client = InferenceClient("http://localhost:8000")
stream = client.chat_completion(messages, model="google/gemma-4-E2B-it", max_tokens=256, stream=True)
for chunk in stream:
token = chunk.choices[0].delta.content
if token:
print(token, end="")يعيد InferenceClient نصًا مطبوعًا.
The video captures a live music performance at a music festival or a large concert. There are several musicians on stage, including a central figure playing an acoustic guitar and singing. The foreground is filled with the backs of the audience, indicating a large crowd watching the show. The stage is dramatically lit with bright spotlights and blue and white stage lighting, with haze and smoke creating an immersive atmosphere.
The lyrics of the song are: "I don't care 'bout street, from that fresh street, 'cause there's no problem, another one I want to be, in the storm..."from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")
completion = client.chat.completions.create(
model="google/gemma-4-E2B-it",
messages=[
{
"role": "user",
"content": [
{"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}},
{"type": "text", "text": "What is happening in the video and what is the song about?"},
],
}
],
max_tokens=256,
)
print(completion.choices[0].message.content)يعيد عميل OpenAI نصاً مطبوعاً.
The video captures a live music performance at a music festival or a large concert. There are several musicians on stage, including a central figure playing an acoustic guitar and singing. The foreground is filled with the backs of the audience, indicating a large crowd watching the show. The stage is dramatically lit with bright spotlights and blue and white stage lighting, with haze and smoke creating an immersive atmosphere.
The lyrics of the song are: "I don't care 'bout street, from that fresh street, 'cause there's no problem, another one I want to be, in the storm..."from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")
completion = client.chat.completions.create(
model="google/gemma-4-E2B-it",
messages=[
{
"role": "user",
"content": [
{"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}},
{"type": "text", "text": "What is happening in the video and what is the song about?"},
],
}
],
max_tokens=256,
stream=True,
)
for chunk in completion:
token = chunk.choices[0].delta.content
if token:
print(token, end="")يعيد عميل OpenAI نصاً مطبوعاً.
The video captures a live music performance at a music festival or a large concert. There are several musicians on stage, including a central figure playing an acoustic guitar and singing. The foreground is filled with the backs of the audience, indicating a large crowd watching the show. The stage is dramatically lit with bright spotlights and blue and white stage lighting, with haze and smoke creating an immersive atmosphere.
The lyrics of the song are: "I don't care 'bout street, from that fresh street, 'cause there's no problem, another one I want to be, in the storm..."curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemma-4-E2B-it",
"messages": [
{
"role": "user",
"content": [
{"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}},
{"type": "text", "text": "What is happening in the video and what is the song about?"}
]
}
],
"max_tokens": 256
}'يعيد الأمر نصًا بصيغة JSON.
{
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"choices": [
{
"finish_reason": "length",
"index": 0,
"message": {
"content": "The video captures a live music performance at a music festival or a large concert [...]",
"role": "assistant"
}
}
],
"created": 1753366665,
"model": "google/gemma-4-E2B-it@main",
"object": "chat.completion",
"usage": {
"completion_tokens": 256,
"prompt_tokens": 350,
"total_tokens": 606
}
}curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemma-4-E2B-it",
"stream": true,
"messages": [
{
"role": "user",
"content": [
{"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}},
{"type": "text", "text": "What is happening in the video and what is the song about?"}
]
}
],
"max_tokens": 256
}'يعيد الأمر تدفّقًا من المقاطع.
data: {"id":"cb997e1d-98b9-414a-be89-1880288610ef","choices":[{"delta":{"role":"assistant"},"index":0}],"created":1776254856,"model":"google/gemma-4-E2B-it@main","object":"chat.completion.chunk","system_fingerprint":""}
data: {"id":"cb997e1d-98b9-414a-be89-1880288610ef","choices":[{"delta":{"content":"Based"},"index":0}],"created":1776254856,"model":"google/gemma-4-E2B-it@main","object":"chat.completion.chunk","system_fingerprint":""}
(...)المحادثات متعددة الأدوار
لإجراء محادثة متعددة الأدوار، شمل سجل المحادثة الكامل في قائمة messages مع أدوار متناوبة بين user وassistant. وكجميع الخوادم المتوافقة مع OpenAI، فإن الواجهة البرمجية (API) غير حالة، لذا يجب أن يحتوي كل طلب على سجل المحادثة الكامل.
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")
completion = client.chat.completions.create(
model="Qwen/Qwen2.5-0.5B-Instruct",
messages=[
{"role": "user", "content": "What is the capital of France?"},
{"role": "assistant", "content": "The capital of France is Paris."},
{"role": "user", "content": "How many people live there?"},
],
)
print(completion.choices[0].message.content)تعتمد السؤال اللاحق «كم عدد الأشخاص الذين يعيشون هناك؟» على السياق السابق، لذا يجيب النموذج عن باريس.
As of 2021, the population of Paris is approximately 2.2 million people.v1/completions
تعتمد واجهة v1/completions على واجهة Completions القديمة. على عكس /v1/chat/completions، تستقبل نصاً حرّاً في prompt بدلاً من رسائل الدردشة، وتعيد النص المولّد في choices[].text. وهذا مفيد للنماذج الأساسية (غير الموجهة) ومهام إكمال النص التي لا تتطلب قالب دردشة. كما تدعم suffix لإدراج النص في المنتصف.
curl -X POST http://localhost:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-0.5B",
"prompt": "The capital of France is",
"max_tokens": 20
}'يعيد الأمر الاستجابة التالية.
{
"id": "chatcmpl-abc123",
"object": "text_completion",
"created": 1234567890,
"model": "Qwen/Qwen2.5-0.5B@main",
"choices": [
{
"text": " Paris, and the capital of the United States is Washington, D.C.",
"index": 0,
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 5,
"completion_tokens": 16,
"total_tokens": 21
}
}from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")
# Non-streaming
completion = client.completions.create(
model="Qwen/Qwen2.5-0.5B",
prompt="The capital of France is",
max_tokens=20,
)
print(completion.choices[0].text)يعيد عميل OpenAI ما يلي.
Paris, and the capital of the United States is Washington, D.C.
يُؤيَّد البثّ المتدفق أيضًا.
stream = client.completions.create(
model="Qwen/Qwen2.5-0.5B",
prompt="The capital of France is",
max_tokens=20,
stream=True,
)
for chunk in stream:
print(chunk.choices[0].text, end="")v1/responses
تُعدّ Responses API أحدث نقطة نهاية لواجهة برمجة التطبيقات من OpenAI مخصصة للتوليد. تدعم التفاعلات ذات الحالة وتدمج أدوات مدمجة لتوسيع قدرات النموذج. وتوصي OpenAI باستخدام Responses API بدلاً من Chat Completions API للمشاريع الجديدة.
يدعم واجهة v1/responses طلبات النص والصورة والصوت والفيديو من خلال أمر curl وعميل OpenAI.
استجابات نصية
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")
response = client.responses.create(
model="Qwen/Qwen2.5-0.5B-Instruct",
input="Tell me a three sentence bedtime story about a unicorn.",
max_output_tokens=256,
stream=False,
)
print(response.output[0].content[0].text)يعيد عميل OpenAI نصاً مطبوعاً.
Once upon a time, in a faraway land, there lived a beautiful unicorn named Luna [...]
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")
response = client.responses.create(
model="Qwen/Qwen2.5-0.5B-Instruct",
input="Tell me a three sentence bedtime story about a unicorn.",
max_output_tokens=256,
stream=True,
)
for event in response:
if hasattr(event, "delta") and event.delta:
print(event.delta, end="")يعيد عميل OpenAI نصاً مطبوعاً.
Once upon a time, in a faraway land, there lived a beautiful unicorn named Luna [...]
curl http://localhost:8000/v1/responses \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-0.5B-Instruct",
"input": "Tell me a three sentence bedtime story about a unicorn.",
"max_output_tokens": 256,
"stream": false
}'يعيد الأمر نصًا بصيغة JSON.
{
"id": "resp_8693af9b-b561-4267-bd1a-22d1b43284cb",
"created_at": 1776258580.7114341,
"model": "Qwen/Qwen2.5-0.5B-Instruct@main",
"object": "response",
"output": [
{
"id": "msg_8693af9b-b561-4267-bd1a-22d1b43284cb",
"content": [
{
"annotations": [],
"text": "Once upon a time, in a faraway land, there lived a beautiful unicorn named Luna [...]",
"type": "output_text"
}
],
"role": "assistant",
"status": "completed",
"type": "message"
}
],
"status": "completed"
}curl http://localhost:8000/v1/responses \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-0.5B-Instruct",
"stream": true,
"input": "Tell me a three sentence bedtime story about a unicorn.",
"max_output_tokens": 256
}'يعيد الأمر تدفّقًا من المقاطع.
data: {"response":{"id":"resp_req_0","created_at":1754059817.783648,"model":"Qwen/Qwen2.5-0.5B-Instruct@main","object":"response","output":[],"status":"queued"},"sequence_number":0,"type":"response.created"}
data: {"content_index":0,"delta":"Once ","item_id":"msg_req_0","output_index":0,"sequence_number":5,"type":"response.output_text.delta"}
data: {"content_index":0,"delta":"upon ","item_id":"msg_req_0","output_index":0,"sequence_number":6,"type":"response.output_text.delta"}
(...)استجابات مبنية على الصور
يدعم واجهة برمجة التطبيقات (API) الخاصة بالاستجابات أيضاً مدخلات الصور والصوت والفيديو.
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")
response = client.responses.create(
model="Qwen/Qwen2.5-VL-7B-Instruct",
input=[
{"type": "input_text", "text": "What's in this image?"},
{
"type": "input_image",
"image_url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg",
},
],
max_output_tokens=256,
stream=False,
)
print(response.output[0].content[0].text)يعيد عميل OpenAI نصاً مطبوعاً.
The image depicts an astronaut in a space suit standing on what appears to be the surface of the moon, given the barren, rocky landscape and the dark sky in the background. The astronaut is holding a large egg that has cracked open, revealing a small creature inside. The scene is imaginative and playful, combining elements of space exploration with a whimsical twist involving the egg and the creature.from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")
response = client.responses.create(
model="Qwen/Qwen2.5-VL-7B-Instruct",
input=[
{"type": "input_text", "text": "What's in this image?"},
{
"type": "input_image",
"image_url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg",
},
],
max_output_tokens=256,
stream=True,
)
for event in response:
if hasattr(event, "delta") and event.delta:
print(event.delta, end="")يعيد عميل OpenAI نصاً مطبوعاً.
The image depicts an astronaut in a space suit standing on what appears to be the surface of the moon, given the barren, rocky landscape and the dark sky in the background. The astronaut is holding a large egg that has cracked open, revealing a small creature inside. The scene is imaginative and playful, combining elements of space exploration with a whimsical twist involving the egg and the creature.curl http://localhost:8000/v1/responses \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-VL-7B-Instruct",
"input": [
{"type": "input_text", "text": "What'\''s in this image?"},
{"type": "input_image", "image_url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg"}
],
"max_output_tokens": 256,
"stream": false
}'يعيد الأمر نصًا بصيغة JSON.
{
"id": "resp_f47ac10b-58cc-4372-a567-0e02b2c3d479",
"created_at": 1776258580.7114341,
"model": "Qwen/Qwen2.5-VL-7B-Instruct@main",
"object": "response",
"output": [
{
"id": "msg_f47ac10b-58cc-4372-a567-0e02b2c3d479",
"content": [
{
"annotations": [],
"text": "The image depicts an astronaut in a space suit standing on what appears to be the surface of the moon [...]",
"type": "output_text"
}
],
"role": "assistant",
"status": "completed",
"type": "message"
}
],
"status": "completed"
}curl http://localhost:8000/v1/responses \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-VL-7B-Instruct",
"stream": true,
"input": [
{"type": "input_text", "text": "What'\''s in this image?"},
{"type": "input_image", "image_url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg"}
],
"max_output_tokens": 256
}'يعيد الأمر تدفّقًا من المقاطع.
data: {"response":{"id":"resp_f47ac10b-58cc-4372-a567-0e02b2c3d479","created_at":1776258580.7114341,"model":"Qwen/Qwen2.5-VL-7B-Instruct@main","object":"response","output":[],"status":"queued"},"sequence_number":0,"type":"response.created"}
data: {"content_index":0,"delta":"The ","item_id":"msg_f47ac10b","output_index":0,"sequence_number":5,"type":"response.output_text.delta"}
(...)استجابات مبنية على الصوت
import base64
from huggingface_hub.utils import httpx
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")
audio_url = "https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3"
audio_b64 = base64.b64encode(httpx.get(audio_url, follow_redirects=True).content).decode()
response = client.responses.create(
model="google/gemma-4-E2B-it",
input=[
{"type": "input_text", "text": "Transcribe this audio."},
{"type": "input_audio", "input_audio": {"data": audio_b64, "format": "mp3"}},
],
max_output_tokens=256,
stream=False,
)
print(response.output[0].content[0].text)يعيد عميل OpenAI نصاً مطبوعاً.
This week, I traveled to Chicago to deliver my final farewell address to the nation, following in the tradition of presidents before me. It was an opportunity to say thank you. Whether we've seen eye to eye or rarely agreed at all, my conversations with you, the American people, in living rooms and schools, at farms and on factory floors, at diners, and on distant military outposts, all these conversations are what have kept me honest.import base64
from huggingface_hub.utils import httpx
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")
audio_url = "https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3"
audio_b64 = base64.b64encode(httpx.get(audio_url, follow_redirects=True).content).decode()
response = client.responses.create(
model="google/gemma-4-E2B-it",
input=[
{"type": "input_text", "text": "Transcribe this audio."},
{"type": "input_audio", "input_audio": {"data": audio_b64, "format": "mp3"}},
],
}
],
max_output_tokens=256,
stream=True,
)
for event in response:
if hasattr(event, "delta") and event.delta:
print(event.delta, end="")يعيد عميل OpenAI نصاً مطبوعاً.
This week, I traveled to Chicago to deliver my final farewell address to the nation, following in the tradition of presidents before me. It was an opportunity to say thank you. Whether we've seen eye to eye or rarely agreed at all, my conversations with you, the American people, in living rooms and schools, at farms and on factory floors, at diners, and on distant military outposts, all these conversations are what have kept me honest.# First, base64-encode the audio file and build the JSON payload
AUDIO_B64=$(curl -sL https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3 | base64 -w 0)
cat <<EOF > /tmp/audio_request.json
{
"model": "google/gemma-4-E2B-it",
"input": [
{"type": "input_text", "text": "Transcribe this audio."},
{"type": "input_audio", "input_audio": {"data": "$AUDIO_B64", "format": "mp3"}}
],
"max_output_tokens": 256,
"stream": false
}
EOF
curl http://localhost:8000/v1/responses \
-H "Content-Type: application/json" \
-d @/tmp/audio_request.jsonيعيد الأمر نصًا بصيغة JSON.
{
"id": "resp_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"created_at": 1776258580.7114341,
"model": "google/gemma-4-E2B-it@main",
"object": "response",
"output": [
{
"id": "msg_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"content": [
{
"annotations": [],
"text": "This week, I traveled to Chicago to deliver my final farewell address to the nation [...]",
"type": "output_text"
}
],
"role": "assistant",
"status": "completed",
"type": "message"
}
],
"status": "completed"
}# First, base64-encode the audio file and build the JSON payload
AUDIO_B64=$(curl -sL https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3 | base64 -w 0)
cat <<EOF > /tmp/audio_request.json
{
"model": "google/gemma-4-E2B-it",
"stream": true,
"input": [
{"type": "input_text", "text": "Transcribe this audio."},
{"type": "input_audio", "input_audio": {"data": "$AUDIO_B64", "format": "mp3"}}
],
"max_output_tokens": 256
}
EOF
curl http://localhost:8000/v1/responses \
-H "Content-Type: application/json" \
-d @/tmp/audio_request.jsonيعيد الأمر تدفّقًا من المقاطع.
data: {"response":{"id":"resp_a1b2c3d4-e5f6-7890-abcd-ef1234567890","created_at":1776258580.7114341,"model":"google/gemma-4-E2B-it@main","object":"response","output":[],"status":"queued"},"sequence_number":0,"type":"response.created"}
data: {"content_index":0,"delta":"This ","item_id":"msg_a1b2c3d4","output_index":0,"sequence_number":5,"type":"response.output_text.delta"}
(...)نوع المحتوى
audio_urlهو امتداد لا يُعد جزءًا من معيار OpenAI وقد يتغير في الإصدارات المستقبلية.
يمكنك أيضًا تمرير الصوت عبر عنوان URL باستخدام نوع المحتوى audio_url لتجاوز الترميز base64.
response = client.responses.create(
model="google/gemma-4-E2B-it",
input=[
{"type": "input_text", "text": "Transcribe this audio."},
{"type": "audio_url", "audio_url": {"url": "https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3"}},
],
max_output_tokens=256,
stream=False,
)استجابات مبنية على الفيديو
نوع المحتوى
video_urlهو امتداد لا يُعد جزءًا من معيار OpenAI وقد يتغير في الإصدارات المستقبلية.
يتطلب معالجة الفيديو torchcodec. ثبّته باستخدام
pip install torchcodec.
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")
response = client.responses.create(
model="google/gemma-4-E2B-it",
input=[
{"type": "input_text", "text": "What is happening in the video and what is the song about?"},
{"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}},
],
max_output_tokens=256,
stream=False,
)
print(response.output[0].content[0].text)يعيد عميل OpenAI نصاً مطبوعاً.
The video captures a live music performance at a music festival or a large concert. There are several musicians on stage, including a central figure playing an acoustic guitar and singing. The foreground is filled with the backs of the audience, indicating a large crowd watching the show. The stage is dramatically lit with bright spotlights and blue and white stage lighting, with haze and smoke creating an immersive atmosphere.
The lyrics of the song are: "I don't care 'bout street, from that fresh street, 'cause there's no problem, another one I want to be, in the storm..."from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")
response = client.responses.create(
model="google/gemma-4-E2B-it",
input=[
{"type": "input_text", "text": "What is happening in the video and what is the song about?"},
{"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}},
],
max_output_tokens=256,
stream=True,
)
for event in response:
if hasattr(event, "delta") and event.delta:
print(event.delta, end="")يعيد عميل OpenAI نصاً مطبوعاً.
The video captures a live music performance at a music festival or a large concert. There are several musicians on stage, including a central figure playing an acoustic guitar and singing. The foreground is filled with the backs of the audience, indicating a large crowd watching the show. The stage is dramatically lit with bright spotlights and blue and white stage lighting, with haze and smoke creating an immersive atmosphere.
The lyrics of the song are: "I don't care 'bout street, from that fresh street, 'cause there's no problem, another one I want to be, in the storm..."curl http://localhost:8000/v1/responses \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemma-4-E2B-it",
"input": [
{"type": "input_text", "text": "What is happening in the video and what is the song about?"},
{"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}}
],
"max_output_tokens": 256,
"stream": false
}'يعيد الأمر نصًا بصيغة JSON.
{
"id": "resp_b2c3d4e5-f6a7-8901-bcde-f12345678901",
"created_at": 1776258580.7114341,
"model": "google/gemma-4-E2B-it@main",
"object": "response",
"output": [
{
"id": "msg_b2c3d4e5-f6a7-8901-bcde-f12345678901",
"content": [
{
"annotations": [],
"text": "The video captures a live music performance at a music festival or a large concert [...]",
"type": "output_text"
}
],
"role": "assistant",
"status": "completed",
"type": "message"
}
],
"status": "completed"
}curl http://localhost:8000/v1/responses \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemma-4-E2B-it",
"stream": true,
"input": [
{"type": "input_text", "text": "What is happening in the video and what is the song about?"},
{"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}}
],
"max_output_tokens": 256
}'يعيد الأمر تدفّقًا من المقاطع.
data: {"response":{"id":"resp_b2c3d4e5-f6a7-8901-bcde-f12345678901","created_at":1776258580.7114341,"model":"google/gemma-4-E2B-it@main","object":"response","output":[],"status":"queued"},"sequence_number":0,"type":"response.created"}
data: {"content_index":0,"delta":"Based ","item_id":"msg_b2c3d4e5","output_index":0,"sequence_number":5,"type":"response.output_text.delta"}
(...)المحادثات متعددة الأدوار
في حالة المحادثات متعددة الأدوار، مرّر قائمة من الرسائل تحتوي على مفاتيح role في حقل input. وكما هو الحال مع جميع الخوادم المتوافقة مع OpenAI، فإن الواجهة البرمجية (API) غير حالة، لذا يجب أن يحتوي كل طلب على سجل المحادثة الكامل.
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")
response = client.responses.create(
model="Qwen/Qwen2.5-0.5B-Instruct",
input=[
{"role": "user", "content": "What is the capital of France?"},
{"role": "assistant", "content": "The capital of France is Paris."},
{"role": "user", "content": "How many people live there?"},
],
max_output_tokens=256,
stream=False,
)
print(response.output[0].content[0].text)تعتمد السؤال اللاحق «كم عدد الأشخاص الذين يعيشون هناك؟» على السياق السابق، لذا يجيب النموذج عن باريس.
As of 2021, Paris has a population of approximately 2.8 million people.v1/systemone
يجيب نقطة النهاية v1/systemone على الأسئلة المُصنَّفة حول state مشترك، وذلك وفقاً لـ واجهة برمجة تطبيقات System One من TypeSafe. استخدمها لاتخاذ قرارات مثل توجيه تذكرة دعم، أو تقييم درجة الاستعجال، أو اختيار إجراء.
تُقيّم النموذج الإجابات المسموح بها في تمريرة أمامية واحدة مجمّعة دون توليد نص. يدعم هذا المنفذ النماذج التوليدية ذات القالب الدلالي (chat template)؛
أرسل نموذجًا، والحالة التي سيتم تقييمها، وأسئلة مفهرسة بالاسم:
curl http://localhost:8000/v1/systemone \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-1.5B-Instruct",
"state": "Our integration has been failing for 3 days and we are losing sales!",
"questions": {
"team": {
"type": "choice",
"instructions": "Which team handles this?",
"criteria": {"billing": null, "technical": "Bugs or integration problems"}
},
"urgency": {
"type": "score",
"instructions": "How urgent is this ticket?",
"criteria": ["low", "medium", "high"]
},
"upset": {"type": "noul", "instructions": "Is the customer upset?"}
}
}'قم بتثبيت TypeSafe SDK لإصدار Node.js 20 أو أحدث:
npm install @typesafe-ai/sdk
اضبط baseURL على جذر الخادم؛ حيث يضيف SDK المسار /v1/systemone. يتطلب SDK مفتاح API، لكن يمكن استخدام قيمة مؤقتة مع الخادم المحلي.
import { choice, noul, score, TypeSafeClient } from "@typesafe-ai/sdk";
const client = new TypeSafeClient({
baseURL: "http://localhost:8000",
apiKey: "<random_string>",
});
const response = await client.systemOne({
model: "Qwen/Qwen2.5-1.5B-Instruct",
state: "Our integration has been failing for 3 days and we are losing sales!",
questions: {
team: choice("Which team handles this?", {
billing: null,
technical: "Bugs or integration problems",
}),
urgency: score("How urgent is this ticket?", ["low", "medium", "high"]),
upset: noul("Is the customer upset?"),
},
});
console.log(response.answers.team.choice);
console.log(response.answers.urgency.score);
console.log(response.answers.upset.noul);يطبع العميل الفريق المختار، ونقاط الاستعجال، واحتمال أن يكون العميل غاضباً. على سبيل المثال:
technical 1.6739138662815094 0.851952850818634
تستخدم الإجابات أسماء الأسئلة نفسها. على سبيل المثال:
{
"model": "Qwen/Qwen2.5-1.5B-Instruct",
"answers": {
"team": {"type": "choice", "choice": "technical", "probabilities": {"billing": 0.000006962256520637311, "technical": 0.999993085861206}, "confidence": 0.9999861717224121},
"urgency": {"type": "score", "score": 1.6739138662815094, "legend": {"0": "low", "1": "medium", "2": "high"}, "probabilities": {"0": 0.0031353600788861513, "1": 0.31981542706489563, "2": 0.6770492196083069}, "confidence": 0.5108707791659981},
"upset": {"type": "noul", "noul": 0.851952850818634}
},
"usage": {"input_tokens": 213, "output_tokens": 0}
}| نوع السؤال | criteria | الإجابة |
|---|---|---|
choice | أسماء الخيارات المرتبطة بالوصف، والتي يمكن أن تكون null. | الخيار الأكثر احتمالاً، واحتمالات الخيارات، ومستوى الثقة. |
score | وصف المستويات مرتبة من الأدنى إلى الأعلى. | مؤشر المستوى المرجّح بالاحتمالات، والاحتمالات، ومفتاح الرموز، ومستوى الثقة. |
noul | وصف اختياري لـ true وfalse. | احتمال true. |
state، وتعليمات اختيارية instructions، ويمكن أن تحتوي الأوصاف على نصوص أو كائنات JSON ومصفوفات. تقبل كل طلب حتى 64 سؤالاً، مع 1–26 خياراً أو مستوى تقييم لكل سؤال.
للنماذج القادرة على الرؤية، أضف مصفوفة images تحتوي على ما يصل إلى أربعة عناوين data:image/...;base64,.... تتلقى كل صورة نفس الصور. يجب أن يدعم معالج النموذج وقالب المحادثة الصور؛ ولا يتم قبول عناوين الصور عن بُعد.
إعدادات القرار
لا تشارك نماذج القرار بعد معيارًا موحّدًا لتخزين الأوامر (prompts) وتسميات الإجابات وإعدادات المعايرة. وتختلف هذه العناصر بين تنفيذه نماذج مختلفة، لذا يتيح لك --decision-config تقديمها بشكل صريح. لا تزال النماذج التي تحتوي على رؤوس قرار مخصصة تتطلب تنفيذًا متوافقًا؛ فملف الإعدادات هذا يهيّك فقط تنسيق الأوامر وتقييم الرمز التالي.
افتراضيًا، تستخدم الأسئلة موجهًا احتياطيًا وقالب المحادثة الخاص بالنموذج مع تعطيل التفكير. وتكون تسميات الإجابات A–Z للخيارات والدرجات، وYes/No للقيم المنطقية. وتُحسب الاحتمالات عبر دالة softmax على هذه التسميات عند درجة حرارة 1.
مرّر --decision-config لتجاوز هذه الإعدادات الافتراضية لنموذج:
transformers serve openjev/openjev --decision-config decision.json
يدعم ملف JSON ثلاثة حقول اختيارية:
| الحقل | المعنى |
|---|---|
labels | تسميات الإجابات حسب نوع السؤال، بترتيب الخيارات (true، ثم false لـnoul). يجب أن تكون كل تسمية رمزًا فرديًا معروفًا ومتميزًا. |
temperature | درجات حرارة موجبة حسب نوع السؤال، مطبقة على شكل softmax(label_logits / temperature). |
chat_template | قالب Jinja مضمّن يستبدل الموجه الكامل، بما في ذلك تنسيق المحادثة والبادئة الخاصة بالمساعد. |
على سبيل المثال، لتغيير التسميات والمعايرة مع الحفاظ على الموجه الافتراضي:
{
"labels": {"noul": ["A", "B"]},
"temperature": {"choice": 0.85, "score": 0.85, "noul": 1.5547129}
}يستقبل القالب المخصص حقول messages المعتادة، بالإضافة إلى حقول state وimages وquestion الخام. يكشف سؤال name وtype وinstructions وoptions وlabels وdescriptions وlegend؛ وتشارك الخيارات والتسميات والوصف نفس الترتيب. استخدم هذه الحقول لاستبدال الصياغة الاحتياطية، واستخدم tojson لعرض القيم المهيكلة. يجب أن تتضمن القوالب الخاصة بإدخالات الصور مكان وضع صورة النموذج.
يتم تحميل الملف عند بدء التشغيل وينطبق على /v1/systemone فقط. تُحافظ الإعدادات غير المذكورة على قيمها الافتراضية؛ ولا يتم قراءة أي تكوين للقرار تلقائيًا من نقطة التفتيش.
v1/audio/transcriptions
ينقل نقطة النهاية v1/audio/transcriptions الصوت إلى نص باستخدام نماذج تحويل الكلام إلى نص. وهي تتبع صيغة واجهة برمجة تطبيقات نقل الصوت إلى نص.
curl -X POST http://localhost:8000/v1/audio/transcriptions \ -H "Content-Type: multipart/form-data" \ -F "file=@/path/to/audio.wav" \ -F "model=openai/whisper-large-v3"
يعيد الأمر الاستجابة التالية.
{
"text": "Transcribed text from the audio file",
}v1/models
يفحص نقطة النهاية v1/models ذاكرة التخزين المؤقت المحلية الخاصة بك على Hugging Face، ويعيد قائمة بالنماذج التي تم تنزيلها في الصيغة المتوافقة مع OpenAI. تستخدم الأدوات من أطراف ثالثة هذه نقطة النهاية للاطلاع على النماذج المتاحة.
قم بتنزيل نموذج قبل تشغيل transformers serve.
transformers download Qwen/Qwen2.5-0.5B-Instruct
بمجرد تنزيله، يظهر النموذج في استجابات /v1/models.
curl http://localhost:8000/v1/models
يعيد نقطة النهاية كائن JSON يحتوي على النماذج المتاحة.
تحميل النماذج
يُحمّل نقطة النهاية /load_model نموذجًا مسبقًا ويبثّ تقدّم العملية عبر Server-Sent Events (SSE). يستخدم سطر الأوامر transformers chat هذه النقطة تلقائيًا حتى يرى المستخدمون تقدّم التنزيل والتحميل بدلًا من واجهة أوامر معلّقة. استخدمها لتسخين نموذج قبل إرسال طلبات الاستدلال.
طلب
curl -N -X POST http://localhost:8000/load_model \
-H "Content-Type: application/json" \
-d '{"model": "Qwen/Qwen2.5-0.5B-Instruct"}'حقل model هو معرّف لنموذج على Hugging Face، مع لاحقة @revision اختيارية (Qwen/Qwen2.5-0.5B-Instruct@main). عند حذف النسخة، يكون الافتراضي main.
الاستجابة
الاستجابة هي تدفق SSE (Content-Type: text/event-stream). كل إطار هو كائن JSON على سطر data:.
data: {"status": "loading", "model": "Qwen/Qwen2.5-0.5B-Instruct@main", "stage": "processor"}تحتوي كل حالة على حقل status وحقل model كحد أدنى. وتعتمد الحقول الإضافية على الحالة.
| الحقل | يوجد عند | الوصف |
|---|---|---|
status | دائمًا | loading أو ready أو error |
model | دائمًا | المعرّف القياسي model_id@revision |
stage | status == "loading" | أحد processor، config، download، weights (انظر المراحل أدناه) |
progress | مراحل download وweights | كائن يحتوي على current وtotal (عدد صحيح أو null) |
cached | status == "ready" | true إذا كان النموذج موجودًا بالفعل في الذاكرة |
message | status == "error" | وصف الخطأ |
المراحل
يتقدم التحميل عبر هذه المراحل بالترتيب. وقد يتم تجاوز بعض هذه المراحل (يتم تجاوز download عندما تكون الملفات مخزنة مسبقًا في ذاكرة التخزين المؤقت محليًا).
| المرحلة | هل هناك تقدم؟ | الوصف |
|---|---|---|
processor | لا | تحميل مُجزِّئ/معالج |
config | لا | تحميل إعدادات النموذج |
download | نعم (بايت) | تنزيل ملفات النموذج |
weights | نعم (العناصر) | تحميل متجهات الأوزان إلى الذاكرة |
ينتهي البث بحدث نهائي واحد بالضبط، إما ready (نجاح) أو error (فشل).
مهلة
يتولى transformers serve معالجة الطلبات الخاصة بأي نموذج. يتم تحميل كل نموذج عند الطلب ويبقى في ذاكرة وحدة معالجة الرسوميات (GPU). يتم تفريغ النماذج تلقائيًا بعد 300 ثانية من عدم النشاط لتحرير ذاكرة وحدة معالجة الرسوميات. اضبط --model-timeout على قيمة مختلفة بالثواني، أو اضبط -1 لتعطيل التفريغ.
transformers serve --model-timeout 400
تحميل الأمثلة
تُظهر الأمثلة أدناه استجابات لنموذج تم تنزيله حديثاً، ونموذج تم تحميله من ذاكرتك المؤقتة المحلية (يتخطى مرحلة التنزيل)، ونموذج موجود بالفعل في الذاكرة.
data: {"status": "loading", "model": "org/model@main", "stage": "processor"}
data: {"status": "loading", "model": "org/model@main", "stage": "config"}
data: {"status": "loading", "model": "org/model@main", "stage": "download", "progress": {"current": 0, "total": 269100000}}
data: {"status": "loading", "model": "org/model@main", "stage": "download", "progress": {"current": 134600000, "total": 269100000}}
data: {"status": "loading", "model": "org/model@main", "stage": "download", "progress": {"current": 269100000, "total": 269100000}}
data: {"status": "loading", "model": "org/model@main", "stage": "weights", "progress": {"current": 1, "total": 272}}
data: {"status": "loading", "model": "org/model@main", "stage": "weights", "progress": {"current": 272, "total": 272}}
data: {"status": "ready", "model": "org/model@main", "cached": false}data: {"status": "loading", "model": "org/model@main", "stage": "processor"}
data: {"status": "loading", "model": "org/model@main", "stage": "config"}
data: {"status": "loading", "model": "org/model@main", "stage": "weights", "progress": {"current": 1, "total": 272}}
data: {"status": "loading", "model": "org/model@main", "stage": "weights", "progress": {"current": 272, "total": 272}}
data: {"status": "ready", "model": "org/model@main", "cached": false}data: {"status": "ready", "model": "org/model@main", "cached": true}استدعاء الأدوات
يدعم خادم transformers serve استدعاء الدوال بنمط OpenAI. تولّد النماذج المدرَّبة لاستخدام الأدوات استدعاءات دوال منظمة تنفّذها تطبيقك.
يعمل استدعاء الأدوات مع أي نموذج يُعلن مُجزّئُه عن رموز استدعاء الأدوات. تعمل نماذج Qwen و Gemma 4 دون أي إعداد مسبق. افتح قضية لطلب دعم نموذج محدد.
حدّد الأدوات على شكل قائمة من مواصفات الدوال وفق صيغة OpenAI.
import json
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<KEY>")
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather in a location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city name, e.g. San Francisco"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "temperature unit"
}
},
"required": ["location"]
}
}
}
]يمكنك تخصيص عملية التوليد عن طريق تمرير معاملات GenerationConfig إلى معامل extra_body في create.
generation_config = {
"max_new_tokens": 512,
"temperature": 0.7,
"top_p": 0.9,
"top_k": 50,
"do_sample": True,
"repetition_penalty": 1.1,
"no_repeat_ngram_size": 3,
}
response = client.responses.create(
model="Qwen/Qwen2.5-7B-Instruct",
instructions="You are a helpful weather assistant. Use the get_weather tool to answer questions.",
input="What's the weather like in San Francisco?",
tools=tools,
stream=True,
extra_body={"generation_config": json.dumps(generation_config)}
)
for event in response:
print(event)استدعاء الأدوات متعدد الأدوار
بعد أن يُرجع النموذج استدعاءً لأداة، نفّذ الدالة محليًا، ثم أرسل النتيجة مرة أخرى في طلب متابعة للحصول على الإجابة النهائية من النموذج. يختلف النمط قليلاً بين الواجهتين البرمجيتين. راجع دليل استدعاء الدوال في OpenAI للاطلاع على المواصفات الكاملة.
تعتمد الأمثلة أدناه على قائمة tools المعرّفة أعلاه.
مرّر نتيجة الأداة كرسالة بدور role: "tool" مع tool_call_id المطابق.
# Model returns a tool call
messages = [{"role": "user", "content": "What's the weather like in San Francisco?"}]
response = client.chat.completions.create(
model="Qwen/Qwen2.5-7B-Instruct",
messages=messages,
tools=tools,
)
assistant_message = response.choices[0].message
# Execute the tool locally
tool_call = assistant_message.tool_calls[0]
result = {"temperature": 22, "condition": "sunny"} # your actual function call here
# Send the tool result back
messages.append(assistant_message)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result),
})
final_response = client.chat.completions.create(
model="Qwen/Qwen2.5-7B-Instruct",
messages=messages,
tools=tools,
)
print(final_response.choices[0].message.content)مرّر نتيجة الأداة كعنصر function_call_output ضمن قائمة input في الطلب اللاحق.
user_message = {"role": "user", "content": "What's the weather like in San Francisco?"}
response = client.responses.create(
model="Qwen/Qwen2.5-7B-Instruct",
input=[user_message],
tools=tools,
stream=False,
)
tool_call = next(item for item in response.output if item.type == "function_call")
result = {"temperature": 22, "condition": "sunny"}
final_response = client.responses.create(
model="Qwen/Qwen2.5-7B-Instruct",
input=[
user_message,
tool_call.model_dump(exclude_none=True),
{"type": "function_call_output", "call_id": tool_call.call_id, "output": json.dumps(result)},
],
tools=tools,
stream=False,
)
print(final_response.output_text)الاستدلال
تُصدر نماذج الاستدلال سلسلة تفكير مخفية قبل الإجابة النهائية. يكتشف الخادم هذه المقاطع الخاصة بالتفكير، ويحذف الفواصل من الإجابة الظاهرة، ويعرض نص الاستدلال في حقل مخصص حتى يتمكن العملاء من عرضه بشكل منفصل.
- يعيد Chat Completions الاستدلال في حقل
reasoning_contentضمن رسالة المساعد. - تُعيد واجهة برمجة التطبيقات الخاصة بالاستجابات الاستدلال كعنصر مخرجات
reasoningيسبق عنصرmessage.
يعتمد كشف الاستدلال على قالب استجابة، يحدد للمُخدِّم مكان بداية ونهاية نطاق التفكير. يبحث المُخدِّم عن هذا القالب في مكانين، بالترتيب التالي.
- خاصية
response_templateفي مُجزِّئ الرموز، إذا كان النموذج يتضمنها. - خيار احتياطي مدمج يتم مطابقته بناءً على بنية النموذج، وذلك لمعالجات الرموز التي لا تتضمن قالبًا بعد.
تُقدَّم النماذج التي لا تحتوي على أيٍّ من هذين العنصرين دون تحليل للاستجابة. حيث يُعاد النص المُفكَّك الخام كـcontent ولا يظهر أي حقل للتفكير، حتى لو أصدر النموذج وسوم <think>...</think>.
تفعيل الاستدلال على الخادم
استخدم --reasoning للتحكم في ما إذا كان قالب المحادثة (chat template) يُصدر رموز التفكير (thinking tokens) أم لا.
| القيمة | السلوك |
|---|---|
auto (الافتراضي) | اتبع القيمة الافتراضية لقالب المحادثة. |
on | قم بتفعيل التفكير إجبارياً من خلال تعيين enable_thinking=True في معاملات قالب المحادثة. |
off | قم بإيقاف التفكير إجبارياً عن طريق تعيين enable_thinking=False. |
transformers serve Qwen/Qwen3-1.7B --reasoning on
لا تدعم جميع نماذج الاستدلال. يعمل
--reasoningفقط عندما يتعامل قالب المحادثة الخاص بالنموذج مع متغيرenable_thinking(أو عندما يُعلن مُجزّئ الرموز الخاص به عن فواصل التفكير). أما بالنسبة للنماذج الأخرى، فيتم تجاهل هذا العلم بصمت.
يعمل --reasoning on و--reasoning off من خلال تعيين متغيّر قالب المحادثة enable_thinking. تستخدم بعض قوالب المحادثة اسم متغيّر مختلف لتبديل التفكير، أو تقبل متغيّرات إضافية تغيّر طريقة عرض الموجه. يمكنك تمرير أي متغيّر من متغيّرات قالب المحادثة مباشرةً باستخدام --chat-template-kwargs ككائن JSON.
transformers serve Qwen/Qwen3-1.7B \
--chat-template-kwargs '{"enable_thinking": true}'يمكن للعملاء أيضًا إرسال chat_template_kwargs في جسم الطلب لتجاوز الإعدادات الافتراضية للخادم لطلب واحد، دون الحاجة إلى إعادة تشغيل الخادم.
اكتمالات الدردشة
تتضمن الاستجابات غير المتدفقة reasoning_content إلى جانب content في رسالة المساعد.
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="<KEY>")
completion = client.chat.completions.create(
model="Qwen/Qwen3-1.7B",
messages=[{"role": "user", "content": "What is 17 * 23?"}],
)
message = completion.choices[0].message
print("reasoning:", message.reasoning_content)
print("answer:", message.content)تصدر البث دلتات reasoning_content قبل دلتات content. قم بدمج كل حقل على حدة.
chunks = list(
client.chat.completions.create(
model="Qwen/Qwen3-1.7B",
messages=[{"role": "user", "content": "What is 17 * 23?"}],
stream=True,
)
)
reasoning = "".join(getattr(c.choices[0].delta, "reasoning_content", None) or "" for c in chunks)
content = "".join(c.choices[0].delta.content or "" for c in chunks)curl -X POST http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen3-1.7B",
"messages": [{"role": "user", "content": "What is 17 * 23?"}],
"chat_template_kwargs": {"enable_thinking": true}
}'يتضمن الرد reasoning_content في رسالة المساعد.
{
"choices": [
{
"message": {
"role": "assistant",
"content": "17 * 23 = 391.",
"reasoning_content": "Let me compute 17 * 23. 17 * 20 = 340, 17 * 3 = 51, so 340 + 51 = 391."
},
"finish_reason": "stop",
"index": 0
}
]
}واجهة برمجة التطبيقات للاستجابات
تُعيد واجهة برمجة التطبيقات الخاصة بالاستجابات الاستدلال كعنصر مخرجات منفصل باسم reasoning يسبق عنصر message.
response = client.responses.create(
model="Qwen/Qwen3-1.7B",
input="What is 17 * 23?",
stream=False,
)
reasoning_item = next(i for i in response.output if i.type == "reasoning")
message_item = next(i for i in response.output if i.type == "message")
print("reasoning:", reasoning_item.content[0].text)
print("answer:", message_item.content[0].text)يفتح البث عنصر الاستدلال أولاً ويصدر أحداث response.reasoning_text.delta، ثم يغلقه ويفتح عنصر الرسالة لإصدار أحداث response.output_text.delta.
stream = client.responses.create(
model="Qwen/Qwen3-1.7B",
input="What is 17 * 23?",
stream=True,
)
for event in stream:
if event.type == "response.reasoning_text.delta":
print(event.delta, end="")
elif event.type == "response.output_text.delta":
print(event.delta, end="")رحلة ذهاب وإياب متعددة الجولات
في محادثات متعددة الأدوار، شمل نص الاستدلال من الاستجابة السابقة في الطلب التالي. يمرر الخادم هذا النص إلى قالب المحادثة، الذي يمكنه عرضه كجزء من دور المساعد السابق، بحيث يرى النموذج عملية التفكير السابقة له.
أرفق reasoning_content برسالة المساعد السابقة.
first = client.chat.completions.create(
model="Qwen/Qwen3-1.7B",
messages=[{"role": "user", "content": "What is 17 * 23?"}],
).choices[0].message
second = client.chat.completions.create(
model="Qwen/Qwen3-1.7B",
messages=[
{"role": "user", "content": "What is 17 * 23?"},
{
"role": "assistant",
"content": first.content,
"reasoning_content": first.reasoning_content,
},
{"role": "user", "content": "Now multiply that result by 2."},
],
)
print(second.choices[0].message.content)مرّر عنصر reasoning السابق كعنصر إدخال قبل رسالة المساعد.
first = client.responses.create(
model="Qwen/Qwen3-1.7B",
input="What is 17 * 23?",
stream=False,
)
reasoning_item = next(i for i in first.output if i.type == "reasoning")
message_item = next(i for i in first.output if i.type == "message")
second = client.responses.create(
model="Qwen/Qwen3-1.7B",
input=[
{"role": "user", "content": "What is 17 * 23?"},
reasoning_item.model_dump(exclude_none=True),
{"role": "assistant", "content": message_item.content[0].text},
{"role": "user", "content": "Now multiply that result by 2."},
],
stream=False,
)
print(second.output_text)إعادة توجيه المنافذ
يتيح لك توجيه المنافذ تقديم النماذج من خادم بعيد. تأكد من أنك تملك وصولاً عبر SSH إلى الخادم، ثم نفّذ هذا الأمر على جهازك المحلي.
ssh -N -f -L 8000:localhost:8000 your_server_account@your_server_IP -p port_to_ssh_into_your_server
إمكانية التكرار
مرّر نموذجًا كحجج موضعية لتجنب تلميحات النموذج لكل طلب، ولإنتاج تشغيلات مستقرة وقابلة للتكرار.
transformers serve Qwen/Qwen2.5-0.5B-Instruct \
--continuous-batching \
--dtype "bfloat16"