JermaineAI commited on
Commit
847ffb5
·
1 Parent(s): 6e2bfd4

Move model download to runtime with auth

Browse files
Files changed (2) hide show
  1. Dockerfile +0 -1
  2. app/services/ai_extractor.py +32 -21
Dockerfile CHANGED
@@ -20,7 +20,6 @@ RUN pip install --no-cache-dir -r requirements.txt
20
  # This ensures it gets the exact file without guessing the version
21
  RUN pip install https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.7.1/en_core_web_sm-3.7.1.tar.gz
22
 
23
- RUN python -c "from fast_gliner import FastGLiNER; FastGLiNER.from_pretrained('Xenova/gliner-small-v2.1')"
24
 
25
  COPY . .
26
 
 
20
  # This ensures it gets the exact file without guessing the version
21
  RUN pip install https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.7.1/en_core_web_sm-3.7.1.tar.gz
22
 
 
23
 
24
  COPY . .
25
 
app/services/ai_extractor.py CHANGED
@@ -1,41 +1,52 @@
1
- # 1. Change Import
2
  from fast_gliner import FastGLiNER
3
 
4
  class UniversalExtractor:
5
  def __init__(self):
6
  print("Loading Fast GLiNER model (ONNX)...")
7
- # 2. Use the ONNX version of the same model
8
- # "Xenova/gliner-small-v2.1" is the optimized version of "urchade/gliner_small-v2.1"
9
- self.model = FastGLiNER.from_pretrained("Xenova/gliner-small-v2.1")
 
 
 
 
 
 
 
 
10
 
11
  self.labels = [
12
- "Skill", "Software",]
 
13
 
14
  def extract_universal(self, text: str):
15
- # 3. Use batch processing for extra speed
16
- # We split text into chunks and process them in parallel
17
  chunks = [text[i:i+3000] for i in range(0, len(text), 3000)]
18
 
19
  extracted_data = {
20
  "skills": set(),
21
  "tools": set(),
 
22
  }
23
 
24
- # FastGLiNER's batch_predict is highly optimized
25
- # We pass all chunks at once
26
  if chunks:
27
- batch_results = self.model.batch_predict_entities(chunks, self.labels, threshold=0.35)
28
-
29
- for entities in batch_results:
30
- for entity in entities:
31
- text_val = entity["text"].strip()
32
- label = entity["label"]
33
-
34
- if label == "Skill":
35
- extracted_data["skills"].add(text_val)
36
- elif label == "Software":
37
- extracted_data["tools"].add(text_val)
38
-
 
 
 
 
39
 
40
  return {k: sorted(list(v)) for k, v in extracted_data.items()}
41
 
 
1
+ import os
2
  from fast_gliner import FastGLiNER
3
 
4
  class UniversalExtractor:
5
  def __init__(self):
6
  print("Loading Fast GLiNER model (ONNX)...")
7
+
8
+ # 1. Get the token securely from Hugging Face Secrets
9
+ hf_token = os.getenv("HF_TOKEN")
10
+
11
+ # 2. Pass the token explicitly.
12
+ # If token is None, it tries anonymous (which might fail in Spaces).
13
+ # If token is valid, it authenticates and succeeds.
14
+ self.model = FastGLiNER.from_pretrained(
15
+ "Xenova/gliner-small-v2.1",
16
+ token=hf_token
17
+ )
18
 
19
  self.labels = [
20
+ "Skill", "Software",
21
+ ]
22
 
23
  def extract_universal(self, text: str):
24
+ # Limit text length to prevent memory spikes
 
25
  chunks = [text[i:i+3000] for i in range(0, len(text), 3000)]
26
 
27
  extracted_data = {
28
  "skills": set(),
29
  "tools": set(),
30
+
31
  }
32
 
 
 
33
  if chunks:
34
+ # Batch predict
35
+ try:
36
+ batch_results = self.model.batch_predict_entities(chunks, self.labels, threshold=0.35)
37
+
38
+ for entities in batch_results:
39
+ for entity in entities:
40
+ text_val = entity["text"].strip()
41
+ label = entity["label"]
42
+
43
+ if label == "Skill":
44
+ extracted_data["skills"].add(text_val)
45
+ elif label == "Software":
46
+ extracted_data["tools"].add(text_val)
47
+
48
+ except Exception as e:
49
+ print(f"GLiNER Prediction Error: {e}")
50
 
51
  return {k: sorted(list(v)) for k, v in extracted_data.items()}
52