Создание AI-рецензента статей с использованием платформы Gradient и GitHub
Введение
Если вы пишете на профессиональной основе или как хобби, вы могли заметить, что хотя личное письмо может следовать любой структуре, профессиональное письмо должно соответствовать определенным стилевым и письменным руководствам и проходить определенные проверки перед публикацией.
Этот учебник предназначен для тех, кто использует рабочие процессы на базе GitHub и хочет ускорить процесс ревью. Вы научитесь реализовывать решение, которое использует ИИ для ускорения процесса ревью, создавая GitHub-действие, обученное на ваших текстах и стилевых руководствах. Это действие будет проверять наличие проблем, выявлять их и предлагать, как можно улучшить текст.
Предварительные требования
- Вводные знания по yaml для создания действия GitHub.
- Рабочие знания JavaScript.
- Учетная запись DigitalOcean для использования платформы Gradient для обучения GitHub Action соответственно.
В чем проблема и как ее решить?
Отзывы требуют времени и обычно выполняются вручную с некоторыми проверками. Ручные проверки могут занимать больше времени, когда объем работы велик, что добавляет к накоплению.
Вы разработаете GitHub-экшн, который использует ИИ, обученный на ваших технических руководствах и документации. Он изучает стиль письма вашей компании или команды и затем предлагает изменения соответственно. Это значительно сокращает время на обзор с нескольких дней до нескольких секунд.
Вот как работает действие GitHub:
GitHub-экшен уже доступен на маркетплейсе, так что вам не нужно создавать его с нуля. Вы можете использовать его прямо в своих репозиториях, обученных на ваших данных.
Это будет включать два основных шага:
- Развертывание агента DigitalOcean Gradient, обученного на ваших уроках.
- Добавление файла рабочего процесса в ваши репозитории для использования действия 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.












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