"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Melhor - Uma ação do GitHub para revisores de código com tecnologia de IA

Melhor - Uma ação do GitHub para revisores de código com tecnologia de IA

Publicado em 2024-11-08
Navegar:124

As revisões de código sempre foram cruciais para manter um padrão e enfatizar as melhores práticas de código em um projeto. Este não é um post sobre como os desenvolvedores devem revisar o código, é mais sobre delegar uma parte dele à IA.

Como Michael Lynch menciona em sua postagem - "Como fazer revisões de código como um humano" - deveríamos deixar os computadores cuidarem das partes chatas da revisão de código. Embora Michael enfatize uma ferramenta de formatação, eu gostaria de dar um passo adiante e deixar a inteligência artificial descobrir isso. Quero dizer, por que não aproveitar a vantagem do boom da IA ​​na indústria?

Agora, não estou dizendo que a IA deva ser usada no lugar de ferramentas de formatação e linters. Em vez disso, deve ser usado além disso, para capturar coisas triviais que podem passar despercebidas a um humano.

É por isso que decidi criar uma ação no github cujo código analisa uma comparação de pull request e gera sugestões usando IA. Deixe-me explicar isso.

? Observação

  • Esta ação do GitHub já está disponível no mercado GitHub.
  • É uma ação javascript - saiba mais sobre como criar ações javascript no github.

Obtendo a diferença

Para interagir com a API do github, usei o octokit, que é uma espécie de SDK ou biblioteca cliente para interagir com a API do github de forma idiomática.

Para obter o diff da solicitação pull levantada, você precisa passar o cabeçalho Accept com o valor application/vnd.github.diff junto com os parâmetros necessários.

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,
        },
    });
}

Se você não está familiarizado com as ações do github, aqui está uma série 101 de ações do github de Victoria Lo e é um bom começo.

Depois de obter a comparação, eu a analiso e removo as alterações indesejadas e, em seguida, a retorno em um esquema mostrado abaixo:

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

Ignorando arquivos

Ignorar arquivos é bastante simples. A lista de entrada do usuário requer uma sequência de padrões glob separados por ponto e vírgula. Em seguida, ele é analisado, concatenado com a lista padrão de arquivos ignorados e desduplicado.

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

A lista de arquivos ignorados é então usada para remover as alterações de comparação que se referem a esses arquivos ignorados. Isso fornece uma carga útil bruta contendo apenas as alterações desejadas.

Gerando sugestões

Depois de obter a carga útil bruta após analisar a diferença, eu a passo para a API da plataforma. Aqui está uma implementação da 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;
}

Você pode notar o uso do formato de resposta na implementação da API. Este é um recurso fornecido por muitas plataformas LLM, que permite dizer ao modelo para gerar a resposta em um esquema/formato específico. É especialmente útil neste caso, pois não quero que o modelo tenha alucinações e gere sugestões para arquivos ou posições incorretas na solicitação pull, ou adicione novas propriedades à carga útil da resposta.

O prompt do sistema existe para fornecer ao modelo mais contexto sobre como ele deve fazer a revisão do código e quais são algumas coisas a serem lembradas. Você pode ver o prompt do sistema aqui github.com/murtuzaalisurti/better.

O prompt do usuário contém a comparação real, as regras e o contexto da solicitação pull. É o que dá início à revisão do código.

Esta ação do github oferece suporte aos modelos OpenAI e Anthropic. Veja como ele implementa a API Antrópica:

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;
}

Adicionando comentários

Finalmente, depois de recuperar as sugestões, eu as limpo e as passo para a API do github para adicionar comentários como parte da revisão.

Escolhi a forma abaixo para adicionar comentários porque, ao criar uma nova avaliação, você pode adicionar todos os comentários de uma vez, em vez de adicionar um único comentário de cada vez. Adicionar comentários um por um também pode acionar a limitação de taxa porque adicionar comentários aciona notificações e você não deseja enviar notificações para os usuários.

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;
    }
}

Conclusão

Eu queria manter a ação do github aberta e aberta a integrações e é por isso que você pode usar qualquer modelo de sua escolha (veja a lista de modelos suportados), ou você pode ajustar e construir seu próprio modelo personalizado sobre os modelos básicos suportados e use-o com esta ação do github.

Se você encontrar algum problema de token ou limitação de taxa, você pode atualizar os limites do seu modelo consultando a documentação da respectiva plataforma.

Então, o que você está esperando? Se você tiver um repositório no github, experimente a ação agora - está no mercado de ações do github.

Better - An AI powered Code Reviewer GitHub Action murtuzaalisurti / melhorar

Uma ação do github de revisor de código com tecnologia de IA, pronta para ser usada em seu fluxo de trabalho.

melhorar

Uma ação do github de revisor de código com tecnologia de IA, pronta para ser usada em seu fluxo de trabalho.

Por que usar?

  • Padronize seu processo de revisão de código
  • Receba feedback mais rapidamente
  • Reconhecer padrões que resultam em código incorreto
  • Detecção de problemas comuns
  • Identificar vulnerabilidades de segurança
  • Segunda opinião
  • Para que os humanos se concentrem em tarefas mais complexas

Uso

1. Crie um fluxo de trabalho

Crie um arquivo de fluxo de trabalho dentro da pasta .github/workflows (crie se não existir) do seu repositório com o seguinte conteúdo:

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
Entrar no modo de tela cheia Sair do modo de tela cheia
Ver no GitHub
Declaração de lançamento Este artigo foi reproduzido em: https://dev.to/murtuzaalisurti/better-an-ai-powered-code-reviewer-github-action-2n28?1 Se houver alguma violação, entre em contato com [email protected] para excluir isto
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3