মূল কনটেন্টে যান
OpenAI

২৩ জানুয়ারি, ২০২৬

ইঞ্জিনিয়ারিং

Codex এজেন্ট লুপ উন্মোচন করা হচ্ছে

মাইকেল বলিন কর্তৃক, টেকনিক্যাল স্টাফের সদস্য

লোডিং…

Codex CLI(একটি নতুন উইন্ডোতে খোলে) আমাদের ক্রস-প্ল্যাটফর্ম লোকাল সফটওয়্যার এজেন্ট, যা আপনার মেশিনে নিরাপদ ও দক্ষভাবে কাজ করে উচ্চ-মানের, নির্ভরযোগ্য সফটওয়্যার পরিবর্তন তৈরি করতে ডিজাইন করা হয়েছে. আমরা বিশ্বমানের সফটওয়্যার এজেন্ট তৈরি করার ব্যাপারে প্রচুর জ্ঞান অর্জন করেছি এপ্রিল মাসে প্রথমবার CLI চালু করার পর থেকে. সেই অন্তর্দৃষ্টিগুলো বিশ্লেষণ করতে, এটি একটি চলমান সিরিজের প্রথম পোস্ট, যেখানে আমরা Codex কিভাবে কাজ করে তার বিভিন্ন দিক এবং কঠোর পরিশ্রমে অর্জিত শিক্ষাগুলো অন্বেষণ করব. (Codex CLI কিভাবে তৈরি করা হয়েছে তার আরও বিস্তারিত ভিউ পেতে, আমাদের ওপেন সোর্স রিপোজিটরি https://github.com/openai/codex(একটি নতুন উইন্ডোতে খোলে) দেখুন. আমাদের ডিজাইন সিদ্ধান্তের অনেক সূক্ষ্ম বিবরণ GitHub ইস্যু এবং পুল রিকোয়েস্টে সংরক্ষিত আছে, যদি আপনি আরও জানতে চান.)

শুরুতে, আমরা এজেন্ট লুপ-এর দিকে মনোযোগ দেব, যা Codex CLI-এর মূল লজিক এবং ব্যবহারকারী, মডেল এবং মডেল যে টুলগুলো ব্যবহার করে সেগুলোর মধ্যে ইন্টারঅ্যাকশন পরিচালনা করার জন্য দায়ী, যাতে অর্থবহ সফটওয়্যার কাজ সম্পন্ন করা যায়. আমরা আশা করি এই পোস্টটি আপনাকে LLM ব্যবহারে আমাদের এজেন্ট (বা “harness”) যে ভূমিকা পালন করে তা সম্পর্কে একটি পরিষ্কার ধারণা দেবে.

আমরা শুরু করার আগে, পরিভাষা সম্পর্কে একটি সংক্ষিপ্ত নোট: OpenAI-এ, “Codex” বলতে Codex CLI, Codex Cloud এবং Codex VS Code এক্সটেনশন সহ সফটওয়্যার এজেন্ট অফারিংগুলোর একটি স্যুটকে বোঝায়. এই পোস্টটি Codex harness এর উপর আলোকপাত করে, যা মূল এজেন্ট লুপ এবং এক্সিকিউশন লজিক প্রদান করে যা সব Codex অভিজ্ঞতার ভিত্তি এবং Codex CLI এর মাধ্যমে প্রকাশিত হয়. সহজভাবে বোঝার সুবিধার্থে, এখানে আমরা "Codex" এবং "Codex CLI" শব্দ দুটিকে একে অপরের পরিবর্তে (একই অর্থে) ব্যবহার করব.

এজেন্ট লুপ

প্রতিটি AI এজেন্টের মূল অংশে রয়েছে “এজেন্ট লুপ” নামে পরিচিত একটি প্রক্রিয়া. এজেন্ট লুপের একটি সরলীকৃত চিত্র নিচে দেওয়া হলো:

“Agent loop” শিরোনামের ডায়াগ্রামটি দেখায় কিভাবে একটি AI সিস্টেম ব্যবহারকারীর অনুরোধ প্রক্রিয়া করে, টুলগুলি কল করে, ফলাফল পর্যবেক্ষণ করে, তার পরিকল্পনা আপডেট করে এবং আউটপুট প্রদান করে. তীরচিহ্নগুলো ব্যবহারকারীর ইনপুট, মডেলের যুক্তি, টুলের কার্যক্রম এবং চূড়ান্ত প্রতিক্রিয়ার মতো ধাপগুলোকে সংযুক্ত করে.

শুরুতে, এজেন্ট ব্যবহারকারীর কাছ থেকে ইনপুট নেয়, যা সে মডেলের জন্য প্রস্তুত করা টেক্সট নির্দেশনার সেটে অন্তর্ভুক্ত করে, যা প্রম্পট নামে পরিচিত.

পরবর্তী ধাপ হলো মডেলকে আমাদের নির্দেশনাবলী পাঠিয়ে সেটির কাছে অনুসন্ধান করা এবং একটি রেসপন্স বা উত্তর তৈরি করতে বলা; এই প্রক্রিয়াটি 'ইনফারেন্স' নামে পরিচিত. ইনফারেন্সের সময়, টেক্সট প্রম্পটটি প্রথমে ইনপুট টোকেন(একটি নতুন উইন্ডোতে খোলে)—এর একটি ক্রমে রূপান্তরিত হয়—যা পূর্ণসংখ্যা হিসেবে মডেলের শব্দভাণ্ডারে সূচক করে. এই টোকেনগুলি মডেলকে নমুনা করতে ব্যবহৃত হয়, যার ফলে আউটপুট টোকেনের একটি নতুন ক্রম তৈরি হয়.

আউটপুট টোকেনগুলো পুনরায় টেক্সটে রূপান্তরিত হয়, যা মডেলের প্রতিক্রিয়া হিসেবে কাজ করে. কারণ টোকেনগুলি ধাপে ধাপে তৈরি হয়, মডেল চলার সময়ই এই অনুবাদটি হতে পারে, এ কারণেই অনেক LLM-ভিত্তিক অ্যাপ্লিকেশন স্ট্রিমিং আউটপুট প্রদর্শন করে. বাস্তবে, ইনফারেন্স সাধারণত এমন একটি API-এর আড়ালে আবদ্ধ থাকে যা টেক্সটের উপর কাজ করে এবং টোকেনাইজেশনের বিস্তারিত বিষয়গুলোকে বিমূর্ত করে.

ইনফারেন্স ধাপের ফলস্বরূপ, মডেল হয় (1) ব্যবহারকারীর মূল ইনপুটের জন্য একটি চূড়ান্ত উত্তর তৈরি করে অথবা (2) একটি টুল কল অনুরোধ করে যা এজেন্টের সম্পাদন করার কথা (যেমন, “ls চালু করুন এবং আউটপুট রিপোর্ট করুন”). (2)-এর ক্ষেত্রে, এজেন্ট টুল কলটি সম্পাদন করে এবং এর আউটপুটটি মূল প্রম্পটে সংযুক্ত করে. এই আউটপুটটি একটি নতুন ইনপুট তৈরি করতে ব্যবহৃত হয়, যা মডেলকে পুনরায় কুয়েরি করতে ব্যবহৃত হয়; এজেন্ট তখন এই নতুন তথ্যটি বিবেচনায় নিয়ে আবার চেষ্টা করতে পারে.

এই প্রক্রিয়াটি পুনরাবৃত্তি হয় যতক্ষণ না মডেল টুল কল বন্ধ করে এবং ব্যবহারকারীর জন্য একটি বার্তা তৈরি করে (OpenAI মডেলগুলিতে যাকে সহকারী বার্তা বলা হয়). অনেক ক্ষেত্রে, এই বার্তাটি সরাসরি ব্যবহারকারীর মূল অনুরোধের উত্তর দেয়, তবে এটি ব্যবহারকারীর জন্য একটি অনুসরণকারী প্রশ্নও হতে পারে.

এজেন্ট যেহেতু এমন টুল কল করতে পারে যা স্থানীয় পরিবেশ পরিবর্তন করে, তার “আউটপুট” কেবলমাত্র সহকারী বার্তায় সীমাবদ্ধ নয়. অনেক সময়, একটি সফটওয়্যার এজেন্টের প্রধান আউটপুট হলো আপনার কম্পিউটারে এটি যে কোড লেখে বা সম্পাদনা করে. তবুও, প্রতিটি টার্ন সবসময় একটি অ্যাসিস্ট্যান্ট মেসেজ দিয়ে শেষ হয়—যেমন “আমি আপনার চাওয়া architecture.md যোগ করেছি”—যা এজেন্ট লুপে একটি সমাপ্তি অবস্থা নির্দেশ করে. এজেন্টের দৃষ্টিকোণ থেকে, তার কাজ সম্পন্ন হয়েছে এবং নিয়ন্ত্রণ ব্যবহারকারীর কাছে ফিরে আসে.

চিত্রে দেখানো ব্যবহারকারীর ইনপুট থেকে এজেন্টের উত্তরের এই যাত্রাটিকে কথোপকথনের একটি 'টার্ন' (একবার কথোপকথন সম্পন্ন হওয়া) বলা হয় (যা Codex-এ একটি 'থ্রেড'হিসেবে পরিচিত). যদিও এই কথোপকথনের পালা মডেল ইনফারেন্স এবং টুল কল এর মধ্যে অনেকবার পুনরাবৃত্তি হতে পারে. প্রতিবার আপনি কোনো বিদ্যমান কথোপকথনে একটি নতুন বার্তা পাঠান, নতুন পালার জন্য প্রম্পটের অংশ হিসেবে কথোপকথনের ইতিহাস অন্তর্ভুক্ত করা হয়, যেখানে আগের পালাগুলোর বার্তা এবং টুল কল অন্তর্ভুক্ত থাকে:

“Multi-turn agent loop” শিরোনামের ডায়াগ্রামটি দেখায় কিভাবে একটি AI এজেন্ট বারবার ব্যবহারকারীর ইনপুট গ্রহণ করে, কর্মপরিকল্পনা তৈরি করে, টুলের সাথে পরামর্শ করে, অবস্থা আপডেট করে এবং ফলাফল প্রদান করে. এজেন্টের চিন্তাভাবনার প্রক্রিয়া প্রদর্শনকারী লেবেলযুক্ত ধাপ, তীরচিহ্ন এবং উদাহরণ টুল আউটপুট অন্তর্ভুক্ত.

এর মানে হলো কথোপকথন যত বাড়ে, মডেলকে স্যাম্পল করতে ব্যবহৃত প্রম্পটের দৈর্ঘ্যও তত বাড়ে. এই দৈর্ঘ্যটি গুরুত্বপূর্ণ কারণ প্রতিটি মডেলের একটি কনটেক্সট উইন্ডো থাকে, যা একবারের ইনফারেন্স কলে এটি সর্বাধিক কতগুলি টোকেন ব্যবহার করতে পারে তা নির্দেশ করে. দ্রষ্টব্য, এই উইন্ডোতে ইনপুট এবং আউটপুট টোকেন উভয়ই অন্তর্ভুক্ত রয়েছে. আপনি যেমন কল্পনা করতে পারেন, একটি এজেন্ট একবারে শত শত টুল কল করার সিদ্ধান্ত নিতে পারে, যার ফলে কনটেক্সট উইন্ডো সম্ভাব্যভাবে নিঃশেষ হয়ে যেতে পারে. এই কারণে, কনটেক্সট উইন্ডো ম্যানেজমেন্ট এজেন্টের অনেক দায়িত্বের একটি. এখন, আসুন দেখি Codex কিভাবে এজেন্ট লুপ পরিচালনা করে.

মডেল অনুমান

Codex CLI মডেল ইনফারেন্স চালানোর জন্য Responses API(একটি নতুন উইন্ডোতে খোলে) -এ HTTP অনুরোধ পাঠায়. আমরা দেখব কিভাবে Codex-এর মাধ্যমে তথ্য প্রবাহিত হয়, যা এজেন্ট লুপ চালানোর জন্য Responses API ব্যবহার করে.

Codex CLI যে Responses API এন্ডপয়েন্ট ব্যবহার করে তা কনফিগারযোগ্য(একটি নতুন উইন্ডোতে খোলে), তাই এটি যেকোনো এন্ডপয়েন্টের সাথে ব্যবহার করা যেতে পারে যা Responses API বাস্তবায়ন করে(একটি নতুন উইন্ডোতে খোলে):

চলুন, একটি কথোপকথনে প্রথম ইন্সফারেন্স কলের জন্য Codex কিভাবে প্রম্পট তৈরি করে তা অন্বেষণ করি.

প্রাথমিক প্রম্পট তৈরি করা হচ্ছে

একজন শেষ ব্যবহারকারী হিসেবে, আপনি যখন Responses API-তে অনুসন্ধান করেন, তখন মডেল নমুনা করতে ব্যবহৃত প্রম্পটটি হুবহু নির্দিষ্ট করেন না. পরিবর্তে, আপনি আপনার কুয়েরির অংশ হিসেবে বিভিন্ন ইনপুট টাইপ নির্দিষ্ট করেন, এবং Responses API সার্ভার সিদ্ধান্ত নেয় কিভাবে এই তথ্যকে এমন একটি প্রম্পটে গঠন করা হবে যা মডেলটি গ্রহণ করার জন্য ডিজাইন করা হয়েছে. আপনি প্রম্পটটিকে একটি “আইটেমের তালিকা” হিসেবে ভাবতে পারেন; এই অংশটি ব্যাখ্যা করবে কিভাবে আপনার কুয়েরি সেই তালিকায় রূপান্তরিত হয়.

প্রাথমিক প্রম্পটে, তালিকার প্রতিটি আইটেম একটি ভূমিকার সাথে যুক্ত থাকে. role নির্দেশ করে সংশ্লিষ্ট কন্টেন্টের কতটা গুরুত্ব থাকা উচিত এবং এটি নিম্নলিখিত মানগুলোর একটি (অগ্রাধিকারের ক্রমানুসারে): system, developer, user, assistant.

Responses API(একটি নতুন উইন্ডোতে খোলে) অনেক প্যারামিটার সহ একটি JSON পে-লোড গ্রহণ করে. আমরা এই তিনটির উপর মনোযোগ দেবো:

Codex-এ, instructions ফিল্ডটি model_instructions_file(একটি নতুন উইন্ডোতে খোলে) থেকে ~/.codex/config.toml-এ নির্দিষ্ট করা থাকলে পড়া হয়; অন্যথায়, the base_instructions যা একটি মডেলের সাথে যুক্ত(একটি নতুন উইন্ডোতে খোলে) ব্যবহার করা হয়. মডেল-নির্দিষ্ট নির্দেশাবলী Codex repo-তে সংরক্ষিত থাকে এবং CLI-তে অন্তর্ভুক্ত করা হয় (যেমন, gpt-5.2-codex_prompt.md(একটি নতুন উইন্ডোতে খোলে)).

tools ফিল্ডটি টুল ডেফিনিশনের একটি তালিকা যা Responses API দ্বারা সংজ্ঞায়িত একটি স্কিমা সাথে সামঞ্জস্যপূর্ণ. Codex-এর জন্য, এর মধ্যে রয়েছে Codex CLI দ্বারা সরবরাহ করা টুল, Responses API দ্বারা সরবরাহ করা টুল যা Codex-এর জন্য উপলব্ধ হওয়া উচিত এবং ব্যবহারকারী দ্বারা সরবরাহ করা টুল, সাধারণত MCP সার্ভারগুলির মাধ্যমে:

JavaScript

1
[
2
// Codex's default shell tool for spawning new processes locally.
3
{
4
"type": "function",
5
"name": "shell",
6
"description": "Runs a shell command and returns its output...",
7
"strict": false,
8
"parameters": {
9
"type": "object",
10
"properties": {
11
"command": {"type": "array", "description": "The command to execute", ...},
12
"workdir": {"description": "The working directory...", ...},
13
"timeout_ms": {"description": "The timeout for the command...", ...},
14
...
15
},
16
"required": ["command"],
17
}
18
}
19

20
// Codex's built-in plan tool.
21
{
22
"type": "function",
23
"name": "update_plan",
24
"description": "Updates the task plan...",
25
"strict": false,
26
"parameters": {
27
"type": "object",
28
"properties": {"plan":..., "explanation":...},
29
"required": ["plan"]
30
}
31
},
32

33
// Web search tool provided by the Responses API.
34
{
35
"type": "web_search",
36
"external_web_access": false
37
},
38

39
// MCP server for getting weather as configured in the
40
// user's ~/.codex/config.toml.
41
{
42
"type": "function",
43
"name": "mcp__weather__get-forecast",
44
"description": "Get weather alerts for a US state",
45
"strict": false,
46
"parameters": {
47
"type": "object",
48
"properties": {"latitude": {...}, "longitude": {...}},
49
"required": ["latitude", "longitude"]
50
}
51
}
52
]

অবশেষে, JSON পে-লোডের input ফিল্ডটি আইটেমের একটি তালিকা. Codex নিম্নলিখিত আইটেমগুলো যোগ করে(একটি নতুন উইন্ডোতে খোলে) input -এ ইউজার মেসেজ যোগ করার আগে:

1. role=developer সহ একটি বার্তা যা সেই স্যান্ডবক্সের বর্ণনা দেয় যা শুধুমাত্র Codex প্রদত্ত shell টুলের জন্য প্রযোজ্য এবং tools সেকশনে সংজ্ঞায়িত. অর্থাৎ, অন্যান্য টুলগুলো—যেমন MCP সার্ভার থেকে পাওয়া টুলগুলো—Codex দ্বারা স্যান্ডবক্সড করা থাকে না এবং সেগুলো তাদের নিজস্ব সুরক্ষা নীতিমালা বা গার্ডরেল কার্যকর করার জন্য নিজেরাই দায়ী থাকে.

বার্তাটি একটি টেমপ্লেট থেকে তৈরি করা হয়, যেখানে মূল কনটেন্টের অংশগুলো Codex CLI-এর সঙ্গে বান্ডেল করা Markdown স্নিপেট থেকে আসে, যেমন workspace_write.md(একটি নতুন উইন্ডোতে খোলে) এবং on_request.md(একটি নতুন উইন্ডোতে খোলে):

প্লেইন টেক্সট

1
<permissions instructions>
2
- description of the sandbox explaining file permissions and network access
3
- instructions for when to ask the user for permissions to run a shell command
4
- list of folders writable by Codex, if any
5
</permissions instructions>

2. (ঐচ্ছিক) role=developer সহ একটি বার্তা, যার বিষয়বস্তু ব্যবহারকারীর config.toml ফাইল থেকে পড়া developer_instructions মান.

3. (ঐচ্ছিক) role=user সহ একটি বার্তা, যার বিষয়বস্তু হলো “ব্যবহারকারীর নির্দেশাবলী,” যা কোনো একক ফাইল থেকে নেওয়া হয়নি, বরং বিভিন্ন উৎস থেকে সংগ্রহ করা হয়েছে(একটি নতুন উইন্ডোতে খোলে). সাধারণভাবে, আরও নির্দিষ্ট নির্দেশনা পরে প্রদর্শিত হয়:

4. একটি বার্তা role=user সহ, যা এজেন্ট বর্তমানে যে স্থানীয় পরিবেশে কাজ করছে তা বর্ণনা করে. এটি বর্তমান কার্যকরী ডিরেক্টরি এবং ব্যবহারকারীর শেল নির্ধারণ করে(একটি নতুন উইন্ডোতে খোলে):

প্লেইন টেক্সট

1
<environment_context>
2
<cwd>/Users/mbolin/code/codex5</cwd>
3
<shell>zsh</shell>
4
</environment_context>

Codex উপরের সব গণনা সম্পন্ন করে input ইনিশিয়ালাইজ করার পর, এটি কথোপকথন শুরু করতে ব্যবহারকারীর বার্তা যোগ করে.

পূর্ববর্তী উদাহরণগুলো প্রতিটি বার্তার বিষয়বস্তুর উপর ফোকাস করেছিল, তবে মনে রাখবেন যে input এর প্রতিটি উপাদান একটি JSON অবজেক্ট, যেখানে type, role(একটি নতুন উইন্ডোতে খোলে), এবং content নিম্নরূপ থাকে:

JSON

1
{
2
"type": "message",
3
"role": "user",
4
"content": [
5
{
6
"type": "input_text",
7
"text": "Add an architecture diagram to the README.md"
8
}
9
]
10
}

Codex যখন Responses API-তে পাঠানোর জন্য সম্পূর্ণ JSON payload তৈরি করে, তখন এটি ~/.codex/config.toml ফাইলে Responses API এন্ডপয়েন্টের কনফিগারেশনের উপর নির্ভর করে Authorization হেডার সহ HTTP POST অনুরোধ করে (যদি অতিরিক্ত HTTP হেডার এবং query প্যারামিটার নির্দিষ্ট করা থাকে তবে সেগুলোও যোগ করা হয়).

যখন একটি OpenAI Responses API সার্ভার অনুরোধ গ্রহণ করে, তখন এটি JSON থেকে মডেলের জন্য প্রম্পট নির্ধারণ করে নিম্নরূপ (যদিও, Responses API-এর একটি কাস্টম ইমপ্লিমেন্টেশন ভিন্নভাবে কাজ করতে পারে):

AI এজেন্ট লুপের একটি ধাপের স্ন্যাপশট ডায়াগ্রাম দেখানো হয়েছে. একটি ব্যবহারকারীর অনুরোধ মডেলে প্রবেশ করে, যা একটি চিন্তা, একটি টুলের নামসহ একটি কার্যকলাপ এবং একটি টুল ইনপুট তৈরি করে. ডায়াগ্রামটি টুলটি কল করার আগে এই মধ্যবর্তী যুক্তিপ্রয়োগের ধাপটি হাইলাইট করে.

আপনি যেমন দেখতে পাচ্ছেন, প্রম্পটের প্রথম তিনটি আইটেমের ক্রম সার্ভার দ্বারা নির্ধারিত হয়, ক্লায়েন্ট দ্বারা নয়. তবে,ঐ তিনটি আইটেমের মধ্যে কেবল system message এর বিষয়বস্তু সার্ভার দ্বারা নিয়ন্ত্রিত হয়, কারণ tools এবং instructions ক্লায়েন্ট দ্বারা নির্ধারিত হয়. এগুলোর পরে প্রম্পট সম্পূর্ণ করতে JSON পেলোড থেকে input দেওয়া হয়.

এখন যেহেতু আমাদের প্রম্পট প্রস্তুত, আমরা মডেল থেকে নমুনা নিতে প্রস্তুত.

প্রথম টার্ন বা প্রথম ধাপ

এই HTTP অনুরোধটি রেসপন্সেস API-তে Codex-এ একটি কথোপকথনের প্রথম “টার্ন” শুরু করে. সার্ভারটি একটি Server-Sent Events (SSE(একটি নতুন উইন্ডোতে খোলে)) স্ট্রিমের মাধ্যমে প্রতিক্রিয়া জানায়. প্রতিটি ইভেন্টের data একটি JSON পেলোড, যার "type" "response" দিয়ে শুরু হয়, যা এরকম কিছু হতে পারে (ইভেন্টগুলোর সম্পূর্ণ তালিকা আমাদের API ডকুমেন্টেশন(একটি নতুন উইন্ডোতে খোলে)-এ পাওয়া যাবে):

প্লেইন টেক্সট

1
data: {"type":"response.reasoning_summary_text.delta","delta":"ah ", ...}
2
data: {"type":"response.reasoning_summary_text.delta","delta":"ha!", ...}
3
data: {"type":"response.reasoning_summary_text.done", "item_id":...}
4
data: {"type":"response.output_item.added", "item":{...}}
5
data: {"type":"response.output_text.delta", "delta":"forty-", ...}
6
data: {"type":"response.output_text.delta", "delta":"two!", ...}
7
data: {"type":"response.completed","response":{...}}

Codex ইভেন্টগুলির প্রবাহ গ্রহণ করে(একটি নতুন উইন্ডোতে খোলে) এবং সেগুলিকে অভ্যন্তরীণ ইভেন্ট অবজেক্ট হিসেবে পুনঃপ্রকাশ করে, যা ক্লায়েন্ট দ্বারা ব্যবহার করা যেতে পারে. response.output_text.delta এর মতো ইভেন্টগুলি UI-তে স্ট্রিমিং সমর্থন করতে ব্যবহৃত হয়, যেখানে response.output_item.added এর মতো অন্যান্য ইভেন্টগুলি অবজেক্টে রূপান্তরিত হয় এবং পরবর্তী Responses API কলের জন্য input-এ যোগ করা হয়.

মনে করুন প্রথম অনুরোধে Responses API-তে দুটি response.output_item.done ইভেন্ট অন্তর্ভুক্ত রয়েছে: একটি type=reasoning এবং একটি type=function_call. মডেলকে টুল কলের প্রতিক্রিয়া দিয়ে আবার কুয়েরি করার সময়, এই ইভেন্টগুলোকে JSON-এর input ফিল্ডে উপস্থাপন করতে হবে: 

JavaScript

1
[
2
/* ... original 5 items from the input array ... */
3
{
4
"type": "reasoning",
5
"summary": [
6
"type": "summary_text",
7
"text": "**Adding an architecture diagram for README.md**\n\nI need to..."
8
],
9
"encrypted_content": "gAAAAABpaDWNMxMeLw..."
10
},
11
{
12
"type": "function_call",
13
"name": "shell",
14
"arguments": "{\"command\":\"cat README.md\",\"workdir\":\"/Users/mbolin/code/codex5\"}",
15
"call_id": "call_8675309..."
16
},
17
{
18
"type": "function_call_output",
19
"call_id": "call_8675309...",
20
"output": "<p align=\"center\"><code>npm i -g @openai/codex</code>..."
21
}
22
]

পরবর্তী প্রশ্নের অংশ হিসেবে মডেলকে নমুনা করতে ব্যবহৃত প্রম্পটটি এমন দেখাবে:

“Snapshot 2” লেবেলযুক্ত ডায়াগ্রাম, যা একটি টুল কলের পর একটি AI এজেন্ট প্রদর্শন করছে. মডেলটি একটি টুল পর্যবেক্ষণ গ্রহণ করে এবং একটি নতুন চিন্তা ও ক্রিয়া তৈরি করে. তীরচিহ্ন ইনপুট, পর্যবেক্ষণ এবং আউটপুটকে সংযুক্ত করে দেখায় কিভাবে এজেন্ট তার যুক্তি-প্রক্রিয়ার লুপ পুনরাবৃত্তি করে.

বিশেষ করে লক্ষ্য করুন কিভাবে পুরোনো প্রম্পট নতুন প্রম্পটের একটি সঠিক প্রিফিক্স. এটি ইচ্ছাকৃত, কারণ এটি পরবর্তী অনুরোধগুলোকে অনেক বেশি কার্যকর করে তোলে, কারণ এটি আমাদের প্রম্পট ক্যাশিং এর সুবিধা নিতে দেয় (যা আমরা পারফরম্যান্সের পরবর্তী অংশে আলোচনা করব).

এজেন্ট লুপের প্রথম ডায়াগ্রামের দিকে ফিরে তাকালে, আমরা দেখতে পাই যে অনুমান এবং টুল কলিং-এর মধ্যে অনেকবার পুনরাবৃত্তি হতে পারে. প্রম্পটটি বাড়তে পারে যতক্ষণ না আমরা শেষ পর্যন্ত একটি সহকারী বার্তা পাই, যা পালার সমাপ্তি নির্দেশ করে:

প্লেইন টেক্সট

1
data: {"type":"response.output_text.done","text": "I added a diagram to explain...", ...}
2
data: {"type":"response.completed","response":{...}}

Codex CLI-তে, আমরা ব্যবহারকারীর কাছে অ্যাসিস্ট্যান্টের বার্তা প্রদর্শন করি এবং কম্পোজারের দিকে মনোযোগ দিই, যাতে ব্যবহারকারী বুঝতে পারেন যে কথোপকথন চালিয়ে যাওয়ার জন্য এখন তাদের পালা. যদি ব্যবহারকারী প্রতিক্রিয়া জানায়, তবে আগের টার্নের অ্যাসিস্ট্যান্ট মেসেজ এবং ব্যবহারকারীর নতুন মেসেজ—দুটিই নতুন টার্ন শুরু করতে Responses API অনুরোধের input -এ সংযুক্ত করতে হবে:

JavaScript

1
[
2
/* ... all items from the last Responses API request ... */
3
{
4
"type": "message",
5
"role": "assistant",
6
"content": [
7
{
8
"type": "output_text",
9
"text": "I added a diagram to explain the client/server architecture."
10
}
11
]
12
},
13
{
14
"type": "message",
15
"role": "user",
16
"content": [
17
{
18
"type": "input_text",
19
"text": "That's not bad, but the diagram is missing the bike shed."
20
}
21
]
22
}
23
]

আবারও, যেহেতু আমরা একটি কথোপকথন চালিয়ে যাচ্ছি, আমরা Responses API-তে যে input পাঠাই তার দৈর্ঘ্য ক্রমাগত বাড়ছে:

“Snapshot 3” লেবেলযুক্ত ডায়াগ্রাম যা একটি AI এজেন্ট লুপের শেষ পর্যায় দেখাচ্ছে. টুলের ফলাফল পাওয়ার পর, মডেল একটি উপসংহারমূলক চিন্তা তৈরি করে এবং ব্যবহারকারীর কাছে একটি চূড়ান্ত উত্তর ফেরত দেয়. তীরগুলো টুলের আউটপুট থেকে সম্পূর্ণ প্রতিক্রিয়ায় রূপান্তরটি চিত্রিত করে.

চলুন, এই ক্রমবর্ধমান প্রম্পটটি পারফরম্যান্সের জন্য কী অর্থ বহন করে তা পরীক্ষা করি.

পারফরম্যান্স বিবেচনা

আপনি হয়তো নিজেকে প্রশ্ন করছেন, "দাঁড়ান, পুরো কথোপকথন চলাকালীন 'Responses API'-তে পাঠানো JSON-এর পরিমাণের দিক থেকে এজেন্ট লুপটি কি 'কোয়াড্রেটিক'নয়?" আর আপনি ঠিকই বলতে. যদিও Responses API এই সমস্যাটি কমানোর জন্য একটি ঐচ্ছিক previous_response_id(একটি নতুন উইন্ডোতে খোলে) প্যারামিটার সমর্থন করে, Codex এটি আজ ব্যবহার করে না, মূলত অনুরোধগুলোকে সম্পূর্ণ স্টেটলেস রাখতে এবং জিরো ডেটা রিটেনশন (ZDR) কনফিগারেশন সমর্থন করতে.

previous_response_id এড়িয়ে চলা রেসপন্সেস API-এর প্রদানকারীর জন্য বিষয়গুলো সহজ করে তোলে, কারণ এটি নিশ্চিত করে যে প্রতিটি অনুরোধ স্টেটলেস থাকে. এটি জিরো ডেটা রিটেনশন (ZDR)(একটি নতুন উইন্ডোতে খোলে)-এ অপ্ট-ইন করা গ্রাহকদের সহায়তা করাও সহজ করে তোলে, কারণ previous_response_id সমর্থনের জন্য প্রয়োজনীয় ডেটা সংরক্ষণ করা ZDR-এর সাথে সাংঘর্ষিক হবে. মনে রাখবেন, ZDR গ্রাহকরা আগের টার্নগুলোর মালিকানাধীন রিজনিং মেসেজ থেকে উপকৃত হওয়ার ক্ষমতা হারায় না, কারণ সংশ্লিষ্ট encrypted_content সার্ভারে ডিক্রিপ্ট করা যায়. (OpenAI একটি ZDR গ্রাহকের ডিক্রিপশন কী সংরক্ষণ করে, কিন্তু তাদের ডেটা সংরক্ষণ করে না.) ZDR সাপোর্ট করার জন্য Codex-এ সংশ্লিষ্ট পরিবর্তনগুলি দেখতে PRs #642(একটি নতুন উইন্ডোতে খোলে) এবং #1641(একটি নতুন উইন্ডোতে খোলে) দেখুন.

সাধারণভাবে, মডেল স্যাম্পলিংয়ের খরচ নেটওয়ার্ক ট্র্যাফিকের খরচকে ছাপিয়ে যায়, যার ফলে স্যাম্পলিং আমাদের দক্ষতা বৃদ্ধির প্রচেষ্টার প্রধান লক্ষ্য হয়ে ওঠে. এই কারণেই প্রম্পট ক্যাশিং এত গুরুত্বপূর্ণ, কারণ এটি আমাদের আগের ইনফারেন্স কল থেকে কম্পিউটেশন পুনরায় ব্যবহার করতে দেয়. যখন আমরা ক্যাশ হিট পাই, মডেল স্যাম্পলিং কোয়াড্রাটিকের পরিবর্তে লিনিয়ার হয়. আমাদের প্রম্পট ক্যাশিং (একটি নতুন উইন্ডোতে খোলে)ডকুমেন্টেশন এই বিষয়ে আরও বিস্তারিতভাবে ব্যাখ্যা করে:

ক্যাশ হিট শুধুমাত্র তখনই সম্ভব যখন একটি প্রম্পটের মধ্যে সুনির্দিষ্ট প্রিফিক্স মিলে যায়. ক্যাশিংয়ের সুবিধা পেতে, আপনার প্রম্পটের শুরুতে নির্দেশনা ও উদাহরণের মতো স্থির বিষয়বস্তু রাখুন এবং শেষে পরিবর্তনশীল বিষয়বস্তু, যেমন ব্যবহারকারী-নির্দিষ্ট তথ্য, রাখুন. এটি ছবি এবং সরঞ্জামের ক্ষেত্রেও প্রযোজ্য, যা অনুরোধগুলোর মধ্যে অবশ্যই অভিন্ন হতে হবে.

এটা মাথায় রেখে, আসুন বিবেচনা করি Codex-এ কোন ধরনের অপারেশন “cache miss” ঘটাতে পারে:

  • কথোপকথনের মাঝখানে মডেলের জন্য উপলব্ধ tools পরিবর্তন করা.
  • Responses API অনুরোধের লক্ষ্যবস্তু মডেল পরিবর্তন করা (প্রকৃতপক্ষে, এটি মূল প্রম্পটের তৃতীয় আইটেমটি পরিবর্তন করে, যেহেতু এতে মডেল-নির্দিষ্ট নির্দেশনা অন্তর্ভুক্ত থাকে).
  • স্যান্ডবক্স কনফিগারেশন, অনুমোদন মোড অথবা বর্তমান ওয়ার্কিং ডিরেক্টরি পরিবর্তন করা.

Codex CLI-এ নতুন ফিচার প্রবর্তনের সময় Codex টিমকে সতর্ক থাকতে হবে, কারণ এগুলি প্রম্পট ক্যাশিংকে ক্ষতিগ্রস্ত করতে পারে. উদাহরণস্বরূপ, MCP টুলগুলোর জন্য আমাদের প্রাথমিক সহায়তায় একটি বাগ ছিল যেখানে আমরা টুলগুলোকে সঙ্গতিপূর্ণ ক্রমে তালিকাভুক্ত করতে ব্যর্থ হয়েছিলাম(একটি নতুন উইন্ডোতে খোলে), যার ফলে ক্যাশ মিস হচ্ছিল. মনে রাখবেন MCP টুলগুলো বিশেষভাবে জটিল হতে পারে, কারণ MCP সার্ভারগুলো notifications/tools/list_changed(একটি নতুন উইন্ডোতে খোলে) নোটিফিকেশনের মাধ্যমে তাৎক্ষণিকভাবে তারা যে টুলগুলোর তালিকা প্রদান করে তা পরিবর্তন করতে পারে. দীর্ঘ কথোপকথনের মাঝপথে এই নোটিফিকেশন বা বিজ্ঞপ্তিটি মেনে চলা একটি ব্যয়বহুল 'ক্যাশ মিস'-এর কারণ হতে পারে.

যখন সম্ভব, আমরা কথোপকথনের মাঝপথে ঘটে যাওয়া কনফিগারেশন পরিবর্তনগুলোকে আগের কোনো বার্তা পরিবর্তন না করে পরিবর্তনটি প্রতিফলিত করতে input-এ একটি নতুন বার্তা যোগ করে পরিচালনা করি:

পারফরম্যান্সের জন্য ক্যাশ হিট নিশ্চিত করতে আমরা সর্বোচ্চ চেষ্টা করি. আমাদের আরেকটি গুরুত্বপূর্ণ সম্পদ পরিচালনা করতে হবে: কনটেক্সট উইন্ডো.

কনটেক্সট উইন্ডো ফুরিয়ে যাওয়া এড়ানোর জন্য আমাদের সাধারণ কৌশল হলো টোকেনের সংখ্যা নির্দিষ্ট সীমা অতিক্রম করলে কথোপকথনটি সংক্ষিপ্ত করা. বিশেষভাবে, আমরা input-কে কথোপকথনের প্রতিনিধিত্বকারী আইটেমগুলোর একটি নতুন, ছোট তালিকা দিয়ে প্রতিস্থাপন করি, যা এজেন্টকে এখন পর্যন্ত কী ঘটেছে তা বুঝে এগিয়ে যেতে সক্ষম করে. কম্প্যাকশনের একটি প্রাথমিক বাস্তবায়ন(একটি নতুন উইন্ডোতে খোলে) ব্যবহারকারীকে ম্যানুয়ালি /compact কমান্ড চালাতে বলত, যা বিদ্যমান কথোপকথন এবং সারসংক্ষেপ(একটি নতুন উইন্ডোতে খোলে) এর জন্য কাস্টম নির্দেশনা ব্যবহার করে Responses API-কে অনুসন্ধান করত. Codex সারাংশসহ প্রাপ্ত অ্যাসিস্ট্যান্ট বার্তাটি নতুন ইনপুট(একটি নতুন উইন্ডোতে খোলে) হিসেবে পরবর্তী কথোপকথনের পালাগুলোর জন্য ব্যবহার করেছে.

তখন থেকে, Responses API একটি বিশেষ /responses/compact এন্ডপয়েন্ট(একটি নতুন উইন্ডোতে খোলে) সমর্থন করার জন্য বিকশিত হয়েছে, যা আরও দক্ষভাবে কম্প্যাকশন সম্পাদন করে. এটি একটি আইটেমের তালিকা(একটি নতুন উইন্ডোতে খোলে) ফেরত দেয়, যা আগের input এর পরিবর্তে ব্যবহার করে কথোপকথন চালিয়ে যাওয়া যায় এবং কনটেক্সট উইন্ডো খালি করা যায়. এই তালিকায় একটি বিশেষ type=compaction আইটেম অন্তর্ভুক্ত রয়েছে, যার মধ্যে একটি অস্বচ্ছ encrypted_content আইটেম রয়েছে যা মডেলের মূল কথোপকথনের সুপ্ত বোঝাপড়া সংরক্ষণ করে. এখন, auto_compact_limit(একটি নতুন উইন্ডোতে খোলে) অতিক্রম হলে Codex কথোপকথন কম্প্যাক্ট করতে স্বয়ংক্রিয়ভাবে এই এন্ডপয়েন্ট ব্যবহার করে.

পরবর্তী পদক্ষেপ আসছে

আমরা Codex এজেন্ট লুপের সাথে পরিচয় করিয়েছি এবং দেখিয়েছি কিভাবে Codex একটি মডেলকে কুয়েরি করার সময় তার প্রেক্ষাপট তৈরি ও পরিচালনা করে. পথে, আমরা ব্যবহারিক বিবেচনা এবং সেরা অনুশীলনগুলি তুলে ধরেছি, যা Responses API-এর উপর একটি এজেন্ট লুপ তৈরি করতে যে কেউ প্রয়োগ করতে পারে.

যদিও এজেন্ট লুপ Codex-এর ভিত্তি প্রদান করে, এটি কেবল শুরু. আসন্ন পোস্টগুলোতে, আমরা CLI-এর আর্কিটেকচারে গভীরভাবে প্রবেশ করব, টুল ব্যবহারের ইমপ্লিমেন্টেশন অন্বেষণ করব এবং Codex-এর স্যান্ডবক্সিং মডেলটি আরও ঘনিষ্ঠভাবে পর্যবেক্ষণ করব.

লেখক

Michael Bolin

প্রাপ্তী স্বীকার

Codex CLI তৈরি করা পুরো দলকে বিশেষ ধন্যবাদ.