6 دقیقه مطالعه

Claude را در Next.js پشت مسیر سرور بگذار، نه داخل کامپوننت

Mehdi Rezaei
Mehdi
نویسنده

وصل کردن Claude به Next.js از آن کارهایی است که نمونه کدش کوتاه به نظر می‌رسد و محصولش زود کثیف می‌شود. SDK را در یک کامپوننت کلاینت وارد می‌کنی، کلید را جایی «موقت» می‌گذاری، یک جعبه متن می‌سازی، و فکر می‌کنی اپ AI داری. چیزی که داری یک دمو است که راز را به مرورگر نزدیک کرده و هیچ قراردادی برای شکست ندارد.

مرزی که تکرار می‌کنم این است. کلید، از جمله ANTHROPIC_API_KEY، فقط در محیط سرور. کامپوننت کلاینت متن کاربر را به یک مسیر می‌فرستد. مسیر، بدنه را اعتبار می‌کند، مدل را صدا می‌زند، و نتیجه را برمی‌گرداند. SDK آنتروپیک را داخل باندل کلاینت نیاور. اگر تابعی که مدل را صدا می‌زند از یک فایل مشترک با کامپوننت وارد شود، دیر یا زود کلید یا شکل درخواست به جایی نشت می‌کند که نباید.

اسم دقیق متد را از همان نسخه‌ای از SDK کپی کن که در قفل وابستگی است. سطح پایدار برای من مفهوم است نه حافظه امضا: یک درخواست پیام به Claude، با سیستم و نوبت کاربر، از مسیر سرور. اگر مستندات امروز شکل استریم یا نام فیلد را عوض کرده، کد مقاله قدیمی را صادق ندان. قرارداد محصول را صادق بدان.

چت شکل پیش‌فرض محصول نیست

رابط گفتگو برای یاد گرفتن مسیر خوب است. برای محصول اغلب تنبل است. اگر کار واقعی خلاصه کردن یک سند، استخراج فیلد، یا پیش‌نویس یک پاسخ در وضعیت مشخص است، همان را اسم بگذار و خروجی را ساخت‌یافته کن. جعبه چت آزاد یعنی مدل هم محدوده کار را انتخاب می‌کند هم لحن را. پشتیبانی فردا نمی‌تواند بگوید سیستم چه تصمیمی گرفته.

ورودی را قبل از مدل اعتبار کن. طول، تهی بودن، و اینکه این کاربر حق این سند را دارد. اعتبار کلید API این سوال را جواب نمی‌دهد. مجوز مال اپ است. اگر مسیر فقط متن را جلو بفرستد، هر کسی که به آن URL برسد از سهمیه تو استفاده می‌کند. rate limit خود مسیر را بگذار. سقف ارائه‌دهنده کنترل سوءاستفاده محصول نیست. دیرتر و گران‌تر خبرت می‌کند.

چیزی که ذخیره می‌کنی را هم از چیزی که نشان می‌دهی جدا کن. نمایش می‌تواند استریم باشد. ذخیره باید بعد از تمام شدن، یا بعد از گذشتن از schema، اتفاق بیفتد. نیمه استریم را به‌عنوان نتیجه قطعی در دیتابیس ننویس. فردا با آن مثل سند رفتار می‌کنی و سند نبوده.

استریم یعنی وضعیت، نه ریختن توکن

برای پاسخ بلند، استریم تجربه را بهتر می‌کند به شرطی که رابط بگوید کجای کار است. در حال پاسخ، تمام شد، یا شکست. ردیف متن که بی‌علامت قطع شود بدتر از یک انتظار صادقانه است. مسیر سرور باید قطع، مهلت، و خطای ارائه‌دهنده را به همین وضعیت‌ها ترجمه کند. console.error وضعیت محصول نیست.

خطاهایی که کاربر باید بفهمد را از هم جدا کن. ورودی نامعتبر مال اوست و باید همان فرم را اصلاح کند. محدودیت نرخ مال حفاظت توست و نباید مثل خرابی مدل به نظر برسد. در دسترس نبودن مدل یا تمام شدن مهلت، حالت «الان نشد» است با راهی که کار کاربر گم نشود. اگر این سه تا یک پیام واحد داشته باشند، هم پشتیبانی کور است هم کاربر دوباره همان درخواست سنگین را می‌فرستد.

بارگذاری را هم طراحی کن. دکمه که هیچ نمی‌گوید، کاربر را به چند بار زدن تشویق می‌کند. چند بار زدن یعنی چند فراخوانی. این را با غیرفعال کردن عمل تا تمام شدن درخواست حل کن، نه با پرامپتی که خواهش می‌کند مدل سریع‌تر باشد.

