paint-brush
Как я создал программатор искусственного интеллекта для автоматизации исправления проблем на GitHub 🤯к@sunilkumardash9
514 чтения
514 чтения

Как я создал программатор искусственного интеллекта для автоматизации исправления проблем на GitHub 🤯

к Sunil Kumar Dash16m2024/08/01
Read on Terminal Reader

Слишком долго; Читать

Узнайте, как создать агент SWE на базе искусственного интеллекта для автоматизации рабочих процессов GitHub с помощью Typescript. В этом руководстве описывается настройка, компоненты и реализация автономного агента, который может выполнять такие задачи, как обновление документации, исправление ошибок и установка исправлений, что позволяет разработчикам сосредоточиться на более творческой работе.
featured image - Как я создал программатор искусственного интеллекта для автоматизации исправления проблем на GitHub 🤯
Sunil Kumar Dash HackerNoon profile picture


Последние несколько недель мы усердно работали над быстрорастущим репозиторием в Composio . Вскоре мы поняли, что такие задачи, как обновление ReadMe, исправление строк документации и исправление мелких ошибок — хотя и повторяющиеся и рутинные — потребляют большую часть нашей пропускной способности.


Итак, я подумал, почему бы не создать автономный агент на базе искусственного интеллекта, который бы выполнял эту тяжелую работу?

Нам нужен был ИИ-агент, который мог бы это сделать.


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


Наконец, мы создали простую и расширяемую мета-инфраструктуру для создания агентов разработки программного обеспечения.

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


Джерри


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

Но перед этим давайте разберемся, что такое вообще агенты AI и SWE.


Что такое ИИ-агенты?

Агенты ИИ — это системы, основанные на моделях ИИ, которые могут автономно выполнять задачи, взаимодействовать со своей средой и принимать решения на основе своего программирования и данных, которые они обрабатывают.

Компоненты ИИ-агентов

Агент ИИ состоит из трех важнейших компонентов:

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

Что такое агенты SWE?

Итак, когда вы называете агента ИИ агентом SWE?

Агенты SWE — это агенты искусственного интеллекта, которые имитируют качества и характеристики человека-разработчика программного обеспечения, например:

  • Долгосрочное планирование и обоснование.
  • Использование стандартных инструментов разработчика.
  • Улучшение качества кода посредством тестирования и обратной связи.
  • Самостоятельная отладка и решение проблем.

свекит

Обзор агента SWE

Вот некоторые характеристики агента SWE, который мы собираемся создать:

  • Он не зависит от фреймворка, поэтому вы можете использовать любой фреймворк, например LangChain, OpenAI SDK и т. д.
  • Вы можете добавить инструменты, чтобы расширить его универсальность, например Tavily для доступа в Интернет.


Агенты SWE могут получать доступ к вашим общедоступным и частным репозиториям, работать над предоставленными проблемами и вносить изменения в репозитории.

Он может выполнять коды, используя хост-машину, Docker или любую другую облачную среду (E2B, FlyIo). Однако было бы лучше, если бы вы предпочли использовать последние два для выполнения кода в песочнице.


Песочница помогает предотвратить любые непредвиденные последствия выполнения произвольного кода.


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

Вот предварительные условия для успешной сборки агента:

  1. Ключ OpenAI API: мы будем использовать OpenAI SDK для доступа к моделям GPT и оркестрации вызовов инструментов.
  2. Токен доступа GitHub: вы должны связать свою учетную запись GitHub с помощью токен личного доступа чтобы позволить агенту SWE получить доступ и изменить ваш репозиторий кода.
  3. Ключ API Composio: вам также понадобится ключ API от Composio. Чтобы получить его, создайте пользователя счет с помощью Composio и перейдите на вкладку «Настройки» на панели инструментов.

страница авторизации


Давайте начнем 🔥

Зависимости

Начните с установки зависимостей с помощью вашего любимого менеджера пакетов. Рекомендуемый метод — pnpm , но вы также можете использовать npm или yarn .

 pnpm install -g composio-core

