wuff-mann commited on
Commit
4e0ab32
·
verified ·
1 Parent(s): 1bde015

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +79 -81
app.py CHANGED
@@ -7,46 +7,57 @@ from mann_engram_en.router import MANNEngramRouter
7
  # 强制缓存路径
8
  os.environ["HF_HOME"] = "/home/user/.cache/huggingface"
9
 
10
- # 💡 架构升级 1:白嫖 HF 官方的 72B 满血云端大模型 API!速度极快且极其聪明
11
- hf_client = InferenceClient("Qwen/Qwen2.5-72B-Instruct")
12
  router_engine = None
13
 
14
  def init_engine():
15
  global router_engine
16
  if router_engine is None:
17
  print("Initializing SiGLIP Tensor Routing Core...")
18
- # 💡 架构升级 2:关闭笨重且缓慢的本地 CPU LLM,纯粹依靠 SiGLIP 做边缘路由
19
  router_engine = MANNEngramRouter(
20
  ckpt_path="./weights/skew_model_v4full_en.pt",
21
  enable_local_intent=False
22
  )
23
  return router_engine
24
 
25
- def extract_intent_via_api(messy_text):
26
- """使用 72B 大脑进行神级意图提取"""
27
- sys_prompt = "You are an expert clinical triage AI. Extract ONLY the critical medical symptoms and targeted body parts from the patient's messy complaint. COMPLETELY IGNORE noise like food, nurses, billing, or hospital conditions. Output a single concise sentence (e.g., 'Assess brain tumor, sudden vision blur, and seizures.')."
 
 
 
 
 
 
 
 
 
 
 
28
  try:
29
- res = hf_client.chat_completion(
30
  messages=[
31
  {"role": "system", "content": sys_prompt},
32
  {"role": "user", "content": messy_text}
33
  ],
34
- max_tokens=50
35
  )
36
  return res.choices[0].message.content.strip()
37
  except Exception as e:
38
- print(f"API Fallback: {e}")
39
- return messy_text # 兜底逻辑
40
 
41
- def process_input(query, files):
 
 
 
 
42
  if not query:
43
- return "⚠️ Please enter a clinical query.", "", "Error: Missing input.", []
44
 
45
  engine = init_engine()
46
 
47
  file_paths = []
48
  image_paths = []
49
-
50
  if files:
51
  for f in files:
52
  ext = f.name.lower().split('.')[-1]
@@ -57,104 +68,91 @@ def process_input(query, files):
57
 
58
  start_time = time.time()
59
 
60
- # --- 阶段 1: Cloud Intelligence (极速提取) ---
61
- clean_intent = extract_intent_via_api(query)
62
 
63
- # --- 阶段 2: Edge Tensor Routing (多模态雷达) ---
64
- # 使用 router 的底层 compress 方法直接传入净化后的文本
 
 
65
  results = engine.compress(
66
  query=clean_intent,
67
- context_pool=[], # 此 Demo 重点展示图片路由,暂时置空长文档
68
  image_pool=image_paths,
69
  top_p=0.85
70
  )
71
 
72
  latency = time.time() - start_time
73
 
74
- # 构建输出
75
- intent = clean_intent
76
- context = results.get("purified_context", "N/A")
77
  stats_dict = results.get("stats", {})
78
-
79
  stats_report = (
80
  f"✅ Extraction Complete\n"
81
  f"---------------------------\n"
82
- f"🧠 Cloud LLM Time: ~1.5s\n"
83
- f"👁️ Edge Vision Time: ~{latency - 1.5:.2f}s\n"
84
- f"🖼️ Images Routed: {stats_dict.get('retained_images', 0)} / {stats_dict.get('original_images', 0)}\n"
85
- f"⚡ Total Latency: {latency:.2f} seconds"
86
  )
87
 
88
- routed_images = results.get("purified_images_pil", [])
89
-
90
- return intent, context, stats_report, routed_images
91
 
92
  # ==========================================
93
- # UI 界面部分 (保持不变取消宽度限制以适应宽屏)
94
  # ==========================================
95
  with gr.Blocks(title="MANN-Engram Router") as demo:
96
 
97
- gr.Markdown(
98
- """
99
- # 🧠 MANN-Engram: Edge-Cloud Multimodal Semantic Router
100
- ### A Privacy-First, Zero-Hallucination Shield for Clinical Vision-Language Models.
101
- """
102
- )
103
-
104
- with gr.Accordion("⚙️ System Architecture & Capabilities (Click to expand)", open=False):
105
- gr.Markdown(
106
- """
107
- * **Cloud-side Intent Extraction (Qwen 72B):** Uses zero-shot reasoning to parse messy, emotion-heavy patient inputs into clean medical vectors.
108
- * **Edge-side Tensor Routing (SiGLIP + MANN):** Projects clinical text and medical imaging (CT, MRI, X-ray) into a shared latent space to dynamically filter out irrelevant exams.
109
- * **Zero-Hallucination Guarantee:** The router does *not* generate new medical facts. It acts purely as a strict extraction and filtering pipeline.
110
- """
111
- )
112
-
113
- gr.Markdown("---")
114
 
