Roland Ding commited on
Commit
004db8a
·
1 Parent(s): 15be848

10.9.26.75 updated ui, data, features, and backend

Browse files

ui
+ added new page for summary generation and allows user to select specific
articles from the database for summary generation
+ updated app.py to include new page

data
+ created four local dataset for testing summary generation prompts

features
+ pulled features, application, cloud_db, chains from main branch (studies demo)
+ added generate summary prompt function to features.py
+ created hand_chains.py for manually creating summary prompt chains
(may be removed later)
+ removed cloud_textract since it was no longer used
+

env settings
+ updated requirements.txt to exclude unused packages
+ updated the backend_update.ipynb for the latest procedure plus all the
new function/class creation and experimentation.
On branch summary

Changes to be committed:
new file: .data/chain.json
new file: .data/instruction_agg_performance.json
new file: .data/overview_chains.json
new file: .data/summary_prompts.json
modified: README.md
modified: app.py
modified: application.py
modified: backend_update.ipynb
modified: chains.py
modified: cloud_db.py
deleted: cloud_textract.py
modified: features.py
new file: hand_chains.py
modified: requirements.txt
new file: ui_studies.py
modified: ui_summary.py

.data/chain.json ADDED
File without changes
.data/instruction_agg_performance.json ADDED
@@ -0,0 +1 @@
 
 
1
+ [{"name":"clin-perfFUtable-FIN","inputs":"Change in Probing Depth\nFFI\nGlobal Rating of Change\nGood to Excellent Odom Score\nGrip Strength\nIncision Length\nJOA\nKaplan-Meier\nLikert\nMcCormick Grade\nNDI\nNeer's Grade\nPatient Improvement\nPSS\nPinch Strength\nPocket Depth\nROM\nStride Length\nSWMT\nTime to Fusion\nVAS Change\nVAS Score\nWalking Velocity\nNew Clinical Symptoms","chain":["Report ALL of the information of the above text by performing the following tasks.\n\nPerform the following tasks:\n1) REPORT each table with the SAME columns as listed.\n\n\nFor Each Table\n1) Report EACH \"table heading\".\n2) Identify if the Table has Groups or NO groups. \n A) If the Table has \"Group\", Report each Group Name as written in the text. \n B) If the Table has No Group, \n 1. Add a Column 0 named: \"Group\". Column 0 will precede Column 1.\n 2. Report: \"No Group\" for each row.\n\n3) Identify if the Table has a \"Preoperative Value (Units)\" or NO \"Preoperative Value (Units)\" Heading. \n A) If the Table has \"Preoperative Value (Units)\", Report each Preoperative Value as written in the text. \n B) If the Table has NO \"Preoperative Value (Units)\" Heading. \n 1. Add a Column 3a named: \"Group\". Column 3a will follow the \"Outcome\" Column\n 2. Report: \"Not Reported\" for each row.\n\n\n4) Report the corresponding Outcome, Values, and Study N for each \"Clinical Outcome\" Table.\n A) Report each VALUE to only One Decimal Point.\n\n5) IF the table is Vertical, Transpose each VERTICAL table to a HORIZONTAL table.\n\n\n\nOverall rules:\n1) Do not exclude any Groups. \n2) Do not exclude any Tables. \n3) Do not exclude any Outcomes.\n4) Do not exclude any Values."],"assessment":"clinical"},{"name":"rad-perfFUtable-FIN","inputs":"Adjacent Segment ROM\nCarpal Height Ratio\nCervical Lordosis Profeta Method\nChange in Disc Height\nChange in Segmental Lordosis Angle\nCoronal Vertical Axis\nDeltoid Tuberosity Index\nDisc Height\nEngh grading scale\nFatty Atrophy\nForaminal Area Height\nFusion Assessment\nFusion Events-simplified 2\nParallel Pitch Lines\nScrew Placement Accuracy\nSegmental Lordosis Angle","chain":["Report ALL of the information of the above text by performing the following tasks.\n\nPerform the following tasks:\n1) REPORT each table with the SAME columns as listed.\n\n\nFor Each Table\n1) Report EACH \"table heading\".\n2) Identify if the Table has Groups or NO groups. \n A) If the Table has \"Group\", Report each Group Name as written in the text. \n B) If the Table has No Group, \n 1. Add a Column 0 named: \"Group\". Column 0 will precede Column 1.\n 2. Report: \"No Group\" for each row.\n\n3) Identify if the Table has a \"Preoperative Value (Units)\" or NO \"Preoperative Value (Units)\" Heading. \n A) If the Table has \"Preoperative Value (Units)\", Report each Preoperative Value as written in the text. \n B) If the Table has NO \"Preoperative Value (Units)\" Heading. \n 1. Add a Column 3a named: \"Group\". Column 3a will follow the \"Outcome\" Column\n 2. Report: \"Not Reported\" for each row.\n\n\n4) Report the corresponding Outcome, Values, and Study N for each \"Radiologic Outcome\" Table.\n A) Report each VALUE to only One Decimal Point.\n\n5) IF the table is Vertical, Transpose each VERTICAL table to a HORIZONTAL table.\n\n\n\nOverall rules:\n1) Do not exclude any Groups. \n2) Do not exclude any Tables. \n3) Do not exclude any Outcomes.\n4) Do not exclude any Values."],"assessment":"radiologic"},{"name":"saf-Futable-FIN","inputs":"abb Nonunion-NG\nGeneric Combo-NG\nMerged Revision\/Reoperation-NG\nSubsidence-NG","chain":["From the above text, extract information to complete the following sections sequentially to create a TABLE. \nCreate ONE table with the following Heading and Columns.\n\nPerform the following tasks\n1) Create the following \"table heading\" as described. \n2) Create the following columns.\n3) Populate each column as described. \n\n\n\n\n\n1) Combine the above Tables. \n2) Create one Table Heading--\"Safety Outcome Summary\"\n\n3) Report EACH Column heading. Only report what is inside of quotes. Remove the Quotation marks and the terms \"Column\" and \"Heading\". \n NOTE: Report ALL the Column Headings in ONE ROW.\n A) REPLACE the first column heading as: \"Adverse Events\".\n B) Report the second column heading as: \"Event N\".\n C) Report the third column heading as: \"Study N\".\n D) Report the fourth column heading as: \"Event %\".\n 1. Report the Event % Value to One Decimal Point.\n Note: Do Not Report any Levels N column or values.\n\n4) Report the corresponding data for each Column Values for each \"Safety Outcome\" Table.\n A) Report all the Adverse Events in the First Column.\n B) Report all the Event N Values in the SAME Column.\n Note: For Duplicate adverse events chose the Highest Event N. Only report one Event N per Adverse Event.\n C) Report all the Study N Values in the SAME Column.\n D) Report all the Event % Values in the SAME Column.\n Note: For Duplicate adverse events chose the Highest Event %. Only report one Event % per Adverse Event.\n\n\n5) IF the table is Vertical, Transpose each VERTICAL table to a HORIZONTAL table."],"assessment":"safety"},{"name":"oth-perfFUtable-FIN","inputs":"Blood Loss\nHospital Charge\nLength of Hospital Stay\nNeed for ICU\nOperation Time\nTransfusion Rate\nTime to Readmission","chain":["Report ALL of the information of the above text by performing the following tasks.\n\nPerform the following tasks:\n1) REPORT each table with the SAME columns as listed.\n\n\nFor Each Table\n1) Report EACH \"table heading\".\n2) Identify if the Table has Groups or NO groups. \n A) If the Table has \"Group\", Report each Group Name as written in the text. \n B) If the Table has No Group, \n 1. Add a Column 0 named: \"Group\". Column 0 will precede Column 1.\n 2. Report: \"No Group\" for each row.\n\n3) Identify if the Table has NO \"Preoperative Value (Units)\" Heading. \n A) If the Table has NO \"Preoperative Value (Units)\" Heading:\n 1. INSERT a column named: \"Group\". The \"Group\" Column will follow the \"Outcome\" Column.\n 2. Report: \"Not Reported\" for each row.\n\n\n4) Report the corresponding Outcome, Values, and Study N for each \"Other Outcome\" Table.\n A) Report each VALUE to only One Decimal Point.\n\n5) IF the table is Vertical, Transpose each VERTICAL table to a HORIZONTAL table.\n\n\n\nOverall rules:\n1) Do not exclude any Groups. \n2) Do not exclude any Tables. \n3) Do not exclude any Outcomes.\n4) Do not exclude any Values."],"assessment":"other"}]
.data/overview_chains.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"studyN-H1-spine-FIN": ["Study-FIN", "FU-FIN", "Number of Patients-Spine-FIN", "Preliminary Data"], "Summary Device-Spine-FIN": ["Study-FIN", "Device-Spine-FIN", "Preliminary Data"], "Summary Age-FIN": ["Study-FIN", "Age-FIN", "Preliminary Data"], "sup-V-spine-FIN": ["SupFix-Spine-FIN", "sup-H1-spine", "Number of Patients-Spine-FIN", "Study-FIN", "sup-H2-spine", "studyN-H1-spine", "Preliminary Data", "sup-H3-spine", "sup-H4-spine"], "bone-V-spine-FIN": ["Bone Graft-FIN", "bone-H1-spine", "Number of Patients-Spine-FIN", "Study-FIN", "bone-H2-spine", "studyN-H1-spine", "Preliminary Data", "bone-H3-spine", "bone-H4-spine"], "app-V-spine-FIN": ["Approach-FIN", "Number of Patients-Spine-FIN", "app-H1-spine", "Study-FIN", "studyN-H1-spine", "app-H2-spine", "Preliminary Data", "app-H3-spine", "app-H4-spine"], "pro-V-spine-FIN": ["Procedure-Spine-FIN", "Number of Patients-Spine-FIN", "pro-H1-spine", "Study-FIN", "studyN-H1-spine", "pro-H2-spine", "Preliminary Data", "pro-H3-spine", "pro-H4-spine"], "type-V-spine-FIN": ["Number of Patients-Spine-FIN", "type-H1-spine", "Study-FIN", "studyN-H1-spine", "type-H2-spine", "Preliminary Data", "type-H3-spine", "type-H4-spine"], "ind-V-spine-FIN": ["Indication Categories-Spine-FIN", "Number of Patients-Spine-FIN", "ind-H1-spine", "Study-FIN", "studyN-H1-spine", "ind-H2-spine", "Preliminary Data", "ind-H3-spine", "ind-H4-spine"], "gen-V-spine-FIN": ["Number of Patients-Spine-FIN", "Gender-FIN", "studyN-H1-spine", "gen-H1-spine", "Study-FIN", "gen-H2-spine", "Preliminary Data", "gen-H3-spine"], "ske-V-spine-FIN": ["DAskemat-FIN", "Number of Patients-Spine-FIN", "ske-H1-spine", "Study-FIN", "studyN-H1-spine", "ske-H2-spine", "Preliminary Data", "ske-H3-spine", "ske-H4-spine"], "loco-V-spine-FIN": ["Location-Spine-FIN", "loco-H1-spine", "loco-H2-spine", "Number of Patients-Spine-FIN", "Study-FIN", "", "loco-H3-spine", "studyN-H1-spine", "Preliminary Data", "loco-H4-spine"], "studyN-H1-extremity-FIN": ["Study-FIN", "FU-FIN", "Number of Patients-Extremity-FIN", "Preliminary Data"], "Summary Device-extremity-FIN": ["Study-FIN", "Device-Extremity-FIN", "Preliminary Data"], "bone-V-extremity-FIN": ["Bone Graft-FIN", "bone-H1-extremity", "Number of Patients-Extremity-FIN", "Study-FIN", "bone-H2-extremity", "studyN-H1-extremity", "Preliminary Data", "bone-H3-extremity", "bone-H4-extremity"], "app-V-extremity-FIN": ["Approach-FIN", "Number of Patients-Extremity-FIN", "app-H1-extremity", "Study-FIN", "studyN-H1-extremity", "app-H2-extremity", "Preliminary Data", "app-H3-extremity", "app-H4-extremity"], "pro-V-extremity-FIN": ["Procedure-Extremity-FIN", "Number of Patients-Extremity-FIN", "pro-H1-extremity", "Study-FIN", "studyN-H1-extremity", "pro-H2-extremity", "Preliminary Data", "pro-H3-extremity", "pro-H4-extremity"], "type-V-extremity-FIN": ["Number of Patients-Extremity-FIN", "type-H1-extremity", "Study-FIN", "studyN-H1-extremity", "type-H2-extremity", "Preliminary Data", "type-H3-extremity", "type-H4-extremity"], "ind-V-extremity-FIN": ["Indication Categories-Extremity-FIN", "Number of Patients-Extremity-FIN", "ind-H1-extremity", "Study-FIN", "studyN-H1-extremity", "ind-H2-extremity", "Preliminary Data", "ind-H3-extremity", "ind-H4-extremity"], "gen-V-extremity-FIN": ["Number of Patients-Extremity-FIN", "Gender-FIN", "studyN-H1-extremity", "gen-H1-extremity", "Study-FIN", "gen-H2-extremity", "Preliminary Data", "gen-H3-extremity"], "ske-V-extremity-FIN": ["DAskemat-FIN", "Number of Patients-Extremity-FIN", "ske-H1-extremity", "Study-FIN", "studyN-H1-extremity", "ske-H2-extremity", "Preliminary Data", "ske-H3-extremity", "ske-H4-extremity"], "loco-V-extremity-FIN": ["Location-Extremity-FIN", "", "loco-H1-extremity", "Number of Patients-Extremity-FIN", "Study-FIN", "loco-H3-extremity", "loco-H2-extremity", "studyN-H1-extremity", "Preliminary Data", "loco-H4-extremity"], "DAproc-H0-spine-FIN": ["DAprocedure-Spine-FIN"], "DAproc-V-spine-FIN": ["Study-FIN", "Daproc-H1-spine", "Preliminary Data", "DAproc-H2-spine", "DAproc-H3-spine"], "DAproc-H0-extremity-FIN": ["DAprocedure-Extremity-FIN"], "DAproc-V-extremity-FIN": ["Study-FIN", "Daproc-H1-extremity", "Preliminary Data", "DAproc-H2-extremity", "DAproc-H3-extremity"], "DAdatcoll-H0-spine-FIN": ["DAdatcoll-FIN"], "DAdatcoll-V-spine-FIN": ["Number of Patients-Spine-FIN", "studyN-H1-spine", "DAdatcoll-FIN", "DAdatcoll-H1-spine", "Study-FIN", "DAdatcoll-H2-spine", "Preliminary Data", "DAdatcoll-H3-spine"], "DAdatsor-H0-spine-FIN": ["DAdatsource-FIN"], "DAdatsor-V-spine-FIN": ["Number of Patients-Spine-FIN", "studyN-H1-spine", "DAdatsource-FIN", "DAdatsor-H1-spine", "Study-FIN", "DAdatsor-H2-spine", "Preliminary Data", "DAdatsor-H3-spine"], "DAperf-H0-spine-FIN": ["DAperf-FIN"], "DAperf-V-spine-FIN": ["Number of Patients-Spine-FIN", "studyN-H1-spine", "DAperf-FIN", "DAperf-H1-spine", "Study-FIN", "DAperf-H2-spine", "Preliminary Data", "DAperf-H3-spine"], "DAsaf-H0-spine-FIN": ["DAsaf-FIN"], "DAsaf-V-spine-FIN": ["Number of Patients-Spine-FIN", "studyN-H1-spine", "DAsaf-FIN", "DAsaf-H1-spine", "Study-FIN", "DAsaf-H2-spine", "Preliminary Data", "DAsaf-H3-spine"], "DAsufFU-H0-spine-FIN": ["DAsufFU-FIN"], "DAsufFU-V-spine-FIN": ["Number of Patients-Spine-FIN", "studyN-H1-spine", "DAsufFU-FIN", "DAsufFU-H1-spine", "Study-FIN", "DAsufFU-H2-spine", "Preliminary Data", "DAsufFU-H3-spine"], "DAdatcoll-H0-extremity-FIN": ["DAdatcoll-FIN"], "DAdatcoll-V-extremity-FIN": ["Number of Patients-Extremity-FIN", "studyN-H1-extremity", "DAdatcoll-FIN", "DAdatcoll-H1-extremity", "Study-FIN", "DAdatcoll-H2-extremity", "Preliminary Data", "DAdatcoll-H3-extremity"], "DAdatsor-H0-extremity-FIN": ["DAdatsource-FIN"], "DAdatsor-V-extremity-FIN": ["Number of Patients-Extremity-FIN", "studyN-H1-extremity", "DAdatsource-FIN", "DAdatsor-H1-extremity", "Study-FIN", "DAdatsor-H2-extremity", "Preliminary Data", "DAdatsor-H3-extremity"], "DAperf-H0-extremity-FIN": ["DAperf-FIN"], "DAperf-V-extremity-FIN": ["Number of Patients-Extremity-FIN", "studyN-H1-extremity", "DAperf-FIN", "DAperf-H1-extremity", "Study-FIN", "DAperf-H2-extremity", "Preliminary Data", "DAperf-H3-extremity"], "DAsaf-H0-extremity-FIN": ["DAsaf-FIN"], "DAsaf-V-extremity-FIN": ["Number of Patients-Extremity-FIN", "studyN-H1-extremity", "DAsaf-FIN", "DAsaf-H1-extremity", "Study-FIN", "DAsaf-H2-extremity", "Preliminary Data", "DAsaf-H3-extremity"], "DAsufFU-H0-extremity-FIN": ["DAsufFU-FIN"], "DAsufFU-V-extremity-FIN": ["Number of Patients-Extremity-FIN", "studyN-H1-extremity", "DAsufFU-FIN", "DAsufFU-H1-extremity", "Study-FIN", "DAsufFU-H2-extremity", "Preliminary Data", "DAsufFU-H3-extremity"]}
.data/summary_prompts.json ADDED
The diff for this file is too large to render. See raw diff
 
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: AMRA Studies demo
3
  emoji: 👀
