মূল কনটেন্টে যান
এআই টিউটোরিয়াল

ToolReplay দিয়ে AI এজেন্টের টুল কল অডিট করুন

এই টিউটোরিয়ালে ToolReplay ইনস্টল করা, কঠোর JSONL ট্রান্সক্রিপ্ট ও স্কোপ ফাইল প্রস্তুত করা, replay, scope, seal এবং verify অডিট চালানো, নির্ধারিত রিপোর্ট ব্যাখ্যা করা, CI-তে যাচাই সংযুক্ত করা এবং প্রকল্পটির নিরাপত্তা মডেল ও সীমাবদ্ধতা বোঝানোর ধাপ দেখানো হয়েছে।

ToolReplay দিয়ে AI এজেন্টের টুল কল অডিট করুন

ToolReplay কী করে

ToolReplay আসল টুল চালু না করেই রেকর্ড করা AI-এজেন্ট টুল কল অডিট করে। এটি একটি ট্রান্সক্রিপ্ট পরীক্ষা করে তিনটি সমস্যা শনাক্ত করে: অনির্ধারিত প্রতিক্রিয়া, অপ্রয়োজনীয় কল এবং কোনো এজেন্টের ঘোষিত অনুমতির বাইরে করা কল। এটি একটি ট্রান্সক্রিপ্টকে SHA-256 হ্যাশ চেইনে সিলও করতে পারে এবং সিল করা ফাইলটি সম্পাদনা করা হয়নি কি না তা যাচাই করতে পারে।

ToolReplay লাইভ কল করার পরিবর্তে রেকর্ড করা প্রতিক্রিয়া পুনরায় চালায় বলে অডিট নিরাপদ, পার্শ্বপ্রতিক্রিয়াহীন, পুনরুৎপাদনযোগ্য এবং মূল টুলগুলো অনুপলব্ধ থাকলেও ব্যবহারযোগ্য।

ToolReplay ইনস্টল ও চালান

ToolReplay-এর জন্য Python 3.11 বা পরবর্তী সংস্করণ প্রয়োজন এবং এতে তৃতীয় পক্ষের কোনো রানটাইম নির্ভরতা নেই। এটি নেটওয়ার্কে প্রবেশ করে না।

সোর্স চেকআউট থেকে মডিউলটি সরাসরি চালান:

python -m toolreplay version

আপনি কনসোল স্ক্রিপ্টটিও ইনস্টল করতে পারেন:

pip install .
toolreplay version

উভয় পদ্ধতিতেই ইনস্টল করা সংস্করণ মুদ্রিত হবে, যেমন:

toolreplay 0.6.0

ট্রান্সক্রিপ্টের ফরম্যাট বুঝুন

একটি ট্রান্সক্রিপ্ট হলো JSON Lines ফাইল। প্রতিটি ফাঁকা নয় এমন লাইনে একটি টুল ইনভোকেশন থাকে এবং ঠিক চারটি ফিল্ড থাকতে হবে:

  • index: 0 থেকে শুরু হওয়া এবং ঠিক 1 করে বাড়তে থাকা একটি পূর্ণসংখ্যা।
  • tool: কল করা টুলের নাম।
  • args: টুলের আর্গুমেন্টসমৃদ্ধ একটি অবজেক্ট।
  • response: রেকর্ড করা টুল প্রতিক্রিয়াসমৃদ্ধ একটি অবজেক্ট।

একটি বৈধ রেকর্ড দেখতে এমন:

{"index": 4, "tool": "write_file", "args": {"path": "docs/intro.md", "text": "edited"}, "response": {"ok": true}}

পার্সিং ইচ্ছাকৃতভাবেই কঠোর। অজানা ফিল্ড, অনুপস্থিত ফিল্ড, অবৈধ অবজেক্টের ধরন, পূর্ণসংখ্যা নয় এমন ইনডেক্স এবং ক্রম-বহির্ভূত ইনডেক্স কঠিন ত্রুটি সৃষ্টি করে। Python bool-কে int-এর সাবক্লাস হিসেবে গণ্য করলেও বুলিয়ান মান পূর্ণসংখ্যা হিসেবে গ্রহণ করা হয় না।

ToolReplay ক্যানোনিক্যাল JSON ব্যবহার করে কল তুলনা করে: টুলের নাম ও আর্গুমেন্টগুলো সাজানো কী এবং অপ্রয়োজনীয় ফাঁকা স্থান ছাড়া এনকোড করা হয়। তাই ভিন্ন কী-ক্রমের আর্গুমেন্ট অবজেক্ট একই কল হিসেবে গণ্য হয়। ToolReplay যখন নির্ধারিততা পরীক্ষা করে, তখন প্রতিক্রিয়ার ক্ষেত্রেও একই ক্যানোনিক্যাল এনকোডিং ব্যবহার করা হয়।

