Spaces:
Running
Running
Commit ·
847ffb5
1
Parent(s): 6e2bfd4
Move model download to runtime with auth
Browse files- Dockerfile +0 -1
- 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 |
-
|
| 2 |
from fast_gliner import FastGLiNER
|
| 3 |
|
| 4 |
class UniversalExtractor:
|
| 5 |
def __init__(self):
|
| 6 |
print("Loading Fast GLiNER model (ONNX)...")
|
| 7 |
-
|
| 8 |
-
#
|
| 9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
self.labels = [
|
| 12 |
-
"Skill", "Software",
|
|
|
|
| 13 |
|
| 14 |
def extract_universal(self, text: str):
|
| 15 |
-
#
|
| 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 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 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 |
|