115
  with gr.Row():
116
- with gr.Column(scale=5):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  gr.Markdown("### 📥 Input Console")
118
  query_input = gr.Textbox(
119
- label="Messy Clinical Query & Complaints",
120
- lines=6,
121
- placeholder="Enter patient complaints, including irrelevant noise, emotions, and specific medical symptoms..."
122
  )
123
- file_input = gr.File(label="Upload Patient File Dump (Images & Docs)", file_count="multiple")
124
- submit_btn = gr.Button("🚀 Trigger Semantic Router", variant="primary", size="lg")
125
-
126
- with gr.Column(scale=5):
127
- gr.Markdown("### 📤 Purified Output Dashboard")
128
- out_intent = gr.Textbox(label="🎯 Purified Core Intent", interactive=False)
129
- out_context = gr.Textbox(label="📄 Filtered High-Value Context", lines=4, interactive=False, visible=False) # 隐藏暂时不用的文本框
130
-
131
- with gr.Row():
132
- out_stats = gr.Textbox(label="📊 Compression Stats", interactive=False, lines=6)
133
-
134
  out_gallery = gr.Gallery(
135
- label="🔭 Latent Space Routed Images (Core Evidence)",
136
- columns=2,
137
- object_fit="contain",
138
- height="auto"
139
  )
140
-
141
- gr.Markdown("---")
142
- gr.Markdown("### 🧪 Quick Try: 'Hell-Mode' Clinical Scenarios")
143
- gr.Examples(
144
- examples=[
145
- [
146
- "Doctor, you have to help me. The food in this ward is absolutely terrible, it's giving me severe stomach aches and diarrhea (see my abdominal scan). Also, my legs have been cramping up lately when I walk to the bathroom, and I have this chronic smoker's cough that won't go away. But honestly, the reason I came to the ER yesterday is that my vision suddenly blurred, I had a seizure, and the left side of my body went numb. My family is threatening to sue the hospital if you don't look at my head scans immediately. Is the mass growing?",
147
- None
148
- ]
149
- ],
150
- inputs=[query_input, file_input],
151
- label="Click a scenario below to auto-fill the input (You will still need to upload the corresponding test images manually):"
152
- )
153
 
 
154
  submit_btn.click(
155
  fn=process_input,
156
- inputs=[query_input, file_input],
157
- outputs=[out_intent, out_context, out_stats, out_gallery]
158
  )
159
 
160
  if __name__ == "__main__":
 
7
  # 强制缓存路径
8
  os.environ["HF_HOME"] = "/home/user/.cache/huggingface"
9
 
10
+ # 全局引擎变量
 
11
  router_engine = None
12
 
13
  def init_engine():
14
  global router_engine
15
  if router_engine is None:
16
  print("Initializing SiGLIP Tensor Routing Core...")
 
17
  router_engine = MANNEngramRouter(
18
  ckpt_path="./weights/skew_model_v4full_en.pt",
19
  enable_local_intent=False
20
  )
21
  return router_engine
22
 
23
+ def extract_intent_via_api(messy_text, hf_token):
24
+ """使用 72B 大脑进行意图提取,动态使用用户提供的 Token"""
25
+ if not hf_token:
26
+ return "ERROR: MISSING TOKEN"
27
+
28
+ # 动态创建 Client
29
+ client = InferenceClient("Qwen/Qwen2.5-72B-Instruct", token=hf_token)
30
+
31
+ sys_prompt = (
32
+ "You are an expert clinical triage AI. Extract ONLY the critical medical symptoms and targeted body parts. "
33
+ "IGNORE all noise like hospital food, billing, emotions, or social complaints. "
34
+ "Output a single concise English sentence."
35
+ )
36
+
37
  try:
38
+ res = client.chat_completion(
39
  messages=[
40
  {"role": "system", "content": sys_prompt},
41
  {"role": "user", "content": messy_text}
42
  ],
43
+ max_tokens=60
44
  )
45
  return res.choices[0].message.content.strip()
46
  except Exception as e:
47
+ return f"API ERROR: {str(e)}"
 
48
 
49
+ def process_input(query, files, hf_token):
50
+ """处理输入的主函数"""
51
+ if not hf_token:
52
+ return "❌ Error", "Please provide a Hugging Face API Token in the settings.", "Status: Failed due to missing token.", []
53
+
54
  if not query:
