मुख्य मजकूराकडे जा
OpenAI

२३ जानेवारी, २०२६

इंजिनिअरिंग

Codex एजंट लूप उलगडणे

मायकेल बोलिन, तांत्रिक कर्मचारी सदस्य

लोड होत आहे...

Codex CLI(नवीन विंडोमध्ये उघडेल) हा आमचा क्रॉस-प्लॅटफॉर्म स्थानिक सॉफ्टवेअर एजंट आहे, जो तुमच्या मशीनवर सुरक्षित आणि कार्यक्षमपणे कार्य करताना उच्च-गुणवत्तेचे, विश्वासार्ह सॉफ्टवेअर बदल तयार करण्यासाठी डिझाइन केलेला आहे. आम्ही एप्रिलमध्ये CLI प्रथम लॉन्च केल्यापासून जागतिक दर्जाचा सॉफ्टवेअर एजंट कसा तयार करायचा याबद्दल खूप काही शिकलो आहोत. त्या अंतर्दृष्टी उलगडण्यासाठी, Codex कसे कार्य करते याच्या विविध पैलूंचा तसेच कठोर परिश्रमातून मिळालेल्या धड्यांचा तुम्ही अभ्यास करू अशा चालू मालिकेतील हा पहिला लेख आहे. (Codex CLI कसा तयार केला आहे याबद्दल अधिक तपशीलवार माहिती मिळवण्यासाठी, आमच्या ओपन सोर्स रिपॉझिटरीला https://github.com/openai/codex(नवीन विंडोमध्ये उघडेल) येथे भेट द्या. आमच्या डिझाइन निर्णयांमधील अनेक सूक्ष्म तपशील GitHub issues आणि पुल रिक्वेस्टमध्ये नोंदवलेले आहेत, जर तुम्हाला अधिक जाणून घ्यायचे असेल तर.)

सुरुवात करण्यासाठी, तुम्ही एजंट लूप वर लक्ष केंद्रित करू, जो Codex CLI मधील मुख्य लॉजिक आहे जो वापरकर्ता, मॉडेल, आणि मॉडेल ज्या साधनांना अर्थपूर्ण सॉफ्टवेअर काम करण्यासाठी कॉल करतो त्यांच्यातील परस्परसंवादाचे ऑर्केस्ट्रेशन करण्यासाठी जबाबदार आहे. आम्हाला आशा आहे की ही पोस्ट LLM चा उपयोग करण्यात आमचा एजंट (किंवा “हार्नेस”) कोणती भूमिका बजावतो याबद्दल तुम्हाला चांगली कल्पना देईल.

आम्ही सुरुवात करण्यापूर्वी, संज्ञांबद्दल एक झटपट टीप: OpenAI मध्ये, “Codex” हा Codex CLI, Codex Cloud, आणि Codex VS Code extension यांसह सॉफ्टवेअर एजंट ऑफरिंग्जचा एक संच आहे. ही पोस्ट Codex harness वर लक्ष केंद्रित करते, जे मुख्य एजंट लूप आणि कार्यान्वयन तर्क प्रदान करते, जे सर्व Codex अनुभवांच्या पायाभूत स्तरावर आहे आणि Codex CLI द्वारे प्रदर्शित केले जाते. येथे सोयीसाठी, आम्ही “Codex” आणि “Codex CLI” या संज्ञा परस्परविनिमयाने वापरू.

एजंट लूप

प्रत्येक AI एजंटच्या केंद्रस्थानी “एजंट लूप” नावाची गोष्ट आहे. एजंट लूपचे एक साधे चित्रण असे दिसते:

“Agent loop” शीर्षक असलेला आरेख, ज्यामध्ये AI प्रणाली वापरकर्त्याची विनंती कशी प्रक्रिया करते, साधने कॉल करते, परिणामांचे निरीक्षण करते, तुमची योजना अद्ययावत करते, आणि आउटपुट परत करते हे दर्शवले आहे. बाण वापरकर्ता इनपुट, मॉडेल रीझनिंग, साधन क्रिया, आणि अंतिम प्रतिसाद यांसारख्या टप्प्यांना जोडतात.

सुरुवातीला, एजंट वापरकर्त्याकडून इनपुट घेतो, ज्याचा समावेश तो प्रॉम्प्ट म्हणून ओळखल्या जाणाऱ्या मॉडेलसाठी तयार करत असलेल्या मजकूर सूचनांच्या संचात करतो.

पुढील पायरी म्हणजे मॉडेलला आमच्या सूचना पाठवून त्याची क्वेरी करणे आणि त्याला प्रतिसाद तयार करण्यास सांगणे, ही प्रक्रिया inference म्हणून ओळखली जाते. इनफरन्स दरम्यान, मजकूर प्रॉम्प्ट प्रथम इनपुट टोकन(नवीन विंडोमध्ये उघडेल)—मॉडेलच्या शब्दसंग्रहात निर्देशांक करणारे पूर्णांक—यांच्या अनुक्रमात अनुवादित केला जातो. ही टोकन नंतर मॉडेलचे नमुना घेण्यासाठी वापरली जातात, ज्यामुळे आउटपुट टोकनची एक नवीन अनुक्रम तयार होते.

आउटपुट टोकन पुन्हा मजकूरात भाषांतरित केले जातात, जे मॉडेलचा प्रतिसाद बनतो. टोकन क्रमाक्रमाने तयार होत असल्यामुळे, मॉडेल चालू असतानाच हे भाषांतर होऊ शकते, म्हणूनच अनेक LLM-आधारित अनुप्रयोग प्रवाहित आउटपुट दाखवतात. प्रत्यक्षात, अनुमान सहसा मजकुरावर कार्य करणाऱ्या API मागे एन्कॅप्स्युलेट केलेले असते, ज्यामुळे टोकनायझेशनचे तपशील अस्पष्ट होतात.

इन्फरन्स स्टेपच्या परिणामी, मॉडेल एकतर (1) वापरकर्त्याच्या मूळ इनपुटला अंतिम प्रतिसाद तयार करते, किंवा (2) टूल कॉल ची विनंती करते जी एजंटने पार पाडणे अपेक्षित असते (उदा., “ls चालवा आणि आउटपुट रिपोर्ट करा”). (२) च्या बाबतीत, एजंट टूल कॉल अंमलात आणतो आणि त्याचे आउटपुट मूळ प्रॉम्प्टला जोडतो. हा आउटपुट नवीन इनपुट तयार करण्यासाठी वापरला जातो, जो मॉडेलला पुन्हा क्वेरी करण्यासाठी वापरला जातो; त्यानंतर एजंट ही नवीन माहिती लक्षात घेऊन पुन्हा प्रयत्न करू शकतो.

ही प्रक्रिया तोपर्यंत पुन्हा पुन्हा होते, जोपर्यंत मॉडेल tool calls उत्सर्जित करणे थांबवते आणि त्याऐवजी वापरकर्त्यासाठी एक संदेश तयार करते (OpenAI मॉडेल्समध्ये याला assistant message असे म्हटले जाते). अनेक प्रकरणांमध्ये, हा संदेश थेट वापरकर्त्याच्या मूळ विनंतीचे उत्तर देतो, परंतु तो वापरकर्त्यासाठी एक पूरक प्रश्न देखील असू शकतो.

एजंट स्थानिक वातावरणात बदल करणारे टूल कॉल्स कार्यान्वित करू शकतो, त्यामुळे त्याचे “output” फक्त असिस्टंट मेसेजपुरते मर्यादित नाही. अनेक प्रकरणांमध्ये, सॉफ्टवेअर एजंटचे प्राथमिक आउटपुट म्हणजे तो तुमच्या मशीनवर लिहितो किंवा संपादित करतो तो कोड. तरीही, प्रत्येक वळण नेहमी सहाय्यकाच्या संदेशानेच संपते—उदाहरणार्थ, “मी तुम्ही मागितलेले architecture.md जोडले”—जे एजंट लूपमध्ये समाप्तीची अवस्था दर्शवते. एजंटच्या दृष्टिकोनातून, त्याचे कार्य पूर्ण झाले आहे आणि नियंत्रण वापरकर्त्याकडे परत जाते.

आकृतीमध्ये वापरकर्त्याचा इनपुट पासून एजंट प्रतिसाद पर्यंतचा प्रवास संभाषणाचा एक वळा (Codex मधील एक थ्रेड ) म्हणून ओळखला जातो. तथापि, या conversation turn मध्ये मॉडेल निष्कर्ष आणि टूल कॉल्स दरम्यान अनेक पुनरावृत्ती समाविष्ट असू शकतात. प्रत्येक वेळी तुम्ही विद्यमान संभाषणात नवीन संदेश पाठवता, तेव्हा संभाषणाचा इतिहास नवीन टर्नसाठीच्या प्रॉम्प्टचा भाग म्हणून समाविष्ट केला जातो, ज्यामध्ये मागील टर्नमधील संदेश आणि साधन कॉल्स समाविष्ट असतात:

“Multi-turn agent loop” शीर्षक असलेला आरेख, ज्यामध्ये AI एजंट पुनरावृत्तीने वापरकर्त्याचे इनपुट घेतो, कृती निर्माण करतो, साधनांचा सल्ला घेतो, स्थिती अद्ययावत करतो आणि परिणाम परत करतो हे दर्शवितो. एजंटच्या रीझनिंगचे स्पष्टीकरण करणारे लेबल केलेले टप्पे, बाण, आणि उदाहरण टूल आउटपुट्स समाविष्ट आहेत.

याचा अर्थ असा की संभाषण जसजसे वाढते, तसतशी मॉडेलचे नमुने घेण्यासाठी वापरल्या जाणाऱ्या प्रॉम्प्टची लांबीही वाढते. ही लांबी महत्त्वाची आहे कारण प्रत्येक मॉडेलला कॉन्टेक्स्ट विंडो असते, जी एका अनुमान कॉलसाठी ते वापरू शकणाऱ्या टोकनची कमाल संख्या आहे. नोंद घ्या की या विंडोमध्ये इनपुट आणि आउटपुट टोकन दोन्ही समाविष्ट आहेत. जसे तुम्ही कल्पना करू शकता, एखादा एजंट एका टर्नमध्ये शेकडो टूल कॉल्स करण्याचा निर्णय घेऊ शकतो, ज्यामुळे कॉन्टेक्स्ट विंडो संभाव्यतः संपुष्टात येऊ शकते. या कारणासाठी, context window management ही एजंटच्या अनेक जबाबदाऱ्यांपैकी एक आहे. आता, Codex एजंट लूप कसा चालवतो ते पाहण्यासाठी चला खोलवर जाऊया.

मॉडेल अनुमान

Codex CLI HTTP विनंत्या Responses API(नवीन विंडोमध्ये उघडेल) कडे मॉडेल इन्फरन्स चालवण्यासाठी पाठवते. तुम्ही पाहू की 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 मध्ये वाचले जाते, जर ते निर्दिष्ट केले असेल; अन्यथा, मॉडेलशी संबंधित base_instructions वापरल्या जातात(नवीन विंडोमध्ये उघडेल). मॉडेल-विशिष्ट सूचना Codex repo मध्ये उपलब्ध आहेत आणि CLI मध्ये समाविष्ट केल्या जातात (उदा., gpt-5.2-codex_prompt.md(नवीन विंडोमध्ये उघडेल)).

tools फील्ड ही Responses API द्वारे परिभाषित केलेल्या स्कीमा शी सुसंगत टूल परिभाषांची यादी आहे. Codex साठी, यामध्ये Codex CLI द्वारे प्रदान केलेली साधने, Codex ला उपलब्ध करून द्यायला हवीत अशी Responses API द्वारे प्रदान केलेली साधने, तसेच वापरकर्त्याने प्रदान केलेली साधने, साधारणपणे MCP servers द्वारे, यांचा समावेश होतो:

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 payload मधील input फील्ड आयटम्सची यादी आहे. Codex खालील आयटम्स समाविष्ट करते(नवीन विंडोमध्ये उघडेल) input मध्ये वापरकर्ता संदेश जोडण्यापूर्वी:

1. role=developer असलेला संदेश जोtoolsविभागात परिभाषित केलेल्या फक्त Codex-प्रदान केलेल्या शेल टूल्ससाठी लागू होणाऱ्या सँडबॉक्सचे वर्णन करतो. म्हणजेच, 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>

२. (पर्यायी) 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 मधील प्रत्येक घटक हा type, role(नवीन विंडोमध्ये उघडेल), आणि content असलेला JSON ऑब्जेक्ट आहे, खालीलप्रमाणे:

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 पूर्ण JSON payload तयार करतो Responses API कडे पाठवण्यासाठी, तेव्हा ~/.codex/config.toml मध्ये Responses API एंडपॉइंट कसा कॉन्फिगर केला आहे त्यानुसार Authorization header सह HTTP POST विनंती करतो (जर अतिरिक्त HTTP headers आणि query parameters निर्दिष्ट केले असतील तर ते जोडले जातात).

जेव्हा OpenAI Responses API सर्व्हरला विनंती प्राप्त होते, तेव्हा ते JSON वापरून मॉडेलसाठी प्रॉम्प्ट खालीलप्रमाणे व्युत्पन्न करते (निश्चितच, Responses API ची कस्टम अंमलबजावणी वेगळा पर्याय निवडू शकते):

AI एजंट लूपमधील एका पायरीचे चित्रण करणारा स्नॅपशॉट आकृती. वापरकर्त्याची विनंती मॉडेलमध्ये प्रवेश करते, ज्यामुळे एक विचार, टूल नावासह एक कृती आणि एक टूल इनपुट तयार होतो. टूल कॉल करण्यापूर्वी डायग्राम हा मधला रीझनिंग टप्पा अधोरेखित करतो.

जसे तुम्ही पाहू शकता, प्रॉम्प्टमधील पहिल्या तीन आयटम्सचा क्रम क्लायंटने नाही, तर सर्व्हरने ठरवला जातो. असे असले तरी, त्या तीन घटकांपैकी, फक्त सिस्टम संदेश चे सामग्री सर्व्हरद्वारे नियंत्रित केली जाते, कारण tools आणि instructions क्लायंटद्वारे ठरवले जातात. प्रॉम्प्ट पूर्ण करण्यासाठी JSON पेलोडमधील input नंतर येते.

आता आमच्याकडे आमचा प्रॉम्प्ट आहे, त्यामुळे आम्ही मॉडेलचे नमुने घेण्यासाठी तयार आहोत.

पहिला वळण

Responses API कडे केलेली ही HTTP विनंती Codex मधील संभाषणाचा पहिला “टर्न” सुरू करते. सर्व्हर Server-Sent Events (SSE(नवीन विंडोमध्ये उघडेल)) प्रवाहासह प्रतिसाद देतो. प्रत्येक इव्हेंटचा data हा JSON पेलोड असतो ज्यामध्ये "type" असतो जो "response" ने सुरू होतो. तो काहीसा असा दिसू शकतो (इव्हेंट्सची संपूर्ण यादी आमच्या API docs(नवीन विंडोमध्ये उघडेल) मध्ये मिळू शकते):

साधा मजकूर

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=रीझनिंग सह आणि एक 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 च्या प्रमाणाच्या दृष्टीने एजंट लूप quadratic नाही का?” आणि तुम्ही योग्य आहात. Responses API मध्ये ऐच्छिक previous_response_id(नवीन विंडोमध्ये उघडेल) पॅरामीटरचा सपोर्ट असला तरी, Codex आज ते वापरत नाही, मुख्यतः विनंत्या पूर्णपणे स्टेटलेस ठेवण्यासाठी आणि झीरो डेटा रिटेन्शन (ZDR) कॉन्फिगरेशन्सना सपोर्ट करण्यासाठी.

previous_response_id टाळल्याने रिस्पॉन्सेस API च्या प्रदात्यासाठी गोष्टी सोप्या होतात कारण त्यामुळे प्रत्येक विनंती stateless असल्याची खात्री होते. हे झीरो डेटा रिटेन्शन (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 मध्ये नवीन संदेश जोडून हाताळतो, आधीचा संदेश बदलण्याऐवजी:

कार्यक्षमतेसाठी कॅशे हिट्स सुनिश्चित करण्यासाठी आम्ही मोठ्या प्रमाणात go करतो. आम्हाला व्यवस्थापित करावा लागणारा आणखी एक महत्त्वाचा संसाधन आहे: कॉन्टेक्स्ट विंडो.

संदर्भ विंडो संपून जाऊ नये यासाठी आमची सामान्य रणनीती म्हणजे टोकनची संख्या काही ठराविक मर्यादेपेक्षा जास्त झाली की संभाषण संक्षिप्त करणे. विशेषतः, आम्ही input ला संभाषणाचे प्रतिनिधित्व करणाऱ्या नवीन, लहान आयटम्सच्या यादीने बदलतो, ज्यामुळे एजंटला आतापर्यंत काय घडले आहे याची समज ठेवून पुढे सुरू ठेवता येते. कॉम्पॅक्शनच्या सुरुवातीच्या अंमलबजावणीसाठी(नवीन विंडोमध्ये उघडेल) वापरकर्त्याला /compact कमांड मॅन्युअली इनव्होक करावी लागली, जी विद्यमान संभाषणासह कस्टम सूचनांचा वापर करून Responses API ला क्वेरी करत असे सारांश(नवीन विंडोमध्ये उघडेल) करण्यासाठी. Codex ने सारांश असलेला परिणामी सहाय्य संदेश नवीन इनपुट(नवीन विंडोमध्ये उघडेल) म्हणून पुढील संभाषण फेऱ्यांसाठी वापरला.

तेव्हापासून, Responses API ने अधिक कार्यक्षमतेने कॉम्पॅक्शन करण्यासाठी समर्थन देणारा विशेष /responses/compact एंडपॉइंट(नवीन विंडोमध्ये उघडेल) विकसित केला आहे. हे आयटम्सची यादी(नवीन विंडोमध्ये उघडेल) परत करते, जी मागील इनपुट च्या जागी वापरता येते, ज्यामुळे कॉन्टेक्स्ट विंडो मोकळी होते आणि संभाषण सुरू ठेवता येते. या यादीमध्ये एक विशेष type=compaction आयटम समाविष्ट आहे, ज्यामध्ये एक अपारदर्शक encrypted_content आयटम आहे जो मूळ संभाषणाबद्दल मॉडेलची लॅटेंट समज जतन करतो. आता, Codex auto_compact_limit(नवीन विंडोमध्ये उघडेल) ओलांडल्यावर संभाषण संक्षिप्त करण्यासाठी हा एंडपॉइंट स्वयंचलितपणे वापरतो.

लवकरच येत आहे

आम्ही Codex एजंट लूप सादर केला आहे आणि Codex मॉडेलला क्वेरी करताना तुमचा संदर्भ कसा तयार करतो आणि व्यवस्थापित करतो याची माहिती दिली आहे. या प्रवासात, आम्ही Responses API वर आधारित एजंट लूप तयार करणाऱ्या कोणालाही लागू होणाऱ्या व्यावहारिक विचार आणि सर्वोत्तम पद्धतींवर प्रकाश टाकला.

एजंट लूप Codex साठी पाया प्रदान करत असला तरी, ही केवळ सुरुवात आहे. आगामी पोस्ट्समध्ये, आम्ही CLI च्या आर्किटेक्चरमध्ये सखोल जाऊ, टूल वापर कसा अंमलात आणला आहे ते पाहू, आणि Codex च्या मॉडेलच्या सँडबॉक्सिंगकडे अधिक सविस्तर पाहू.

लेखक

Michael Bolin

पावती

Codex CLI तयार केलेल्या संपूर्ण संघाचे विशेष आभार.