রিপ্লে অডিট চালান

replay কমান্ড একটি ট্রান্সক্রিপ্টকে তার নিজস্ব রেকর্ড করা প্রতিক্রিয়ার সঙ্গে যাচাই করে। রিপোজিটরিতে থাকা ত্রুটিপূর্ণ নমুনাটি চালিয়ে দেখুন:

python -m toolreplay replay samples/session-dirty.jsonl

কমান্ডটি একটি নির্ধারিত, লাইনভিত্তিক রিপোর্ট তৈরি করে:

calls: 6
divergence: index 5
findings: 2
index 2: redundant-call: tool 'read_file' repeats the identical call at index 1 with no state change between them
index 5: non-determinism: tool 'search' returned a different response than the identical call at index 3

হেডারটি ওপর থেকে নিচে পড়া হয়। calls: 6 অর্থ ছয়টি বৈধ রেকর্ড পার্স করা হয়েছে। divergence: index 5 সেই প্রথম বিন্দু চিহ্নিত করে যেখানে একটি নির্ধারিত পুনরায় চালনা রেকর্ডের সঙ্গে অমিল হবে। findings: 2 পরবর্তী ফাইন্ডিংগুলোর সংখ্যা নির্দেশ করে।

ফাইন্ডিংগুলো প্রথমে ইনডেক্স এবং তারপর ধরন অনুযায়ী সাজানো হয়, ফলে একই ইনপুটের বারবার অডিটে বাইট-স্তরে অভিন্ন আউটপুট তৈরি হয়।

অনির্ধারিততা

ToolReplay প্রতিটি ক্যানোনিক্যাল কলের প্রথম প্রতিক্রিয়া মনে রাখে। পরে একই কলের রেকর্ড করা প্রতিক্রিয়া ভিন্ন হলে এটি অনির্ধারিততা রিপোর্ট করে। নমুনায় install-এর জন্য search কলটি 3 ও 5 ইনডেক্সে দেখা যায়, কিন্তু প্রতিক্রিয়াগুলো ভিন্ন সংখ্যক ফলাফল জানায়। ইনডেক্স 5 বিচ্যুতির বিন্দু হয়ে যায়।

এজেন্টের জন্য এটি গুরুত্বপূর্ণ, কারণ প্রথম উত্তরের ভিত্তিতে নেওয়া সিদ্ধান্ত দ্বিতীয় উত্তরটি ফেরত এলে বদলে যেতে পারে। এই ফাইন্ডিং নির্দেশ করে যে সেশনটি এমন তথ্যের ওপর নির্ভরশীল যা রেকর্ডের মধ্যে স্থিতিশীল নয়।

অপ্রয়োজনীয় কল

দুটি কলের মাঝখানে রেকর্ড করা এমন কোনো ঘটনা না থাকলেই কেবল পুনরাবৃত্ত কলকে অপ্রয়োজনীয় ধরা হয়, যা অবস্থা পরিবর্তন করতে পারত। ডিফল্ট মিউটেটরগুলো হলো write_file, delete_file, create_file, move_file এবং run_command। অভিন্ন কলের মাঝখানে থাকা যেকোনো ভিন্ন কলকেও সম্ভাব্য অবস্থা পরিবর্তন হিসেবে সতর্কতার সঙ্গে গণ্য করা হয়।

নমুনায় read_file কোনো মধ্যবর্তী অবস্থা পরিবর্তন ছাড়াই 1 ও 2 ইনডেক্সে docs/intro.md পড়ে, তাই ইনডেক্স 2 চিহ্নিত হয়। write_file কলের পরের কোনো পড়াকে অপ্রয়োজনীয় ধরা হবে না।

এজেন্টের অনুমতি পরীক্ষা করুন

এজেন্টের জন্য অনুমতির ঘোষণা থাকলে scope ব্যবহার করুন:

python -m toolreplay scope samples/session-dirty.jsonl samples/scope.json

নমুনাটি তৈরি করে:

calls: 6
findings: 1
index 4: permission-overreach: tool 'write_file' is not in the declared scope for agent 'docs-reader'

রিপ্লে ও স্কোপ নকশাগতভাবে আলাদা কমান্ড। রিপ্লে একটি সেশনকে নিজস্ব রেকর্ডের বিপরীতে মূল্যায়ন করে এবং শুধু ট্রান্সক্রিপ্ট প্রয়োজন। স্কোপ প্রতিটি কলকে একটি পৃথক অনুমতি ফাইলের সঙ্গে তুলনা করে।

একটি স্কোপ ফাইলে এজেন্টের নাম এবং অনুমোদিত টুলগুলোর একটি সুনির্দিষ্ট তালিকাসহ একটি JSON অবজেক্ট থাকে:

