ZDPLI commited on
Commit
dff96f0
Β·
verified Β·
1 Parent(s): 27b9c71

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +170 -0
app.py ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import logging
3
+ import torch
4
+ import gradio as gr
5
+ from tqdm import tqdm
6
+ from PIL import Image
7
+
8
+ # LangChain & LangGraph
9
+ from langgraph.graph import StateGraph
10
+ from langgraph.checkpoint.memory import MemorySaver
11
+ from langchain.tools import tool
12
+ from langchain_community.vectorstores import FAISS
13
+ from langchain_community.embeddings import HuggingFaceEmbeddings
14
+ from langchain_community.document_loaders import PyPDFLoader
15
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
16
+ from duckduckgo_search import DDGS
17
+ from llama_cpp import Llama
18
+ from huggingface_hub import hf_hub_download
19
+
20
+ logging.basicConfig(level=logging.INFO)
21
+ logger = logging.getLogger(__name__)
22
+
23
+ # ------------------------------
24
+ # πŸ”Ή Download GGUF Model from Hugging Face
25
+ # ------------------------------
26
+ MODEL_REPO = "nitsuai/Bio-Medical-MultiModal-Llama-3-8B-V1-i1-GGUF"
27
+ MODEL_FILENAME = "Bio-Medical-MultiModal-Llama-3-8B-V1-i1-Q4_0.gguf"
28
+
29
+ model_path = hf_hub_download(repo_id=MODEL_REPO, filename=MODEL_FILENAME)
30
+
31
+ llm = Llama(
32
+ model_path=model_path,
33
+ n_ctx=8192,
34
+ n_gpu_layers=0, # Set to 0 for CPU inference
35
+ logits_all=True,
36
+ n_batch=512
37
+ )
38
+
39
+ logger.info("Llama GGUF Model Loaded Successfully from Hugging Face.")
40
+
41
+ # ------------------------------
42
+ # πŸ”Ή Multi-Specialty Prompt
43
+ # ------------------------------
44
+ UNIFIED_MEDICAL_PROMPT = """
45
+ You are an advanced Medical AI Assistant capable of providing thorough,
46
+ comprehensive answers for a wide range of medical specialties:
47
+ General Practice, Radiology, Cardiology, Neurology, Psychiatry, Pediatrics,
48
+ Endocrinology, Oncology, and more.
49
+
50
+ You can:
51
+ 1) Analyze images if provided (Radiology).
52
+ 2) Search the web for up-to-date medical info (Web Search).
53
+ 3) Retrieve relevant documents from a knowledge base (Vector Store).
54
+ 4) Provide scientific, evidence-based explanations and references when possible.
55
+
56
+ Always strive to provide a detailed, helpful, and empathetic response.
57
+ """
58
+
59
+ # ------------------------------
60
+ # πŸ”Ή FAISS Vector Store for RAG
61
+ # ------------------------------
62
+ _vector_store_cache = None
63
+
64
+ def load_vectorstore(pdf_path="medical_docs.pdf"):
65
+ try:
66
+ loader = PyPDFLoader(pdf_path)
67
+ documents = loader.load()
68
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=1024, chunk_overlap=100)
69
+ docs = text_splitter.split_documents(documents)
70
+ embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
71
+ vector_store = FAISS.from_documents(docs, embeddings)
72
+ logger.info(f"Vector store loaded with {len(docs)} documents.")
73
+ return vector_store
74
+ except Exception as e:
75
+ logger.error(f"Error loading vector store: {str(e)}")
76
+ return None
77
+
78
+ if os.path.exists("medical_docs.pdf"):
79
+ _vector_store_cache = load_vectorstore("medical_docs.pdf")
80
+
81
+ vector_store = _vector_store_cache
82
+
83
+ # ------------------------------
84
+ # πŸ”Ή Define AI Tools
85
+ # ------------------------------
86
+ @tool
87
+ def analyze_medical_image(image_path: str):
88
+ """Analyzes a medical image and returns a diagnostic explanation."""
89
+ try:
90
+ image = Image.open(image_path)
91
+ except Exception as e:
92
+ logger.error(f"Error opening image: {str(e)}")
93
+ return "Error processing image."
94
+ output = llm(f"Analyze this medical image for radiological findings:\n{image}", max_tokens=512)
95
+ return output["choices"][0]["text"]
96
+
97
+ @tool
98
+ def retrieve_medical_knowledge(query: str):
99
+ """Retrieves medical knowledge from FAISS vector store."""
100
+ if vector_store is None:
101
+ return "No external medical knowledge available."
102
+ retriever = vector_store.as_retriever(search_type="similarity", search_kwargs={"k": 5})
103
+ docs = retriever.get_relevant_documents(query)
104
+ citations = [f"[{i+1}] {doc.metadata.get('source', 'Unknown Source')}" for i, doc in enumerate(docs)]
105
+ content = "\n".join([doc.page_content for doc in docs])
106
+ citations_text = "\n".join(citations)
107
+ return content + f"\n\n**Citations:**\n{citations_text}"
108
+
109
+ @tool
110
+ def web_search(query: str):
111
+ """Performs a real-time web search using DuckDuckGo."""
112
+ try:
113
+ results = DDGS().text(query, max_results=5)
114
+ summary = "\n".join([f"{r['title']}: {r['body']} ({r['href']})" for r in results]) or "No relevant results found."
115
+ return summary
116
+ except Exception as e:
117
+ logger.error(f"Web search error: {str(e)}")
118
+ return "Error retrieving web search results."
119
+
120
+ # ------------------------------
121
+ # πŸ”Ή Multi-Context Chat Function
122
+ # ------------------------------
123
+ def chat_with_agent(user_query, image_file, pdf_file):
124
+ image_analysis = analyze_medical_image(image_file) if image_file else ""
125
+ rag_text = retrieve_medical_knowledge(user_query)
126
+ web_text = web_search(user_query)
127
+
128
+ combined_context = f"""
129
+ {UNIFIED_MEDICAL_PROMPT}
130
+
131
+ Additional Context:
132
+ - Radiology Analysis (if any): {image_analysis}
133
+ - Retrieved from Vector Store (RAG): {rag_text}
134
+ - Web Search Results: {web_text}
135
+
136
+ Now, respond to the user's query with detailed, medically accurate information.
137
+ Q: {user_query}
138
+ A:
139
+ """
140
+
141
+ response_accumulator = ""
142
+ for token in llm(
143
+ prompt=combined_context,
144
+ max_tokens=1024,
145
+ temperature=0.7,
146
+ top_p=0.9,
147
+ stream=True
148
+ ):
149
+ partial_text = token["choices"][0]["text"]
150
+ response_accumulator += partial_text
151
+ yield response_accumulator
152
+
153
+ # ------------------------------
154
+ # πŸ”Ή Gradio Interface
155
+ # ------------------------------
156
+ with gr.Blocks(title="πŸ₯ Llama3-Med AI Assistant") as demo:
157
+ gr.Markdown("# πŸ₯ Llama3-Med AI Assistant\n_Your intelligent medical assistant powered by advanced AI._")
158
+
159
+ with gr.Row():
160
+ user_input = gr.Textbox(label="πŸ’¬ Ask a medical question", placeholder="Type your question here...")
161
+ image_file = gr.Image(label="πŸ“· Upload Medical Image", type="filepath")
162
+ pdf_file = gr.File(label="πŸ“„ Upload PDF (Optional)", file_types=[".pdf"])
163
+
164
+ submit_btn = gr.Button("πŸš€ Submit", variant="primary")
165
+ output_text = gr.Textbox(label="πŸ“ Assistant's Response", interactive=False, lines=25)
166
+
167
+ submit_btn.click(fn=chat_with_agent, inputs=[user_input, image_file, pdf_file], outputs=output_text)
168
+
169
+ if __name__ == "__main__":
170
+ demo.queue().launch(server_name="0.0.0.0", server_port=7860)