import os import gradio as gr from dotenv import load_dotenv from openai import OpenAI from prompts.initial_prompt import INITIAL_PROMPT from prompts.main_prompt import MAIN_PROMPT, PROBLEM_SOLUTIONS_PROMPT # Ensure both are imported # Load the API key from the .env file if available if os.path.exists(".env"): load_dotenv(".env") OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") client = OpenAI(api_key=OPENAI_API_KEY) def gpt_call(history, user_message, model="gpt-4o", max_tokens=3000, # Increased to 3000 to prevent truncation temperature=0.7, top_p=0.95): """ Calls the OpenAI API to generate a response. - history: [(user_text, assistant_text), ...] - user_message: The latest user message """ # 1) Start with the system message (MAIN_PROMPT) for context messages = [{"role": "system", "content": MAIN_PROMPT}] # 2) Append conversation history for user_text, assistant_text in history: if user_text: messages.append({"role": "user", "content": user_text}) if assistant_text: messages.append({"role": "assistant", "content": assistant_text}) # 3) Add the user's new message messages.append({"role": "user", "content": user_message}) # 4) Call OpenAI API (with continuation handling) full_response = "" while True: completion = client.chat.completions.create( model=model, messages=messages, max_tokens=max_tokens, # Increased to allow longer responses temperature=temperature, top_p=top_p ) response_part = completion.choices[0].message.content.strip() full_response += " " + response_part # If the response looks incomplete, force the AI to continue if len(response_part) < max_tokens - 50: # Ensures near full completion break # Stop loop if response is complete # Add last response back into conversation history to continue it messages.append({"role": "assistant", "content": response_part}) return full_response.strip() def respond(user_message, history): """ Handles user input and gets GPT-generated response. - user_message: The message from the user - history: List of (user, assistant) conversation history """ if not user_message: return "", history # If the user asks for a solution, inject PROBLEM_SOLUTIONS_PROMPT if "solution" in user_message.lower(): assistant_reply = gpt_call(history, PROBLEM_SOLUTIONS_PROMPT) else: assistant_reply = gpt_call(history, user_message) # Add conversation turn to history history.append((user_message, assistant_reply)) return "", history ############################## # Gradio Blocks UI ############################## with gr.Blocks() as demo: gr.Markdown("## AI-Guided Math PD Chatbot") # Chatbot initialization with the first AI message chatbot = gr.Chatbot( value=[("", INITIAL_PROMPT)], # Initial system prompt height=500 ) # Stores the chat history state_history = gr.State([("", INITIAL_PROMPT)]) # User input field user_input = gr.Textbox( placeholder="Type your message here...", label="Your Input" ) # Submit action user_input.submit( respond, inputs=[user_input, state_history], outputs=[user_input, chatbot] ).then( fn=lambda _, h: h, inputs=[user_input, chatbot], outputs=[state_history] ) # Run the Gradio app if __name__ == "__main__": demo.launch(server_name="0.0.0.0", server_port=7860, share=True)