an explicit 'draw it' request without topic words gets the whole diagram catalog (tutor-v8-asked-figure)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-29 03:34:12 +03:30
parent 731dea9bb1
commit a8cd681d65
4 changed files with 34 additions and 4 deletions

View File

@@ -401,7 +401,9 @@ anyone who can read this repo can forge a token for any user.**
می‌کند؛ HTML/SVGِ مدل هرگز وارد صفحه نمی‌شود. ۱۴ نوع (plane، numberline، fraction، grid، می‌کند؛ HTML/SVGِ مدل هرگز وارد صفحه نمی‌شود. ۱۴ نوع (plane، numberline، fraction، grid،
groups، clock، bar/linechart/pie، table، venn، mapping، tree، solid)؛ گالریِ آزمایشی در groups، clock، bar/linechart/pie، table، venn، mapping، tree، solid)؛ گالریِ آزمایشی در
`?gallery` فقط در حالتِ توسعه. کاتالوگ بخش‌بخش است و کنارِ هر سوال فقط بخشِ مربوط می‌رود `?gallery` فقط در حالتِ توسعه. کاتالوگ بخش‌بخش است و کنارِ هر سوال فقط بخشِ مربوط می‌رود
(`hint_for`). پرامپت `tutor-v6-diagrams`. سنجش روی ۹۶ مسئله‌ی واقعیِ کتاب: ۴۵ از ۴۸ شکلِ (`hint_for`)؛ سوالِ ادامه‌ای بخشِ سوالِ قبلی را می‌گیرد (`follow_up_hint_for`)، و درخواستِ صریحِ
«شکلش رو بکش» بی‌کلمه‌ی موضوعی کلِ کاتالوگ را (`asked_hint_for`، پرامپت `tutor-v8-asked-figure`؛
یک بار با GapGPT آزموده شد: مستطیلِ باغچه). فرانت هیچ تشخیصی نمی‌دهد. پرامپت `tutor-v6-diagrams`. سنجش روی ۹۶ مسئله‌ی واقعیِ کتاب: ۴۵ از ۴۸ شکلِ
معتبر (دورِ ۲)، ۰ از ۸ برای سوالِ بی‌شکل؛ وارسیِ چشمیِ ۸۳ شکل: ۶۴ درست، ۳ ضعیف، ۱۶ غلط. معتبر (دورِ ۲)، ۰ از ۸ برای سوالِ بی‌شکل؛ وارسیِ چشمیِ ۸۳ شکل: ۶۴ درست، ۳ ضعیف، ۱۶ غلط.
اصلاح‌های بعد از آن (خط از معادله، کسرِ مقایسه‌ای، محرکِ ساعت، …) روی مدل سنجیده نشده‌اند. اصلاح‌های بعد از آن (خط از معادله، کسرِ مقایسه‌ای، محرکِ ساعت، …) روی مدل سنجیده نشده‌اند.
- **فرانت آزمونِ جزیره را بازی می‌کند** (`/nodes/{id}/quiz`); خانه خودِ مسیر است با «شروع». - **فرانت آزمونِ جزیره را بازی می‌کند** (`/nodes/{id}/quiz`); خانه خودِ مسیر است با «شروع».

View File

@@ -177,6 +177,23 @@ def follow_up_hint_for(question: str, previous: str) -> str:
return '\n'.join([FOLLOW_UP_HINT, _HEAD, *parts]) return '\n'.join([FOLLOW_UP_HINT, _HEAD, *parts])
# «شکلش رو بکش» بی‌هیچ کلمه‌ی موضوعی (و بی‌سوالِ شکل‌دارِ قبلی): نمی‌دانیم کدام بخش،
# پس کلِ کاتالوگ می‌رود (~۱٬۹۰۰ توکن). نادر است، چون بیشترِ درخواست‌ها کلمه‌ی موضوعی دارند.
# مرزِ پیش از کلمه لازم است: «مشکل» و «بپرسم» نباید درخواستِ شکل شمرده شوند.
_ASK_FIGURE = re.compile(r'(?<![\u0600-\u06FF])(?:شکل|رسم|بکش|تصویر)')
ASKED_HINT = (
'دانش‌آموز شکل خواسته: اگر مسئله شکلی دارد، در پایانِ پاسخ بلوکِ <diagram>…</diagram> را '
'طبقِ این قالب بگذار؛ اگر ندارد، کوتاه بگو که این مسئله شکل ندارد.'
)
def asked_hint_for(question: str) -> str:
"""درخواستِ صریحِ شکل وقتی هیچ بخشی از کاتالوگ با سوال (یا سوالِ قبلی) نخورد."""
if not _ASK_FIGURE.search(question or ''):
return ''
return '\n'.join([ASKED_HINT, DIAGRAM_SPEC])
def hint_for(question: str) -> str: def hint_for(question: str) -> str:
"""یادآوری و فقط آن بخش‌هایی از کاتالوگ که به همین سوال می‌خورند؛ سوالِ بی‌شکل → ''.""" """یادآوری و فقط آن بخش‌هایی از کاتالوگ که به همین سوال می‌خورند؛ سوالِ بی‌شکل → ''."""
text = question or '' text = question or ''

View File