55
+ return "⚠️ Warning", "Please enter a clinical query.", "Status: Waiting for input.", []
56
 
57
  engine = init_engine()
58
 
59
  file_paths = []
60
  image_paths = []
 
61
  if files:
62
  for f in files:
63
  ext = f.name.lower().split('.')[-1]
 
68
 
69
  start_time = time.time()
70
 
71
+ # --- 阶段 1: Cloud Intelligence (使用用户 Token) ---
72
+ clean_intent = extract_intent_via_api(query, hf_token)
73
 
74
+ if "API ERROR" in clean_intent or "ERROR: MISSING" in clean_intent:
75
+ return "Cloud API Error", clean_intent, "Please check your HF Token and try again.", []
76
+
77
+ # --- 阶段 2: Edge Tensor Routing ---
78
  results = engine.compress(
79
  query=clean_intent,
80
+ context_pool=[],
81
  image_pool=image_paths,
82
  top_p=0.85
83
  )
84
 
85
  latency = time.time() - start_time
86
 
87
+ # 构建统计报告
 
 
88
  stats_dict = results.get("stats", {})
 
89
  stats_report = (
90
  f"✅ Extraction Complete\n"
91
  f"---------------------------\n"
92
+ f"🧠 Cloud Brain: Qwen-72B-Instruct\n"
93
+ f"👁️ Edge Vision: SiGLIP-So400M\n"
94
+ f"🖼️ Images Filtered: {stats_dict.get('retained_images', 0)} / {stats_dict.get('original_images', 0)}\n"
95
+ f"⚡ Total Latency: {latency:.2f}s"
96
  )
97
 
98
+ return clean_intent, "", stats_report, results.get("purified_images_pil", [])
 
 
99
 
100
  # ==========================================
101
+ # 重新布局:左侧设置中间输入,右侧输出
102
  # ==========================================
103
  with gr.Blocks(title="MANN-Engram Router") as demo:
104
 
105
+ gr.Markdown("# 🧠 MANN-Engram: Edge-Cloud Multimodal Router")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
 
107
  with gr.Row():
108
+ # --- 左侧边栏:设置区 ---
109
+ with gr.Column(scale=2, min_width=250):
110
+ gr.Markdown("### ⚙️ Settings")
111
+ token_input = gr.Textbox(
112
+ label="Hugging Face API Token",
113
+ placeholder="hf_xxxxxxxxxxxxxxxxx",
114
+ type="password", # 密码模式保护隐私
115
+ info="Get your token at: hf.co/settings/tokens"
116
+ )
117
+ gr.Markdown(
118
+ "**Why Token?**\n"
119
+ "We use Qwen-72B (Cloud) for intent parsing and SiGLIP (Edge) for image routing. "
120
+ "A free HF token is required for the cloud API."
121
+ )
122
+ gr.Markdown("---")
123
+ gr.Markdown("### 🧪 Quick Try")
124
+ example_btn = gr.Examples(
125
+ examples=[["The hospital food is bad, it gives me stomach pain, but my real concern is the sudden numbness in my left arm and the seizures I had. Please check my head MRI.", None]],
126
+ inputs=[None, None], # 仅作展示,不直接填入 Token
127
+ label="Sample Scenario"
128
+ )
129
+
130
+ # --- 中间:输入区 ---
131
+ with gr.Column(scale=4):
132
  gr.Markdown("### 📥 Input Console")
133
  query_input = gr.Textbox(
134
+ label="Patient Complaint / Session Logs",
135
+ lines=8,
136
+ placeholder="Enter messy clinical text here..."
137
  )
138
+ file_input = gr.File(label="Upload Diagnostic Images", file_count="multiple")
139
+ submit_btn = gr.Button("🚀 Process & Route", variant="primary", size="lg")
140
+
141
+ # --- 右侧:输出区 ---
142
+ with gr.Column(scale=4):
143
+ gr.Markdown("### 📤 Routing Result")
144
+ out_intent = gr.Textbox(label="🎯 Purified Core Intent (By Cloud 72B)", interactive=False)
145
+ out_stats = gr.Textbox(label="📊 Performance Metrics", interactive=False, lines=5)
 
 
 
146
  out_gallery = gr.Gallery(
147
+ label="🔭 Selected Core Evidence (By Edge SiGLIP)",
148
+ columns=2, height="auto"
 
 
149
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
150
 
151
+ # 绑定事件
152
  submit_btn.click(
153
  fn=process_input,
154
+ inputs=[query_input, file_input, token_input],
155
+ outputs=[out_intent, gr.State(), out_stats, out_gallery]
156
  )
157
 
158
  if __name__ == "__main__":