docs/extraction-playbook.md: چهار تصمیمی که تفاوتِ چند برابری در هزینه و کیفیت ساختند، با عددهای اندازهگیریشدهی واقعی نه تخمین. سرفصلها: انتخابِ مدل از روی اندازهگیری (gpt-4.1-mini هم دقیقتر از gpt-4o بود هم ۳٫۵ برابر ارزانتر، و gemini برخلافِ جدولِ قیمت سه برابر گرانتر)، قاعدهی self-contained، تعمیرِ بکاسلشِ LaTeX، محافظِ شکل، و ساختِ سوال با subagent بهجای API. وجهِ مشترکِ هر چهار مورد: هیچکدام خطا تولید نمیکردند — نه در لاگ، نه در تست. فقط دادهٔ کمتر یا بدتر میساختند. برای همین توصیهی محوریِ فایل این است که قبل از اعتماد به هر ران انبوه، نمونهای ۴۰-۵۰تایی با چشم خوانده شود. تستهای rag هم اینجا میآیند: بازخوانی، تعمیرِ JSON، و محافظِ شکل. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
106 lines
7.2 KiB
Markdown
106 lines
7.2 KiB
Markdown
# روشِ استخراجِ ارزان و دقیق از کتابِ درسی
|
||
|
||
این فایل نتیجهی یک روزِ اندازهگیریِ واقعی روی پنج کتابِ ریاضی است
|
||
(۱۴۰۵/۰۶/۲۹). هر عددی که اینجا میبینید از پنلِ صورتحساب یا از دادهٔ واقعی
|
||
درآمده، نه از جدولِ قیمتِ رسمی و نه از تخمین.
|
||
|
||
**برای تیمهای دیگر:** اگر کتابِ درسی را با مدلِ vision استخراج میکنید،
|
||
این چهار تصمیم تفاوتِ چند برابری در هزینه و کیفیت میسازند.
|
||
|
||
---
|
||
|
||
## ۱. مدل را اندازه بگیرید، از جدولِ قیمت نخوانید
|
||
|
||
قیمتِ GapGPT با قیمتِ رسمیِ OpenAI یکی نیست. اگر از جدولِ رسمی تخمین بزنید،
|
||
گرانترین گزینه را ارزان میبینید.
|
||
|
||
اندازهگیریِ واقعی روی سه صفحهی یکسان، با خواندنِ
|
||
`/v1/dashboard/billing/usage` قبل و بعد:
|
||
|
||
| مدل | سنت/صفحه (واقعی) | عددهای درست¹ | مسئلهی جعلی |
|
||
|---|---|---|---|
|
||
| **gpt-4.1-mini** | **۰٫۲۲** | **۹۸٪** | خیر |
|
||
| gpt-4o | ۰٫۷۷ | ۹۷٪ | بله |
|
||
| gemini-3.6-flash | ۲٫۱۳ | ۱۰۰٪ | خیر |
|
||
| gpt-4o-mini | — | ۰٪ | مختصات را از خود ساخت |
|
||
|
||
¹ سنجهی رایگان: هر عددی که مدل در متنِ مسئله مینویسد باید در لایهی متنیِ
|
||
همان صفحهی PDF وجود داشته باشد. عددی که آنجا نیست یا از شکل خوانده شده
|
||
(خوب) یا جعل شده (بد)، و نرخِ نسبیِ مدلها قابلِ مقایسه است.
|
||
|
||
**نتیجه:** `gpt-4.1-mini` هم دقیقتر از `gpt-4o` بود هم ۳٫۵ برابر ارزانتر.
|
||
`gemini` دقیقترین بود ولی سه برابرِ `gpt-4o` گران. `gpt-4o-mini` صریحاً
|
||
مختصات را از خود درمیآورد («با فرض مختصات A(1,2)…») — شکستِ بیصدا، بدترین نوع.
|
||
|
||
**Batch API روی GapGPT وجود ندارد** (`/v1/batches` → ۴۰۴)، پس تخفیفِ ۵۰٪
|
||
در دسترس نیست. هر ابزاری که آن را وعده بدهد دارد گمراه میکند.
|
||
|
||
**DPI اهرمِ هزینه نیست.** OpenAI تصویر را به ضلعِ کوتاهِ ۷۶۸ نرمال میکند،
|
||
پس رندر با ۲۰۰ یا ۱۱۰ DPI توکنِ یکسانی میدهد. ۲۰۰ را نگه دارید.
|
||
|
||
## ۲. قاعدهی self-contained را در پرامپت بگذارید
|
||
|
||
مدلِ vision شکل را **میبیند**؛ فقط از او خواسته نشده بنویسدش. بدونِ این
|
||
قاعده، ۴۲٪ مسئلهها به «شکلِ زیر» ارجاع میدهند و برای هیچکس قابلِ حل نیستند.
|
||
|
||
قاعده (در `rag/services/pdf.py`): هرجا مسئله به شکل/جدول ارجاع میدهد،
|
||
اندازهها، برچسبِ رأسها، زاویهها و مقادیرِ جدول را **داخلِ متنِ مسئله**
|
||
بنویس؛ و اگر شکلی واقعاً قابلِ توصیف نیست (رسمِ آزاد، رنگآمیزی) مسئله را
|
||
رد کن بهجای نوشتنِ ارجاعِ بیفایده.
|
||
|
||
اثرش با عدد: نرخِ `unjudgeable` در بازبینی از **۴۰٪ به ۳٪** رسید.
|
||
|
||
## ۳. بکاسلشِ LaTeX را تعمیر کنید، وگرنه صفحههای پرفرمول را میبازید
|
||
|
||
مدل در متنِ ریاضی `\frac` و `\sqrt` مینویسد و بکاسلشِ تنها JSON را میشکند.
|
||
`json.loads` کلِ صفحه را دور میریزد — یعنی دقیقاً باارزشترین صفحهها.
|
||
|
||
⚠️ **تلهی نسخهی اولِ تعمیر:** `\f`، `\t`، `\b`، `\r` و `\n` از نظرِ JSON
|
||
**معتبر**اند، پس «سالم» رد میشوند و `\frac` به formfeed+«rac» و `\theta` به
|
||
tab+«heta» تبدیل میشود — خرابیِ بیصدا بهجای خطای بلند.
|
||
|
||
قاعدهی تفکیک: دستورِ LaTeX همیشه با حرفِ ASCII ادامه مییابد (`\frac`,
|
||
`\times`)، ولی escapeِ واقعی با رقم، فاصله، فارسی یا پایانِ رشته میآید
|
||
(`\n۲.`). پیادهسازی: `rag/services/pdf.py::repair_json_escapes`.
|
||
|
||
## ۴. محافظِ «وابسته به شکل» را با regexِ تخت نسازید
|
||
|
||
برای صرفهجویی، مسئلههای وابسته به شکل را قبل از فرستادن کنار میگذاشتیم.
|
||
regexِ اولیه شاملِ `شکل|جدول|روبهرو|مقابل|زیر را` بود و فاجعهبار گشاد:
|
||
|
||
| متن | چرا رد میشد | واقعیت |
|
||
|---|---|---|
|
||
| «زاویههای **روبهرو** در لوزی برابرند؟» | کلمهی «روبهرو» | یعنی زاویهی مقابل |
|
||
| «کسرهای **زیر را** گویا کنید: ۲/√۳» | «زیر را» | داده همانجاست |
|
||
| «ظرفی **به شکل** مخروطی با شعاع ۴» | کلمهی «شکل» | یعنی شبیهِ مخروط |
|
||
|
||
اندازهگیری روی نمونهی ۵۰تایی: **۸۴٪ از ردشدهها واقعاً قابلِ قضاوت بودند**
|
||
— حدود ۷۸۴ مسئلهی سالم بیصدا از چرخه بیرون مانده بود.
|
||
|
||
قاعدهی درست دو شرط دارد و هر دو باید برقرار باشند: (۱) ارجاعِ صریح به چیزی
|
||
بیرونِ متن، و (۲) بعد از آن ارجاع هیچ توصیفی نیامده باشد. پیادهسازی:
|
||
`rag/management/commands/rag_verify_solutions.py::needs_figure`.
|
||
|
||
## ۵. ساختِ سوال: subagent بهجای API
|
||
|
||
ساختِ سوالِ چهارگزینهای با `o4-mini` روی GapGPT **۰٫۷۷ سنت برای هر سوال**
|
||
تمام میشود (چهار برابرِ تخمینِ خودِ ابزار، چون مدلِ ریزنینگ است).
|
||
|
||
همان کار با subagentهای Claude Code (مدلِ Sonnet) **رایگان** است و بازدهاش
|
||
روی ۳۴۵ ورودی **۹۲٪** بود. Haiku برای این کار مناسب نیست — جوابِ نهایی را
|
||
از راهحل بیرون نمیکشد.
|
||
|
||
مسیر: جفتهای (درس، مسئلهی تأییدشده) را به JSON بیرون بدهید، subagent فایلِ
|
||
خروجی بنویسد، و از `content.question_io` واردش کنید — که اعتبارسنجی دارد و
|
||
فلسفهاش این است که **فایلِ بد هیچچیز نمینویسد**.
|
||
|
||
---
|
||
|
||
## درسِ فراگیر
|
||
|
||
هر چهار موردِ بالا یک وجهِ مشترک دارند: **هیچکدام خطا تولید نمیکردند.**
|
||
نه در لاگ، نه در خروجی، نه در تست. فقط دادهٔ کمتر یا بدتر میساختند.
|
||
|
||
پس: **قبل از اعتماد به هر ران انبوه، یک نمونهی ۴۰ تا ۵۰تایی را با چشم
|
||
بخوانید.** هر چهار موردِ این فایل با همین کار پیدا شدند، نه با کدخوانی.
|