استكشاف الأخطاءدليل
400 بعد استدعاء أداة: أعد إرسال reasoning_content
لماذا يعيد الطلب الثاني لحلقة استدعاء أداة رمز 400 على نموذج تفكير، وإصلاح بـ Python يلحق الرسالة كاملة، ومتى يمكنك تخطيه.

في هذه الصفحة
حلقة الوكيل الخاصة بك تعمل في الطلب الأول وتفشل في الثاني برمز 400. في نموذج تفكير، أحد الأسباب الموثقة هو حقل مفقود: رسالة المساعد التي ترسلها مرة أخرى فقدت reasoning_. إذا كان هذا هو السبب، فإن إلحاق الرسالة كاملة تمامًا كما أعادتها واجهة API يحل المشكلة.
دليل وضع التفكير من DeepSeek (الوثائق، تم التحقق في 8 نوفمبر 2026) يضع القاعدة في جملة واحدة: عندما يحتوي الطلب على المعامل tools، يجب إعادة تمرير reasoning_ بالكامل في جميع الطلبات اللاحقة، بما في ذلك الأدوار التي لا تتضمن استدعاء أداة. وإلا فإن واجهة API تعيد 400. وتقول نفس الصفحة إن التفكير مفعّل افتراضيًا، بجهد high. لذا فإن حلقة كتبتها لنموذج غير مفكر يمكن أن تتعطل دون تغيير سطر واحد.
ما يحدث بين الطلب الأول والطلب الثاني#
في وضع التفكير تعود سلسلة التفكير في reasoning_، وهو حقل على نفس مستوى content. تخيل الحلقة:
- ترسل السؤال وقائمة
tools. - يجيب النموذج بـ
tool_calls(وreasoning_بجانبها).content - تشغّل الأداة وترسل كل شيء مرة أخرى: السجل، ورسالة المساعد، ورسالة
toolبالنتيجة.
يظهر الخطأ 400 في الطلب في الخطوة 3 إذا كانت رسالة المساعد فيه لا تحتوي على reasoning_.

صفحة DeepSeek توثق الخطأ 400 فقط لحالة استدعاء الأداة هذه ولا تقتبس نص خطأ، لذا انظر إلى حالة HTTP، وليس إلى رسالة محددة، عندما تتحقق مما إذا كانت لديك هذه المشكلة.
الإصلاح: ألحق الرسالة كما أُعيدت#
الخطوة الأكثر أمانًا هي عدم إعادة بناء رسالة المساعد على الإطلاق. خذها من الاستجابة وألحقها كاملة. إليك حلقة كاملة باستخدام OpenAI Python SDK موجهة إلى CheapTokens. أداة الطقس هي دالة وهمية، لذا يمكنك تشغيلها كما هي.
import json, os
from openai import OpenAI
client = OpenAI(
base_url="https://api.cheaptokens.dev/v1",
api_key=os.environ["CHEAPTOKENS_API_KEY"],
)
MODEL = "deepseek-ai/DeepSeek-V4-Flash-0731"
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Current weather for a city",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
},
}]
def get_weather(city):
return {"city": city, "temp_c": 7} # stub
messages = [{"role": "user", "content": "Do I need a jacket in Oslo today?"}]
for _ in range(5): # hard step limit
resp = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
msg = resp.choices[0].message
messages.append(msg.model_dump(exclude_none=True)) # the whole message
if not msg.tool_calls:
print(msg.content)
break
for call in msg.tool_calls:
args = json.loads(call.function.arguments)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(get_weather(**args)),
})السطر الوحيد المهم هو messages.. يحتفظ SDK بالحقول التي لا يعرفها، لذا فإن أي شيء وضعته واجهة API على الرسالة، بما في ذلك reasoning_، ينتقل معها. يتم إلحاق الإجابة النهائية أيضًا، وهذا ما تطلبه القاعدة: بعد استدعاء الأداة الأول، يحمل كل طلب لاحق تفكير أدوار المساعد السابقة.
آليات استدعاء الأداة نفسها (المخطط، tool_call_id، تحليل الوسائط) موجودة في استدعاء الدوال في Python باستخدام واجهة API متوافقة مع OpenAI. عنوان URL الأساسي والمفتاح ومعرّف النموذج موجودة في صفحة وثائق CheapTokens؛ النموذج المستخدم هنا موصوف في صفحة DeepSeek: سياق 380K وحتى 32,768 رمز إخراج لكل إجابة، مما يترك مجالًا لتفكير طويل بالإضافة إلى إجابة.
سبب شائع: رسالة أعيد بناؤها يدويًا#
طريقة شائعة لفقدان الحقل هي الكود الذي لا يلحق كائن الاستجابة بل يبني قاموسًا جديدًا. يبدو غير ضار: الدور، المحتوى، استدعاءات الأدوات. تفعل الأطر والمغلفات الشيء نفسه عندما تخزن السجل بتنسيقها الخاص. الحقل الوحيد الذي لم يسمعوا به هو الذي يضيع.

