অধ্যায় 3 · ডকুমেন্টেশন ও তদারকি
প্রকাশ ও ডকুমেন্টেশন যাচাই: Python দিয়ে সিস্টেম কার্ড পরীক্ষা
- পৃষ্ঠা 10 / 22
- 18 মিনিট পড়া
আগের পাতায় কার্ডটা হাতে বানানো হয়েছিল। এই পাতায় কাজটা শেষ হবে: ডেটার অনুমতি আর ভার্সন নিয়ে কী লিখবেন, একটা আউটপুট কী বলতে পারে আর কী পারে না তা কীভাবে লিখবেন, প্রভাবিত মানুষদের সহজ ভাষায় কীভাবে জানাবেন, কী প্রকাশ্য রাখবেন আর কী অভ্যন্তরীণ, এবং একটা ছোট প্রোগ্রাম কীভাবে কার্ড পরীক্ষা করতে পারে। পরীক্ষাগুলো ইচ্ছে করেই সাধারণ। কার্ডটা সত্য কি না তা এগুলো বলতে পারে না; কোথায় কার্ড ফাঁকা, প্রমাণহীন, বা নিজের সঙ্গেই অসংগত, তা দেখাতে পারে।
আপনার দরকার Python 3.12, শুধু স্ট্যান্ডার্ড লাইব্রেরি: কোনো প্যাকেজ, নেটওয়ার্ক বা মডেল কল নেই। এই পাতা নতুন ফোল্ডারে নিজে নিজে চলে, তাই মডেল কার্ড, সিস্টেম কার্ড ও ডেটাশিট: কী নথিভুক্ত করবেন এবং কার জন্য পাতার কার্ডের একটা ছোট সংস্করণ এখানে আবার বানানো হয়েছে।
সততার নিয়ম। এখানকার প্রতিটা নাম, ফাইল, তারিখ ও সংখ্যা কাল্পনিক, আর ফল শুধু দেখায় একটা পরীক্ষা কীভাবে কাজ করে। নিচের সব পরীক্ষা পেরিয়ে যাওয়া কার্ড তাতে নির্ভুল, নিরাপদ বা আইনসম্মত হয়ে যায় না। স্ক্রিপ্টগুলো যা নেই বা অজানা, তা রিপোর্ট করে, ফাঁক অনুমান দিয়ে ভরে না। এখানকার কিছুই আইনি পরামর্শ নয়।
যা শিখবেন
- ডেটার উৎস, অনুমতির অনুমান আর মডেল ও সিস্টেমের সুনির্দিষ্ট ভার্সন কীভাবে লিখবেন।
- সিস্টেম নিজেকে "ব্যাখ্যা করে" এমন অতিদাবি না করে একটা আউটপুটের সীমা কীভাবে বর্ণনা করবেন।
- ব্যবহারকারীদের জন্য AI-ব্যবহারের প্রকাশ-বিবৃতি সহজ ভাষায় কীভাবে লিখবেন, আর দুর্বল ও ভালো সংস্করণের পার্থক্য কীভাবে বুঝবেন।
- সীমাবদ্ধতা না লুকিয়ে প্রকাশ্য ডকুমেন্টেশন আর অভ্যন্তরীণ রেকর্ড কীভাবে আলাদা করবেন।
- টেমপ্লেট থেকে কার্ডের খসড়া বানানো, প্রয়োজনীয় ফিল্ড যাচাই, অনুপস্থিত প্রমাণ চিহ্নিত করা এবং স্ববিরোধ ও পুরোনো দাবি ধরা।
ডেটার উৎস, অনুমতি ও ভার্সন
ডেটার উৎস ও অনুমতির অনুমান লিখুন। প্রতিটা ডেটাসেটের জন্য লিখুন সেটা কোথা থেকে এসেছে এবং এই উদ্দেশ্যে ব্যবহারের ভিত্তি কী। অনুমান (assumption) হলো এমন কিছু যা আপনি বিশ্বাস করেন কিন্তু যাচাই করেননি। একে অনুমান হিসেবেই লিখুন, কে যাচাই করবেন তা বলুন, আর কেউ যাচাই না করা পর্যন্ত "checked by" খালি রাখুন। এর পেছনের প্রশ্নগুলো ব্যাখ্যা করা আছে ডেটা গভর্ন্যান্স: উদ্দেশ্য, সম্মতি, ন্যূনতম ডেটা, মান ও পুনঃশনাক্তকরণ পাতায়।
মডেল ও সিস্টেমের ভার্সন লিখুন। মডেল ভার্সন প্রশিক্ষিত মডেলটাকে চিহ্নিত করে; সিস্টেম ভার্সন চিহ্নিত করে তার চারপাশের পুরো ওয়ার্কফ্লো, পার্সার, থ্রেশহোল্ড ও ইন্টারফেসসহ। ফল একটা ভার্সনের। ভার্সন ছাড়া "পরীক্ষিত" লেখা কার্ডকে আজ যা চলছে তার সঙ্গে মেলানো যায় না।
টয় ডেটা: স্ক্রিনিং ফিচারের ০.৪ ভার্সনের জন্য ছোট একটা কার্ড।
CARD = {
"name": "ShortlistHelper (hypothetical)",
"card_version": "1.2",
"versions": {"system": "0.4", "model": "fit-scorer-2026.08", "parser": "1.3"},
"intended_use": "order the CVs for ONE job so a recruiter knows which to read first",
"out_of_scope": ["automatic rejection", "ranking current staff"],
"data_sources": [
{"name": "past_applicants_2023_2025", "origin": "the agency's own archive",
"permission": {"basis": "assumed",
"assumption": "the 2023 privacy notice covers testing of tools",
"checked_by": None}},
],
}
from pprint import pprint
for key in ("versions", "data_sources"):
print(key, "->")
pprint(CARD[key], width=88, sort_dicts=False)versions ->
{'system': '0.4', 'model': 'fit-scorer-2026.08', 'parser': '1.3'}
data_sources ->
[{'name': 'past_applicants_2023_2025',
'origin': "the agency's own archive",
'permission': {'basis': 'assumed',
'assumption': 'the 2023 privacy notice covers testing of tools',
'checked_by': None}}]অনুমতিটা assumed হিসেবে লেখা, আর কেউ তা যাচাই করেননি। এটা সৎ লেখা, আবার একটা পর্যবেক্ষণও: পরের পরীক্ষা একে চিহ্নিত করবে, নিষ্পত্তি-হওয়া বিষয় হিসেবে পার হতে দেবে না।
অতিদাবি ছাড়া আউটপুটের সীমা
ব্যাখ্যাযোগ্যতার অতিদাবি না করে আউটপুটের সীমাবদ্ধতা বর্ণনা করুন। এই কোর্সে ব্যাখ্যা (explanation) মানে এমন বক্তব্য, যা দিয়ে একজন মানুষ ফল বুঝতে ও তাতে আপত্তি তুলতে পারেন। অনেক টুল ব্যাখ্যার মতো দেখতে কিছু দেখায়: হাইলাইট করা শব্দ, "ফ্যাক্টর"-এর র্যাংক করা তালিকা, মডেলের বানানো একটা ছোট বাক্য। এগুলো দেখায় মডেল কিসে সাড়া দিয়েছে, বা মডেল কী লিখেছে। এগুলো স্কোরের আসল কারণ কি না, সেটা আলাদা প্রশ্ন, আর তার জন্য আলাদা পরীক্ষা লাগে।
| অতিদাবি | ভালো শব্দচয়ন |
|---|---|
| "হাইলাইট করা শব্দগুলোই স্কোরের কারণ।" | "হাইলাইট করা শব্দগুলো স্কোরকে সবচেয়ে বেশি বদলেছে। এগুলো মানুষের দেওয়া কারণের সঙ্গে মেলে কি না, তা আমরা পরীক্ষা করিনি।" |
| "সিস্টেম প্রতিটা সিদ্ধান্ত ব্যাখ্যা করে।" | "সিস্টেম একটা স্কোর ও হাইলাইট দেখায়। একটা CV কেন এই স্কোর পেল তার পূর্ণ ব্যাখ্যা এটা দেয় না।" |
| "স্কোর প্রার্থীর মান মাপে।" | "স্কোর চাকরির বিবরণের সঙ্গে মিলের মাত্রা দেখায়। এটা দক্ষতা বা সাফল্যের সম্ভাবনা মাপে না।" |
CARD["output_limitations"] = {
"score_is": "a number from 0 to 100 computed by a model from the CV text",
"score_is_not": ["a measure of ability", "a probability of success", "a reason"],
"highlights": "words that changed the score most; not tested as a human reason",
}
print(CARD["output_limitations"]["score_is_not"])['a measure of ability', 'a probability of success', 'a reason']প্রভাবিত মানুষদের জানানো
ব্যবহারকারীর জন্য AI-ব্যবহারের প্রকাশ-বিবৃতি লিখুন। প্রকাশ-বিবৃতি (disclosure) প্রভাবিত মানুষদের এমন ভাষায় জানায় যে AI জড়িত, যা তাঁরা কাজে লাগাতে পারেন। তাতে থাকা উচিত সিস্টেম কী করে, কোন ডেটা ব্যবহার করে, সিদ্ধান্ত কে নেয়, সীমা কী, আর মানুষের কাছে কীভাবে চাইবেন। নোটিশ নিয়ে নিয়ম দেশ ও খাতভেদে আলাদা (দেখুন স্ট্যান্ডার্ড, নিয়ন্ত্রণ ও প্রয়োজন ম্যাপিং: কী, কার জন্য এবং কেন প্রযোজ্য); ভালো নোটিশ এমন জায়গাতেও মানুষের কাজে লাগে, যেখানে কোনো নিয়ম নেই।
কাল্পনিক পরিস্থিতি: এজেন্সির আবেদন ফর্মে দুই সংস্করণের নোটিশ।
WEAK
Applications may be processed using automated tools in accordance with applicable policies
and procedures, and the outputs of such tools may inform decisions.
BETTER
We use a computer program to suggest the order in which our recruiters read CVs. It reads
only the text of your CV and gives it a score. A recruiter, not the program, decides who is
invited to an interview. A CV low on the list may not be opened unless a recruiter chooses
to. If you want a person to read your whole CV, tell us on the form or by email. The program
has been tested only on CVs written in English. We last checked this notice on 2026-10-01.দুর্বল সংস্করণটা সত্য, কিন্তু প্রায় কিছুই বলে না: টুলটা কী করে, কে সিদ্ধান্ত নেয় বা মানুষকে কীভাবে চাওয়া যায়, কোনোটাই পাঠক জানতে পারেন না। ভালো সংস্করণটা না-খোলা CV নিয়ে সৎ, ফলে কার্ডের সঙ্গেও মেলে। পড়ার সহজতার একটা মোটা মাপকাঠি হলো বাক্যের গড় দৈর্ঘ্য; এটা শুধু একটা ইঙ্গিত, কারণ ছোট বাক্যও বিভ্রান্ত করতে পারে।
import re
def sentence_stats(text):
sentences = [s for s in re.split(r"(?<=[.!?])\s+", " ".join(text.split())) if s]
words = sum(len(s.split()) for s in sentences)
return len(sentences), words, round(words / len(sentences), 1)
weak = ("Applications may be processed using automated tools in accordance with applicable "
"policies and procedures, and the outputs of such tools may inform decisions.")
better = ("We use a computer program to suggest the order in which our recruiters read CVs. "
"It reads only the text of your CV and gives it a score. A recruiter, not the program, "
"decides who is invited to an interview. A CV low on the list may not be opened unless "
"a recruiter chooses to. If you want a person to read your whole CV, tell us on the "
"form or by email. The program has been tested only on CVs written in English. "
"We last checked this notice on 2026-10-01.")
for name, text in (("weak", weak), ("better", better)):
print(name, "(sentences, words, words per sentence):", sentence_stats(text))weak (sentences, words, words per sentence): (1, 23, 23.0)
better (sentences, words, words per sentence): (7, 91, 13.0)নোটিশ আপনার আবেদনকারীরা যে ভাষায় কথা বলেন সেই ভাষাগুলোতেও থাকা উচিত। কার্ড বলছে শুধু ইংরেজি পরীক্ষা হয়েছে; নোটিশ যেন এর চেয়ে বেশি কিছু বোঝায় না।
প্রকাশ্য ডকুমেন্টেশন ও অভ্যন্তরীণ রেকর্ড
প্রকাশ্য ডকুমেন্টেশন আর অভ্যন্তরীণ সীমাবদ্ধ রেকর্ডের পার্থক্য করুন। আপনি যা জানেন তার কিছু সম্ভাব্য প্রভাবিত সবার জন্য: সিস্টেম কিসের জন্য, তার সীমা, মানুষের কাছে কীভাবে পৌঁছাবেন। কিছু অংশ ভালো কারণেই সীমাবদ্ধ: ব্যক্তিগত ডেটা, নিরাপত্তার খুঁটিনাটি, বাণিজ্যিক শর্ত, যে টেস্ট সেটের হুবহু বিষয়বস্তু জানলে ফল ম্যানিপুলেট করা যায়। দুটো নিয়ম কাজে লাগে। প্রথমত, সীমাবদ্ধ রাখার কারণ লিখিতভাবে রাখুন। দ্বিতীয়ত, কোনো সীমাবদ্ধতা লজ্জার বলে সীমাবদ্ধ রাখবেন না। সীমাবদ্ধ রেকর্ডও তাঁদের জন্য খোলা থাকে যাঁদের তা পর্যালোচনা করতে হয়, যেমন অডিটর এবং আইনে বললে কর্তৃপক্ষ।
CARD.update({
"tests": [{"name": "group comparison", "result": "done", "evidence": "eval/group_check.csv"},
{"name": "parser check", "result": "passed", "evidence": None}],
"evaluation": {"claim": "score order tested on 40 past applicants",
"evidence_file": "eval/shortlist_check_01.csv"},
"limitations": ["uses CV text only", {"status": "UNKNOWN", "why": "no calibration test run"}],
"language_coverage": {"tested": ["English"], "not_tested": ["Spanish"]},
"accessibility": {"status": "UNKNOWN", "why": "upload form not reviewed"},
"human_oversight": {"escalation": ["parse warning -> read by hand"]},
"failure_modes": [],
"next_review": "2026-09-30",
})
VISIBILITY = {"name": "public", "card_version": "public", "versions": "public",
"intended_use": "public", "out_of_scope": "public", "output_limitations": "public",
"limitations": "public", "language_coverage": "public", "accessibility": "public",
"human_oversight": "public", "next_review": "public",
"data_sources": "internal", "tests": "internal", "evaluation": "internal",
"failure_modes": "public"}
def view(card, audience):
keep = {k: v for k, v in card.items()
if audience == "internal" or VISIBILITY[k] == "public"}
return keep, len(card) - len(keep)
public, withheld = view(CARD, "public")
import textwrap
print(textwrap.fill("public sections: " + ", ".join(public), 90))
print("withheld from the public page:", withheld, "(listed as available to reviewers)")
assert "limitations" in public and "language_coverage" in publicpublic sections: name, card_version, versions, intended_use, out_of_scope,
output_limitations, limitations, language_coverage, accessibility, human_oversight,
failure_modes, next_review
withheld from the public page: 3 (listed as available to reviewers)প্রকাশ্য ভিউয়ে প্রতিটা সীমাবদ্ধতা আছে, আর সেটা বলে যে কিছু আটকে রাখা হয়েছে। টেস্ট সেট ও ডেটা রেকর্ড অভ্যন্তরীণ ভিউয়ে রাখা এই টয় উদাহরণের একটা বাছাই; প্রতিটা দলের উচিত লিখে রাখা কেন, আর অভ্যন্তরীণ ভিউ কে পড়তে পারবেন। ব্যর্থতার ধরন এখানে প্রকাশ্য, কারণ জানা ব্যর্থতার উপায় এমন একটা সীমাবদ্ধতা যা প্রভাবিত মানুষের জানা দরকার।
কার্ডের খসড়া ও যাচাই
কাঠামোবদ্ধ টেমপ্লেট থেকে সিস্টেম কার্ডের খসড়া বানান। টেমপ্লেট বলে কার্ডে কোন কোন ফিল্ড থাকতেই হবে। একটা প্রোগ্রাম ডিকশনারিকে পড়ার মতো খসড়ায় বদলাতে পারে, আর দেখাতে পারে কোন ফিল্ড এখনও ভরা হয়নি। খসড়া শুধু ডিকশনারি যা বলে তা লেখে, নিজে কিছু যোগ করে না। একই ফাইলে প্রয়োজনীয় ফিল্ড যাচাই করুন: ফিল্ড না থাকলে বা খালি হলে MISSING, আর কেউ ইচ্ছে করে ফাঁক লিখে রাখলে UNKNOWN।
# file: cardcheck.py
import textwrap
from datetime import date
AS_OF = date(2026, 10, 12) # a fixed "today", so every run gives the same answer
MISSING = object()
REQUIRED = [
("name", "Feature"), ("versions.system", "System version"),
("versions.model", "Model version"), ("intended_use", "Intended use"),
("out_of_scope", "Out of scope"), ("data_sources", "Data sources"),
("evaluation.evidence_file", "Evaluation evidence"), ("limitations", "Limitations"),
("language_coverage", "Language coverage"), ("accessibility", "Accessibility"),
("human_oversight.escalation", "Escalation"), ("failure_modes", "Failure modes"),
("next_review", "Next review"),
]
def get(card, path):
node = card
for key in path.split("."):
if not isinstance(node, dict) or key not in node:
return MISSING
node = node[key]
return node
def status(value):
if value is MISSING or value in ("", [], {}, None):
return "MISSING"
if isinstance(value, dict) and value.get("status") == "UNKNOWN":
return "UNKNOWN"
return "ok"
def validate(card):
return [(status(get(card, p)), p, label) for p, label in REQUIRED]
def unknown_paths(x, prefix=""):
found = []
if isinstance(x, dict):
if x.get("status") == "UNKNOWN":
found.append(prefix)
for k, v in x.items():
found += unknown_paths(v, f"{prefix}.{k}" if prefix else k)
elif isinstance(x, list):
for i, v in enumerate(x):
found += unknown_paths(v, f"{prefix}[{i}]")
return found
def show(value):
if isinstance(value, str):
return value
if isinstance(value, list):
return "; ".join(show(v) for v in value)
if isinstance(value, dict) and value.get("status") == "UNKNOWN":
return "UNKNOWN (" + value["why"] + ")"
if isinstance(value, dict):
return ", ".join(f"{k}: {show(v)}" for k, v in value.items())
return str(value)
def draft(card):
lines = ["SYSTEM CARD (DRAFT, not reviewed)"]
for path, label in REQUIRED:
value, s = get(card, path), status(get(card, path))
if s == "MISSING":
text = "MISSING - the owner must supply this"
elif s == "UNKNOWN":
text = "UNKNOWN - " + value["why"]
else:
text = show(value)
lines.append(textwrap.fill(f"{label}: {text}", 92, subsequent_indent=" "))
return "\n".join(lines)from cardcheck import draft, validate, unknown_paths
print(draft(CARD))
rows = validate(CARD)
print()
print({s: sum(1 for r in rows if r[0] == s) for s in ("ok", "UNKNOWN", "MISSING")})
for s, path, label in rows:
if s != "ok":
print(f"{s:<8}{path}")
print("UNKNOWN anywhere in the card:", sorted(unknown_paths(CARD)))SYSTEM CARD (DRAFT, not reviewed)
Feature: ShortlistHelper (hypothetical)
System version: 0.4
Model version: fit-scorer-2026.08
Intended use: order the CVs for ONE job so a recruiter knows which to read first
Out of scope: automatic rejection; ranking current staff
Data sources: name: past_applicants_2023_2025, origin: the agency's own archive, permission:
basis: assumed, assumption: the 2023 privacy notice covers testing of tools, checked_by:
None
Evaluation evidence: eval/shortlist_check_01.csv
Limitations: uses CV text only; UNKNOWN (no calibration test run)
Language coverage: tested: English, not_tested: Spanish
Accessibility: UNKNOWN - upload form not reviewed
Escalation: parse warning -> read by hand
Failure modes: MISSING - the owner must supply this
Next review: 2026-09-30
{'ok': 11, 'UNKNOWN': 1, 'MISSING': 1}
UNKNOWN accessibility
MISSING failure_modes
UNKNOWN anywhere in the card: ['accessibility', 'limitations[1]']খসড়াটা পড়া যায় কিন্তু শেষ হয়নি, আর যেখানে দরকার সেখানে তা নিজেই বলে দেয়। Failure modes MISSING (তালিকা খালি), Accessibility ইচ্ছে করে UNKNOWN, আর কার্ডের আরও ভেতরের একটা সীমাবদ্ধতাও UNKNOWN। যে ভ্যালিডেটর এগুলো বিশ্বাসযোগ্য বাক্য দিয়ে ভরে দিত, সে এমন কার্ড বানাত যা দেখতে সম্পূর্ণ আর মানে কিছুই নয়।
অনুপস্থিত প্রমাণ চিহ্নিত করা ও স্ববিরোধ ধরা
অনুমান দিয়ে না ভরে অনুপস্থিত প্রমাণ চিহ্নিত করুন। কার্ড "পরীক্ষিত" বা "পাস"-এর মতো দাবি করে। প্রতিটা দাবির সঙ্গে এমন কিছু থাকা উচিত যা পাঠক খুলে দেখতে পারেন। নিচের পরীক্ষাটা চিহ্নিত করে প্রমাণের উল্লেখ ছাড়া দাবি, এমন ফাইলের উল্লেখ যা নেই, আর এখনও-যাচাই-না-হওয়া অনুমান-ভিত্তিক অনুমতি।
ডকুমেন্টেশনের স্ববিরোধ ও পুরোনো দাবি পর্যালোচনা করুন। ডকুমেন্টেশন দুভাবে পুরোনো হয়: সিস্টেম বদলায়, বা সময় যায়। কার্ডকে এমন অন্য রেকর্ডের সঙ্গে মেলান যেগুলোর কার্ডের সঙ্গে একমত হওয়ার কথা: রিলিজ লগ, কনফিগারেশন আর রিভিউয়ের তারিখ। পরীক্ষাগুলো সহজ নিয়ম; প্রতিটা ফ্ল্যাগের মানে কী, তা ঠিক করেন একজন মানুষ।
# file: consistency.py
from datetime import date
from pathlib import Path
from cardcheck import AS_OF, get
def evidence_flags(card):
flags = []
path = get(card, "evaluation.evidence_file")
if isinstance(path, str) and not Path(path).exists():
flags.append(f"evaluation: evidence file {path} not found")
for t in card.get("tests", []):
ev = t.get("evidence")
if not ev:
flags.append(f"test '{t['name']}' says '{t['result']}' but cites no evidence")
elif not Path(ev).exists():
flags.append(f"test '{t['name']}': evidence file {ev} not found")
for s in card.get("data_sources", []):
p = s.get("permission", {})
if p.get("basis") == "assumed" and not p.get("checked_by"):
flags.append(f"data '{s['name']}': permission is an unchecked assumption")
return flags
def consistency_flags(card, release, config):
flags = []
for part in ("system", "model"):
said, real = card["versions"][part], release[part]
if said != real:
flags.append(f"{part} version: card says {said}, release log says {real}")
due = date.fromisoformat(card["next_review"])
if due < AS_OF:
flags.append(f"review overdue: {due} is {(AS_OF - due).days} days before {AS_OF}")
if config.get("auto_reject_below") is not None and \
"automatic rejection" in card.get("out_of_scope", []):
flags.append("card puts automatic rejection out of scope, but the config sets "
f"auto_reject_below={config['auto_reject_below']}")
tested = set(card["language_coverage"]["tested"])
for lang in sorted(set(config["languages_enabled"]) - tested):
flags.append(f"language {lang} is enabled in the config but not tested")
return flagsfrom pathlib import Path
from consistency import evidence_flags, consistency_flags
Path("eval").mkdir()
Path("eval/shortlist_check_01.csv").write_text("toy stand-in for the team's results file\n")
RELEASE = {"system": "0.5", "model": "fit-scorer-2026.08"} # Toy data: the release log
CONFIG = {"auto_reject_below": 15, "languages_enabled": ["English", "Spanish"]} # Toy data
print("EVIDENCE")
for f in evidence_flags(CARD):
print(" -", f)
print("CONSISTENCY (as of 2026-10-12)")
for f in consistency_flags(CARD, RELEASE, CONFIG):
print(" -", f)EVIDENCE
- test 'group comparison': evidence file eval/group_check.csv not found
- test 'parser check' says 'passed' but cites no evidence
- data 'past_applicants_2023_2025': permission is an unchecked assumption
CONSISTENCY (as of 2026-10-12)
- system version: card says 0.4, release log says 0.5
- review overdue: 2026-09-30 is 12 days before 2026-10-12
- card puts automatic rejection out of scope, but the config sets auto_reject_below=15
- language Spanish is enabled in the config but not testedপ্রমাণের ফ্ল্যাগগুলো বলে কার্ড আজ কোন দাবির পেছনে দাঁড়াতে পারছে না। অসংগতির ফ্ল্যাগে চার ধরনের বিরোধ দেখা যায়। সবচেয়ে গুরুতর বিরোধ কার্ড (স্বয়ংক্রিয় বাতিল পরিধির বাইরে) আর কনফিগারেশনের (একটা থ্রেশহোল্ড, যার নিচে আবেদনকারী বাতিল হয়, দৃশ্যত মানুষ ছাড়াই) মধ্যে। কোন ডকুমেন্ট ঠিক, কোনো ফ্ল্যাগ তা বলে না। সেটা খুঁজে বের করা মালিকের কাজ, আর সমাধান হতে পারে কনফিগারেশন, কার্ড বা পরিকল্পনা বদলানো।
এই পরীক্ষার সীমা। এগুলো শুধু লেখা তথ্য মেলায়। একটা মিথ্যা বক্তব্য প্রতিটা জায়গায় একই রকম লেখা থাকলে সেটা পার হয়ে যায়। পরিষ্কার আউটপুটের মানে "এই নিয়মগুলোতে কোনো বিরোধ পাওয়া যায়নি", "ডকুমেন্টেশন সত্য" নয়। আসল পর্যালোচনায় এখনও এমন মানুষ লাগে যাঁরা সিস্টেমটা দেখতে পারেন।
কাজের জায়গায় এটা কোথায় দেখা যায়
দলগুলো রিলিজ বা ত্রৈমাসিক পর্যালোচনার আগে এ ধরনের পরীক্ষা চালায় এবং আউটপুট রেকর্ডে জুড়ে দেয়। অডিটর ও গ্রাহকেরা প্রায়ই কার্ড, রিলিজ লগ ও রিভিউয়ের ইতিহাস একসঙ্গে চান। মালিক ও তারিখসহ চিহ্নিত ফাঁক স্বাভাবিক; অন্য কেউ আবিষ্কার করার মতো চিহ্নহীন ফাঁকই ব্যয়বহুল।
সাধারণ ভুল
- "compliant" বা "বায়াসমুক্ত" লেখা। কার্ড কোনোটাই প্রমাণ করতে পারে না। কী করা হয়েছে আর প্রমাণ কোথায়, তা লিখুন।
- সীমা "অভ্যন্তরীণ" বলে লুকানো। প্রভাবিত মানুষের সেই সীমাগুলো জানা দরকার যা তাঁদের কাজ বদলে দেয়। ব্যক্তিগত ডেটা ও নিরাপত্তার খুঁটিনাটি সীমাবদ্ধ রাখুন, দুর্বলতা নয়।
- অনুমানকে তথ্য ধরা। "আমাদের গোপনীয়তা নোটিশে আছে" একটা অনুমান, যতক্ষণ না উপযুক্ত জ্ঞান আছে এমন কেউ যাচাই করেন।
- যে ভ্যালিডেটর ফাঁক ভরে। প্রোগ্রাম পাস করার জন্য লেখা বানালে সংকেতটা নষ্ট হয়। MISSING ও UNKNOWN যেমন আছে তেমন রিপোর্ট করুন।
- পরিষ্কার পরীক্ষাকে বিশ্বাস করা। নিয়ম পার হওয়া শুধু প্রমাণ করে কিছু সাংঘর্ষিক ছিল না। কাউকে কার্ডের সঙ্গে সিস্টেমটা মিলিয়ে দেখতে হবে।
নিজে চেষ্টা করুন
এই পাতার নেমস্পেস ব্যবহার করুন। অনুশীলনগুলো বিগিনার টিউটোরিয়ালের পলিসি, ভেন্ডর, রেকর্ড ও ঘটনা: ছোট টিমে দায়িত্বশীল AI পাতাটা আবার ছোঁয়।
- সহজ। এর কোনগুলো ব্যাখ্যাযোগ্যতার অতিদাবি করে? (ক) "হাইলাইট করা শব্দগুলোই স্কোরের কারণ।" (খ) "হাইলাইট করা শব্দগুলো স্কোরকে সবচেয়ে বেশি বদলেছে; কারণ হিসেবে আমরা এগুলো পরীক্ষা করিনি।" (গ) "মডেল তার প্রতিটা সিদ্ধান্ত ব্যাখ্যা করে।" কেন, তা বলুন।
- মাঝারি। দুর্বল নোটিশ "আমাদের প্রক্রিয়ায় AI ব্যবহার হতে পারে" নতুন করে লিখুন, যাতে টুল কী করে, কে সিদ্ধান্ত নেয়, একটা সীমা আর মানুষকে কীভাবে চাইবেন, তা থাকে।
- কঠিন। নিচের টয় ফিচারের জন্য একটা ডিকশনারিতে সিস্টেম কার্ড বানান, যা
validateগ্রহণ করে; তারপর ভ্যালিডেটর আর প্রমাণ-পরীক্ষা চালান।
কাল্পনিক পরিস্থিতি:
Feature: ReplyDrafter (hypothetical), version 0.1, model "drafter-2026.09".
Owner: Kofi, who runs a small shop in Kumasi. Efua, a staff member, reads every draft
before it is sent. If a customer complains, Kofi handles it.
Use: drafts English replies to customer emails about orders. It must not answer
refund or legal questions; those go to Kofi.
Tested: on 25 past emails (Toy data) by Kofi himself; results in eval/reply_check.csv.
3 of the 25 drafts stated the refund policy wrongly.
Languages: English tested. Twi (a language widely spoken in Ghana) not tested.
Data: past customer emails from the shop's inbox; customers have not been asked.
Access: nobody has checked whether customers can reach the shop by another route.
Review: next card review 2026-12-01.উত্তর
সহজ। (ক) ও (গ) অতিদাবি করে। (ক) পরীক্ষা ছাড়াই হাইলাইটকে কারণ বলে; (গ) পূর্ণ ব্যাখ্যার দাবি করে। (খ) বলে হাইলাইট কী, আর কী জানা নেই।
পাস চেকলিস্ট: দুটো অতিদাবির নাম এবং কারণ বলে (হাইলাইট আর কারণের সংযোগ পরীক্ষা হয়নি; "প্রতিটা" একটা চূড়ান্ত শব্দ)। দুর্বল উত্তর তিনটাই বাদ দেয় কারণ সেগুলোতে "ব্যাখ্যা" শব্দ আছে।
মাঝারি। একটা ভালো উত্তর: "আমরা গ্রাহকদের কিছু উত্তরের প্রথম খসড়া লিখতে একটা কম্পিউটার প্রোগ্রাম ব্যবহার করি। এটা শুধু আপনার বার্তাটা পড়ে। পাঠানোর আগে একজন কর্মী প্রতিটা খসড়া পড়েন ও বদলান। প্রোগ্রাম ভুল করতে পারে, তাই কিছু ঠিক না লাগলে আমাদের জানান। মানুষের সঙ্গে কথা বলতে চাইলে নিচের ঠিকানায় লিখুন।" এতে টুল কী করে, কে সিদ্ধান্ত নেয়, একটা সীমা আর মানুষের কাছে যাওয়ার পথ আছে।
পাস চেকলিস্ট: সহজ শব্দ ও ছোট বাক্য; সিদ্ধান্ত-নেওয়া মানুষটা ভূমিকা দিয়ে চেনানো; একটা সৎ সীমা; মানুষের কাছে পৌঁছানোর পথ। দুর্বল উত্তর "স্বয়ংক্রিয় টুল" শব্দটা আবার বলে বা নির্ভুলতার প্রতিশ্রুতি দেয়।
কঠিন।
from pathlib import Path
from cardcheck import validate
REPLY = {
"name": "ReplyDrafter (hypothetical)",
"versions": {"system": "0.1", "model": "drafter-2026.09"},
"intended_use": "draft English replies to order emails; a staff member reads every draft",
"out_of_scope": ["answering refund or legal questions", "sending without a person reading"],
"data_sources": [{"name": "past_customer_emails", "origin": "the shop's inbox",
"permission": {"basis": "assumed",
"assumption": "customers were not asked; not yet checked",
"checked_by": None}}],
"evaluation": {"claim": "25 past emails tested by the owner",
"evidence_file": "eval/reply_check.csv"},
"tests": [{"name": "past-email test", "result": "done", "evidence": "eval/reply_check.csv"}],
"limitations": ["3 of 25 drafts stated the refund policy wrongly (Toy data)"],
"language_coverage": {"tested": ["English"], "not_tested": ["Twi"]},
"accessibility": {"status": "UNKNOWN", "why": "no check of other contact routes"},
"human_oversight": {"escalation": ["refund or legal question -> Kofi"]},
"failure_modes": [{"mode": "wrong refund policy", "signal": "Efua spots it or a complaint",
"response": "Kofi handles it"}],
"next_review": "2026-12-01",
}
Path("eval/reply_check.csv").write_text("toy stand-in for Kofi's results file\n")
print([r[:2] for r in validate(REPLY) if r[0] != "ok"])
from consistency import evidence_flags
print(evidence_flags(REPLY))[('UNKNOWN', 'accessibility')]
["data 'past_customer_emails': permission is an unchecked assumption"]পাস চেকলিস্ট: প্রতিটা প্রয়োজনীয় ফিল্ড পরিস্থিতি থেকে ভরা বা UNKNOWN চিহ্নিত; ভুল রিফান্ড বক্তব্যগুলো সীমাবদ্ধতা ও ব্যর্থতার ধরন হিসেবে আছে; অনুমতি যাচাই-না-হওয়া অনুমান হিসেবে লেখা; পরিস্থিতিতে না-করা অ্যাক্সেসিবিলিটি পরীক্ষা UNKNOWN, "ok" নয়। এখানে ভ্যালিডেটর একটা ইচ্ছাকৃত ফাঁক পায়, আর প্রমাণ-পরীক্ষা অনুমতির অনুমানের নাম করে। দুর্বল উত্তর "গ্রাহকেরা সম্মতি দিয়েছেন" বা "অ্যাক্সেসযোগ্য" লেখে, যা পরিস্থিতি সমর্থন করে না।
সারসংক্ষেপ
- ডেটার উৎস লিখুন, অনুমতিকে কেউ যাচাই না করা পর্যন্ত অনুমান হিসেবে রাখুন, আর প্রতিটা ফল একটা মডেল ও সিস্টেম ভার্সনের সঙ্গে বাঁধুন।
- স্কোর আর হাইলাইট যা, তা-ই বলুন; পরীক্ষা না করা ব্যাখ্যার দাবি করবেন না।
- ভালো প্রকাশ-বিবৃতি ছোট সহজ বাক্যে বলে সিস্টেম কী করে, কোন ডেটা ব্যবহার করে, কে সিদ্ধান্ত নেয়, সীমা কী, আর মানুষের কাছে কীভাবে পৌঁছাবেন।
- ব্যক্তিগত ডেটা ও নিরাপত্তার খুঁটিনাটি অভ্যন্তরীণ রাখুন; প্রভাবিত মানুষের দরকার এমন সীমাবদ্ধতা কখনও লুকাবেন না।
- প্রয়োজনীয় ফিল্ড যাচাই করুন, MISSING ও UNKNOWN রিপোর্ট করুন, প্রমাণহীন দাবি চিহ্নিত করুন, আর কার্ডকে রিলিজ লগ, কনফিগারেশন ও রিভিউয়ের তারিখের সঙ্গে মেলান।
এরপর: মানুষের তদারকির ডিজাইন: অর্থবহ পর্যালোচনা, রাবার-স্ট্যাম্প নয় পাতায় প্রশ্ন উঠবে, কার্ডে যাঁদের নাম আছে তাঁরা সত্যিই একটা AI-সহায়তার সিদ্ধান্ত পর্যালোচনা, ওভাররাইড ও আপিল করতে পারেন কি না।