Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -2,6 +2,9 @@ import streamlit as st
|
|
2 |
import pandas as pd
|
3 |
import numpy as np
|
4 |
import random
|
|
|
|
|
|
|
5 |
|
6 |
class RoFTGame:
|
7 |
def __init__(self, dataset_path):
|
@@ -15,13 +18,29 @@ class RoFTGame:
|
|
15 |
self.current_sentences = None
|
16 |
self.true_boundary_index = None
|
17 |
self.current_guess_index = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
|
19 |
def load_random_sample(self):
|
20 |
"""
|
21 |
Load a random sample from the dataset
|
22 |
"""
|
23 |
-
# Filter for samples with valid generations
|
24 |
-
valid_samples = self.df[
|
|
|
|
|
|
|
|
|
25 |
|
26 |
# Select a random sample
|
27 |
self.current_sample = valid_samples.sample(n=1).iloc[0]
|
@@ -37,6 +56,12 @@ class RoFTGame:
|
|
37 |
# Store true boundary
|
38 |
self.true_boundary_index = self.current_sample['true_boundary_index']
|
39 |
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
# Reset current guess
|
41 |
self.current_guess_index = None
|
42 |
|
@@ -57,6 +82,64 @@ class RoFTGame:
|
|
57 |
else:
|
58 |
return 0
|
59 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
def main():
|
61 |
st.title("Real or Fake Text (RoFT) Game")
|
62 |
|
@@ -80,29 +163,60 @@ def main():
|
|
80 |
# Boundary selection
|
81 |
guess = st.radio(
|
82 |
"Where do you think the AI-generated text begins?",
|
83 |
-
options=[
|
84 |
)
|
85 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
# Guess submission
|
87 |
if st.button("Submit Guess"):
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
|
107 |
# Optional: Show metadata for current sample
|
108 |
if st.checkbox("Show Sample Metadata"):
|
@@ -111,6 +225,7 @@ def main():
|
|
111 |
st.write(f"Model: {sample['model']}")
|
112 |
st.write(f"Dataset: {sample['dataset']}")
|
113 |
st.write(f"Sampling Strategy (p): {sample['dec_strat_value']}")
|
|
|
114 |
|
115 |
if __name__ == "__main__":
|
116 |
main()
|
|
|
2 |
import pandas as pd
|
3 |
import numpy as np
|
4 |
import random
|
5 |
+
import os
|
6 |
+
from datetime import datetime
|
7 |
+
import ast
|
8 |
|
9 |
class RoFTGame:
|
10 |
def __init__(self, dataset_path):
|
|
|
18 |
self.current_sentences = None
|
19 |
self.true_boundary_index = None
|
20 |
self.current_guess_index = None
|
21 |
+
|
22 |
+
# Predefined reasons from the dataset description
|
23 |
+
self.predefined_reasons = [
|
24 |
+
"grammar",
|
25 |
+
"repetition",
|
26 |
+
"irrelevant",
|
27 |
+
"contradicts_sentence",
|
28 |
+
"contradicts_knowledge",
|
29 |
+
"common_sense",
|
30 |
+
"coreference",
|
31 |
+
"generic"
|
32 |
+
]
|
33 |
|
34 |
def load_random_sample(self):
|
35 |
"""
|
36 |
Load a random sample from the dataset
|
37 |
"""
|
38 |
+
# Filter for samples with valid generations and reasons
|
39 |
+
valid_samples = self.df[
|
40 |
+
(self.df['gen_body'].notna()) &
|
41 |
+
(self.df['reason'].notna()) &
|
42 |
+
(self.df['reason'] != '[]')
|
43 |
+
]
|
44 |
|
45 |
# Select a random sample
|
46 |
self.current_sample = valid_samples.sample(n=1).iloc[0]
|
|
|
56 |
# Store true boundary
|
57 |
self.true_boundary_index = self.current_sample['true_boundary_index']
|
58 |
|
59 |
+
# Parse reasons from the dataset
|
60 |
+
try:
|
61 |
+
self.current_reasons = ast.literal_eval(self.current_sample['reason'])
|
62 |
+
except:
|
63 |
+
self.current_reasons = []
|
64 |
+
|
65 |
# Reset current guess
|
66 |
self.current_guess_index = None
|
67 |
|
|
|
82 |
else:
|
83 |
return 0
|
84 |
|
85 |
+
def validate_reason(self, user_reason):
|
86 |
+
"""
|
87 |
+
Validate user's reason against dataset reasons
|
88 |
+
|
89 |
+
:param user_reason: Reason provided by user
|
90 |
+
:return: Tuple of (is_valid, matching_reasons)
|
91 |
+
"""
|
92 |
+
# Convert user reason to lowercase for matching
|
93 |
+
user_reason_lower = user_reason.lower()
|
94 |
+
|
95 |
+
# Check against predefined reasons and current sample's reasons
|
96 |
+
matching_reasons = []
|
97 |
+
|
98 |
+
# Check predefined reasons
|
99 |
+
for reason in self.predefined_reasons:
|
100 |
+
if reason.lower() in user_reason_lower:
|
101 |
+
matching_reasons.append(reason)
|
102 |
+
|
103 |
+
# Check original sample's reasons
|
104 |
+
for orig_reason in self.current_reasons:
|
105 |
+
if orig_reason.lower() in user_reason_lower:
|
106 |
+
matching_reasons.append(orig_reason)
|
107 |
+
|
108 |
+
return len(matching_reasons) > 0, matching_reasons
|
109 |
+
|
110 |
+
def save_annotation(self, guess_index, reason, reason_validity):
|
111 |
+
"""
|
112 |
+
Save annotation to a text file
|
113 |
+
|
114 |
+
:param guess_index: Index of the guessed boundary
|
115 |
+
:param reason: Reason for the guess
|
116 |
+
:param reason_validity: Validity of the reason
|
117 |
+
"""
|
118 |
+
# Ensure logs directory exists
|
119 |
+
os.makedirs('logs', exist_ok=True)
|
120 |
+
|
121 |
+
# Generate unique filename with timestamp
|
122 |
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
123 |
+
filename = f'logs/annotation_{timestamp}.txt'
|
124 |
+
|
125 |
+
# Prepare annotation details
|
126 |
+
annotation_details = [
|
127 |
+
f"Timestamp: {timestamp}",
|
128 |
+
f"Model: {self.current_sample['model']}",
|
129 |
+
f"Dataset: {self.current_sample['dataset']}",
|
130 |
+
f"Guess Index: {guess_index + 1}",
|
131 |
+
f"True Boundary Index: {self.true_boundary_index + 1}",
|
132 |
+
f"Original Dataset Reasons: {self.current_reasons}",
|
133 |
+
f"User Reason: {reason}",
|
134 |
+
f"Reason Validity: {reason_validity[0]}",
|
135 |
+
f"Matching Reasons: {reason_validity[1]}",
|
136 |
+
"\nFull Text:\n" + "\n".join(f"{i+1}. {sent}" for i, sent in enumerate(self.current_sentences))
|
137 |
+
]
|
138 |
+
|
139 |
+
# Write to file
|
140 |
+
with open(filename, 'w') as f:
|
141 |
+
f.write("\n".join(annotation_details))
|
142 |
+
|
143 |
def main():
|
144 |
st.title("Real or Fake Text (RoFT) Game")
|
145 |
|
|
|
163 |
# Boundary selection
|
164 |
guess = st.radio(
|
165 |
"Where do you think the AI-generated text begins?",
|
166 |
+
options=[str(i+1) for i in range(len(st.session_state.game.current_sentences))]
|
167 |
)
|
168 |
|
169 |
+
# Reason input with predefined options
|
170 |
+
st.subheader("Reason Selection")
|
171 |
+
reason_options = st.session_state.game.predefined_reasons
|
172 |
+
selected_predefined_reasons = st.multiselect(
|
173 |
+
"Select predefined reasons (you can also add custom text)",
|
174 |
+
options=reason_options
|
175 |
+
)
|
176 |
+
|
177 |
+
# Custom reason input
|
178 |
+
custom_reason = st.text_area("Additional explanation (optional)")
|
179 |
+
|
180 |
+
# Combine predefined and custom reasons
|
181 |
+
full_reason = " ".join(selected_predefined_reasons)
|
182 |
+
if custom_reason:
|
183 |
+
full_reason += f" {custom_reason}"
|
184 |
+
|
185 |
# Guess submission
|
186 |
if st.button("Submit Guess"):
|
187 |
+
if not full_reason.strip():
|
188 |
+
st.warning("Please provide a reason for your guess.")
|
189 |
+
else:
|
190 |
+
# Convert guess to index (subtract 1 for 0-based indexing)
|
191 |
+
guess_index = int(guess) - 1
|
192 |
+
|
193 |
+
# Check guess and update points
|
194 |
+
points_earned = st.session_state.game.check_guess(guess_index)
|
195 |
+
st.session_state.total_points += points_earned
|
196 |
+
st.session_state.rounds_played += 1
|
197 |
+
|
198 |
+
# Validate reason
|
199 |
+
reason_validity = st.session_state.game.validate_reason(full_reason)
|
200 |
+
|
201 |
+
# Save annotation
|
202 |
+
st.session_state.game.save_annotation(guess_index, full_reason, reason_validity)
|
203 |
+
|
204 |
+
# Show results
|
205 |
+
st.subheader("Results")
|
206 |
+
st.write(f"Your Guess: Sentence {guess}")
|
207 |
+
st.write(f"Actual Boundary: Sentence {st.session_state.game.true_boundary_index + 1}")
|
208 |
+
st.write(f"Points Earned: {points_earned}")
|
209 |
+
|
210 |
+
# Display reason validation
|
211 |
+
st.write("Reason Validation:")
|
212 |
+
st.write(f"Valid Reason: {reason_validity[0]}")
|
213 |
+
if reason_validity[1]:
|
214 |
+
st.write("Matching Reasons:", ", ".join(reason_validity[1]))
|
215 |
+
|
216 |
+
# Option to continue
|
217 |
+
if st.button("Next Round"):
|
218 |
+
st.session_state.game.load_random_sample()
|
219 |
+
st.experimental_rerun()
|
220 |
|
221 |
# Optional: Show metadata for current sample
|
222 |
if st.checkbox("Show Sample Metadata"):
|
|
|
225 |
st.write(f"Model: {sample['model']}")
|
226 |
st.write(f"Dataset: {sample['dataset']}")
|
227 |
st.write(f"Sampling Strategy (p): {sample['dec_strat_value']}")
|
228 |
+
st.write(f"Original Reasons: {st.session_state.game.current_reasons}")
|
229 |
|
230 |
if __name__ == "__main__":
|
231 |
main()
|