{"agent": "docs-reader", "allowed_tools": ["read_file", "list_dir", "search"]}

টুলের নাম হুবহু এবং বড়-ছোট অক্ষর মেনে মিলানো হয়। অনুপস্থিত ফিল্ড, ভুল ধরন বা স্ট্রিং নয় এমন এন্ট্রি প্রত্যাখ্যান করা হয়। স্কোপ যাচাই নামভিত্তিক; এটি আর্গুমেন্ট পরীক্ষা করে না বা অনুমোদিত টুলটি অনুমোদিত কোনো পাথ লক্ষ্য করছে কি না তা নির্ধারণ করে না।

ট্রান্সক্রিপ্ট সিল করুন

seal কমান্ড একটি ট্রান্সক্রিপ্টকে হ্যাশ-চেইনযুক্ত JSONL ফাইলে রূপান্তর করে:

python -m toolreplay seal samples/session-dirty.jsonl > sealed.jsonl

প্রতিটি সিল করা লিঙ্কে মূল রেকর্ডের ক্ষেত্রগুলোর পাশাপাশি prev এবং digest থাকে। প্রথম লিঙ্কে পূর্ববর্তী ডাইজেস্ট হিসেবে ৬৪টি শূন্য হেক্সাডেসিমাল অক্ষর ব্যবহার করা হয়। পরবর্তী প্রতিটি SHA-256 ডাইজেস্টে পূর্ববর্তী ডাইজেস্ট এবং বর্তমান রেকর্ডের ক্যানোনিক্যাল বাইট অন্তর্ভুক্ত থাকে, যার মধ্যে এর ইনডেক্স, টুল, আর্গুমেন্ট এবং প্রতিক্রিয়াও রয়েছে।

প্রতিটি লিঙ্ক আগের লিঙ্কের ওপর নির্ভর করে বলে, আগের কোনো রেকর্ড পরিবর্তন করলে সেই রেকর্ডের ডাইজেস্ট এবং পরবর্তী সব ডাইজেস্ট পরিবর্তিত হয়। ফলে চেইনটি পরিবর্তন দৃশ্যমান করে এবং প্রথম কোন লিঙ্কটি ভেঙেছে তা শনাক্ত করে।

সিল করা ফাইল যাচাই

অক্ষত চেইন যাচাই করতে চালান:

python -m toolreplay verify sealed.jsonl

অপরিবর্তিত ফাইলের ক্ষেত্রে ফলাফল হবে:

chain: intact

রেকর্ড করা প্রতিক্রিয়া বা চেইনে থাকা অন্য কোনো ক্ষেত্র পরিবর্তন করা হলে, যাচাই প্রথম ভাঙা লিঙ্ক এবং প্রত্যাশিত ও পাওয়া ডাইজেস্ট দেখায়:

chain: broken
first broken link: index 3
expected: 34d19a9dfb112baa07afa37994ddcbbebe2973674385f3942340653d08d205bd
found: 40aadf3b8156217f0b5b1d95010b6b79f82a26ccf5e780aed0f5f311f865028a

সিল করা হলে সিল করার পরের পরিবর্তন শনাক্ত করা যায়, যার মধ্যে ক্রম, ইনডেক্স, টুল, আর্গুমেন্ট এবং প্রতিক্রিয়ার পরিবর্তনও রয়েছে। এটি কোনো ডিজিটাল স্বাক্ষর নয়: যে কেউ ফাইল সম্পাদনা করতে পারলে সেটি পুনরায় সিলও করতে পারে। প্রোভেন্যান্স নিশ্চিত করতে ToolReplay-এর বাইরে পরিচালিত কোনো কী দিয়ে চূড়ান্ত ডাইজেস্টে স্বাক্ষর করতে হবে।

CI-তে ToolReplay ব্যবহার

ToolReplay-এর এক্সিট কোডগুলো এটিকে বিল্ড গেটের জন্য উপযোগী করে:

  • 0: অডিট পরিষ্কার অথবা চেইন অক্ষত।
  • 1: কোনো ফাইন্ডিং আছে অথবা চেইন ভাঙা।
  • 2: ব্যবহারে ত্রুটি ঘটেছে, যেমন ভুল ফরম্যাটের ইনপুট বা অনুপস্থিত ফাইল।

CI জবে সরাসরি রিপ্লে এবং স্কোপ পরীক্ষা চালান:

python -m toolreplay replay session.jsonl
python -m toolreplay scope session.jsonl scope.json

এক্সিট কোড ১ বোঝায়, টুলটি অডিট সম্পন্ন করে রিপোর্ট করার মতো কিছু পেয়েছে। এক্সিট কোড ২ বোঝায়, অডিট চালানো সম্ভব হয়নি। তাই অটোমেশন ভুল ফরম্যাটের ইনপুটকে প্রকৃত ফাইন্ডিং থেকে আলাদাভাবে বিবেচনা করতে পারে।

