自己紹介
こんにちは!ニューヨークでプログラミングを勉強している高校2年生です! qiitaでは学ぶのに苦戦した事や作った物などを日記代わりに書いていきます!僕が作った物が誰かの役に立ったら良いなと思っています!ですが、しょっちゅう間違えた理解をしているのでここに書く事は全部信じないでください!笑
作ったもの:
僕が今回作ったものは "DEBUG-GPT" です! DEBUG-GPTは自動的にエラーメッセージ、コードの全貌、それにプロジェクトのフォルダー構造を理解した上で効果的なエラーの改善方法を提供してくれます!僕はpythonでコードを書いていてエラーが起こるとchatgptに聞くことがよくあります。ですがエラーメッセージだけ提供しても効果的な解決方法が得られることは非常に少ないです!なのでエラーが起こると自動的に色んな情報をChatGPTに送信し、それらを理解した上で効果的なエラーの改善方法を提供してくれたら良いのになと思って作りました!
作った過程
まずopenai apiを使うのに三日ほど苦戦しました笑
なぜかずっと使えなかったのですが"python3 ファイル名"をコマンドで実行すると出来ました笑
そしてまずver1はこんな感じです
import os
import subprocess
import openai
import api_key
openai.api_key = api_key.api_key
# Content_list and activate_file is only thing you are suppposed to change
content_list = ['test.py', 'ask.py']
activate_file = "test.py"
# Content_list and activate_file is only thing you are suppposed to change
code_dict = {}
messages = [
{"role": "system", "content": "You are an assistant that helps with Python debugging."}
]
# Folder tree structure
tree_structure = subprocess.run(['tree', '-L', '3'], capture_output=True, text=True).stdout
messages.append({"role": "assistant", "content": f'Project file structure:\n\n{tree_structure}\n\n'})
# Read file contents
def read_code(file_name):
with open(file_name, 'r') as file:
code = file.read()
return code
for file_name in content_list:
with open(file_name, 'r') as file:
code = read_code(file_name)
code_dict[file_name] = code
messages.append({"role": "assistant", "content": f'Content of each file:\n\n{code_dict}\n\n'})
# Get error code
try:
result = subprocess.run(['python3', '-c', activate_file], capture_output=True, text=True, check=True)
stdout = result.stdout
print(stdout)
except subprocess.CalledProcessError as e:
stderr = e.stderr
messages.append({"role": "assistant", "content": f'Error code generated by executing {activate_file}:\n\n{stderr}\n\n'})
messages.append({"role": "user", "content": 'Please provide a really short summary of why the error occurred and a possible solution.'})
chat_completion = openai.ChatCompletion.create(
model="gpt-3.5-turbo-16k",
messages=messages
)
response = chat_completion["choices"][0]["message"]["content"]
print(response)
debug-gptを作るのにもChtaGPT使用しました。実現したい物を言うとそれにあった関数やmoduleを教えてくれるのですごく便利ですよね!2年前勉強してたときとは学習スピードが全然違います!!
まず
content_list = ['test.py', 'ask.py']
activate_file = "test.py"
を指定します!
content_list
で読み込みたいコード(エラーに関係してそうなファイル)を記述します
activate_file
で実行したいコードを書きます
tree_structure = subprocess.run(['tree', '-L', '3'], capture_output=True, text=True).stdout
ではフォルダー構造を取得します!
def read_code(file_name):
with open(file_name, 'r') as file:
code = file.read()
return code
for file_name in content_list:
with open(file_name, 'r') as file:
code = read_code(file_name)
code_dict[file_name] = code
ここではread_code
関数を指定しています。この関数は引数のfile_name
のコードの全貌を返します。
for文でcontent_list
に指定されたコード全てを最初らへんに指定したcode_dict
に保存していきます。
try:
result = subprocess.run(['python3', '-c', activate_file], capture_output=True, text=True, check=True)
stdout = result.stdout
print(stdout)
except subprocess.CalledProcessError as e:
stderr = e.stderr
これはsubprocess関数でactivate_fileに指定されたファイルを実行するものです。
try文で実行しエラーが起きるとexcept文にジャンプしエラーコードを取得します。取得したエラーコードはstderrに入ります。
そして全てmesseges
のdictに入れopenai apiに投げています。
ダメだったところ
-
なぜか途中からsubprocessが動かなくなりました。よくよく調べてみると、subprocessで実行したファイルでエラーが起こった場合except文にジャンプしないそうです。なぜ最初は動いんたのかは結局わかりませんでした。笑
-
実行したいファイルを実行してエラーが起きたら自動的に解決策教えてくれる訳ではなくいわざわざ
debug.py
を実行しないと教えてくれないのが少し微妙
これらをもとにver2を作ってみた!
改善したコードがこちらです!from distutils.log import error
import os
import subprocess
import openai
import api_key
openai.api_key = api_key.api_key
# Content_list and activate_file is the only thing you are supposed to change
content_list = ['test.py', 'ask.py']
activate_file = "test.py"
# Content_list and activate_file is the only thing you are supposed to change
code_dict = {}
messages = [
{"role": "system", "content": "You are an assistant that helps with Python debugging."}
]
stdout = ''
stderr = ''
# Folder tree structure
tree_structure = subprocess.run(['tree', '-L', '3'], capture_output=True, text=True).stdout
messages.append({"role": "assistant", "content": f'Project file structure:\n\n{tree_structure}\n\n'})
# Read file contents
def read_code(file_name):
with open(file_name, 'r') as file:
code = file.read()
return code
for file_name in content_list:
with open(file_name, 'r') as file:
code = read_code(file_name)
code_dict[file_name] = code
messages.append({"role": "assistant", "content": f'Content of each file:\n\n{code_dict}\n\n'})
error_occur = True
# Get error code
def outerr():
process = subprocess.Popen(['python3', 'test.py'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
stdout, stderr = process.communicate()
process.wait()
print("Standard output:")
print(stdout)
if len(stderr) > 0:
print("Standard error:")
print(stderr)
messages.append({"role": "assistant", "content": f'Error code generated by executing {activate_file}:\n\n{stderr}\n\n'})
messages.append({"role": "user", "content": 'Please provide a brief summary of why the error occurred and a possible solution.'})
error_occur = True
else:
print("No error occurred!")
error_occur = False
outerr()
with open('final.txt', 'w') as filing:
filing.write('1')
chat_completion = openai.ChatCompletion.create(
model="gpt-3.5-turbo-16k",
messages=messages
)
if error_occur == True:
response = chat_completion["choices"][0]["message"]["content"]
print(response)
else:
pass
元々のdebug.py
はもうその名前にふさわしくなくなったのでmake_message.py
に降格させてやりました
そして新しくファイルを作成しました。
import subprocess
def read_file(file_name):
with open(file_name,"r") as file:
content = file.read()
content = int(content)
return content
def write_file(file_name):
with open(file_name , 'w') as file:
file.write('0')
def debug_file():
content = read_file("num.txt")
if content == 0:
with open("num.txt", "w") as file:
file.write("1")
subprocess.run(["python3", "make_message.py"])
else:
write_file('num.txt')
def quit_code():
stop_code = read_file("final.txt")
if stop_code == 1:
write_file('final.txt')
quit()
debug_file()
quit_code()
import debug_gpt
print('hello world! from test.py!!')
print(hi)
こんな感じです!
変更点!
まず初めにtest.pyを実行してエラーが起きたら解決策を教えてほしいので「test.pyからsubprocessを使ってdebug.pyを呼び出せば良いじゃん!」と思って書いて実行すればターミナルが一生なんかをprintし始めました笑 subprocess.runがずーっとループしだしたので改善方法を考えました!ここからわかりにくくなります!笑def debug_file():
content = read_file("num.txt")
if content == 0:
with open("num.txt", "w") as file:
file.write("1")
subprocess.run(["python3", "make_message.py"])
else:
write_file('num.txt')
まずdebug_file()
関数を実行します。この関数はmake_message.py
を実行する関数です。ですがmake_message.py
でtest.py
を実行する際、またdebug_file
関数が呼び出されるのでループを防ぐ為にこんなアイデアを思いつきました!
- 新しくtxtファイルを作成し0と書いておきます。
-
read_file
関数でnum.txt
を読み込みます - もし0の場合(初めて呼び出される場合)は
subprocess.run
でmake_message.py
を実行します - 実行する前にnum.txtの数字を1に変えておきます
- そして2回目に
debug_file
関数が呼び出される時にはnum.txt
が1になっているのでelseにジャンプします。 -
write_file
関数でnum.txt
を0に戻します(次またデバッグする時に0になっていないとmake_messag
eが実行されないので)
と言う感じです。ややこしいですよね笑
これ今書いていて気づいたんですがファイル増やす必要無かったんじゃ無いかなって思い始めました笑
ちなみにtest.py
からdebug_gpt.py
をimportした際にdebug_gpt
内に実行されるコードがある場合、それは import debug_gpt
を行った時点で実行されるので、できるだけtest.py
内をスッキリさせる為にdebug_gpt.py
内で実行することにしました。
これでループ問題とわざわざdebug.py
を実行してデバッグをしないといけない問題が解決し、結果的にはdebug_gpt
ファイルをimportするだけですみました!僕的にこれが理想だったのですごく満足してます!
あと変えたところで言うとここら辺ですね〜!
def outerr():
process = subprocess.Popen(['python3', 'test.py'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
stdout, stderr = process.communicate()
process.wait()
print("Standard output:")
print(stdout)
if len(stderr) > 0:
print("Standard error:")
print(stderr)
messages.append({"role": "assistant", "content": f'Error code generated by executing {activate_file}:\n\n{stderr}\n\n'})
messages.append({"role": "user", "content": 'Please provide a brief summary of why the error occurred and a possible solution.'})
error_occur = True
else:
print("No error occurred!")
error_occur = False
try/except
文を使っていましたが、subprocess.poppen
関数を使ってエラーコードを取得することにしました。そしてもしエラーが起きた場合は解決策を聞いてもしエラーが起きなかったら何もしないと言う機能付け足しました!
終わり!!
終わりです!最後に適当に感想でも述べとこうかなと思います!
なんかめっちゃ楽しかったです!笑
特にループするのをどうして解決しようかなと考えてる時がなんかダンジョン攻略してるみたいで面白かったです!笑
制作するのに一週間かかりましたがなんだか完成した後溜めてたアニメを全て見終わったみたいな感覚になりました笑
次は夏休み中にdjangoで口コミサイトを作ろうと思うのですが、このデバッグツールを駆使して頑張ろうと思います!
ここまで読んでくれた人はありがとうございました!!また読んでください!!🙇♂️