ehtyalee commited on
Commit
35d1965
·
verified ·
1 Parent(s): bc39d1a

Upload 3 files

Browse files
Files changed (3) hide show
  1. app.py +151 -0
  2. requirements.txt +4 -0
  3. saved_model/combined_analyzer.pkl +3 -0
app.py ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # test_preloaded_model.py
2
+ import gradio as gr
3
+ import pickle
4
+ import os
5
+
6
+ # --- Dependencies needed for the Class Definition ---
7
+ from transformers import pipeline
8
+ import torch
9
+
10
+ # --- Define the Class to Hold Both Pipelines ---
11
+ # IMPORTANT: This exact class definition MUST be present here,
12
+ # identical to the one in save_combined_model.py, for unpickling to work.
13
+ class CombinedAnalyzer:
14
+ """
15
+ A class to encapsulate sentiment analysis and AI text detection pipelines.
16
+ NOTE: This definition must match the one used when saving the .pkl file.
17
+ """
18
+ def __init__(self, sentiment_model_name="distilbert-base-uncased-finetuned-sst-2-english",
19
+ detector_model_name="Hello-SimpleAI/chatgpt-detector-roberta"):
20
+ print("Initializing CombinedAnalyzer structure...")
21
+ self.device = 0 if torch.cuda.is_available() else -1
22
+ self.sentiment_model_name = sentiment_model_name
23
+ self.detector_model_name = detector_model_name
24
+ self.sentiment_pipeline = None
25
+ self.detector_pipeline = None
26
+ print(f"Class structure defined. Expecting pipelines for models: {sentiment_model_name}, {detector_model_name}")
27
+
28
+ def analyze(self, text):
29
+ """
30
+ Analyzes the input text for both sentiment and authenticity.
31
+ """
32
+ if not isinstance(text, str) or not text.strip():
33
+ return "Error: Input text cannot be empty."
34
+ results = []
35
+ # 1. Sentiment Analysis
36
+ if self.sentiment_pipeline and callable(self.sentiment_pipeline):
37
+ try:
38
+ sentiment_result = self.sentiment_pipeline(text)[0]
39
+ sentiment_label = sentiment_result['label']
40
+ sentiment_score = round(sentiment_result['score'] * 100, 2)
41
+ results.append(f"Sentiment: {sentiment_label} (Confidence: {sentiment_score}%)")
42
+ except Exception as e:
43
+ results.append(f"Sentiment Analysis Error in loaded model: {e}")
44
+ else:
45
+ results.append("Sentiment Analysis: Model not available or not callable in loaded object.")
46
+ # 2. AI Text Detection (Authenticity)
47
+ if self.detector_pipeline and callable(self.detector_pipeline):
48
+ try:
49
+ detector_result = self.detector_pipeline(text)[0]
50
+ auth_label_raw = detector_result['label']
51
+ auth_score = round(detector_result['score'] * 100, 2)
52
+ if auth_label_raw.lower() in ['chatgpt', 'ai', 'generated']:
53
+ auth_label_display = "Likely AI-Generated"
54
+ elif auth_label_raw.lower() in ['human', 'real']:
55
+ auth_label_display = "Likely Human-Written"
56
+ else:
57
+ auth_label_display = f"Label: {auth_label_raw}"
58
+ results.append(f"Authenticity: {auth_label_display} (Confidence: {auth_score}%)")
59
+ except Exception as e:
60
+ results.append(f"AI Text Detection Error in loaded model: {e}")
61
+ else:
62
+ results.append("Authenticity: AI Text Detector model not available or not callable in loaded object.")
63
+ return "\n".join(results)
64
+
65
+ # --- Load the Model Automatically on Startup ---
66
+ analyzer = None
67
+ pickle_filename = "combined_analyzer.pkl"
68
+ model_dir = "saved_model"
69
+ pickle_filepath = os.path.join(model_dir, pickle_filename)
70
+ model_load_error = None # Store potential loading error message
71
+
72
+ print(f"Attempting to load pre-saved model from: {pickle_filepath}")
73
+ try:
74
+ print("\n--- SECURITY WARNING ---")
75
+ print(f"Loading '{pickle_filepath}'. Unpickling data from untrusted sources is a security risk.")
76
+ print("Ensure this .pkl file was created by you or a trusted source.\n")
77
+
78
+ if not os.path.exists(pickle_filepath):
79
+ raise FileNotFoundError(f"Model file not found at {pickle_filepath}")
80
+ with open(pickle_filepath, 'rb') as f:
81
+ analyzer = pickle.load(f)
82
+ if not hasattr(analyzer, 'analyze') or not callable(analyzer.analyze):
83
+ raise TypeError("Loaded object is not a valid analyzer (missing 'analyze' method).")
84
+ else:
85
+ print("Model loaded successfully.")
86
+ sentiment_name = getattr(analyzer, 'sentiment_model_name', 'Unknown')
87
+ detector_name = getattr(analyzer, 'detector_model_name', 'Unknown')
88
+ print(f" -> Sentiment Model: {sentiment_name}")
89
+ print(f" -> Detector Model: {detector_name}")
90
+
91
+ except FileNotFoundError as e:
92
+ model_load_error = f"ERROR loading model: {e}"
93
+ print(model_load_error)
94
+ print("Please ensure 'save_combined_model.py' was run successfully and")
95
+ print(f"the file '{pickle_filename}' exists in the '{model_dir}' directory.")
96
+ except (pickle.UnpicklingError, TypeError, AttributeError) as e:
97
+ model_load_error = f"ERROR loading model: The pickle file might be corrupted, incompatible, or from a different version. Details: {e}"
98
+ print(model_load_error)
99
+ except Exception as e:
100
+ model_load_error = f"An unexpected ERROR occurred during model loading: {e}"
101
+ print(model_load_error)
102
+
103
+ # --- Define the Gradio Analysis Function ---
104
+ def analyze_text_interface(text_input):
105
+ """Function called by Gradio to perform analysis using the pre-loaded model."""
106
+ if analyzer is None:
107
+ # Use the stored error message if available
108
+ error_msg = model_load_error or f"ERROR: The analyzer model could not be loaded from '{pickle_filepath}'."
109
+ return error_msg
110
+ if not text_input or not text_input.strip():
111
+ return "Please enter some text to analyze."
112
+ print(f"Analyzing text: '{text_input[:60]}...'")
113
+ try:
114
+ results = analyzer.analyze(text_input)
115
+ print("Analysis complete.")
116
+ return results
117
+ except Exception as e:
118
+ print(f"Error during analysis: {e}")
119
+ return f"An error occurred during analysis:\n{e}"
120
+
121
+ # --- Build the Gradio Interface ---
122
+
123
+ # **CORRECTION HERE:** Define the warning message string separately
124
+ warning_message_text = ""
125
+ if analyzer is None:
126
+ # Use newline characters safely outside the f-string expression
127
+ warning_message_text = "\n\n***WARNING: MODEL FAILED TO LOAD. ANALYSIS WILL NOT WORK.***"
128
+
129
+ # Construct the full description string
130
+ description_text = (
131
+ f"Enter text to analyze using the pre-loaded model from '{pickle_filepath}'.\n"
132
+ "Checks for sentiment (Positive/Negative) and predicts if text is Human-Written or AI-Generated."
133
+ f"{warning_message_text}" # Use the variable here
134
+ )
135
+
136
+ interface = gr.Interface(
137
+ fn=analyze_text_interface,
138
+ inputs=gr.Textbox(lines=7, label="Text to Analyze", placeholder="Enter review text here..."),
139
+ outputs=gr.Textbox(lines=7, label="Analysis Results", interactive=False),
140
+ title="Sentiment & Authenticity Analyzer",
141
+ description=description_text, # Use the constructed description string
142
+ allow_flagging='never'
143
+ )
144
+
145
+ # --- Launch the Interface ---
146
+ if __name__ == "__main__":
147
+ if analyzer is None:
148
+ print("\n--- Interface launched, but MODEL IS NOT LOADED. Analysis will fail. ---")
149
+ else:
150
+ print("\n--- Launching Gradio Interface with pre-loaded model ---")
151
+ interface.launch()
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ transformers
2
+ torch
3
+ gradio
4
+ sentencepiece
saved_model/combined_analyzer.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8e4dd11e04e895a5d1847965f97a25ad79fde1624a1ffe8d5d45c25b07afaaaa
3
+ size 768588802