DanLevy.net

توقف عن طلب الرياضيات من نماذج اللغة الكبيرة

إنهم سيئون في ذلك. إليك طريقة الإصلاح.

أنت تعرف ما الغريب في نماذج اللغة؟ يمكنها شرح ميكانيكا الكم، كتابة شعر، وتصحيح أخطاء TypeScript الخاص بك… لكن إذا طلبت منها ضرب 18472 في 9347 فهناك احتمال كبير أن تعطيك نتيجة خاطئة بثلاثة آلاف تقريبًا بثقة تامة.

كان هذا يحيّرني حتى أدركت ما نطلبه منها فعليًا. نحن نطلب من محرك مطابقة الأنماط أن يكون حاسبة. هذا يشبه طلب من لاعب جمباز أن يوازن دفتر حساباتك لأنه يفهم مفهوم “التوازن”.

المسألة هي أن نماذج اللغة الكبيرة لا تحسب شيئًا. عندما تسأل GPT أو Claude ما ناتج 2 + 2، فإنهما لا يجريان عملية جمع. إنهما يتوقعان أن “4” هو الرمز الأكثر احتمالًا للظهور بعد “2 + 2 =”. في معظم الأحيان، ينجح هذا لأن هذه الأنماط موجودة في بيانات التدريب. لكن إذا تجاوزت الحسابات البسيطة إلى عمليات متعددة الخطوات أو أية أرقام لم تكن شائعة في التدريب، فأنت في الأساس ترمي النرد.

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

حتى مع تحسن النماذج في الاستدلال (يُقال إن GPT‑5 يظهر تحسينات)، فإنها لا تزال تقوم بمطابقة أنماط متقدمة، وليس حسابًا رمزيًا. بالنسبة للأعمال الإبداعية ومهام اللغة الطبيعية، هذه الطبيعة الاحتمالية هي ما يجعلها سحرية. أما بالنسبة للرياضيات؟ فليس الأمر كذلك.

ما هو الحل الفعلي؟

الإجابة ليست انتظار نماذج أذكى. بل إعطاء النموذج الأداة المناسبة للمهمة.

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

استدعاء الأدوات في SDKs الذكاء الاصطناعي الحديثة يتيح لنا تزويد النموذج بدوال منظمة يمكنه استدعاؤها. بدلاً من إجبار النموذج على تمثيل أنه يعرف الرياضيات، نمنحه ما يفعله فعليًا: محرك رياضيات رمزي.

لقد استخدمت AI SDK v5 و v6 لهذا الغرض، مقترنًا بـ CortexJS Compute Engine. يتولى SDK تنسيق العملية وتوجيه الأدوات، بينما يتعامل CortexJS مع أي شيء من الحسابات الأساسية إلى حساب التفاضل والتكامل. إنه فصل واضح ومفاجئ للمهام.

Terminal window
bun add ai @ai-sdk/anthropic @cortex-js/compute-engine zod

بناء أداة الرياضيات

التنفيذ أبسط مما قد تتوقع. ما نبنيه هو جسر بين فهم النموذج للغة الطبيعية والحساب الرياضي الفعلي.

import { generateText, stepCountIs, tool } from 'ai';
import { ComputeEngine } from '@cortex-js/compute-engine';
import { z } from 'zod';
// تهيئة المحرك مرة واحدة
const ce = new ComputeEngine();
const mathTool = tool({
description: 'Evaluate mathematical expressions and solve equations with guaranteed accuracy. MUST be used for all mathematical operations to verify correctness - do not attempt mental math. Supports arithmetic, algebra, calculus, and complex operations. Can process multiple expressions at once.',
parameters: z.object({
expressions: z.array(z.string()).describe(
'Array of mathematical expressions in LaTeX or plain notation, e.g. ["2 + 2", "\\frac{x^2 + 1}{x - 1}", "\\int x^2 dx"]'
),
}),
execute: async ({ expressions }) => {
// معالجة جميع التعبيرات بالتوازي (أو دفعة مفصلة)
return expressions.map(expression => {
try {
const result = ce.parse(expression).evaluate();
return {
expression,
result: result.toString(),
latex: result.latex,
};
} catch (error) {
return {
expression,
error: (error as Error).message
};
}
});
},
});

بعض النقاط التي تستحق الذكر حول هذا:

الوصف يتحمل الجزء الأكبر من العبء. قد يبدو أن عبارة “MUST be used” عدوانية، لكن في تجربتي، كونك صريحًا مع النموذج حول متى يستخدم الأداة هو الفارق بين عمله أحيانًا وعمله بشكل موثوق دائمًا. اعتبرها هندسة توجيه على مستوى الأداة.

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

استخدام محرك رمزي بدلاً من eval() (من فضلك لا تستخدم eval()) يمنحنا فهماً رياضياً حقيقيًا. المحرك يحلل النية، يتعامل مع تنسيق LaTeX، ويمكنه العمل مع المشتقات والتكاملات. نحن لا نجري مجرد حسابات، بل نؤدي رياضيات.

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

وضعها موضع التنفيذ

لنرمي شيئًا عليها عادةً ما يجعل نموذجًا خامًا يهلوس:

import { anthropic } from '@ai-sdk/anthropic';
const { text } = await generateText({
model: anthropic('claude-sonnet-4-5'),
prompt: 'Calculate 18472 × 9347, divide by 127, then take the square root of the result.',
tools: { mathTool },
stopWhen: stepCountIs(5), // السماح بما يصل إلى خمس خطوات نموذج/أداة
});
console.log(text);

النموذج يرى العملية الرياضية، يدرك الحاجة إلى الدقة، يستدعي الأداة، يحصل على النتيجة الدقيقة، ثم يشرحها بلغة طبيعية. كل مكوّن يقوم بما يجيده.

ما وراء الحساب الأساسي

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

هل تريد حل معادلات جبرية؟ “حل هذه المعادلات: 3x + 7 = 22 و 2y - 5 = 13” يعمل بشكل جيد.

هل تحتاج إلى حسابات تفاضلية وتكاملية؟ “احسب مشتقة x^3 + 2x^2 وقيّمها عند x = 2” هو مجرد استدعاء أداة آخر.

دعم LaTeX مفيد بشكل خاص إذا كنت تبني تطبيقات تعليمية. المحرك يفهم إدخال LaTeX بطبيعته ويمكنه إرجاع النتائج بصيغة جاهزة للعرض. لا حاجة إلى أي تحليل إضافي.

الصورة الأكبر

أعتقد أن هذا النمط له أهمية تتجاوز مجرد الرياضيات. ما نفعله فعليًا هو الاعتراف بحدود نماذج اللغة الكبيرة مع الاستفادة من نقاط قوتها. فهي ممتازة في فهم النوايا، وتحليل اللغة الطبيعية، وتنسيق سير العمل. لكنها ليست آلات حاسبة ولا قواعد بيانات ولا أنظمة ملفات.

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

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

إنها تحول في طريقة تفكيرنا في بناء الأنظمة باستخدام الذكاء الاصطناعي. ليس “هل يستطيع النموذج القيام بهذا؟” بل “هل يستطيع النموذج تنسيق هذا؟” فرق بسيط في الصياغة، لكنه فرق كبير في الاعتمادية.

الموارد