Проверки кода всегда имели решающее значение для поддержания стандартов и акцентирования внимания на лучших практиках использования кода в проекте. Это не пост о том, как разработчики должны проверять код, а скорее о делегировании его части ИИ.
Как упоминает Майкл Линч в своем посте «Как проводить проверку кода по-человечески», мы должны позволить компьютерам позаботиться о скучных частях проверки кода. Хотя Майкл делает упор на инструменте форматирования, я хотел бы пойти еще дальше и позволить искусственному интеллекту разобраться во всем. Я имею в виду, почему бы не воспользоваться бумом искусственного интеллекта в отрасли?
Я не говорю, что ИИ следует использовать вместо инструментов форматирования и линтеров. Вместо этого его следует использовать в дополнение к этому, чтобы уловить тривиальные вещи, которые человек может пропустить.
Вот почему я решил создать действие на GitHub, которое проверяет код различий запросов на включение и генерирует предложения с использованием искусственного интеллекта. Позвольте мне рассказать вам об этом.
? Примечание
- Это действие GitHub теперь доступно на торговой площадке GitHub.
- Это действие javascript — узнайте больше о создании действий javascript на GitHub.
Для взаимодействия с 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(), })
Игнорировать файлы довольно просто. Для списка пользовательского ввода требуется строка шаблонов, разделенных точкой с запятой. Затем он анализируется, объединяется со списком игнорируемых файлов по умолчанию и устраняет дублирование.
**/*.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.
Приглашение пользователя содержит фактические различия, правила и контекст запроса на включение. С этого начинается проверка кода.
Этот экшен на 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.
Экшен 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