قارن
أعيد بناؤها يدويًا مقابل إلحاقها كاملة
أعيد بناؤها يدويًا (تتعطل)
messages.append({
"role": "assistant",
"content": msg.content,
"tool_calls": [c.model_dump() for c in msg.tool_calls],
})ملحقة كاملة (تعمل)
messages.append(msg.model_dump(exclude_none=True))إذا كنت تستخدم إطارًا ولا يمكنك لمس ذلك السطر، فتحقق من كيفية تخزينه لأدوار المساعد. السجل الذي يمر عبر مُسلسِل يحتفظ فقط بـ content وtool_calls لديه نفس الخلل، لكن على طبقة أدنى.
عندما لا تحتاج إلى هذا#
ليس كل استدعاء لنموذج تفكير يحتاج إلى العناية الإضافية. للمحادثة متعددة الأدوار بدون أدوات، يقول دليل DeepSeek إن reasoning_ لا يجب إعادة تمريره؛ إذا أرسلته على أي حال، يتم تجاهله ولا يضاف التفكير السابق إلى السياق. لذا يمكن للمحادثة العادية الاستمرار في إسقاطه ولن ينكسر شيء.
اختر حالتك
أي حالة تنطبق عليك؟
اختر خيارًا لعرض الإجابة
الطلب يحتوي على tools، والنموذج يفكر
ألحق رسالة المساعد كاملة في كل دور، أدوار الأدوات والإجابات النهائية على حد سواء.
محادثة عادية، بدون معامل tools
لا حاجة لإصلاح. يمكنك إسقاط reasoning_ من السجل، أو إرساله؛ يتم تجاهله.
إطار يبني السجل نيابة عنك
ابحث عن المكان الذي يسلسل فيه رسائل المساعد وتأكد من بقاء reasoning_. إذا لم يكن ممكنًا، فاستدعِ واجهة API بحلقتك الخاصة لجزء الأداة.
أثر جانبي يجب تذكره: السجل الذي تعيد إرساله هو مدخلات في كل طلب، لذا فإن التفكير الطويل في حلقة طويلة يتراكم. كيفية حساب رموز التفكير مشمولة في جهد التفكير ورموز التفكير، وما يجب فعله عندما يتجاوز الطلب حدود النموذج موجود في الطلب طويل جدًا: 400 مقابل 413.
إذا استمر إرجاع 400#
اتبع هذا بالترتيب:
- اطبع
messagesمباشرة قبل الاستدعاء الفاشل. هل كل رسالة مساعد جاءت من النموذج تحتوي علىreasoning_، إذا كانت الاستجابة تحتوي عليها؟content - هل تعيد بناء رسالة في أي مكان: دالة مساعدة، فئة سجل،
json.dumpsثم العودة بقائمة مفاتيح ثابتة؟ - هل رسالة
toolلكلtool_call_idموجودة، بنفس المعرّف؟ - هل هو حقًا الطول؟ الطلب الذي يتجاوز حد السياق هو 400 مختلف، موصوف في المقال أعلاه.
فحص سريع
ماذا تلحق بعد أن يطلب النموذج أداة؟
إظهار الإجابة
الإجابة: رسالة المساعد كاملة كما أُعيدت، بما في ذلك reasoning_content
استدعاءات الأدوات هي ما تجيب عليه رسائل الأدوات الخاصة بك، ومع وجود الأدوات في الطلب يجب أن يرافقها التفكير.
هذا هو الإصلاح كله: إلحاق واحد، بدون إعادة بناء. أضف حد الخطوات من المثال إلى أي حلقة تنشرها، حتى يكلف الدور السيئ خمسة طلبات، وليس خمسمائة.



