Spaces:
Sleeping
Sleeping
2024-07-25T11:56:26.492034 | |
UPLOADED FILES: | |
File: config.py | |
import yaml | |
from log_writer import logger | |
def load_config(): | |
""" | |
Loads the configuration from the 'config.yaml' file and sets the global variables accordingly. | |
If the 'GENERATE_MODEL' key in the configuration is set to 'gpt-4', it forces the use of 'gpt-4-turbo-preview' | |
as the value for the 'GENERATE_MODEL' key, since 'gpt-4' no longer supports json modes. | |
Returns: | |
None | |
""" | |
with open("config.yaml", "r") as conf: | |
config_content = yaml.safe_load(conf) | |
for key, value in config_content.items(): | |
if key == "GENERATE_MODEL" and value == "gpt-4": | |
globals()[ | |
key | |
] = "gpt-4-turbo-preview" # Force using gpt-4-turbo-preview if the user set the GENERATE_MODEL to gpt-4. Because gpt-4 is not longer supports json modes. | |
globals()[key] = value | |
logger(f"config: {key} -> {value}") | |
def edit_config(key, value): | |
""" | |
Edits the config file. | |
Args: | |
key (str): The key to edit. | |
value (str): The value to set. | |
Returns: | |
bool: True | |
""" | |
with open("config.yaml", "r") as conf: | |
config_content = conf.readlines() | |
with open("config.yaml", "w") as conf: | |
for line in config_content: | |
if line.startswith(key): | |
if value == True: | |
write_value = "True" | |
elif value == False: | |
write_value = "False" | |
else: | |
write_value = f'"{value}"' | |
if "#" in line: | |
conf.write(f"{key}: {write_value} # {line.split('#')[1]}\n") | |
else: | |
conf.write(f"{key}: {write_value}\n") | |
else: | |
conf.write(line) | |
return True | |
load_config() | |
File: config.yaml | |
########## EDIT REQUIRED ########## | |
# GPT SETTINGS # | |
# Get your api key from openai. Remember google/bing is always your best friend. | |
# Model names: gpt-4-turbo-preview, gpt-3.5-turbo, etc. | |
# Recommend -> gpt-4-turbo (Better performance, more expensive), gpt-4-o (Good performance, cheaper) | |
API_KEY: "" # Free API Key with GPT-4 access: https://github.com/CubeGPT/.github/discussions/1 | |
BASE_URL: "https://api.openai.com/v1/chat/completions" | |
GENERATION_MODEL: "gpt-4-turbo-2024-04-09" | |
FIXING_MODEL: "gpt-4-turbo-2024-04-09" | |
# DEVELOPER SETTINGS # | |
VERSION_NUMBER: "0.1.1" | |
# PROMPT SETTINGS # | |
# If you don't know what it is, please don't touch it. Be sure to backup before editing. | |
## Code Generation ## | |
SYS_GEN: | | |
You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) | |
Write the code & choose a artifact name for the following files with the infomation which is also provided by the user: | |
codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java | |
codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml | |
codes/%ARTIFACT_NAME%/src/main/resources/config.yml | |
codes/%ARTIFACT_NAME%/pom.xml | |
Response in json format: | |
{ | |
\"codes\": [ | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", | |
\"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", | |
\"code\": \"name: ...\\nversion: ...\\n...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", | |
\"code\": \"...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", | |
\"code\": \"...\" | |
} | |
] | |
} | |
You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Uncompeleted". | |
USR_GEN: | | |
%DESCRIPTION% | |
SYS_FIX: | | |
You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) | |
Fix the error in the code provided by user. The error message is also provided by the user. | |
Response in json format: | |
{ | |
\"codes\": [ | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", | |
\"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", | |
\"code\": \"name: ...\\nversion: ...\\n...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", | |
\"code\": \"...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", | |
\"code\": \"...\" | |
} | |
] | |
} | |
You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Original code" or "// Uncompeleted". | |
USR_FIX: | | |
Main.java: | |
%MAIN_JAVA% | |
plugin.yml: | |
%PLUGIN_YML% | |
config.yml: | |
%CONFIG_YML% | |
pom.xml: | |
%POM_XML% | |
error message: | |
%P_ERROR_MSG% | |
File: console.py | |
import sys | |
import uuid | |
import shutil | |
from log_writer import logger | |
import core | |
import config | |
import build | |
if __name__ == "__main__": | |
main_java = None | |
plugin_yml = None | |
config_yml = None | |
pom_xml = None | |
core.initialize() | |
print("BukkitGPT v3 beta console running") | |
# Get user inputs | |
name = input("Enter the plugin name: ") | |
description = input("Enter the plugin description: ") | |
artifact_name = name.replace(" ", "") | |
package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" | |
pkg_id_path = "" | |
for id in package_id.split("."): | |
pkg_id_path += id + "/" | |
logger(f"user_input -> name: {name}") | |
logger(f"user_input -> description: {description}") | |
logger(f"random_generate -> package_id: {package_id}") | |
logger(f"str_path -> pkg_id_path: {pkg_id_path}") | |
print("Generating plugin...") | |
codes = core.askgpt( | |
config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( | |
"%PKG_ID_LST%", pkg_id_path | |
), | |
config.USR_GEN.replace("%DESCRIPTION", description), | |
config.GENERATION_MODEL, | |
) | |
logger(f"codes: {codes}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
elif "Compilation failure": | |
print("Build failed. Passing the error to ChatGPT and let it to fix it?") | |
fix = input("Y/n: ") | |
if fix == "n": | |
print("Exiting...") | |
sys.exit(0) | |
else: | |
print("Passing the error to ChatGPT...") | |
files = [ | |
f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", | |
f"codes/{artifact_name}/src/main/resources/plugin.yml", | |
f"codes/{artifact_name}/src/main/resources/config.yml", | |
f"codes/{artifact_name}/pom.xml", | |
] | |
ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] | |
for file in files: | |
with open(file, "r") as f: | |
code = f.read() | |
id = ids[files.index(file)] | |
globals()[id] = code | |
print("Generating...") | |
codes = core.askgpt( | |
config.SYS_FIX.replace("%ARTIFACT_NAME%", artifact_name), | |
config.USR_FIX.replace("%MAIN_JAVA%", main_java) | |
.replace("%PLUGIN_YML%", plugin_yml) | |
.replace("%CONFIG_YML%", config_yml) | |
.replace("%POM_XML%", pom_xml) | |
.replace("%P_ERROR_MSG%", result), | |
config.FIXING_MODEL, | |
) | |
shutil.rmtree(f"codes/{artifact_name}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
else: | |
print( | |
"Build failed. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
print("Exiting...") | |
sys.exit(0) | |
else: | |
print( | |
"Unknown error. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
print("Exiting...") | |
sys.exit(0) | |
else: | |
print( | |
"Error: Please run console.py as the main program instead of importing it from another program." | |
) | |
File: core.py | |
from openai import OpenAI | |
import chardet | |
import sys | |
import json | |
import locale | |
import os | |
from log_writer import logger | |
import config | |
def initialize(): | |
""" | |
Initializes the software. | |
This function logs the software launch, including the version number and platform. | |
Args: | |
None | |
Returns: | |
None | |
""" | |
locale.setlocale(locale.LC_ALL, "en_US.UTF-8") | |
logger(f"Launch. Software version {config.VERSION_NUMBER}, platform {sys.platform}") | |
if ( | |
"gpt-3.5" in config.GENERATION_MODEL | |
and config.BYPASS_NO_GPT35_FOR_GENERATION_LIMIT is False | |
): | |
print( | |
"gpt-3.5 writes bugs *all the time* and is not recommended for code generation. Switching to gpt-4." | |
) | |
config.edit_config( | |
"GENERATION_MODEL", config.GENERATION_MODEL.replace("gpt-3.5", "gpt-4") | |
) | |
def askgpt( | |
system_prompt: str, | |
user_prompt: str, | |
model_name: str, | |
disable_json_mode: bool = False, | |
image_url: str = None, | |
): | |
""" | |
Interacts with ChatGPT using the specified prompts. | |
Args: | |
system_prompt (str): The system prompt. | |
user_prompt (str): The user prompt. | |
model_name (str): The model name to use. | |
disable_json_mode (bool): Whether to disable JSON mode. | |
Returns: | |
str: The response from ChatGPT. | |
""" | |
if image_url is not None and config.USE_DIFFERENT_APIKEY_FOR_VISION_MODEL: | |
logger("Using different API key for vision model.") | |
client = OpenAI(api_key=config.VISION_API_KEY, base_url=config.VISION_BASE_URL) | |
else: | |
client = OpenAI(api_key=config.API_KEY, base_url=config.BASE_URL) | |
logger("Initialized the OpenAI client.") | |
# Define the messages for the conversation | |
if image_url is not None: | |
messages = [ | |
{"role": "system", "content": system_prompt}, | |
{ | |
"role": "user", | |
"content": [ | |
{"type": "text", "text": user_prompt}, | |
{"type": "image_url", "image_url": {"url": image_url}}, | |
], | |
}, | |
] | |
else: | |
messages = [ | |
{"role": "system", "content": system_prompt}, | |
{"role": "user", "content": user_prompt}, | |
] | |
logger(f"askgpt: system {system_prompt}") | |
logger(f"askgpt: user {user_prompt}") | |
# Create a chat completion | |
if disable_json_mode: | |
response = client.chat.completions.create(model=model_name, messages=messages) | |
else: | |
response = client.chat.completions.create( | |
model=model_name, response_format={"type": "json_object"}, messages=messages | |
) | |
logger(f"askgpt: response {response}") | |
# Extract the assistant's reply | |
assistant_reply = response.choices[0].message.content | |
logger(f"askgpt: extracted reply {assistant_reply}") | |
return assistant_reply | |
def response_to_action(msg): | |
""" | |
Converts a response from ChatGPT to an action. | |
Args: | |
msg (str): The response from ChatGPT. | |
Returns: | |
str: The action to take. | |
""" | |
text = json.loads(msg) | |
codes = text["codes"] | |
for section in codes: | |
file = section["file"] | |
code = section["code"] | |
paths = file.split("/") | |
# Join the list elements to form a path | |
path = os.path.join(*paths) | |
# Get the directory path and the file name | |
dir_path, file_name = os.path.split(path) | |
# Create directories, if they don't exist | |
try: | |
os.makedirs(dir_path, exist_ok=True) | |
except FileNotFoundError: | |
pass | |
# Create the file | |
with open(path, "w") as f: | |
f.write(code) # Write an empty string to the file | |
def mixed_decode(text: str): | |
""" | |
Decode a mixed text containing both normal text and a byte sequence. | |
Args: | |
text (str): The mixed text to be decoded. | |
Returns: | |
str: The decoded text, where the byte sequence has been converted to its corresponding characters. | |
""" | |
# Split the normal text and the byte sequence | |
# Assuming the byte sequence is everything after the last colon and space ": " | |
try: | |
normal_text, byte_text = text.rsplit(": ", 1) | |
except (TypeError, ValueError): | |
# The text only contains normal text | |
return text | |
# Convert the byte sequence to actual bytes | |
byte_sequence = byte_text.encode( | |
"latin1" | |
) # latin1 encoding maps byte values directly to unicode code points | |
# Detect the encoding of the byte sequence | |
detected_encoding = chardet.detect(byte_sequence) | |
encoding = detected_encoding["encoding"] | |
# Decode the byte sequence | |
decoded_text = byte_sequence.decode(encoding) | |
# Combine the normal text with the decoded byte sequence | |
final_text = normal_text + ": " + decoded_text | |
return final_text | |
if __name__ == "__main__": | |
print("This script is not meant to be run directly. Please run console.py instead.") | |
File: log_writer.py | |
import os | |
from datetime import datetime | |
first_call_time = None | |
def get_log_filename(): | |
global first_call_time | |
if first_call_time is None: | |
first_call_time = datetime.now() | |
log_filename = first_call_time.strftime("logs/%b-%d-%H-%M-%S-%Y") | |
return log_filename | |
def logger(text: str): | |
log_filename = get_log_filename() | |
timestamp_prefix = datetime.now().strftime("[%H:%M:%S]") | |
log_line = f"{timestamp_prefix} {text}\n" | |
os.makedirs(os.path.dirname(log_filename), exist_ok=True) | |
with open(log_filename + ".log", "a", encoding="utf-8") as log_file: | |
log_file.write(log_line) | |
File: README.md | |
<div align="center"> | |
<img src="https://github.com/CubeGPT/CubeAgents/blob/master/banner.jpeg?raw=true"/> | |
<img src="https://img.shields.io/badge/Cube-Agents-blue"> | |
<a href="https://github.com/CubeGPT/BuilderGPT/pulls"><img src="https://img.shields.io/badge/PRs-welcome-20BF20"></a> | |
<img src="https://img.shields.io/badge/License-Apache-red"> | |
<a href="https://discord.gg/kTZtXw8s7r"><img src="https://img.shields.io/discord/1212765516532289587 | |
"></a> | |
<!-- <p>English | <a href="https://github.com/CubeGPT/CubeAgents/blob/master/README-zh_cn.md">简体中文</a></p> --> | |
<br> | |
<a href="https://discord.gg/kTZtXw8s7r">Join our discord</a> | |
<br/> | |
</div> | |
> [!NOTE] | |
> Developers and translators are welcome to join the CubeGPT Team! | |
## Introduction | |
> A simple template for CubeGPT projects. | |
CubeAgents is a template for CubeGPT's projects like [BuilderGPT](https://github.com/CubeGPT/BuilderGPT). It provides a simple and clean interface for users to interact with the program. | |
# Showcase | |
... | |
## Partner | |
[](https://bisecthosting.com/cubegpt) | |
## Features | |
- [x] Feature 1 | |
- [x] Feature 2 | |
- [x] Feature 3 | |
- [ ] Feature 4 | |
### Other projects of CubeGPT Team | |
- [x] Bukkit plugin generator. {*.jar} ([BukkitGPT](https://github.com/CubeGPT/BukkitGPT)) | |
- [x] Structure generator. {*.schem} ([BuilderGPT](https://github.com/CubeGPT/BuilderGPT)) | |
- [ ] Serverpack generator. {*.zip} (ServerpackGPT or ServerGPT, or..?) | |
- [ ] Have ideas or want to join our team? Send [us](mailto:admin@baimoqilin.top) an email! | |
## How it works | |
... | |
## Requirements | |
### Plan A. Windows/Linux (executable edition) | |
Nothing. Just download the executable file and run it. | |
### Plan B. Python (Any operating systems; Recommend if possible) | |
You can use BukkitGPT on any device with [Python 3+](https://www.python.org/). | |
And you need to install the depencies with this command: | |
``` | |
pip install -r requirements.txt | |
``` | |
## Quick Start | |
*(Make sure you have the [Python](https://www.python.org) environment installed on your computer)* | |
... | |
## Contributing | |
If you like the project, you can give the project a star, or [submit an issue](https://github.com/CubeGPT/CubeAgents/issues) or [pull request](https://github.com/CubeGPT/CubeAgents/pulls) to help make it better. | |
## License | |
``` | |
Copyright [2024] [CubeGPT Team] | |
Licensed under the Apache License, Version 2.0 (the "License"); | |
you may not use this file except in compliance with the License. | |
You may obtain a copy of the License at | |
http://www.apache.org/licenses/LICENSE-2.0 | |
Unless required by applicable law or agreed to in writing, software | |
distributed under the License is distributed on an "AS IS" BASIS, | |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
See the License for the specific language governing permissions and | |
limitations under the License. | |
``` | |
File: requirements.txt | |
openai>=1.13.3 | |
pyyaml | |
cx_Freeze | |
ttkbootstrap | |
playwright | |
chardet | |
File: ui.py | |
from cube_qgui.__init__ import CreateQGUI | |
from cube_qgui.banner_tools import * | |
from cube_qgui.notebook_tools import * | |
from playwright.sync_api import Playwright, sync_playwright | |
import os | |
import shutil | |
import uuid | |
from log_writer import logger | |
import config | |
import core | |
import build | |
# ---------- Functions ----------# | |
def open_config(args: dict): | |
""" | |
Opens the config file. | |
Args: | |
args (dict): A dictionary containing the necessary arguments. | |
Returns: | |
bool: Always True. | |
""" | |
os.system("notepad config.yaml") | |
return True | |
def save_apply_config(args: dict): | |
""" | |
Saves and applies the configuration. | |
Args: | |
args (dict): A dictionary containing the necessary arguments. | |
Returns: | |
bool: Always True. | |
""" | |
keys = ["API_KEY", "BASE_URL"] | |
for key in keys: | |
value = args[key].get() | |
if key == "ADVANCED_MODE": | |
value = True if value == 1 else False | |
else: | |
pass | |
config.edit_config(key, value) | |
config.load_config() | |
args["DevTool_CONFIG_API_KEY_DISPLAY"].set(f"CONFIG.API_KEY = {config.API_KEY}") | |
args["DevTools_CONFIG_BASE_URL_DISPLAY"].set(f"CONFIG.BASE_URL = {config.BASE_URL}") | |
return True | |
def load_config(args: dict): | |
""" | |
Loads the configuration. | |
Args: | |
args (dict): A dictionary containing the necessary arguments. | |
Returns: | |
bool: Always True. | |
""" | |
config.load_config() | |
args["API_KEY"].set(config.API_KEY) | |
args["BASE_URL"].set(config.BASE_URL) | |
return True | |
def print_args(args: dict): | |
""" | |
Prints the arguments. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
Returns: | |
bool: Always True. | |
""" | |
for arg, v_fun in args.items(): | |
print(f"Name: {arg}, Value: {v_fun.get()}") | |
return True | |
def raise_error(args: dict): | |
""" | |
Raises an error. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
""" | |
raise Exception("This is a test error.") | |
# ---------- Generate Function ----------# | |
def generate(args: dict): | |
""" | |
Generates the plugin. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
Returns: | |
bool: Always True. | |
""" | |
global error_msg, pkg_id_path | |
# Get user inputs | |
name = args["PluginName"].get() | |
description = args["PluginDescription"].get() | |
artifact_name = name.replace(" ", "") | |
package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" | |
pkg_id_path = "" | |
for id in package_id.split("."): | |
pkg_id_path += id + "/" | |
logger(f"user_input -> name: {name}") | |
logger(f"user_input -> description: {description}") | |
logger(f"random_generate -> package_id: {package_id}") | |
logger(f"str_path -> pkg_id_path: {pkg_id_path}") | |
print("Generating plugin...") | |
codes = core.askgpt( | |
config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( | |
"%PKG_ID_LST%", pkg_id_path | |
), | |
config.USR_GEN.replace("%DESCRIPTION", description), | |
config.GENERATION_MODEL, | |
) | |
logger(f"codes: {codes}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
elif "Compilation failure": | |
error_msg = result | |
print( | |
"Build failed. To pass the error to ChatGPT && let it fix, jump to the Fixing page and click the Fix button." | |
) | |
else: | |
print( | |
"Unknown error. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
return True | |
def fix(args: dict): | |
""" | |
Fixes the error. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
Returns: | |
bool: Always True. | |
""" | |
artifact_name = args["PluginName"].get() | |
print("Passing the error to ChatGPT...") | |
files = [ | |
f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", | |
f"codes/{artifact_name}/src/main/resources/plugin.yml", | |
f"codes/{artifact_name}/src/main/resources/config.yml", | |
f"codes/{artifact_name}/pom.xml", | |
] | |
ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] | |
main_java = None | |
plugin_yml = None | |
config_yml = None | |
pom_xml = None | |
for file in files: | |
with open(file, "r") as f: | |
code = f.read() | |
id = ids[files.index(file)] | |
globals()[id] = code | |
print("Generating...") | |
codes = core.askgpt( | |
config.SYS_FIX.replace("%ARTIFACT_NAME%", str(artifact_name)), | |
config.USR_FIX.replace("%MAIN_JAVA%", str(main_java)) | |
.replace("%PLUGIN_YML%", str(plugin_yml)) | |
.replace("%CONFIG_YML%", str(config_yml)) | |
.replace("%POM_XML%", str(pom_xml)) | |
.replave("%PKG_ID_LST%", pkg_id_path) | |
.replace("%P_ERROR_MSG%", str(error_msg)), | |
config.FIXING_MODEL, | |
) | |
shutil.rmtree(f"codes/{artifact_name}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
else: | |
print( | |
"Build failed again. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
return True | |
# ---------- Main Program ----------# | |
root = CreateQGUI(title="BukkitGPT-v3", tab_names=["Generate", "Settings", "DevTools"]) | |
error_msg = None | |
logger("Starting program.") | |
# Initialize Core | |
core.initialize() | |
print("BukkitGPT v3 beta console running") | |
# Banner | |
root.add_banner_tool(GitHub("https://github.com/CubeGPT/BukkitGPT-v3")) | |
# Generate Page | |
root.add_notebook_tool( | |
InputBox(name="PluginName", default="ExamplePlugin", label_info="Plugin Name") | |
) | |
root.add_notebook_tool( | |
InputBox( | |
name="PluginDescription", | |
default="Send msg 'hello' to every joined player.", | |
label_info="Plugin Description", | |
) | |
) | |
root.add_notebook_tool( | |
RunButton( | |
bind_func=generate, | |
name="Generate", | |
text="Generate Plugin", | |
checked_text="Generating...", | |
tab_index=0, | |
) | |
) | |
# Fixing Page # | |
# root.add_notebook_tool(Label(name="Fixing_DESCRIPTION", text="This is a fixing page. If the build fails, click the Fix button to fix the error in the LATEST build.", tab_index=1)) | |
# root.add_notebook_tool(RunButton(bind_func=fix, name="Fix", text="Fix", checked_text="Fixing...", tab_index=1)) | |
# Settings Page | |
root.add_notebook_tool( | |
InputBox(name="API_KEY", default=config.API_KEY, label_info="API Key", tab_index=1) | |
) | |
root.add_notebook_tool( | |
InputBox( | |
name="BASE_URL", default=config.BASE_URL, label_info="BASE URL", tab_index=1 | |
) | |
) | |
config_buttons = HorizontalToolsCombine( | |
[ | |
BaseButton( | |
bind_func=save_apply_config, | |
name="Save & Apply Config", | |
text="Save & Apply", | |
tab_index=1, | |
), | |
BaseButton( | |
bind_func=load_config, name="Load Config", text="Load Config", tab_index=1 | |
), | |
BaseButton( | |
bind_func=open_config, | |
name="Open Config", | |
text="Open Full Config", | |
tab_index=1, | |
), | |
] | |
) | |
root.add_notebook_tool(config_buttons) | |
# DevTools Page | |
root.add_notebook_tool( | |
Label( | |
name="DevTool_DESCRIPTION", | |
text="This is a testing page for developers. Ignore it if you are a normal user.", | |
tab_index=2, | |
) | |
) | |
root.add_notebook_tool( | |
Label( | |
name="DevTool_CONFIG_API_KEY_DISPLAY", | |
text=f"CONFIG.API_KEY = {config.API_KEY}", | |
tab_index=2, | |
) | |
) | |
root.add_notebook_tool( | |
Label( | |
name="DevTools_CONFIG_BASE_URL_DISPLAY", | |
text=f"CONFIG.BASE_URL = {config.BASE_URL}", | |
tab_index=2, | |
) | |
) | |
root.add_notebook_tool( | |
RunButton(bind_func=print_args, name="Print Args", text="Print Args", tab_index=2) | |
) | |
root.add_notebook_tool( | |
RunButton( | |
bind_func=raise_error, name="Raise Error", text="Raise Error", tab_index=2 | |
) | |
) | |
# Sidebar | |
root.set_navigation_about( | |
author="CubeGPT Team", | |
version=config.VERSION_NUMBER, | |
github_url="https://github.com/CubeGPT/BukkitGPT-v3", | |
) | |
# Run | |
root.run() | |
PROMPT: | |
添加生成DataPack的选项,使得用户可以选择生成Bukkit插件或者DataPack。 | |
在`ui.py`中可以在Generate Page里添加这行代码 `root.add_notebook_tool(RadioObviousToolButton(options=["BukkitPlugin", "Datapack(Experimental)"], name="GenerationType", title="Type", default="BukkitPlugin",tab_index=0))` | |
你还需要自行完成DataPack的生成逻辑。你可能需要更改的文件有`ui.py`, `core.py`, `config.yaml`, `console.py`。你还可能需要创建一些新的文件或文件夹,也有可能不需要。祝你好运。 | |
2024-07-25T11:56:26.944792 | |
CONSOLE OUTPUT: | |
Error while improving the project: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted" | |
Could you please upload the debug_log_file.txt in D:\zhousl\BukkitGPT\BukkitGPT-v3\.gpteng\memory/logs folder to github? | |
FULL STACK TRACE: | |
Traceback (most recent call last): | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 379, in handle_improve_mode | |
files_dict = agent.improve(files_dict, prompt) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\applications\cli\cli_agent.py", line 208, in improve | |
files_dict = self.improve_fn( | |
^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 311, in improve_fn | |
return _improve_loop(ai, files_dict, memory, messages) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 317, in _improve_loop | |
messages = ai.next(messages, step_name=curr_fn()) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 243, in next | |
response = self.backoff_inference(messages) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\backoff\_sync.py", line 105, in retry | |
ret = target(*args, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 287, in backoff_inference | |
return self.llm.invoke(messages) # type: ignore | |
^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 270, in invoke | |
self.generate_prompt( | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 703, in generate_prompt | |
return self.generate(prompt_messages, stop=stop, callbacks=callbacks, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 560, in generate | |
raise e | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 550, in generate | |
self._generate_with_cache( | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 775, in _generate_with_cache | |
result = self._generate( | |
^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 755, in _generate | |
return generate_from_stream(stream_iter) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 102, in generate_from_stream | |
generation = next(stream, None) | |
^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 676, in _stream | |
stream = self._client.messages.create(**payload) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_utils\_utils.py", line 277, in wrapper | |
return func(*args, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\resources\messages.py", line 902, in create | |
return self._post( | |
^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 1266, in post | |
return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 942, in request | |
return self._request( | |
^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 968, in _request | |
request = self._build_request(options) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 461, in _build_request | |
headers = self._build_headers(options) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 416, in _build_headers | |
self._validate_headers(headers_dict, custom_headers) | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_client.py", line 192, in _validate_headers | |
raise TypeError( | |
TypeError: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted" | |
2024-07-25T11:59:37.704389 | |
UPLOADED FILES: | |
File: config.py | |
import yaml | |
from log_writer import logger | |
def load_config(): | |
""" | |
Loads the configuration from the 'config.yaml' file and sets the global variables accordingly. | |
If the 'GENERATE_MODEL' key in the configuration is set to 'gpt-4', it forces the use of 'gpt-4-turbo-preview' | |
as the value for the 'GENERATE_MODEL' key, since 'gpt-4' no longer supports json modes. | |
Returns: | |
None | |
""" | |
with open("config.yaml", "r") as conf: | |
config_content = yaml.safe_load(conf) | |
for key, value in config_content.items(): | |
if key == "GENERATE_MODEL" and value == "gpt-4": | |
globals()[ | |
key | |
] = "gpt-4-turbo-preview" # Force using gpt-4-turbo-preview if the user set the GENERATE_MODEL to gpt-4. Because gpt-4 is not longer supports json modes. | |
globals()[key] = value | |
logger(f"config: {key} -> {value}") | |
def edit_config(key, value): | |
""" | |
Edits the config file. | |
Args: | |
key (str): The key to edit. | |
value (str): The value to set. | |
Returns: | |
bool: True | |
""" | |
with open("config.yaml", "r") as conf: | |
config_content = conf.readlines() | |
with open("config.yaml", "w") as conf: | |
for line in config_content: | |
if line.startswith(key): | |
if value == True: | |
write_value = "True" | |
elif value == False: | |
write_value = "False" | |
else: | |
write_value = f'"{value}"' | |
if "#" in line: | |
conf.write(f"{key}: {write_value} # {line.split('#')[1]}\n") | |
else: | |
conf.write(f"{key}: {write_value}\n") | |
else: | |
conf.write(line) | |
return True | |
load_config() | |
File: config.yaml | |
########## EDIT REQUIRED ########## | |
# GPT SETTINGS # | |
# Get your api key from openai. Remember google/bing is always your best friend. | |
# Model names: gpt-4-turbo-preview, gpt-3.5-turbo, etc. | |
# Recommend -> gpt-4-turbo (Better performance, more expensive), gpt-4-o (Good performance, cheaper) | |
API_KEY: "" # Free API Key with GPT-4 access: https://github.com/CubeGPT/.github/discussions/1 | |
BASE_URL: "https://api.openai.com/v1/chat/completions" | |
GENERATION_MODEL: "gpt-4-turbo-2024-04-09" | |
FIXING_MODEL: "gpt-4-turbo-2024-04-09" | |
# DEVELOPER SETTINGS # | |
VERSION_NUMBER: "0.1.1" | |
# PROMPT SETTINGS # | |
# If you don't know what it is, please don't touch it. Be sure to backup before editing. | |
## Code Generation ## | |
SYS_GEN: | | |
You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) | |
Write the code & choose a artifact name for the following files with the infomation which is also provided by the user: | |
codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java | |
codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml | |
codes/%ARTIFACT_NAME%/src/main/resources/config.yml | |
codes/%ARTIFACT_NAME%/pom.xml | |
Response in json format: | |
{ | |
\"codes\": [ | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", | |
\"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", | |
\"code\": \"name: ...\\nversion: ...\\n...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", | |
\"code\": \"...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", | |
\"code\": \"...\" | |
} | |
] | |
} | |
You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Uncompeleted". | |
USR_GEN: | | |
%DESCRIPTION% | |
SYS_FIX: | | |
You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) | |
Fix the error in the code provided by user. The error message is also provided by the user. | |
Response in json format: | |
{ | |
\"codes\": [ | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", | |
\"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", | |
\"code\": \"name: ...\\nversion: ...\\n...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", | |
\"code\": \"...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", | |
\"code\": \"...\" | |
} | |
] | |
} | |
You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Original code" or "// Uncompeleted". | |
USR_FIX: | | |
Main.java: | |
%MAIN_JAVA% | |
plugin.yml: | |
%PLUGIN_YML% | |
config.yml: | |
%CONFIG_YML% | |
pom.xml: | |
%POM_XML% | |
error message: | |
%P_ERROR_MSG% | |
File: console.py | |
import sys | |
import uuid | |
import shutil | |
from log_writer import logger | |
import core | |
import config | |
import build | |
if __name__ == "__main__": | |
main_java = None | |
plugin_yml = None | |
config_yml = None | |
pom_xml = None | |
core.initialize() | |
print("BukkitGPT v3 beta console running") | |
# Get user inputs | |
name = input("Enter the plugin name: ") | |
description = input("Enter the plugin description: ") | |
artifact_name = name.replace(" ", "") | |
package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" | |
pkg_id_path = "" | |
for id in package_id.split("."): | |
pkg_id_path += id + "/" | |
logger(f"user_input -> name: {name}") | |
logger(f"user_input -> description: {description}") | |
logger(f"random_generate -> package_id: {package_id}") | |
logger(f"str_path -> pkg_id_path: {pkg_id_path}") | |
print("Generating plugin...") | |
codes = core.askgpt( | |
config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( | |
"%PKG_ID_LST%", pkg_id_path | |
), | |
config.USR_GEN.replace("%DESCRIPTION", description), | |
config.GENERATION_MODEL, | |
) | |
logger(f"codes: {codes}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
elif "Compilation failure": | |
print("Build failed. Passing the error to ChatGPT and let it to fix it?") | |
fix = input("Y/n: ") | |
if fix == "n": | |
print("Exiting...") | |
sys.exit(0) | |
else: | |
print("Passing the error to ChatGPT...") | |
files = [ | |
f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", | |
f"codes/{artifact_name}/src/main/resources/plugin.yml", | |
f"codes/{artifact_name}/src/main/resources/config.yml", | |
f"codes/{artifact_name}/pom.xml", | |
] | |
ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] | |
for file in files: | |
with open(file, "r") as f: | |
code = f.read() | |
id = ids[files.index(file)] | |
globals()[id] = code | |
print("Generating...") | |
codes = core.askgpt( | |
config.SYS_FIX.replace("%ARTIFACT_NAME%", artifact_name), | |
config.USR_FIX.replace("%MAIN_JAVA%", main_java) | |
.replace("%PLUGIN_YML%", plugin_yml) | |
.replace("%CONFIG_YML%", config_yml) | |
.replace("%POM_XML%", pom_xml) | |
.replace("%P_ERROR_MSG%", result), | |
config.FIXING_MODEL, | |
) | |
shutil.rmtree(f"codes/{artifact_name}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
else: | |
print( | |
"Build failed. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
print("Exiting...") | |
sys.exit(0) | |
else: | |
print( | |
"Unknown error. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
print("Exiting...") | |
sys.exit(0) | |
else: | |
print( | |
"Error: Please run console.py as the main program instead of importing it from another program." | |
) | |
File: core.py | |
from openai import OpenAI | |
import chardet | |
import sys | |
import json | |
import locale | |
import os | |
from log_writer import logger | |
import config | |
def initialize(): | |
""" | |
Initializes the software. | |
This function logs the software launch, including the version number and platform. | |
Args: | |
None | |
Returns: | |
None | |
""" | |
locale.setlocale(locale.LC_ALL, "en_US.UTF-8") | |
logger(f"Launch. Software version {config.VERSION_NUMBER}, platform {sys.platform}") | |
if ( | |
"gpt-3.5" in config.GENERATION_MODEL | |
and config.BYPASS_NO_GPT35_FOR_GENERATION_LIMIT is False | |
): | |
print( | |
"gpt-3.5 writes bugs *all the time* and is not recommended for code generation. Switching to gpt-4." | |
) | |
config.edit_config( | |
"GENERATION_MODEL", config.GENERATION_MODEL.replace("gpt-3.5", "gpt-4") | |
) | |
def askgpt( | |
system_prompt: str, | |
user_prompt: str, | |
model_name: str, | |
disable_json_mode: bool = False, | |
image_url: str = None, | |
): | |
""" | |
Interacts with ChatGPT using the specified prompts. | |
Args: | |
system_prompt (str): The system prompt. | |
user_prompt (str): The user prompt. | |
model_name (str): The model name to use. | |
disable_json_mode (bool): Whether to disable JSON mode. | |
Returns: | |
str: The response from ChatGPT. | |
""" | |
if image_url is not None and config.USE_DIFFERENT_APIKEY_FOR_VISION_MODEL: | |
logger("Using different API key for vision model.") | |
client = OpenAI(api_key=config.VISION_API_KEY, base_url=config.VISION_BASE_URL) | |
else: | |
client = OpenAI(api_key=config.API_KEY, base_url=config.BASE_URL) | |
logger("Initialized the OpenAI client.") | |
# Define the messages for the conversation | |
if image_url is not None: | |
messages = [ | |
{"role": "system", "content": system_prompt}, | |
{ | |
"role": "user", | |
"content": [ | |
{"type": "text", "text": user_prompt}, | |
{"type": "image_url", "image_url": {"url": image_url}}, | |
], | |
}, | |
] | |
else: | |
messages = [ | |
{"role": "system", "content": system_prompt}, | |
{"role": "user", "content": user_prompt}, | |
] | |
logger(f"askgpt: system {system_prompt}") | |
logger(f"askgpt: user {user_prompt}") | |
# Create a chat completion | |
if disable_json_mode: | |
response = client.chat.completions.create(model=model_name, messages=messages) | |
else: | |
response = client.chat.completions.create( | |
model=model_name, response_format={"type": "json_object"}, messages=messages | |
) | |
logger(f"askgpt: response {response}") | |
# Extract the assistant's reply | |
assistant_reply = response.choices[0].message.content | |
logger(f"askgpt: extracted reply {assistant_reply}") | |
return assistant_reply | |
def response_to_action(msg): | |
""" | |
Converts a response from ChatGPT to an action. | |
Args: | |
msg (str): The response from ChatGPT. | |
Returns: | |
str: The action to take. | |
""" | |
text = json.loads(msg) | |
codes = text["codes"] | |
for section in codes: | |
file = section["file"] | |
code = section["code"] | |
paths = file.split("/") | |
# Join the list elements to form a path | |
path = os.path.join(*paths) | |
# Get the directory path and the file name | |
dir_path, file_name = os.path.split(path) | |
# Create directories, if they don't exist | |
try: | |
os.makedirs(dir_path, exist_ok=True) | |
except FileNotFoundError: | |
pass | |
# Create the file | |
with open(path, "w") as f: | |
f.write(code) # Write an empty string to the file | |
def mixed_decode(text: str): | |
""" | |
Decode a mixed text containing both normal text and a byte sequence. | |
Args: | |
text (str): The mixed text to be decoded. | |
Returns: | |
str: The decoded text, where the byte sequence has been converted to its corresponding characters. | |
""" | |
# Split the normal text and the byte sequence | |
# Assuming the byte sequence is everything after the last colon and space ": " | |
try: | |
normal_text, byte_text = text.rsplit(": ", 1) | |
except (TypeError, ValueError): | |
# The text only contains normal text | |
return text | |
# Convert the byte sequence to actual bytes | |
byte_sequence = byte_text.encode( | |
"latin1" | |
) # latin1 encoding maps byte values directly to unicode code points | |
# Detect the encoding of the byte sequence | |
detected_encoding = chardet.detect(byte_sequence) | |
encoding = detected_encoding["encoding"] | |
# Decode the byte sequence | |
decoded_text = byte_sequence.decode(encoding) | |
# Combine the normal text with the decoded byte sequence | |
final_text = normal_text + ": " + decoded_text | |
return final_text | |
if __name__ == "__main__": | |
print("This script is not meant to be run directly. Please run console.py instead.") | |
File: log_writer.py | |
import os | |
from datetime import datetime | |
first_call_time = None | |
def get_log_filename(): | |
global first_call_time | |
if first_call_time is None: | |
first_call_time = datetime.now() | |
log_filename = first_call_time.strftime("logs/%b-%d-%H-%M-%S-%Y") | |
return log_filename | |
def logger(text: str): | |
log_filename = get_log_filename() | |
timestamp_prefix = datetime.now().strftime("[%H:%M:%S]") | |
log_line = f"{timestamp_prefix} {text}\n" | |
os.makedirs(os.path.dirname(log_filename), exist_ok=True) | |
with open(log_filename + ".log", "a", encoding="utf-8") as log_file: | |
log_file.write(log_line) | |
File: requirements.txt | |
openai>=1.13.3 | |
pyyaml | |
cx_Freeze | |
ttkbootstrap | |
playwright | |
chardet | |
File: ui.py | |
from cube_qgui.__init__ import CreateQGUI | |
from cube_qgui.banner_tools import * | |
from cube_qgui.notebook_tools import * | |
from playwright.sync_api import Playwright, sync_playwright | |
import os | |
import shutil | |
import uuid | |
from log_writer import logger | |
import config | |
import core | |
import build | |
# ---------- Functions ----------# | |
def open_config(args: dict): | |
""" | |
Opens the config file. | |
Args: | |
args (dict): A dictionary containing the necessary arguments. | |
Returns: | |
bool: Always True. | |
""" | |
os.system("notepad config.yaml") | |
return True | |
def save_apply_config(args: dict): | |
""" | |
Saves and applies the configuration. | |
Args: | |
args (dict): A dictionary containing the necessary arguments. | |
Returns: | |
bool: Always True. | |
""" | |
keys = ["API_KEY", "BASE_URL"] | |
for key in keys: | |
value = args[key].get() | |
if key == "ADVANCED_MODE": | |
value = True if value == 1 else False | |
else: | |
pass | |
config.edit_config(key, value) | |
config.load_config() | |
args["DevTool_CONFIG_API_KEY_DISPLAY"].set(f"CONFIG.API_KEY = {config.API_KEY}") | |
args["DevTools_CONFIG_BASE_URL_DISPLAY"].set(f"CONFIG.BASE_URL = {config.BASE_URL}") | |
return True | |
def load_config(args: dict): | |
""" | |
Loads the configuration. | |
Args: | |
args (dict): A dictionary containing the necessary arguments. | |
Returns: | |
bool: Always True. | |
""" | |
config.load_config() | |
args["API_KEY"].set(config.API_KEY) | |
args["BASE_URL"].set(config.BASE_URL) | |
return True | |
def print_args(args: dict): | |
""" | |
Prints the arguments. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
Returns: | |
bool: Always True. | |
""" | |
for arg, v_fun in args.items(): | |
print(f"Name: {arg}, Value: {v_fun.get()}") | |
return True | |
def raise_error(args: dict): | |
""" | |
Raises an error. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
""" | |
raise Exception("This is a test error.") | |
# ---------- Generate Function ----------# | |
def generate(args: dict): | |
""" | |
Generates the plugin. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
Returns: | |
bool: Always True. | |
""" | |
global error_msg, pkg_id_path | |
# Get user inputs | |
name = args["PluginName"].get() | |
description = args["PluginDescription"].get() | |
artifact_name = name.replace(" ", "") | |
package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" | |
pkg_id_path = "" | |
for id in package_id.split("."): | |
pkg_id_path += id + "/" | |
logger(f"user_input -> name: {name}") | |
logger(f"user_input -> description: {description}") | |
logger(f"random_generate -> package_id: {package_id}") | |
logger(f"str_path -> pkg_id_path: {pkg_id_path}") | |
print("Generating plugin...") | |
codes = core.askgpt( | |
config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( | |
"%PKG_ID_LST%", pkg_id_path | |
), | |
config.USR_GEN.replace("%DESCRIPTION", description), | |
config.GENERATION_MODEL, | |
) | |
logger(f"codes: {codes}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
elif "Compilation failure": | |
error_msg = result | |
print( | |
"Build failed. To pass the error to ChatGPT && let it fix, jump to the Fixing page and click the Fix button." | |
) | |
else: | |
print( | |
"Unknown error. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
return True | |
def fix(args: dict): | |
""" | |
Fixes the error. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
Returns: | |
bool: Always True. | |
""" | |
artifact_name = args["PluginName"].get() | |
print("Passing the error to ChatGPT...") | |
files = [ | |
f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", | |
f"codes/{artifact_name}/src/main/resources/plugin.yml", | |
f"codes/{artifact_name}/src/main/resources/config.yml", | |
f"codes/{artifact_name}/pom.xml", | |
] | |
ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] | |
main_java = None | |
plugin_yml = None | |
config_yml = None | |
pom_xml = None | |
for file in files: | |
with open(file, "r") as f: | |
code = f.read() | |
id = ids[files.index(file)] | |
globals()[id] = code | |
print("Generating...") | |
codes = core.askgpt( | |
config.SYS_FIX.replace("%ARTIFACT_NAME%", str(artifact_name)), | |
config.USR_FIX.replace("%MAIN_JAVA%", str(main_java)) | |
.replace("%PLUGIN_YML%", str(plugin_yml)) | |
.replace("%CONFIG_YML%", str(config_yml)) | |
.replace("%POM_XML%", str(pom_xml)) | |
.replave("%PKG_ID_LST%", pkg_id_path) | |
.replace("%P_ERROR_MSG%", str(error_msg)), | |
config.FIXING_MODEL, | |
) | |
shutil.rmtree(f"codes/{artifact_name}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
else: | |
print( | |
"Build failed again. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
return True | |
# ---------- Main Program ----------# | |
root = CreateQGUI(title="BukkitGPT-v3", tab_names=["Generate", "Settings", "DevTools"]) | |
error_msg = None | |
logger("Starting program.") | |
# Initialize Core | |
core.initialize() | |
print("BukkitGPT v3 beta console running") | |
# Banner | |
root.add_banner_tool(GitHub("https://github.com/CubeGPT/BukkitGPT-v3")) | |
# Generate Page | |
root.add_notebook_tool( | |
InputBox(name="PluginName", default="ExamplePlugin", label_info="Plugin Name") | |
) | |
root.add_notebook_tool( | |
InputBox( | |
name="PluginDescription", | |
default="Send msg 'hello' to every joined player.", | |
label_info="Plugin Description", | |
) | |
) | |
root.add_notebook_tool( | |
RunButton( | |
bind_func=generate, | |
name="Generate", | |
text="Generate Plugin", | |
checked_text="Generating...", | |
tab_index=0, | |
) | |
) | |
# Fixing Page # | |
# root.add_notebook_tool(Label(name="Fixing_DESCRIPTION", text="This is a fixing page. If the build fails, click the Fix button to fix the error in the LATEST build.", tab_index=1)) | |
# root.add_notebook_tool(RunButton(bind_func=fix, name="Fix", text="Fix", checked_text="Fixing...", tab_index=1)) | |
# Settings Page | |
root.add_notebook_tool( | |
InputBox(name="API_KEY", default=config.API_KEY, label_info="API Key", tab_index=1) | |
) | |
root.add_notebook_tool( | |
InputBox( | |
name="BASE_URL", default=config.BASE_URL, label_info="BASE URL", tab_index=1 | |
) | |
) | |
config_buttons = HorizontalToolsCombine( | |
[ | |
BaseButton( | |
bind_func=save_apply_config, | |
name="Save & Apply Config", | |
text="Save & Apply", | |
tab_index=1, | |
), | |
BaseButton( | |
bind_func=load_config, name="Load Config", text="Load Config", tab_index=1 | |
), | |
BaseButton( | |
bind_func=open_config, | |
name="Open Config", | |
text="Open Full Config", | |
tab_index=1, | |
), | |
] | |
) | |
root.add_notebook_tool(config_buttons) | |
# DevTools Page | |
root.add_notebook_tool( | |
Label( | |
name="DevTool_DESCRIPTION", | |
text="This is a testing page for developers. Ignore it if you are a normal user.", | |
tab_index=2, | |
) | |
) | |
root.add_notebook_tool( | |
Label( | |
name="DevTool_CONFIG_API_KEY_DISPLAY", | |
text=f"CONFIG.API_KEY = {config.API_KEY}", | |
tab_index=2, | |
) | |
) | |
root.add_notebook_tool( | |
Label( | |
name="DevTools_CONFIG_BASE_URL_DISPLAY", | |
text=f"CONFIG.BASE_URL = {config.BASE_URL}", | |
tab_index=2, | |
) | |
) | |
root.add_notebook_tool( | |
RunButton(bind_func=print_args, name="Print Args", text="Print Args", tab_index=2) | |
) | |
root.add_notebook_tool( | |
RunButton( | |
bind_func=raise_error, name="Raise Error", text="Raise Error", tab_index=2 | |
) | |
) | |
# Sidebar | |
root.set_navigation_about( | |
author="CubeGPT Team", | |
version=config.VERSION_NUMBER, | |
github_url="https://github.com/CubeGPT/BukkitGPT-v3", | |
) | |
# Run | |
root.run() | |
File: cube_qgui\\__main__.py | |
# 这是对于cube_qgui的一个简单示例,展示了如何使用QGUI来创建一个简单的GUI应用。 | |
import time | |
# 导入CreateQGUI模块 | |
from qgui import CreateQGUI, MessageBox | |
# 【可选】导入自定义导航栏按钮模块、GitHub导航栏模块 | |
from qgui.banner_tools import BaseBarTool, GitHub, AIStudio | |
# 【可选】一次性导入所有的主界面工具模块 | |
from qgui.notebook_tools import * | |
# 【可选】导入占位符 | |
from qgui.manager import QStyle, HORIZONTAL | |
def click(args: dict): | |
MessageBox.info("要开始啦~") | |
# 证明一下自己被点到了 | |
print("你点到我啦~") | |
# 通过ChooseFileTextButton(name="文件选择")中预先设置的name参数,使用get方法即可获取对应的输入框信息 | |
print("你选择的文件是:", args["文件选择"].get()) | |
# 当然也可以通过name参数来设置对应的内容,使用set方法即可完成设置 | |
print("保存位置修改为“快看,我被修改啦”", args["保存位置"].set("快看,我被修改啦")) | |
# 即使没有指定name,我们照样可以拿到所有的小工具情况 | |
for arg, v_fun in args.items(): | |
print("自定义组件Name:", arg, "状态:", v_fun.get()) | |
# 若我们绑定了进度条,那么每当需要设置进度的时候,通过args["进度条"].set(当前进度)来进行设置吧,倒吸进度条也是可以哒 | |
for i in range(1, 101): | |
time.sleep(0.01) | |
args["进度条"].set(i) | |
# 增加打印间隔 | |
if i % 20 == 0: | |
print("当前进度", i) | |
MessageBox.warning(text="给个评价吧亲~") | |
# 也可以在终端中打印组件,顺便绑定用户调研函数 | |
q_gui.print_tool( | |
RadioButton( | |
["满意", "一般", "你好垃圾啊"], title="体验如何?", name="feedback", bind_func=feedback | |
) | |
) | |
# 甚至打印图片 | |
from qgui import RESOURCES_PATH | |
q_gui.print_image(os.path.join(RESOURCES_PATH, "demo/panda.jpg")) | |
def feedback(args: dict): | |
# 用户调研Callback | |
info = args["feedback"].get() | |
if info == "满意": | |
print("么么哒") | |
elif info == "一般": | |
print("啊啊啊,告诉GT哪里没做好吧") | |
else: | |
print("以后漂流瓶见吧,拜拜!") | |
def bind_dir(args: dict): | |
# 获取所选择文件所在的文件夹路径 | |
path = os.path.dirname(args["文件选择"].get()) | |
# 可以通过name参数来设置对应的内容,使用set方法即可完成设置 | |
args["保存位置"].set(path) | |
print("保存位置已自动修改为:", path) | |
def go_to_first_page(args: dict): | |
args["QGUI-BaseNoteBook"].set(0) | |
# 创建主界面 | |
q_gui = CreateQGUI( | |
title="一个新应用", # 界面标题 | |
tab_names=["主控制台", "选择按钮", "其他小工具"], # 界面中心部分的分页标题 - 可不填 | |
style=QStyle.default, | |
) # 皮肤 | |
# 在界面最上方添加一个按钮,链接到GitHub主页 | |
q_gui.add_banner_tool(GitHub(url="https://github.com/QPT-Family/QGUI")) | |
# 也可以是AI Studio | |
q_gui.add_banner_tool( | |
AIStudio(url="https://aistudio.baidu.com/aistudio/personalcenter/thirdview/29724") | |
) | |
# 要不试试自定义Banner按钮,在大家点击它时触发刚刚定义的click函数,并向它传递其他组件的情况 | |
q_gui.add_banner_tool(BaseBarTool(bind_func=click, name="一个新组件")) | |
# 在主界面部分添加一个文件选择工具吧,并在选择文件后自动变为文件所在的路径 | |
q_gui.add_notebook_tool(ChooseFileTextButton(name="文件选择", bind_func=bind_dir)) | |
# 再加个文件夹选择工具 | |
q_gui.add_notebook_tool(ChooseDirTextButton(name="保存位置")) | |
# 当然也可以来个输入框 | |
q_gui.add_notebook_tool(InputBox(name="我是个木有感情的输入框")) | |
# 想要加一个 进度条 和 运行按钮 而且俩要水平方向排列该如何做? | |
# 试试HorizontalToolsCombine,它可以接受一组工具并将其进行水平排列 | |
# 这里我们也为RunButton绑定click函数 | |
run_menu = HorizontalToolsCombine( | |
[Progressbar(name="进度条"), RunButton(bind_func=click)], | |
text="试试HorizontalToolsCombine,它可以接受一组工具并将其进行水平排列", | |
) | |
q_gui.add_notebook_tool(run_menu) | |
# 第二页 - 复选框和单选框 | |
# 使用VerticalFrameCombine可以将他们在垂直方向快速组合,它们会从左到右按顺序排列 | |
combine_left = VerticalFrameCombine( | |
[ | |
CheckButton(options=[("选择1", 0), ("选择2", 1), ("选择3", 0)]), | |
CheckToolButton(options=[("选择1", 0), ("选择2", 1), ("选择3", 0)]), | |
CheckObviousToolButton(options=[("选择1", 0), ("选择2", 1), ("选择3", 0)]), | |
ToggleButton(options=("开", 1)), | |
], | |
tab_index=1, | |
text="使用VerticalFrameCombine可以将他们在垂直方向快速组合,它们会从左到右按顺序排列", | |
) | |
q_gui.add_notebook_tool(combine_left) | |
# 设置title参数后会为其增加标题 | |
combine_right = VerticalFrameCombine( | |
[ | |
RadioButton(["选择1", "选择2", "选择3"], tab_index=1), | |
RadioToolButton(["选择1", "选择2", "选择3"], tab_index=1), | |
RadioObviousToolButton(["选择1", "选择2", "选择3"], tab_index=1), | |
], | |
title="右侧的复选框", | |
) | |
q_gui.add_notebook_tool(combine_right) | |
# 第三页 | |
q_gui.add_notebook_tool( | |
Label(text="这只是个简单的Label组件", alignment=RIGHT + TOP, tab_index=2) | |
) | |
q_gui.add_notebook_tool(Slider(default=4, tab_index=2)) | |
q_gui.add_notebook_tool(Combobox(options=["选择1", "选择2", "选择3"], tab_index=2)) | |
q_gui.add_notebook_tool( | |
BaseButton(bind_func=go_to_first_page, text="回到首页", tab_index=2) | |
) | |
# 左侧信息栏 | |
# 简单加个简介 | |
q_gui.set_navigation_about( | |
author="GT", | |
version="0.0.1", | |
github_url="https://github.com/QPT-Family/QGUI", | |
other_info=["欢迎加入QPT!"], | |
) | |
# 也可以加一下其他信息 | |
q_gui.set_navigation_info(title="随便写段话", info="除了QGUI,你还可以试试例如AgentQGUI这样同样简单的GUI框架") | |
print("小Tips:占位符可以被Print,不信你看HORIZONTAL的描述被打印了出来->", HORIZONTAL) | |
# 跑起来~切记!一定要放在程序末尾 | |
q_gui.run() | |
PROMPT: | |
添加生成DataPack的选项,使得用户可以选择生成Bukkit插件或者DataPack。 | |
在`ui.py`中可以在Generate Page里添加这行代码 `root.add_notebook_tool(RadioObviousToolButton(options=["BukkitPlugin", "Datapack(Experimental)"], name="GenerationType", title="Type", default="BukkitPlugin",tab_index=0))` | |
你还需要自行完成DataPack的生成逻辑。你可能需要更改的文件有`ui.py`, `core.py`, `config.yaml`, `console.py`。你还可能需要创建一些新的文件或文件夹,也有可能不需要。祝你好运。 | |
2024-07-25T11:59:38.142362 | |
CONSOLE OUTPUT: | |
Error while improving the project: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted" | |
Could you please upload the debug_log_file.txt in D:\zhousl\BukkitGPT\BukkitGPT-v3\.gpteng\memory/logs folder to github? | |
FULL STACK TRACE: | |
Traceback (most recent call last): | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 379, in handle_improve_mode | |
files_dict = agent.improve(files_dict, prompt) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\applications\cli\cli_agent.py", line 208, in improve | |
files_dict = self.improve_fn( | |
^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 311, in improve_fn | |
return _improve_loop(ai, files_dict, memory, messages) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 317, in _improve_loop | |
messages = ai.next(messages, step_name=curr_fn()) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 243, in next | |
response = self.backoff_inference(messages) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\backoff\_sync.py", line 105, in retry | |
ret = target(*args, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 287, in backoff_inference | |
return self.llm.invoke(messages) # type: ignore | |
^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 270, in invoke | |
self.generate_prompt( | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 703, in generate_prompt | |
return self.generate(prompt_messages, stop=stop, callbacks=callbacks, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 560, in generate | |
raise e | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 550, in generate | |
self._generate_with_cache( | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 775, in _generate_with_cache | |
result = self._generate( | |
^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 755, in _generate | |
return generate_from_stream(stream_iter) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 102, in generate_from_stream | |
generation = next(stream, None) | |
^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 676, in _stream | |
stream = self._client.messages.create(**payload) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_utils\_utils.py", line 277, in wrapper | |
return func(*args, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\resources\messages.py", line 902, in create | |
return self._post( | |
^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 1266, in post | |
return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 942, in request | |
return self._request( | |
^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 968, in _request | |
request = self._build_request(options) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 461, in _build_request | |
headers = self._build_headers(options) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 416, in _build_headers | |
self._validate_headers(headers_dict, custom_headers) | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_client.py", line 192, in _validate_headers | |
raise TypeError( | |
TypeError: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted" | |
2024-07-25T12:05:50.603498 | |
UPLOADED FILES: | |
File: config.py | |
import yaml | |
from log_writer import logger | |
def load_config(): | |
""" | |
Loads the configuration from the 'config.yaml' file and sets the global variables accordingly. | |
If the 'GENERATE_MODEL' key in the configuration is set to 'gpt-4', it forces the use of 'gpt-4-turbo-preview' | |
as the value for the 'GENERATE_MODEL' key, since 'gpt-4' no longer supports json modes. | |
Returns: | |
None | |
""" | |
with open("config.yaml", "r") as conf: | |
config_content = yaml.safe_load(conf) | |
for key, value in config_content.items(): | |
if key == "GENERATE_MODEL" and value == "gpt-4": | |
globals()[ | |
key | |
] = "gpt-4-turbo-preview" # Force using gpt-4-turbo-preview if the user set the GENERATE_MODEL to gpt-4. Because gpt-4 is not longer supports json modes. | |
globals()[key] = value | |
logger(f"config: {key} -> {value}") | |
def edit_config(key, value): | |
""" | |
Edits the config file. | |
Args: | |
key (str): The key to edit. | |
value (str): The value to set. | |
Returns: | |
bool: True | |
""" | |
with open("config.yaml", "r") as conf: | |
config_content = conf.readlines() | |
with open("config.yaml", "w") as conf: | |
for line in config_content: | |
if line.startswith(key): | |
if value == True: | |
write_value = "True" | |
elif value == False: | |
write_value = "False" | |
else: | |
write_value = f'"{value}"' | |
if "#" in line: | |
conf.write(f"{key}: {write_value} # {line.split('#')[1]}\n") | |
else: | |
conf.write(f"{key}: {write_value}\n") | |
else: | |
conf.write(line) | |
return True | |
load_config() | |
File: config.yaml | |
########## EDIT REQUIRED ########## | |
# GPT SETTINGS # | |
# Get your api key from openai. Remember google/bing is always your best friend. | |
# Model names: gpt-4-turbo-preview, gpt-3.5-turbo, etc. | |
# Recommend -> gpt-4-turbo (Better performance, more expensive), gpt-4-o (Good performance, cheaper) | |
API_KEY: "" # Free API Key with GPT-4 access: https://github.com/CubeGPT/.github/discussions/1 | |
BASE_URL: "https://api.openai.com/v1/chat/completions" | |
GENERATION_MODEL: "gpt-4-turbo-2024-04-09" | |
FIXING_MODEL: "gpt-4-turbo-2024-04-09" | |
# DEVELOPER SETTINGS # | |
VERSION_NUMBER: "0.1.1" | |
# PROMPT SETTINGS # | |
# If you don't know what it is, please don't touch it. Be sure to backup before editing. | |
## Code Generation ## | |
SYS_GEN: | | |
You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) | |
Write the code & choose a artifact name for the following files with the infomation which is also provided by the user: | |
codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java | |
codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml | |
codes/%ARTIFACT_NAME%/src/main/resources/config.yml | |
codes/%ARTIFACT_NAME%/pom.xml | |
Response in json format: | |
{ | |
\"codes\": [ | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", | |
\"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", | |
\"code\": \"name: ...\\nversion: ...\\n...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", | |
\"code\": \"...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", | |
\"code\": \"...\" | |
} | |
] | |
} | |
You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Uncompeleted". | |
USR_GEN: | | |
%DESCRIPTION% | |
SYS_FIX: | | |
You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) | |
Fix the error in the code provided by user. The error message is also provided by the user. | |
Response in json format: | |
{ | |
\"codes\": [ | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", | |
\"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", | |
\"code\": \"name: ...\\nversion: ...\\n...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", | |
\"code\": \"...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", | |
\"code\": \"...\" | |
} | |
] | |
} | |
You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Original code" or "// Uncompeleted". | |
USR_FIX: | | |
Main.java: | |
%MAIN_JAVA% | |
plugin.yml: | |
%PLUGIN_YML% | |
config.yml: | |
%CONFIG_YML% | |
pom.xml: | |
%POM_XML% | |
error message: | |
%P_ERROR_MSG% | |
File: console.py | |
import sys | |
import uuid | |
import shutil | |
from log_writer import logger | |
import core | |
import config | |
import build | |
if __name__ == "__main__": | |
main_java = None | |
plugin_yml = None | |
config_yml = None | |
pom_xml = None | |
core.initialize() | |
print("BukkitGPT v3 beta console running") | |
# Get user inputs | |
name = input("Enter the plugin name: ") | |
description = input("Enter the plugin description: ") | |
artifact_name = name.replace(" ", "") | |
package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" | |
pkg_id_path = "" | |
for id in package_id.split("."): | |
pkg_id_path += id + "/" | |
logger(f"user_input -> name: {name}") | |
logger(f"user_input -> description: {description}") | |
logger(f"random_generate -> package_id: {package_id}") | |
logger(f"str_path -> pkg_id_path: {pkg_id_path}") | |
print("Generating plugin...") | |
codes = core.askgpt( | |
config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( | |
"%PKG_ID_LST%", pkg_id_path | |
), | |
config.USR_GEN.replace("%DESCRIPTION", description), | |
config.GENERATION_MODEL, | |
) | |
logger(f"codes: {codes}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
elif "Compilation failure": | |
print("Build failed. Passing the error to ChatGPT and let it to fix it?") | |
fix = input("Y/n: ") | |
if fix == "n": | |
print("Exiting...") | |
sys.exit(0) | |
else: | |
print("Passing the error to ChatGPT...") | |
files = [ | |
f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", | |
f"codes/{artifact_name}/src/main/resources/plugin.yml", | |
f"codes/{artifact_name}/src/main/resources/config.yml", | |
f"codes/{artifact_name}/pom.xml", | |
] | |
ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] | |
for file in files: | |
with open(file, "r") as f: | |
code = f.read() | |
id = ids[files.index(file)] | |
globals()[id] = code | |
print("Generating...") | |
codes = core.askgpt( | |
config.SYS_FIX.replace("%ARTIFACT_NAME%", artifact_name), | |
config.USR_FIX.replace("%MAIN_JAVA%", main_java) | |
.replace("%PLUGIN_YML%", plugin_yml) | |
.replace("%CONFIG_YML%", config_yml) | |
.replace("%POM_XML%", pom_xml) | |
.replace("%P_ERROR_MSG%", result), | |
config.FIXING_MODEL, | |
) | |
shutil.rmtree(f"codes/{artifact_name}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
else: | |
print( | |
"Build failed. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
print("Exiting...") | |
sys.exit(0) | |
else: | |
print( | |
"Unknown error. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
print("Exiting...") | |
sys.exit(0) | |
else: | |
print( | |
"Error: Please run console.py as the main program instead of importing it from another program." | |
) | |
File: core.py | |
from openai import OpenAI | |
import chardet | |
import sys | |
import json | |
import locale | |
import os | |
from log_writer import logger | |
import config | |
def initialize(): | |
""" | |
Initializes the software. | |
This function logs the software launch, including the version number and platform. | |
Args: | |
None | |
Returns: | |
None | |
""" | |
locale.setlocale(locale.LC_ALL, "en_US.UTF-8") | |
logger(f"Launch. Software version {config.VERSION_NUMBER}, platform {sys.platform}") | |
if ( | |
"gpt-3.5" in config.GENERATION_MODEL | |
and config.BYPASS_NO_GPT35_FOR_GENERATION_LIMIT is False | |
): | |
print( | |
"gpt-3.5 writes bugs *all the time* and is not recommended for code generation. Switching to gpt-4." | |
) | |
config.edit_config( | |
"GENERATION_MODEL", config.GENERATION_MODEL.replace("gpt-3.5", "gpt-4") | |
) | |
def askgpt( | |
system_prompt: str, | |
user_prompt: str, | |
model_name: str, | |
disable_json_mode: bool = False, | |
image_url: str = None, | |
): | |
""" | |
Interacts with ChatGPT using the specified prompts. | |
Args: | |
system_prompt (str): The system prompt. | |
user_prompt (str): The user prompt. | |
model_name (str): The model name to use. | |
disable_json_mode (bool): Whether to disable JSON mode. | |
Returns: | |
str: The response from ChatGPT. | |
""" | |
if image_url is not None and config.USE_DIFFERENT_APIKEY_FOR_VISION_MODEL: | |
logger("Using different API key for vision model.") | |
client = OpenAI(api_key=config.VISION_API_KEY, base_url=config.VISION_BASE_URL) | |
else: | |
client = OpenAI(api_key=config.API_KEY, base_url=config.BASE_URL) | |
logger("Initialized the OpenAI client.") | |
# Define the messages for the conversation | |
if image_url is not None: | |
messages = [ | |
{"role": "system", "content": system_prompt}, | |
{ | |
"role": "user", | |
"content": [ | |
{"type": "text", "text": user_prompt}, | |
{"type": "image_url", "image_url": {"url": image_url}}, | |
], | |
}, | |
] | |
else: | |
messages = [ | |
{"role": "system", "content": system_prompt}, | |
{"role": "user", "content": user_prompt}, | |
] | |
logger(f"askgpt: system {system_prompt}") | |
logger(f"askgpt: user {user_prompt}") | |
# Create a chat completion | |
if disable_json_mode: | |
response = client.chat.completions.create(model=model_name, messages=messages) | |
else: | |
response = client.chat.completions.create( | |
model=model_name, response_format={"type": "json_object"}, messages=messages | |
) | |
logger(f"askgpt: response {response}") | |
# Extract the assistant's reply | |
assistant_reply = response.choices[0].message.content | |
logger(f"askgpt: extracted reply {assistant_reply}") | |
return assistant_reply | |
def response_to_action(msg): | |
""" | |
Converts a response from ChatGPT to an action. | |
Args: | |
msg (str): The response from ChatGPT. | |
Returns: | |
str: The action to take. | |
""" | |
text = json.loads(msg) | |
codes = text["codes"] | |
for section in codes: | |
file = section["file"] | |
code = section["code"] | |
paths = file.split("/") | |
# Join the list elements to form a path | |
path = os.path.join(*paths) | |
# Get the directory path and the file name | |
dir_path, file_name = os.path.split(path) | |
# Create directories, if they don't exist | |
try: | |
os.makedirs(dir_path, exist_ok=True) | |
except FileNotFoundError: | |
pass | |
# Create the file | |
with open(path, "w") as f: | |
f.write(code) # Write an empty string to the file | |
def mixed_decode(text: str): | |
""" | |
Decode a mixed text containing both normal text and a byte sequence. | |
Args: | |
text (str): The mixed text to be decoded. | |
Returns: | |
str: The decoded text, where the byte sequence has been converted to its corresponding characters. | |
""" | |
# Split the normal text and the byte sequence | |
# Assuming the byte sequence is everything after the last colon and space ": " | |
try: | |
normal_text, byte_text = text.rsplit(": ", 1) | |
except (TypeError, ValueError): | |
# The text only contains normal text | |
return text | |
# Convert the byte sequence to actual bytes | |
byte_sequence = byte_text.encode( | |
"latin1" | |
) # latin1 encoding maps byte values directly to unicode code points | |
# Detect the encoding of the byte sequence | |
detected_encoding = chardet.detect(byte_sequence) | |
encoding = detected_encoding["encoding"] | |
# Decode the byte sequence | |
decoded_text = byte_sequence.decode(encoding) | |
# Combine the normal text with the decoded byte sequence | |
final_text = normal_text + ": " + decoded_text | |
return final_text | |
if __name__ == "__main__": | |
print("This script is not meant to be run directly. Please run console.py instead.") | |
File: log_writer.py | |
import os | |
from datetime import datetime | |
first_call_time = None | |
def get_log_filename(): | |
global first_call_time | |
if first_call_time is None: | |
first_call_time = datetime.now() | |
log_filename = first_call_time.strftime("logs/%b-%d-%H-%M-%S-%Y") | |
return log_filename | |
def logger(text: str): | |
log_filename = get_log_filename() | |
timestamp_prefix = datetime.now().strftime("[%H:%M:%S]") | |
log_line = f"{timestamp_prefix} {text}\n" | |
os.makedirs(os.path.dirname(log_filename), exist_ok=True) | |
with open(log_filename + ".log", "a", encoding="utf-8") as log_file: | |
log_file.write(log_line) | |
File: requirements.txt | |
openai>=1.13.3 | |
pyyaml | |
cx_Freeze | |
ttkbootstrap | |
playwright | |
chardet | |
File: ui.py | |
from cube_qgui.__init__ import CreateQGUI | |
from cube_qgui.banner_tools import * | |
from cube_qgui.notebook_tools import * | |
from playwright.sync_api import Playwright, sync_playwright | |
import os | |
import shutil | |
import uuid | |
from log_writer import logger | |
import config | |
import core | |
import build | |
# ---------- Functions ----------# | |
def open_config(args: dict): | |
""" | |
Opens the config file. | |
Args: | |
args (dict): A dictionary containing the necessary arguments. | |
Returns: | |
bool: Always True. | |
""" | |
os.system("notepad config.yaml") | |
return True | |
def save_apply_config(args: dict): | |
""" | |
Saves and applies the configuration. | |
Args: | |
args (dict): A dictionary containing the necessary arguments. | |
Returns: | |
bool: Always True. | |
""" | |
keys = ["API_KEY", "BASE_URL"] | |
for key in keys: | |
value = args[key].get() | |
if key == "ADVANCED_MODE": | |
value = True if value == 1 else False | |
else: | |
pass | |
config.edit_config(key, value) | |
config.load_config() | |
args["DevTool_CONFIG_API_KEY_DISPLAY"].set(f"CONFIG.API_KEY = {config.API_KEY}") | |
args["DevTools_CONFIG_BASE_URL_DISPLAY"].set(f"CONFIG.BASE_URL = {config.BASE_URL}") | |
return True | |
def load_config(args: dict): | |
""" | |
Loads the configuration. | |
Args: | |
args (dict): A dictionary containing the necessary arguments. | |
Returns: | |
bool: Always True. | |
""" | |
config.load_config() | |
args["API_KEY"].set(config.API_KEY) | |
args["BASE_URL"].set(config.BASE_URL) | |
return True | |
def print_args(args: dict): | |
""" | |
Prints the arguments. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
Returns: | |
bool: Always True. | |
""" | |
for arg, v_fun in args.items(): | |
print(f"Name: {arg}, Value: {v_fun.get()}") | |
return True | |
def raise_error(args: dict): | |
""" | |
Raises an error. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
""" | |
raise Exception("This is a test error.") | |
# ---------- Generate Function ----------# | |
def generate(args: dict): | |
""" | |
Generates the plugin. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
Returns: | |
bool: Always True. | |
""" | |
global error_msg, pkg_id_path | |
# Get user inputs | |
name = args["PluginName"].get() | |
description = args["PluginDescription"].get() | |
artifact_name = name.replace(" ", "") | |
package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" | |
pkg_id_path = "" | |
for id in package_id.split("."): | |
pkg_id_path += id + "/" | |
logger(f"user_input -> name: {name}") | |
logger(f"user_input -> description: {description}") | |
logger(f"random_generate -> package_id: {package_id}") | |
logger(f"str_path -> pkg_id_path: {pkg_id_path}") | |
print("Generating plugin...") | |
codes = core.askgpt( | |
config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( | |
"%PKG_ID_LST%", pkg_id_path | |
), | |
config.USR_GEN.replace("%DESCRIPTION", description), | |
config.GENERATION_MODEL, | |
) | |
logger(f"codes: {codes}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
elif "Compilation failure": | |
error_msg = result | |
print( | |
"Build failed. To pass the error to ChatGPT && let it fix, jump to the Fixing page and click the Fix button." | |
) | |
else: | |
print( | |
"Unknown error. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
return True | |
def fix(args: dict): | |
""" | |
Fixes the error. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
Returns: | |
bool: Always True. | |
""" | |
artifact_name = args["PluginName"].get() | |
print("Passing the error to ChatGPT...") | |
files = [ | |
f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", | |
f"codes/{artifact_name}/src/main/resources/plugin.yml", | |
f"codes/{artifact_name}/src/main/resources/config.yml", | |
f"codes/{artifact_name}/pom.xml", | |
] | |
ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] | |
main_java = None | |
plugin_yml = None | |
config_yml = None | |
pom_xml = None | |
for file in files: | |
with open(file, "r") as f: | |
code = f.read() | |
id = ids[files.index(file)] | |
globals()[id] = code | |
print("Generating...") | |
codes = core.askgpt( | |
config.SYS_FIX.replace("%ARTIFACT_NAME%", str(artifact_name)), | |
config.USR_FIX.replace("%MAIN_JAVA%", str(main_java)) | |
.replace("%PLUGIN_YML%", str(plugin_yml)) | |
.replace("%CONFIG_YML%", str(config_yml)) | |
.replace("%POM_XML%", str(pom_xml)) | |
.replave("%PKG_ID_LST%", pkg_id_path) | |
.replace("%P_ERROR_MSG%", str(error_msg)), | |
config.FIXING_MODEL, | |
) | |
shutil.rmtree(f"codes/{artifact_name}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
else: | |
print( | |
"Build failed again. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
return True | |
# ---------- Main Program ----------# | |
root = CreateQGUI(title="BukkitGPT-v3", tab_names=["Generate", "Settings", "DevTools"]) | |
error_msg = None | |
logger("Starting program.") | |
# Initialize Core | |
core.initialize() | |
print("BukkitGPT v3 beta console running") | |
# Banner | |
root.add_banner_tool(GitHub("https://github.com/CubeGPT/BukkitGPT-v3")) | |
# Generate Page | |
root.add_notebook_tool( | |
InputBox(name="PluginName", default="ExamplePlugin", label_info="Plugin Name") | |
) | |
root.add_notebook_tool( | |
InputBox( | |
name="PluginDescription", | |
default="Send msg 'hello' to every joined player.", | |
label_info="Plugin Description", | |
) | |
) | |
root.add_notebook_tool( | |
RunButton( | |
bind_func=generate, | |
name="Generate", | |
text="Generate Plugin", | |
checked_text="Generating...", | |
tab_index=0, | |
) | |
) | |
# Fixing Page # | |
# root.add_notebook_tool(Label(name="Fixing_DESCRIPTION", text="This is a fixing page. If the build fails, click the Fix button to fix the error in the LATEST build.", tab_index=1)) | |
# root.add_notebook_tool(RunButton(bind_func=fix, name="Fix", text="Fix", checked_text="Fixing...", tab_index=1)) | |
# Settings Page | |
root.add_notebook_tool( | |
InputBox(name="API_KEY", default=config.API_KEY, label_info="API Key", tab_index=1) | |
) | |
root.add_notebook_tool( | |
InputBox( | |
name="BASE_URL", default=config.BASE_URL, label_info="BASE URL", tab_index=1 | |
) | |
) | |
config_buttons = HorizontalToolsCombine( | |
[ | |
BaseButton( | |
bind_func=save_apply_config, | |
name="Save & Apply Config", | |
text="Save & Apply", | |
tab_index=1, | |
), | |
BaseButton( | |
bind_func=load_config, name="Load Config", text="Load Config", tab_index=1 | |
), | |
BaseButton( | |
bind_func=open_config, | |
name="Open Config", | |
text="Open Full Config", | |
tab_index=1, | |
), | |
] | |
) | |
root.add_notebook_tool(config_buttons) | |
# DevTools Page | |
root.add_notebook_tool( | |
Label( | |
name="DevTool_DESCRIPTION", | |
text="This is a testing page for developers. Ignore it if you are a normal user.", | |
tab_index=2, | |
) | |
) | |
root.add_notebook_tool( | |
Label( | |
name="DevTool_CONFIG_API_KEY_DISPLAY", | |
text=f"CONFIG.API_KEY = {config.API_KEY}", | |
tab_index=2, | |
) | |
) | |
root.add_notebook_tool( | |
Label( | |
name="DevTools_CONFIG_BASE_URL_DISPLAY", | |
text=f"CONFIG.BASE_URL = {config.BASE_URL}", | |
tab_index=2, | |
) | |
) | |
root.add_notebook_tool( | |
RunButton(bind_func=print_args, name="Print Args", text="Print Args", tab_index=2) | |
) | |
root.add_notebook_tool( | |
RunButton( | |
bind_func=raise_error, name="Raise Error", text="Raise Error", tab_index=2 | |
) | |
) | |
# Sidebar | |
root.set_navigation_about( | |
author="CubeGPT Team", | |
version=config.VERSION_NUMBER, | |
github_url="https://github.com/CubeGPT/BukkitGPT-v3", | |
) | |
# Run | |
root.run() | |
PROMPT: | |
添加生成DataPack的选项,使得用户可以选择生成Bukkit插件或者DataPack。 | |
在`ui.py`中可以在Generate Page里添加这行代码 `root.add_notebook_tool(RadioObviousToolButton(options=["BukkitPlugin", "Datapack(Experimental)"], name="GenerationType", title="Type", default="BukkitPlugin",tab_index=0))` | |
你还需要自行完成DataPack的生成逻辑。你可能需要更改的文件有`ui.py`, `core.py`, `config.yaml`, `console.py`。你还可能需要创建一些新的文件或文件夹,也有可能不需要。祝你好运。 | |
2024-07-25T12:05:51.036844 | |
CONSOLE OUTPUT: | |
Error while improving the project: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted" | |
Could you please upload the debug_log_file.txt in D:\zhousl\BukkitGPT\BukkitGPT-v3\.gpteng\memory/logs folder to github? | |
FULL STACK TRACE: | |
Traceback (most recent call last): | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 379, in handle_improve_mode | |
files_dict = agent.improve(files_dict, prompt) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\applications\cli\cli_agent.py", line 208, in improve | |
files_dict = self.improve_fn( | |
^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 311, in improve_fn | |
return _improve_loop(ai, files_dict, memory, messages) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 317, in _improve_loop | |
messages = ai.next(messages, step_name=curr_fn()) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 243, in next | |
response = self.backoff_inference(messages) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\backoff\_sync.py", line 105, in retry | |
ret = target(*args, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 287, in backoff_inference | |
return self.llm.invoke(messages) # type: ignore | |
^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 270, in invoke | |
self.generate_prompt( | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 703, in generate_prompt | |
return self.generate(prompt_messages, stop=stop, callbacks=callbacks, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 560, in generate | |
raise e | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 550, in generate | |
self._generate_with_cache( | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 775, in _generate_with_cache | |
result = self._generate( | |
^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 755, in _generate | |
return generate_from_stream(stream_iter) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 102, in generate_from_stream | |
generation = next(stream, None) | |
^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 676, in _stream | |
stream = self._client.messages.create(**payload) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_utils\_utils.py", line 277, in wrapper | |
return func(*args, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\resources\messages.py", line 902, in create | |
return self._post( | |
^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 1266, in post | |
return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 942, in request | |
return self._request( | |
^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 968, in _request | |
request = self._build_request(options) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 461, in _build_request | |
headers = self._build_headers(options) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 416, in _build_headers | |
self._validate_headers(headers_dict, custom_headers) | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_client.py", line 192, in _validate_headers | |
raise TypeError( | |
TypeError: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted" | |
2024-07-25T12:10:01.414816 | |
UPLOADED FILES: | |
File: config.py | |
import yaml | |
from log_writer import logger | |
def load_config(): | |
""" | |
Loads the configuration from the 'config.yaml' file and sets the global variables accordingly. | |
If the 'GENERATE_MODEL' key in the configuration is set to 'gpt-4', it forces the use of 'gpt-4-turbo-preview' | |
as the value for the 'GENERATE_MODEL' key, since 'gpt-4' no longer supports json modes. | |
Returns: | |
None | |
""" | |
with open("config.yaml", "r") as conf: | |
config_content = yaml.safe_load(conf) | |
for key, value in config_content.items(): | |
if key == "GENERATE_MODEL" and value == "gpt-4": | |
globals()[ | |
key | |
] = "gpt-4-turbo-preview" # Force using gpt-4-turbo-preview if the user set the GENERATE_MODEL to gpt-4. Because gpt-4 is not longer supports json modes. | |
globals()[key] = value | |
logger(f"config: {key} -> {value}") | |
def edit_config(key, value): | |
""" | |
Edits the config file. | |
Args: | |
key (str): The key to edit. | |
value (str): The value to set. | |
Returns: | |
bool: True | |
""" | |
with open("config.yaml", "r") as conf: | |
config_content = conf.readlines() | |
with open("config.yaml", "w") as conf: | |
for line in config_content: | |
if line.startswith(key): | |
if value == True: | |
write_value = "True" | |
elif value == False: | |
write_value = "False" | |
else: | |
write_value = f'"{value}"' | |
if "#" in line: | |
conf.write(f"{key}: {write_value} # {line.split('#')[1]}\n") | |
else: | |
conf.write(f"{key}: {write_value}\n") | |
else: | |
conf.write(line) | |
return True | |
load_config() | |
File: config.yaml | |
########## EDIT REQUIRED ########## | |
# GPT SETTINGS # | |
# Get your api key from openai. Remember google/bing is always your best friend. | |
# Model names: gpt-4-turbo-preview, gpt-3.5-turbo, etc. | |
# Recommend -> gpt-4-turbo (Better performance, more expensive), gpt-4-o (Good performance, cheaper) | |
API_KEY: "" # Free API Key with GPT-4 access: https://github.com/CubeGPT/.github/discussions/1 | |
BASE_URL: "https://api.openai.com/v1/chat/completions" | |
GENERATION_MODEL: "gpt-4-turbo-2024-04-09" | |
FIXING_MODEL: "gpt-4-turbo-2024-04-09" | |
# DEVELOPER SETTINGS # | |
VERSION_NUMBER: "0.1.1" | |
# PROMPT SETTINGS # | |
# If you don't know what it is, please don't touch it. Be sure to backup before editing. | |
## Code Generation ## | |
SYS_GEN: | | |
You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) | |
Write the code & choose a artifact name for the following files with the infomation which is also provided by the user: | |
codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java | |
codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml | |
codes/%ARTIFACT_NAME%/src/main/resources/config.yml | |
codes/%ARTIFACT_NAME%/pom.xml | |
Response in json format: | |
{ | |
\"codes\": [ | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", | |
\"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", | |
\"code\": \"name: ...\\nversion: ...\\n...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", | |
\"code\": \"...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", | |
\"code\": \"...\" | |
} | |
] | |
} | |
You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Uncompeleted". | |
USR_GEN: | | |
%DESCRIPTION% | |
SYS_FIX: | | |
You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) | |
Fix the error in the code provided by user. The error message is also provided by the user. | |
Response in json format: | |
{ | |
\"codes\": [ | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", | |
\"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", | |
\"code\": \"name: ...\\nversion: ...\\n...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", | |
\"code\": \"...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", | |
\"code\": \"...\" | |
} | |
] | |
} | |
You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Original code" or "// Uncompeleted". | |
USR_FIX: | | |
Main.java: | |
%MAIN_JAVA% | |
plugin.yml: | |
%PLUGIN_YML% | |
config.yml: | |
%CONFIG_YML% | |
pom.xml: | |
%POM_XML% | |
error message: | |
%P_ERROR_MSG% | |
File: console.py | |
import sys | |
import uuid | |
import shutil | |
from log_writer import logger | |
import core | |
import config | |
import build | |
if __name__ == "__main__": | |
main_java = None | |
plugin_yml = None | |
config_yml = None | |
pom_xml = None | |
core.initialize() | |
print("BukkitGPT v3 beta console running") | |
# Get user inputs | |
name = input("Enter the plugin name: ") | |
description = input("Enter the plugin description: ") | |
artifact_name = name.replace(" ", "") | |
package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" | |
pkg_id_path = "" | |
for id in package_id.split("."): | |
pkg_id_path += id + "/" | |
logger(f"user_input -> name: {name}") | |
logger(f"user_input -> description: {description}") | |
logger(f"random_generate -> package_id: {package_id}") | |
logger(f"str_path -> pkg_id_path: {pkg_id_path}") | |
print("Generating plugin...") | |
codes = core.askgpt( | |
config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( | |
"%PKG_ID_LST%", pkg_id_path | |
), | |
config.USR_GEN.replace("%DESCRIPTION", description), | |
config.GENERATION_MODEL, | |
) | |
logger(f"codes: {codes}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
elif "Compilation failure": | |
print("Build failed. Passing the error to ChatGPT and let it to fix it?") | |
fix = input("Y/n: ") | |
if fix == "n": | |
print("Exiting...") | |
sys.exit(0) | |
else: | |
print("Passing the error to ChatGPT...") | |
files = [ | |
f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", | |
f"codes/{artifact_name}/src/main/resources/plugin.yml", | |
f"codes/{artifact_name}/src/main/resources/config.yml", | |
f"codes/{artifact_name}/pom.xml", | |
] | |
ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] | |
for file in files: | |
with open(file, "r") as f: | |
code = f.read() | |
id = ids[files.index(file)] | |
globals()[id] = code | |
print("Generating...") | |
codes = core.askgpt( | |
config.SYS_FIX.replace("%ARTIFACT_NAME%", artifact_name), | |
config.USR_FIX.replace("%MAIN_JAVA%", main_java) | |
.replace("%PLUGIN_YML%", plugin_yml) | |
.replace("%CONFIG_YML%", config_yml) | |
.replace("%POM_XML%", pom_xml) | |
.replace("%P_ERROR_MSG%", result), | |
config.FIXING_MODEL, | |
) | |
shutil.rmtree(f"codes/{artifact_name}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
else: | |
print( | |
"Build failed. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
print("Exiting...") | |
sys.exit(0) | |
else: | |
print( | |
"Unknown error. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
print("Exiting...") | |
sys.exit(0) | |
else: | |
print( | |
"Error: Please run console.py as the main program instead of importing it from another program." | |
) | |
File: core.py | |
from openai import OpenAI | |
import chardet | |
import sys | |
import json | |
import locale | |
import os | |
from log_writer import logger | |
import config | |
def initialize(): | |
""" | |
Initializes the software. | |
This function logs the software launch, including the version number and platform. | |
Args: | |
None | |
Returns: | |
None | |
""" | |
locale.setlocale(locale.LC_ALL, "en_US.UTF-8") | |
logger(f"Launch. Software version {config.VERSION_NUMBER}, platform {sys.platform}") | |
if ( | |
"gpt-3.5" in config.GENERATION_MODEL | |
and config.BYPASS_NO_GPT35_FOR_GENERATION_LIMIT is False | |
): | |
print( | |
"gpt-3.5 writes bugs *all the time* and is not recommended for code generation. Switching to gpt-4." | |
) | |
config.edit_config( | |
"GENERATION_MODEL", config.GENERATION_MODEL.replace("gpt-3.5", "gpt-4") | |
) | |
def askgpt( | |
system_prompt: str, | |
user_prompt: str, | |
model_name: str, | |
disable_json_mode: bool = False, | |
image_url: str = None, | |
): | |
""" | |
Interacts with ChatGPT using the specified prompts. | |
Args: | |
system_prompt (str): The system prompt. | |
user_prompt (str): The user prompt. | |
model_name (str): The model name to use. | |
disable_json_mode (bool): Whether to disable JSON mode. | |
Returns: | |
str: The response from ChatGPT. | |
""" | |
if image_url is not None and config.USE_DIFFERENT_APIKEY_FOR_VISION_MODEL: | |
logger("Using different API key for vision model.") | |
client = OpenAI(api_key=config.VISION_API_KEY, base_url=config.VISION_BASE_URL) | |
else: | |
client = OpenAI(api_key=config.API_KEY, base_url=config.BASE_URL) | |
logger("Initialized the OpenAI client.") | |
# Define the messages for the conversation | |
if image_url is not None: | |
messages = [ | |
{"role": "system", "content": system_prompt}, | |
{ | |
"role": "user", | |
"content": [ | |
{"type": "text", "text": user_prompt}, | |
{"type": "image_url", "image_url": {"url": image_url}}, | |
], | |
}, | |
] | |
else: | |
messages = [ | |
{"role": "system", "content": system_prompt}, | |
{"role": "user", "content": user_prompt}, | |
] | |
logger(f"askgpt: system {system_prompt}") | |
logger(f"askgpt: user {user_prompt}") | |
# Create a chat completion | |
if disable_json_mode: | |
response = client.chat.completions.create(model=model_name, messages=messages) | |
else: | |
response = client.chat.completions.create( | |
model=model_name, response_format={"type": "json_object"}, messages=messages | |
) | |
logger(f"askgpt: response {response}") | |
# Extract the assistant's reply | |
assistant_reply = response.choices[0].message.content | |
logger(f"askgpt: extracted reply {assistant_reply}") | |
return assistant_reply | |
def response_to_action(msg): | |
""" | |
Converts a response from ChatGPT to an action. | |
Args: | |
msg (str): The response from ChatGPT. | |
Returns: | |
str: The action to take. | |
""" | |
text = json.loads(msg) | |
codes = text["codes"] | |
for section in codes: | |
file = section["file"] | |
code = section["code"] | |
paths = file.split("/") | |
# Join the list elements to form a path | |
path = os.path.join(*paths) | |
# Get the directory path and the file name | |
dir_path, file_name = os.path.split(path) | |
# Create directories, if they don't exist | |
try: | |
os.makedirs(dir_path, exist_ok=True) | |
except FileNotFoundError: | |
pass | |
# Create the file | |
with open(path, "w") as f: | |
f.write(code) # Write an empty string to the file | |
def mixed_decode(text: str): | |
""" | |
Decode a mixed text containing both normal text and a byte sequence. | |
Args: | |
text (str): The mixed text to be decoded. | |
Returns: | |
str: The decoded text, where the byte sequence has been converted to its corresponding characters. | |
""" | |
# Split the normal text and the byte sequence | |
# Assuming the byte sequence is everything after the last colon and space ": " | |
try: | |
normal_text, byte_text = text.rsplit(": ", 1) | |
except (TypeError, ValueError): | |
# The text only contains normal text | |
return text | |
# Convert the byte sequence to actual bytes | |
byte_sequence = byte_text.encode( | |
"latin1" | |
) # latin1 encoding maps byte values directly to unicode code points | |
# Detect the encoding of the byte sequence | |
detected_encoding = chardet.detect(byte_sequence) | |
encoding = detected_encoding["encoding"] | |
# Decode the byte sequence | |
decoded_text = byte_sequence.decode(encoding) | |
# Combine the normal text with the decoded byte sequence | |
final_text = normal_text + ": " + decoded_text | |
return final_text | |
if __name__ == "__main__": | |
print("This script is not meant to be run directly. Please run console.py instead.") | |
File: log_writer.py | |
import os | |
from datetime import datetime | |
first_call_time = None | |
def get_log_filename(): | |
global first_call_time | |
if first_call_time is None: | |
first_call_time = datetime.now() | |
log_filename = first_call_time.strftime("logs/%b-%d-%H-%M-%S-%Y") | |
return log_filename | |
def logger(text: str): | |
log_filename = get_log_filename() | |
timestamp_prefix = datetime.now().strftime("[%H:%M:%S]") | |
log_line = f"{timestamp_prefix} {text}\n" | |
os.makedirs(os.path.dirname(log_filename), exist_ok=True) | |
with open(log_filename + ".log", "a", encoding="utf-8") as log_file: | |
log_file.write(log_line) | |
File: requirements.txt | |
openai>=1.13.3 | |
pyyaml | |
cx_Freeze | |
ttkbootstrap | |
playwright | |
chardet | |
File: ui.py | |
from cube_qgui.__init__ import CreateQGUI | |
from cube_qgui.banner_tools import * | |
from cube_qgui.notebook_tools import * | |
from playwright.sync_api import Playwright, sync_playwright | |
import os | |
import shutil | |
import uuid | |
from log_writer import logger | |
import config | |
import core | |
import build | |
# ---------- Functions ----------# | |
def open_config(args: dict): | |
""" | |
Opens the config file. | |
Args: | |
args (dict): A dictionary containing the necessary arguments. | |
Returns: | |
bool: Always True. | |
""" | |
os.system("notepad config.yaml") | |
return True | |
def save_apply_config(args: dict): | |
""" | |
Saves and applies the configuration. | |
Args: | |
args (dict): A dictionary containing the necessary arguments. | |
Returns: | |
bool: Always True. | |
""" | |
keys = ["API_KEY", "BASE_URL"] | |
for key in keys: | |
value = args[key].get() | |
if key == "ADVANCED_MODE": | |
value = True if value == 1 else False | |
else: | |
pass | |
config.edit_config(key, value) | |
config.load_config() | |
args["DevTool_CONFIG_API_KEY_DISPLAY"].set(f"CONFIG.API_KEY = {config.API_KEY}") | |
args["DevTools_CONFIG_BASE_URL_DISPLAY"].set(f"CONFIG.BASE_URL = {config.BASE_URL}") | |
return True | |
def load_config(args: dict): | |
""" | |
Loads the configuration. | |
Args: | |
args (dict): A dictionary containing the necessary arguments. | |
Returns: | |
bool: Always True. | |
""" | |
config.load_config() | |
args["API_KEY"].set(config.API_KEY) | |
args["BASE_URL"].set(config.BASE_URL) | |
return True | |
def print_args(args: dict): | |
""" | |
Prints the arguments. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
Returns: | |
bool: Always True. | |
""" | |
for arg, v_fun in args.items(): | |
print(f"Name: {arg}, Value: {v_fun.get()}") | |
return True | |
def raise_error(args: dict): | |
""" | |
Raises an error. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
""" | |
raise Exception("This is a test error.") | |
# ---------- Generate Function ----------# | |
def generate(args: dict): | |
""" | |
Generates the plugin. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
Returns: | |
bool: Always True. | |
""" | |
global error_msg, pkg_id_path | |
# Get user inputs | |
name = args["PluginName"].get() | |
description = args["PluginDescription"].get() | |
artifact_name = name.replace(" ", "") | |
package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" | |
pkg_id_path = "" | |
for id in package_id.split("."): | |
pkg_id_path += id + "/" | |
logger(f"user_input -> name: {name}") | |
logger(f"user_input -> description: {description}") | |
logger(f"random_generate -> package_id: {package_id}") | |
logger(f"str_path -> pkg_id_path: {pkg_id_path}") | |
print("Generating plugin...") | |
codes = core.askgpt( | |
config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( | |
"%PKG_ID_LST%", pkg_id_path | |
), | |
config.USR_GEN.replace("%DESCRIPTION", description), | |
config.GENERATION_MODEL, | |
) | |
logger(f"codes: {codes}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
elif "Compilation failure": | |
error_msg = result | |
print( | |
"Build failed. To pass the error to ChatGPT && let it fix, jump to the Fixing page and click the Fix button." | |
) | |
else: | |
print( | |
"Unknown error. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
return True | |
def fix(args: dict): | |
""" | |
Fixes the error. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
Returns: | |
bool: Always True. | |
""" | |
artifact_name = args["PluginName"].get() | |
print("Passing the error to ChatGPT...") | |
files = [ | |
f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", | |
f"codes/{artifact_name}/src/main/resources/plugin.yml", | |
f"codes/{artifact_name}/src/main/resources/config.yml", | |
f"codes/{artifact_name}/pom.xml", | |
] | |
ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] | |
main_java = None | |
plugin_yml = None | |
config_yml = None | |
pom_xml = None | |
for file in files: | |
with open(file, "r") as f: | |
code = f.read() | |
id = ids[files.index(file)] | |
globals()[id] = code | |
print("Generating...") | |
codes = core.askgpt( | |
config.SYS_FIX.replace("%ARTIFACT_NAME%", str(artifact_name)), | |
config.USR_FIX.replace("%MAIN_JAVA%", str(main_java)) | |
.replace("%PLUGIN_YML%", str(plugin_yml)) | |
.replace("%CONFIG_YML%", str(config_yml)) | |
.replace("%POM_XML%", str(pom_xml)) | |
.replave("%PKG_ID_LST%", pkg_id_path) | |
.replace("%P_ERROR_MSG%", str(error_msg)), | |
config.FIXING_MODEL, | |
) | |
shutil.rmtree(f"codes/{artifact_name}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
else: | |
print( | |
"Build failed again. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
return True | |
# ---------- Main Program ----------# | |
root = CreateQGUI(title="BukkitGPT-v3", tab_names=["Generate", "Settings", "DevTools"]) | |
error_msg = None | |
logger("Starting program.") | |
# Initialize Core | |
core.initialize() | |
print("BukkitGPT v3 beta console running") | |
# Banner | |
root.add_banner_tool(GitHub("https://github.com/CubeGPT/BukkitGPT-v3")) | |
# Generate Page | |
root.add_notebook_tool( | |
InputBox(name="PluginName", default="ExamplePlugin", label_info="Plugin Name") | |
) | |
root.add_notebook_tool( | |
InputBox( | |
name="PluginDescription", | |
default="Send msg 'hello' to every joined player.", | |
label_info="Plugin Description", | |
) | |
) | |
root.add_notebook_tool( | |
RunButton( | |
bind_func=generate, | |
name="Generate", | |
text="Generate Plugin", | |
checked_text="Generating...", | |
tab_index=0, | |
) | |
) | |
# Fixing Page # | |
# root.add_notebook_tool(Label(name="Fixing_DESCRIPTION", text="This is a fixing page. If the build fails, click the Fix button to fix the error in the LATEST build.", tab_index=1)) | |
# root.add_notebook_tool(RunButton(bind_func=fix, name="Fix", text="Fix", checked_text="Fixing...", tab_index=1)) | |
# Settings Page | |
root.add_notebook_tool( | |
InputBox(name="API_KEY", default=config.API_KEY, label_info="API Key", tab_index=1) | |
) | |
root.add_notebook_tool( | |
InputBox( | |
name="BASE_URL", default=config.BASE_URL, label_info="BASE URL", tab_index=1 | |
) | |
) | |
config_buttons = HorizontalToolsCombine( | |
[ | |
BaseButton( | |
bind_func=save_apply_config, | |
name="Save & Apply Config", | |
text="Save & Apply", | |
tab_index=1, | |
), | |
BaseButton( | |
bind_func=load_config, name="Load Config", text="Load Config", tab_index=1 | |
), | |
BaseButton( | |
bind_func=open_config, | |
name="Open Config", | |
text="Open Full Config", | |
tab_index=1, | |
), | |
] | |
) | |
root.add_notebook_tool(config_buttons) | |
# DevTools Page | |
root.add_notebook_tool( | |
Label( | |
name="DevTool_DESCRIPTION", | |
text="This is a testing page for developers. Ignore it if you are a normal user.", | |
tab_index=2, | |
) | |
) | |
root.add_notebook_tool( | |
Label( | |
name="DevTool_CONFIG_API_KEY_DISPLAY", | |
text=f"CONFIG.API_KEY = {config.API_KEY}", | |
tab_index=2, | |
) | |
) | |
root.add_notebook_tool( | |
Label( | |
name="DevTools_CONFIG_BASE_URL_DISPLAY", | |
text=f"CONFIG.BASE_URL = {config.BASE_URL}", | |
tab_index=2, | |
) | |
) | |
root.add_notebook_tool( | |
RunButton(bind_func=print_args, name="Print Args", text="Print Args", tab_index=2) | |
) | |
root.add_notebook_tool( | |
RunButton( | |
bind_func=raise_error, name="Raise Error", text="Raise Error", tab_index=2 | |
) | |
) | |
# Sidebar | |
root.set_navigation_about( | |
author="CubeGPT Team", | |
version=config.VERSION_NUMBER, | |
github_url="https://github.com/CubeGPT/BukkitGPT-v3", | |
) | |
# Run | |
root.run() | |
PROMPT: | |
添加生成DataPack的选项,使得用户可以选择生成Bukkit插件或者DataPack。 | |
在`ui.py`中可以在Generate Page里添加这行代码 `root.add_notebook_tool(RadioObviousToolButton(options=["BukkitPlugin", "Datapack(Experimental)"], name="GenerationType", title="Type", default="BukkitPlugin",tab_index=0))` | |
你还需要自行完成DataPack的生成逻辑。你可能需要更改的文件有`ui.py`, `core.py`, `config.yaml`, `console.py`。你还可能需要创建一些新的文件或文件夹,也有可能不需要。祝你好运。 | |
2024-07-25T12:10:01.841094 | |
CONSOLE OUTPUT: | |
Error while improving the project: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted" | |
Could you please upload the debug_log_file.txt in D:\zhousl\BukkitGPT\BukkitGPT-v3\.gpteng\memory/logs folder to github? | |
FULL STACK TRACE: | |
Traceback (most recent call last): | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 379, in handle_improve_mode | |
files_dict = agent.improve(files_dict, prompt) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\applications\cli\cli_agent.py", line 208, in improve | |
files_dict = self.improve_fn( | |
^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 311, in improve_fn | |
return _improve_loop(ai, files_dict, memory, messages) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 317, in _improve_loop | |
messages = ai.next(messages, step_name=curr_fn()) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 243, in next | |
response = self.backoff_inference(messages) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\backoff\_sync.py", line 105, in retry | |
ret = target(*args, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 287, in backoff_inference | |
return self.llm.invoke(messages) # type: ignore | |
^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 270, in invoke | |
self.generate_prompt( | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 703, in generate_prompt | |
return self.generate(prompt_messages, stop=stop, callbacks=callbacks, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 560, in generate | |
raise e | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 550, in generate | |
self._generate_with_cache( | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 775, in _generate_with_cache | |
result = self._generate( | |
^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 755, in _generate | |
return generate_from_stream(stream_iter) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 102, in generate_from_stream | |
generation = next(stream, None) | |
^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 676, in _stream | |
stream = self._client.messages.create(**payload) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_utils\_utils.py", line 277, in wrapper | |
return func(*args, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\resources\messages.py", line 902, in create | |
return self._post( | |
^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 1266, in post | |
return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 942, in request | |
return self._request( | |
^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 968, in _request | |
request = self._build_request(options) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 461, in _build_request | |
headers = self._build_headers(options) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 416, in _build_headers | |
self._validate_headers(headers_dict, custom_headers) | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_client.py", line 192, in _validate_headers | |
raise TypeError( | |
TypeError: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted" | |
2024-07-25T12:12:17.814305 | |
UPLOADED FILES: | |
File: config.py | |
import yaml | |
from log_writer import logger | |
def load_config(): | |
""" | |
Loads the configuration from the 'config.yaml' file and sets the global variables accordingly. | |
If the 'GENERATE_MODEL' key in the configuration is set to 'gpt-4', it forces the use of 'gpt-4-turbo-preview' | |
as the value for the 'GENERATE_MODEL' key, since 'gpt-4' no longer supports json modes. | |
Returns: | |
None | |
""" | |
with open("config.yaml", "r") as conf: | |
config_content = yaml.safe_load(conf) | |
for key, value in config_content.items(): | |
if key == "GENERATE_MODEL" and value == "gpt-4": | |
globals()[ | |
key | |
] = "gpt-4-turbo-preview" # Force using gpt-4-turbo-preview if the user set the GENERATE_MODEL to gpt-4. Because gpt-4 is not longer supports json modes. | |
globals()[key] = value | |
logger(f"config: {key} -> {value}") | |
def edit_config(key, value): | |
""" | |
Edits the config file. | |
Args: | |
key (str): The key to edit. | |
value (str): The value to set. | |
Returns: | |
bool: True | |
""" | |
with open("config.yaml", "r") as conf: | |
config_content = conf.readlines() | |
with open("config.yaml", "w") as conf: | |
for line in config_content: | |
if line.startswith(key): | |
if value == True: | |
write_value = "True" | |
elif value == False: | |
write_value = "False" | |
else: | |
write_value = f'"{value}"' | |
if "#" in line: | |
conf.write(f"{key}: {write_value} # {line.split('#')[1]}\n") | |
else: | |
conf.write(f"{key}: {write_value}\n") | |
else: | |
conf.write(line) | |
return True | |
load_config() | |
File: config.yaml | |
########## EDIT REQUIRED ########## | |
# GPT SETTINGS # | |
# Get your api key from openai. Remember google/bing is always your best friend. | |
# Model names: gpt-4-turbo-preview, gpt-3.5-turbo, etc. | |
# Recommend -> gpt-4-turbo (Better performance, more expensive), gpt-4-o (Good performance, cheaper) | |
API_KEY: "" # Free API Key with GPT-4 access: https://github.com/CubeGPT/.github/discussions/1 | |
BASE_URL: "https://api.openai.com/v1/chat/completions" | |
GENERATION_MODEL: "gpt-4-turbo-2024-04-09" | |
FIXING_MODEL: "gpt-4-turbo-2024-04-09" | |
# DEVELOPER SETTINGS # | |
VERSION_NUMBER: "0.1.1" | |
# PROMPT SETTINGS # | |
# If you don't know what it is, please don't touch it. Be sure to backup before editing. | |
## Code Generation ## | |
SYS_GEN: | | |
You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) | |
Write the code & choose a artifact name for the following files with the infomation which is also provided by the user: | |
codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java | |
codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml | |
codes/%ARTIFACT_NAME%/src/main/resources/config.yml | |
codes/%ARTIFACT_NAME%/pom.xml | |
Response in json format: | |
{ | |
\"codes\": [ | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", | |
\"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", | |
\"code\": \"name: ...\\nversion: ...\\n...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", | |
\"code\": \"...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", | |
\"code\": \"...\" | |
} | |
] | |
} | |
You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Uncompeleted". | |
USR_GEN: | | |
%DESCRIPTION% | |
SYS_FIX: | | |
You're a minecraft bukkit plugin coder AI. Game Version: 1.13.2 (1.13.2-R0.1-SNAPSHOT) | |
Fix the error in the code provided by user. The error message is also provided by the user. | |
Response in json format: | |
{ | |
\"codes\": [ | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/java/%PKG_ID_LST%Main.java\", | |
\"code\": \"package ...;\\nimport org.bukkit.Bukkit;\\npublic class Main extends JavaPlugin implements CommandExecutor {\\n... (The code you need to write)\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/plugin.yml\", | |
\"code\": \"name: ...\\nversion: ...\\n...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/src/main/resources/config.yml\", | |
\"code\": \"...\" | |
}, | |
{ | |
\"file\": \"codes/%ARTIFACT_NAME%/pom.xml\", | |
\"code\": \"...\" | |
} | |
] | |
} | |
You should never response anything else. Never use Markdown format. Use \n for line feed, and never forget to use \ before ". Never write uncompeleted codes, such as leave a comment that says "// Your codes here" or "// Original code" or "// Uncompeleted". | |
USR_FIX: | | |
Main.java: | |
%MAIN_JAVA% | |
plugin.yml: | |
%PLUGIN_YML% | |
config.yml: | |
%CONFIG_YML% | |
pom.xml: | |
%POM_XML% | |
error message: | |
%P_ERROR_MSG% | |
File: console.py | |
import sys | |
import uuid | |
import shutil | |
from log_writer import logger | |
import core | |
import config | |
import build | |
if __name__ == "__main__": | |
main_java = None | |
plugin_yml = None | |
config_yml = None | |
pom_xml = None | |
core.initialize() | |
print("BukkitGPT v3 beta console running") | |
# Get user inputs | |
name = input("Enter the plugin name: ") | |
description = input("Enter the plugin description: ") | |
artifact_name = name.replace(" ", "") | |
package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" | |
pkg_id_path = "" | |
for id in package_id.split("."): | |
pkg_id_path += id + "/" | |
logger(f"user_input -> name: {name}") | |
logger(f"user_input -> description: {description}") | |
logger(f"random_generate -> package_id: {package_id}") | |
logger(f"str_path -> pkg_id_path: {pkg_id_path}") | |
print("Generating plugin...") | |
codes = core.askgpt( | |
config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( | |
"%PKG_ID_LST%", pkg_id_path | |
), | |
config.USR_GEN.replace("%DESCRIPTION", description), | |
config.GENERATION_MODEL, | |
) | |
logger(f"codes: {codes}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
elif "Compilation failure": | |
print("Build failed. Passing the error to ChatGPT and let it to fix it?") | |
fix = input("Y/n: ") | |
if fix == "n": | |
print("Exiting...") | |
sys.exit(0) | |
else: | |
print("Passing the error to ChatGPT...") | |
files = [ | |
f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", | |
f"codes/{artifact_name}/src/main/resources/plugin.yml", | |
f"codes/{artifact_name}/src/main/resources/config.yml", | |
f"codes/{artifact_name}/pom.xml", | |
] | |
ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] | |
for file in files: | |
with open(file, "r") as f: | |
code = f.read() | |
id = ids[files.index(file)] | |
globals()[id] = code | |
print("Generating...") | |
codes = core.askgpt( | |
config.SYS_FIX.replace("%ARTIFACT_NAME%", artifact_name), | |
config.USR_FIX.replace("%MAIN_JAVA%", main_java) | |
.replace("%PLUGIN_YML%", plugin_yml) | |
.replace("%CONFIG_YML%", config_yml) | |
.replace("%POM_XML%", pom_xml) | |
.replace("%P_ERROR_MSG%", result), | |
config.FIXING_MODEL, | |
) | |
shutil.rmtree(f"codes/{artifact_name}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
else: | |
print( | |
"Build failed. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
print("Exiting...") | |
sys.exit(0) | |
else: | |
print( | |
"Unknown error. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
print("Exiting...") | |
sys.exit(0) | |
else: | |
print( | |
"Error: Please run console.py as the main program instead of importing it from another program." | |
) | |
File: core.py | |
from openai import OpenAI | |
import chardet | |
import sys | |
import json | |
import locale | |
import os | |
from log_writer import logger | |
import config | |
def initialize(): | |
""" | |
Initializes the software. | |
This function logs the software launch, including the version number and platform. | |
Args: | |
None | |
Returns: | |
None | |
""" | |
locale.setlocale(locale.LC_ALL, "en_US.UTF-8") | |
logger(f"Launch. Software version {config.VERSION_NUMBER}, platform {sys.platform}") | |
if ( | |
"gpt-3.5" in config.GENERATION_MODEL | |
and config.BYPASS_NO_GPT35_FOR_GENERATION_LIMIT is False | |
): | |
print( | |
"gpt-3.5 writes bugs *all the time* and is not recommended for code generation. Switching to gpt-4." | |
) | |
config.edit_config( | |
"GENERATION_MODEL", config.GENERATION_MODEL.replace("gpt-3.5", "gpt-4") | |
) | |
def askgpt( | |
system_prompt: str, | |
user_prompt: str, | |
model_name: str, | |
disable_json_mode: bool = False, | |
image_url: str = None, | |
): | |
""" | |
Interacts with ChatGPT using the specified prompts. | |
Args: | |
system_prompt (str): The system prompt. | |
user_prompt (str): The user prompt. | |
model_name (str): The model name to use. | |
disable_json_mode (bool): Whether to disable JSON mode. | |
Returns: | |
str: The response from ChatGPT. | |
""" | |
if image_url is not None and config.USE_DIFFERENT_APIKEY_FOR_VISION_MODEL: | |
logger("Using different API key for vision model.") | |
client = OpenAI(api_key=config.VISION_API_KEY, base_url=config.VISION_BASE_URL) | |
else: | |
client = OpenAI(api_key=config.API_KEY, base_url=config.BASE_URL) | |
logger("Initialized the OpenAI client.") | |
# Define the messages for the conversation | |
if image_url is not None: | |
messages = [ | |
{"role": "system", "content": system_prompt}, | |
{ | |
"role": "user", | |
"content": [ | |
{"type": "text", "text": user_prompt}, | |
{"type": "image_url", "image_url": {"url": image_url}}, | |
], | |
}, | |
] | |
else: | |
messages = [ | |
{"role": "system", "content": system_prompt}, | |
{"role": "user", "content": user_prompt}, | |
] | |
logger(f"askgpt: system {system_prompt}") | |
logger(f"askgpt: user {user_prompt}") | |
# Create a chat completion | |
if disable_json_mode: | |
response = client.chat.completions.create(model=model_name, messages=messages) | |
else: | |
response = client.chat.completions.create( | |
model=model_name, response_format={"type": "json_object"}, messages=messages | |
) | |
logger(f"askgpt: response {response}") | |
# Extract the assistant's reply | |
assistant_reply = response.choices[0].message.content | |
logger(f"askgpt: extracted reply {assistant_reply}") | |
return assistant_reply | |
def response_to_action(msg): | |
""" | |
Converts a response from ChatGPT to an action. | |
Args: | |
msg (str): The response from ChatGPT. | |
Returns: | |
str: The action to take. | |
""" | |
text = json.loads(msg) | |
codes = text["codes"] | |
for section in codes: | |
file = section["file"] | |
code = section["code"] | |
paths = file.split("/") | |
# Join the list elements to form a path | |
path = os.path.join(*paths) | |
# Get the directory path and the file name | |
dir_path, file_name = os.path.split(path) | |
# Create directories, if they don't exist | |
try: | |
os.makedirs(dir_path, exist_ok=True) | |
except FileNotFoundError: | |
pass | |
# Create the file | |
with open(path, "w") as f: | |
f.write(code) # Write an empty string to the file | |
def mixed_decode(text: str): | |
""" | |
Decode a mixed text containing both normal text and a byte sequence. | |
Args: | |
text (str): The mixed text to be decoded. | |
Returns: | |
str: The decoded text, where the byte sequence has been converted to its corresponding characters. | |
""" | |
# Split the normal text and the byte sequence | |
# Assuming the byte sequence is everything after the last colon and space ": " | |
try: | |
normal_text, byte_text = text.rsplit(": ", 1) | |
except (TypeError, ValueError): | |
# The text only contains normal text | |
return text | |
# Convert the byte sequence to actual bytes | |
byte_sequence = byte_text.encode( | |
"latin1" | |
) # latin1 encoding maps byte values directly to unicode code points | |
# Detect the encoding of the byte sequence | |
detected_encoding = chardet.detect(byte_sequence) | |
encoding = detected_encoding["encoding"] | |
# Decode the byte sequence | |
decoded_text = byte_sequence.decode(encoding) | |
# Combine the normal text with the decoded byte sequence | |
final_text = normal_text + ": " + decoded_text | |
return final_text | |
if __name__ == "__main__": | |
print("This script is not meant to be run directly. Please run console.py instead.") | |
File: log_writer.py | |
import os | |
from datetime import datetime | |
first_call_time = None | |
def get_log_filename(): | |
global first_call_time | |
if first_call_time is None: | |
first_call_time = datetime.now() | |
log_filename = first_call_time.strftime("logs/%b-%d-%H-%M-%S-%Y") | |
return log_filename | |
def logger(text: str): | |
log_filename = get_log_filename() | |
timestamp_prefix = datetime.now().strftime("[%H:%M:%S]") | |
log_line = f"{timestamp_prefix} {text}\n" | |
os.makedirs(os.path.dirname(log_filename), exist_ok=True) | |
with open(log_filename + ".log", "a", encoding="utf-8") as log_file: | |
log_file.write(log_line) | |
File: requirements.txt | |
openai>=1.13.3 | |
pyyaml | |
cx_Freeze | |
ttkbootstrap | |
playwright | |
chardet | |
File: ui.py | |
from cube_qgui.__init__ import CreateQGUI | |
from cube_qgui.banner_tools import * | |
from cube_qgui.notebook_tools import * | |
from playwright.sync_api import Playwright, sync_playwright | |
import os | |
import shutil | |
import uuid | |
from log_writer import logger | |
import config | |
import core | |
import build | |
# ---------- Functions ----------# | |
def open_config(args: dict): | |
""" | |
Opens the config file. | |
Args: | |
args (dict): A dictionary containing the necessary arguments. | |
Returns: | |
bool: Always True. | |
""" | |
os.system("notepad config.yaml") | |
return True | |
def save_apply_config(args: dict): | |
""" | |
Saves and applies the configuration. | |
Args: | |
args (dict): A dictionary containing the necessary arguments. | |
Returns: | |
bool: Always True. | |
""" | |
keys = ["API_KEY", "BASE_URL"] | |
for key in keys: | |
value = args[key].get() | |
if key == "ADVANCED_MODE": | |
value = True if value == 1 else False | |
else: | |
pass | |
config.edit_config(key, value) | |
config.load_config() | |
args["DevTool_CONFIG_API_KEY_DISPLAY"].set(f"CONFIG.API_KEY = {config.API_KEY}") | |
args["DevTools_CONFIG_BASE_URL_DISPLAY"].set(f"CONFIG.BASE_URL = {config.BASE_URL}") | |
return True | |
def load_config(args: dict): | |
""" | |
Loads the configuration. | |
Args: | |
args (dict): A dictionary containing the necessary arguments. | |
Returns: | |
bool: Always True. | |
""" | |
config.load_config() | |
args["API_KEY"].set(config.API_KEY) | |
args["BASE_URL"].set(config.BASE_URL) | |
return True | |
def print_args(args: dict): | |
""" | |
Prints the arguments. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
Returns: | |
bool: Always True. | |
""" | |
for arg, v_fun in args.items(): | |
print(f"Name: {arg}, Value: {v_fun.get()}") | |
return True | |
def raise_error(args: dict): | |
""" | |
Raises an error. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
""" | |
raise Exception("This is a test error.") | |
# ---------- Generate Function ----------# | |
def generate(args: dict): | |
""" | |
Generates the plugin. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
Returns: | |
bool: Always True. | |
""" | |
global error_msg, pkg_id_path | |
# Get user inputs | |
name = args["PluginName"].get() | |
description = args["PluginDescription"].get() | |
artifact_name = name.replace(" ", "") | |
package_id = f"org.cubegpt.{uuid.uuid4().hex[:8]}" | |
pkg_id_path = "" | |
for id in package_id.split("."): | |
pkg_id_path += id + "/" | |
logger(f"user_input -> name: {name}") | |
logger(f"user_input -> description: {description}") | |
logger(f"random_generate -> package_id: {package_id}") | |
logger(f"str_path -> pkg_id_path: {pkg_id_path}") | |
print("Generating plugin...") | |
codes = core.askgpt( | |
config.SYS_GEN.replace("%ARTIFACT_NAME%", artifact_name).replace( | |
"%PKG_ID_LST%", pkg_id_path | |
), | |
config.USR_GEN.replace("%DESCRIPTION", description), | |
config.GENERATION_MODEL, | |
) | |
logger(f"codes: {codes}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
elif "Compilation failure": | |
error_msg = result | |
print( | |
"Build failed. To pass the error to ChatGPT && let it fix, jump to the Fixing page and click the Fix button." | |
) | |
else: | |
print( | |
"Unknown error. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
return True | |
def fix(args: dict): | |
""" | |
Fixes the error. | |
Args: | |
args (dict): A dictionary containing the arguments. | |
Returns: | |
bool: Always True. | |
""" | |
artifact_name = args["PluginName"].get() | |
print("Passing the error to ChatGPT...") | |
files = [ | |
f"codes/{artifact_name}/src/main/java/{pkg_id_path}Main.java", | |
f"codes/{artifact_name}/src/main/resources/plugin.yml", | |
f"codes/{artifact_name}/src/main/resources/config.yml", | |
f"codes/{artifact_name}/pom.xml", | |
] | |
ids = ["main_java", "plugin_yml", "config_yml", "pom_xml"] | |
main_java = None | |
plugin_yml = None | |
config_yml = None | |
pom_xml = None | |
for file in files: | |
with open(file, "r") as f: | |
code = f.read() | |
id = ids[files.index(file)] | |
globals()[id] = code | |
print("Generating...") | |
codes = core.askgpt( | |
config.SYS_FIX.replace("%ARTIFACT_NAME%", str(artifact_name)), | |
config.USR_FIX.replace("%MAIN_JAVA%", str(main_java)) | |
.replace("%PLUGIN_YML%", str(plugin_yml)) | |
.replace("%CONFIG_YML%", str(config_yml)) | |
.replace("%POM_XML%", str(pom_xml)) | |
.replave("%PKG_ID_LST%", pkg_id_path) | |
.replace("%P_ERROR_MSG%", str(error_msg)), | |
config.FIXING_MODEL, | |
) | |
shutil.rmtree(f"codes/{artifact_name}") | |
core.response_to_action(codes) | |
print("Code generated. Building now...") | |
result = build.build_plugin(artifact_name) | |
if "BUILD SUCCESS" in result: | |
print( | |
f"Build complete. Find your plugin at 'codes/{artifact_name}/target/{artifact_name}.jar'" | |
) | |
else: | |
print( | |
"Build failed again. Please check the logs && send the log to @BaimoQilin on discord." | |
) | |
return True | |
# ---------- Main Program ----------# | |
root = CreateQGUI(title="BukkitGPT-v3", tab_names=["Generate", "Settings", "DevTools"]) | |
error_msg = None | |
logger("Starting program.") | |
# Initialize Core | |
core.initialize() | |
print("BukkitGPT v3 beta console running") | |
# Banner | |
root.add_banner_tool(GitHub("https://github.com/CubeGPT/BukkitGPT-v3")) | |
# Generate Page | |
root.add_notebook_tool( | |
InputBox(name="PluginName", default="ExamplePlugin", label_info="Plugin Name") | |
) | |
root.add_notebook_tool( | |
InputBox( | |
name="PluginDescription", | |
default="Send msg 'hello' to every joined player.", | |
label_info="Plugin Description", | |
) | |
) | |
root.add_notebook_tool( | |
RunButton( | |
bind_func=generate, | |
name="Generate", | |
text="Generate Plugin", | |
checked_text="Generating...", | |
tab_index=0, | |
) | |
) | |
# Fixing Page # | |
# root.add_notebook_tool(Label(name="Fixing_DESCRIPTION", text="This is a fixing page. If the build fails, click the Fix button to fix the error in the LATEST build.", tab_index=1)) | |
# root.add_notebook_tool(RunButton(bind_func=fix, name="Fix", text="Fix", checked_text="Fixing...", tab_index=1)) | |
# Settings Page | |
root.add_notebook_tool( | |
InputBox(name="API_KEY", default=config.API_KEY, label_info="API Key", tab_index=1) | |
) | |
root.add_notebook_tool( | |
InputBox( | |
name="BASE_URL", default=config.BASE_URL, label_info="BASE URL", tab_index=1 | |
) | |
) | |
config_buttons = HorizontalToolsCombine( | |
[ | |
BaseButton( | |
bind_func=save_apply_config, | |
name="Save & Apply Config", | |
text="Save & Apply", | |
tab_index=1, | |
), | |
BaseButton( | |
bind_func=load_config, name="Load Config", text="Load Config", tab_index=1 | |
), | |
BaseButton( | |
bind_func=open_config, | |
name="Open Config", | |
text="Open Full Config", | |
tab_index=1, | |
), | |
] | |
) | |
root.add_notebook_tool(config_buttons) | |
# DevTools Page | |
root.add_notebook_tool( | |
Label( | |
name="DevTool_DESCRIPTION", | |
text="This is a testing page for developers. Ignore it if you are a normal user.", | |
tab_index=2, | |
) | |
) | |
root.add_notebook_tool( | |
Label( | |
name="DevTool_CONFIG_API_KEY_DISPLAY", | |
text=f"CONFIG.API_KEY = {config.API_KEY}", | |
tab_index=2, | |
) | |
) | |
root.add_notebook_tool( | |
Label( | |
name="DevTools_CONFIG_BASE_URL_DISPLAY", | |
text=f"CONFIG.BASE_URL = {config.BASE_URL}", | |
tab_index=2, | |
) | |
) | |
root.add_notebook_tool( | |
RunButton(bind_func=print_args, name="Print Args", text="Print Args", tab_index=2) | |
) | |
root.add_notebook_tool( | |
RunButton( | |
bind_func=raise_error, name="Raise Error", text="Raise Error", tab_index=2 | |
) | |
) | |
# Sidebar | |
root.set_navigation_about( | |
author="CubeGPT Team", | |
version=config.VERSION_NUMBER, | |
github_url="https://github.com/CubeGPT/BukkitGPT-v3", | |
) | |
# Run | |
root.run() | |
PROMPT: | |
添加生成DataPack的选项,使得用户可以选择生成Bukkit插件或者DataPack。 | |
在`ui.py`中可以在Generate Page里添加这行代码 `root.add_notebook_tool(RadioObviousToolButton(options=["BukkitPlugin", "Datapack(Experimental)"], name="GenerationType", title="Type", default="BukkitPlugin",tab_index=0))` | |
你还需要自行完成DataPack的生成逻辑。你可能需要更改的文件有`ui.py`, `core.py`, `config.yaml`, `console.py`。你还可能需要创建一些新的文件或文件夹,也有可能不需要。祝你好运。 | |
2024-07-25T12:12:18.250819 | |
CONSOLE OUTPUT: | |
Error while improving the project: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted" | |
Could you please upload the debug_log_file.txt in D:\zhousl\BukkitGPT\BukkitGPT-v3\.gpteng\memory/logs folder to github? | |
FULL STACK TRACE: | |
Traceback (most recent call last): | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 379, in handle_improve_mode | |
files_dict = agent.improve(files_dict, prompt) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\applications\cli\cli_agent.py", line 208, in improve | |
files_dict = self.improve_fn( | |
^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 311, in improve_fn | |
return _improve_loop(ai, files_dict, memory, messages) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\default\steps.py", line 317, in _improve_loop | |
messages = ai.next(messages, step_name=curr_fn()) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 243, in next | |
response = self.backoff_inference(messages) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\backoff\_sync.py", line 105, in retry | |
ret = target(*args, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\gpt_engineer\core\ai.py", line 287, in backoff_inference | |
return self.llm.invoke(messages) # type: ignore | |
^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 270, in invoke | |
self.generate_prompt( | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 703, in generate_prompt | |
return self.generate(prompt_messages, stop=stop, callbacks=callbacks, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 560, in generate | |
raise e | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 550, in generate | |
self._generate_with_cache( | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 775, in _generate_with_cache | |
result = self._generate( | |
^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 755, in _generate | |
return generate_from_stream(stream_iter) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_core\language_models\chat_models.py", line 102, in generate_from_stream | |
generation = next(stream, None) | |
^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\langchain_anthropic\chat_models.py", line 676, in _stream | |
stream = self._client.messages.create(**payload) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_utils\_utils.py", line 277, in wrapper | |
return func(*args, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\resources\messages.py", line 902, in create | |
return self._post( | |
^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 1266, in post | |
return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 942, in request | |
return self._request( | |
^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 968, in _request | |
request = self._build_request(options) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 461, in _build_request | |
headers = self._build_headers(options) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_base_client.py", line 416, in _build_headers | |
self._validate_headers(headers_dict, custom_headers) | |
File "C:\Users\BaimoQilin\AppData\Local\Programs\Python\Python312\Lib\site-packages\anthropic\_client.py", line 192, in _validate_headers | |
raise TypeError( | |
TypeError: "Could not resolve authentication method. Expected either api_key or auth_token to be set. Or for one of the `X-Api-Key` or `Authorization` headers to be explicitly omitted" | |