Automating Content Quality with AI: Implementing a Pre-Commit Hook in TypeScript with GPT-4o

Learn how to implement a pre-commit hook in TypeScript that validates and grades content quality using AI, specifically GPT-4o, applies changes, and manages state with markdown metadata.

Automate Content Quality with AI: Implement a Pre-Commit Hook in TypeScript with GPT-4o

In this article, we'll show you how to set up a pre-commit hook in TypeScript to validate and grade the quality of your content using AI, specifically GPT-4o. Think of it as having an AI editor who helps you improve your content before you commit it. Plus, it keeps track of things with markdown metadata.

Step-by-Step Guide

Step 1: Set Up the Pre-Commit Hook

First, create a pre-commit hook that triggers the content validation and grading process:

  1. Go to the .git/hooks folder.
  2. Create a new file named pre-commit.
  3. Add the following content to pre-commit:
    import { exec } from 'child_process';
    import { promisify } from 'util';
    import * as fs from 'fs';
    import * as path from 'path';
    import * as readline from 'readline';
    import fetch from 'node-fetch';
    import OpenAI from 'openai';
    import matter from 'gray-matter';

    const execAsync = promisify(exec);

    const verbosity = process.argv[2] ? parseInt(process.argv[2], 10) : 1;

    const openai = new OpenAI({
      apiKey: process.env.OPENAI_API_KEY,
    });

    async function run() {
      try {
        // Navigate to the root of the project
        const { stdout: rootDir } = await execAsync('git rev-parse --show-toplevel');
        process.chdir(rootDir.trim());

        // Log a message to verify the hook is running
        if (verbosity >= 1) console.log('Running pre-commit hook...');

        // Check if this is the initial commit
        let against;
        try {
          await execAsync('git rev-parse --verify HEAD');
          against = 'HEAD';
        } catch {
          const { stdout } = await execAsync('git rev-parse --verify HEAD');
          against = stdout.trim();
        }

        // Log the files being checked
        if (verbosity >= 1) console.log("Checking for staged .mdx files under 'blog/src/articles'...");

        // Get list of staged .mdx files under 'blog/src/articles'
        const { stdout: stagedFiles } = await execAsync('git diff --cached --name-only --diff-filter=ACM');
        if (verbosity >= 2) console.log(`Staged files: ${stagedFiles}`);
        const files = stagedFiles.split('\n').filter(file => file.startsWith('blog/src/articles/') && file.endsWith('.mdx'));
        if (verbosity >= 2) console.log(`Filtered .mdx files: ${files}`);

        if (files.length > 0) {
          for (const file of files) {
            const content = fs.readFileSync(file, 'utf8');
            const { data: metadata } = matter(content);

            if (metadata.processed) {
              if (verbosity >= 1) console.log(`Skipping ${file} as it is already processed.`);
              continue;
            }

            // Log a message to verify the hook is running
            if (verbosity >= 1) console.log(`Processing file: ${file}`);

            const response = await openai.chat.completions.create({
              model: 'gpt-4o',
              messages: [
                {
                  role: 'system',
                  content: `You are an expert professional editor, skilled in evaluating the quality of markdown content.
     Maintain the current level of complexity and style in the articles.
     Follow these style guidelines:
     <Add a list of guidelines you want here>
     Output only JSON:
     { "initialFeedback": "string", "revisedContent": "string", "grade": "integer (0-100)" }`
                },
                {
                  role: 'user',
                  content: `Check the quality of the following markdown content and provide a revised version. Markdown content:\n\n${content}`
                }
              ],
            });

            // Ensure the response is a string and remove backticks and 'json' if they are included
            let responseContent = response.choices[0].message?.content || '{}';
            responseContent = responseContent.replace(/```json/g, '').replace(/```/g, '');

            // Parse the response
            let result;
            try {
              result = JSON.parse(responseContent);
              console.log('Parsed JSON:', result);
            } catch (e) {
              console.error('Failed to parse JSON response:', e);
              continue;
            }

            const initialFeedback = result.initialFeedback;
            const revisedContent = result.revisedContent;
            const grade = result.grade;

            if (revisedContent) {
              fs.writeFileSync(file, revisedContent, 'utf8');
              if (verbosity >= 1) console.log(`File updated with the revised version: ${file}`);
              if (verbosity >= 1) console.log(`Grade for ${file}: ${grade}`);
              if (verbosity >= 2) console.log(`Summary for ${file}: ${initialFeedback}`);
            } else {
              if (verbosity >= 1) console.log('Error: No revised content found in the response');
            }

            // After processing, update the 'processed' flag to true
            const updatedContent = matter.stringify(revisedContent, { ...metadata, processed: true, grade: grade });
            fs.writeFileSync(file, updatedContent, 'utf8');
          }
        } else {
          if (verbosity >= 1) console.log('No staged .mdx files found.');
        }

        // Check for whitespace errors
        await execAsync(`git diff-index --check --cached ${against}`);

        // Remind user to review and stage the changed files
        if (verbosity >= 1) console.log('Please review the updated files and stage them if they are correct.');
      } catch (error) {
        console.error('Pre-commit hook failed:', error);
        process.exit(1);
      }
    }

    run();

Conclusion

By following these steps, you can automate the process of validating and grading your content's quality using AI, specifically GPT-4o. This pre-commit hook, written in TypeScript, ensures your content meets quality standards before you commit, and it manages state with markdown metadata.

For more information on the AI technology used, you can refer to OpenAI's GPT-4o.

And of course, we can further improve guidelines and grading system.

Remember, good content is key! And, with a little help from AI, creating top-notch articles becomes a breeze.

← Back to posts

We use cookies to improve your experience and analyze our traffic. By using our site, you consent to our use of cookies. You can manage your preferences below: