Update, API version.
This commit is contained in:
parent
05ab6c1476
commit
93bcd444d2
109
botje.py
Normal file → Executable file
109
botje.py
Normal file → Executable file
@ -1,13 +1,11 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import argparse
|
||||
import json
|
||||
import subprocess
|
||||
from openai import OpenAI
|
||||
import sys
|
||||
import shlex
|
||||
import requests
|
||||
|
||||
# ANSI escape codes for colors
|
||||
class Colors:
|
||||
RED = '\033[91m'
|
||||
GREEN = '\033[92m'
|
||||
@ -17,28 +15,13 @@ class Colors:
|
||||
CYAN = '\033[96m'
|
||||
RESET = '\033[0m'
|
||||
|
||||
# Initialize the OpenAI client
|
||||
# It will automatically pick up the OPENAI_API_KEY from your environment variables.
|
||||
try:
|
||||
client = OpenAI()
|
||||
except ImportError:
|
||||
print(f"{Colors.RED}OpenAI Python package not found. Please install it with 'pip install openai'{Colors.RESET}")
|
||||
exit(1)
|
||||
except Exception as e:
|
||||
print(f"{Colors.RED}Error initializing OpenAI client: {e}{Colors.RESET}")
|
||||
print(f"{Colors.YELLOW}Please ensure your OPENAI_API_KEY environment variable is set correctly.{Colors.RESET}")
|
||||
api_key = os.environ.get("OPENAI_API_KEY")
|
||||
if not api_key:
|
||||
print(f"{Colors.RED}Error: OPENAI_API_KEY environment variable not set.{Colors.RESET}")
|
||||
exit(1)
|
||||
|
||||
class AutonomousBot:
|
||||
"""
|
||||
An autonomous bot that executes tasks based on a user prompt.
|
||||
It can call functions, manage its state, and decompose complex tasks.
|
||||
"""
|
||||
|
||||
def __init__(self, prompt, memory=None):
|
||||
"""
|
||||
Initializes the bot with a prompt and an optional memory of past actions.
|
||||
"""
|
||||
self.initial_prompt = prompt
|
||||
self.memory = memory if memory is not None else []
|
||||
self.is_finished = False
|
||||
@ -156,7 +139,6 @@ class AutonomousBot:
|
||||
}
|
||||
|
||||
def get_system_prompt(self):
|
||||
"""Constructs the system prompt for the AI model."""
|
||||
return f"""You are an autonomous AI builder bot. Your goal is to accomplish the user's request by calling functions to interact with the system.
|
||||
|
||||
You have complete CRUD access to the filesystem and can execute terminal commands. Be aware of your actions and their consequences.
|
||||
@ -179,10 +161,7 @@ Here is a summary of the steps taken so far:
|
||||
"""
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
Main execution loop for the bot.
|
||||
"""
|
||||
print(f"{Colors.GREEN}▶ Starting bot with prompt: '{self.initial_prompt}'{Colors.RESET}")
|
||||
print(f"{Colors.GREEN}Starting bot with prompt: '{self.initial_prompt}'{Colors.RESET}")
|
||||
|
||||
messages = [
|
||||
{"role": "system", "content": self.get_system_prompt()},
|
||||
@ -191,21 +170,33 @@ Here is a summary of the steps taken so far:
|
||||
|
||||
while not self.is_finished:
|
||||
try:
|
||||
print(f"\n{Colors.BLUE}🤔 Thinking...{Colors.RESET}")
|
||||
response = client.chat.completions.create(
|
||||
model="gpt-4-turbo",
|
||||
messages=messages,
|
||||
tools=self.tools,
|
||||
tool_choice="auto",
|
||||
)
|
||||
print(f"\n{Colors.BLUE}Thinking...{Colors.RESET}")
|
||||
|
||||
response_message = response.choices[0].message
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f"Bearer {api_key}"
|
||||
}
|
||||
payload = {
|
||||
"model": "gpt-4-turbo",
|
||||
"messages": messages,
|
||||
"tools": self.tools,
|
||||
"tool_choice": "auto"
|
||||
}
|
||||
|
||||
response_raw = requests.post("https://api.openai.com/v1/chat/completions", headers=headers, json=payload)
|
||||
|
||||
if response_raw.status_code != 200:
|
||||
print(f"{Colors.RED}Error from OpenAI API: {response_raw.status_code} - {response_raw.text}{Colors.RESET}")
|
||||
break
|
||||
|
||||
response_json = response_raw.json()
|
||||
response_message = response_json['choices'][0]['message']
|
||||
messages.append(response_message)
|
||||
tool_calls = response_message.tool_calls
|
||||
tool_calls = response_message.get('tool_calls')
|
||||
|
||||
if not tool_calls:
|
||||
print(f"\n{Colors.CYAN}🤖 AI Response (no tool call):{Colors.RESET}")
|
||||
no_tool_call_message = response_message.content or "No text content in response."
|
||||
print(f"\n{Colors.CYAN}AI Response (no tool call):{Colors.RESET}")
|
||||
no_tool_call_message = response_message.get('content') or "No text content in response."
|
||||
print(no_tool_call_message)
|
||||
|
||||
messages.append({
|
||||
@ -215,25 +206,25 @@ Here is a summary of the steps taken so far:
|
||||
continue
|
||||
|
||||
for tool_call in tool_calls:
|
||||
function_name = tool_call.function.name
|
||||
function_name = tool_call['function']['name']
|
||||
function_to_call = self.available_functions.get(function_name)
|
||||
function_args = {}
|
||||
|
||||
if not function_to_call:
|
||||
print(f"{Colors.RED}❌ Unknown function called by model: {function_name}{Colors.RESET}")
|
||||
print(f"{Colors.RED}Unknown function called by model: {function_name}{Colors.RESET}")
|
||||
tool_result = {"status": "error", "message": f"Unknown function: {function_name}"}
|
||||
else:
|
||||
try:
|
||||
function_args = json.loads(tool_call.function.arguments)
|
||||
print(f"\n{Colors.GREEN}▶ Calling function: `{function_name}` with arguments:{Colors.RESET}")
|
||||
function_args = json.loads(tool_call['function']['arguments'])
|
||||
print(f"\n{Colors.GREEN}Calling function: `{function_name}` with arguments:{Colors.RESET}")
|
||||
print(json.dumps(function_args, indent=2))
|
||||
tool_result = function_to_call(**function_args)
|
||||
except Exception as e:
|
||||
print(f"{Colors.RED}❌ Error calling function '{function_name}': {e}{Colors.RESET}")
|
||||
print(f"{Colors.RED}Error calling function '{function_name}': {e}{Colors.RESET}")
|
||||
tool_result = {"status": "error", "message": str(e)}
|
||||
|
||||
messages.append({
|
||||
"tool_call_id": tool_call.id,
|
||||
"tool_call_id": tool_call['id'],
|
||||
"role": "tool",
|
||||
"name": function_name,
|
||||
"content": json.dumps(tool_result),
|
||||
@ -245,7 +236,7 @@ Here is a summary of the steps taken so far:
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n{Colors.RED}❌ An unexpected error occurred in the main loop: {e}{Colors.RESET}")
|
||||
print(f"\n{Colors.RED}An unexpected error occurred in the main loop: {e}{Colors.RESET}")
|
||||
break
|
||||
|
||||
def _write_file(self, filepath, content, purpose=""):
|
||||
@ -256,10 +247,10 @@ Here is a summary of the steps taken so far:
|
||||
with open(filepath, 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
purpose_text = f" ({purpose})" if purpose else ""
|
||||
print(f"{Colors.GREEN}✅ File '{filepath}' created{purpose_text} successfully.{Colors.RESET}")
|
||||
print(f"{Colors.GREEN}File '{filepath}' created{purpose_text} successfully.{Colors.RESET}")
|
||||
return {"status": "success", "filepath": filepath}
|
||||
except Exception as e:
|
||||
print(f"{Colors.RED}❌ Error creating file '{filepath}': {e}{Colors.RESET}")
|
||||
print(f"{Colors.RED}Error creating file '{filepath}': {e}{Colors.RESET}")
|
||||
return {"status": "error", "message": str(e)}
|
||||
|
||||
def create_file(self, filepath, content):
|
||||
@ -272,25 +263,25 @@ Here is a summary of the steps taken so far:
|
||||
try:
|
||||
with open(filepath, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
print(f"{Colors.GREEN}✅ File '{filepath}' read successfully.{Colors.RESET}")
|
||||
print(f"{Colors.GREEN}File '{filepath}' read successfully.{Colors.RESET}")
|
||||
return {"status": "success", "content": content}
|
||||
except FileNotFoundError:
|
||||
print(f"{Colors.RED}❌ File not found: '{filepath}'{Colors.RESET}")
|
||||
print(f"{Colors.RED}File not found: '{filepath}'{Colors.RESET}")
|
||||
return {"status": "error", "message": "File not found."}
|
||||
except Exception as e:
|
||||
print(f"{Colors.RED}❌ Error reading file '{filepath}': {e}{Colors.RESET}")
|
||||
print(f"{Colors.RED}Error reading file '{filepath}': {e}{Colors.RESET}")
|
||||
return {"status": "error", "message": str(e)}
|
||||
|
||||
def delete_file(self, filepath):
|
||||
try:
|
||||
os.remove(filepath)
|
||||
print(f"{Colors.GREEN}✅ File '{filepath}' deleted successfully.{Colors.RESET}")
|
||||
print(f"{Colors.GREEN}File '{filepath}' deleted successfully.{Colors.RESET}")
|
||||
return {"status": "success", "filepath": filepath}
|
||||
except FileNotFoundError:
|
||||
print(f"{Colors.RED}❌ File not found: '{filepath}'{Colors.RESET}")
|
||||
print(f"{Colors.RED}File not found: '{filepath}'{Colors.RESET}")
|
||||
return {"status": "error", "message": "File not found."}
|
||||
except Exception as e:
|
||||
print(f"{Colors.RED}❌ Error deleting file '{filepath}': {e}{Colors.RESET}")
|
||||
print(f"{Colors.RED}Error deleting file '{filepath}': {e}{Colors.RESET}")
|
||||
return {"status": "error", "message": str(e)}
|
||||
|
||||
def terminal_execute(self, command):
|
||||
@ -311,11 +302,11 @@ Here is a summary of the steps taken so far:
|
||||
print(f" - Return Code: {result.returncode}")
|
||||
return output
|
||||
except Exception as e:
|
||||
print(f"{Colors.RED}❌ Error executing command '{command}': {e}{Colors.RESET}")
|
||||
print(f"{Colors.RED}Error executing command '{command}': {e}{Colors.RESET}")
|
||||
return {"status": "error", "message": str(e), "stdout": "", "stderr": str(e), "returncode": -1}
|
||||
|
||||
def finish_task(self, reason):
|
||||
print(f"\n{Colors.YELLOW}🏁 BOT INSTANCE FINISHED: {reason}{Colors.RESET}")
|
||||
print(f"\n{Colors.YELLOW}BOT INSTANCE FINISHED: {reason}{Colors.RESET}")
|
||||
self.is_finished = True
|
||||
return {"status": "finished"}
|
||||
|
||||
@ -323,13 +314,13 @@ Here is a summary of the steps taken so far:
|
||||
print("\n" + "="*50)
|
||||
print(" PYRAMID OF BUILDERS")
|
||||
print("="*50)
|
||||
print(f"{Colors.MAGENTA}🚀 Delegating remaining prompt to a new bot instance...{Colors.RESET}")
|
||||
print(f"{Colors.MAGENTA}Delegating remaining prompt to a new bot instance...{Colors.RESET}")
|
||||
print(f" python {__file__} \"{remaining_prompt}\"")
|
||||
try:
|
||||
subprocess.Popen([sys.executable, __file__, remaining_prompt])
|
||||
print(f"{Colors.GREEN}✅ New bot instance launched successfully.{Colors.RESET}")
|
||||
print(f"{Colors.GREEN}New bot instance launched successfully.{Colors.RESET}")
|
||||
except Exception as e:
|
||||
print(f"{Colors.RED}❌ Failed to launch new bot instance: {e}{Colors.RESET}")
|
||||
print(f"{Colors.RED}Failed to launch new bot instance: {e}{Colors.RESET}")
|
||||
return {"status": "error", "message": f"Failed to delegate: {e}"}
|
||||
|
||||
self.initial_prompt = current_task_prompt
|
||||
@ -338,9 +329,6 @@ Here is a summary of the steps taken so far:
|
||||
return {"status": "success", "message": "Task split. This bot will now handle the first part."}
|
||||
|
||||
def main():
|
||||
"""
|
||||
Entry point for the CLI application.
|
||||
"""
|
||||
parser = argparse.ArgumentParser(description="An autonomous bot to execute tasks.")
|
||||
parser.add_argument("prompt", type=str, help="The user prompt describing the task to be done.")
|
||||
args = parser.parse_args()
|
||||
@ -350,3 +338,4 @@ def main():
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user