कोडिंग प्रोजेक्ट में उच्च मानकों को बनाए रखने और सर्वोत्तम प्रथाओं को सुदृढ़ करने में कोड समीक्षा हमेशा महत्वपूर्ण रही है। यह पोस्ट इस बारे में नहीं है कि डेवलपर्स को कोड की समीक्षा कैसे करनी चाहिए, यह इसके एक हिस्से को AI को सौंपने के बारे में अधिक है। जैसा कि माइकल लिंच ने अपनी पोस्ट - में उल्लेख किया है - हमें चाहिए। जबकि माइकल एक फ़ॉर्मेटिंग टूल पर जोर देते हैं, मैं इसे एक कदम आगे ले जाना चाहता हूँ और कृत्रिम बुद्धिमत्ता को इसे हल करने देना चाहता हूँ। मेरा मतलब है, उद्योग में एआई बूम का लाभ क्यों न उठाया जाए? "मानव की तरह कोड समीक्षा कैसे करें" कंप्यूटर को कोड समीक्षा के उबाऊ हिस्सों का ध्यान रखने देना अब मैं यह नहीं कह रहा हूँ कि AI का इस्तेमाल फ़ॉर्मेटिंग टूल और लिंटर की जगह किया जाना चाहिए। इसके बजाय, इसका इस्तेमाल उसके ऊपर किया जाना चाहिए, ताकि छोटी-छोटी चीज़ों को पकड़ा जा सके जो शायद किसी इंसान से छूट जाएँ। इसीलिए मैंने एक बनाने का फ़ैसला किया जो पुल रिक्वेस्ट डिफ़ की कोड समीक्षा करता है और AI का इस्तेमाल करके सुझाव तैयार करता है। चलिए मैं आपको इसके बारे में बताता हूँ। github एक्शन 🚨 नोट: यह GitHub क्रिया अब पर उपलब्ध है। GitHub बाज़ार यह एक जावास्क्रिप्ट क्रिया है - के बारे में अधिक जानें। जावास्क्रिप्ट गिटहब क्रियाएँ बनाने अंतर समझना गिटहब एपीआई के साथ बातचीत करने के लिए, मैंने उपयोग किया है, जो कि एक एसडीके या । octokit क्लाइंट लाइब्रेरी है जो गिटहब एपीआई के साथ मुहावरेदार तरीके से बातचीत करता है आपके द्वारा उठाए गए पुल अनुरोध का अंतर प्राप्त करने के लिए, आपको आवश्यक पैरामीटर के साथ मान के साथ हेडर को पास करना होगा। application/vnd.github.diff Accept async function getPullRequestDetails(octokit, { mode }) { let AcceptFormat = "application/vnd.github.raw+json"; if (mode === "diff") AcceptFormat = "application/vnd.github.diff"; if (mode === "json") AcceptFormat = "application/vnd.github.raw+json"; return await octokit.rest.pulls.get({ owner: github.context.repo.owner, repo: github.context.repo.repo, pull_number: github.context.payload.pull_request.number, headers: { accept: AcceptFormat, }, }); } यदि आप गिटहब एक्शन्स से बिल्कुल भी परिचित नहीं हैं, तो यहां है और यह एक अच्छी शुरुआत है। विक्टोरिया लो द्वारा गिटहब एक्शन्स 101 श्रृंखला एक बार जब मुझे अंतर मिल जाता है, तो मैं इसे पार्स करता हूं और अवांछित परिवर्तनों को हटा देता हूं, और फिर इसे नीचे दिखाए गए स्कीमा में वापस कर देता हूं: /** using zod */ schema = z.object({ path: z.string(), position: z.number(), line: z.number(), change: z.object({ type: z.string(), add: z.boolean(), ln: z.number(), content: z.string(), relativePosition: z.number(), }), previously: z.string().optional(), suggestions: z.string().optional(), }) फ़ाइलों को अनदेखा करना फ़ाइलों को अनदेखा करना बहुत आसान है। उपयोगकर्ता इनपुट सूची के लिए ग्लोब पैटर्न की अर्धविराम से अलग की गई स्ट्रिंग की आवश्यकता होती है। फिर इसे पार्स किया जाता है, अनदेखा की गई फ़ाइलों की डिफ़ॉल्ट सूची के साथ संयोजित किया जाता है और डी-डुप किया जाता है। **/*.md; **/*.env; **/*.lock; const filesToIgnoreList = [ ...new Set( filesToIgnore .split(";") .map(file => file.trim()) .filter(file => file !== "") .concat(FILES_IGNORED_BY_DEFAULT) ), ]; फिर अनदेखा की गई फ़ाइलों की सूची का उपयोग उन अंतर परिवर्तनों को हटाने के लिए किया जाता है जो उन अनदेखा की गई फ़ाइलों को संदर्भित करते हैं। यह आपको एक कच्चा पेलोड देता है जिसमें केवल वही परिवर्तन होते हैं जो आप चाहते हैं। सुझाव उत्पन्न करना एक बार जब मुझे अंतर को पार्स करने के बाद कच्चा पेलोड मिल जाता है, तो मैं इसे प्लेटफ़ॉर्म API को पास कर देता हूँ। यहाँ OpenAI API का कार्यान्वयन है। async function useOpenAI({ rawComments, openAI, rules, modelName, pullRequestContext }) { const result = await openAI.beta.chat.completions.parse({ model: getModelName(modelName, "openai"), messages: [ { role: "system", content: COMMON_SYSTEM_PROMPT, }, { role: "user", content: getUserPrompt(rules, rawComments, pullRequestContext), }, ], response_format: zodResponseFormat(diffPayloadSchema, "json_diff_response"), }); const { message } = result.choices[0]; if (message.refusal) { throw new Error(`the model refused to generate suggestions - ${message.refusal}`); } return message.parsed; } आप API कार्यान्वयन में प्रतिक्रिया प्रारूप के उपयोग को देख सकते हैं। यह कई LLM प्लेटफ़ॉर्म द्वारा प्रदान की जाने वाली एक सुविधा है, जो आपको मॉडल को एक विशिष्ट स्कीमा/प्रारूप में प्रतिक्रिया उत्पन्न करने के लिए कहने की अनुमति देती है। यह इस मामले में विशेष रूप से सहायक है क्योंकि मैं नहीं चाहता कि मॉडल भ्रम में पड़ जाए और पुल अनुरोध में गलत फ़ाइलों या स्थितियों के लिए सुझाव उत्पन्न करे, या प्रतिक्रिया पेलोड में नई प्रॉपर्टी जोड़े। सिस्टम प्रॉम्प्ट मॉडल को इस बारे में अधिक संदर्भ देने के लिए है कि उसे कोड समीक्षा कैसे करनी चाहिए और किन बातों को ध्यान में रखना चाहिए। आप सिस्टम प्रॉम्प्ट यहाँ देख सकते हैं । उपयोगकर्ता प्रॉम्प्ट में वास्तविक अंतर, नियम और पुल अनुरोध का संदर्भ शामिल है। यह वही है जो कोड समीक्षा को शुरू करता है। github.com/murtuzaalisurti/better यह गिटहब एक्शन OpenAI और एंथ्रोपिक दोनों मॉडल का समर्थन करता है। यहाँ बताया गया है कि यह एंथ्रोपिक API को कैसे लागू करता है: async function useAnthropic({ rawComments, anthropic, rules, modelName, pullRequestContext }) { const { definitions } = zodToJsonSchema(diffPayloadSchema, "diffPayloadSchema"); const result = await anthropic.messages.create({ max_tokens: 8192, model: getModelName(modelName, "anthropic"), system: COMMON_SYSTEM_PROMPT, tools: [ { name: "structuredOutput", description: "Structured Output", input_schema: definitions["diffPayloadSchema"], }, ], tool_choice: { type: "tool", name: "structuredOutput", }, messages: [ { role: "user", content: getUserPrompt(rules, rawComments, pullRequestContext), }, ], }); let parsed = null; for (const block of result.content) { if (block.type === "tool_use") { parsed = block.input; break; } } return parsed; } टिप्पणियाँ जोड़ना अंत में, सुझावों को प्राप्त करने के बाद, मैं उन्हें संशोधित करता हूं और समीक्षा के एक भाग के रूप में टिप्पणियां जोड़ने के लिए उन्हें GitHub API को भेजता हूं। मैंने टिप्पणियाँ जोड़ने के लिए नीचे दिया गया तरीका चुना क्योंकि एक नई समीक्षा बनाकर, आप एक बार में एक ही टिप्पणी जोड़ने के बजाय एक बार में सभी टिप्पणियाँ जोड़ सकते हैं। एक-एक करके टिप्पणियाँ जोड़ने से दर सीमित हो सकती है क्योंकि टिप्पणियाँ जोड़ने से सूचनाएँ सक्रिय हो जाती हैं और आप उपयोगकर्ताओं को सूचनाओं से स्पैम नहीं करना चाहते। function filterPositionsNotPresentInRawPayload(rawComments, comments) { return comments.filter(comment => rawComments.some(rawComment => rawComment.path === comment.path && rawComment.line === comment.line) ); } async function addReviewComments(suggestions, octokit, rawComments, modelName) { const { info } = log({ withTimestamp: true }); // eslint-disable-line no-use-before-define const comments = filterPositionsNotPresentInRawPayload(rawComments, extractComments().comments(suggestions)); try { await octokit.rest.pulls.createReview({ owner: github.context.repo.owner, repo: github.context.repo.repo, pull_number: github.context.payload.pull_request.number, body: `Code Review by ${modelName}`, event: "COMMENT", comments, }); } catch (error) { info(`Failed to add review comments: ${JSON.stringify(comments, null, 2)}`); throw error; } } निष्कर्ष मैं GitHub एक्शन को ओपन-एंडेड और एकीकरण के लिए खुला रखना चाहता था और इसीलिए आप अपनी पसंद के किसी भी मॉडल का उपयोग कर सकते हैं , या आप समर्थित बेस मॉडल के शीर्ष पर अपने स्वयं के कस्टम मॉडल को ठीक कर सकते हैं और बना सकते हैं और इसे इस GitHub एक्शन के साथ उपयोग कर सकते हैं। ( की सूची देखें) समर्थित मॉडलों यदि आपको किसी सामना करना पड़ता है, तो आप संबंधित प्लेटफ़ॉर्म के दस्तावेज़ों का संदर्भ लेकर अपनी मॉडल सीमाओं को अपग्रेड करना चाह सकते हैं। टोकन समस्या या दर सीमा का तो, आप किस बात का इंतज़ार कर रहे हैं? अगर आपके पास github पर रिपॉजिटरी है, तो अभी एक्शन आज़माएँ - यह पर है। github एक्शन मार्केटप्लेस