«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Лучше — средство проверки кода на базе искусственного интеллекта GitHub Action

Лучше — средство проверки кода на базе искусственного интеллекта GitHub Action

Опубликовано 8 ноября 2024 г.
Просматривать:508

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

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

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

Вот почему я решил создать действие на 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.

Better - An AI powered Code Reviewer GitHub Action Муртузаалисурти / лучше

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

лучше

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

Зачем это использовать?

  • Стандартизируйте процесс проверки кода
  • Быстрее получайте отзывы
  • Распознайте шаблоны, которые приводят к плохому коду
  • Обнаружение распространенных проблем
  • Определить уязвимости безопасности
  • Второе мнение
  • Чтобы люди могли сосредоточиться на более сложных задачах

Использование

1. Создайте рабочий процесс

Создайте файл рабочего процесса в папке .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
Войти в полноэкранный режимВыйти из полноэкранного режима
Просмотреть на GitHub
Заявление о выпуске Эта статья воспроизведена по адресу: https://dev.to/murtuzaalisurti/better-an-ai-powered-code-reviewer-github-action-2n28?1. Если есть какие-либо нарушения, свяжитесь с [email protected], чтобы удалить это
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3