From 76715d6e822733b6f12e6c43e2173f801d2ce149 Mon Sep 17 00:00:00 2001 From: Madhu Date: Mon, 3 Feb 2025 00:56:22 +0530 Subject: [PATCH 1/5] new proj - o3 mini code interpreter --- ai_agent_tutorials/o3-mini-agent/main.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 ai_agent_tutorials/o3-mini-agent/main.py diff --git a/ai_agent_tutorials/o3-mini-agent/main.py b/ai_agent_tutorials/o3-mini-agent/main.py new file mode 100644 index 0000000..cf21706 --- /dev/null +++ b/ai_agent_tutorials/o3-mini-agent/main.py @@ -0,0 +1,20 @@ +from agno.agent import Agent, RunResponse +from agno.models.openai import OpenAIChat +from agno.models.google import Gemini +import os +from dotenv import load_dotenv +load_dotenv() + +vision_agent = Agent( + model=Gemini(id="gemini-2.0-flash-exp", api_key=os.getenv("GEMINI_API_KEY")), + markdown=True, +) + +coding_agent = Agent( + model=OpenAIChat(id="o3-mini", api_key=os.getenv("OPENAI_API_KEY")), + markdown=True +) + +# Print the response in the terminal +coding_agent.print_response("Share a 2 sentence horror story.") + From ee8166d74683ee300ad8f80a532bd55cfd98f02d Mon Sep 17 00:00:00 2001 From: Madhu Date: Wed, 5 Feb 2025 16:40:08 +0530 Subject: [PATCH 2/5] o3-mini agent gives code successfully --- ai_agent_tutorials/o3-mini-agent/main.py | 255 +++++++++++++++++- .../o3-mini-agent/requirements.txt | 5 + 2 files changed, 250 insertions(+), 10 deletions(-) create mode 100644 ai_agent_tutorials/o3-mini-agent/requirements.txt diff --git a/ai_agent_tutorials/o3-mini-agent/main.py b/ai_agent_tutorials/o3-mini-agent/main.py index cf21706..5768654 100644 --- a/ai_agent_tutorials/o3-mini-agent/main.py +++ b/ai_agent_tutorials/o3-mini-agent/main.py @@ -1,20 +1,255 @@ +from typing import Optional, Dict, Any +import streamlit as st from agno.agent import Agent, RunResponse from agno.models.openai import OpenAIChat from agno.models.google import Gemini +from e2b_code_interpreter import Sandbox import os from dotenv import load_dotenv +from PIL import Image +from io import BytesIO load_dotenv() -vision_agent = Agent( - model=Gemini(id="gemini-2.0-flash-exp", api_key=os.getenv("GEMINI_API_KEY")), - markdown=True, -) +def initialize_session_state() -> None: + """Initialize Streamlit session state variables.""" + if 'openai_key' not in st.session_state: + st.session_state.openai_key = '' + if 'gemini_key' not in st.session_state: + st.session_state.gemini_key = '' + if 'e2b_key' not in st.session_state: + st.session_state.e2b_key = '' + if 'sandbox' not in st.session_state: + st.session_state.sandbox = None -coding_agent = Agent( - model=OpenAIChat(id="o3-mini", api_key=os.getenv("OPENAI_API_KEY")), - markdown=True -) +def setup_sidebar() -> None: + """Setup sidebar with API key inputs.""" + with st.sidebar: + st.title("API Configuration") + st.session_state.openai_key = st.text_input("OpenAI API Key", + value=st.session_state.openai_key, + type="password") + st.session_state.gemini_key = st.text_input("Gemini API Key", + value=st.session_state.gemini_key, + type="password") + st.session_state.e2b_key = st.text_input("E2B API Key", + value=st.session_state.e2b_key, + type="password") -# Print the response in the terminal -coding_agent.print_response("Share a 2 sentence horror story.") +def create_agents() -> tuple[Agent, Agent, Agent]: + """Create vision, coding, and execution agents with API keys from session state.""" + vision_agent = Agent( + model=Gemini(id="gemini-2.0-flash-exp", api_key=st.session_state.gemini_key), + markdown=True, + ) + + coding_agent = Agent( + model=OpenAIChat( + id="o3-mini", + api_key=st.session_state.openai_key, + system_prompt="""You are an expert Python programmer. You will receive coding problems similar to LeetCode questions, + which may include problem statements, sample inputs, and examples. Your task is to: + 1. Analyze the problem carefully + 2. Write clean, efficient Python code to solve it + 3. Include proper documentation and type hints + 4. The code will be executed in an e2b sandbox environment + Please ensure your code is complete and handles edge cases appropriately.""" + ), + markdown=True + ) + + execution_agent = Agent( + model=OpenAIChat( + id="o3-mini", + api_key=st.session_state.openai_key, + system_prompt="""You are an expert at executing Python code in sandbox environments. + Your task is to: + 1. Take the provided Python code + 2. Execute it in the e2b sandbox + 3. Format and explain the results clearly + 4. Handle any execution errors gracefully + Always ensure proper error handling and clear output formatting.""" + ), + markdown=True + ) + + return vision_agent, coding_agent, execution_agent + +def initialize_sandbox() -> None: + """Initialize or reset the e2b sandbox.""" + try: + if st.session_state.sandbox: + st.session_state.sandbox.close() + os.environ['E2B_API_KEY'] = st.session_state.e2b_key + st.session_state.sandbox = Sandbox() + except Exception as e: + st.error(f"Failed to initialize sandbox: {str(e)}") + st.session_state.sandbox = None + +def run_code_in_sandbox(code: str) -> Dict[str, Any]: + """ + Run code in e2b sandbox and return execution results. + + Args: + code: Python code to execute + + Returns: + Dict containing execution logs and any output + """ + if not st.session_state.sandbox: + initialize_sandbox() + + execution = st.session_state.sandbox.run_code(code) + return { + "logs": execution.logs, + "files": st.session_state.sandbox.files.list("/") + } + +def process_image_with_gemini(vision_agent: Agent, image: Image) -> str: + """ + Process uploaded image with Gemini Vision to extract code problem. + + Args: + vision_agent: Initialized Gemini vision agent + image: Uploaded image to process + + Returns: + str: Extracted problem description in natural language + """ + prompt = """Analyze this image and extract any coding problem or code snippet shown. + Describe it in clear natural language, including any: + 1. Problem statement + 2. Input/output examples + 3. Constraints or requirements + Format it as a proper coding problem description.""" + + # Convert image to bytes for Gemini + img_byte_arr = BytesIO() + image.save(img_byte_arr, format=image.format) + img_byte_arr = img_byte_arr.getvalue() + + response = vision_agent.run(prompt, images=[img_byte_arr]) + return response.content + +def execute_code_with_agent(execution_agent: Agent, code: str, sandbox: Sandbox) -> str: + """ + Use execution agent to run and explain code results. + """ + try: + execution = sandbox.run_code(code) + + # Handle execution errors + if execution.error: + error_prompt = f"""The code execution resulted in an error: + Error: {execution.error} + + Please analyze the error and provide a clear explanation of what went wrong.""" + response = execution_agent.run(error_prompt) + return f"⚠️ Execution Error:\n{response.content}" + + prompt = f"""Here is the code execution result: + Logs: {execution.logs} + Files: {sandbox.files.list("/")} + + Please provide a clear explanation of the results and any outputs.""" + + response = execution_agent.run(prompt) + return response.content + except Exception as e: + return f"⚠️ Sandbox Error: {str(e)}" + +def main() -> None: + """Main application function.""" + st.title("O3-Mini Coding Assistant") + + initialize_session_state() + setup_sidebar() + + # Check all required API keys + if not (st.session_state.openai_key and + st.session_state.gemini_key and + st.session_state.e2b_key): + st.warning("Please enter all required API keys in the sidebar.") + return + + vision_agent, coding_agent, execution_agent = create_agents() + + # Clean, single-column layout + uploaded_image = st.file_uploader( + "Upload an image of your coding problem (optional)", + type=['png', 'jpg', 'jpeg'] + ) + + if uploaded_image: + st.image(uploaded_image, caption="Uploaded Image", use_column_width=True) + + user_query = st.text_area( + "Or type your coding problem here:", + placeholder="Example: Write a function to find the sum of two numbers. Include sample input/output cases.", + height=100 + ) + + # Process button + if st.button("Generate & Execute Solution", type="primary"): + if uploaded_image and not user_query: + # Process image with Gemini + with st.spinner("Processing image..."): + image = Image.open(uploaded_image) + extracted_query = process_image_with_gemini(vision_agent, image) + + st.info("📝 Extracted Problem:") + st.write(extracted_query) + + # Pass extracted query to coding agent + with st.spinner("Generating solution..."): + response = coding_agent.run(extracted_query) + + elif user_query and not uploaded_image: + # Direct text input processing + with st.spinner("Generating solution..."): + response = coding_agent.run(user_query) + + elif user_query and uploaded_image: + st.error("Please use either image upload OR text input, not both.") + return + else: + st.warning("Please provide either an image or text description of your coding problem.") + return + + # Display and execute solution + if 'response' in locals(): + st.divider() + st.subheader("💻 Solution") + + # Extract code from markdown response + code_blocks = response.content.split("```python") + if len(code_blocks) > 1: + code = code_blocks[1].split("```")[0].strip() + + # Display the code + st.code(code, language="python") + + # Execute code with execution agent + with st.spinner("Executing code..."): + if not st.session_state.sandbox: + initialize_sandbox() + + execution_results = execute_code_with_agent( + execution_agent, + code, + st.session_state.sandbox + ) + + # Display execution results + st.divider() + st.subheader("🚀 Execution Results") + st.markdown(execution_results) + + # Display any generated files + files = st.session_state.sandbox.files.list("/") + if files: + st.markdown("📁 **Generated Files:**") + st.json(files) + +if __name__ == "__main__": + main() diff --git a/ai_agent_tutorials/o3-mini-agent/requirements.txt b/ai_agent_tutorials/o3-mini-agent/requirements.txt new file mode 100644 index 0000000..c593947 --- /dev/null +++ b/ai_agent_tutorials/o3-mini-agent/requirements.txt @@ -0,0 +1,5 @@ +streamlit +python-dotenv +e2b +agno +Pillow \ No newline at end of file From d8825c00ee38c23bc754192fe4a670bfe9d75151 Mon Sep 17 00:00:00 2001 From: Madhu Date: Wed, 5 Feb 2025 18:12:56 +0530 Subject: [PATCH 3/5] working o3 mini code interpreter --- ai_agent_tutorials/o3-mini-agent/main.py | 153 ++++++++++++++--------- 1 file changed, 96 insertions(+), 57 deletions(-) diff --git a/ai_agent_tutorials/o3-mini-agent/main.py b/ai_agent_tutorials/o3-mini-agent/main.py index 5768654..69ef98b 100644 --- a/ai_agent_tutorials/o3-mini-agent/main.py +++ b/ai_agent_tutorials/o3-mini-agent/main.py @@ -8,6 +8,7 @@ import os from dotenv import load_dotenv from PIL import Image from io import BytesIO +import base64 load_dotenv() def initialize_session_state() -> None: @@ -38,7 +39,7 @@ def setup_sidebar() -> None: def create_agents() -> tuple[Agent, Agent, Agent]: """Create vision, coding, and execution agents with API keys from session state.""" vision_agent = Agent( - model=Gemini(id="gemini-2.0-flash-exp", api_key=st.session_state.gemini_key), + model=Gemini(id="gemini-exp-1206", api_key=st.session_state.gemini_key), markdown=True, ) @@ -75,26 +76,21 @@ def create_agents() -> tuple[Agent, Agent, Agent]: return vision_agent, coding_agent, execution_agent def initialize_sandbox() -> None: - """Initialize or reset the e2b sandbox.""" + """Initialize or reset the e2b sandbox with proper timeout configuration.""" try: if st.session_state.sandbox: - st.session_state.sandbox.close() + try: + st.session_state.sandbox.close() + except: + pass os.environ['E2B_API_KEY'] = st.session_state.e2b_key - st.session_state.sandbox = Sandbox() + # Initialize sandbox with 60 second timeout + st.session_state.sandbox = Sandbox(timeout=60) except Exception as e: st.error(f"Failed to initialize sandbox: {str(e)}") st.session_state.sandbox = None def run_code_in_sandbox(code: str) -> Dict[str, Any]: - """ - Run code in e2b sandbox and return execution results. - - Args: - code: Python code to execute - - Returns: - Dict containing execution logs and any output - """ if not st.session_state.sandbox: initialize_sandbox() @@ -107,13 +103,6 @@ def run_code_in_sandbox(code: str) -> Dict[str, Any]: def process_image_with_gemini(vision_agent: Agent, image: Image) -> str: """ Process uploaded image with Gemini Vision to extract code problem. - - Args: - vision_agent: Initialized Gemini vision agent - image: Uploaded image to process - - Returns: - str: Extracted problem description in natural language """ prompt = """Analyze this image and extract any coding problem or code snippet shown. Describe it in clear natural language, including any: @@ -122,23 +111,46 @@ def process_image_with_gemini(vision_agent: Agent, image: Image) -> str: 3. Constraints or requirements Format it as a proper coding problem description.""" - # Convert image to bytes for Gemini - img_byte_arr = BytesIO() - image.save(img_byte_arr, format=image.format) - img_byte_arr = img_byte_arr.getvalue() - - response = vision_agent.run(prompt, images=[img_byte_arr]) - return response.content + # Save image to a temporary file + temp_path = "temp_image.png" + try: + # Convert to RGB if needed + if image.mode != 'RGB': + image = image.convert('RGB') + image.save(temp_path, format="PNG") + + # Read the file and create image data + with open(temp_path, 'rb') as img_file: + img_bytes = img_file.read() + + # Pass image to Gemini + response = vision_agent.run( + prompt, + images=[{"filepath": temp_path}] # Use filepath instead of content + ) + return response.content + except Exception as e: + st.error(f"Error processing image: {str(e)}") + return "Failed to process the image. Please try again or use text input instead." + finally: + # Clean up temporary file + if os.path.exists(temp_path): + os.remove(temp_path) def execute_code_with_agent(execution_agent: Agent, code: str, sandbox: Sandbox) -> str: """ Use execution agent to run and explain code results. """ try: + # Set timeout to 30 seconds for code execution + sandbox.set_timeout(30) execution = sandbox.run_code(code) # Handle execution errors if execution.error: + if "TimeoutException" in str(execution.error): + return "⚠️ Execution Timeout: The code took too long to execute (>30 seconds). Please optimize your solution or try a smaller input." + error_prompt = f"""The code execution resulted in an error: Error: {execution.error} @@ -146,23 +158,37 @@ def execute_code_with_agent(execution_agent: Agent, code: str, sandbox: Sandbox) response = execution_agent.run(error_prompt) return f"⚠️ Execution Error:\n{response.content}" + # Get files list safely + try: + files = sandbox.files.list("/") + except: + files = [] + prompt = f"""Here is the code execution result: Logs: {execution.logs} - Files: {sandbox.files.list("/")} + Files: {str(files)} Please provide a clear explanation of the results and any outputs.""" response = execution_agent.run(prompt) return response.content except Exception as e: + # Reinitialize sandbox on error + try: + initialize_sandbox() + except: + pass return f"⚠️ Sandbox Error: {str(e)}" def main() -> None: """Main application function.""" - st.title("O3-Mini Coding Assistant") + st.title("O3-Mini Coding Agent") + # Add timeout info in sidebar initialize_session_state() setup_sidebar() + with st.sidebar: + st.info("⏱️ Code execution timeout: 30 seconds") # Check all required API keys if not (st.session_state.openai_key and @@ -180,7 +206,7 @@ def main() -> None: ) if uploaded_image: - st.image(uploaded_image, caption="Uploaded Image", use_column_width=True) + st.image(uploaded_image, caption="Uploaded Image", use_container_width=True) user_query = st.text_area( "Or type your coding problem here:", @@ -193,16 +219,25 @@ def main() -> None: if uploaded_image and not user_query: # Process image with Gemini with st.spinner("Processing image..."): - image = Image.open(uploaded_image) - extracted_query = process_image_with_gemini(vision_agent, image) - - st.info("📝 Extracted Problem:") - st.write(extracted_query) - - # Pass extracted query to coding agent - with st.spinner("Generating solution..."): - response = coding_agent.run(extracted_query) + try: + # Save uploaded file to temporary location + image = Image.open(uploaded_image) + extracted_query = process_image_with_gemini(vision_agent, image) + if extracted_query.startswith("Failed to process"): + st.error(extracted_query) + return + + st.info("📝 Extracted Problem:") + st.write(extracted_query) + + # Pass extracted query to coding agent + with st.spinner("Generating solution..."): + response = coding_agent.run(extracted_query) + except Exception as e: + st.error(f"Error processing image: {str(e)}") + return + elif user_query and not uploaded_image: # Direct text input processing with st.spinner("Generating solution..."): @@ -230,25 +265,29 @@ def main() -> None: # Execute code with execution agent with st.spinner("Executing code..."): - if not st.session_state.sandbox: - initialize_sandbox() + # Always initialize a fresh sandbox for each execution + initialize_sandbox() - execution_results = execute_code_with_agent( - execution_agent, - code, - st.session_state.sandbox - ) - - # Display execution results - st.divider() - st.subheader("🚀 Execution Results") - st.markdown(execution_results) - - # Display any generated files - files = st.session_state.sandbox.files.list("/") - if files: - st.markdown("📁 **Generated Files:**") - st.json(files) + if st.session_state.sandbox: + execution_results = execute_code_with_agent( + execution_agent, + code, + st.session_state.sandbox + ) + + # Display execution results + st.divider() + st.subheader("🚀 Execution Results") + st.markdown(execution_results) + + # Try to display files if available + try: + files = st.session_state.sandbox.files.list("/") + if files: + st.markdown("📁 **Generated Files:**") + st.json(files) + except: + pass if __name__ == "__main__": main() From ceb218bc5048997023c38beff41c6bf72a7cb08c Mon Sep 17 00:00:00 2001 From: Madhu Date: Wed, 5 Feb 2025 18:55:53 +0530 Subject: [PATCH 4/5] final version --- ai_agent_tutorials/o3-mini-agent/main.py | 294 ------------------ .../o3-mini-agent/requirements.txt | 5 - 2 files changed, 299 deletions(-) delete mode 100644 ai_agent_tutorials/o3-mini-agent/main.py delete mode 100644 ai_agent_tutorials/o3-mini-agent/requirements.txt diff --git a/ai_agent_tutorials/o3-mini-agent/main.py b/ai_agent_tutorials/o3-mini-agent/main.py deleted file mode 100644 index 69ef98b..0000000 --- a/ai_agent_tutorials/o3-mini-agent/main.py +++ /dev/null @@ -1,294 +0,0 @@ -from typing import Optional, Dict, Any -import streamlit as st -from agno.agent import Agent, RunResponse -from agno.models.openai import OpenAIChat -from agno.models.google import Gemini -from e2b_code_interpreter import Sandbox -import os -from dotenv import load_dotenv -from PIL import Image -from io import BytesIO -import base64 -load_dotenv() - -def initialize_session_state() -> None: - """Initialize Streamlit session state variables.""" - if 'openai_key' not in st.session_state: - st.session_state.openai_key = '' - if 'gemini_key' not in st.session_state: - st.session_state.gemini_key = '' - if 'e2b_key' not in st.session_state: - st.session_state.e2b_key = '' - if 'sandbox' not in st.session_state: - st.session_state.sandbox = None - -def setup_sidebar() -> None: - """Setup sidebar with API key inputs.""" - with st.sidebar: - st.title("API Configuration") - st.session_state.openai_key = st.text_input("OpenAI API Key", - value=st.session_state.openai_key, - type="password") - st.session_state.gemini_key = st.text_input("Gemini API Key", - value=st.session_state.gemini_key, - type="password") - st.session_state.e2b_key = st.text_input("E2B API Key", - value=st.session_state.e2b_key, - type="password") - -def create_agents() -> tuple[Agent, Agent, Agent]: - """Create vision, coding, and execution agents with API keys from session state.""" - vision_agent = Agent( - model=Gemini(id="gemini-exp-1206", api_key=st.session_state.gemini_key), - markdown=True, - ) - - coding_agent = Agent( - model=OpenAIChat( - id="o3-mini", - api_key=st.session_state.openai_key, - system_prompt="""You are an expert Python programmer. You will receive coding problems similar to LeetCode questions, - which may include problem statements, sample inputs, and examples. Your task is to: - 1. Analyze the problem carefully - 2. Write clean, efficient Python code to solve it - 3. Include proper documentation and type hints - 4. The code will be executed in an e2b sandbox environment - Please ensure your code is complete and handles edge cases appropriately.""" - ), - markdown=True - ) - - execution_agent = Agent( - model=OpenAIChat( - id="o3-mini", - api_key=st.session_state.openai_key, - system_prompt="""You are an expert at executing Python code in sandbox environments. - Your task is to: - 1. Take the provided Python code - 2. Execute it in the e2b sandbox - 3. Format and explain the results clearly - 4. Handle any execution errors gracefully - Always ensure proper error handling and clear output formatting.""" - ), - markdown=True - ) - - return vision_agent, coding_agent, execution_agent - -def initialize_sandbox() -> None: - """Initialize or reset the e2b sandbox with proper timeout configuration.""" - try: - if st.session_state.sandbox: - try: - st.session_state.sandbox.close() - except: - pass - os.environ['E2B_API_KEY'] = st.session_state.e2b_key - # Initialize sandbox with 60 second timeout - st.session_state.sandbox = Sandbox(timeout=60) - except Exception as e: - st.error(f"Failed to initialize sandbox: {str(e)}") - st.session_state.sandbox = None - -def run_code_in_sandbox(code: str) -> Dict[str, Any]: - if not st.session_state.sandbox: - initialize_sandbox() - - execution = st.session_state.sandbox.run_code(code) - return { - "logs": execution.logs, - "files": st.session_state.sandbox.files.list("/") - } - -def process_image_with_gemini(vision_agent: Agent, image: Image) -> str: - """ - Process uploaded image with Gemini Vision to extract code problem. - """ - prompt = """Analyze this image and extract any coding problem or code snippet shown. - Describe it in clear natural language, including any: - 1. Problem statement - 2. Input/output examples - 3. Constraints or requirements - Format it as a proper coding problem description.""" - - # Save image to a temporary file - temp_path = "temp_image.png" - try: - # Convert to RGB if needed - if image.mode != 'RGB': - image = image.convert('RGB') - image.save(temp_path, format="PNG") - - # Read the file and create image data - with open(temp_path, 'rb') as img_file: - img_bytes = img_file.read() - - # Pass image to Gemini - response = vision_agent.run( - prompt, - images=[{"filepath": temp_path}] # Use filepath instead of content - ) - return response.content - except Exception as e: - st.error(f"Error processing image: {str(e)}") - return "Failed to process the image. Please try again or use text input instead." - finally: - # Clean up temporary file - if os.path.exists(temp_path): - os.remove(temp_path) - -def execute_code_with_agent(execution_agent: Agent, code: str, sandbox: Sandbox) -> str: - """ - Use execution agent to run and explain code results. - """ - try: - # Set timeout to 30 seconds for code execution - sandbox.set_timeout(30) - execution = sandbox.run_code(code) - - # Handle execution errors - if execution.error: - if "TimeoutException" in str(execution.error): - return "⚠️ Execution Timeout: The code took too long to execute (>30 seconds). Please optimize your solution or try a smaller input." - - error_prompt = f"""The code execution resulted in an error: - Error: {execution.error} - - Please analyze the error and provide a clear explanation of what went wrong.""" - response = execution_agent.run(error_prompt) - return f"⚠️ Execution Error:\n{response.content}" - - # Get files list safely - try: - files = sandbox.files.list("/") - except: - files = [] - - prompt = f"""Here is the code execution result: - Logs: {execution.logs} - Files: {str(files)} - - Please provide a clear explanation of the results and any outputs.""" - - response = execution_agent.run(prompt) - return response.content - except Exception as e: - # Reinitialize sandbox on error - try: - initialize_sandbox() - except: - pass - return f"⚠️ Sandbox Error: {str(e)}" - -def main() -> None: - """Main application function.""" - st.title("O3-Mini Coding Agent") - - # Add timeout info in sidebar - initialize_session_state() - setup_sidebar() - with st.sidebar: - st.info("⏱️ Code execution timeout: 30 seconds") - - # Check all required API keys - if not (st.session_state.openai_key and - st.session_state.gemini_key and - st.session_state.e2b_key): - st.warning("Please enter all required API keys in the sidebar.") - return - - vision_agent, coding_agent, execution_agent = create_agents() - - # Clean, single-column layout - uploaded_image = st.file_uploader( - "Upload an image of your coding problem (optional)", - type=['png', 'jpg', 'jpeg'] - ) - - if uploaded_image: - st.image(uploaded_image, caption="Uploaded Image", use_container_width=True) - - user_query = st.text_area( - "Or type your coding problem here:", - placeholder="Example: Write a function to find the sum of two numbers. Include sample input/output cases.", - height=100 - ) - - # Process button - if st.button("Generate & Execute Solution", type="primary"): - if uploaded_image and not user_query: - # Process image with Gemini - with st.spinner("Processing image..."): - try: - # Save uploaded file to temporary location - image = Image.open(uploaded_image) - extracted_query = process_image_with_gemini(vision_agent, image) - - if extracted_query.startswith("Failed to process"): - st.error(extracted_query) - return - - st.info("📝 Extracted Problem:") - st.write(extracted_query) - - # Pass extracted query to coding agent - with st.spinner("Generating solution..."): - response = coding_agent.run(extracted_query) - except Exception as e: - st.error(f"Error processing image: {str(e)}") - return - - elif user_query and not uploaded_image: - # Direct text input processing - with st.spinner("Generating solution..."): - response = coding_agent.run(user_query) - - elif user_query and uploaded_image: - st.error("Please use either image upload OR text input, not both.") - return - else: - st.warning("Please provide either an image or text description of your coding problem.") - return - - # Display and execute solution - if 'response' in locals(): - st.divider() - st.subheader("💻 Solution") - - # Extract code from markdown response - code_blocks = response.content.split("```python") - if len(code_blocks) > 1: - code = code_blocks[1].split("```")[0].strip() - - # Display the code - st.code(code, language="python") - - # Execute code with execution agent - with st.spinner("Executing code..."): - # Always initialize a fresh sandbox for each execution - initialize_sandbox() - - if st.session_state.sandbox: - execution_results = execute_code_with_agent( - execution_agent, - code, - st.session_state.sandbox - ) - - # Display execution results - st.divider() - st.subheader("🚀 Execution Results") - st.markdown(execution_results) - - # Try to display files if available - try: - files = st.session_state.sandbox.files.list("/") - if files: - st.markdown("📁 **Generated Files:**") - st.json(files) - except: - pass - -if __name__ == "__main__": - main() - diff --git a/ai_agent_tutorials/o3-mini-agent/requirements.txt b/ai_agent_tutorials/o3-mini-agent/requirements.txt deleted file mode 100644 index c593947..0000000 --- a/ai_agent_tutorials/o3-mini-agent/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -streamlit -python-dotenv -e2b -agno -Pillow \ No newline at end of file From acc5105818b9c798fc8a85909c391832664a7dc6 Mon Sep 17 00:00:00 2001 From: Madhu Date: Wed, 5 Feb 2025 18:56:33 +0530 Subject: [PATCH 5/5] final version - readme + requirements --- .../ai_coding_agent_o3-mini/README.md | 61 ++++ .../ai_coding_agent_o3.py | 280 ++++++++++++++++++ .../ai_coding_agent_o3-mini/requirements.txt | 4 + 3 files changed, 345 insertions(+) create mode 100644 ai_agent_tutorials/ai_coding_agent_o3-mini/README.md create mode 100644 ai_agent_tutorials/ai_coding_agent_o3-mini/ai_coding_agent_o3.py create mode 100644 ai_agent_tutorials/ai_coding_agent_o3-mini/requirements.txt diff --git a/ai_agent_tutorials/ai_coding_agent_o3-mini/README.md b/ai_agent_tutorials/ai_coding_agent_o3-mini/README.md new file mode 100644 index 0000000..095dac9 --- /dev/null +++ b/ai_agent_tutorials/ai_coding_agent_o3-mini/README.md @@ -0,0 +1,61 @@ +# 💻 O3-Mini Coding Agent +An AI Powered Streamlit application that serves as your personal coding assistant, powered by multiple Agents built on the new o3-mini model. You can also upload an image of a coding problem or describe it in text, and the AI agent will analyze, generate an optimal solution, and execute it in a sandbox environment. + +## Features +#### Multi-Modal Problem Input +- Upload images of coding problems (supports PNG, JPG, JPEG) +- Type problems in natural language +- Automatic problem extraction from images +- Interactive problem processing + +#### Intelligent Code Generation +- Optimal solution generation with best time/space complexity +- Clean, documented Python code output +- Type hints and proper documentation +- Edge case handling + +#### Secure Code Execution +- Sandboxed code execution environment +- Real-time execution results +- Error handling and explanations +- 30-second execution timeout protection + +#### Multi-Agent Architecture +- Vision Agent (Gemini-exp-1206) for image processing +- Coding Agent (OpenAI- o3-mini) for solution generation +- Execution Agent (OpenAI) for code running and result analysis +- E2B Sandbox for secure code execution + +## How to Run + +Follow the steps below to set up and run the application: +- Get an OpenAI API key from: https://platform.openai.com/ +- Get a Google (Gemini) API key from: https://makersuite.google.com/app/apikey +- Get an E2B API key from: https://e2b.dev/docs/getting-started/api-key + +1. **Clone the Repository** + ```bash + git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git + cd ai_agent_tutorials/ai_coding_agent_o3-mini + ``` + +2. **Install the dependencies** + ```bash + pip install -r requirements.txt + ``` + +3. **Run the Streamlit app** + ```bash + streamlit run ai_coding_agent_o3.py + ``` + +4. **Configure API Keys** + - Enter your API keys in the sidebar + - All three keys (OpenAI, Gemini, E2B) are required for full functionality + +## Usage +1. Upload an image of a coding problem OR type your problem description +2. Click "Generate & Execute Solution" +3. View the generated solution with full documentation +4. See execution results and any generated files +5. Review any error messages or execution timeouts diff --git a/ai_agent_tutorials/ai_coding_agent_o3-mini/ai_coding_agent_o3.py b/ai_agent_tutorials/ai_coding_agent_o3-mini/ai_coding_agent_o3.py new file mode 100644 index 0000000..c7b8ce3 --- /dev/null +++ b/ai_agent_tutorials/ai_coding_agent_o3-mini/ai_coding_agent_o3.py @@ -0,0 +1,280 @@ +from typing import Optional, Dict, Any +import streamlit as st +from agno.agent import Agent, RunResponse +from agno.models.openai import OpenAIChat +from agno.models.google import Gemini +from e2b_code_interpreter import Sandbox +import os +from PIL import Image +from io import BytesIO +import base64 + +def initialize_session_state() -> None: + if 'openai_key' not in st.session_state: + st.session_state.openai_key = '' + if 'gemini_key' not in st.session_state: + st.session_state.gemini_key = '' + if 'e2b_key' not in st.session_state: + st.session_state.e2b_key = '' + if 'sandbox' not in st.session_state: + st.session_state.sandbox = None + +def setup_sidebar() -> None: + with st.sidebar: + st.title("API Configuration") + st.session_state.openai_key = st.text_input("OpenAI API Key", + value=st.session_state.openai_key, + type="password") + st.session_state.gemini_key = st.text_input("Gemini API Key", + value=st.session_state.gemini_key, + type="password") + st.session_state.e2b_key = st.text_input("E2B API Key", + value=st.session_state.e2b_key, + type="password") + +def create_agents() -> tuple[Agent, Agent, Agent]: + vision_agent = Agent( + model=Gemini(id="gemini-exp-1206", api_key=st.session_state.gemini_key), + markdown=True, + ) + + coding_agent = Agent( + model=OpenAIChat( + id="o3-mini", + api_key=st.session_state.openai_key, + system_prompt="""You are an expert Python programmer. You will receive coding problems similar to LeetCode questions, + which may include problem statements, sample inputs, and examples. Your task is to: + 1. Analyze the problem carefully and Optimally with best possible time and space complexities. + 2. Write clean, efficient Python code to solve it + 3. Include proper documentation and type hints + 4. The code will be executed in an e2b sandbox environment + Please ensure your code is complete and handles edge cases appropriately.""" + ), + markdown=True + ) + + execution_agent = Agent( + model=OpenAIChat( + id="o3-mini", + api_key=st.session_state.openai_key, + system_prompt="""You are an expert at executing Python code in sandbox environments. + Your task is to: + 1. Take the provided Python code + 2. Execute it in the e2b sandbox + 3. Format and explain the results clearly + 4. Handle any execution errors gracefully + Always ensure proper error handling and clear output formatting.""" + ), + markdown=True + ) + + return vision_agent, coding_agent, execution_agent + +def initialize_sandbox() -> None: + try: + if st.session_state.sandbox: + try: + st.session_state.sandbox.close() + except: + pass + os.environ['E2B_API_KEY'] = st.session_state.e2b_key + # Initialize sandbox with 60 second timeout + st.session_state.sandbox = Sandbox(timeout=60) + except Exception as e: + st.error(f"Failed to initialize sandbox: {str(e)}") + st.session_state.sandbox = None + +def run_code_in_sandbox(code: str) -> Dict[str, Any]: + if not st.session_state.sandbox: + initialize_sandbox() + + execution = st.session_state.sandbox.run_code(code) + return { + "logs": execution.logs, + "files": st.session_state.sandbox.files.list("/") + } + +def process_image_with_gemini(vision_agent: Agent, image: Image) -> str: + prompt = """Analyze this image and extract any coding problem or code snippet shown. + Describe it in clear natural language, including any: + 1. Problem statement + 2. Input/output examples + 3. Constraints or requirements + Format it as a proper coding problem description.""" + + # Save image to a temporary file + temp_path = "temp_image.png" + try: + # Convert to RGB if needed + if image.mode != 'RGB': + image = image.convert('RGB') + image.save(temp_path, format="PNG") + + # Read the file and create image data + with open(temp_path, 'rb') as img_file: + img_bytes = img_file.read() + + # Pass image to Gemini + response = vision_agent.run( + prompt, + images=[{"filepath": temp_path}] # Use filepath instead of content + ) + return response.content + except Exception as e: + st.error(f"Error processing image: {str(e)}") + return "Failed to process the image. Please try again or use text input instead." + finally: + # Clean up temporary file + if os.path.exists(temp_path): + os.remove(temp_path) + +def execute_code_with_agent(execution_agent: Agent, code: str, sandbox: Sandbox) -> str: + try: + # Set timeout to 30 seconds for code execution + sandbox.set_timeout(30) + execution = sandbox.run_code(code) + + # Handle execution errors + if execution.error: + if "TimeoutException" in str(execution.error): + return "⚠️ Execution Timeout: The code took too long to execute (>30 seconds). Please optimize your solution or try a smaller input." + + error_prompt = f"""The code execution resulted in an error: + Error: {execution.error} + + Please analyze the error and provide a clear explanation of what went wrong.""" + response = execution_agent.run(error_prompt) + return f"⚠️ Execution Error:\n{response.content}" + + # Get files list safely + try: + files = sandbox.files.list("/") + except: + files = [] + + prompt = f"""Here is the code execution result: + Logs: {execution.logs} + Files: {str(files)} + + Please provide a clear explanation of the results and any outputs.""" + + response = execution_agent.run(prompt) + return response.content + except Exception as e: + # Reinitialize sandbox on error + try: + initialize_sandbox() + except: + pass + return f"⚠️ Sandbox Error: {str(e)}" + +def main() -> None: + st.title("O3-Mini Coding Agent") + + # Add timeout info in sidebar + initialize_session_state() + setup_sidebar() + with st.sidebar: + st.info("⏱️ Code execution timeout: 30 seconds") + + # Check all required API keys + if not (st.session_state.openai_key and + st.session_state.gemini_key and + st.session_state.e2b_key): + st.warning("Please enter all required API keys in the sidebar.") + return + + vision_agent, coding_agent, execution_agent = create_agents() + + # Clean, single-column layout + uploaded_image = st.file_uploader( + "Upload an image of your coding problem (optional)", + type=['png', 'jpg', 'jpeg'] + ) + + if uploaded_image: + st.image(uploaded_image, caption="Uploaded Image", use_container_width=True) + + user_query = st.text_area( + "Or type your coding problem here:", + placeholder="Example: Write a function to find the sum of two numbers. Include sample input/output cases.", + height=100 + ) + + # Process button + if st.button("Generate & Execute Solution", type="primary"): + if uploaded_image and not user_query: + # Process image with Gemini + with st.spinner("Processing image..."): + try: + # Save uploaded file to temporary location + image = Image.open(uploaded_image) + extracted_query = process_image_with_gemini(vision_agent, image) + + if extracted_query.startswith("Failed to process"): + st.error(extracted_query) + return + + st.info("📝 Extracted Problem:") + st.write(extracted_query) + + # Pass extracted query to coding agent + with st.spinner("Generating solution..."): + response = coding_agent.run(extracted_query) + except Exception as e: + st.error(f"Error processing image: {str(e)}") + return + + elif user_query and not uploaded_image: + # Direct text input processing + with st.spinner("Generating solution..."): + response = coding_agent.run(user_query) + + elif user_query and uploaded_image: + st.error("Please use either image upload OR text input, not both.") + return + else: + st.warning("Please provide either an image or text description of your coding problem.") + return + + # Display and execute solution + if 'response' in locals(): + st.divider() + st.subheader("💻 Solution") + + # Extract code from markdown response + code_blocks = response.content.split("```python") + if len(code_blocks) > 1: + code = code_blocks[1].split("```")[0].strip() + + # Display the code + st.code(code, language="python") + + # Execute code with execution agent + with st.spinner("Executing code..."): + # Always initialize a fresh sandbox for each execution + initialize_sandbox() + + if st.session_state.sandbox: + execution_results = execute_code_with_agent( + execution_agent, + code, + st.session_state.sandbox + ) + + # Display execution results + st.divider() + st.subheader("🚀 Execution Results") + st.markdown(execution_results) + + # Try to display files if available + try: + files = st.session_state.sandbox.files.list("/") + if files: + st.markdown("📁 **Generated Files:**") + st.json(files) + except: + pass + +if __name__ == "__main__": + main() diff --git a/ai_agent_tutorials/ai_coding_agent_o3-mini/requirements.txt b/ai_agent_tutorials/ai_coding_agent_o3-mini/requirements.txt new file mode 100644 index 0000000..5b06e93 --- /dev/null +++ b/ai_agent_tutorials/ai_coding_agent_o3-mini/requirements.txt @@ -0,0 +1,4 @@ +streamlit +e2b-code-interpreter +agno +Pillow \ No newline at end of file