Linaya commited on
Commit
fb2fd45
·
verified ·
1 Parent(s): 7511076

FINAL FINAL UPDATES TO app.py

Browse files
Files changed (1) hide show
  1. app.py +19 -19
app.py CHANGED
@@ -22,7 +22,7 @@ from transformers import AutoTokenizer, AutoModelForSequenceClassification
22
  from peft import PeftModel
23
  import shap
24
 
25
- #nltk bits used by vader, tf-idf cleaning and the sentence splitter (same as my notebooks)
26
  for pkg in ["stopwords", "vader_lexicon", "punkt", "punkt_tab"]:
27
  nltk.download(pkg, quiet=True)
28
 
@@ -49,19 +49,19 @@ VADER_COMPOUND, VADER_NEG = -0.30, 0.02
49
  NO_GATE = {"OUTSIDE_COMMS"} #outside comms fires on the keyword alone
50
  sia = SentimentIntensityAnalyzer()
51
 
52
- #2. tf-idf + logistic regression (one model per category, saved from my layer 6 notebook)
53
  vec = joblib.load(os.path.join(HERE, "tfidf_vectorizer.pkl"))
54
  tf_models = joblib.load(os.path.join(HERE, "tfidf_logistic_models.pkl"))
55
  STOP = set(stopwords.words("english"))
56
  stemmer = SnowballStemmer("english")
57
 
58
- #3. bert-base-uncased + my lora adapter (the adapter files sit next to this app.py)
59
 
60
  BERT_THRESHOLDS = {"WORKLOAD": 0.65, "TEAM": 0.90, "ADJUSTMENT": 0.85, "OUTSIDE_COMMS": 0.90}
61
  tok = AutoTokenizer.from_pretrained(HERE)
62
  base = AutoModelForSequenceClassification.from_pretrained(
63
  "bert-base-uncased", num_labels=4, problem_type="multi_label_classification")
64
- bert = PeftModel.from_pretrained(base, HERE, torch_device="cpu").eval()
65
 
66
 
67
  def vader_flags(seg):
@@ -156,14 +156,14 @@ def diarise(text):
156
  return "\n\n".join(kept), "fallback", [s for s in speakers if s != astro], speakers, len(kept), len(turns)
157
 
158
 
159
- #segmentation: whole sentences packed up to 300 words and nothing under 20 words
160
  MIN_WORDS, MAX_WORDS = 20, 300
161
 
162
 
163
  def segment(text):
164
  blocks = [b.strip() for b in text.split("\n\n") if b.strip()]
165
  paras = blocks[:1]
166
- for b in blocks[1:]:
167
  if paras[-1][-1] in ".!?\"\u201d" and b[0].isupper():
168
  paras.append(b)
169
  else:
@@ -176,7 +176,7 @@ def segment(text):
176
  chunks.append(p)
177
  continue
178
  sents = []
179
- for s in sent_tokenize(p):
180
  if sents and s[:1].islower():
181
  sents[-1] += " " + s
182
  else:
@@ -226,7 +226,7 @@ def analyse(file, text):
226
  elif method == "fallback":
227
  s3 = f"PASSED (fallback): no 'Interviewed by' line, kept the longest speaker. Removed: {', '.join(removed)}."
228
  else:
229
- s3 = "NO SPEAKER TAGS FOUND so the whole text is treated as the astronaut's words."
230
  if method != "no_tags" and not narrative.strip():
231
  #known failure from my report: a curly apostrophe or accent in the astronaut's tag (O’CONNOR) isn't matched
