import os from openai import OpenAI from datetime import datetime import gradio as gr import time import openai # Redundant import # --- Constants --- # Default model might need to align with what client.responses.create supports DEFAULT_MODEL = "gpt-4.1" # As per your example MAX_HISTORY_LENGTH = 5 # History formatting will be manual and limited # --- API Key and Client Initialization --- API_KEY = os.getenv("OPENAI_API_KEY") if not API_KEY: print("Error: OPENAI_API_KEY environment variable not set.") # Handle missing key appropriately (e.g., disable UI, raise error) client = OpenAI(api_key=API_KEY) # --- Helper Functions --- # !!! WARNING: This function is adapted to the requested format and LOSES features !!! def get_openai_response_simplified(prompt, model=DEFAULT_MODEL, system_prompt="", chat_history=None): """ Gets a response using the client.responses.create format. NOTE: This is NON-STREAMING and handles history/system prompt crudely. Advanced parameters (temp, top_p etc.) are NOT supported by this structure. """ today_day = datetime.now().strftime("%Y-%m-%d %H:%M:%S") # --- Attempt to manually format history and system prompt into 'input' --- formatted_input = "" # Add system prompt if provided effective_system_prompt = f"Today's date is: {today_day}. {system_prompt}".strip() if effective_system_prompt: # How best to include system prompt? Prepend? Specific tags? Unknown. formatted_input += f"System: {effective_system_prompt}\n\n" # Add chat history (simple concatenation) if chat_history: for turn in chat_history: if len(turn) == 2 and turn[0] is not None and turn[1] is not None: formatted_input += f"User: {turn[0]}\nAssistant: {turn[1]}\n" # Add the current user prompt formatted_input += f"User: {prompt}\nAssistant:" # Prompt the model for the next turn try: # *** Using the requested client.responses.create format *** # NOTE: This assumes client.responses.create actually exists and works this way. # NOTE: Parameters like temperature, top_p, max_tokens are NOT included here # as they are not part of the provided example format. response = client.responses.create( model=model, input=formatted_input ) # Assuming the response object has an 'output_text' attribute return response.output_text # Error handling might need adjustment based on how client.responses.create fails except openai.APIConnectionError as e: print(f"OpenAI API request failed: {e}") return f"Error: Could not connect to OpenAI API. {e}" except openai.RateLimitError as e: print(f"OpenAI API request failed: {e}") return f"Error: Rate limit exceeded. Please try again later. {e}" except openai.AuthenticationError as e: print(f"OpenAI API request failed: {e}") return f"Error: Authentication failed. Check your API key. {e}" except openai.APIStatusError as e: print(f"OpenAI API request failed: {e}") return f"Error: OpenAI API returned an error (Status: {e.status_code}). {e}" except AttributeError as e: print(f"Error accessing response or client method: {e}") return f"Error: The API call structure 'client.responses.create' or its response format might be incorrect or not available. {e}" except Exception as e: print(f"An unexpected error occurred: {e}") return f"An unexpected error occurred: {e}" # !!! WARNING: This update function is now NON-STREAMING !!! def update_ui_simplified(message, chat_history, model, system_prompt, history_length): """Updates the Gradio UI WITHOUT streaming.""" if not message: return "", chat_history # Return original history if message is empty # Keep only the specified length of history for the *next* call history_for_api = chat_history[-int(history_length):] if history_length > 0 else [] # Call the simplified, non-streaming function bot_response = get_openai_response_simplified( prompt=message, model=model, system_prompt=system_prompt, chat_history=history_for_api # Pass the potentially trimmed history ) # Append the user message and the *complete* bot response chat_history.append((message, bot_response)) # Update UI only once with the full response # Always display history based on the slider length for visibility visible_history = chat_history[-int(history_length):] if history_length > 0 else [] return "", visible_history # Clear input, return updated history # --- Gradio Interface (Modified for Simplified API Call) --- with gr.Blocks(theme=gr.themes.Soft()) as demo: # Keep your Markdown, titles, etc. gr.Markdown("# Chat (Simplified API Demo)") gr.Markdown("---") gr.Markdown("Using a simplified, non-streaming API call structure.") gr.Markdown("---") # ... (rest of your Markdown) ... gr.Markdown("Chat below (Note: Responses will appear all at once): 👇") with gr.Row(): with gr.Column(scale=4): chatbot = gr.Chatbot( label="Chat Window", show_label=False, avatar_images=( "https://cdn-icons-png.flaticon.com/512/1077/1077114.png", # User "https://cdn-icons-png.flaticon.com/512/8649/8649540.png" # AI ), render_markdown=True, height=500, bubble_full_width=False ) msg = gr.Textbox( label="Your Message", placeholder="Type your message here and press Enter...", scale=4, show_label=False, container=False ) # Accordion remains, but parameters might not be used by the simplified API call with gr.Accordion("Advanced Options (May Not Apply to Simplified API)", open=False): model_select = gr.Dropdown( label="Model", # Ensure gpt-4.1 is a valid choice if used choices=["gpt-4.1", "gpt-4o-mini-2024-07-18", "gpt-3.5-turbo-0125", "gpt-4o"], value=DEFAULT_MODEL, interactive=True ) # These sliders are kept for UI, but won't be passed to the simplified API call temperature_slider = gr.Slider(label="Temperature (Not Used)", minimum=0.0, maximum=2.0, value=1.0, step=0.1, interactive=True) top_p_slider = gr.Slider(label="Top P (Not Used)", minimum=0.0, maximum=1.0, value=1.0, step=0.05, interactive=True) frequency_penalty_slider = gr.Slider(label="Frequency Penalty (Not Used)", minimum=-2.0, maximum=2.0, value=0.0, step=0.1, interactive=True) presence_penalty_slider = gr.Slider(label="Presence Penalty (Not Used)", minimum=-2.0, maximum=2.0, value=0.0, step=0.1, interactive=True) system_prompt_textbox = gr.Textbox(label="System Prompt", placeholder="e.g., You are a helpful assistant.", lines=3, interactive=True) history_length_slider = gr.Slider(label="Chat History Length (Affects Input & Display)", minimum=1, maximum=20, value=MAX_HISTORY_LENGTH, step=1, interactive=True) with gr.Row(): clear = gr.Button("Clear Chat") send = gr.Button("Send Message", variant="primary") # --- Event Handlers (Using Simplified Functions) --- # Define inputs, excluding sliders not used by the simplified function inputs_simplified = [ msg, chatbot, model_select, system_prompt_textbox, history_length_slider ] outputs = [msg, chatbot] # Outputs remain the same # Connect send button click send.click( update_ui_simplified, # Use the non-streaming UI update function inputs=inputs_simplified, outputs=outputs, queue=True ) # Connect textbox submit (Enter key) msg.submit( update_ui_simplified, # Use the non-streaming UI update function inputs=inputs_simplified, outputs=outputs, queue=True ) # Connect clear button clear.click(lambda: (None, []), None, outputs=[msg, chatbot], queue=False) gr.Examples( examples=["Tell me about the latest AI developments", "Write a short story about a friendly robot", "Explain black holes simply"], inputs=msg, label="Example Prompts" ) # --- Launch --- if __name__ == "__main__": demo.queue() demo.launch()