alaajabari commited on
Commit
f4bba2e
·
verified ·
1 Parent(s): 4585cd9

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +182 -0
main.py CHANGED
@@ -599,6 +599,188 @@ def predict_re(request: RERequest):
599
  except Exception as e:
600
  return {"error": str(e)}
601
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
602
  # =========== Front End =============================
603
  from fastapi.staticfiles import StaticFiles
604
  from fastapi.responses import FileResponse
 
599
  except Exception as e:
600
  return {"error": str(e)}
601
 
602
+
603
+ # =========== Event Argument Extraction =============
604
+
605
+ # ============ Event Argument Extraction ==============
606
+ from transformers import pipeline
607
+
608
+ EVENT_MODEL_ID = "SinaLab/arabic-relation-extraction-model"
609
+ EVENT_MAX_LEN = 128
610
+
611
+ event_pipe = pipeline(
612
+ "sentiment-analysis",
613
+ model=EVENT_MODEL_ID,
614
+ tokenizer=EVENT_MODEL_ID,
615
+ device=0 if torch.cuda.is_available() else -1,
616
+ return_all_scores=True,
617
+ max_length=EVENT_MAX_LEN,
618
+ truncation=True
619
+ )
620
+
621
+ event_relation_prompt = {
622
+ "location": "مكان حدوث",
623
+ "agent": "أحد المتأثرين في",
624
+ "happened at": "تاريخ حدوث"
625
+ }
626
+
627
+ event_categories = {
628
+ "agent": ["PERS", "NORP", "OCC", "ORG"],
629
+ "location": ["LOC", "FAC", "GPE"],
630
+ "happened at": ["DATE", "TIME"]
631
+ }
632
+
633
+ event_relation_name_map = {
634
+ "agent": "hasAgent",
635
+ "location": "hasLocation",
636
+ "happened at": "hasDate"
637
+ }
638
+
639
+
640
+ def get_entity_category(entity_type, categories):
641
+ for category, types in categories.items():
642
+ if entity_type in types:
643
+ return category
644
+ return None
645
+
646
+
647
+ def get_positive_score(predicted_relation):
648
+ """
649
+ The pipeline returns something like:
650
+ [
651
+ [
652
+ {"label": "LABEL_0", "score": 0.12},
653
+ {"label": "LABEL_1", "score": 0.88}
654
+ ]
655
+ ]
656
+
657
+ In your original code, you used:
658
+ predicted_relation[0][0]["score"]
659
+
660
+ If your positive class is LABEL_0, keep index 0.
661
+ If your positive class is LABEL_1, change this to index 1.
662
+
663
+ This version first tries LABEL_1, then falls back to index 0.
664
+ """
665
+
666
+ scores = predicted_relation[0]
667
+
668
+ for item in scores:
669
+ if item["label"] in ["LABEL_1", "relation", "RELATION", "positive"]:
670
+ return item["score"]
671
+
672
+ return scores[0]["score"]
673
+
674
+
675
+ def event_argument_extractor(sentence):
676
+ entities = entities_and_types(sentence)
677
+
678
+ event_entities = [
679
+ (entity_name, entity_type)
680
+ for entity_name, entity_type in entities.items()
681
+ if entity_type == "EVENT"
682
+ ]
683
+
684
+ argument_entities = [
685
+ (entity_name, entity_type)
686
+ for entity_name, entity_type in entities.items()
687
+ if entity_type != "EVENT"
688
+ ]
689
+
690
+ output_list = []
691
+
692
+ for event_entity, event_type in event_entities:
693
+ for arg_name, arg_type in argument_entities:
694
+ category = get_entity_category(arg_type, event_categories)
695
+
696
+ if category not in event_relation_prompt:
697
+ continue
698
+
699
+ relation_sentence = (
700
+ f"[CLS] {sentence} [SEP] "
701
+ f"{event_entity} {event_relation_prompt[category]} {arg_name}"
702
+ )
703
+
704
+ predicted_relation = event_pipe(relation_sentence)
705
+ score = get_positive_score(predicted_relation)
706
+
707
+ if score > 0.50:
708
+ output_list.append({
709
+ "Subject": {
710
+ "Type": event_type,
711
+ "Label": event_entity
712
+ },
713
+ "Relation": event_relation_name_map[category],
714
+ "Object": {
715
+ "Type": arg_type,
716
+ "Label": arg_name
717
+ },
718
+ "Confidence": float(round(score, 4))
719
+ })
720
+
721
+ return output_list
722
+
723
+
724
+ class EAERequest(BaseModel):
725
+ text: str
726
+
727
+
728
+ @app.post("/predict_eae")
729
+ def predict_eae(request: EAERequest):
730
+ try:
731
+ text = request.text.strip()
732
+
733
+ if not text:
734
+ return JSONResponse(
735
+ content={
736
+ "resp": [],
737
+ "statusText": "EMPTY_INPUT",
738
+ "statusCode": 1,
739
+ },
740
+ media_type="application/json",
741
+ status_code=200,
742
+ )
743
+
744
+ sentences = sentence_tokenizer(
745
+ text,
746
+ dot=False,
747
+ new_line=True,
748
+ question_mark=False,
749
+ exclamation_mark=False
750
+ )
751
+
752
+ results = []
753
+
754
+ for sentence in sentences:
755
+ sentence = sentence.strip()
756
+ if not sentence:
757
+ continue
758
+
759
+ sentence_results = event_argument_extractor(sentence)
760
+ results.extend(sentence_results)
761
+
762
+ return JSONResponse(
763
+ content={
764
+ "resp": results,
765
+ "statusText": "OK",
766
+ "statusCode": 0,
767
+ },
768
+ media_type="application/json",
769
+ status_code=200,
770
+ )
771
+
772
+ except Exception as e:
773
+ return JSONResponse(
774
+ content={
775
+ "resp": [],
776
+ "statusText": str(e),
777
+ "statusCode": 500,
778
+ },
779
+ media_type="application/json",
780
+ status_code=500,
781
+ )
782
+
783
+
784
  # =========== Front End =============================
785
  from fastapi.staticfiles import StaticFiles
786
  from fastapi.responses import FileResponse