كانت مراجعات التعليمات البرمجية دائمًا حاسمة في الحفاظ على المعيار والتأكيد على أفضل ممارسات التعليمات البرمجية في المشروع. هذا ليس منشورًا حول كيفية مراجعة المطورين للتعليمات البرمجية، بل يتعلق أكثر بتفويض جزء منه إلى الذكاء الاصطناعي.
كما ذكر مايكل لينش في منشوره - "كيفية إجراء مراجعات الكود مثل الإنسان" - يجب علينا السماح لأجهزة الكمبيوتر بالاهتمام بالأجزاء المملة من مراجعة الكود. بينما يؤكد مايكل على أداة التنسيق، أود أن أخطو خطوة إلى الأمام وأدع الذكاء الاصطناعي يكتشفها. أعني، لماذا لا نستفيد من ازدهار الذكاء الاصطناعي في الصناعة؟
الآن أنا لا أقول أنه يجب استخدام الذكاء الاصطناعي بدلاً من أدوات التنسيق والأدوات. بدلاً من ذلك، يتم استخدامه فوق ذلك، لالتقاط الأشياء التافهة التي قد يفوتها الإنسان.
لهذا السبب قررت إنشاء إجراء جيثب يقوم فيه الكود بمراجعة فرق طلب السحب وإنشاء اقتراحات باستخدام الذكاء الاصطناعي. اسمحوا لي أن أطلعكم على ذلك.
؟ ملحوظة
- هذا الإجراء على GitHub متاح الآن في سوق GitHub.
- إنه إجراء جافا سكريبت - تعرف على المزيد حول إنشاء إجراءات جافا سكريبت على جيثب.
للتفاعل مع واجهة برمجة تطبيقات github، استخدمت octokit، وهو نوع من SDK أو مكتبة عميل للتفاعل مع واجهة برمجة تطبيقات github بطريقة اصطلاحية.
لكي تتمكن من رفع فرق طلب السحب، تحتاج إلى تمرير رأس القبول مع القيمة application/vnd.github.diff مع المعلمات المطلوبة.
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) ), ];
يتم بعد ذلك استخدام قائمة الملفات المتجاهلة لإزالة التغييرات المختلفة التي تشير إلى تلك الملفات المتجاهلة. يمنحك ذلك حمولة أولية تحتوي فقط على التغييرات التي تريدها.
بمجرد أن أحصل على الحمولة الأولية بعد تحليل الفرق، أقوم بتمريرها إلى واجهة برمجة تطبيقات النظام الأساسي. إليك تطبيق 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; }
قد تلاحظ استخدام تنسيق الاستجابة في تنفيذ واجهة برمجة التطبيقات. هذه هي الميزة التي توفرها العديد من منصات LLM، والتي تسمح لك بإخبار النموذج بإنشاء الاستجابة في مخطط/تنسيق محدد. إنه مفيد بشكل خاص في هذه الحالة لأنني لا أريد أن يهلوس النموذج ويولد اقتراحات لملفات أو مواضع غير صحيحة في طلب السحب، أو يضيف خصائص جديدة إلى حمولة الاستجابة.
موجه النظام موجود لإعطاء النموذج مزيدًا من السياق حول كيفية إجراء مراجعة التعليمات البرمجية وما هي بعض الأشياء التي يجب وضعها في الاعتبار. يمكنك عرض موجه النظام هنا github.com/murtuzaalisurti/better.
يحتوي موجه المستخدم على الفرق الفعلي والقواعد وسياق طلب السحب. وهذا هو ما يبدأ مراجعة الكود.
يدعم إجراء github هذا كلاً من نماذج OpenAI وAnthropic. وإليك كيفية تنفيذ Anthropic 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 لإضافة التعليقات كجزء من المراجعة.
لقد اخترت الطريقة أدناه لإضافة التعليقات لأنه من خلال إنشاء مراجعة جديدة، يمكنك إضافة جميع التعليقات دفعة واحدة بدلاً من إضافة تعليق واحد في كل مرة. قد تؤدي إضافة التعليقات واحدًا تلو الآخر أيضًا إلى تحديد المعدل لأن إضافة التعليقات تؤدي إلى تشغيل الإشعارات ولا ترغب في إرسال رسائل غير مرغوب فيها إلى المستخدمين باستخدام الإشعارات.
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/workflows (قم بإنشائه إذا لم يكن موجودًا) لمستودعك بالمحتوى التالي:
name: Code Review
on
pull_request:
types: [opened, reopened, synchronize, ready_for_review]
branches:
- main # change this to your target branch
workflow_dispatch: # Allows you to run the workflow manually from the Actions tab
permissions: # necessary permissions
pull-requests: write
contents: read
jobs:
your-job-name:
runs-on: ubuntu-latest
name: your-job-name
steps:
- name: step-name
id: step-id
uses: murtuzaalisurti/better@v2 # this is
…تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.
Copyright© 2022 湘ICP备2022001581号-3