gaurannggg7 commited on
Commit
ebb7d91
·
verified ·
1 Parent(s): 25f2802

Update gloss_builder.py

Browse files
Files changed (1) hide show
  1. gloss_builder.py +124 -9
gloss_builder.py CHANGED
@@ -1,13 +1,128 @@
1
- from gemma_loader import Gemma3nEdge
 
 
2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
- def build_gloss_sequence(transcript: str, model_name: str, max_tokens: int = 100) -> list[str]:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  """
6
- Returns a list of uppercase ASL gloss tokens using the selected Gemma model.
 
7
  """
8
- # Initialize Gemma with the chosen model directory
9
- gemma = Gemma3nEdge(model_dir=model_name)
10
- # Generate the raw gloss string
11
- raw_gloss = gemma.generate_gloss(transcript, max_tokens=max_tokens)
12
- # Split tokens and uppercase for ASL convention
13
- return [token.upper() for token in raw_gloss.split()]
 
 
 
 
1
+ import os
2
+ import requests
3
+ import pandas as pd
4
 
5
+ def load_known_tokens(csv_path: str = "content/asl_app_data/asl_video_index_final_with_path_cleaned.csv") -> list[str]:
6
+ """Load vocabulary from CSV — single words only for prompt constraint."""
7
+ try:
8
+ df = pd.read_csv(csv_path)
9
+ tokens = df['token'].dropna().str.upper().str.strip().unique().tolist()
10
+ # Single words only — more useful for Gemma constraint
11
+ single = sorted([t for t in tokens if ' ' not in t and len(t) > 1])
12
+ return single
13
+ except Exception as e:
14
+ print(f"⚠️ Could not load tokens from CSV: {e}")
15
+ # Fallback: words we know we have
16
+ return [
17
+ "HELLO", "PLEASE", "COME", "CLEAN", "YOU", "AND", "ANY",
18
+ "ASK", "ANSWER", "ANOTHER", "ANYONE", "ANYTHING", "ANYWHERE",
19
+ "APOLOGY", "APPRECIATE", "APPROACH", "ARMY", "AROUND",
20
+ "ARRIVE", "ART", "ASSIST", "ATTEND", "ATTENTION", "ATTITUDE",
21
+ "ANGER", "ANIMAL", "ANNOUNCE", "ANNOY", "ANNOYED", "ANXIOUS",
22
+ "APART", "APARTMENT", "APPLE", "ARROGANT", "ASSOCIATE",
23
+ "ASSUME", "ATTRACT", "AUNT"
24
+ ]
25
 
26
+
27
+ def build_gloss_sequence(
28
+ transcript: str,
29
+ model_name: str,
30
+ max_tokens: int = 60,
31
+ csv_path: str = "content/asl_app_data/asl_video_index_final_with_path_cleaned.csv"
32
+ ) -> list[str]:
33
+ """
34
+ Convert English transcript to ASL gloss tokens using Gemma.
35
+ Uses constrained prompt to maximize hits against known vocabulary.
36
+ Falls back to simple uppercase split if API fails.
37
+ """
38
+ known_tokens = load_known_tokens(csv_path)
39
+
40
+ # Take first 300 tokens for prompt — keep it under context limit
41
+ vocab_sample = ', '.join(known_tokens[:300])
42
+
43
+ prompt = f"""You are an expert ASL (American Sign Language) gloss translator.
44
+
45
+ STRICT RULES:
46
+ 1. DROP all articles: a, an, the
47
+ 2. DROP all linking verbs: is, are, was, were, am, be, been, being
48
+ 3. DROP all prepositions: to, of, for, in, on, at, by, with, from, into
49
+ 4. USE present tense root form only: CLEAN not CLEANING, DELAY not DELAYED, ARRIVE not ARRIVED
50
+ 5. ONLY output words from this vocabulary list: {vocab_sample}
51
+ 6. If a word has no match, find the CLOSEST SYNONYM from the vocabulary
52
+ 7. Output ONLY uppercase tokens separated by spaces — no punctuation, no explanation
53
+
54
+ EXAMPLES:
55
+ English: "Hello, how are you doing today?"
56
+ ASL Gloss: HELLO YOU
57
+
58
+ English: "Please clean the dishes"
59
+ ASL Gloss: PLEASE CLEAN
60
+
61
+ English: "I am anxious about the appointment"
62
+ ASL Gloss: ANXIOUS APPOINT
63
+
64
+ English: "Can you come here and help me?"
65
+ ASL Gloss: COME ASSIST
66
+
67
+ English: "{transcript}"
68
+ ASL Gloss:"""
69
+
70
+ api_url = f"https://api-inference.huggingface.co/models/google/gemma-2b-it"
71
+ headers = {"Authorization": f"Bearer {os.environ.get('HF_TOKEN')}"}
72
+
73
+ payload = {
74
+ "inputs": prompt,
75
+ "parameters": {
76
+ "max_new_tokens": max_tokens,
77
+ "return_full_text": False,
78
+ "temperature": 0.1, # Low temp = more deterministic/constrained
79
+ "do_sample": False
80
+ }
81
+ }
82
+
83
+ try:
84
+ response = requests.post(api_url, headers=headers, json=payload, timeout=20)
85
+ output = response.json()
86
+
87
+ raw = ""
88
+ if isinstance(output, list) and len(output) > 0:
89
+ raw = output[0].get("generated_text", "").strip()
90
+ elif isinstance(output, dict):
91
+ raw = output.get("generated_text", "").strip()
92
+
93
+ if not raw:
94
+ print(f"⚠️ Empty Gemma response, falling back. Raw: {output}")
95
+ return _simple_gloss(transcript)
96
+
97
+ # Clean output — take only first line, strip non-alpha
98
+ first_line = raw.split('\n')[0].strip()
99
+ tokens = [
100
+ t.upper() for t in first_line.split()
101
+ if t.isalpha() and t.upper() not in {"ASL", "GLOSS", "ENGLISH"}
102
+ ]
103
+
104
+ if not tokens:
105
+ return _simple_gloss(transcript)
106
+
107
+ print(f"✅ Gemma gloss: {tokens}")
108
+ return tokens
109
+
110
+ except Exception as e:
111
+ print(f"⚠️ Gemma API failed: {e}. Falling back to simple gloss.")
112
+ return _simple_gloss(transcript)
113
+
114
+
115
+ def _simple_gloss(transcript: str) -> list[str]:
116
  """
117
+ Fallback: strip stopwords and return uppercase tokens.
118
+ Used when Gemma API is unavailable.
119
  """
120
+ STOPWORDS = {
121
+ "A", "AN", "THE", "IS", "ARE", "WAS", "WERE", "AM", "BE", "BEEN",
122
+ "BEING", "TO", "OF", "FOR", "IN", "ON", "AT", "BY", "WITH", "FROM",
123
+ "INTO", "AND", "BUT", "OR", "SO", "IF", "AS", "IT", "ITS", "THIS",
124
+ "THAT", "THESE", "THOSE", "MY", "YOUR", "HIS", "HER", "OUR", "THEIR"
125
+ }
126
+ import re
127
+ words = re.findall(r"[A-Za-z]+", transcript)
128
+ return [w.upper() for w in words if w.upper() not in STOPWORDS]