|
|
|
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:[email protected]) 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"
|
|
|
|
|