paint-brush
GitHub Sorun Düzeltmelerini Otomatikleştirmek için Nasıl Bir Yapay Zeka Programcısı Oluşturdum 🤯ile@sunilkumardash9
486 okumalar
486 okumalar

GitHub Sorun Düzeltmelerini Otomatikleştirmek için Nasıl Bir Yapay Zeka Programcısı Oluşturdum 🤯

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

Çok uzun; Okumak

Typescript kullanarak GitHub iş akışlarını otomatikleştirmek için yapay zeka destekli bir SWE aracısının nasıl oluşturulacağını keşfedin. Bu kılavuz, belgeleri güncelleme, hataları düzeltme ve yamaları gönderme gibi görevleri yerine getirebilen ve geliştiricilerin daha yaratıcı çalışmalara odaklanmasını sağlayan özerk bir aracının kurulumunu, bileşenlerini ve uygulanmasını kapsar.
featured image - GitHub Sorun Düzeltmelerini Otomatikleştirmek için Nasıl Bir Yapay Zeka Programcısı Oluşturdum 🤯
Sunil Kumar Dash HackerNoon profile picture


Geçtiğimiz birkaç hafta boyunca Composio'da hızla büyüyen bir veri havuzu üzerinde özenle çalışıyoruz. ReadMes'i güncellemek, belge dizelerini düzeltmek ve küçük hata düzeltmeleri yapmak gibi görevlerin (tekrarlayan ve sıradan olsa da) bant genişliğimizin çoğunu tükettiğini çok geçmeden fark ettik.


O halde neden bu zorlu işlerin üstesinden gelmek için yapay zeka destekli otonom bir aracı oluşturmayayım diye düşündüm.

Bunu yapabilen bir yapay zeka ajanı istedik.


  • GitHub deposuna erişin.
  • Herhangi bir sorunu alın ve bunun için bir çözüm yazın.
  • Gerekirse kodun iyi olup olmadığını kontrol etmek için çalıştırın.
  • Son olarak yama dosyalarını uzak depoya gönderin.


Son olarak, yazılım mühendisliği aracıları oluşturmak için basit ve genişletilebilir bir meta çerçeve oluşturduk.

Bu ajanlar, bu tür birçok görevde insan meslektaşlarına benzer şekilde performans gösterebilir. Sıradan görevleri bu aracılara devretmek, geliştiricilerinize daha yaratıcı görevlere odaklanmaları için zaman kazandırmak açısından mantıklıdır.


Jerry


Bu makalede, GitHub iş akışlarınızı otomatikleştirmek için Typescript'te nasıl bir SWE aracısı oluşturulacağını göstereceğim.

Ancak ondan önce yapay zeka ve SWE ajanlarının bile ne olduğunu anlayalım.


Yapay Zeka Aracıları nedir?

Yapay zeka aracıları, görevleri özerk bir şekilde gerçekleştirebilen, çevreleriyle etkileşime girebilen ve programlamalarına ve işledikleri verilere dayalı olarak kararlar alabilen, yapay zeka modelleri tarafından desteklenen sistemlerdir.

Yapay Zeka Aracılarının Bileşenleri

Bir yapay zeka aracısı üç önemli bileşenden oluşur:

  • LLM'ler : Büyük Dil Modeli, akıl yürütme, karar verme, araç çağırma vb.'den sorumludur.
  • Bellek : İş akışlarını takip etmek için kısa vadeli ve uzun vadeli bilgileri yönetir.
  • Araçlar : Depolardan bilgi çıkarmak ve gerekli değişiklikleri yapmak için GitHub aracı gibi harici ortamla etkileşimi etkinleştirin.

SWE Ajanları nedir?

Peki ne zaman bir AI ajanına SWE ajanı diyorsunuz?

SWE aracıları, bir insan yazılım mühendisinin niteliklerini ve özelliklerini taklit eden yapay zeka aracılarıdır;

  • Uzun vadeli planlama ve muhakeme.
  • Standart geliştirici araçlarını kullanma.
  • Test ve geri bildirim yoluyla kod kalitesini artırma.
  • Sorunları bağımsız olarak hata ayıklama ve çözme.

güzel

Genel Bakış SWE Temsilcisi

Oluşturacağımız SWE aracısının bazı özellikleri şunlardır:

  • Çerçeveden bağımsızdır, dolayısıyla LangChain, OpenAI SDK vb. gibi herhangi bir çerçeveyi kullanabilirsiniz.
  • Çok yönlülüğünü artırmak için internet erişimi için Tavily gibi araçlar ekleyebilirsiniz.


SWE aracıları, genel ve özel depolarınıza erişebilir, sağlanan sorunlar üzerinde çalışabilir ve değişiklikleri depolara iletebilir.

Ana makineyi, Docker'ı veya başka herhangi bir bulut ortamını (E2B, FlyIo) kullanarak kodları çalıştırabilir. Ancak, korumalı alanda kod yürütme için son ikisini kullanmayı tercih etmeniz en iyisi olacaktır.


Korumalı alan oluşturma, rastgele kod yürütmenin istenmeyen sonuçlarını önlemeye yardımcı olur.