4
  colorFrom: blue
5
  colorTo: cyan
@@ -9,42 +9,29 @@ app_file: app.py
9
  pinned: false
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
13
-
14
  ## AMRA Studies demo
 
15
  AMRA Studies demo contains the functionality to utilize LLM and cofounder heuristic knowledge to process one
16
  or multiple studies and return the results in a structured format.
17
 
18
- It was deployed in huggingface spaces and can be accessed through here: https://amra-ai.com
19
 
20
  ### Introduction
 
21
  In medical device industry, process of clinical studies is a crucial step to get validation of the product.
22
  The process is very time consuming and requires a lot of manual work. The goal of this project is to automate
23
  the process of clinical studies by utilizing LLM and cofounder heuristic knowledge.
24
 
25
  ### To host the demo locally
 
26
  1. Clone the repo
27
  2. Install the requirements
28
- ```
29
- pip install -r requirements.txt
30
- ```
31
- 3. Run the app.py file
32
- ```
33
- python app.py
34
- ```
35
-
36
- ### To use the demo
37
- 1. Log into https://amra-ai.com
38
- 2. Select the studies from the sidebar
39
- 3. Upload the study file
40
- 4. Click on the "Add" button
41
-
42
- ### Demo
43
-
44
- <iframe src="https://amra-ai-studies.hf.space"><iframe>
45
 
 
46
 
