hjtz commited on
Commit
17bff13
·
verified ·
1 Parent(s): 714bc0e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +136 -22
app.py CHANGED
@@ -1,19 +1,123 @@
1
  import gradio as gr
2
- import torch
 
 
 
 
 
 
3
  from PIL import Image
4
  # from transformers import AutoModel, AutoProcessor
5
 
6
  # ==========================================
7
- # 1. Load Model Weights
8
  # ==========================================
9
- MODEL_ID = "yangxiaoda/SpatialLogic-ckpt-tag"
10
- device = "cuda" if torch.cuda.is_available() else "cpu"
 
 
 
 
11
 
12
- print(f"Loading model to {device}...")
13
- # [REPLACE THIS] with your actual model loading code
14
- # processor = AutoProcessor.from_pretrained(MODEL_ID)
15
- # model = AutoModel.from_pretrained(MODEL_ID).to(device)
16
- print("Model loaded successfully!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
 
19
  # ==========================================
@@ -32,29 +136,39 @@ def compare_images(img1, img2, action_desc):
32
  return "⚠️ Please enter an action description!"
33
 
34
  try:
35
- # [REPLACE THIS] with your actual inference code
36
- # Example pseudo-code:
37
- # inputs = processor(text=action_desc, images=[img1, img2], return_tensors="pt").to(device)
38
- # outputs = model(**inputs)
39
- # score1, score2 = outputs.logits
40
-
41
- # Dummy scores for UI testing (Replace with real logic)
42
- score_img1 = 0.8
43
- score_img2 = 0.4
44
 
45
  # 2. Logic Judgment
46
  if score_img1 > score_img2:
47
  result = "img1"
48
- explanation = "The model evaluates that **Image 1 (img1)** is closer to the completed state of the described task."
 
 
 
49
  elif score_img2 > score_img1:
50
  result = "img2"
51
- explanation = "The model evaluates that **Image 2 (img2)** is closer to the completed state of the described task."
 
 
 
52
  else:
53
  result = "Tie"
54
- explanation = "The model evaluates both images equally regarding the task completion."
 
 
 
55
 
56
  # 3. Format Output
57
- return f"### **Output:** {result}\n\n**Explanation:** {explanation}"
 
 
 
 
 
58
 
59
  except Exception as e:
60
  return f"❌ An error occurred during inference: {str(e)}"
 
1
  import gradio as gr
2
+ import base64
3
+ import io
4
+ import json
5
+ import os
6
+ import re
7
+ import urllib.error
8
+ import urllib.request
9
  from PIL import Image
10
  # from transformers import AutoModel, AutoProcessor
11
 
12
  # ==========================================
13
+ # 1. Configure SiliconFlow API
14
  # ==========================================
15
+ API_URL = "https://api.siliconflow.cn/v1/chat/completions"
16
+ MODEL_ID = "Qwen/Qwen3.6-35B-A3B"
17
+ API_KEY = os.getenv(
18
+ "SILICONFLOW_API_KEY",
19
+ "sk-aflkmenvmawlrzbmlawwnhdyaacpylqeebiqzvjhgkujbttw",
20
+ )
21
 
22
+ print("SiliconFlow API mode enabled.")
23
+
24
+
25
+ def pil_to_data_url(img: Image.Image) -> str:
26
+ """Convert PIL image to data URL string for API transport."""
27
+ buffered = io.BytesIO()
28
+ img.convert("RGB").save(buffered, format="JPEG", quality=92)
29
+ img_b64 = base64.b64encode(buffered.getvalue()).decode("utf-8")
30
+ return f"data:image/jpeg;base64,{img_b64}"
31
+
32
+
33
+ def extract_json_block(text: str) -> dict:
34
+ """Extract first valid JSON object from model text output."""
35
+ text = text.strip()
36
+
37
+ try:
38
+ return json.loads(text)
39
+ except json.JSONDecodeError:
40
+ pass
41
+
42
+ fenced = re.search(r"```(?:json)?\s*(\{[\s\S]*?\})\s*```", text)
43
+ if fenced:
44
+ return json.loads(fenced.group(1))
45
+
46
+ inline = re.search(r"(\{[\s\S]*\})", text)
47
+ if inline:
48
+ return json.loads(inline.group(1))
49
+
50
+ raise ValueError("No valid JSON found in model response")
51
+
52
+
53
+ def call_siliconflow_compare(img1: Image.Image, img2: Image.Image, action_desc: str):
54
+ """Call SiliconFlow API and return (score_img1, score_img2, explanation)."""
55
+ img1_data_url = pil_to_data_url(img1)
56
+ img2_data_url = pil_to_data_url(img2)
57
+
58
+ system_prompt = (
59
+ "You are an image-comparison judge. Given two images and an action description, "
60
+ "decide which image is closer to the completed state of the action. "
61
+ "Return only JSON with keys: score_img1, score_img2, explanation. "
62
+ "score_img1 and score_img2 must be numbers in [0,1]."
63
+ )
64
+
65
+ payload = {
66
+ "model": MODEL_ID,
67
+ "temperature": 0.1,
68
+ "response_format": {"type": "json_object"},
69
+ "messages": [
70
+ {"role": "system", "content": system_prompt},
71
+ {
72
+ "role": "user",
73
+ "content": [
74
+ {
75
+ "type": "text",
76
+ "text": (
77
+ "Action description: "
78
+ f"{action_desc}\n"
79
+ "Please compare image1 and image2 and output JSON only."
80
+ ),
81
+ },
82
+ {"type": "image_url", "image_url": {"url": img1_data_url}},
83
+ {"type": "image_url", "image_url": {"url": img2_data_url}},
84
+ ],
85
+ },
86
+ ],
87
+ }
88
+
89
+ data = json.dumps(payload).encode("utf-8")
90
+ request = urllib.request.Request(
91
+ API_URL,
92
+ data=data,
93
+ headers={
94
+ "Authorization": f"Bearer {API_KEY}",
95
+ "Content-Type": "application/json",
96
+ },
97
+ method="POST",
98
+ )
99
+
100
+ try:
101
+ with urllib.request.urlopen(request, timeout=120) as response:
102
+ raw = response.read().decode("utf-8")
103
+ except urllib.error.HTTPError as e:
104
+ error_body = e.read().decode("utf-8", errors="ignore")
105
+ raise RuntimeError(f"HTTP {e.code}: {error_body}") from e
106
+ except urllib.error.URLError as e:
107
+ raise RuntimeError(f"Network error: {e.reason}") from e
108
+
109
+ api_result = json.loads(raw)
110
+ content = api_result["choices"][0]["message"]["content"]
111
+ parsed = extract_json_block(content)
112
+
113
+ score_img1 = float(parsed.get("score_img1", 0.0))
114
+ score_img2 = float(parsed.get("score_img2", 0.0))
115
+ explanation = str(parsed.get("explanation", "No explanation provided."))
116
+
117
+ score_img1 = max(0.0, min(1.0, score_img1))
118
+ score_img2 = max(0.0, min(1.0, score_img2))
119
+
120
+ return score_img1, score_img2, explanation
121
 
122
 
123
  # ==========================================
 
136
  return "⚠️ Please enter an action description!"
137
 
138
  try:
139
+ score_img1, score_img2, api_explanation = call_siliconflow_compare(
140
+ img1=img1,
141
+ img2=img2,
142
+ action_desc=action_desc,
143
+ )
 
 
 
 
144
 
145
  # 2. Logic Judgment
146
  if score_img1 > score_img2:
147
  result = "img1"
148
+ explanation = (
149
+ "The model evaluates that **Image 1 (img1)** is closer to the completed "
150
+ f"state of the described task.\n\nModel rationale: {api_explanation}"
151
+ )
152
  elif score_img2 > score_img1:
153
  result = "img2"
154
+ explanation = (
155
+ "The model evaluates that **Image 2 (img2)** is closer to the completed "
156
+ f"state of the described task.\n\nModel rationale: {api_explanation}"
157
+ )
158
  else:
159
  result = "Tie"
160
+ explanation = (
161
+ "The model evaluates both images equally regarding the task completion."
162
+ f"\n\nModel rationale: {api_explanation}"
163
+ )
164
 
165
  # 3. Format Output
166
+ return (
167
+ f"### **Output:** {result}\n\n"
168
+ f"**Score(img1):** {score_img1:.3f} \n"
169
+ f"**Score(img2):** {score_img2:.3f}\n\n"
170
+ f"**Explanation:** {explanation}"
171
+ )
172
 
173
  except Exception as e:
174
  return f"❌ An error occurred during inference: {str(e)}"