অধ্যায় 1 · ইন্সট্রাকশন, মডেল ও রিজনিং
প্রোভাইডারের পার্থক্য ও পোর্টেবিলিটি: গাইড পড়া ও একাধিক মডেলে টেস্ট
- পৃষ্ঠা 2 / 24
- 15 মিনিট পড়া
একটা প্রোডাক্টে যে প্রম্পট ভালো কাজ করে, অন্যটায় সেটা ব্যর্থ হতে পারে; এমনকি একই প্রোডাক্টেও মডেল আপডেটের পরে। কারণটা সাধারণত রহস্যময় নয়: মডেলগুলো আলাদা, কে কতটা আক্ষরিকভাবে নির্দেশ মানে, কে কতটা ব্যাখ্যা দেয়, আর কোন সেটিং গ্রহণ করে। এই পাতা এর জন্য একটা পুনরাবৃত্তিযোগ্য পদ্ধতি দেয়: কৌশল নেওয়ার আগে প্রোভাইডারের গাইড পড়ুন, প্রতিটা টার্গেটে একই কেস চালান, টেস্ট যেটুকু বদলাতে বাধ্য করে শুধু সেটুকু বদলান, আর পার্থক্যগুলো লিখে রাখুন।
আপনার Python ৩.১২ বা তার পরের ভার্সন লাগবে, আর শুধু স্ট্যান্ডার্ড লাইব্রেরি। কোড ব্লকগুলো ভেরিয়েবল ভাগ করে নেয়, তাই পরপর টাইপ করুন। আগের পাতার মতোই কোডের প্রতিটা প্রোভাইডার একটা টয় প্রোভাইডার (toy provider): ছোট, নির্দিষ্ট ফল দেওয়া ফাংশন, যা একটা আচরণের বদলি হয়ে দাঁড়ায়, যাতে টেস্ট হারনেস হুবহু আবার চালানো যায়। আসল মডেল আরও অনির্দিষ্ট, আর সেজন্যই টেস্ট করতে হয়; টয়ের ফল আসল মডেল সম্পর্কে কিছুই বলে না।
যা শিখবেন
- কোনো কৌশল নেওয়ার আগে প্রোভাইডারের অফিসিয়াল প্রম্পট গাইড কীভাবে পড়বেন, আর তার সম্পর্কে কী লিখে রাখবেন।
- কীভাবে একটা সাধারণ প্রম্পট কোর আর ছোট, নামওয়ালা অ্যাডাপ্টেশন আলাদা রাখবেন, এবং ভ্যারিয়েন্ট লাগবে কি না কীভাবে ঠিক করবেন।
- কীভাবে একই টেস্ট কেস একাধিক টার্গেটে এবং একই টার্গেটের দুই স্ন্যাপশটে, English ও Bangla দুই ভাষাতেই চালাবেন।
- কোন আচরণ ও ফিচারের ওপর নির্ভর করা চলবে না, আর কীভাবে কম্প্যাটিবিলিটি চেকলিস্ট ও পার্থক্যের রেকর্ড লিখবেন।
কৌশল নেওয়ার আগে অফিসিয়াল গাইড পড়ুন
কোনো কৌশল নেওয়ার আগে অফিসিয়াল প্রম্পট গাইড পড়ুন। ব্লগ পোস্ট বা স্ক্রিনশট শুধু বলে যে কোনো এক মডেলে, কারও জন্য, একবার একটা কৌশল কাজ করেছিল। প্রোভাইডারের গাইড বলে ভেন্ডর আজ নিজের মডেল সম্পর্কে কী বলছে। কোনো কৌশল প্রোডাক্টে কপি করার আগে একটা ছোট ইনটেক কার্ড পূরণ করুন।
| প্রশ্ন | কেন জরুরি |
|---|---|
| উপদেশটা কোন মডেল বা মোডের জন্য লেখা? | উত্তর দেওয়ার আগে ভাবে এমন মডেলের উপদেশ যে মডেল ভাবে না তার ক্ষতি করতে পারে। |
| গাইড ঠিক কী বলে, এবং কোথায়? | উদ্ধৃতি আর তারিখ লিখে রাখুন; গাইড বদলায়। |
| চালানোর মতো কোনো উদাহরণ আছে কি না? | উদাহরণ উপদেশকে টেস্ট কেস বানায়। |
| আপনার ব্যবহৃত অন্য প্রোভাইডাররাও একই কথা বলে কি না? | একাধিক গাইডে মিল থাকলে প্যাটার্নটা সম্ভবত অন্যত্রও খাটে। |
| আপনার কেসে কীভাবে টেস্ট করবেন? | নিজের টেস্ট পাস না করা পর্যন্ত কোনো কৌশল গ্রহণ করা হয় না। |
প্রোভাইডার নোট (২০২৬-১০-১২ অনুযায়ী): OpenAI-এর প্রম্পট-ইঞ্জিনিয়ারিং গাইড বলে, রিজনিং মডেল উচ্চস্তরের নির্দেশনায় ভালো ফল দেয়, আর GPT-ধাঁচের মডেলের দরকার আরও স্পষ্ট, নির্দিষ্ট নির্দেশ; তারা আরও পরামর্শ দেয় প্রোডাকশন অ্যাপকে নির্দিষ্ট মডেল স্ন্যাপশটে পিন করতে এবং eval বানাতে। Anthropic মডেল-ভিত্তিক আলাদা প্রম্পটিং পাতা রাখে এবং জানায় মডেলভেদে আচরণ আলাদা, যেমন শব্দবহুলতা, নির্দেশ কতটা আক্ষরিকভাবে মানা হয়, আর effort কীভাবে ক্যালিব্রেট করা। Google-এর প্রম্পটিং-স্ট্র্যাটেজি পাতায় তাদের নতুনতম মডেল-পরিবারের জন্য নির্দিষ্ট উপদেশ আছে। ওপেন-ওয়েট মডেল চ্যাট টেমপ্লেট ব্যবহার করে, যা প্রতিটা মডেলের কার্ডে বর্ণিত। গাইড সরে যায় আর পুরোনো লিংক রিডাইরেক্ট করে, তাই প্রতিটা প্রোভাইডারের ডকুমেন্টেশন হোম থেকে শুরু করুন এবং বর্তমান ডকুমেন্টেশন দেখে নিন।
একটা কোর, ছোট ছোট অ্যাডাপ্টেশন
প্রোভাইডাররা আলাদা আচরণ করলে আলাদা অ্যাডাপ্টেশন রাখুন, এবং প্রম্পটের প্রোভাইডার-নির্দিষ্ট ভ্যারিয়েন্ট লাগবে কি না মূল্যায়ন করুন। লক্ষ্য হলো একটা সাধারণ কোর, যা টাস্ক বলে, আর প্রতিটা টার্গেটের জন্য অল্প কয়েকটা বাড়তি লাইন, যেগুলো আছে শুধু কারণ কোনো টেস্ট ব্যর্থ হয়েছিল। তিনটা টার্গেটের জন্য প্রম্পট সাজানোর দুটো উপায় তুলনা করুন।
দুর্বল প্রম্পট:
Classify the ticket. IMPORTANT!!! Output JSON only. No intro. No code fences. No chat. Be
literal. Think step by step but do not show steps. Never apologise. JSON ONLY!!!এটা একটাই প্রম্পট, যাতে সব মডেল নিয়ে সব দুশ্চিন্তা ঢোকানো। কোন লাইন কোন ব্যর্থতা ঠিক করে তা কেউ বলতে পারে না, তাই কেউ কোনো লাইন সরানোর সাহস পায় না, আর পরের মডেল আপডেটে কিছু লাইন ভুল হয়ে যায়।
ভালো প্রম্পট:
Classify the support ticket as one of: billing, delivery, other.
Reply in the language of the ticket, in one short sentence.
Return a JSON object with the keys "label" and "reply".
Return no text before or after the JSON object.প্রথম তিন লাইন কোর, আর সব টার্গেটের। শেষ লাইনটা একটা অ্যাডাপ্টেশন: সেটা আছে কারণ একটা টেস্টে দেখা গেছে একটা টার্গেট JSON-এর আগে একটা বন্ধুত্বপূর্ণ বাক্য জুড়ে দেয়। পরের কোড ব্লকে অ্যাডাপ্টেশনগুলো থাকে টার্গেট ধরে সাজানো একটা টেবিলে, প্রতিটার কারণসহ, আর টয় টার্গেটগুলো ধারণাটা দেখায়।
প্রতিটা টার্গেটে একই কেস টেস্ট করুন
ব্লকটা চারটা টেস্ট কেস (দুটো English, দুটো Bangla), কোর প্রম্পট, তিনটা টয় টার্গেট আর একটা চেকার ঠিক করে। Bangla টিকেট দুটোর অর্থ "আমার পার্সেল এখনো আসেনি" আর "আমার কাছ থেকে দুইবার টাকা কেটে নেওয়া হয়েছে"। প্রতিটা টয় একটা বদলি: toy_a শুধু JSON ফেরত দেয় এবং Bangla কীওয়ার্ড বোঝে; toy_b না বলা পর্যন্ত JSON-এর আগে একটা বাক্য জোড়ে, আর শুধু English কীওয়ার্ড চেনে; toy_c না বলা পর্যন্ত JSON-কে কোড ফেন্সে মোড়ে।
import json
LABELS = ("billing", "delivery", "other")
CASES = [ # (id, ticket, expected label, script the reply should use)
("en-late", "My parcel is late again.", "delivery", "latin"),
("en-twice", "I was charged twice. Please refund one payment.", "billing", "latin"),
("bn-late", "আমার পার্সেল এখনো আসেনি।", "delivery", "bengali"), # my parcel has not arrived yet
("bn-twice", "আমার কাছ থেকে দুইবার টাকা কেটে নেওয়া হয়েছে।", "billing", "bengali"), # money taken twice
]
CORE = ("Classify the support ticket as one of: billing, delivery, other.\n"
"Reply in the language of the ticket, in one short sentence.\n"
'Return a JSON object with the keys "label" and "reply".\n')
ADAPT = { # target -> (extra line, reason it exists)
"toy_a": ("", "none needed"),
"toy_b": ("Return no text before or after the JSON object.", "adds an intro sentence"),
"toy_c": ("Use no code fence.", "wraps the JSON in a fence"),
}
BENGALI = range(0x0980, 0x0A00)
def answer(prompt, knows_bangla, fix=str):
ticket = prompt.split("Ticket:\n")[1]
words = {"billing": ["refund", "charged"], "delivery": ["parcel", "late"]}
if knows_bangla:
words["billing"].append("টাকা")
words["delivery"].append("পার্সেল")
label = next((k for k, ws in words.items() if any(w in ticket.lower() for w in ws)), "other")
bn = any(ord(c) in BENGALI for c in ticket)
reply = "আপনার অনুরোধ পেয়েছি।" if bn else "We received your request." # the Bangla text says the same
return json.dumps({"label": fix(label), "reply": reply}, ensure_ascii=False)
def toy_a(prompt): return answer(prompt, True)
def toy_a_v2(prompt): return answer(prompt, True, str.upper) # a later snapshot of toy_a
def toy_b(prompt):
out = answer(prompt, False)
return out if "no text before or after" in prompt else "Sure! Here is the JSON:\n" + out
def toy_c(prompt):
out = answer(prompt, True)
return out if "no code fence" in prompt else "```json\n" + out + "\n```"
def check(reply, label, script):
try:
data = json.loads(reply)
except ValueError:
return "not-json"
if not isinstance(data, dict) or set(data) != {"label", "reply"}:
return "bad-keys"
if data["label"] not in LABELS:
return "bad-label"
if data["label"] != label:
return "wrong-label"
if any(ord(c) in BENGALI for c in data["reply"]) != (script == "bengali"):
return "wrong-script"
return "ok"
def run(targets, adapted):
rows = {}
for cid, ticket, label, script in CASES:
rows[cid] = {}
for name, fn in targets.items():
extra = ADAPT[name.split("_v")[0]][0] # a snapshot shares its target's line
prompt = CORE + (extra + "\n" if adapted and extra else "")
rows[cid][name] = check(fn(prompt + "Ticket:\n" + ticket), label, script)
return rows
def show(rows):
names = sorted(next(iter(rows.values())))
print("case".ljust(10) + "".join(n.ljust(13) for n in names))
for cid, cells in rows.items():
print(cid.ljust(10) + "".join(cells[n].ljust(13) for n in names))
TARGETS = {"toy_a": toy_a, "toy_b": toy_b, "toy_c": toy_c}
before, after = run(TARGETS, False), run(TARGETS, True)
print("core prompt only"); show(before)
print("core + adaptations"); show(after)core prompt only
case toy_a toy_b toy_c
en-late ok not-json not-json
en-twice ok not-json not-json
bn-late ok not-json not-json
bn-twice ok not-json not-json
core + adaptations
case toy_a toy_b toy_c
en-late ok ok ok
en-twice ok ok ok
bn-late ok wrong-label ok
bn-twice ok wrong-label ok দুটো টেবিলকে টেস্ট রিপোর্ট হিসেবে পড়ুন। শুধু কোর প্রম্পটে toy_b আর toy_c প্রতিটা কেসে not-json দিয়ে ব্যর্থ হয়, যদিও দুটোই উত্তরটা "জানে": ভুল শুধু মোড়ানোয়। প্রত্যেকের জন্য একটা বাড়তি লাইনই যথেষ্ট, তাই ওই দুটো প্রম্পটের পার্থক্য আর ছোট একটা ভ্যারিয়েন্টই ঠিক উত্তর। অ্যাডাপ্টেশনের পরেও toy_b দুটো Bangla কেসে wrong-label দিয়ে ব্যর্থ হয়। কোনো শব্দবিন্যাসে এটা ঠিক হয় না, কারণ বদলি ফাংশনটা ভাষাটাই বোঝে না। এটা সক্ষমতার ফাঁক (capability gap): ঠিক প্রতিক্রিয়া হলো ওই টিকেটের জন্য অন্য মডেল, একটা রাউটিং নিয়ম, বা নথিবদ্ধ সীমা; লম্বা প্রম্পট নয়।
চেকারটাই আপনার প্রম্পট কম্প্যাটিবিলিটি চেকলিস্ট, কোড হিসেবে লেখা, যাতে প্রতিবার একইভাবে প্রয়োগ হয়:
| চেকলিস্টের আইটেম | কোডের চেক |
|---|---|
| আউটপুট শুধু চাওয়া ফরম্যাটে | not-json |
| ঠিক ওই কি (key), বাড়তি ফিল্ড নেই | bad-keys |
| শুধু অনুমোদিত মান (enum) | bad-label |
| জানা কেসে সঠিক সিদ্ধান্ত | wrong-label |
| ব্যবহারকারীর ভাষা ও লিপিতে উত্তর | wrong-script |
| প্রতিটা ফলের সঙ্গে প্রম্পট, মডেলের শনাক্তকারী ও তারিখ রেকর্ড করা | নিচের রেকর্ডের snapshot ফিল্ড |
নিজের ব্যর্থতা থেকে সারি যোগ করুন: দৈর্ঘ্যের সীমা, যে প্রত্যাখ্যান হওয়ার কথা নয়, বা কেটে যাওয়ার ইঙ্গিত দেওয়া স্টপ কারণ।
একই টার্গেটের দুটো স্ন্যাপশট
একই টেস্ট কেস দিয়ে মডেল স্ন্যাপশট তুলনা করুন। প্রোভাইডাররা মডেলের তারিখ বা নম্বরওয়ালা স্ন্যাপশট প্রকাশ করে, আর "latest" ধরনের অ্যালিয়াস আপনার দিকে কিছু না বদলেও নতুন স্ন্যাপশটে সরে যেতে পারে। যেটা টেস্ট করেছেন সেই স্ন্যাপশট পিন করুন, আর সরার আগে অপরিবর্তিত কেসগুলো আবার চালান। এখানে toy_a_v2 হলো toy_a-এর একটা পরের স্ন্যাপশটের বদলি, যে একটা ছোট জিনিস বদলেছে:
snaps = run({"toy_a": toy_a, "toy_a_v2": toy_a_v2}, False)
for cid, cells in snaps.items():
print(cid.ljust(10) + cells["toy_a"].ljust(8) + cells["toy_a_v2"])en-late ok bad-label
en-twice ok bad-label
bn-late ok bad-label
bn-twice ok bad-labelপ্রম্পটে কিছু বদলায়নি, তবু এখন প্রতিটা কেস ব্যর্থ, কারণ নতুন স্ন্যাপশট লেবেল বড় হাতের অক্ষরে লেখে। কড়া চেকার এটা সঙ্গে সঙ্গে ধরে; চোখ দিয়ে কয়েকটা উত্তর পড়লে মানুষ বলত ঠিকই আছে। আসল স্ন্যাপশট-পরিবর্তন সাধারণত আরও সূক্ষ্ম (একটু লম্বা, একটু বেশি সতর্ক), তাই কেসের সেট স্থির ও সংরক্ষিত থাকতে হবে, আর প্রতিটা সংরক্ষিত ফলে মডেলের শনাক্তকারী থাকতে হবে।
English ও দ্বিতীয় ভাষায় নির্দেশ মানা
English ও একটা দ্বিতীয় ভাষায় নির্দেশ মানা টেস্ট করুন, এখানে Bangla। একই টাস্ক দুই ভাষায় একটা টেস্ট সেটে রাখুন, আর নির্দেশ English-এই রাখুন (এই টিউটোরিয়ালের প্রম্পটগুলোর মতো), অনুবাদের বিশেষ কারণ না থাকলে। চারটা বিষয়ে ভাষাগুলো তুলনা করুন: সিদ্ধান্ত (লেবেল), ফরম্যাট (JSON কি), উত্তরের ভাষা, আর উত্তরের লিপি। ওপরের ম্যাট্রিক্স ঠিক এটাই করেছে, আর এমন একটা ব্যর্থতা ধরেছে যা শুধু English টেস্টে লুকিয়ে থাকত: toy_b দুটো English কেস পাস করে আর দুটো Bangla কেসে ব্যর্থ।
আসল মডেলের জন্য দুটো সতর্কতা। মিশ্র ভাষা আর রোমান হরফে লেখা Bangla (লাতিন অক্ষরে Bangla) আলাদা টেস্ট কেস, যার প্রত্যাশিত আচরণও আলাদা; দেখুন নিজের ভাষায় প্রম্পট: নিজস্ব লিপি, রোমান হরফ ও মিশ্র ভাষা। আর একটা Bangla লেখা টোকেন বা কনটেক্সটে কতটা খরচ করে তা ধরে নেবেন না: প্রোভাইডারের টোকেন কাউন্টার দিয়ে মাপুন, কারণ প্রোভাইডার ও মডেলভেদে তা আলাদা।
যে আচরণের ওপর নির্ভর করবেন না
অনথিভুক্ত প্রম্পট আচরণের ওপর নির্ভর করা এড়ান, এবং মডেল-নির্দিষ্ট যে ফিচার সরাসরি পোর্ট করা যায় না তা চিনুন। অনথিভুক্ত আচরণ মানে এমন কিছু যা আজ কাজ করছে অথচ কোনো গাইড তার প্রতিশ্রুতি দেয় না: যে শব্দগুচ্ছ নাকি "মনোযোগ বাড়ায়", লুকানো স্যাম্পলিং ডিফল্ট, প্রত্যাখ্যানের হুবহু শব্দ। একে এমন সুবিধা ভাবুন, যা পরের আপডেটে ভেন্ডর তুলে নিতে পারে।
| আপনি যার ওপর নির্ভর করছেন | নিরাপদ উপায় |
|---|---|
| যাদুকরী শব্দগুচ্ছ বা বড় হাতের অক্ষর | চাহিদাটা সরল ভাষায় লিখুন এবং টেস্ট করুন |
| উত্তরের হুবহু শব্দ | বাক্য নয়, কাঠামো আর মান যাচাই করুন |
| কোনো সেটিংয়ের ডিফল্ট মান | মডেল নিলে যা দরকার তা স্পষ্ট করে সেট করুন |
| একবার দেখা আউটপুট | কেসের সেট কয়েকবার চালিয়ে গুনুন |
| শুধু একজন প্রোভাইডারের ফিচার (থিঙ্কিং গভীরতা, ক্যাশ মার্কার, স্কিমা-সীমাবদ্ধ আউটপুট) | অ্যাডাপ্টার স্তরে রাখুন, কোরে প্রম্পট-ও-ভ্যালিডেটর ফলব্যাকসহ |
প্রোভাইডার নোট (২০২৬-১০-১২ অনুযায়ী): থিঙ্কিং গভীরতার শব্দভান্ডার প্রোভাইডারভেদে আলাদা। OpenAI ডকুমেন্ট করে
reasoning.effortসেটিং। Anthropic ডকুমেন্ট করে অ্যাডাপ্টিভ থিঙ্কিং ও একটাeffortসেটিং, এবং বলে আগের ম্যানুয়ালbudget_tokensঅচল ঘোষিত (deprecated) আর তাদের নতুনতম মডেলে সেটা এরর দেয়। Google ডকুমেন্ট করেthinking_level। স্যাম্পলিং সেটিংও আলাদা: OpenAI বলে রিজনিং effortnoneনা হলেtemperatureওtop_pসরিয়ে দিতে; Anthropic বলে বর্তমানের কিছু মডেলে ডিফল্ট ছাড়াtemperature,top_pবাtop_kএরর দেয়; Google তাদের নতুনতম পরিবারে এগুলো ডিফল্টে রাখার পরামর্শ দেয়। ক্যাশ মার্কার ও স্ট্রাকচার্ড-আউটপুট স্কিমাও প্রোভাইডার-নির্দিষ্ট, আর প্রত্যেকে JSON Schema-র শুধু একটা উপসেট সমর্থন করে। বর্তমান ডকুমেন্টেশন দেখে নিন।
জানা পার্থক্য রেকর্ড করা
পরীক্ষা করা মডেলগুলোর জানা পার্থক্য রেকর্ড করুন, যাতে পরের জনকে সেগুলো আবার আবিষ্কার করতে না হয়, আর ভ্যারিয়েন্ট নিয়ে সিদ্ধান্তের পেছনে প্রমাণ থাকে। নিচের ফাংশন দুটো ম্যাট্রিক্সকে রেকর্ডে বদলায় এবং এই পাতার একটা নিয়ম খাটায়: কোনো ব্যর্থতা না থাকলে সাধারণ প্রম্পট কাজ করছে; অ্যাডাপ্টেশনের পরে যে ব্যর্থতা মিলিয়ে যায় তার মানে ছোট একটা ভ্যারিয়েন্ট রাখুন; যে ব্যর্থতা থেকে যায় তার মানে ভ্যারিয়েন্ট যথেষ্ট নয়।
def decide(bad_before, bad_after):
if not bad_before:
return "shared prompt works"
return "keep a small variant" if not bad_after else "variant is not enough: change model or route"
records = []
for name in sorted(TARGETS):
bad_before = [c for c, cells in before.items() if cells[name] != "ok"]
bad_after = [c for c, cells in after.items() if cells[name] != "ok"]
records.append({"target": name, "snapshot": "toy-1", "tested": "2026-10-12",
"fails_core": bad_before, "fails_adapted": bad_after,
"decision": decide(bad_before, bad_after)})
for record in records:
print(json.dumps(record, ensure_ascii=False, sort_keys=True)){"decision": "shared prompt works", "fails_adapted": [], "fails_core": [], "snapshot": "toy-1", "target": "toy_a", "tested": "2026-10-12"}
{"decision": "variant is not enough: change model or route", "fails_adapted": ["bn-late", "bn-twice"], "fails_core": ["en-late", "en-twice", "bn-late", "bn-twice"], "snapshot": "toy-1", "target": "toy_b", "tested": "2026-10-12"}
{"decision": "keep a small variant", "fails_adapted": [], "fails_core": ["en-late", "en-twice", "bn-late", "bn-twice"], "snapshot": "toy-1", "target": "toy_c", "tested": "2026-10-12"}এই লাইনগুলো প্রম্পটের পাশে রাখুন (ভার্সন কন্ট্রোলে একটা JSONL ফাইল ভালো কাজ করে; প্রম্পট ও মডেল ভার্সন ট্র্যাকিংয়ের জন্য দেখুন AI-এর জন্য Git, API ও ব্যাকএন্ড: অ্যাডভান্সড)। স্ন্যাপশট বদলালে আবার চালান, নতুন লাইন যোগ করুন, আর পুরোনোগুলো রেখে দিন: ইতিহাস দেখায় কোন পার্থক্য স্থিতিশীল আর কোনটা সরে যায়।
কাজের জায়গায় এটা কোথায় দেখা যায়
যে টিম একটা বিকল্প হাতে রাখতে দুজন মডেল ভেন্ডর সমর্থন করে, তারা একটা কোর প্রম্পট, কারণসহ প্রতি-টার্গেট লাইনের একটা টেবিল, আর কেসের সেটের একটা প্রতি রাতের রান রাখে। নতুন মডেল স্ন্যাপশটে যাওয়া তখন আগে-পরে ম্যাট্রিক্সসহ একটা পুল রিকোয়েস্ট। যে প্রোডাক্ট Bangla ও English গ্রাহক দুই দলকেই সেবা দেয়, সে প্রতিটা রিলিজ টেস্টে দুই ভাষাই রাখে, কারণ ভাষার ফাঁক শুধু-English টিমের চোখে পড়ে না।
সাধারণ ভুল
- গাইড না পড়ে পোস্ট থেকে কৌশল কপি করা। সেটা অন্য মডেল বা মোডের জন্য লেখা হতে পারে। উৎস পড়ুন, তারিখ লিখুন, নিজের কেস চালান।
- এক প্রম্পটে সব সমাধান ঢোকানো। কোন লাইন গুরুত্বপূর্ণ কেউ জানে না। একটা কোর আর কারণসহ নামওয়ালা অ্যাডাপ্টেশন রাখুন।
- শব্দ দিয়ে সক্ষমতার ফাঁক ভরাতে চাওয়া। লম্বা প্রম্পটে ব্যর্থ কেস না নড়লে মডেল বদলান, ওই কেসগুলো রাউট করুন, বা সীমাটা নথিবদ্ধ করুন।
- শুধু English-এ টেস্ট করা। আপনি যত ভাষায় সেবা দেন সবগুলো কেসের সেটে রাখুন, প্রতিটার প্রত্যাশিত ফলসহ।
- অ্যালিয়াস ব্যবহার করে রেকর্ড না রাখা। যে স্ন্যাপশট টেস্ট করেছেন সেটা পিন করুন, আর প্রতিটা ফলের সঙ্গে তার শনাক্তকারী রাখুন।
নিজে চেষ্টা করুন
এই পাতার কোড ব্যবহার করুন; ব্লকগুলো একই নেমস্পেস ভাগ করে। অনুশীলনগুলো ইন্সট্রাকশন হায়ারার্কি ও মেসেজ রোল: সিস্টেম, ডেভেলপার ও ইউজার পাতার অ্যাডাপ্টার ধারণাটা আবার ছোঁয়।
- সহজ। "শুধু কোর প্রম্পট" টেবিলটা দেখুন। যে ব্যর্থতার ধরনগুলো আসে প্রতিটার নাম বলুন, আর বলুন প্রতিটার ঠিক প্রতিক্রিয়া একটা প্রম্পট লাইন না অন্য মডেল।
- মাঝারি। একটা বদলি স্ন্যাপশট
toy_c_v2যোগ করুন, যাtoy_c-এর মতো আচরণ করে কিন্তু একটা বাড়তি কি"confidence"ফেরত দেয়।toy_cওtoy_c_v2-এর জন্য অ্যাডাপ্ট করা ম্যাট্রিক্স চালান এবং বলুন ব্যর্থতাটা আপনাকে কী জানায়। - কঠিন। একটা প্রম্পটকে তিনটা প্রোভাইডার ইন্টারফেসে মানিয়ে নিন। তিনটা নিরপেক্ষ আকারের জন্য
adapt(rules, ticket, shape)লিখুন:role_message(নিয়মdeveloperরোলের মেসেজে),system_field(নিয়ম টপ-লেভেলsystemফিল্ডে) আরsingle_box(নিয়মের আলাদা জায়গা নেই: লেবেল দেওয়া অংশসহ একটাই ইউজার টেক্সট, সঙ্গে বাড়তি "no text before or after" লাইন)। তিনটাকে JSON হিসেবে ছাপুন এবং যাচাই করুন টিকেটের টেক্সট সবকটায় হুবহু এক।
উত্তর
সহজ। not-json (toy_b ও toy_c) ফরম্যাটের পার্থক্য, তাই প্রতি টার্গেটে একটা লাইন যোগ করুন। toy_b-এর Bangla টিকেটে wrong-label আসে শুধু ফরম্যাট ঠিক হওয়ার পরে, আর সেটা সক্ষমতার ফাঁক, তাই রাউট করুন বা মডেল বদলান। পাস চেকলিস্ট: আপনি ফরম্যাটের ব্যর্থতা আর সক্ষমতার ব্যর্থতা আলাদা করেছেন, এবং দেখেছেন প্রথম ধরন ঠিক করতেই দ্বিতীয়টা বেরিয়ে এল।
মাঝারি।
def toy_c_v2(prompt):
data = json.loads(toy_c(prompt))
data["confidence"] = 0.9
return json.dumps(data, ensure_ascii=False)
for cid, cells in run({"toy_c": toy_c, "toy_c_v2": toy_c_v2}, True).items():
print(cid.ljust(10) + cells["toy_c"].ljust(8) + cells["toy_c_v2"])en-late ok bad-keys
en-twice ok bad-keys
bn-late ok bad-keys
bn-twice ok bad-keysপাস চেকলিস্ট: toy_c_v2 সব কেসে bad-keys দিয়ে ব্যর্থ, যদিও লেবেল ঠিক; আপনি ব্যাখ্যা করেছেন অপ্রত্যাশিত ফিল্ডে ডাউনস্ট্রিম পার্সার ভেঙে যেত, তাই চোখ নয়, চেকারই এটা ধরেছে; আর আপনি ঠিক করেছেন একটা প্রম্পট লাইন যোগ করবেন ("ঠিক এই দুটো কি ব্যবহার করুন") না চেকারে বাড়তি কি অনুমোদন করবেন।
কঠিন। একটা সম্ভাব্য সমাধান:
RULES = CORE.split("Ticket:")[0] + ADAPT["toy_b"][0]
def adapt(rules, ticket, shape):
if shape == "role_message":
return {"input": [{"role": "developer", "content": rules}, {"role": "user", "content": ticket}]}
if shape == "system_field":
return {"system": rules, "messages": [{"role": "user", "content": ticket}]}
return {"messages": [{"role": "user", "content": "Rules:\n" + rules + "\n\nTicket:\n" + ticket}]}
ticket = CASES[2][1]
built = {s: adapt(RULES, ticket, s) for s in ("role_message", "system_field", "single_box")}
for shape, request in built.items():
print(shape, sorted(request), len(json.dumps(request, ensure_ascii=False)))
print(all(ticket in json.dumps(r, ensure_ascii=False) for r in built.values()))role_message ['input'] 341
system_field ['messages', 'system'] 320
single_box ['messages'] 327
Trueপাস চেকলিস্ট: নিয়মের স্ট্রিং একবারই বানানো; আকারভেদে শুধু মোড়ক আলাদা; টিকেট তিনটাতেই অপরিবর্তিত; ফিল্ডের নামগুলো নিরপেক্ষ লেবেল, আর প্রতিটা প্রোভাইডারের আসল নাম তার ডকুমেন্টেশন থেকে আসে। আসল প্রজেক্টে ব্যবহারের আগে তিনটা র্যাপারের প্রতিটার ভেতর দিয়ে একই কেস ম্যাট্রিক্স চালাবেন।
সারসংক্ষেপ
- কোনো কৌশল নেওয়ার আগে প্রোভাইডারের গাইড পড়ুন এবং মডেল, উদ্ধৃতি ও তারিখ লিখে রাখুন; তারপর নিজের কেসে টেস্ট করুন।
- একটা সাধারণ কোর আর ছোট নামওয়ালা অ্যাডাপ্টেশন রাখুন। প্রম্পটের পার্থক্য (একটা লাইনে ঠিক হয়) আর সক্ষমতার ফাঁক (শব্দে ঠিক হয় না) আলাদা করুন।
- প্রতিটা টার্গেট ও প্রতিটা স্ন্যাপশটে, English ও আপনার সেবা দেওয়া প্রতিটা অন্য ভাষায়, একই স্থির কেস চালান, আর কোড দিয়ে ফল যাচাই করুন।
- অনথিভুক্ত আচরণের ওপর নির্ভর করবেন না; শুধু-এক-প্রোভাইডারের ফিচার ফলব্যাকসহ অ্যাডাপ্টার স্তরে রাখুন।
- পার্থক্য স্ন্যাপশট ও তারিখসহ রেকর্ড করুন, আর কিছু বদলালেই আবার চালান।
এরপর: রিজনিং টাস্ক ডিজাইন: টাস্ক ভাগ করা, যুক্তির সারাংশ ও মধ্যবর্তী স্কিমা দেখায় কয়েক ধাপের টাস্ক কীভাবে ডিজাইন করবেন, আর কখন সরাসরি নির্দেশই যথেষ্ট।