SWE Aracısı için önkoşullar

Aracıyı başarıyla oluşturmanın önkoşulları şunlardır:

  1. OpenAI API anahtarı: GPT modellerine erişmek ve araç çağrılarını düzenlemek için OpenAI SDK'yı kullanacağız.
  2. GitHub Erişim Simgesi: GitHub hesabınızı bir kullanarak bağlamanız gerekir. kişisel erişim belirteci SWE aracısının kod deponuza erişmesini ve değiştirmesini sağlamak için.
  3. Composio API anahtarı: Ayrıca Composio'dan bir API anahtarına da ihtiyacınız olacak. Bir tane almak için bir kullanıcı oluşturun hesap Composio ile kontrol panelindeki Ayarlar sekmesine gidin.

Giriş sayfası


Haydi Başlayalım 🔥

Bağımlılıklar

Favori paket yöneticinizi kullanarak bağımlılıkları yükleyerek başlayın. Önerilen yöntem pnpm ancak npm veya yarn de kullanabilirsiniz.

 pnpm install -g composio-core

Ortam Değişkenlerini Ayarlayın 🌐

Projeyi tamamlamak için GITHUB_ACCESS_TOKEN, OPENAI_API_KEY, COMPOSIO_API_KEY, GITHUB_USERNAME ve GITHUB_USER_EMAIL'e ihtiyacınız olacak.


Bu nedenle bir .env dosyası oluşturun ve yukarıdaki değişkenleri ekleyin.

 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"

Proje Yapısı 📁

Proje şu şekilde organize edilmiştir:

kaynak
├── aracılar
│ └── tatlılar
├── uygulama.ts
├── istemleri.ts
└── utils.ts

İşte dosyaların kısa bir açıklaması.

  • Agents/swe.ts : SWE aracısının uygulamasını içerir.
  • app.ts : Uygulamanın ana giriş noktası.
  • Prompts.ts : Aracılar tarafından kullanılan istemleri tanımlar.
  • utils.ts : Proje boyunca kullanılan yardımcı işlevler.

Hızlı bir şekilde başlamak için bu depoyu kopyalayın ve bağımlılıkların geri kalanını yükleyin.

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


Artık tüm kurulumu tamamladığınıza göre. Yapay zeka aracımızı kodlayalım.


kodlayıcı pepe



İstemleri ve Hedefleri Tanımlamak 🎯

SWE aracısı için istemleri ve hedefleri tanımlayarak başlıyoruz. Bu tanımlar aracının performansını ve yürütmesini önemli ölçüde etkilediğinden, her adımı ayrıntılı olarak açıklamak çok önemlidir.

Eğer henüz yapmadıysanız bir prompts.ts dosyası oluşturun.

Daha sonra aracının rolünü ve amacını tanımlayın.

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


Burada rolü SWE olarak tanımladık ve amaç herhangi bir kodlama sorununu düzeltmek ve filetool_git_patch kullanarak düzeltme için bir yama oluşturmaktır. Bu, yama dosyaları oluşturmaya yönelik GitHub entegrasyonuna yönelik bir Compsoio Eylemidir.

Şimdi Swe ajanının arka planını ve açıklamasını tanımlayın.

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

Yukarıdaki kod bloğunda, aracının görevi gerçekleştirmek için atması gereken adımları dikkatli ve açık bir şekilde tanımladık. Bu, aracının ortak programlama engelleriyle karşılaştığında ne yapacağını bilmesini sağlamak için önemlidir.


Yardımcı Fonksiyonların Tanımlanması 🛠️

Bu bölümde from GitHub ve getBranchNameFromIssue bir sorunla ilgili bilgileri çıkaracak iki ana işlevi tanımlayacağız.

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

İşte yukarıdaki kod bloğunda neler oluyor.

  • readUserInput : Bu işlev, komut satırından kullanıcı girişini okur. Yalnızca GitHub kullanıcı kimliğine, depo adına ve sayı numarasına veya açıklamaya ihtiyacımız var.
  • createGithubIssueValidator : Bu işlev GitHub sorunları için bir doğrulayıcı döndürür. Girişi bir dosya yolu, sayısal bir sorun kimliği veya düz bir dize açıklaması olarak işleyebilir. Giriş sayısal bir sorun kimliği ise Composio'nun github_issues_get eylemini kullanarak sorunun ayrıntılarını GitHub'dan alır.
  • fromGitHub : Bu işlev, bir GitHub deposu ve bir sorun hakkında gerekli bilgileri toplamak ve doğrulamak için bu öğeleri birleştirir.

Şimdi sorun açıklamasından bir dal adı oluşturmak için getBranchNameFromIssue tanımlayın.

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

İsveç Temsilcisini Tanımlamak 🤖

Bu, OpenAI asistanlarını ve Composio araç setlerini kullanarak Swe aracısını tanımlayacağınız en önemli bölümdür.

Bu nedenle, önce kütüphaneleri içe aktarın ve LLM'yi ve araçları tanımlayın.

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

