ciftselcuk's picture
Initial deployment: GLiNER Large entity extractor with 70 labels
f0b69ef
"""
T9 Oracle GLiNER Entity Extractor - HF Space Deployment
Gradio API endpoint for zero-shot NER with 70 medical device labels
Deployed on: Persistent T4 GPU
Model: urchade/gliner_large-v2.1 (1.7GB)
Cost: $0.60/hour
"""
import gradio as gr
import json
import logging
from typing import List, Dict
from gliner import GLiNER
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# 70 APPROVED ENTITY LABELS (from T9 configuration)
ENTITY_LABELS = [
# Tier 1: Critical Identifiers (4)
"part_number", "component_name", "manufacturer", "model_number",
# Tier 2: Specifications & Measurements (13)
"pressure", "temperature", "voltage", "current", "material",
"dimension", "weight", "volume", "flow_rate", "power",
"diameter", "length", "thickness",
# Tier 3: Standards & Compliance (4)
"standard_reference", "certification", "compliance", "safety_class",
# Tier 4: Geometry & Mechanical (11)
"thread_standard", "pipe_size", "tubing_size", "connector_type",
"surface_finish", "surface_treatment", "width", "height",
"tolerance", "hardness", "torque",
# Tier 5: Documentation (7)
"diagram_reference", "drawing_number", "procedure_number",
"test_protocol", "revision", "sku_number", "part_label",
# Tier 6: Operational Parameters (9)
"accuracy", "speed", "frequency", "resistance",
"operating_temperature", "supply_voltage", "response_time",
"duty_cycle", "operating_range",
# Tier 7: Manufacturing (8)
"operator_id", "tool_number", "gauge_id", "fixture_number",
"machine_id", "lot_number", "serial_number", "batch_id",
# Tier 8: Medical Device (7)
"medical_device", "scope_manufacturer", "channel_type",
"port_type", "hub_type", "color_code", "leak_test",
# Tier 9: Visual Elements (2)
"diagram_type", "technical_annotation",
# Tier 10: Quality & Maintenance (7)
"calibration_interval", "service_interval", "mtbf",
"warranty", "expiration_date", "production_date", "inspection_report"
]
# Load GLiNER model (runs once on Space startup)
logger.info("Loading GLiNER Large model (1.7GB)...")
model = GLiNER.from_pretrained("urchade/gliner_large-v2.1")
logger.info(f"✓ GLiNER loaded with {len(ENTITY_LABELS)} labels")
def extract_entities(text: str, max_length: int = 10000) -> str:
"""
Extract entities from text using GLiNER zero-shot NER
Args:
text: Input text (max 10,000 characters recommended)
max_length: Maximum text length per prediction
Returns:
JSON string with extracted entities
"""
if not text or not text.strip():
return json.dumps({"entities": [], "error": "Empty text provided"})
# Truncate if too long
if len(text) > max_length:
logger.warning(f"Text truncated from {len(text)} to {max_length} chars")
text = text[:max_length]
try:
# GLiNER prediction
predictions = model.predict_entities(text, ENTITY_LABELS)
# Format output
entities = []
for pred in predictions:
entities.append({
"text": pred.get("text", ""),
"label": pred.get("label", ""),
"start": pred.get("start", 0),
"end": pred.get("end", 0),
"score": float(pred.get("score", 0.0))
})
logger.info(f"Extracted {len(entities)} entities from {len(text)} chars")
return json.dumps({
"entities": entities,
"input_length": len(text),
"entity_count": len(entities),
"labels_used": len(ENTITY_LABELS)
}, indent=2)
except Exception as e:
logger.error(f"Extraction failed: {e}")
return json.dumps({"entities": [], "error": str(e)})
def batch_extract(text_batch: str) -> str:
"""
Extract entities from multiple texts (newline-separated)
Args:
text_batch: Multiple texts separated by double newlines
Returns:
JSON string with results for each text
"""
texts = [t.strip() for t in text_batch.split("\n\n") if t.strip()]
results = []
for i, text in enumerate(texts):
result_json = extract_entities(text)
result = json.loads(result_json)
result["text_index"] = i
results.append(result)
return json.dumps({"results": results, "batch_size": len(texts)}, indent=2)
# Create Gradio interface
demo = gr.Interface(
fn=extract_entities,
inputs=[
gr.Textbox(
lines=10,
placeholder="Enter technical text here (max 10,000 chars)...",
label="Input Text"
)
],
outputs=gr.JSON(label="Extracted Entities"),
title="T9 Oracle Entity Extractor (GLiNER Large)",
description=f"""
**Zero-shot NER for Medical Device Technical Documentation**
Extracts **{len(ENTITY_LABELS)} entity types** across 10 tiers:
- Part numbers, dimensions, materials, standards
- Electrical specs, pressure, temperature, flow rates
- Thread standards, tolerances, surface treatments
- Medical device specific (scopes, channels, colors)
- Quality & maintenance data
**Model:** GLiNER Large v2.1 (1.7GB)
**Hardware:** NVIDIA T4 GPU (16GB VRAM)
**Max input:** 10,000 characters per request
""",
examples=[
["Part Number: A70002-2, Material: SS316L, Pressure: 60 psi, Thread: 1/4\" NPT"],
["Standard: ISO 1179-2, ASTM A112, Temperature: -40 to 85°C, Dimension: 6mm x 35mm"],
["Manufacturer: Olympus, Channel: Biopsy, Color: Orange Tubing, Serial: SN-123456"]
],
api_name="extract", # Important: enables API access
allow_flagging="never"
)
# Launch with API enabled
if __name__ == "__main__":
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=False # HF Spaces handles sharing
)