در سیستمهای خودکار تولید متن و مقالههای پژوهشی، سپردن کل فرایند نوشتن به یک مدل زبانی معمولاً به آشفتگی ساختار، ارجاعات نامعتبر یا گمشدن تصاویر ختم میشود. وقتی متن پیش از ساختار نوشته شود، اصلاح خطاهای فنی کامپایل و پیوندهای شکسته زمان بسیار زیادی میبرد.
این درس به شما نشان میدهد چطور مقاله علمی را نه یک سند متنی خام، بلکه یک «دستسازه ساختاریافته» ببینید. ابتدا اسکلت مقاله، بخشها، جایگاه تصاویر و کلیدهای کتابشناسی را در قالب دادههای صریح پایتون میسازیم و پس از اعتبارسنجی کامل، متن را در جایگاههای مشخص تزریق میکنیم.
تمام کدهای این درس کاملاً متکی بر پایتون و منطق قطعی داخلی هستند؛ بنابراین نیازی به فراخوانی API مدلهای زبانی خارجی، کارت گرافیک، پرداخت ارزی یا عبور از محدودیتهای شبکه ندارید و تمام پایپلاین روی پردازنده سیستم شما بهصورت محلی اجرا و آزمایش میشود.
اسکلت LaTeX در واقع قراردادی میان پژوهشگر و حروفچین (typesetter) است. اگر این قرارداد نقض شود، سند کامپایل نخواهد شد و شکست آن کاملاً پر سر و صدا خواهد بود. اول اسکلت را بسازید، سپس درونش را پر کنید.
اهداف یادگیری
- نگاه به مقالهی پژوهشی بهعنوان یک دستسازه (Artifact) ساختاریافته با گرافی مشخص از بخشها، نه متنی آزاد و بیساختار.
- تولید یک اسکلت LaTeX که چکیده، بخشها، جایگاه شکلها و کلیدهای کتابشناسی را پیش از نگارش حتی یک جمله از متن مشخص میکند.
- تزریق شکلها از خروجیهای آزمایش (مسیرها و زیرنویسها) به درون اسکلت از طریق یک سازوکار قطعی برای جایگاهها (slots).
- اتصال یک تولیدکنندهی متن ساختگی (mocked) که هر بخش را بر اساس طرحی کلی و ساختاریافته پر میکند تا بستر آزمایشی (harness) بدون نیاز به مدل هم قابل آزمایش باشد.
- تولید یک فایل مجزای
paper.texبههمراهreferences.bibو یک مانیفست (Manifest) که تمام شکلهای ارجاعشده و ارجاعاتِ بهکاررفته را فهرست میکند.
چرا اول اسکلت؟
پیشنویسی که مستقیماً از نگارش متن آغاز شود، بدهی ساختاری به بار میآورد. به مقدمه ناگهان سه پاراگراف اضافه میشود که جای اصلیشان در کارهای مرتبط است. شکلی ارجاع داده میشود، پیش از آنکه اصلاً تعریف شده باشد. در نهایت، بخش کتابشناسی برای مقالهای یکسان، به سه کلید مختلف ختم میشود. زمانی نویسنده متوجه این موضوع میشود که هزینهی بازنویسی بسیار بیشتر از هزینهی نگارش اولیه شده است.
اسکلت این رویه را معکوس میکند. ساختار از همان ابتدا بهشکل داده تعریف میشود. بخشها جایگاههایی با نام و ترتیبی مشخص هستند. شکلها جایگاههایی دارای شناسه و زیرنویساند. کلیدهای کتابشناسی بههمراه مدخلهایی که به آنها اشاره دارند، در بالای سند مشخص میشوند. سپس متن، یکییکی درون این جایگاهها ریخته میشود. بستر آزمایشی میتواند پیش از نوشته شدن هر متنی بررسی و اعتبارسنجی کند که هر شکل جایگاهی دارد، هر ارجاع یک مدخل معتبر دارد و همهی بخشها در فهرست مطالب ظاهر شدهاند.
این دقیقاً همان نظمی است که در درسهای قبلی برای برنامهها، فراخوانی ابزار (Tool call) و ردگیری محاسبات (Trace) به کار رفت. ساختار، همان قرارداد است.
ساختار دادهی Paper
تکتک فیلدها دادههای معمولی پایتون هستند. رندرر (renderer) یک تابع خالص (Pure Function) از Paper به رشتهای در قالب LaTeX است. بستر آزمایشی میتواند پیش از رندر کردن، ساختار مقاله را تحلیل کند: تعداد بخشها را بشمارد، فایلهای مفقود تصاویر را فهرست کند و مطمئن شود که به ازای هر \cite{key} یک BibEntry متناظر وجود دارد.
قرارداد رندر
رندرر سه ویژگی را تضمین میکند. اول، به ازای هر جایگاه تصویر در اسکلت، یک بلوک \begin{figure} با برچسبی پایدار بهفرم fig:<id> تولید میشود. دوم، هر بخش یک \section{} با برچسبی پایدار بهفرم sec:<id> تولید میکند تا ارجاعهای متقابل درست کار کنند. سوم، بخش کتابشناسی یک بلوک \bibliography تولید میکند که فایل references.bib آن دقیقاً شامل مدخلهای اعلامشده در ساختار مقاله باشد؛ نه یک مورد بیشتر و نه کمتر.
نقض هر یک از این موارد یک خطای رندر بهشمار میرود، نه یک هشدار ساده. اسکلت، همان قرارداد است؛ رندری که بهطور ضمنی و بیصدا شکلی را حذف کند، این قرارداد را نقض کرده است.
تزریق شکلها از آزمایشها
درسهای پیشین این مسیر، خروجیهای آزمایش را در قالب مانیفستهای JSON تولید میکردند. هر مانیفست فهرستی از دستسازهها را همراه با مسیرها و زیرنویسهای کوتاه در بر دارد. نویسندهی مقاله (paper writer) این مانیفست را میخواند و رکوردهای Figure را تولید میکند.
این تزریق کاملاً قطعی (deterministic) است. شناسههای تصویر از نام آزمایش بههمراه یک شمارندهی صعودی بهدست میآیند. زیرنویسها از مانیفست خوانده میشوند. مسیرها نسبت به دایرکتوری خروجیِ مقاله یکسانسازی (نرمالایز) میشوند تا حتی اگر خروجیهای آزمایش در جای دیگری از دیسک باشند، فایل LaTeX بدون مشکل کامپایل شود.
تولیدکنندهی ساختگی متن
در این درس از هیچ مدلی استفاده نمیشود. یک MockProseGenerator ساختارِ طرح کلی را میخواند و متن را بهشکلی کاملاً قطعی تولید میکند. ساختار طرح کلی در واقع یک رشتهی کوتاه بهازای هر بخش است. این تولیدکننده آن رشته را به دو پاراگراف کوتاه بسط میدهد و عنوان بخش را هم در دل آن میگنجاند. متنِ تولیدشده دقیقاً در همان جاهایی به شکلها و ارجاعات اشاره میکند که در طرح کلی تعیین شده است.
همین برای آزمودن تمام رفتارهای نویسنده کافی است. در پیادهسازی واقعی میتوان بهسادگی این تولیدکننده را با یک فراخوانی مدل زبانی جایگزین کرد؛ بستر آزمایشیِ پیرامون آن هیچ تغییری نخواهد کرد. ارزشِ تعریف تولیدکنندهی متن بهصورت یک موجودیت فراخوانپذیر (callable) در همین است: در آزمون یک نسخهی قطعی میگذارید و در محیط عملیاتی (پروداکشن) یک مدل واقعی، در حالی که باقی پایپلاین کاملاً دستنخورده باقی میماند.
خروجی مانیفست
نویسنده سه فایل در دایرکتوری خروجی میسازد.
مانیفست همان چیزی است که ارزیابها یا چرخهی ناقد (Critic) بعدی آن را میخوانند. این ابزارها LaTeX را تجزیه (parse) نمیکنند، بلکه مانیفست را میخوانند. در درس بعدی، یعنی چرخهی ناقد، این مانیفست ورودی کار خواهد بود تا فهرستی از بازخوردها تولید شود. دقیقاً به همین دلیل مانیفست بخشی از قرارداد است، اما خودِ LaTeX جزو قرارداد نیست.
گیتهای کنترلی اعتبارسنجی
نویسنده پیش از نوشتن هر فایلی، چهار گیت کنترلی (Gates) را بررسی میکند:
- شناسهی هر شکل در سراسر مقاله یکتا باشد.
- فیلد
citesدر هر بخش، به کلید کتابشناسی معتبری اشاره کند که در سند مقاله تعریف شده است. - چکیده خالی نباشد.
- عنوان مقاله خالی نباشد.
رد شدن در هر گیت با اعلام خطای PaperValidationError و ذکر دقیق علت همراه است. بستر آزمایشی این دلیل را بهعنوان حالت شکست (failure mode) منعکس میکند. نوشتن ناقص یا بخشی از فایلها معنا ندارد: یا هر سه فایل کامل نوشته میشوند، یا هیچکدام.
راهنمای خواندن کدها
فایل code/main.py کلاسهای Paper، Section، Figure، BibEntry، PaperValidationError، MockProseGenerator، PaperWriter و تابع render_latex را تعریف میکند. متد write یک دایرکتوری خروجی میگیرد و سه فایل paper.tex، references.bib و manifest.json را تولید میکند. تابع کمکی read_experiment_manifest هم فهرستی از مانیفستهای آزمایش را به رکوردهای Figure تبدیل میکند.
فایل code/tests/test_paper_writer.py این سناریوها را پوشش میدهد: رندر اسکلت بدون هیچ بخشی، رندر کامل با 2 بخش و 2 شکل، گیت ارجاع ناموجود، گیت شناسهی تکراری شکل، محتوای مانیفست و قرارداد ساختار LaTeX (اینکه هر بخش حتماً یک \section{} و هر شکل یک \begin{figure} تولید کند).
گامهای بعدی
در یک پیادهسازی واقعی، دو قابلیت اضافه بسیار کارآمد خواهد بود. اول، رندر به فرمتهای گوناگون: اینکه همان ساختار Paper برای پستهای وبلاگی به Markdown و برای پیشنمایش به HTML تبدیل شود. با این کار، رندرر به یک استراتژی روی Paper تبدیل میشود. دوم، غنیسازی ارجاعات: نویسنده با تکیه بر کش محلیِ DOIها، مدخلهای BibTeX را از روی کلید ارجاع استخراج کند. هر دوی این قابلیتها ارزش بالایی دارند و هر دو را میتوان بدون دست زدن به قرارداد پایهای اسکلت اضافه کرد.
تمام تکیه روی خودِ اسکلت است. بخشها، شکلها و ارجاعات در قالب داده تعریف میشوند، متن درون این جایگاهها تزریق میشود و مانیفست همزمان با فایل LaTeX خروجی داده میشود. هر بهبود دیگری بعد از این، روی همین بستر پیاده خواهد شد.