Настройте переменные среды 🌐

Для завершения проекта вам понадобятся GITHUB_ACCESS_TOKEN, OPENAI_API_KEY, COMPOSIO_API_KEY, GITHUB_USERNAME и GITHUB_USER_EMAIL.


Итак, создайте файл .env и добавьте указанные выше переменные.

 GITHUB_ACCESS_TOKEN="your access token" OPENAI_API_KEY="openai_key" COMPOSIO_API_KEY="composio-api-key" GITHUB_USER_NAME="GitHub username" GITHUB_USER_EMAIL="GitHub user email"

Структура проекта 📁

Проект организован следующим образом:

источник
├── агенты
│ └── сладости
├── app.ts
├── подсказки.ts
└── utils.ts

Вот краткое описание файлов.

  • агенты/swe.ts : содержит реализацию агента SWE.
  • app.ts : основная точка входа приложения.
  • Prompts.ts : определяет подсказки, используемые агентами.
  • utils.ts : служебные функции, используемые в проекте.

Чтобы начать быстро, клонируйте этот репозиторий и установите остальные зависимости.

 git clone https://github.com/ComposioHQ/swe-js-template.git swe-js cd swe-js && pnpm i


Теперь, когда вы закончили всю настройку. Давайте напишем наш ИИ-агент.


кодер Пепе



Определение подсказок и целей 🎯

Начнем с определения задач и целей агента SWE. Подробное объяснение каждого шага имеет решающее значение, поскольку эти определения существенно влияют на производительность и выполнение агента.

Итак, создайте файл prompts.ts если вы этого еще не сделали.

Далее определите роль и цель агента.

 export const ROLE = "Software Engineer"; export const GOAL = "Fix the coding issues given by the user, and finally generate a patch with the newly created files using `filetool_git_patch` tool";


Здесь мы определили роль как SWE, и цель — исправить любую проблему с кодированием и создать исправление для исправления с помощью filetool_git_patch . Это действие Compsoio для интеграции GitHub для создания файлов исправлений.

Теперь определите предысторию и описание агента Швеции.

 export const BACKSTORY = `You are an autonomous programmer; your task is to solve the issue given in the task with the tools in hand. Your mentor gave you the following tips. 1. Please clone the github repo using the 'FILETOOL_GIT_CLONE' tool, and if it already exists - you can proceed with the rest of the instructions after going into the directory using \`cd\` shell command. 2. PLEASE READ THE CODE AND UNDERSTAND THE FILE STRUCTURE OF THE CODEBASE USING GIT REPO TREE ACTION. 3. POST THAT READ ALL THE RELEVANT READMES AND TRY TO LOOK AT THE FILES RELATED TO THE ISSUE. 4. Form a thesis around the issue and the codebase. Think step by step. Form pseudocode in case of large problems. 5. THEN TRY TO REPLICATE THE BUG THAT THE ISSUES DISCUSS. - If the issue includes code for reproducing the bug, we recommend that you re-implement that in your environment, and run it to make sure you can reproduce the bug. - Then start trying to fix it. - When you think you've fixed the bug, re-run the bug reproduction script to make sure that the bug has indeed been fixed. - If the bug reproduction script does not print anything when it is successfully runs, we recommend adding a print("Script completed successfully, no errors.") command at the end of the file so that you can be sure that the script indeed, it ran fine all the way through. 6. If you run a command that doesn't work, try running a different one. A command that did not work once will not work the second time unless you modify it! 7. If you open a file and need to get to an area around a specific line that is not in the first 100 lines, say line 583, don't just use the scroll_down command multiple times. Instead, use the goto 583 command. It's much quicker. 8. If the bug reproduction script requires inputting/reading a specific file, such as buggy-input.png, and you'd like to understand how to input that file, conduct a search in the existing repo code to see whether someone else has I've already done that. Do this by running the command find_file "buggy-input.png" If that doesn't work, use the Linux 'find' command. 9. Always make sure to look at the currently open file and the current working directory (which appears right after the currently open file). The currently open file might be in a different directory than the working directory! Some commands, such as 'create', open files, so they might change the currently open file. 10. When editing files, it is easy to accidentally specify a wrong line number or write code with incorrect indentation. Always check the code after You issue an edit to ensure it reflects what you want to accomplish. If it didn't, issue another command to fix it. 11. When you FINISH WORKING on the issue, USE THE 'filetool_git_patch' ACTION with the new files using the "new_file_paths" parameters created to create the final patch to be submitted to fix the issue. Example, if you add \`js/src/app.js\`, then pass \`new_file_paths\` for the action like below, { "new_file_paths": ["js/src/app.js"] } `; export const DESCRIPTION = `We're solving the following issue within our repository. Here's the issue text: ISSUE: {issue} REPO: {repo} Now, you're going to solve this issue on your own. When you're satisfied with all your changes, you can submit them to the code base by simply running the submit command. Note, however, that you cannot use any interactive session commands (eg python, vim) in this environment, but you can write scripts and run them. Eg you can write a Python script and then run it with \`python </path/to/script>.py\`. If you face a "module not found error", you can install dependencies. Example: in case the error is "pandas not found", install pandas like this \`pip install pandas\` Respond to the human as helpfully and accurately as possible`;

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