نوع را روی مرز بگذار

TypeScript وقتی به درد می‌خورد که بدنه درخواست و نتیجه‌ای که نگه می‌داری نوع داشته باشند. پرامپت بلند را نوع‌دار کردن، ایمنی نمی‌آورد. رشته همان رشته است. ایمنی از این می‌آید که فیلد اضافه بی‌صدا به مدل نرسد و خروجی اگر شکل وعده داده‌شده را نداشت، ذخیره نشود.

راز را در مثال، در تست اسنپ‌شات، و در لاگ مسیر نگذار. .env.local جای کلید است و نباید وارد git شود. کلید جای‌نگهدار داخل ریپو، حتی «برای اینکه README کامل باشد»، عادت بدی است چون نفر بعدی همان را به محیط تولید کپی می‌کند. در سند بنویس متغیر چه نامی دارد. مقدار را ننویس.

مدل را هم در یک جا انتخاب کن، نه در هر کامپوننت. امروز Claude برای یک کار مناسب است و برای کار کناری شاید مدل دیگری. اگر نام مدل در ده فایل پخش شود، عوض کردنش یک مهاجرت اعلام‌نشده است. یک ماژول سرور که کار محصول را به یک فراخوانی ترجمه کند کافی است. آن ماژول حق ندارد UI را بشناسد. UI حق ندارد قیمت و کلید را بشناسد.

چه چیزی را همان هفته کامل می‌کنم

یک کار اسم‌دار. یک مسیر. اعتبار ورودی. یک حالت بارگذاری و سه حالت خطای قابل تشخیص. استریم فقط اگر پاسخ آن‌قدر بلند است که سکوت رابط دروغ می‌شود. لاگی که شناسه درخواست را دارد و متن کامل کاربر را بی‌دلیل برای همیشه نگه نمی‌دارد.

چه چیزی را عقب می‌اندازم. عامل چندابزاری، حافظه گفتگوی نامحدود، و «هر سوالی بپرس». این‌ها وقتی معنی دارند که همان یک کار، شکست قابل فهم داشته باشد. قبل از آن، سطح بیشتر یعنی راه بیشتر برای گم کردن کلید و سهمیه.

ترکیب Next.js و SDK آنتروپیک به‌خاطر کم بودن کد جذاب است. جذابیت محصول جای دیگری است. کاربر می‌فهمد سیستم چه کاری را قبول کرده، چه وقت تمام شده، و چه وقت باید خودش تصمیم بگیرد. Claude این قرارداد را اجرا نمی‌کند. مسیر سرور اجرا می‌کند، اگر تو مرز را قبل از اولین کامپوننت چت کشیده باشی.

مشاهده را از متن کاربر جدا کن

برای فهمیدن اینکه مسیر سالم است، لازم نیست هر پرامپت را در ابزار لاگ نگه داری. لازم است بدانی مدل صدا زده شد یا اعتبار ورودی همان اول رد کرد، پاسخ تمام شد یا مهلت خورد، و این اتفاق مال کدام کار اسم‌دار بود. شناسه درخواست این‌ها را به هم وصل می‌کند. متن خام کاربر، اگر اصلاً لازم است بماند، باید دلیل نگهداری و عمر مشخص داشته باشد. «شاید بعداً به درد ارزیابی بخورد» دلیل نگهداری نامحدود نیست.

اگر استریم را از مسیر سرور به کلاینت می‌دهی، قطع شدن اتصال را هم جزو همان مشاهده بدان. کاربر ممکن است صفحه را ببندد. کار پس‌زمینه نباید از این قطع شدن، یک نتیجه نیمه‌کاره بسازد و دفعه بعد آن را به‌عنوان پاسخ کامل نشان بدهد. تمام شدن یعنی مسیر خودش گفته تمام شد، نه اینکه دیگر توکنی نرسید.

این سطح از صراحت، همان چیزی است که نمونه چت معمولاً جا می‌اندازد. نمونه فقط مسیر شاد را نشان می‌دهد. محصول را مسیرهای ناراحت می‌سازند: ورودی بد، سهمیه، مهلت، و جوابی که شکل وعده‌داده‌شده را ندارد. اگر این چهار تا در رابط و در لاگ یک شکل دارند، Claude را به Next.js وصل کرده‌ای. اگر فقط جعبه متن در حالت موفق کار می‌کند، هنوز روی دمو ایستاده‌ای.

Share this article

Claude را در Next.js پشت مسیر سرور بگذار، نه داخل کامپوننت | Mehd.ir