@@ -38,7 +38,7 @@ _RAW_MARKUP = re.compile(r'\\[A-Za-z(\[]|\$|\*\*|^\s*#{1,6}\s|^\s*\|\s*:?-{3,}',
# بشود گفت «کدام نسخه‌ی پرامپت جوابِ بهتری می‌داد» — بدونِ این، همه‌ی فیدبک‌ها # بشود گفت «کدام نسخه‌ی پرامپت جوابِ بهتری می‌داد» — بدونِ این، همه‌ی فیدبک‌ها
# در یک کاسه می‌ریزند و مقایسه‌ی نسخه‌ها ممکن نیست. کشِ پاسخ هم با همین نسخه # در یک کاسه می‌ریزند و مقایسه‌ی نسخه‌ها ممکن نیست. کشِ پاسخ هم با همین نسخه
# کلید می‌خورد، پس جوابِ نسخه‌ی قبلی بعد از دیپلوی دوباره سرو نمی‌شود. # کلید می‌خورد، پس جوابِ نسخه‌ی قبلی بعد از دیپلوی دوباره سرو نمی‌شود.
PROMPT_VERSION = 'tutor-v7-diagram-kit' PROMPT_VERSION = 'tutor-v8-asked-figure'
_PRIMARY = {'اول', 'دوم', 'سوم', 'چهارم', 'پنجم', 'ششم'} _PRIMARY = {'اول', 'دوم', 'سوم', 'چهارم', 'پنجم', 'ششم'}
_MIDDLE = {'هفتم', 'هشتم', 'نهم'} _MIDDLE = {'هفتم', 'هشتم', 'نهم'}
@@ -184,7 +184,8 @@ def _user_prompt(question: str, contexts: list[str], focus: str = '',
asked = (f'{asked}\n(این ادامه‌ی گفتگوست؛ سوالِ قبلیِ دانش‌آموز: «{previous[:300]}». ' asked = (f'{asked}\n(این ادامه‌ی گفتگوست؛ سوالِ قبلیِ دانش‌آموز: «{previous[:300]}». '
'اگر به آن مربوط است، همان مسئله را با تغییرِ خواسته‌شده حل کن.)') 'اگر به آن مربوط است، همان مسئله را با تغییرِ خواسته‌شده حل کن.)')
shape_hint = (diagram_mod.hint_for(f'{question}\n{focus}') shape_hint = (diagram_mod.hint_for(f'{question}\n{focus}')
or diagram_mod.follow_up_hint_for(question, previous)) or diagram_mod.follow_up_hint_for(question, previous)
or diagram_mod.asked_hint_for(question))
if shape_hint: if shape_hint:
asked = f'{asked}\n\n{shape_hint}' asked = f'{asked}\n\n{shape_hint}'
slash_rule = primary and '/' in question slash_rule = primary and '/' in question

View File

@@ -130,7 +130,7 @@ class DiagramThroughTheApiTests(TestCase):
message = Message.objects.get(role='assistant', conversation__user_id=self.user.id) message = Message.objects.get(role='assistant', conversation__user_id=self.user.id)
self.assertEqual(message.diagram, done['diagram']) self.assertEqual(message.diagram, done['diagram'])
self.assertEqual(message.prompt_version, 'tutor-v7-diagram-kit') self.assertEqual(message.prompt_version, 'tutor-v8-asked-figure')
history = self.client.get(f'/api/ai/conversations/{done["conversationId"]}/messages').json() history = self.client.get(f'/api/ai/conversations/{done["conversationId"]}/messages').json()
self.assertEqual(history['messages'][-1]['diagram']['kind'], 'plane') self.assertEqual(history['messages'][-1]['diagram']['kind'], 'plane')
self.assertIsNone(history['messages'][0]['diagram']) self.assertIsNone(history['messages'][0]['diagram'])
@@ -352,6 +352,16 @@ class FollowUpHintTests(SimpleTestCase):
self.assertIn(DIAGRAM_HINT, last) self.assertIn(DIAGRAM_HINT, last)
self.assertNotIn(FOLLOW_UP_HINT, last) self.assertNotIn(FOLLOW_UP_HINT, last)
def test_explicit_request_without_topic_words_gets_the_whole_catalog(self):
from .services.diagram import ASKED_HINT, DIAGRAM_SPEC, asked_hint_for
from .services.generation import build_messages
last = build_messages('یه باغچه ۵ در ۸ متره، شکلش رو برام بکش', None, 'ششم')[-1]['content']
self.assertIn(ASKED_HINT, last)
self.assertIn(DIAGRAM_SPEC, last)
for q in ('مشکل دارم با این سوال', 'می‌خوام یه سوال بپرسم', '۳۴۵ × ۱۲'):
self.assertEqual(asked_hint_for(q), '', q)
class ThirdRoundTests(SimpleTestCase): class ThirdRoundTests(SimpleTestCase):
"""از چتِ واقعی با gpt-4.1-mini (۲۰۲۶-۰۹-۲۹): خط، چندضلعیِ منتظم، زاویه‌ی خارجی، کسرِ کلمه‌ای.""" """از چتِ واقعی با gpt-4.1-mini (۲۰۲۶-۰۹-۲۹): خط، چندضلعیِ منتظم، زاویه‌ی خارجی، کسرِ کلمه‌ای."""