Определение служебных функций 🛠️

В этом разделе мы определим две основные функции from GitHub и getBranchNameFromIssue , которые будут извлекать информацию о проблеме.

 import * as fs from 'fs'; import * as path from 'path'; import * as readline from 'readline'; import { ComposioToolSet } from "composio-core/lib/sdk/base.toolset"; import { nanoid } from "nanoid"; type InputType = any; function readUserInput( prompt: string, metavar: string, validator: (value: string) => InputType ): InputType { const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); return new Promise<InputType>((resolve, reject) => { rl.question(`${prompt} > `, (value) => { try { const validatedValue = validator(value); rl.close(); resolve(validatedValue); } catch (e) { console.error(`Invalid value for \`${metavar}\` error parsing \`${value}\`; ${e}`); rl.close(); reject(e); } }); }); } function createGithubIssueValidator(owner: string, name: string, toolset: ComposioToolSet) { return async function githubIssueValidator(value: string): Promise<string> { const resolvedPath = path.resolve(value); if (fs.existsSync(resolvedPath)) { return fs.readFileSync(resolvedPath, 'utf-8'); } if (/^\d+$/.test(value)) { const responseData = await toolset.executeAction('github_issues_get', { owner, repo: name, issue_number: parseInt(value, 10), }); return responseData.body as string; } return value; }; } export async function fromGithub(toolset: ComposioToolSet): Promise<{ repo: string; issue: string }> { const owner = await readUserInput( 'Enter github repository owner', 'github repository owner', (value: string) => value ); const name = await readUserInput( 'Enter github repository name', 'github repository name', (value: string) => value ); const repo = `${owner}/${name.replace(",", "")}`; const issue = await readUserInput( 'Enter the github issue ID or description or path to the file containing the description', 'github issue', createGithubIssueValidator(owner, name, toolset) ); return { repo, issue }; }

Итак, вот что происходит в приведенном выше блоке кода.

  • readUserInput : эта функция считывает вводимые пользователем данные из командной строки. Нам нужен только идентификатор пользователя GitHub, имя репозитория и номер или описание проблемы.
  • createGithubIssueValidator : эта функция возвращает валидатор для проблем GitHub. Он может обрабатывать входные данные в виде пути к файлу, числового идентификатора проблемы или простого строкового описания. Если входные данные представляют собой числовой идентификатор проблемы, они извлекают сведения о проблеме из GitHub с помощью действия Composio github_issues_get .
  • fromGitHub : эта функция объединяет эти элементы для сбора и проверки необходимой информации о репозитории GitHub и проблеме.

Теперь определите getBranchNameFromIssue , чтобы создать имя ветки из описания проблемы.

 export function getBranchNameFromIssue(issue: string): string { return "swe/" + issue.toLowerCase().replace(/\s+/g, '-') + "-" + nanoid(); }