Yukarıdaki kod bloğunda,

  • API anahtarıyla bir OpenAI örneği oluşturduk.
  • Ayrıca, workspaceConfig Docker olarak ayarlandığı bir OpenAIToolSet örneği de oluşturduk. Bunun amacı, Swe aracısının kodlama ortamını korumalı alana almak için Docker'ı kullanmaktır. Ayrıca E2B ve FlyIo gibi bulut kodu yorumlayıcılarını da kullanabilirsiniz.

Şimdi Swe Agent’ı tanımlayacağız.

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

Yukarıdaki kod bloğunda neler oluyor.

  • Araçları Al : filetool , file edit tool ve shelltool için Composio araç setinden araçları getirir. Adından da anlaşılacağı gibi bunlar dosyalara erişmek, dosyaları düzenlemek ve komutları yürütmek için kabuk kullanmak için kullanılacaktır.
  • Kırpma Aracı Açıklamaları : Araç açıklamalarını maksimum 1024 karakterle sınırlar.
  • Boş Değerleri Güncelle : Araç konfigürasyonlarındaki boş değerleri boş dizilerle değiştirir.
  • Asistan İş Parçacığı Oluştur : Önceden tanımlanmış istemlerle bir OpenAI asistan iş parçacığı başlatır.
  • İade Bildirimi : Başlatılan araçları, yardımcı iş parçacığını, OpenAI örneğini ve Composio araç setini sağlar.

Uygulamaya Giriş Noktasını Tanımlama 🚀

Uygulamanın giriş noktasını tanımladığımız son bölümdür. Bu nedenle ortam değişkenlerini yükleyin ve gerekli modülleri içe aktarın.

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

Kod bloğu

  • Ortam değişkenlerini yükler.
  • Gerekli yardımcı program işlevlerini içe aktarır.
  • Daha önce tanımladığımız Swe Temsilcisini ve aracı Hedefini içe aktarır.

Şimdi main fonksiyonu tanımlayalım.

 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();


Bu, aracı iş akışını yürütmek için kullanılacak olan tam app.ts dosyamızdır.


Yani yukarıdaki kodda neler oluyor.

  • SWE Aracısını Başlat : Asistan iş parçacığını, OpenAI örneğini, araçları ve Composio araç setini almak için initSWEAgent çağırır.
  • Depoyu ve Sayıyı Getir : fromGithub depo ve sorun ayrıntılarını getirir.
  • Asistan Oluştur : Talimatlar, araçlar ve dil modeliyle bir OpenAI asistanını başlatır.
  • Sorunu Asistana Gönder : Sorunun içeriğini asistan dizisine mesaj olarak gönderir.
  • Çalıştırma Asistanı ve Anket : Asistanı çalıştırır ve araç çağrısı yanıtları için yoklama yapar. Anket yanıtları hakkında daha fazla bilgi için bkz. OpenAI SDK deposu.
  • Yama Eylemini Yürüt : Bir yama oluşturmak için filetool_git_patch çalıştırır.
  • Yama Yanıtını İşle : Bir yama oluşturulursa, onu günlüğe kaydedin, bir dal oluşturun, onaylayın ve değişiklikleri iletin. Çekme isteği oluşturmadan önce 2 saniye bekleyin. GitHub'da bir çekme isteği oluşturun.
  • Çalışma Alanını Kapat : Composio araç seti çalışma alanını kapatır.
  • Ana İşlevi Çalıştır : Yukarıdaki adımları yürütmek için main() öğesini çağırır.


Şimdi uygulamayı pnpm start kullanarak çalıştırın.


Bu sizden GitHub kullanıcı kimliğini, depo adını ve ele almak istediğiniz sorunun kimliğini veya açıklamasını girmenizi isteyecektir.

Tamamlandığında kayıt defterinden bir Composio Docker konteyneri çekecek ve sorun üzerinde çalışmaya başlayacaktır.


Son olarak iş akışı tamamlandığında yama uzak depoya aktarılacaktır. Artık GitHub deponuzu açtığınızda sorun için önerilen düzeltmeyi içeren yeni bir şube göreceksiniz. Ana dal ile karşılaştırıp pull request oluşturabilirsiniz.
teşekkür ederim Mike Scott

Kodun tamamını bulabilirsiniz burada GitHub'da .


Sonraki Adımlar ⏭️

Bu SWE aracısının en iyi yanı, Composio araçlarını ve entegrasyonlarını kullanarak yeteneklerini genişletebilmenizdir.

Yürütme tamamlandığında size bildirimde bulunması için temsilcinize Slack veya Discord'u ekleyebilirsiniz. Ayrıca aracının etkinliklerine göre görevleri otomatik olarak oluşturmak ve güncellemek için Jira veya Linear'ı da bağlayabilirsiniz.


Haydi bağlanalım! 🔌

Bakımcılarla iletişim kurmak ve açık kaynak geliştirici olarak katkıda bulunmak için topluluğumuza katılabilirsiniz. Composio ile ilgili katkıda bulunmak ve sorunlar oluşturmak için GitHub depomuzu ziyaret etmekten çekinmeyin. Dev.

Kompozisyona yıldız ekleyin. geliştirici deposu ⭐

repoyu yıldızla


Okuduğunuz için teşekkürler!