stop the figure guard from throwing away four fifths of what it caught
محافظِ «وابسته به شکل» یک regexِ تخت بود (شکل|جدول|روبهرو|مقابل|زیر را) و
مسئلهها را بدونِ هیچ فراخوانی کنار میگذاشت. فاجعهبار گشاد بود:
«زاویههای روبهرو در لوزی برابرند؟» ← «روبهرو» یعنی مقابل، نه شکل
«کسرهای زیر را گویا کنید: ۲/√۳» ← داده همانجاست
«ظرفی به شکل مخروطی با شعاع ۴» ← «به شکلِ» یعنی شبیهِ
اندازهگیری روی نمونهی ۵۰تایی از کتابهای بازخوانیشده: ۸۴٪ از ردشدهها واقعاً
قابلِ قضاوت بودند — یعنی ~۷۸۴ مسئلهی سالم بیصدا از چرخهی ساختِ سوال بیرون
مانده بود، بدونِ هیچ خطایی در هیچ لاگی.
قاعدهی تازه دو شرط دارد و هر دو باید برقرار باشند: ارجاعِ صریح به چیزی بیرونِ
متن، و نیامدنِ هیچ توصیفی بعد از آن. شرطِ دوم همان چیزی را میگیرد که قاعدهی
self-contained تولید میکند: «با توجه به شکل مقابل که شامل {a,1} است».
اثرش روی دادهٔ واقعی: unjudgeable از ۱٬۴۴۱ به ۵۰۸ و agrees از ۷۹۱ به ۲٬۴۶۶.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -82,12 +82,46 @@ def is_account_limit(exc) -> bool:
|
|||||||
return '403' in text and 'insufficient' in text
|
return '403' in text and 'insufficient' in text
|
||||||
|
|
||||||
|
|
||||||
# مسئلهای که به شکل/جدولِ کتاب ارجاع میدهد بدونِ آن شکل قابلِ حل نیست.
|
# مسئلهای که به شکل/جدولِ کتاب ارجاع میدهد و **محتوای آن را ننوشته** بدونِ
|
||||||
# فرستادنش هم پول میسوزاند هم آمار را خراب میکند.
|
# تصویر قابلِ حل نیست؛ فرستادنش هم پول میسوزاند هم آمار را خراب میکند.
|
||||||
NEEDS_FIGURE = re.compile(
|
#
|
||||||
r'شکل|جدول|نمودار|روبهرو|روبرو|مقابل|تصویر|نقشه|رسم کنید|بکشید|'
|
# ⚠️ نسخهی اولِ این محافظ یک regexِ تخت بود:
|
||||||
r'رنگ[ ]?آمیزی|زیر را|بالا را|وِن'
|
# شکل|جدول|نمودار|روبهرو|روبرو|مقابل|...|زیر را|بالا را
|
||||||
|
# و فاجعهبار گشاد بود. سه نمونه از چیزهایی که بیدلیل رد میکرد:
|
||||||
|
# «زاویههای روبهرو در لوزی برابرند؟» ← «روبهرو» یعنی مقابل، نه شکل
|
||||||
|
# «کسرهای زیر را گویا کنید: ۲/√۳» ← داده همانجاست
|
||||||
|
# «به شکل مخروطی با شعاع ۴ و ارتفاع ۱۲» ← «به شکلِ ...» یعنی شبیهِ
|
||||||
|
# اندازهگیری (۱۴۰۵/۰۶/۲۹، نمونهی ۵۰تایی از کتابهای بازخوانیشده): از
|
||||||
|
# مسئلههایی که این محافظ رد کرده بود، **۸۴٪ واقعاً قابلِ قضاوت بودند** —
|
||||||
|
# یعنی ~۷۸۴ مسئلهی سالم بیصدا از چرخهی ساختِ سوال بیرون مانده بودند.
|
||||||
|
#
|
||||||
|
# قاعدهی تازه دو شرط دارد، و هر دو باید برقرار باشند:
|
||||||
|
# ۱. ارجاعِ صریح به چیزی بیرونِ متن باشد («شکل زیر»، «جدول روبهرو»)
|
||||||
|
# ۲. بعد از آن ارجاع، توصیفی نیامده باشد (نه «که ...»، نه عدد، نه نماد)
|
||||||
|
# شرطِ دوم همان چیزی است که قاعدهی self-contained تولید میکند: مدل حالا
|
||||||
|
# مینویسد «با توجه به شکل مقابل **که شامل {a,1} است**».
|
||||||
|
_FIGURE_REFERENCE = re.compile(
|
||||||
|
r'(شکل|جدول|نمودار|تصویر|نقشه)\s*(ِ|های|های)?\s*'
|
||||||
|
r'(زیر|بالا|روبه\u200cرو|روبرو|مقابل|فوق|داده\s*شده)'
|
||||||
|
r'|با توجه به\s*(شکل|جدول|نمودار|تصویر)'
|
||||||
)
|
)
|
||||||
|
# نشانهی اینکه محتوای شکل داخلِ متن آمده.
|
||||||
|
_FIGURE_DESCRIBED = re.compile(r'که\s|شامل|اعضای|مقادیر|برابر|=|\{|\d')
|
||||||
|
# کارهایی که ذاتاً تصویریاند و هیچ متنی نجاتشان نمیدهد.
|
||||||
|
_ART_TASK = re.compile(r'رنگ[ ]?آمیزی|رنگ کنید|رنگ\u200cآمیزی')
|
||||||
|
|
||||||
|
|
||||||
|
def needs_figure(problem: str) -> bool:
|
||||||
|
"""آیا این مسئله بدونِ دیدنِ صفحهی کتاب واقعاً قابلِ قضاوت نیست؟"""
|
||||||
|
text = problem or ''
|
||||||
|
if _ART_TASK.search(text):
|
||||||
|
return True
|
||||||
|
match = _FIGURE_REFERENCE.search(text)
|
||||||
|
if not match:
|
||||||
|
return False
|
||||||
|
# ۱۶۰ نویسه بعد از ارجاع: جایی که توصیفِ شکل اگر بیاید، میآید.
|
||||||
|
return not _FIGURE_DESCRIBED.search(text[match.end():match.end() + 160])
|
||||||
|
|
||||||
|
|
||||||
PROMPT = """تو یک ریاضیدانِ دقیق هستی که راهحلهای کتابِ درسیِ ایران را بازبینی میکند.
|
PROMPT = """تو یک ریاضیدانِ دقیق هستی که راهحلهای کتابِ درسیِ ایران را بازبینی میکند.
|
||||||
|
|
||||||
@@ -183,7 +217,7 @@ class Command(BaseCommand):
|
|||||||
rows = list(qs.order_by('collection', 'source_page', 'order'))
|
rows = list(qs.order_by('collection', 'source_page', 'order'))
|
||||||
|
|
||||||
skipped = self._mark_figure_dependent(rows)
|
skipped = self._mark_figure_dependent(rows)
|
||||||
rows = [r for r in rows if not NEEDS_FIGURE.search(r.problem or '')]
|
rows = [r for r in rows if not needs_figure(r.problem or '')]
|
||||||
if opts['limit']:
|
if opts['limit']:
|
||||||
rows = rows[:opts['limit']]
|
rows = rows[:opts['limit']]
|
||||||
if skipped:
|
if skipped:
|
||||||
@@ -203,7 +237,7 @@ class Command(BaseCommand):
|
|||||||
"""قبل از خرجِ یک ریال، آنهایی که ذاتاً قابلِ قضاوت نیستند کنار میروند."""
|
"""قبل از خرجِ یک ریال، آنهایی که ذاتاً قابلِ قضاوت نیستند کنار میروند."""
|
||||||
marked = []
|
marked = []
|
||||||
for chunk in rows:
|
for chunk in rows:
|
||||||
if NEEDS_FIGURE.search(chunk.problem or ''):
|
if needs_figure(chunk.problem or ''):
|
||||||
chunk.solution_verdict = LessonChunk.VERDICT_UNJUDGEABLE
|
chunk.solution_verdict = LessonChunk.VERDICT_UNJUDGEABLE
|
||||||
chunk.check_note = 'به شکل/جدولِ کتاب ارجاع میدهد؛ از متن قابلِ قضاوت نیست.'
|
chunk.check_note = 'به شکل/جدولِ کتاب ارجاع میدهد؛ از متن قابلِ قضاوت نیست.'
|
||||||
chunk.checked_by = 'pre-filter'
|
chunk.checked_by = 'pre-filter'
|
||||||
|
|||||||
Reference in New Issue
Block a user