diff --git a/README.md b/README.md index 95ced08..e789a4c 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,18 @@ ![Animated GIF](https://github.com/wunderwuzzi23/blog/raw/master/static/images/2023/yolo-shell-anim-gif.gif) +# Update Yolo v0.6 - Support for G4F and Improved Installation + +* Added G4F (GPT4Free) support. No API key required! Just set `api: g4f` in your `yolo.yaml`. +* Default model for G4F is `gpt-3.5-turbo` +* Now configured as the default API in yolo.yaml since no API key configuration is needed +* Improved installation process with `install.sh`: + - Creates an isolated virtual environment for clean dependency management + - Particularly beneficial for Arch Linux users to avoid conflicts with system packages + - Automatically handles venv activation/deactivation when running commands + - Supports both bash and zsh shells with proper shell function integration +* Simplified model initialization and error handling + # Update Yolo v0.5 - Support for Claude and other providers * Added Claude support. Can an API key from Anthropic, current model `claude-3-5-sonnet-20240620`. @@ -78,6 +90,11 @@ There are three ways to configure the key on Linux and macOS: - You can either `export GROQ_API_KEY=`, or have a `.env` file in the same directory as `yolo.py` with `GROQ_API_KEY=""` as a line - Set `api` and `model` (e.g llama3-8b-8192) in `yolo.yaml` configuration file +### G4F Configuration +- No API key required! +- Set `api: g4f` in `yolo.yaml` configuration file +- Default model is `gpt-3.5-turbo` + ## Aliases To set the alias, like `yolo` or `computer` on each login, add them to .bash_aliases (or .zshrc on macOS) file. Make sure the path is the one you want to use. diff --git a/ai_model.py b/ai_model.py index c55ec3e..c28acce 100644 --- a/ai_model.py +++ b/ai_model.py @@ -8,6 +8,7 @@ from ollama import Client from openai import AzureOpenAI from anthropic import Anthropic +from g4f.client import Client as G4FClient import os class AIModel(ABC): @@ -58,6 +59,9 @@ def get_model_client(config): #ollama_model = os.environ.get("OLLAMA_MODEL", "llama3-8b-8192") return OllamaModel(ollama_api) + elif api_provider == "g4f": + return G4FModel() + if api_provider == "anthropic": api_key = os.getenv("ANTHROPIC_API_KEY") if not api_key: @@ -124,6 +128,22 @@ def chat(self, messages, model, temperature, max_tokens): def moderate(self, message): return self.client.moderations.create(input=message) +class G4FModel(AIModel): + def __init__(self, api_key=None): + self.client = G4FClient() + + def chat(self, messages, model, temperature, max_tokens): + resp = self.client.chat.completions.create( + model="gpt-3.5-turbo", + messages=messages, + temperature=temperature, + max_tokens=max_tokens + ) + return resp.choices[0].message.content + + def moderate(self, message): + return self.client.moderations.create(input=message) + class AnthropicModel(AIModel): def __init__(self, api_key): self.client = Anthropic(api_key=api_key) diff --git a/install.bat b/install.bat index fb42d0e..4b7dabf 100644 --- a/install.bat +++ b/install.bat @@ -123,11 +123,12 @@ goto :EOF :: Installs optional files if user wants :install_optional cls -call :print_apikey -choice /n /c YN /m "Let me know which option you want to select: " +call :print_optional_menu +choice /n /c YNOC /m "Let me know which option you want to select: " set /a createAPIKEY=!ERRORLEVEL! if /i !createAPIKEY!==1 ( call :create_openai_apikey ) +if /i !createAPIKEY!==3 ( exit /b 0 ) goto :EOF :: Creates a directory to hold yolo.py and prompt.txt @@ -198,9 +199,10 @@ echo. echo Installation Options: echo. echo [Y] Yolo, Default installation to your home folder ( `%HOMEDRIVE%%HOMEPATH%\` ) +echo Uses G4F by default (no API key needed) echo [N] Non-default install, Set custom install locations echo [C] Cancel, Do not install (exit this script) -echo [O] Optional Files (advanced options) +echo [O] Optional Files (API keys for other providers) echo. echo You probably want to use [Y]. echo. @@ -246,6 +248,21 @@ echo You probably want to use [Y], you can manually move the `yolo.bat` file aft echo. goto :EOF +:: Prints a prompt for `.openai.apikey` +:print_optional_menu +echo. +echo Optional Files: +echo. +echo Note: By default, Yolo uses G4F which requires no API key. +echo These options are only needed if you want to use other providers. +echo. +echo Y. Yes - Create optional API key files +echo N. No - Skip (recommended for G4F) +echo O. Only create optional files and exit +echo C. Cancel +echo. +goto :EOF + :: Prints a prompt for `.openai.apikey` :print_apikey echo. @@ -298,22 +315,41 @@ goto :EOF :print_apikey_guide echo. -echo API Key: -echo. -echo You need to provide your OpenAI API key to use yolo. -echo. -echo You can get a key from `https://platform.openai.com/account/api-keys` after logging in. -echo There are multiple options for providing the key: -echo (1) You can put the key into a `.openai.apikey` file in `%HOMEDRIVE%%HOMEPATH%\` -echo Run `install.bat` again and select `O`ptional Files to create a `.openai.apikey` file -echo (2) You can paste `OPENAI_API_KEY="[yourkey]"` into a `.env` file that should be in the folder yolo is installed in currently. -if /i !createDIR!==1 ( echo `.env` should be in: !TARGET_DIR! ) -if /i !createDIR!==2 ( echo `.env` should be in: %~dp0 ) -echo (3) You can run `$env:OPENAI_API_KEY="[yourkey]"` in your terminal before using yolo in that terminal -echo -If you run PowerShell as administrator you can then run `setx OPENAI_API_KEY "[yourkey]"` to permanently and use yolo in any terminal (you may need to reopen the terminal once). -echo -Go to `Start` and search `edit environment variables for your account` and manually create the variable with name `OPENAI_API_KEY` and value `[yourkey]` -echo (4) Another option is to put the API key in the yolo.yaml configuration file (since v.0.2) -echo. -echo Yolo also supports Azure OpenAI, and many other LLMs now. Configure settings in yolo.yaml accordingly. +echo API Key Configuration: +echo. +echo By default, Yolo uses G4F which requires no API key. +echo However, if you want to use other providers, you'll need their respective API keys. +echo. +echo There are multiple options for providing API keys: +echo (1) Environment Variables (Recommended) +echo Run these commands in PowerShell: +echo $env:OPENAI_API_KEY="[yourkey]" +echo $env:AZURE_OPENAI_API_KEY="[yourkey]" +echo $env:ANTHROPIC_API_KEY="[yourkey]" +echo $env:GROQ_API_KEY="[yourkey]" +echo. +echo (2) Configuration File +echo Edit yolo.yaml and add your keys: +if /i !createDIR!==1 ( echo yolo.yaml is in: !TARGET_DIR! ) +if /i !createDIR!==2 ( echo yolo.yaml is in: %~dp0 ) +echo. +echo (3) Environment File +echo Create a .env file with your keys: +if /i !createDIR!==1 ( echo .env should be in: !TARGET_DIR! ) +if /i !createDIR!==2 ( echo .env should be in: %~dp0 ) +echo. +echo (4) API Key File +echo Put your OpenAI key in .openai.apikey in %HOMEDRIVE%%HOMEPATH% +echo Run install.bat again and select Optional Files to create it +echo. +echo Supported Providers: +echo - G4F (Default, no key needed) +echo - OpenAI +echo - Azure OpenAI +echo - Anthropic (Claude) +echo - Groq +echo - Ollama +echo. +echo To change providers, update the 'api' setting in yolo.yaml echo. goto :EOF \ No newline at end of file diff --git a/install.sh b/install.sh index 54f6cc2..a4b1605 100755 --- a/install.sh +++ b/install.sh @@ -1,44 +1,479 @@ -# Simple installer for yolo in the user's home directory - -echo "Hello. Installing yolo..." -echo "- Creating yolo-ai-cmdbot in home directory..." -TARGET_DIR=~/yolo-ai-cmdbot -TARGET_FULLPATH=$TARGET_DIR/yolo.py -mkdir -p $TARGET_DIR - -echo "- Copying files..." -cp yolo.py prompt.txt yolo.yaml ai_model.py $TARGET_DIR -chmod +x $TARGET_FULLPATH - -# Creates two aliases for use -echo "- Creating yolo and computer aliases..." -alias yolo=$TARGET_FULLPATH -alias computer=$TARGET_FULLPATH - -# Add the aliases to the logon scripts -# Depends on your shell -if [[ "$SHELL" == "/bin/bash" ]]; then - echo "- Adding aliases to ~/.bash_aliases" - [ "$(grep '^alias yolo=' ~/.bash_aliases)" ] && echo "alias yolo already created" || echo "alias yolo=$TARGET_FULLPATH" >> ~/.bash_aliases - [ "$(grep '^alias computer=' ~/.bash_aliases)" ] && echo "alias computer already created" || echo "alias computer=$TARGET_FULLPATH" >> ~/.bash_aliases -elif [[ "$SHELL" == "/bin/zsh" ]]; then - echo "- Adding aliases to ~/.zshrc" - [ "$(grep '^alias yolo=' ~/.zshrc)" ] && echo "alias yolo already created" || echo "alias yolo=$TARGET_FULLPATH" >> ~/.zshrc - [ "$(grep '^alias computer=' ~/.zshrc)" ] && echo "alias computer already created" || echo "alias computer=$TARGET_FULLPATH" >> ~/.zshrc -else - echo "Note: Shell was not bash or zsh." - echo " Consider configuring aliases (like yolo and/or computer) manually by adding them to your login script, e.g:" - echo " alias yolo=$TARGET_FULLPATH >> " -fi +#!/bin/bash + +# Colors for pretty output +RED='\033[0;31m' +GREEN='\033[0;32m' +BLUE='\033[0;34m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color +BOLD='\033[1m' +CYAN='\033[0;36m' + +# Default values +TARGET_DIR="$HOME/yolo-ai-cmdbot" +CREATE_VENV=1 +CONFIGURE_SHELL=1 +CREATE_OPTIONAL=0 + +# Check for required files +echo -e "${BLUE}${BOLD}Checking required files...${NC}" +for file in yolo.py prompt.txt yolo.yaml ai_model.py; do + if [ ! -f "$file" ]; then + echo -e "${RED}Error: $file is missing in $(pwd), cannot install${NC}" + exit 1 + fi +done +echo -e "${GREEN}✓ All required files found${NC}\n" + +# Print installation options +print_options() { + echo -e "${BLUE}${BOLD}Installation Options:${NC}" + echo -e "1. Full Installation (Recommended)" + echo -e " - Creates virtual environment" + echo -e " - Configures shell integration" + echo -e " - Installs all dependencies\n" + + echo -e "2. Minimal Installation" + echo -e " - No virtual environment" + echo -e " - Basic shell aliases only" + echo -e " - Manual dependency management\n" + + echo -e "3. Custom Installation" + echo -e " - Choose components to install" + echo -e " - Configure paths manually\n" + + echo -e "4. Cancel Installation\n" +} + +# Print optional files menu +print_optional_menu() { + echo -e "\n${BLUE}${BOLD}Optional Files:${NC}" + echo -e "\nNote: By default, Yolo uses G4F which requires no API key." + echo -e "These options are only needed if you want to use other providers.\n" + echo -e "[Y] Yes - Create optional API key files" + echo -e "[N] No - Skip (recommended for G4F)" + echo -e "[O] Only create optional files and exit" + echo -e "[C] Cancel" +} + +handle_optional_files() { + clear + print_optional_menu + read -p "Let me know which option you want to select [Y/N/O/C]: " choice + case "$choice" in + [Yy]) + create_api_key_files + ;; + [Oo]) + create_api_key_files + exit 0 + ;; + [Cc]) + echo -e "\n${YELLOW}Cancelled optional files setup${NC}" + ;; + *) + echo -e "\n${GREEN}Skipping optional files (using G4F by default)${NC}" + ;; + esac +} + +create_api_key_files() { + echo -e "\n${BLUE}${BOLD}Creating optional API key files...${NC}" + + # Create .env file + if [ ! -f "$TARGET_DIR/.env" ]; then + mkdir -p "$TARGET_DIR" + cat > "$TARGET_DIR/.env" << EOL +# API Keys for different providers +OPENAI_API_KEY= +AZURE_OPENAI_API_KEY= +ANTHROPIC_API_KEY= +GROQ_API_KEY= +EOL + chmod 600 "$TARGET_DIR/.env" + echo -e "${GREEN}✓ Created .env template at $TARGET_DIR/.env${NC}" + else + echo -e "${YELLOW}⚠ .env file already exists, skipping${NC}" + fi + + # Create .openai.apikey file + if [ ! -f "$HOME/.openai.apikey" ]; then + read -p "Would you like to create .openai.apikey file? [y/N]: " create_apikey + if [[ "$create_apikey" =~ ^[Yy]$ ]]; then + read -p "Enter your OpenAI API key (or press Enter to skip): " apikey + if [ ! -z "$apikey" ]; then + echo "$apikey" > "$HOME/.openai.apikey" + chmod 600 "$HOME/.openai.apikey" + echo -e "${GREEN}✓ Created .openai.apikey at $HOME/.openai.apikey${NC}" + fi + fi + else + echo -e "${YELLOW}⚠ .openai.apikey already exists, skipping${NC}" + fi +} + +# Create API key file +create_apikey_file() { + echo -e "\n${BLUE}${BOLD}Creating API Key File...${NC}" + read -p "Enter your OpenAI API key (or press Enter to skip): " api_key + if [ -n "$api_key" ]; then + echo "$api_key" > "$HOME/.openai.apikey" + chmod 600 "$HOME/.openai.apikey" # Set secure permissions + echo -e "${GREEN}✓ API key file created at ~/.openai.apikey${NC}" + fi +} -echo -echo "Done." -echo -echo "Make sure you have your LLM key (e.g. OpenAI API) set via one of these options:" -echo " - environment variable" -echo " - .env or in" -echo " - yolo.yaml" -echo -echo "Yolo also supports Azure OpenAI, Ollama, groq, Claude now. Change settings in yolo.yaml accordingly." -echo -echo "Have fun!" +# Create environment file +create_env_file() { + echo -e "\n${BLUE}${BOLD}Creating .env File...${NC}" + # Ensure target directory exists + mkdir -p "$TARGET_DIR" + + if [ ! -f "$TARGET_DIR/.env" ]; then + cat > "$TARGET_DIR/.env" << EOL +# API Keys for different providers +OPENAI_API_KEY= +AZURE_OPENAI_API_KEY= +ANTHROPIC_API_KEY= +GROQ_API_KEY= +EOL + chmod 600 "$TARGET_DIR/.env" # Set secure permissions + echo -e "${GREEN}✓ .env template created at $TARGET_DIR/.env${NC}" + else + echo -e "${YELLOW}⚠ .env file already exists, skipping${NC}" + fi +} + +# Handle optional files +handle_optional_files_menu() { + print_optional_menu + read -p "Select an option (Y/N/O/C): " opt + case ${opt:0:1} in + [Yy]*) + CREATE_OPTIONAL=1 + ;; + [Nn]*) + CREATE_OPTIONAL=0 + ;; + [Oo]*) + create_apikey_file + create_env_file + exit 0 + ;; + [Cc]*) + echo -e "${RED}Installation cancelled${NC}" + exit 0 + ;; + *) + echo -e "${RED}Invalid option${NC}" + handle_optional_files_menu + ;; + esac +} + +# Get user choice +get_choice() { + local choice + read -p "Select an option (1-4): " choice + case $choice in + 1) # Full installation + CREATE_VENV=1 + CONFIGURE_SHELL=1 + ;; + 2) # Minimal installation + CREATE_VENV=0 + CONFIGURE_SHELL=1 + ;; + 3) # Custom installation + echo -e "\n${BLUE}${BOLD}Custom Installation Options:${NC}" + read -p "Create virtual environment? (y/n): " venv_choice + [[ $venv_choice == "y" ]] && CREATE_VENV=1 || CREATE_VENV=0 + + read -p "Configure shell integration? (y/n): " shell_choice + [[ $shell_choice == "y" ]] && CONFIGURE_SHELL=1 || CONFIGURE_SHELL=0 + + read -p "Enter installation directory [$TARGET_DIR]: " custom_dir + [[ -n $custom_dir ]] && TARGET_DIR=$custom_dir + ;; + 4) # Cancel + echo -e "${RED}Installation cancelled${NC}" + exit 0 + ;; + *) + echo -e "${RED}Invalid option. Please select 1-4${NC}" + get_choice + ;; + esac +} + +# Main installation process +main_install() { + # Create target directory + echo -e "\n${BLUE}${BOLD}Setting up Yolo AI Command Bot...${NC}" + echo -e "Installation directory: ${BOLD}$TARGET_DIR${NC}" + mkdir -p $TARGET_DIR + + # Copy files + echo -e "\n${BLUE}${BOLD}Copying files...${NC}" + cp yolo.py prompt.txt yolo.yaml ai_model.py requirements.txt $TARGET_DIR + echo -e "${GREEN}✓ Files copied successfully${NC}" + + # Setup virtual environment if requested + if [ $CREATE_VENV -eq 1 ]; then + echo -e "\n${BLUE}${BOLD}Creating virtual environment...${NC}" + python3 -m venv $TARGET_DIR/venv + source $TARGET_DIR/venv/bin/activate + pip install -r $TARGET_DIR/requirements.txt + deactivate + echo -e "${GREEN}✓ Virtual environment created and dependencies installed${NC}" + fi + + # Configure shell integration if requested + if [ $CONFIGURE_SHELL -eq 1 ]; then + echo -e "\n${BLUE}${BOLD}Configuring shell integration...${NC}" + + # Function definition for bash/zsh + YOLO_FUNCTION=" +# Yolo AI Command Bot +function yolo-ai() { + if [ -f \"$TARGET_DIR/venv/bin/activate\" ]; then + source \"$TARGET_DIR/venv/bin/activate\" + python \"$TARGET_DIR/yolo.py\" \"\$@\" + deactivate + else + python \"$TARGET_DIR/yolo.py\" \"\$@\" + fi +}" + + # Function definition for fish + FISH_FUNCTION=" +# Yolo AI Command Bot +function yolo-ai + if test -f \"$TARGET_DIR/venv/bin/activate.fish\" + source \"$TARGET_DIR/venv/bin/activate.fish\" + python \"$TARGET_DIR/yolo.py\" \$argv + deactivate + else + python \"$TARGET_DIR/yolo.py\" \$argv + end +end" + + # Add to appropriate shell config + if [[ "$SHELL" == "/bin/bash" ]]; then + ALIASES_FILE="$HOME/.bash_aliases" + # Create .bash_aliases if it doesn't exist + touch "$ALIASES_FILE" + # Add source .bash_aliases to .bashrc if not already there + if ! grep -q "source ~/.bash_aliases" "$HOME/.bashrc"; then + echo "if [ -f ~/.bash_aliases ]; then" >> "$HOME/.bashrc" + echo " source ~/.bash_aliases" >> "$HOME/.bashrc" + echo "fi" >> "$HOME/.bashrc" + fi + + # Check if function already exists + if ! grep -q "function yolo-ai()" "$ALIASES_FILE"; then + echo "$YOLO_FUNCTION" >> "$ALIASES_FILE" + echo -e "${GREEN}✓ Added yolo-ai function to ${BOLD}~/.bash_aliases${NC}" + else + echo -e "${YELLOW}⚠ yolo-ai function already exists in ~/.bash_aliases${NC}" + fi + + # Check if aliases already exist + if ! grep -q "alias yolo='yolo-ai'" "$ALIASES_FILE"; then + echo "alias yolo='yolo-ai'" >> "$ALIASES_FILE" + echo -e "${GREEN}✓ Added yolo alias to ${BOLD}~/.bash_aliases${NC}" + else + echo -e "${YELLOW}⚠ yolo alias already exists in ~/.bash_aliases${NC}" + fi + + if ! grep -q "alias computer='yolo-ai'" "$ALIASES_FILE"; then + echo "alias computer='yolo-ai'" >> "$ALIASES_FILE" + echo -e "${GREEN}✓ Added computer alias to ${BOLD}~/.bash_aliases${NC}" + else + echo -e "${YELLOW}⚠ computer alias already exists in ~/.bash_aliases${NC}" + fi + + # Note about sourcing + echo -e "${YELLOW}Note: Run 'source ~/.bashrc' to apply changes in current session${NC}" + elif [[ "$SHELL" == "/bin/zsh" || "$SHELL" == "/usr/bin/zsh" ]]; then + ZSHRC="$HOME/.zshrc" + + # Check if function already exists + if ! grep -q "function yolo-ai()" "$ZSHRC"; then + echo "$YOLO_FUNCTION" >> "$ZSHRC" + echo -e "${GREEN}✓ Added yolo-ai function to ${BOLD}~/.zshrc${NC}" + else + echo -e "${YELLOW}⚠ yolo-ai function already exists in ~/.zshrc${NC}" + fi + + # Check if aliases already exist + if ! grep -q "alias yolo='yolo-ai'" "$ZSHRC"; then + echo "alias yolo='yolo-ai'" >> "$ZSHRC" + echo -e "${GREEN}✓ Added yolo alias to ${BOLD}~/.zshrc${NC}" + else + echo -e "${YELLOW}⚠ yolo alias already exists in ~/.zshrc${NC}" + fi + + if ! grep -q "alias computer='yolo-ai'" "$ZSHRC"; then + echo "alias computer='yolo-ai'" >> "$ZSHRC" + echo -e "${GREEN}✓ Added computer alias to ${BOLD}~/.zshrc${NC}" + else + echo -e "${YELLOW}⚠ computer alias already exists in ~/.zshrc${NC}" + fi + + # Note about sourcing + echo -e "${YELLOW}Note: Run 'source ~/.zshrc' to apply changes in current session${NC}" + elif [[ "$SHELL" == "/usr/bin/fish" ]] || [[ "$SHELL" == "/bin/fish" ]]; then + FISH_DIR="$HOME/.config/fish/functions" + mkdir -p "$FISH_DIR" + + # Check if function files already exist + if [ -f "$FISH_DIR/yolo-ai.fish" ]; then + echo -e "${YELLOW}⚠ yolo-ai function already exists in fish${NC}" + else + echo "$FISH_FUNCTION" > "$FISH_DIR/yolo-ai.fish" + echo -e "${GREEN}✓ Created yolo-ai function for fish${NC}" + fi + + if [ -f "$FISH_DIR/yolo.fish" ]; then + echo -e "${YELLOW}⚠ yolo alias already exists in fish${NC}" + else + echo "alias yolo 'yolo-ai'" > "$FISH_DIR/yolo.fish" + echo -e "${GREEN}✓ Created yolo alias for fish${NC}" + fi + + if [ -f "$FISH_DIR/computer.fish" ]; then + echo -e "${YELLOW}⚠ computer alias already exists in fish${NC}" + else + echo "alias computer 'yolo-ai'" > "$FISH_DIR/computer.fish" + echo -e "${GREEN}✓ Created computer alias for fish${NC}" + fi + + # Note about sourcing + echo -e "${YELLOW}Note: Restart fish or run 'source ~/.config/fish/config.fish' to apply changes${NC}" + else + echo -e "${YELLOW}Unsupported shell ($SHELL). Please add aliases manually:${NC}" + echo -e "Add these lines to your shell's configuration file:" + echo "$YOLO_FUNCTION" + echo "alias yolo='yolo-ai'" + echo "alias computer='yolo-ai'" + fi + echo -e "${GREEN}✓ Shell integration configured${NC}" + fi +} + +# Print API key guide +print_apikey_guide() { + echo -e "\n${BLUE}${BOLD}API Key Configuration Guide:${NC}" + echo -e "\nYou have several options to configure your API keys:" + + echo -e "\n${BOLD}1. Environment Variables (Recommended)${NC}" + echo -e "Add to your shell's rc file (~/.bashrc, ~/.zshrc, or ~/.config/fish/config.fish):" + echo -e " export OPENAI_API_KEY=\"your-key-here\"" + echo -e " export AZURE_OPENAI_API_KEY=\"your-key-here\"" + echo -e " export ANTHROPIC_API_KEY=\"your-key-here\"" + echo -e " export GROQ_API_KEY=\"your-key-here\"" + + echo -e "\n${BOLD}2. Configuration File${NC}" + echo -e "Edit ${BOLD}$TARGET_DIR/yolo.yaml${NC} and add your keys:" + echo -e " openai_api_key: your-key-here" + echo -e " azure_openai_api_key: your-key-here" + echo -e " anthropic_api_key: your-key-here" + echo -e " groq_api_key: your-key-here" + + echo -e "\n${BOLD}3. Environment File${NC}" + echo -e "Create ${BOLD}$TARGET_DIR/.env${NC} with:" + echo -e " OPENAI_API_KEY=your-key-here" + echo -e " AZURE_OPENAI_API_KEY=your-key-here" + echo -e " ANTHROPIC_API_KEY=your-key-here" + echo -e " GROQ_API_KEY=your-key-here" + + echo -e "\n${GREEN}${BOLD}Note:${NC} The default configuration uses G4F which ${GREEN}doesn't require an API key!${NC}" + echo -e "To use other providers, configure the appropriate API key and update ${BOLD}yolo.yaml${NC}" + echo -e "Supported providers: OpenAI, Azure OpenAI, Anthropic (Claude), Groq, Ollama, and G4F\n" +} + +# Print success message +print_success() { + echo -e "\n${GREEN}${BOLD}Installation Complete!${NC}" + echo -e "\nTo start using Yolo AI Command Bot:" + echo -e "1. Restart your terminal or run: ${BOLD}source ~/.$(basename $SHELL)rc${NC}" + echo -e "2. Run: ${BOLD}yolo what time is it${NC}" + echo -e "\nFor configuration options, check: ${BOLD}$TARGET_DIR/yolo.yaml${NC}" + if [ $CREATE_VENV -eq 1 ]; then + echo -e "Virtual environment is at: ${BOLD}$TARGET_DIR/venv${NC}" + fi +} + +print_completion_guide() { + echo -e "\n${GREEN}${BOLD}✓ Finished Installing Yolo${NC}" + echo -e "\nRun commands using:" + echo -e " ${CYAN}\`yolo [Enter Prompt Here]\`${NC}" + + # Print warning about directory dependencies + echo -e "\n${YELLOW}${BOLD}Warning:${NC}" + if [ "$CUSTOM_INSTALL" = true ]; then + echo -e "If ${TARGET_DIR} is moved or deleted, the yolo command will not work." + else + echo -e "If the installation directory is moved or deleted, the yolo command will not work." + fi + echo -e "You will need to run install.sh again to recreate the configuration." + + # Print API configuration guide + echo -e "\n${BLUE}${BOLD}API Key Configuration:${NC}" + echo -e "\nBy default, Yolo uses G4F which requires no API key." + echo -e "However, if you want to use other providers, you'll need their respective API keys." + echo -e "\nThere are multiple options for providing API keys:" + + echo -e "\n1. ${BOLD}Environment Variables${NC} (Recommended)" + echo -e " Add these to your shell's config file (.bashrc, .zshrc, or config.fish):" + echo -e " ${CYAN}export OPENAI_API_KEY=\"[yourkey]\"" + echo -e " export AZURE_OPENAI_API_KEY=\"[yourkey]\"" + echo -e " export ANTHROPIC_API_KEY=\"[yourkey]\"" + echo -e " export GROQ_API_KEY=\"[yourkey]\"${NC}" + + echo -e "\n2. ${BOLD}Configuration File${NC}" + echo -e " Edit yolo.yaml and add your keys:" + echo -e " ${CYAN}Location: ${TARGET_DIR}/yolo.yaml${NC}" + + echo -e "\n3. ${BOLD}Environment File${NC}" + echo -e " Create or edit .env file with your keys:" + echo -e " ${CYAN}Location: ${TARGET_DIR}/.env${NC}" + + echo -e "\n4. ${BOLD}API Key File${NC}" + echo -e " For OpenAI, you can also use:" + echo -e " ${CYAN}Location: ~/.openai.apikey${NC}" + + echo -e "\n${BOLD}Supported Providers:${NC}" + echo -e "- G4F (Default, no key needed)" + echo -e "- OpenAI" + echo -e "- Azure OpenAI" + echo -e "- Anthropic (Claude)" + echo -e "- Groq" + echo -e "- Ollama" + + echo -e "\nTo change providers, update the 'api' setting in yolo.yaml" +} + +finish_installation() { + if [ $? -eq 0 ]; then + print_completion_guide + echo -e "\n${GREEN}${BOLD}Installation Complete!${NC}" + else + echo -e "\n${RED}${BOLD}Installation failed. Please check the errors above.${NC}" + fi +} + +# Main execution +clear +echo -e "${BOLD}Welcome to Yolo AI Command Bot Installer${NC}\n" +print_options +get_choice +handle_optional_files_menu +if [ $CREATE_OPTIONAL -eq 1 ]; then + create_apikey_file + create_env_file +fi +main_install +print_apikey_guide +finish_installation diff --git a/prompt.txt b/prompt.txt index 0575506..2e4939e 100644 --- a/prompt.txt +++ b/prompt.txt @@ -20,6 +20,11 @@ Rules: * Do not repeat or paraphrase the question in your response * Do not rush to a conclusion * Never start a response with ``` +* IMPORTANT: If your answer is purely informational (not intended to be executed), use echo with properly escaped quotes: echo "This is information" +* Never mix echo with actual commands - either provide a pure command OR echo text, not both +* When showing a command, just show the command itself without echo +* Always properly escape quotes in echo statements +* Always ensure your response can be executed directly in a shell without syntax errors Follow above rules. There are no exceptions to these rules. diff --git a/requirements.txt b/requirements.txt index f618921..43f2207 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,4 +7,6 @@ distro==1.9.0 PyYAML==6.0.1 pyperclip==1.9.0 groq==0.9.0 -anthropic==0.30.0 \ No newline at end of file +anthropic==0.30.0 +g4f==0.3.2.3 +curl_cffi==0.7.3 \ No newline at end of file diff --git a/yolo.py b/yolo.py index 18b1671..e0882b0 100755 --- a/yolo.py +++ b/yolo.py @@ -6,7 +6,7 @@ import os import platform -from ai_model import AIModel, GroqModel, OpenAIModel, OllamaModel, AnthropicModel, AzureOpenAIModel +from ai_model import AIModel, GroqModel, OpenAIModel, OllamaModel, AnthropicModel, AzureOpenAIModel, G4FModel import sys import subprocess import dotenv @@ -72,22 +72,43 @@ def get_os_friendly_name(): else: return os_name -def chat_completion(client, query, config, shell): +# Global variable to store conversation history +conversation_history = [] + +def chat_completion(client, query, config, shell, use_history=False): if query == "": print ("No user prompt specified.") sys.exit(-1) system_prompt = get_system_prompt(shell) - + + # Initialize messages with system prompt + messages = [{"role": "system", "content": system_prompt}] + + # Add conversation history if requested + if use_history and conversation_history: + messages.extend(conversation_history) + + # Add the current query + messages.append({"role": "user", "content": query}) + response = client.chat( model=config["model"], - messages=[ - {"role": "system", "content": system_prompt}, - {"role": "user", "content": query} - ], + messages=messages, temperature=config["temperature"], max_tokens=config["max_tokens"]) - + + # Add the user query and AI response to history + # Always update history regardless of use_history flag + if not conversation_history: + conversation_history.append({"role": "user", "content": query}) + else: + # Only add if it's not already the last user message + if conversation_history[-1]["role"] != "user" or conversation_history[-1]["content"] != query: + conversation_history.append({"role": "user", "content": query}) + + conversation_history.append({"role": "assistant", "content": response}) + return response def check_for_issue(response): @@ -115,9 +136,12 @@ def prompt_user_for_action(config, ask_flag, response): if os.name == "posix" and missing_posix_display(): if get_os_friendly_name() != "Darwin/macOS": copy_to_clipboard_snippet = "" - + + # Add follow-up option + followup_snippet = " [f]ollow-up" + if bool(config["safety"]) == True or ask_flag == True: - prompt_text = f"Execute command? [Y]es [n]o{modify_snippet}{copy_to_clipboard_snippet} ==> " + prompt_text = f"Execute command? [Y]es [n]o{modify_snippet}{copy_to_clipboard_snippet}{followup_snippet} ==> " print(prompt_text, end = '') user_input = input() return user_input @@ -126,7 +150,7 @@ def prompt_user_for_action(config, ask_flag, response): return "Y" def eval_user_intent_and_execute(client, config, user_input, command, shell, ask_flag): - if user_input.upper() not in ["", "Y", "C", "M"]: + if user_input.upper() not in ["", "Y", "C", "M", "F"]: print("No action taken.") return @@ -147,6 +171,22 @@ def eval_user_intent_and_execute(client, config, user_input, command, shell, ask print() eval_user_intent_and_execute(client, config, user_intent, modded_response, shell, ask_flag) + if user_input.upper() == "F": + print("Follow-up question: ", end = '') + followup_query = input() + + # For follow-ups about previous commands, add context + if "command" in followup_query.lower() and ("what" in followup_query.lower() or "explain" in followup_query.lower() or "do" in followup_query.lower()): + followup_query = f"Regarding the previous command '{command}': {followup_query}" + + # Use conversation history for follow-up + followup_response = chat_completion(client, followup_query, config, shell, use_history=True) + check_for_issue(followup_response) + check_for_markdown(followup_response) + user_intent = prompt_user_for_action(config, ask_flag, followup_response) + print() + eval_user_intent_and_execute(client, config, user_intent, followup_response, shell, ask_flag) + if user_input.upper() == "C": if os.name == "posix" and missing_posix_display(): if get_os_friendly_name() != "Darwin/macOS": @@ -185,7 +225,10 @@ def main(): user_prompt = " ".join(arguments) ## core prompting loop logic - result = chat_completion(client, user_prompt, config, shell) + # Clear conversation history at the start of a new command + conversation_history.clear() + + result = chat_completion(client, user_prompt, config, shell, use_history=False) check_for_issue(result) check_for_markdown(result) diff --git a/yolo.yaml b/yolo.yaml index 77d24a2..2a7db28 100644 --- a/yolo.yaml +++ b/yolo.yaml @@ -1,5 +1,5 @@ -api: openai # openai, azure, groq, ollama, anthropic -model: gpt-4o # if azure this is the deployment name +api: g4f # openai, azure, groq, ollama, anthropic, g4f +model: gpt-3.5-turbo # if azure this is the deployment name # other options: gpt-4o, llama3-8b-8192, or claude-3-5-sonnet-20240620 # Azure specific (only needed if api: azure-openai)