|
|
|
|
|
import gradio as gr |
|
from transformers import AutoTokenizer, AutoModelForCausalLM, TextStreamer, BitsAndBytesConfig |
|
from peft import PeftModel, PeftConfig |
|
import torch |
|
import regex as re |
|
|
|
|
|
peft_config = PeftConfig.from_pretrained("unica/CLiMA") |
|
|
|
|
|
bnb_config = BitsAndBytesConfig( |
|
load_in_4bit=True, |
|
bnb_4bit_quant_type="nf4", |
|
bnb_4bit_compute_dtype=torch.bfloat16, |
|
bnb_4bit_use_double_quant=True |
|
) |
|
|
|
|
|
base_model = AutoModelForCausalLM.from_pretrained( |
|
peft_config.base_model_name_or_path, |
|
quantization_config=bnb_config, |
|
device_map="auto" |
|
) |
|
|
|
|
|
model = PeftModel.from_pretrained(base_model, "unica/CLiMA") |
|
|
|
|
|
tokenizer = AutoTokenizer.from_pretrained(peft_config.base_model_name_or_path) |
|
|
|
prompt_instruction_drug_reviews = f"""Given a drug review enclosed in triple quotes and a pair of entities E1 corresponding to the drug name and E2 corresponding to the treated condition, classify the relation holding between E1 and E2. |
|
The relations are identified with 9 labels from 0 to 8. The meaning of the labels is the following: |
|
0 means that E1 causes E2 |
|
1 means that E2 causes E1 |
|
2 means that E1 enables E2 |
|
3 means that E2 enables E1 |
|
4 means that E1 prevents E2 |
|
5 means that E2 prevents E1 |
|
6 means that E1 hinders E2 |
|
7 means that E2 hinders E1 |
|
8 means that E1 and E2 are in a relation different than any of the previous ones. |
|
Given X the label that you predicted, for the output use the format LABEL: X |
|
""" |
|
|
|
|
|
|
|
def format_prompt(user_input, entity1, entity2): |
|
|
|
text = user_input |
|
prompt_text = f"Text:'''{text}'''" |
|
e1 = entity1 |
|
e2 = entity2 |
|
prompt_entities = f"\nEntities: E1: '''{e1}''', E2: '''{e2}'''" |
|
full_prompt = f"<USER> {prompt_instruction_drug_reviews} {prompt_text} {prompt_entities} <ASSISTANT>" |
|
return full_prompt |
|
|
|
|
|
def generate_relations(text, entity1, entity2): |
|
answer_label_regex_pattern = re.compile(r'LABEL:?\s?(\d+)') |
|
|
|
|
|
prompt = format_prompt(text, entity1, entity2) |
|
inputs = tokenizer(prompt, return_tensors="pt").to(model.device) |
|
outputs = model.generate(**inputs, max_new_tokens=256, do_sample=False) |
|
response = tokenizer.decode(outputs[0], skip_special_tokens=True) |
|
modelOut = response[len(prompt):].strip() |
|
answer_match = answer_label_regex_pattern.search(modelOut) |
|
if answer_match: |
|
if answer_match.group(1)=='0': |
|
return f"""'{entity1}' causes '{entity2}'""" |
|
elif answer_match.group(1)=='1': |
|
return f"""'{entity2}' causes '{entity1}'""" |
|
elif answer_match.group(1)=='2': |
|
return f"""'{entity1}' enables '{entity2}'""" |
|
elif answer_match.group(1)=='3': |
|
return f"""'{entity2}' enables '{entity1}'""" |
|
elif answer_match.group(1)=='4': |
|
return f"""'{entity1}' prevents '{entity2}'""" |
|
elif answer_match.group(1)=='5': |
|
return f"""'{entity2}' prevents '{entity1}'""" |
|
elif answer_match.group(1)=='6': |
|
return f"""'{entity1}' hinders '{entity2}'""" |
|
elif answer_match.group(1)=='7': |
|
return f"""'{entity2}' hinders '{entity1}'""" |
|
elif answer_match.group(1)=='8': |
|
return f"""No causal relation between '{entity1}' and '{entity2}'""" |
|
else: |
|
return 'No causal relation could be extracted' |
|
|
|
|
|
|
|
|
|
demo = gr.Interface( |
|
fn=generate_relations, |
|
inputs=[ |
|
gr.Textbox(lines=10, label="Clinical Note or Drug Review Text"), |
|
gr.Textbox(label="Entity 1 (e.g., Drug)"), |
|
gr.Textbox(label="Entity 2 (e.g., Condition or Symptom)") |
|
], |
|
outputs=gr.Textbox(label="Extracted Causal Relations"), |
|
title="Causal Relation Extractor with MedLlama", |
|
description="Paste your clinical note or drug review, and specify two target entities. This AI agent extracts drug-condition or symptom causal relations using a fine-tuned LLM adapter model.", |
|
examples=[ |
|
["Odynophagia: Was presumed due to mucositis from recent chemotherapy.", "chemotherapy", "mucositis"], |
|
["patient's wife noticed erythema on patient's face. On [**3-27**]the visiting nurse [**First Name (Titles) 8706**][**Last Name (Titles)11282**]of a rash on his arms as well. The patient was noted to be febrile and was admitted to the [**Company 191**] Firm. In the EW, patient's Dilantin was discontinued and he was given Tegretol instead.", "Dilantin", "erythema on patient's face"], |
|
["i had a urinary tract infection so bad that when i pee it smells but when i started taking ciprofloxacin it worked it’s a good medicine for a urinary tract infections.","ciprofloxacin","urinary tract infection"], |
|
["when i first started using ziana, i only had acne in between my eyebrows, chin, and the nose area. my acne worsened while using it and then it got better. but after about 4 months of using it, it became ineffective. so i now have acne between my eyebrows, chin, cheeks, forehead, and the nose area. its great at first but after a while it made my face even worse than before i used the product.","ziana","acne"] |
|
] |
|
) |
|
|
|
demo.launch() |
|
|