Создание AI-рецензента статей с использованием платформы Gradient и GitHub

Создание AI-рецензента статей с использованием платформы Gradient и GitHub


Введение

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

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

Предварительные требования

  • Вводные знания по yaml для создания действия GitHub.
  • Рабочие знания JavaScript.
  • Учетная запись DigitalOcean для использования платформы Gradient для обучения GitHub Action соответственно.

В чем проблема и как ее решить?

Отзывы требуют времени и обычно выполняются вручную с некоторыми проверками. Ручные проверки могут занимать больше времени, когда объем работы велик, что добавляет к накоплению.

Вы разработаете GitHub-экшн, который использует ИИ, обученный на ваших технических руководствах и документации. Он изучает стиль письма вашей компании или команды и затем предлагает изменения соответственно. Это значительно сокращает время на обзор с нескольких дней до нескольких секунд.

Вот как работает действие GitHub:

GitHub-экшен уже доступен на маркетплейсе, так что вам не нужно создавать его с нуля. Вы можете использовать его прямо в своих репозиториях, обученных на ваших данных.

Это будет включать два основных шага:

  1. Развертывание агента DigitalOcean Gradient, обученного на ваших уроках.
  2. Добавление файла рабочего процесса в ваши репозитории для использования действия GitHub.

Создание агента DigitalOcean Gradient

На этом этапе мы увидим, как мы можем создать агент Gradient, который будет просматривать файлы markdown, которые вы коммитите, и давать рекомендации на основе вашего стиля письма.

