import os import re import gradio as gr from openai import OpenAI # Initialize the OpenAI client with the API key from environment variables. client = OpenAI(api_key=os.environ["OPENAI_API_KEY"]) # In-memory storage to track submitted emails (not persistent; resets on app restart). submitted_emails = set() def get_evaluation_questions(): """ Loads evaluation questions and expected answers from environment variables. Expected environment variable names are: TEST_QUESTION_1, TEST_EXPECTED_1, TEST_QUESTION_2, TEST_EXPECTED_2, and so on. """ questions = [] i = 1 while True: question = os.environ.get(f"TEST_QUESTION_{i}") expected = os.environ.get(f"TEST_EXPECTED_{i}") if not question or not expected: break questions.append({"question": question, "expected": expected}) i += 1 return questions # Load the evaluation questions once at startup. EVALUATION_QUESTIONS = get_evaluation_questions() def sanitize_input(text): """ Sanitizes input to prevent harmful content and limits its length. """ # Allow alphanumerics and some punctuation, then truncate to 500 characters. clean_text = re.sub(r"[^a-zA-Z0-9\s.,!?@:\-]", "", text) return clean_text.strip()[:500] def validate_email(email): """ Validates that the provided email is in a valid format. Returns True if valid, False otherwise. """ email_regex = r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$" return re.match(email_regex, email) is not None def submit_prompt(email, name, system_prompt): """ Handles user submission: - Validates email format. - Checks if the email has already been used for submission. - Evaluates the system prompt against predefined test questions. - Prevents multiple submissions from the same email. Returns the evaluation results or an error message if the submission is invalid. """ # Validate email format. if not validate_email(email): return "Invalid email address. Please enter a valid email." # Check if this email has already been used for submission. if email in submitted_emails: return f"Submission already received for {email}. You can only submit once." # Sanitize inputs. email = sanitize_input(email) name = sanitize_input(name) system_prompt = sanitize_input(system_prompt) score = 0 responses = [] for item in EVALUATION_QUESTIONS: question = item["question"] expected = item["expected"] try: # Use the new client-based API for chat completions. response = client.chat.completions.create( model="gpt-4o-mini", # Ensure this identifier matches the deployed model. messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": question} ] ) # Extract the answer from the response object. answer = response.choices[0].message.content.strip() except Exception as e: answer = f"Error during OpenAI API call: {str(e)}" # Simple evaluation: check if the answer contains the expected substring. if expected.lower() in answer.lower(): score += 1 verdict = "Correct" else: verdict = "Incorrect" responses.append( f"Question: {question}\n" f"Answer: {answer}\n" f"Expected: {expected}\n" f"Result: {verdict}\n" ) result_details = "\n".join(responses) # Record this email as having submitted their prompt. submitted_emails.add(email) return ( f"Thank you for your submission, {name}!\n\n" f"Your evaluation score is {score} out of {len(EVALUATION_QUESTIONS)}.\n\nDetails:\n{result_details}" ) def build_interface(): """ Constructs the Gradio interface with a submission button and single-submission mechanism. """ with gr.Blocks() as demo: gr.Markdown("# GPT-4o Mini Prompt Submission") gr.Markdown( "Please enter your details and submit your system prompt below. " "You can only submit once." ) email_input = gr.Textbox(label="Email", placeholder="your.email@example.com") name_input = gr.Textbox(label="Name", placeholder="Your name") system_prompt_input = gr.Textbox( label="System Prompt", placeholder="Enter your system prompt here...", lines=6, ) submit_button = gr.Button("Submit") output_text = gr.Textbox(label="Results", lines=15) submit_button.click( fn=submit_prompt, inputs=[email_input, name_input, system_prompt_input], outputs=output_text, ) return demo if __name__ == "__main__": interface = build_interface() # Launch the app on 0.0.0.0 so it is accessible externally (e.g., in a container). interface.launch(server_name="0.0.0.0", server_port=7860)