import gspread from google.oauth2.service_account import Credentials import json import os from datetime import datetime import streamlit as st class FeedbackManager: def __init__(self): self.client = None self.sheet = None self.worksheet = None self._initialize_google_sheets() def _initialize_google_sheets(self): """Initialize Google Sheets connection""" try: # Get credentials from environment variable or file creds_json = os.getenv("GOOGLE_SHEETS_CREDENTIALS") sheet_id = os.getenv("GOOGLE_SHEETS_ID") if not creds_json or not sheet_id: st.warning("⚠️ Google Sheets credentials not configured. Feedback will not be saved.") return # Parse credentials if creds_json.startswith('{'): # JSON string in environment variable creds_dict = json.loads(creds_json) else: # File path with open(creds_json, 'r') as f: creds_dict = json.load(f) # Define the scope scope = [ 'https://www.googleapis.com/auth/spreadsheets', 'https://www.googleapis.com/auth/drive' ] # Create credentials object credentials = Credentials.from_service_account_info(creds_dict, scopes=scope) # Initialize the client self.client = gspread.authorize(credentials) # Open the spreadsheet self.sheet = self.client.open_by_key(sheet_id) # Get or create the feedback worksheet try: self.worksheet = self.sheet.worksheet("Feedback") except gspread.WorksheetNotFound: # Create the worksheet with headers self.worksheet = self.sheet.add_worksheet(title="Feedback", rows="1000", cols="15") headers = [ "Timestamp", "User Query", "AI Response", "Source Rating (1-5)", "Answer Rating (1-5)", "Q1: Mistakes/Missing Info", "Q2: Correct Answer", "Q3: Thought Process", "Embedder Model", "LLM Model", "Temperature", "Top P", "Max Length" ] self.worksheet.append_row(headers) # Get or create the conversation log worksheet try: self.conversation_worksheet = self.sheet.worksheet("Conversations") except gspread.WorksheetNotFound: # Create the worksheet with headers self.conversation_worksheet = self.sheet.add_worksheet(title="Conversations", rows="1000", cols="10") headers = [ "Timestamp", "Session ID", "User Query", "AI Response", "Embedder Model", "LLM Model", "Temperature", "Top P", "Max Length", "Response Time (seconds)" ] self.conversation_worksheet.append_row(headers) except Exception as e: st.error(f"❌ Failed to initialize Google Sheets: {str(e)}") self.client = None self.conversation_worksheet = None def save_feedback(self, user_query, ai_response, source_rating, answer_rating, feedback_q1, embedder_model, llm_model, temperature, top_p, max_length): """Save feedback data to Google Sheets""" if not self.worksheet: st.error("❌ Google Sheets not initialized. Cannot save feedback.") return False try: timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") # Truncate long responses to fit in Google Sheets cells ai_response_truncated = ai_response[:1000] + "..." if len(ai_response) > 1000 else ai_response feedback_q1_truncated = feedback_q1[:500] + "..." if len(feedback_q1) > 500 else feedback_q1 row = [ timestamp, user_query, ai_response_truncated, source_rating if source_rating is not None else "", answer_rating if answer_rating is not None else "", feedback_q1_truncated, embedder_model, llm_model, temperature, top_p, max_length ] self.worksheet.append_row(row) return True except Exception as e: st.error(f"❌ Failed to save feedback: {str(e)}") return False def is_connected(self): """Check if Google Sheets connection is available""" return self.client is not None and self.worksheet is not None def log_conversation(self, session_id, user_query, ai_response, embedder_model, llm_model, temperature, top_p, max_length, response_time): """Log conversation data to Google Sheets""" if not hasattr(self, 'conversation_worksheet') or not self.conversation_worksheet: print("⚠️ Google Sheets conversation logging not initialized. Skipping log.") return False try: timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") # Truncate long responses to fit in Google Sheets cells user_query_truncated = user_query[:500] + "..." if len(user_query) > 500 else user_query ai_response_truncated = ai_response[:1000] + "..." if len(ai_response) > 1000 else ai_response row = [ timestamp, session_id, user_query_truncated, ai_response_truncated, embedder_model, llm_model, temperature, top_p, max_length, round(response_time, 2) ] self.conversation_worksheet.append_row(row) return True except Exception as e: print(f"❌ Failed to log conversation: {str(e)}") return False