Вам необходимо добавить и индексировать базу знаний, чтобы обеспечить обучение агента по вашим руководствам.

  • После входа в DigitalOcean перейдите на платформу Gradient и на вкладке Базы знаний нажмите на Создать базу знаний.

  • Дайте ему имя, а из Выбрать источник данных выберите URL для веб-сканирования. Теперь, в зависимости от того, где находятся ваши учебные материалы или документация, и сколько уровней вы хотите просмотреть, вы можете выбрать Scoped/URL и все связанные страницы в пути/URL и все связанные страницы в домене/поддоменах.

    • В этом примере мы выберем вариант Поддомены, поскольку он является самым широким вариантом и может привести к лучшим результатам. Вы можете выбрать индексировать встроенные медиа, а можете и нет.

  • Затем выберите модель встраивания по вашему выбору и нажмите на Создать базу знаний.
  • Теперь, когда мы создали базу знаний, мы перейдем к созданию агента и ссылке на базу знаний для агента. Для этого:

    • Перейдите к опции Платформа Градиент в левом меню и нажмите Создать агента.

    • Дайте ему уникальное имя и напишите подсказку, что-то похожее на:
    Your task is to check for grammatical errors in an article. Use the knowledge base to learn how the writing style is and make sure to check for these three things: - Look for typos, punctuation errors, and incorrect sentence structures. - Use active voice and avoid passive constructions where possible. - Check for H tags, and trailing spaces. 
    • Выберите модель по своему выбору. В этом примере мы используем Claude 3.5 Sonnet и выбираем базу знаний, которую мы создали на первом шаге.

    • Наконец, нажмите на Создать агента.
    • Это займет несколько минут. После развертывания перейдите в Playground и вставьте файл разметки с неправильной грамматикой и структурой, который не соответствует вашему стилю письма. Вы увидите, что агент отвечает вам проблемами и предложениями, как показано на изображении ниже.

    И так вы завершили обучение и создание ИИ-агента. Это был первый и самый важный шаг.

    Используя GitHub Action

    Теперь, когда агент ИИ создан, следующий шаг — использовать действие GitHub в ваших репозиториях.

    1. Скопируйте конечную точку агента и на вкладке Настройки создайте ключ и сохраните его. Эти данные необходимы для доступа к агенту.

    3. Затем, в вашем репозитории, в папке workflow создайте файл .yml (например, .github/workflows/grammar-check.yml) и вставьте следующий код:

    name: Check Markdown Grammar  on:   pull_request:     types: [opened, synchronize, reopened]     paths:       - '**.md'   workflow_dispatch:  jobs:   check-markdown:     runs-on: ubuntu-latest     steps:       - uses: actions/checkout@v3         with:           fetch-depth: 0         - name: Get changed files         id: changed-files         uses: dorny/paths-filter@v2         with:           filters: |             markdown:               - '**/*.md'               - '!**/node_modules/**'              - name: Check Markdown Grammar         if: steps.changed-files.outputs.markdown == 'true'         uses: Haimantika/article-review-github-action@v1.1.1         with:           do-api-token: ${{ secrets.DO_API_TOKEN }}           do-agent-base-url: ${{ secrets.DO_AGENT_BASE_URL }}           file-pattern: ${{ steps.changed-files.outputs.files_markdown }}           exclude-pattern: '**/node_modules/**,**/vendor/**' 

    4. Чтобы протестировать действие, откройте запрос на извлечение с файлом markdown, и вы увидите, как процесс проверки запускается. Он завершится неудачей, если возникнут какие-либо проблемы; если нет, он пройдет успешно и будет готов к слиянию.

    Создание собственного GitHub Action

    Первый шаг — написать файл рабочего процесса, который автоматически запускает действие при открытии запроса на слияние. Он проверяет грамматику и стиль написания файла markdown с помощью скрипта grammar-checker.js.

    Вот как будет выглядеть код:

    name: Markdown Grammar Checker  on:   pull_request:     types: [opened, synchronize, reopened]     paths:       - '**.md'   workflow_dispatch:  jobs:   grammar-check:     runs-on: ubuntu-latest     steps:       - name: Checkout code         uses: actions/checkout@v3         with:           fetch-depth: 0          - name: Setup Node.js         uses: actions/setup-node@v3         with:           node-version: '18'                  - name: Install dependencies         run: npm install axios                  - name: Get changed files         id: changed-files         uses: dorny/paths-filter@v2         with:           base: ${{ github.event.pull_request.base.sha }}           ref: ${{ github.event.pull_request.head.sha }}           filters: |             markdown:               - '**.md'               - '!**/node_modules/**'        - name: Run grammar checks         if: steps.changed-files.outputs.markdown == 'true'         env:           DO_API_TOKEN: ${{ secrets.DO_API_TOKEN }}           DO_AGENT_BASE_URL: ${{ secrets.DO_AGENT_BASE_URL }}         run: |           echo "Running grammar checks on changed files..."                      # Split the files by newlines           IFS=$'n'           files=($(echo "${{ steps.changed-files.outputs.files_markdown }}"))                      for file in "${files[@]}"; do             echo "Checking grammar in $file..."             node grammar-checker.js "$file"           done 

    Следующий шаг — написать скрипт, который сканирует файлы markdown, упомянутые в запроса на слияние, извлекает из них простой текст, отправляет текст агенту ИИ DigitalOcean для проверки грамматики и сообщает о любых обнаруженных проблемах.

    Вы уже узнали в начале статьи, как создать ИИ-агента, используя DigitalOcean. Так что следуйте этим шагам.

    Код для этого будет следующим:

    #!/usr/bin/env node  const fs = require('fs'); const path = require('path'); const axios = require('axios');  // DigitalOcean AI Agent endpoint and key const AGENT_BASE_URL = process.env.DO_AGENT_BASE_URL || 'https://agent-aaf74f4416df5696a67b-o4npv.ondigitalocean.app';  // Update this to your actual base URL const AGENT_ENDPOINT = `${AGENT_BASE_URL}/api/v1/chat/completions`; const API_TOKEN = process.env.DO_API_TOKEN;  if (!API_TOKEN) {   console.error('Error: DigitalOcean API token not found. Please set the DO_API_TOKEN environment variable.');   process.exit(1); }  // Get all markdown files from the repository const getAllMarkdownFiles = (dir, fileList = [], excludeDirs = ['node_modules', '.git']) => {   const files = fs.readdirSync(dir);      files.forEach(file => {     const filePath = path.join(dir, file);          // Skip excluded directories     if (fs.statSync(filePath).isDirectory()) {       if (!excludeDirs.includes(file)) {         getAllMarkdownFiles(filePath, fileList, excludeDirs);       }     } else if (file.endsWith('.md')) {       fileList.push(filePath);     }   });      return fileList; };  // Extract plain text content from markdown const extractTextFromMarkdown = (content) => {   // Remove YAML front matter   let text = content;   if (content.startsWith('---')) {     const endOfFrontMatter = content.indexOf('---', 3);     if (endOfFrontMatter !== -1) {       text = content.slice(endOfFrontMatter + 3);     }   }      // Remove code blocks   text = text.replace(/```[sS]*?```/g, '');      // Remove HTML tags   text = text.replace(/<[^>]*>/g, '');      // Remove markdown links but keep the text   text = text.replace(/[([^]]+)]([^)]+)/g, '$1');      // Remove images   text = text.replace(/![[^]]*]([^)]+)/g, '');      return text; };  // Function to check grammar using DigitalOcean's AI Agent const checkGrammar = async (text) => {   try {     console.log("Sending request to DigitalOcean AI agent...");          const response = await axios.post(AGENT_ENDPOINT, {       model: "claude-3.5-sonnet",       messages: [         {           role: "system",           content: "You are a skilled editor focused on identifying grammatical errors, typos, incorrect sentence structures, passive voice, and unnecessary jargon."         },         {           role: "user",           content: `Please review the following text for grammatical errors, typos, incorrect sentence structures, passive voice, and unnecessary jargon. For each issue, identify the specific problem, explain why it's an issue, and suggest a correction. Format your response as a JSON array with objects containing: "issue_type", "text_with_issue", "explanation", and "suggestion". Only identify actual issues. If there are no grammatical problems, return an empty array.nnText to review:n${text}`         }       ],       temperature: 0.0,       max_tokens: 1024     }, {       headers: {         'Content-Type': 'application/json',         'Authorization': `Bearer ${API_TOKEN}`       }     });          console.log("Received response from AI agent");          // Parse the AI response to get the JSON data     const aiResponse = response.data.choices[0].message.content;     try {       // Extract JSON from the response (in case there's additional text)       const jsonMatch = aiResponse.match(/[[sS]*]/);       return jsonMatch ? JSON.parse(jsonMatch[0]) : [];     } catch (e) {       console.error('❌ Error parsing AI response:', e);       console.log('AI response:', aiResponse);       return [];     }   } catch (error) {     console.error('❌ Error checking grammar:', error.message);     if (error.response) {       console.error('Response status:', error.response.status);       console.error('Response data:', JSON.stringify(error.response.data, null, 2));     }     return [];   } };  // Process a single markdown file const processFile = async (filePath) => {   try {     console.log(`nChecking grammar in ${filePath}...`);          // Check if file exists     if (!fs.existsSync(filePath)) {       console.error(`❌ Error: File does not exist: ${filePath}`);       return false;     }          const content = fs.readFileSync(filePath, 'utf8');     const textToCheck = extractTextFromMarkdown(content);          // Skip empty files or files with very little text content     if (textToCheck.trim().length < 50) {       console.log(`⚠️ Skipping ${filePath}: Not enough text content to check`);       return true;     }          console.log(`Sending content to grammar check API...`);          const issues = await checkGrammar(textToCheck);          if (issues.length === 0) {       console.log(`✅ ${filePath}: No grammar issues found`);       return true;     } else {       console.log(`⚠️ ${filePath}: Found ${issues.length} grammar issues:`);       issues.forEach((issue, index) => {         console.log(`  ${index + 1}. ${issue.issue_type}: "${issue.text_with_issue}"`);         console.log(`     Explanation: ${issue.explanation}`);         console.log(`     Suggestion: ${issue.suggestion}`);         console.log();       });       return false;     }   } catch (error) {     console.error(`❌ Error processing ${filePath}:`, error.message);     return false;   } };  // Main function to process all markdown files const checkAllFiles = async () => {   // Get files to check - either from command line args or find all   let markdownFiles = [];      if (process.argv.length > 2) {     // Use files passed as arguments     markdownFiles = process.argv.slice(2);     console.log(`Checking grammar in specific file(s): ${markdownFiles.join(', ')}`);   } else {     // Find all markdown files     markdownFiles = getAllMarkdownFiles('.');     console.log(`Found ${markdownFiles.length} markdown files to check for grammar`);   }      if (markdownFiles.length === 0) {     console.log('No files to check.');     return true;   }      let allValid = true;      // Process each file   for (const file of markdownFiles) {     const fileValid = await processFile(file);     if (!fileValid) {       allValid = false;     }   }      return allValid; };  // Run the grammar checker checkAllFiles().then(allValid => {   if (!allValid) {     console.error('n❌ Grammar check failed: Issues were found');     process.exit(1);   } else {     console.log('n✅ Grammar check passed: No issues were found');     process.exit(0);   } }).catch(error => {   console.error('❌ Error running grammar check:', error.message);   process.exit(1); }); 

    Подготовка действия для использования сообществом

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

    После того как это будет сделано, создайте файл action.yml, который определяет метаданные вашего действия:

    name: 'Markdown Grammar Checker' description: 'Checks markdown files for grammar, style, and formatting issues using AI' author: 'Your Name'  inputs:   github-token:     description: 'GitHub token for accessing PR files'     required: true     default: ${{ github.token }}   do-api-token:     description: 'DigitalOcean API token'     required: true   do-agent-base-url:     description: 'DigitalOcean AI agent base URL'     required: true   file-pattern:     description: 'Glob pattern for files to check'     required: false     default: '**/*.md'   exclude-pattern:     description: 'Glob pattern for files to exclude'     required: false     default: '**/node_modules/**'  runs:   using: 'node16'   main: 'index.js'  branding:   icon: 'book'   color: 'blue' 
    • Затем создайте файл index.js, который будет работать с инструментом GitHub Actions.
    • Создайте файл package.json, который содержит все требования.
    • Когда все будет готово, вы можете выпустить и опубликовать это на рынке.
    • Затем, наконец, добавьте файл yml, который пользователи должны добавить в свой файл рабочего процесса, чтобы использовать ваше действие. Он будет выглядеть примерно так:
    name: Check Markdown Grammar  on:   pull_request:     types: [opened, synchronize, reopened]     paths:       - '**.md'   workflow_dispatch:  jobs:   check-markdown:     runs-on: ubuntu-latest     steps:       - uses: actions/checkout@v3         with:           fetch-depth: 0         - name: Get changed files         id: changed-files         uses: dorny/paths-filter@v2         with:           filters: |             markdown:               - '**/*.md'               - '!**/node_modules/**'              - name: Check Markdown Grammar         if: steps.changed-files.outputs.markdown == 'true'         uses: Haimantika/article-review-github-action@v1.1.1         with:           do-api-token: ${{ secrets.DO_API_TOKEN }}           do-agent-base-url: ${{ secrets.DO_AGENT_BASE_URL }}           file-pattern: ${{ steps.changed-files.outputs.files_markdown }}           exclude-pattern: '**/node_modules/**,**/vendor/**' 

    И вот как вы можете создать своё действие GitHub!

    Заключение

    В этом учебном пособии вы узнали, как создать комплексную систему рецензирования статей с использованием платформы Gradient от DigitalOcean и GitHub Actions. Система предназначена для оптимизации процессов рецензирования технических текстов, используя возможности ИИ для проверки грамматических ошибок, предложения улучшений и обеспечения согласованности с стилем письма вашей команды.

    Если вы хотите узнать больше о DigitalOcean, обязательно ознакомьтесь с этими ресурсами:

    • Документация DigitalOcean.
    • YouTube DigitalOcean.
    • Сообщество Discord DigitalOcean.

    Комментарии

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

    Ваш адрес email не будет опубликован. Обязательные поля помечены *