পুনরুৎপাদনযোগ্য তুলনার জন্য প্রতিটি রান সিল করে ফলাফল তুলনা করুন:

python -m toolreplay seal run-a.jsonl > run-a.sealed.jsonl
python -m toolreplay seal run-b.jsonl > run-b.sealed.jsonl
git --no-pager diff --no-index run-a.sealed.jsonl run-b.sealed.jsonl

রিপোর্টে টাইমস্ট্যাম্প বা এলোমেলো মান থাকে না বলে অভিন্ন ইনপুট অভিন্ন আউটপুট তৈরি করে। প্রথম ভিন্ন সিল করা লাইনটি দেখায় কোথায় দুটি রান একমত থাকা বন্ধ করেছে, আর পরিবর্তিত ডাইজেস্ট দেখায় যে পরবর্তী লিঙ্কগুলো ওই পার্থক্যের ওপর নির্ভর করে।

উন্নত ব্যবহার ও ব্যবহারিক সীমাবদ্ধতা

  • ট্রান্সক্রিপ্ট সংযোজন-উপযোগী রাখুন। JSON Lines কোনো প্রযোজককে প্রতি কলে একটি করে রেকর্ড যোগ করতে দেয় এবং ভার্সন কন্ট্রোলে পরিবর্তন পর্যালোচনা সহজ করে।
  • রেকর্ড করা প্রতিক্রিয়া সংরক্ষণ করুন। Replay প্রকৃত টুল কল করে না; ট্রান্সক্রিপ্টে উপস্থাপিত সমস্যাগুলোই কেবল শনাক্ত করতে পারে।
  • রিডানড্যান্সি সতর্কভাবে ব্যাখ্যা করুন। ডিফল্ট মিউটেটর তালিকা নির্দিষ্ট, এবং সেই তালিকায় নেই এমন কাস্টম মিউটেটিং টুলকে রিডানড্যান্সি বিশ্লেষণে শুধু-পাঠযোগ্য হিসেবে বিবেচনা করা হয়।
  • তুলনার সীমানা মনে রাখুন। একই ক্যানোনিক্যাল কল পুনরাবৃত্তি হলে তবেই নন-ডিটারমিনিজম শনাক্ত হয়। অর্থগতভাবে সম্পর্কিত প্রতিক্রিয়াসহ ভিন্ন কলগুলোর সমতুল্যতা যাচাই করা হয় না।
  • কর্তৃত্ব ও লক্ষ্য আলাদা রাখুন। স্কোপ পরীক্ষা শুধু টুলের নাম যাচাই করে। অনুমোদিত কোনো টুল নিষিদ্ধ রিসোর্সে ব্যবহার করা হয়েছে কি না, তা এটি শনাক্ত করতে পারে না।
  • পরিচয়ের জন্য নয়, অখণ্ডতার জন্য সিল ব্যবহার করুন। সিল করার পর কোনো ফাইল পরিবর্তিত হয়েছে কি না, একটি চেইন তা দেখায়; তবে চেইনটি কে তৈরি করেছে তা প্রমাণ করে না।

টেস্ট স্যুট চালান

প্রকল্পটি Python-এর স্ট্যান্ডার্ড-লাইব্রেরির unittest ফ্রেমওয়ার্ক ব্যবহার করে এবং এতে কোনো তৃতীয় পক্ষের টেস্ট নির্ভরতা নেই। রিপোজিটরির মূল ডিরেক্টরি থেকে চালান:

python -m unittest discover -s tests

টেস্টগুলো কঠোর ট্রান্সক্রিপ্ট পার্সিং, ক্যানোনিক্যাল এনকোডিং, হ্যাশ-চেইন তৈরি ও টেম্পার শনাক্তকরণ, রিপ্লে ফাইন্ডিং, স্কোপ প্রয়োগ, CLI আচরণ এবং এক্সিট কোড যাচাই করে।

উপসংহার

ToolReplay AI-এজেন্ট সেশনের জন্য একটি কেন্দ্রীভূত অডিট ওয়ার্কফ্লো সরবরাহ করে। অসামঞ্জস্যপূর্ণ বা অপচয়মূলক আচরণ খুঁজতে replay দিয়ে শুরু করুন, ঘোষিত টুল অনুমতি যাচাই করতে scope ব্যবহার করুন, এবং রেকর্ড করার পরের পরিবর্তন শনাক্ত করতে seal ও verify ব্যবহার করুন। এর কঠোর ইনপুট যাচাই এবং ডিটারমিনিস্টিক রিপোর্টগুলো ডিবাগিং, পর্যালোচনা, ভার্সন কন্ট্রোল ও CI প্রয়োগের জন্য এটিকে ব্যবহারিক করে তোলে।