Определение агента Swe 🤖

Это самый важный раздел, в котором вы определите агент Swe с помощью помощников OpenAI и наборов инструментов Composio.

Итак, сначала импортируйте библиотеки и определите LLM и инструменты.

 import { OpenAIToolSet, Workspace } from 'composio-core'; import { BACKSTORY, DESCRIPTION, GOAL } from '../prompts'; import OpenAI from 'openai'; // Initialize tool. const llm = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, }); const composioToolset = new OpenAIToolSet({ workspaceConfig: Workspace.Docker({}) }); // To use E2B Code interpreter /* const composioToolset = new OpenAIToolSet({ workspaceConfig: Workspace.E2B({ apiKey: process.env.E2B_API_KEY, }) }); */

В приведенном выше блоке кода

  • Мы создали экземпляр OpenAI с ключом API.
  • Мы также создали экземпляр OpenAIToolSet с workspaceConfig установленным в Docker. Это делается для использования Docker для изолированной среды кодирования для агента Swe. Вы также можете использовать интерпретаторы облачного кода, такие как E2B и FlyIo.

Теперь мы определим агента Swe.

 export async function initSWEAgent(): Promise<{composioToolset: OpenAIToolSet; assistantThread: OpenAI.Beta.Thread; llm: OpenAI; tools: Array<any>}> { let tools = await composioToolset.getTools({ apps: [ "filetool", "fileedittool", "shelltool" ], }); tools = tools.map((a) => { if (a.function?.description?.length || 0 > 1024) { a.function.description = a.function.description?.substring(0, 1024); } return a; }); tools = tools.map((tool) => { const updateNullToEmptyArray = (obj) => { for (const key in obj) { if (obj[key] === null) { obj[key] = []; } else if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) { updateNullToEmptyArray(obj[key]); } } }; updateNullToEmptyArray(tool); return tool; }); const assistantThread = await llm.beta.threads.create({ messages: [ { role: "assistant", content:`${BACKSTORY}\n\n${GOAL}\n\n${DESCRIPTION}` } ] }); return { assistantThread, llm, tools, composioToolset }; }

Вот что происходит в приведенном выше блоке кода.

  • Получить инструменты : извлекает инструменты из набора инструментов Composio для filetool , file edit tool и shelltool . Как следует из названия, они будут использоваться для доступа к файлам, редактирования файлов и использования оболочки для выполнения команд.
  • Описания инструментов обрезки : ограничивает описание инструментов максимум 1024 символами.
  • Обновить нулевые значения : заменяет нулевые значения в конфигурациях инструмента пустыми массивами.
  • Создать поток помощника : инициирует поток помощника OpenAI с предопределенными подсказками.
  • Оператор возврата : предоставляет инициализированные инструменты, поток помощника, экземпляр OpenAI и набор инструментов Composio.

Определение точки входа в приложение 🚀

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

 import dotenv from "dotenv"; dotenv.config(); import { fromGithub, getBranchNameFromIssue } from './utils'; import { initSWEAgent } from './agents/swe'; import { GOAL } from './prompts';

Блок кода

  • Загружает переменные среды.
  • Импортирует необходимые служебные функции.
  • Импортирует агент Swe и цель агента, которую мы определили ранее.