47
  ### Limitations and bias
 
48
  Currently the demo is only validated for the studies in the following anatomical regions:
 
49
  + Spine
50
- + Extremity
 
1
  ---
2
+ title: AMRA Summary demo
3
  emoji: 👀
4
  colorFrom: blue
5
  colorTo: cyan
 
9
  pinned: false
10
  ---
11
 
 
 
12
  ## AMRA Studies demo
13
+
14
  AMRA Studies demo contains the functionality to utilize LLM and cofounder heuristic knowledge to process one
15
  or multiple studies and return the results in a structured format.
16
 
17
+ It was deployed in huggingface spaces and can be accessed through here: [AMRA-AI](https://amra-ai.com)
18
 
19
  ### Introduction
20
+
21
  In medical device industry, process of clinical studies is a crucial step to get validation of the product.
22
  The process is very time consuming and requires a lot of manual work. The goal of this project is to automate
23
  the process of clinical studies by utilizing LLM and cofounder heuristic knowledge.
24
 
25
  ### To host the demo locally
26
+
27
  1. Clone the repo
28
  2. Install the requirements
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
+ To access the demo, please visit: [AMRA-AI Studies](https://amra-ai-studies.hf.space)
31
 
32
  ### Limitations and bias
33
+
34
  Currently the demo is only validated for the studies in the following anatomical regions:
35
+
36
  + Spine
37
+ + Extremity
app.py CHANGED
@@ -14,8 +14,8 @@ examples = []
14
 
15
  def create_demo():
16
  return gr.TabbedInterface(
17
- [summary_page(),articles_page()],
18
- ["Summary","Articles"],
19
  theme = gr.themes.Soft(primary_hue="sky",secondary_hue="orange"),
20
  title="AMRA AI Medi Reader",
21
  css = "footer {visibility: hidden}",
 
14
 
15
  def create_demo():
16
  return gr.TabbedInterface(
17
+ [summary_page(),articles_page(),preference_page()],
18
+ ["Summary","Articles","User Preferences"],
19
  theme = gr.themes.Soft(primary_hue="sky",secondary_hue="orange"),
20
  title="AMRA AI Medi Reader",
21
  css = "footer {visibility: hidden}",
application.py CHANGED
@@ -90,6 +90,7 @@ app_data = {
90
  "terms":[],
91
  "summary":{},
92
  "user":{
 
93
  "performance outcome #1":{"assessment_step":"Clinical"},
94
  "performance outcome #2":{"assessment_step":"Clinical"},
95
  "safety outcome #1":{},
 
90
  "terms":[],
91
  "summary":{},
92
  "user":{
93
+ "summary":{"articles":[]},
94
  "performance outcome #1":{"assessment_step":"Clinical"},
95
  "performance outcome #2":{"assessment_step":"Clinical"},
96
  "safety outcome #1":{},
backend_update.ipynb CHANGED
The diff for this file is too large to render. See raw diff
 
chains.py CHANGED
@@ -2,43 +2,49 @@ import asyncio
2
  import openai
3
 
4
  from langchain.chat_models import ChatOpenAI
 
5
  from langchain.prompts.chat import ChatPromptTemplate
6
- from langchain.schema import BaseOutputParser
7
  from application import *
8
 
9
- from utility import read_pdf,terminal_print
10
 
11
- class Replacement(BaseOutputParser):
12
- """Parse the output of an LLM call to a comma-separated list."""
 
 
13
 
 
14
 
15
- def parse(self, text: str, **kwargs):
16
- """Parse the output of an LLM call."""
17
- if kwargs:
18
- print(kwargs)
19
- return text.strip().split(", ")
20
 
21
- @terminal_print # need to review this.
 
 
 
 
 
 
 
 
22
  async def async_generate(article,name,chain,replacement_term=None):
23
  if replacement_term:
24
- resp = await chain.ainvoke({"term":replacement_term})
25
  else:
26
- resp = await chain.ainvoke({"term":""})
27
- article[name] = resp.content
 
 
28
 
29
- @terminal_print # need to review this.
 
30
  async def execute_concurrent(article,prompts):
31
- llm = ChatOpenAI(
32
- temperature=0.0,
33
- model_name="gpt-3.5-turbo-16k",
34
- openai_api_key=openai.api_key)
35
  tasks = []
36
 
37
  prompt_type = article["logic"]
38
  prompt_list = list(prompts.keys())
39
- print(prompt_list)
40
 
41
- # for name,p in prompts.items():
42
  while prompt_list:
43
  name = prompt_list.pop(0)
44
  p = prompts[name]
@@ -46,16 +52,14 @@ async def execute_concurrent(article,prompts):
46
  missing_inputs = [s for s in p["input_list"] if s not in article]
47
  for x in missing_inputs:
48
  await execute_concurrent(article,{x:app_data["prompts"][x]})
49
-
50
- # if any([s not in article for s in p["input_list"]]):
51
- # # prompt_list.append(name)
52
- # print("skip",name,"due to missing input",p["input_list"])
53
- # continue
54
 
55
  print("executing",p["assessment_step"],name)
56
  input_text = "".join([article[s] for s in p["input_list"]])
57
-
 
 
58
  chat_prompt = ChatPromptTemplate.from_messages([
 
59
  ("human",input_text),
60
  ("system",p[prompt_type]),
61
  ])
@@ -90,16 +94,10 @@ if __name__ == "__main__":
90
  sample_content,_ = read_pdf(sample_artice)
91
 
92
  llm = ChatOpenAI(temperature=0.0,model_name="gpt-3.5-turbo-16k")
93
- # with open(".prompts/other/Need for ICU.txt") as f:
94
- # prompt = f.read()
95
- # name = "Need for ICU"
96
  with open(".prompts/other/Operation Time.txt") as f:
97
  prompt = f.read()
98
  name = "Operation Time"
99
- # with open(".prompts/other/Blood Loss.txt") as f:
100
- # prompt = f.read()
101
- # name = "Blood Loss"
102
-
103
  post_prompt_maping = {}
104
  post_replace_term = lambda res,map=post_prompt_maping:replace_term(res,map=map)
105
 
 
2
  import openai
3
 
4
  from langchain.chat_models import ChatOpenAI
5
+ from langchain.chat_models.openai import _create_retry_decorator
6
  from langchain.prompts.chat import ChatPromptTemplate
7
+ # from langchain.schema import BaseOutputParser
8
  from application import *
9
 
10
+ from utility import read_pdf,aterminal_print
11
 
12
+ llm = ChatOpenAI(
13
+ temperature=0.0,
14
+ model_name="gpt-3.5-turbo-16k",
15
+ openai_api_key=openai.api_key)
16
 
17
+ retry_decorator = _create_retry_decorator(llm)
18
 
 
 
 
 
 
19
 
20
+ # class Replacement(BaseOutputParser):
21
+ # """Parse the output of an LLM call to a comma-separated list."""
22
+ # def parse(self, text: str, **kwargs):
23
+ # """Parse the output of an LLM call."""
24
+ # if kwargs:
25
+ # print(kwargs)
26
+ # return text.strip().split(", ")
27
+
28
+ @aterminal_print # need to review this.
29
  async def async_generate(article,name,chain,replacement_term=None):
30
  if replacement_term:
31
+ res = await chain.ainvoke({"term":replacement_term})
32
  else:
33
+ res = await chain.ainvoke({"term":""})
34
+
35
+ print("completed",name)
36
+ article[name] = res.content
37
 
38
+ @aterminal_print # need to review this.
39
+ @retry_decorator
40
  async def execute_concurrent(article,prompts):
41
+
 
 
 
42
  tasks = []
43
 
44
  prompt_type = article["logic"]
45
  prompt_list = list(prompts.keys())
 
46
 
47
+ i = 0
48
  while prompt_list:
49
  name = prompt_list.pop(0)
50
  p = prompts[name]
 
52
  missing_inputs = [s for s in p["input_list"] if s not in article]
53
  for x in missing_inputs:
54
  await execute_concurrent(article,{x:app_data["prompts"][x]})
 
 
 
 
 
55
 
56
  print("executing",p["assessment_step"],name)
57
  input_text = "".join([article[s] for s in p["input_list"]])
58
+ # with open(f".outputs/{i}_{name}.txt","w+") as f:
59
+ # f.write(input_text)
60
+ # f.write(p[prompt_type])
61
  chat_prompt = ChatPromptTemplate.from_messages([
62
+ ("system","You are a helpful AI that can answer questions about clinical trail and operation studies."),
63
  ("human",input_text),
64
  ("system",p[prompt_type]),
65
  ])
 
94
  sample_content,_ = read_pdf(sample_artice)
95
 
96
  llm = ChatOpenAI(temperature=0.0,model_name="gpt-3.5-turbo-16k")
 
 
 
97
  with open(".prompts/other/Operation Time.txt") as f:
98
  prompt = f.read()
99
  name = "Operation Time"
100
+
 
 
 
101
  post_prompt_maping = {}
102
  post_replace_term = lambda res,map=post_prompt_maping:replace_term(res,map=map)
103
 
cloud_db.py CHANGED
@@ -17,8 +17,12 @@ dynamodb data operations
17
  # get the list of articles from articles table in dynamodb
18
  @terminal_print
19
  def get_table(table_name:str):
20
- result = db_client.scan(TableName = table_name)#,AttributesToGet = data_structure[table_name]["fields"])
21
- return [db_map_to_py_dict(r) for r in result["Items"]]
 
 
 
 
22
 
23
  # add a new article to table articles in dynamodb, return error if failed
24
  def post_item(table_name:str,item:dict):
 
17
  # get the list of articles from articles table in dynamodb
18
  @terminal_print
19
  def get_table(table_name:str):
20
+ result = db_client.scan(TableName = table_name)
21
+ items = result["Items"]
22
+ while "LastEvaluatedKey" in result:
23
+ result = db_client.scan(TableName = table_name,ExclusiveStartKey = result["LastEvaluatedKey"])
24
+ items.extend(result["Items"])
25
+ return [db_map_to_py_dict(r) for r in items]
26
 
27
  # add a new article to table articles in dynamodb, return error if failed
28
  def post_item(table_name:str,item:dict):
cloud_textract.py DELETED
@@ -1,227 +0,0 @@
1
- import boto3
2
-
3
- from utility import terminal_print, create_md_table
4
- from application import aws_access_key_id, aws_secret_access_key, default_s3_bucket
5
-
6
- textract = boto3.client(
7
- 'textract',
8
- aws_access_key_id=aws_access_key_id,
9
- aws_secret_access_key=aws_secret_access_key,
10
- region_name='us-east-1')
11
-
12
- @terminal_print
13
- def textract_get_tables(res_tables,textract=textract):
14
- '''
15
- This function is used to get the tables from the textract output
16
-
17
- Parameters:
18
- res_tables: the output from the textract.get_document_analysis function
19
- textract: the boto3 client for textract
20
-
21
- Returns:
22
- result: the cascaded output with blocks from the textract.get_document_analysis function
23
- '''
24
- job_id = res_tables["JobId"]
25
- temp = result = res_tables.copy()
26
-
27
- while "NextToken" in temp:
28
- temp = textract.get_document_analysis(JobId=job_id,NextToken=temp["NextToken"])
29
- result["Blocks"].extend(temp["Blocks"])
30
-
31
- return result
32
-
33
- @terminal_print
34
- def textract_get_text(res_text,textract=textract):
35
- '''
36
- This function is used to get the text from the textract output
37
-
38
- Parameters:
39
- res_text: the output from the textract.get_document_text_detection function
40
- textract: the boto3 client for textract
41
-
42
- Returns:
43
- result: the cascaded output with blocks from the textract.get_document_text_detection function
44
- '''
45
- job_id = res_text["JobId"]
46
- temp = result = res_text.copy()
47
-
48
- while "NextToken" in temp:
49
- temp = textract.get_document_text_detection(JobId=job_id,NextToken=temp["NextToken"])
50
- result["Blocks"].extend(temp["Blocks"])
51
-
52
- return result
53
-
54
- @terminal_print
55
- def get_article_tables(file_name:str,bucket:str,delay:int=5):
56
- '''
57
- This function is used to get the tables from the textract output
58
-
59
- Parameters:
60
- file_name: the name of the file in the bucket
61
- bucket: the name of the bucket
62
- delay: the delay time for the textract.get_document_analysis function
63
-
64
- Returns:
65
- res_tables: the output from the textract.get_document_analysis function with initial blocks
66
- '''
67
- import time
68
- # need to use async method to process the files
69
- job_tables = textract.start_document_analysis(
70
- DocumentLocation={
71
- "S3Object":{
72
- "Bucket":bucket,
73
- "Name": file_name
74
- }
75
- },
76
- FeatureTypes=["TABLES"]
77
- )
78
-
79
- table_job_id = job_tables["JobId"]
80
- res_tables = {"JobStatus":"IN_PROGRESS"}
81
-
82
- while res_tables["JobStatus"] == "IN_PROGRESS":
83
- time.sleep(delay)
84
- res_tables = textract.get_document_analysis(JobId=table_job_id)
85
-
86
- res_tables["JobId"] = table_job_id
87
-
88
- return res_tables
89
-
90
- @terminal_print
91
- def get_article_text(file_name:str,bucket:str,delay:int=5):
92
- '''
93
- This function is used to get the text from the textract output
94
-
95
- Parameters:
96
- file_name: the name of the file in the bucket
97
- bucket: the name of the bucket
98
- delay: the delay time for the textract.get_document_text_detection function
99
-
100
- Returns:
101
- res_text: the output from the textract.get_document_text_detection function with initial blocks
102
- '''
103
- import time
104
- job_text = textract.start_document_text_detection(
105
- DocumentLocation={
106
- "S3Object":{
107
- "Bucket":bucket,
108
- "Name": file_name
109
- }
110
- }
111
- )
112
-
113
- text_job_id = job_text["JobId"]
114
- res_text = {"JobStatus":"IN_PROGRESS"}
115
-
116
- while res_text["JobStatus"] == "IN_PROGRESS":
117
- time.sleep(delay)
118
- if res_text["JobStatus"] == "IN_PROGRESS":
119
- res_text = textract.get_document_text_detection(JobId=text_job_id)
120
-
121
-
122
- res_text["JobId"] = text_job_id
123
-
124
- return res_text
125
-
126
- @terminal_print
127
- def construct_tables(tables):
128
- '''
129
- This function is used to construct the tables from the textract output
130
-
131
- Parameters:
132
- tables: the output from the textract.get_document_analysis function
133
-
134
- Returns:
135
- table_blocks: the list of tables with the blocks
136
- blocks_dict: the dictionary of blocks with the block id as the key
137
- '''
138
- blocks = tables["Blocks"]
139
-
140
- blocks_dict = {}
141
- table_blocks = []
142
-
143
- for b in blocks:
144
-
145
- blocks_dict[b["Id"]] = b
146
-
147
- if b["BlockType"] == "TABLE":
148
- temp = {
149
- "id":b["Id"],
150
- "relationship":b["Relationships"],
151
- "confidence":b["Confidence"],
152
- "page":b["Page"],
153
- "map":{}
154
- }
155
- table_blocks.append(temp)
156
-
157
- for t in table_blocks:
158
- for e in t["relationship"]:
159
- t["map"].update({id:{"Type":e["Type"]} for id in e["Ids"]})
160
-
161
- for id in t["map"]:
162
- component = blocks_dict[id]
163
- if component["BlockType"] not in t:
164
- t[component["BlockType"]] = []
165
- t[component["BlockType"]].append(component)
166
-
167
- # table_blocks.append(t)
168
-
169
- return table_blocks, blocks_dict
170
-
171
- # Transfer the table blocks from aws textract into a table
172
- @terminal_print
173
- def textract_output_to_table(table,blocks_dict):
174
- '''
175
- This function is used to transfer the table blocks from aws textract into a table
176
-
177
- Parameters:
178
- table: the table block from the textract output
179
- blocks_dict: the dictionary of blocks with the block id as the key
180
-
181
- Returns:
182
- array: the table array with the text from the table blocks
183
- '''
184
- array = [[]]
185
- cur_row = 1
186
- for c in table["CELL"]:
187
- r_id = c["RowIndex"]
188
-
189
- if r_id > cur_row:
190
- array.append([])
191
- cur_row = r_id
192
- if "Relationships" in c:
193
- words = [blocks_dict[i]["Text"] for i in c["Relationships"][0]["Ids"] if blocks_dict[i]["BlockType"] == "WORD"]
194
- else:
195
- words =[""]
196
- # print(c["RowIndex"],c["ColumnIndex"]," ".join(words))
197
- array[-1].append(" ".join(words))
198
-
199
- return array
200
-
201
- @terminal_print
202
- def get_tables(filename:str,bucket:str=default_s3_bucket):
203
- '''
204
- This function is used to get the tables from the textract output
205
-
206
- Parameters:
207
- filename: the name of the file in the bucket
208
- bucket: the name of the bucket
209
-
210
- Returns:
211
- md_tables: the list of tables in markdown format
212
- '''
213
- tables_temp = get_article_tables(file_name=filename,bucket=bucket)
214
-
215
- tables = textract_get_tables(tables_temp)
216
- table_blocks,block_dict = construct_tables(tables)
217
-
218
- md_tables = []
219
- for table in table_blocks:
220
- table_array = textract_output_to_table(table,block_dict)
221
- md_tables.append(create_md_table(table_array))
222
-
223
- return md_tables
224
-
225
-
226
-
227
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
features.py CHANGED
@@ -13,11 +13,8 @@ from langchain.chains import LLMChain
13
  from chains import *
14
  from cloud_db import *
15
  from cloud_storage import *
16
- from cloud_textract import *
17
  from supplier import *
18
  from utility import list_dict_to_dict
19
- from application import *
20
- # from features_beta import *
21
 
22
  # get prompts, terms, outputs from the cloud
23
  @terminal_print
@@ -38,6 +35,9 @@ def init_app_data():
38
  app_data["terms"] = get_table("terms")
39
  app_data["articles"] = list_dict_to_dict(get_table("articles"),key="name")
40
  app_data["summary"] = list_dict_to_dict(get_table("summary"),key="term")
 
 
 
41
 
42
  @terminal_print
43
  def get_existing_article(
@@ -61,6 +61,12 @@ def get_existing_article(
61
 
62
  return create_overview(article), create_detail_views(article)
63
 
 
 
 
 
 
 
64
  @terminal_print
65
  def process_study( # need revision
66
  domain,
@@ -69,10 +75,7 @@ def process_study( # need revision
69
  ):
70
 
71
  if study_file_obj:
72
- if type(study_file_obj) is list:
73
- article = add_article(domain,study_file_obj[0])
74
- else:
75
- article = add_article(domain,study_file_obj)
76
  elif study_content:
77
  article = add_article(domain,study_content,file_object=False)
78
  else:
@@ -83,9 +86,13 @@ def process_study( # need revision
83
 
84
  # perform pathway logic and content extraction
85
  process_prompts(article=article)
 
 
 
86
 
87
  # set the current article to the completed article object
88
  app_data["current_article"] = article
 
89
 
90
  # update the article to the cloud
91
  try:
@@ -100,6 +107,29 @@ def process_study( # need revision
100
 
101
  return overview, detail_views
102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  @terminal_print
104
  def update_article_segment(article):
105
  # get the key content between article objective and discussion
@@ -121,8 +151,7 @@ def update_article_segment(article):
121
  "Material and Methods": materials_and_methods,
122
  "Results": results,
123
  "Meta Content": meta_content,
124
- "tables": get_tables(article["name"]),
125
-
126
  })
127
 
128
  # add the key content as an aggregation of the other sections
@@ -146,13 +175,13 @@ def update_article_segment(article):
146
  tasks.append(get_segments(article,article_prompts))
147
  asyncio.gather(*tasks,return_exceptions=True)
148
 
149
- @terminal_print # need to review this.
150
  async def gen_segment(article,name,chain):
151
 
152
  resp = await chain.ainvoke({"term":""})
153
  article[name] = resp.content #["content"]
154
 
155
- @terminal_print # need to review this.
156
  async def get_segments(article,prompts):
157
  llm = ChatOpenAI(
158
  temperature=0.0,
@@ -341,7 +370,12 @@ def add_article(domain,file,add_to_s3=True, add_to_local=True, file_object=True)
341
  else:
342
  # extract the content from the pdf file
343
  content, _ = read_pdf(file)
344
- filename = file.name.split("\\")[-1]
 
 
 
 
 
345
 
346
  # upload the article to s3
347
  pdf_obj = open(file.name, 'rb')
@@ -467,7 +501,8 @@ def select_overview_prompts(article):
467
  if validate_term(article,t,"overview"):
468
  # add the prompts to the memory
469
  valid_prompts.update(t["prompts_list"])
470
- article["extraction"]["overview"] = valid_prompts.copy()
 
471
 
472
  return {p:app_data["prompts"][p] for p in valid_prompts}
473
 
@@ -494,8 +529,8 @@ def select_performance_prompts(article,performance_assessment):
494
  else:
495
  valid_prompts[p]["term"].update({t["term"]:t})
496
  if performance_assessment not in article["extraction"]:
497
- article["extraction"][performance_assessment] = []
498
- article["extraction"][performance_assessment].append(prompt["prompt_name"])
499
 
500
  return valid_prompts
501
 
@@ -625,6 +660,32 @@ def run_executor(article,prompt):
625
  case "f_summary_term":
626
  f_summary_term(article,prompt)
627
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
628
 
629
  def add_inst(instructions,prompt):
630
  return instructions + prompt
 
13
  from chains import *
14
  from cloud_db import *
15
  from cloud_storage import *
 
16
  from supplier import *
17
  from utility import list_dict_to_dict
 
 
18
 
19
  # get prompts, terms, outputs from the cloud
20
  @terminal_print
 
35
  app_data["terms"] = get_table("terms")
36
  app_data["articles"] = list_dict_to_dict(get_table("articles"),key="name")
37
  app_data["summary"] = list_dict_to_dict(get_table("summary"),key="term")
38
+ with open(".data/instruction_agg_performance.json","r") as f:
39
+ prompts_agg_json = json.load(f)
40
+ app_data["prompts_agg"] = list_dict_to_dict(prompts_agg_json,key="assessment")
41
 
42
  @terminal_print
43
  def get_existing_article(
 
61
 
62
  return create_overview(article), create_detail_views(article)
63
 
64
+ @terminal_print
65
+ def generate_summary():
66
+ articles = app_data["user"]["summary"]["articles"]
67
+
68
+ pass
69
+
70
  @terminal_print
71
  def process_study( # need revision
72
  domain,
 
75
  ):
76
 
77
  if study_file_obj:
78
+ article = add_article(domain,study_file_obj)
 
 
 
79
  elif study_content:
80
  article = add_article(domain,study_content,file_object=False)
81
  else:
 
86
 
87
  # perform pathway logic and content extraction
88
  process_prompts(article=article)
89
+
90
+ # perform a post process for perfFUTables
91
+ post_process(article)
92
 
93
  # set the current article to the completed article object
94
  app_data["current_article"] = article
95
+ app_data["articles"][article["name"]] = article
96
 
97
  # update the article to the cloud
98
  try:
 
107
 
108
  return overview, detail_views
109
 
110
+ @terminal_print
111
+ def process_studies(
112
+ domain,
113
+ file_objs):
114
+
115
+ for file_obj in file_objs:
116
+ process_study(domain,file_obj,None)
117
+ return gr.update(value=create_md_tables(app_data["articles"]))
118
+
119
+ @terminal_print
120
+ def create_md_tables(articles):
121
+ '''
122
+ create markdown tables for the articles.
123
+ '''
124
+ md_text = ""
125
+ md_text += "| Article Name | Authors | Domain | Upload Time |\n| --- | --- | --- | --- |\n"
126
+
127
+ for name, article in articles.items():
128
+ md_table = f"| {name} | {article['Authors']} |{article['domain']} | {article['upload_time']} | \n"
129
+ md_text += md_table
130
+
131
+ return md_text
132
+
133
  @terminal_print
134
  def update_article_segment(article):
135
  # get the key content between article objective and discussion
 
151
  "Material and Methods": materials_and_methods,
152
  "Results": results,
153
  "Meta Content": meta_content,
154
+ "tables": ""
 
155
  })
156
 
157
  # add the key content as an aggregation of the other sections
 
175
  tasks.append(get_segments(article,article_prompts))
176
  asyncio.gather(*tasks,return_exceptions=True)
177
 
178
+ @aterminal_print # need to review this.
179
  async def gen_segment(article,name,chain):
180
 
181
  resp = await chain.ainvoke({"term":""})
182
  article[name] = resp.content #["content"]
183
 
184
+ @aterminal_print # need to review this.
185
  async def get_segments(article,prompts):
186
  llm = ChatOpenAI(
187
  temperature=0.0,
 
370
  else:
371
  # extract the content from the pdf file
372
  content, _ = read_pdf(file)
373
+ if "\\" in file.name:
374
+ filename = file.name.split("\\")[-1]
375
+ elif "/" in file.name:
376
+ filename = file.name.split("/")[-1]
377
+ else:
378
+ filename = file.name
379
 
380
  # upload the article to s3
381
  pdf_obj = open(file.name, 'rb')
 
501
  if validate_term(article,t,"overview"):
502
  # add the prompts to the memory
503
  valid_prompts.update(t["prompts_list"])
504
+ sorted_prompts = sorted(valid_prompts,key=lambda x:app_data["prompts"][x]["section_sequence"])
505
+ article["extraction"]["overview"] = sorted_prompts
506
 
507
  return {p:app_data["prompts"][p] for p in valid_prompts}
508
 
 
529
  else:
530
  valid_prompts[p]["term"].update({t["term"]:t})
531
  if performance_assessment not in article["extraction"]:
532
+ article["extraction"][performance_assessment] = set()
533
+ article["extraction"][performance_assessment].add(prompt["prompt_name"])
534
 
535
  return valid_prompts
536
 
 
660
  case "f_summary_term":
661
  f_summary_term(article,prompt)
662
 
663
+ @retry_decorator
664
+ @terminal_print
665
+ def post_process(article):
666
+ post_inputs = {}
667
+ for assessment,segements in article["extraction"].items():
668
+ if assessment == "overview":
669
+ continue
670
+ post_inputs[assessment] = "\n".join([article[s] for s in segements])
671
+
672
+ template = ChatPromptTemplate.from_messages([
673
+ ("human","{text}"),
674
+ ("system","From the text above {instruction}"),
675
+ ])
676
+
677
+ llm = ChatOpenAI(
678
+ temperature=0.0,
679
+ model_name="gpt-3.5-turbo-16k",
680
+ openai_api_key=openai.api_key)
681
+
682
+ chain = template | llm
683
+
684
+ for assessment,post_input in post_inputs.items():
685
+ instruction_agg = app_data["prompts_agg"][assessment]
686
+ article[instruction_agg["name"]] = chain.invoke({"text":post_input,"instruction":instruction_agg["chain"][0]}).content
687
+ article["extraction"][assessment].add(instruction_agg["name"])
688
+
689
 
690
  def add_inst(instructions,prompt):
691
  return instructions + prompt
hand_chains.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import json
3
+
4
+ from collections import deque
5
+ from application import app_data
6
+ from langchain.prompts import ChatPromptTemplate
7
+ from chains import llm, retry_decorator
8
+ from utility import list_dict_to_dict
9
+ from pydantic import BaseModel, Field
10
+ from typing import List, Dict, Optional
11
+
12
+ # manual create chain objects
13
+ with open(".data/summary_prompts.json","r") as f:
14
+ overview_summary = json.load(f)
15
+ overview_summary = list_dict_to_dict(overview_summary,"name")
16
+
17
+
18
+ class Instruction(BaseModel):
19
+ name: str
20
+ inputs: List[str]
21
+ instruction: str
22
+
23
+ def execute_chain(instruction,articles): # target shall be the object of the summary instruction
24
+ # a recursive function to generate the chain object for llm execution
25
+ # it will recursively create the chain object for each prompt required from article object
26
+ if all([instruction.name in article for article in articles]):
27
+ return
28
+
29
+ for i in instruction.inputs:
30
+ for article in articles:
31
+ if i not in article:
32
+ execute_chain(overview_summary[i],articles)
33
+
34
+
35
+ def gen_node(name):
36
+ instruction = app_data["summary"][name]["instruction"]
37
+
38
+ prompt = ChatPromptTemplate.from_messages(
39
+ ("system", "{content}"),
40
+ ("system",f"{instruction}")
41
+ )
42
+
43
+ node = prompt | llm
44
+ return {name:node}
requirements.txt CHANGED
@@ -1,9 +1,6 @@
1
- gradio
2
- pandas
3
- PyPDF2
4
- boto3
5
- requests
6
- openai
7
- pdfminer.six
8
- tiktoken
9
- langchain
 
1
+ gradio==3.35.2
2
+ boto3==1.26.165
3
+ openai==0.27.8
4
+ pdfminer.six==20221105
5
+ tiktoken==0.4.0
6
+ langchain==0.0.338
 
 
 
ui_studies.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+
3
+ from application import *
4
+ from features import init_app_data,process_studies,create_md_tables
5
+ from utility import terminal_print
6
+
7
+ def refresh():
8
+ init_app_data()
9
+ '''
10
+ refresh the literature report.
11
+ '''
12
+ return create_md_tables(app_data["articles"])
13
+
14
+ @terminal_print
15
+ def init_studies_page():
16
+ with gr.Blocks() as studies_page:
17
+ with gr.Row(equal_height=False):
18
+ with gr.Column():
19
+ gr.Markdown("## Clinical Studies")
20
+ domain = gr.Radio(label="Anatomical Region",choices=anatomic_domains,value=default_region)
21
+ upload_studies = gr.File(label="Upload clinical study reports",type="file",file_count="multiple")
22
+ btn_upload_studies = gr.Button(value="Upload",variant="primary")
23
+ with gr.Column():
24
+ gr.Markdown("## Article Lists")
25
+ btn_refresh = gr.Button(value="Refresh",variant="primary")
26
+ gr.HTML("<hr>")
27
+ article_list = gr.Markdown("")
28
+
29
+ btn_upload_studies.click(
30
+ process_studies,
31
+ inputs=[
32
+ domain,
33
+ upload_studies,
34
+ ],
35
+ outputs=[
36
+ article_list,
37
+ ],
38
+ )
39
+
40
+ btn_refresh.click(
41
+ fn=refresh,
42
+ outputs=[article_list]
43
+ )
44
+ return studies_page
ui_summary.py CHANGED
@@ -1,36 +1,76 @@
1
  import gradio as gr
2
- import pandas as pd
3
 
4
  from utility import *
5
  from application import *
6
- from features import init_app_data # , add_device, remove_device, get_device
7
- # from features_beta import *
8
 
9
-
10
- def refresh(selected_article):
11
  init_app_data()
12
  '''
13
  refresh the literature report.
14
  '''
15
- return create_md_tables(app_data["articles"]),app_data["articles"][selected_article]
16
 
17
  def articles_page():
18
 
19
  with gr.Blocks() as tab_page:
20
- fields = ["name","domain","Authors","Acceptance Year","Acceptance Month"]
21
-
22
- df_articles = pd.DataFrame(app_data["articles"],columns=fields)
23
- gr.DataFrame(df_articles)
24
-
 
 
 
 
25
  return tab_page
26
 
27
- def summary_page():
28
  with gr.Blocks() as tab_page:
29
  render_custom_performance()
30
  render_custom_safety()
31
 
32
  return tab_page
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  def render_custom_performance():
35
  with gr.Blocks():
36
  render_performance_row("Performance Outcome #1",show_header=True)
@@ -75,17 +115,16 @@ def render_performance_row(row_name, show_header=False):
75
  label="Units",
76
  choices = defaults["units"])
77
 
78
- assessment_step.change(fn=lambda value: update_user_performance(value,"assessment_step",row_name),inputs=[assessment_step],outputs=[name])
79
- name.change(fn=lambda value: update_user_performance(value,"name",row_name),inputs=[name])
80
- replationship.change(fn=lambda value: update_user_performance(value,"relationship",row_name),inputs=[replationship])
81
- numeric_value.change(fn=lambda value: update_user_performance(value,"numeric value",row_name),inputs=[numeric_value])
82
- unit.change(fn=lambda value: update_user_performance(value,"unit",row_name),inputs=[unit])
83
 
84
  def render_custom_safety():
85
  with gr.Blocks():
86
  render_safety_row("Safety Outcome #1",show_header=True)
87
- render_safety_row("Safety Outcome #2")
88
-
89
 
90
  def render_safety_row(row_name, show_header=False):
91
  with gr.Row():
@@ -118,11 +157,10 @@ def render_safety_row(row_name, show_header=False):
118
  value="%",
119
  label="Units")
120
 
121
- name.change(fn=lambda value: update_user_performance(value,"name",row_name),inputs=[name])
122
- numeric_value.change(fn=lambda value: update_user_performance(value,"numeric value",row_name),inputs=[numeric_value])
123
-
124
 
125
- def update_user_performance(value,element,setting):
126
  app_data["user"][setting.lower()][element] = value
127
  print(app_data["user"])
128
  if element == "assessment_step":
 
1
  import gradio as gr
 
2
 
3
  from utility import *
4
  from application import *
5
+ from features import init_app_data, create_md_tables, generate_summary # , add_device, remove_device, get_device
 
6
 
7
+ def refresh():
 
8
  init_app_data()
9
  '''
10
  refresh the literature report.
11
  '''
12
+ return create_md_tables(app_data["articles"])
13
 
14
  def articles_page():
15
 
16
  with gr.Blocks() as tab_page:
17
+ gr.Markdown("## Article Lists")
18
+ btn_refresh = gr.Button(value="Refresh",variant="primary")
19
+ gr.HTML("<hr>")
20
+ article_list = gr.Markdown("")
21
+
22
+ btn_refresh.click(
23
+ fn=refresh,
24
+ outputs=[article_list]
25
+ )
26
  return tab_page
27
 
28
+ def preference_page():
29
  with gr.Blocks() as tab_page:
30
  render_custom_performance()
31
  render_custom_safety()
32
 
33
  return tab_page
34
 
35
+ def summary_page():
36
+ # create a selection box for the user to select the articles
37
+ # that they want to include in the summary
38
+ with gr.Blocks() as tab_page:
39
+ gr.Markdown("## Summary")
40
+ gr.HTML("<hr>")
41
+
42
+ with gr.Row(equal_height=False):
43
+ with gr.Column():
44
+ article_selection = gr.Dropdown(
45
+ label="Select Articles",
46
+ choices=list(app_data["articles"].keys()),
47
+ info="Select the articles that you want to include in the summary.",
48
+ multiselect=True
49
+ )
50
+
51
+
52
+ with gr.Column():
53
+ gen_button = gr.Button(
54
+ label="Generate Summary",
55
+ variant="primary",
56
+ info="Click to generate the summary."
57
+ )
58
+ gr.HTML("<hr>")
59
+ summary = gr.Markdown("")
60
+
61
+ gen_button.click(
62
+ fn=generate_summary,
63
+ inputs=[article_selection],
64
+ outputs=[summary]
65
+ )
66
+
67
+ article_selection.change(
68
+ fn=lambda value: update_user_preference(value,"articles","summary"),
69
+ inputs=[article_selection]
70
+ )
71
+
72
+ return tab_page
73
+
74
  def render_custom_performance():
75
  with gr.Blocks():
76
  render_performance_row("Performance Outcome #1",show_header=True)
 
115
  label="Units",
116
  choices = defaults["units"])
117
 
118
+ assessment_step.change(fn=lambda value: update_user_preference(value,"assessment_step",row_name),inputs=[assessment_step],outputs=[name])
119
+ name.change(fn=lambda value: update_user_preference(value,"name",row_name),inputs=[name])
120
+ replationship.change(fn=lambda value: update_user_preference(value,"relationship",row_name),inputs=[replationship])
121
+ numeric_value.change(fn=lambda value: update_user_preference(value,"numeric value",row_name),inputs=[numeric_value])
122
+ unit.change(fn=lambda value: update_user_preference(value,"unit",row_name),inputs=[unit])
123
 
124
  def render_custom_safety():
125
  with gr.Blocks():
126
  render_safety_row("Safety Outcome #1",show_header=True)
127
+ render_safety_row("Safety Outcome #2")
 
128
 
129
  def render_safety_row(row_name, show_header=False):
130
  with gr.Row():
 
157
  value="%",
158
  label="Units")
159
 
160
+ name.change(fn=lambda value: update_user_preference(value,"name",row_name),inputs=[name])
161
+ numeric_value.change(fn=lambda value: update_user_preference(value,"numeric value",row_name),inputs=[numeric_value])
 
162
 
163
+ def update_user_preference(value,element,setting):
164
  app_data["user"][setting.lower()][element] = value
165
  print(app_data["user"])
166
  if element == "assessment_step":