paint-brush
Лучше — Рецензент кода на базе искусственного интеллектак@murtuzaalisurti

Лучше — Рецензент кода на базе искусственного интеллекта

к Murtuza
Murtuza HackerNoon profile picture

Murtuza

@murtuzaalisurti

Software Engineer, Building syntackle.com

8 мин read2024/11/20
Read on Terminal Reader
Read this story in a terminal
Print this story
Read this story w/o Javascript
Read this story w/o Javascript
tldt arrow
ru-flagRU
Прочтите эту историю на русском языке!
en-flagEN
Read this story in the original language, English!
tr-flagTR
Bu hikayeyi Türkçe okuyun!
ko-flagKO
이 이야기를 한국어로 읽어보세요!
de-flagDE
Lesen Sie diese Geschichte auf Deutsch!
bn-flagBN
এই গল্পটি বাংলায় পড়ুন!
es-flagES
Lee esta historia en Español!
hi-flagHI
इस कहानी को हिंदी में पढ़ें!
zh-flagZH
用繁體中文閱讀這個故事!
vi-flagVI
Đọc bài viết này bằng tiếng Việt!
fr-flagFR
Lisez cette histoire en Français!
pt-flagPT
Leia esta história em português!
ja-flagJA
この物語を日本語で読んでください!
RU

Слишком долго; Читать

Обзоры кода всегда были важны для поддержания стандарта и акцентирования внимания на лучших практиках кода в проекте. Это не пост о том, как разработчики должны просматривать код, а скорее о делегировании его части ИИ. Вот почему я решил создать действие github (github.com/murtuzaalisurti/better), которое проверяет разницу в запросе на извлечение и генерирует предложения с использованием ИИ.

People Mentioned

Mention Thumbnail

Michael Lynch

@mtlynch

Mention Thumbnail

Code Review

@codereview

Companies Mentioned

Mention Thumbnail
GitHub
Mention Thumbnail
Human
featured image - Лучше — Рецензент кода на базе искусственного интеллекта
Murtuza HackerNoon profile picture
Murtuza

Murtuza

@murtuzaalisurti

Software Engineer, Building syntackle.com

0-item
1-item

STORY’S CREDIBILITY

AI-assisted

AI-assisted

This story contains AI-generated text. The author has used AI either for research, to generate outlines, or write the text itself.

Product Launch

Product Launch

This post provides insights into new product.

Обзоры кода всегда были важны для поддержания высоких стандартов и закрепления лучших практик в проекте кодирования. Это не пост о том, как разработчикам следует просматривать код, а скорее о делегировании его части ИИ.


Как упоминает Майкл Линч в своем посте «Как делать обзоры кода, как человек» , мы должны позволить компьютерам заботиться о скучных частях обзора кода. В то время как Майкл подчеркивает инструмент форматирования, я хотел бы пойти дальше и позволить искусственному интеллекту разобраться с этим. Я имею в виду, почему бы не воспользоваться бумом ИИ в отрасли?


Я не говорю, что ИИ следует использовать вместо инструментов форматирования и линтеров. Вместо этого его следует использовать поверх всего этого, чтобы отлавливать тривиальные вещи, которые может пропустить человек. Вот почему я решил создать действие github , которое просматривает код diff pull request и генерирует предложения с помощью ИИ. Позвольте мне провести вас через это.


🚨 ПРИМЕЧАНИЕ:


Получение разницы

Для взаимодействия с API github я использовал octokit , который представляет собой своего рода SDK или клиентскую библиотеку для взаимодействия с API github идиоматическим способом.


Чтобы получить разницу в запросе на извлечение, вам необходимо передать заголовок Accept со значением 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, }, }); }



Если вы вообще не знакомы с действиями GitHub, вот серия «101 действие GitHub» от Виктории Ло , и это хорошее начало.



Получив разницу, я анализирую ее и удаляю нежелательные изменения, а затем возвращаю ее в виде схемы, показанной ниже:


 /** 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(), })

Игнорирование файлов

Игнорирование файлов довольно простое. Список пользовательского ввода требует строку шаблонов glob, разделенную точкой с запятой. Затем он анализируется, объединяется со списком игнорируемых файлов по умолчанию и дедуплицируется.


 **/*.md; **/*.env; **/*.lock; const filesToIgnoreList = [ ...new Set( filesToIgnore .split(";") .map(file => file.trim()) .filter(file => file !== "") .concat(FILES_IGNORED_BY_DEFAULT) ), ];


Список игнорируемых файлов затем используется для удаления изменений diff, которые ссылаются на эти игнорируемые файлы. Это дает вам сырую полезную нагрузку, содержащую только нужные вам изменения.

Генерация предложений

Как только я получаю сырую полезную нагрузку после разбора diff, я передаю ее в API платформы. Вот реализация API OpenAI.


 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 . Пользовательское приглашение содержит фактическое различие, правила и контекст запроса на извлечение. Это то, что запускает проверку кода.


Это действие 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; }

Добавление комментариев

Наконец, после получения предложений я очищаю их и передаю в API 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.


Если у вас возникли проблемы с токенами или ограничения по скорости , возможно, вам следует обновить лимиты вашей модели, обратившись к документации соответствующей платформы.


Так чего же вы ждете? Если у вас есть репозиторий на github, попробуйте действие прямо сейчас — оно есть на github action marketplace .


L O A D I N G
. . . comments & more!

About Author

Murtuza HackerNoon profile picture
Software Engineer, Building syntackle.com

БИРКИ

ЭТА СТАТЬЯ БЫЛА ПРЕДСТАВЛЕНА В...

Permanent on Arweave
Read on Terminal Reader
Read this story in a terminal
 Terminal
Read this story w/o Javascript
Read this story w/o Javascript
 Lite
Also published here

Mentioned in this story

profiles
X REMOVE AD