Теперь определите main функцию.

 async function main() { /**Run the agent.**/ const { assistantThread, llm, tools, composioToolset } = await initSWEAgent(); const { repo, issue } = await fromGithub(composioToolset); const assistant = await llm.beta.assistants.create({ name: "SWE agent", instructions: GOAL + `\nRepo is: ${repo} and your goal is to ${issue}`, model: "gpt-4o", tools: tools }); await llm.beta.threads.messages.create( assistantThread.id, { role: "user", content: issue } ); const stream = await llm.beta.threads.runs.createAndPoll(assistantThread.id, { assistant_id: assistant.id, instructions: `Repo is: ${repo} and your goal is to ${issue}`, tool_choice: "required" }); await composioToolset.waitAndHandleAssistantToolCalls(llm as any, stream, assistantThread, "default"); const response = await composioToolset.executeAction("filetool_git_patch", { }); if (response.patch && response.patch?.length > 0) { console.log('=== Generated Patch ===\n' + response.patch, response); const branchName = getBranchNameFromIssue(issue); const output = await composioToolset.executeAction("SHELL_EXEC_COMMAND", { cmd: `cp -r ${response.current_working_directory} git_repo && cd git_repo && git config --global --add safe.directory '*' && git config --global user.name ${process.env.GITHUB_USER_NAME} && git config --global user.email ${process.env.GITHUB_USER_EMAIL} && git checkout -b ${branchName} && git commit -m 'feat: ${issue}' && git push origin ${branchName}` }); // Wait for 2s await new Promise((resolve) => setTimeout(() => resolve(true), 2000)); console.log("Have pushed the code changes to the repo. Let's create the PR now", output); await composioToolset.executeAction("GITHUB_PULLS_CREATE", { owner: repo.split("/")[0], repo: repo.split("/")[1], head: branchName, base: "master", title: `SWE: ${issue}` }) console.log("Done! The PR has been created for this issue in " + repo); } else { console.log('No output available - no patch was generated :('); } await composioToolset.workspace.close(); } main();


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


Итак, вот что происходит в приведенном выше коде.

  • Инициализация агента SWE : вызывает initSWEAgent , чтобы получить поток помощника, экземпляр OpenAI, инструменты и набор инструментов Composio.
  • Извлечь репозиторий и проблему : извлекает сведения о репозитории и проблеме из fromGithub .
  • Create Assistant : инициализирует помощник OpenAI с инструкциями, инструментами и языковой моделью.
  • Отправить задачу помощнику : отправляет содержимое задачи в виде сообщения в ветку помощника.
  • Запустить помощник и опрос : запускает помощник и опрашивает ответы на вызовы инструментов. Дополнительную информацию об ответах на опрос см. Репозиторий OpenAI SDK.
  • Действие «Выполнить исправление» : выполняет filetool_git_patch для создания исправления.
  • Обработка ответа на исправление . Если исправление создано, зарегистрируйте его, создайте ветку, зафиксируйте и отправьте изменения. Подождите 2 секунды, прежде чем создавать запрос на включение. Создайте запрос на включение на GitHub.
  • Закрыть рабочую область : закрывает рабочую область набора инструментов Composio.
  • Запуск основной функции : вызывает main() для выполнения вышеуказанных шагов.


Теперь запустите приложение, используя pnpm start .


Вам будет предложено ввести идентификатор пользователя GitHub, имя репозитория и идентификатор проблемы или описание проблемы, которую вы хотите решить.

После завершения он извлечет контейнер Composio Docker из реестра и начнет работать над проблемой.


Наконец, когда рабочий процесс будет завершен, патч будет отправлен в удаленный репозиторий. Теперь, когда вы откроете свой репозиторий GitHub, вы увидите новую ветку с предлагаемым исправлением проблемы. Вы можете сравнить его с основной веткой и создать запрос на включение.
спасибо, Майк Скотт

Вы можете найти полный код здесь, на GitHub .


Следующие шаги ⏭️

Самое лучшее в этом агенте SWE — то, что вы можете расширить его возможности с помощью инструментов и интеграций Composio.

Вы можете добавить Slack или Discord к своему агенту, чтобы уведомлять вас о завершении выполнения. Вы также можете подключить Jira или Linear для автоматического создания и обновления задач на основе активности агента.


Давайте соединимся! 🔌

Вы можете присоединиться к нашему сообществу, чтобы взаимодействовать с сопровождающими и вносить свой вклад в качестве разработчика с открытым исходным кодом. Не стесняйтесь посетить наш репозиторий GitHub, чтобы внести свой вклад и создать проблемы, связанные с Composio. Дев.

Звезда композиции. репозиторий разработчиков ⭐

пометить репо


Спасибо за чтение!