Use Nvidia NIM API as LLM Client.
Browse files- SNOMED-CT_Assistant.py +30 -22
SNOMED-CT_Assistant.py
CHANGED
@@ -14,16 +14,28 @@ remote = True
|
|
14 |
|
15 |
if remote:
|
16 |
with st.sidebar:
|
17 |
-
if '
|
18 |
st.success('API key already provided!', icon='β
')
|
19 |
-
|
20 |
else:
|
21 |
load_dotenv()
|
22 |
openai_api_key = os.environ.get("OpenAI_API_KEY")
|
|
|
23 |
|
24 |
st.title("π₯ SNOMED-CT Assistant")
|
25 |
st.caption("π©ββοΈ A smart medical assistant with SNOMED-CT knowledge.")
|
26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
# System prompt
|
28 |
system_prompt = """You are a medical expert with rich experience in SNOMED-CT professional knowledge.
|
29 |
You are skilled at assisting medical professionals and answering questions in the medical field.
|
@@ -35,19 +47,19 @@ Please refuse to answer inquiries and requests unrelated to the medical field, i
|
|
35 |
As an experienced professional, you possess deep expertise in the field of SNOMED CT Entity Linking.
|
36 |
You have a thorough understanding of the relevant workflows and critical aspects involved, encompassing:
|
37 |
- Adept handling of electronic medical record (EMR) data processing
|
38 |
-
- Entity Identification
|
39 |
- Skilled Entity Mapping, accurately linking identified entities to their corresponding SNOMED CT concepts
|
40 |
- Seamless integration and output of clinical terminology, ensuring the accurate representation and utilization of standardized medical language
|
41 |
- Patiently and professionally respond to all SNOMED CT related inquiries, even if the user repeats questions.
|
42 |
- Demonstrate deep expertise in the standard SNOMED CT Entity Linking workflow, which involves:
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
- the input text in EHRs: "Patient referred for a biopsy to investigate potential swelling in upper larynx."
|
49 |
-
- the identified entity: "biopsy", "larynx"
|
50 |
- response the identified entities with JSON format: {"identified_entity" : ["biopsy", "larynx"]}
|
|
|
|
|
51 |
- During Entity Identification processing, if the original medical text data clearly contains commonly used medical abbreviations, convert the abbreviations into their full names, and provide the original abbreviations in parentheses for easy reference.
|
52 |
- For example: "The patient has the multiple disease, including T2D, CAD, HTN, CKD etc. decreased T3 and T4 levels."
|
53 |
- T2D: "Type 2 Diabetes Mellitus", CAD: "Coronary Artery Disease", HTN: "Hypertension", CKD: "Chronic Kidney Disease", T3: "Triiodothyronine", T4: "Thyroxine"
|
@@ -65,6 +77,8 @@ Numbers or units related symbols are not included in this range and can be ignor
|
|
65 |
Output Format Requirements (Must follow):
|
66 |
- As default, only process "Entity Identification", and find out the entity related to SNOMED CT terms.
|
67 |
- Present the results in JSON format, like: {"identified_entity" : ["biopsy", "larynx"]}
|
|
|
|
|
68 |
"""
|
69 |
|
70 |
|
@@ -90,10 +104,6 @@ def generate_entity_identification_prompt(medical_text):
|
|
90 |
def generate_entity_mapping_prompt(entity, query_result_dict):
|
91 |
return f"""Help me to do "SNOMED-CT Entity Mapping" process with entity: {entity} and query result \n {query_result_dict} \n , output with table format, including 5 columns: "Identified Entity", "Distance", "IDs", "SNOMED CT Concept IDs", "SNOMED CT Descriptions" \n """
|
92 |
|
93 |
-
# Chroma DB Client
|
94 |
-
chroma_client = chromadb.PersistentClient(path="snomed_ct_id_term_1410k")
|
95 |
-
collection = chroma_client.get_or_create_collection(name="snomed_ct_id_term")
|
96 |
-
|
97 |
# Func: query chrome_db
|
98 |
def query_chroma_db(query_text, query_number):
|
99 |
results = collection.query(
|
@@ -108,19 +118,17 @@ def get_dict_from_chroma_results(results):
|
|
108 |
result_dict = {'ids': results['ids'][0], 'concept_ids': [ str(sub['concept_id']) for sub in results['metadatas'][0] ], 'distances': results['distances'][0], 'descriptions': results['documents'][0]}
|
109 |
return result_dict
|
110 |
|
111 |
-
|
112 |
-
# OpenAI Client Configuration
|
113 |
-
client = OpenAI(api_key=openai_api_key)
|
114 |
-
model_tag = "gpt-3.5-turbo"
|
115 |
-
|
116 |
-
# Chat Session with OpenAI API
|
117 |
def chat_input(prompt, med_text):
|
118 |
st.session_state.messages.append({"role": "user", "content": med_text})
|
119 |
st.chat_message("user").write(med_text)
|
120 |
with st.spinner("Thinking..."):
|
121 |
entity_identification_response = client.chat.completions.create(
|
122 |
-
model=model_tag,
|
|
|
|
|
123 |
msg = entity_identification_response.choices[0].message.content
|
|
|
124 |
entity_list = json.loads(msg)["identified_entity"]
|
125 |
st.session_state.messages.append({"role": "assistant", "content": msg})
|
126 |
st.chat_message("assistant").write(msg)
|
@@ -163,7 +171,7 @@ def entity_mapping_result_to_table(entity, results_dict):
|
|
163 |
|
164 |
if "messages" not in st.session_state:
|
165 |
st.session_state["messages"] = [{"role": "system", "content": system_prompt},
|
166 |
-
{"role": "assistant", "content": "π©ββοΈ
|
167 |
|
168 |
for msg in st.session_state.messages:
|
169 |
if msg["role"] == "system":
|
|
|
14 |
|
15 |
if remote:
|
16 |
with st.sidebar:
|
17 |
+
if 'NVIDIA_NIM_KEY' in st.secrets:
|
18 |
st.success('API key already provided!', icon='β
')
|
19 |
+
nvidia_nim_key = st.secrets['NVIDIA_NIM_KEY']
|
20 |
else:
|
21 |
load_dotenv()
|
22 |
openai_api_key = os.environ.get("OpenAI_API_KEY")
|
23 |
+
nvidia_nim_key = os.environ.get("NVIDIA_NIM_KEY")
|
24 |
|
25 |
st.title("π₯ SNOMED-CT Assistant")
|
26 |
st.caption("π©ββοΈ A smart medical assistant with SNOMED-CT knowledge.")
|
27 |
|
28 |
+
# Chroma DB Client
|
29 |
+
chroma_client = chromadb.PersistentClient(path="snomed_ct_id_term_1410k")
|
30 |
+
collection = chroma_client.get_or_create_collection(name="snomed_ct_id_term")
|
31 |
+
|
32 |
+
# NIM Client Configuration
|
33 |
+
client = OpenAI(
|
34 |
+
base_url = "https://integrate.api.nvidia.com/v1",
|
35 |
+
api_key = nvidia_nim_key
|
36 |
+
)
|
37 |
+
model_tag = "meta/llama3-70b-instruct"
|
38 |
+
|
39 |
# System prompt
|
40 |
system_prompt = """You are a medical expert with rich experience in SNOMED-CT professional knowledge.
|
41 |
You are skilled at assisting medical professionals and answering questions in the medical field.
|
|
|
47 |
As an experienced professional, you possess deep expertise in the field of SNOMED CT Entity Linking.
|
48 |
You have a thorough understanding of the relevant workflows and critical aspects involved, encompassing:
|
49 |
- Adept handling of electronic medical record (EMR) data processing
|
50 |
+
- *Entity Identification*, Proficient entity recognition capabilities, identifying and extracting relevant medical concepts from unstructured text
|
51 |
- Skilled Entity Mapping, accurately linking identified entities to their corresponding SNOMED CT concepts
|
52 |
- Seamless integration and output of clinical terminology, ensuring the accurate representation and utilization of standardized medical language
|
53 |
- Patiently and professionally respond to all SNOMED CT related inquiries, even if the user repeats questions.
|
54 |
- Demonstrate deep expertise in the standard SNOMED CT Entity Linking workflow, which involves:
|
55 |
+
- **All YOU CAN DO** : Performing **Entity Identification** : Try to extract relevant medical terminology from the medical text input.
|
56 |
+
|
57 |
+
Here is the practical entity identification process example:
|
58 |
+
- the input text will the part of EHRs record: "Patient referred for a biopsy to investigate potential swelling in upper larynx."
|
59 |
+
- if the identified entity: "biopsy", "larynx"
|
|
|
|
|
60 |
- response the identified entities with JSON format: {"identified_entity" : ["biopsy", "larynx"]}
|
61 |
+
- If no identifiable entity is found in the input text, return an empty list: {"identified_entity" : []}
|
62 |
+
- **DON't response the other format besides JSON**
|
63 |
- During Entity Identification processing, if the original medical text data clearly contains commonly used medical abbreviations, convert the abbreviations into their full names, and provide the original abbreviations in parentheses for easy reference.
|
64 |
- For example: "The patient has the multiple disease, including T2D, CAD, HTN, CKD etc. decreased T3 and T4 levels."
|
65 |
- T2D: "Type 2 Diabetes Mellitus", CAD: "Coronary Artery Disease", HTN: "Hypertension", CKD: "Chronic Kidney Disease", T3: "Triiodothyronine", T4: "Thyroxine"
|
|
|
77 |
Output Format Requirements (Must follow):
|
78 |
- As default, only process "Entity Identification", and find out the entity related to SNOMED CT terms.
|
79 |
- Present the results in JSON format, like: {"identified_entity" : ["biopsy", "larynx"]}
|
80 |
+
- If no identifiable entity is found in the input text, return an empty list: {"identified_entity" : []}
|
81 |
+
- **DON't response the other format besides JSON**
|
82 |
"""
|
83 |
|
84 |
|
|
|
104 |
def generate_entity_mapping_prompt(entity, query_result_dict):
|
105 |
return f"""Help me to do "SNOMED-CT Entity Mapping" process with entity: {entity} and query result \n {query_result_dict} \n , output with table format, including 5 columns: "Identified Entity", "Distance", "IDs", "SNOMED CT Concept IDs", "SNOMED CT Descriptions" \n """
|
106 |
|
|
|
|
|
|
|
|
|
107 |
# Func: query chrome_db
|
108 |
def query_chroma_db(query_text, query_number):
|
109 |
results = collection.query(
|
|
|
118 |
result_dict = {'ids': results['ids'][0], 'concept_ids': [ str(sub['concept_id']) for sub in results['metadatas'][0] ], 'distances': results['distances'][0], 'descriptions': results['documents'][0]}
|
119 |
return result_dict
|
120 |
|
121 |
+
# Chat Session with NIM API
|
|
|
|
|
|
|
|
|
|
|
122 |
def chat_input(prompt, med_text):
|
123 |
st.session_state.messages.append({"role": "user", "content": med_text})
|
124 |
st.chat_message("user").write(med_text)
|
125 |
with st.spinner("Thinking..."):
|
126 |
entity_identification_response = client.chat.completions.create(
|
127 |
+
model=model_tag,
|
128 |
+
messages=st.session_state.messages,
|
129 |
+
temperature=0.5)
|
130 |
msg = entity_identification_response.choices[0].message.content
|
131 |
+
print("NIM output" + msg)
|
132 |
entity_list = json.loads(msg)["identified_entity"]
|
133 |
st.session_state.messages.append({"role": "assistant", "content": msg})
|
134 |
st.chat_message("assistant").write(msg)
|
|
|
171 |
|
172 |
if "messages" not in st.session_state:
|
173 |
st.session_state["messages"] = [{"role": "system", "content": system_prompt},
|
174 |
+
{"role": "assistant", "content": "π©ββοΈ Hello, I am your professional medical assistant. Is there anything I can assist you with?"}]
|
175 |
|
176 |
for msg in st.session_state.messages:
|
177 |
if msg["role"] == "system":
|