232
  s3 = (f"FAILED: interviewer found ({', '.join(removed)}) but nothing was left after removing them, "
@@ -234,7 +234,7 @@ def analyse(file, text):
234
  s3 += f" Words left: {len(narrative.split()):,}."
235
  if method == "no_tags":
236
  #no cover page and no NAME: tags --> probably not an oral history, the models still run but read with care
237
- s3 += " Note: this does not look like a NASA oral history transcript !! so the scores below are less meaningful."
238
 
239
  #step 4
240
  segs = segment(narrative)
@@ -321,7 +321,7 @@ def find_files(pairs):
321
  # the page
322
 
323
  CSS = """
324
- .gradio-container {background: radial-gradient(ellipse at top, #141b33 0%, #05070f 70%) !important;}
325
  * {box-shadow: none !important;}
326
  .seg {border: 1px solid #ffffff44; border-radius: 12px; padding: 8px 12px; margin: 6px 0; color: #e6ebff;}
327
  table {width: 100%; border-collapse: collapse; color: #e6ebff;}
@@ -333,7 +333,7 @@ with gr.Blocks(title="SPACEMIND") as demo:
333
  gr.Markdown("# SPACEMIND")
334
 
335
  with gr.Row():
336
- #left side: inputs
337
  with gr.Column():
338
  textInput = gr.Textbox(label="Paste a transcript or a passage", lines=10)
339
  fileInput = gr.File(label="...or upload a .txt / .pdf transcript", file_types=[".txt", ".pdf"])
@@ -345,13 +345,13 @@ with gr.Blocks(title="SPACEMIND") as demo:
345
  heldOut = find_files(TEST_SET)
346
  if heldOut:
347
  gr.Examples([[p] for p, _ in heldOut], inputs=fileInput, example_labels=[l for _, l in heldOut],
348
- label="Load a transcript from my test set")
349
  tests = find_files(PIPELINE_TESTS)
350
  if tests:
351
  gr.Examples([[p] for p, _ in tests], inputs=fileInput, example_labels=[l for _, l in tests],
352
- label="Pipeline tests")
353
 
354
- #right side: the stages
355
  with gr.Column():
356
  out1 = gr.Textbox(label="1. Input (word count)")
357
  out2 = gr.Textbox(label="2. Cleaning")
@@ -372,9 +372,9 @@ with gr.Blocks(title="SPACEMIND") as demo:
372
  shapButton.click(explain, [state, segPick, catPick], shapOut)
373
 
374
 
375
- BURGUNDY = gr.themes.Color(c50="#fdf2f4", c100="#fbe5e9", c200="#f5c6d0", c300="#ec9aab", c400="#d9637c",
376
- c500="#9b2743", c600="#801f38", c700="#661a2e", c800="#4f1524", c900="#3d1019",
377
- c950="#2e0a14", name="burgundy")
378
 
379
- demo.launch(theme=gr.themes.Base(primary_hue=BURGUNDY, neutral_hue="slate"), css=CSS,
380
- js="() => document.body.classList.add('dark')")
 
22
  from peft import PeftModel
23
  import shap
24
 
25
+ #nltk bits used by vader, tf-idf cleaning and the sentence splitter
26
  for pkg in ["stopwords", "vader_lexicon", "punkt", "punkt_tab"]:
27
  nltk.download(pkg, quiet=True)
28
 
 
49
  NO_GATE = {"OUTSIDE_COMMS"} #outside comms fires on the keyword alone
50
  sia = SentimentIntensityAnalyzer()
51
 
52
+ #2. tf-idf + logistic regression
53
  vec = joblib.load(os.path.join(HERE, "tfidf_vectorizer.pkl"))
54
  tf_models = joblib.load(os.path.join(HERE, "tfidf_logistic_models.pkl"))
55
  STOP = set(stopwords.words("english"))
56
  stemmer = SnowballStemmer("english")
57
 
58
+ #3. bert-base-uncased + my lora adapter
59
 
60
  BERT_THRESHOLDS = {"WORKLOAD": 0.65, "TEAM": 0.90, "ADJUSTMENT": 0.85, "OUTSIDE_COMMS": 0.90}
61
  tok = AutoTokenizer.from_pretrained(HERE)
62
  base = AutoModelForSequenceClassification.from_pretrained(
63
  "bert-base-uncased", num_labels=4, problem_type="multi_label_classification")
64
+ bert = PeftModel.from_pretrained(base, HERE, torch_device="cpu").eval() #cpu --> zerogpu pretends cuda exists at startup, eval() turns dropout off
65
 
66
 
67
  def vader_flags(seg):
 
156
  return "\n\n".join(kept), "fallback", [s for s in speakers if s != astro], speakers, len(kept), len(turns)
157
 
158
 
159
+ #segmentation: whole sentences packed up to 300 words, nothing under 20 words
160
  MIN_WORDS, MAX_WORDS = 20, 300
161
 
162
 
163
  def segment(text):
164
  blocks = [b.strip() for b in text.split("\n\n") if b.strip()]
165
  paras = blocks[:1]
166
+ for b in blocks[1:]: #a blank line is only a real break if the sentence ended and the next starts with a capital
167
  if paras[-1][-1] in ".!?\"\u201d" and b[0].isupper():
168
  paras.append(b)
169
  else:
 
176
  chunks.append(p)
177
  continue
178
  sents = []
179
+ for s in sent_tokenize(p): #glue back "sentences" that start lowercase (punkt splits on initials)
180
  if sents and s[:1].islower():
181
  sents[-1] += " " + s
182
  else:
 
226
  elif method == "fallback":
227
  s3 = f"PASSED (fallback): no 'Interviewed by' line, kept the longest speaker. Removed: {', '.join(removed)}."
228
  else:
229
+ s3 = "NO SPEAKER TAGS FOUND (like ARMSTRONG:), so the whole text is treated as the astronaut's words."
230
  if method != "no_tags" and not narrative.strip():
231
  #known failure from my report: a curly apostrophe or accent in the astronaut's tag (O’CONNOR) isn't matched
232
  s3 = (f"FAILED: interviewer found ({', '.join(removed)}) but nothing was left after removing them, "
 
234
  s3 += f" Words left: {len(narrative.split()):,}."
235
  if method == "no_tags":
236
  #no cover page and no NAME: tags --> probably not an oral history, the models still run but read with care
237
+ s3 += " Note: this does not look like a NASA oral history transcript, so the scores below are less meaningful."
238
 
239
  #step 4
240
  segs = segment(narrative)
 
321
  # the page
322
 
323
  CSS = """
324
+ .gradio-container {background: radial-gradient(ellipse at top, #2a0f1a 0%, #05070f 70%) !important;}
325
  * {box-shadow: none !important;}
326
  .seg {border: 1px solid #ffffff44; border-radius: 12px; padding: 8px 12px; margin: 6px 0; color: #e6ebff;}
327
  table {width: 100%; border-collapse: collapse; color: #e6ebff;}
 
333
  gr.Markdown("# SPACEMIND")
334
 
335
  with gr.Row():
336
+ #inputs
337
  with gr.Column():
338
  textInput = gr.Textbox(label="Paste a transcript or a passage", lines=10)
339
  fileInput = gr.File(label="...or upload a .txt / .pdf transcript", file_types=[".txt", ".pdf"])
 
345
  heldOut = find_files(TEST_SET)
346
  if heldOut:
347
  gr.Examples([[p] for p, _ in heldOut], inputs=fileInput, example_labels=[l for _, l in heldOut],
348
+ label="Load a transcript from my held-out test set")
349
  tests = find_files(PIPELINE_TESTS)
350
  if tests:
351
  gr.Examples([[p] for p, _ in tests], inputs=fileInput, example_labels=[l for _, l in tests],
352
+ label="Pipeline tests (where it works and where it breaks)")
353
 
354
+ #the stages
355
  with gr.Column():
356
  out1 = gr.Textbox(label="1. Input (word count)")
357
  out2 = gr.Textbox(label="2. Cleaning")
 
372
  shapButton.click(explain, [state, segPick, catPick], shapOut)
373
 
374
 
375
+ BURGUNDY = gr.themes.Color(c50="#fdf2f4", c100="#fbe5e9", c200="#f5c6d0", c300="#ec9aab", c400="#d9637c",
376
+ c500="#9b2743", c600="#801f38", c700="#661a2e", c800="#4f1524", c900="#3d1019",
377
+ c950="#2e0a14", name="burgundy")
378
 
379
+ demo.launch(theme=gr.themes.Base(primary_hue=BURGUNDY, neutral_hue="slate"), css=CSS,
380
+ js="() => document.body.classList.add('dark')")