OppaAI commited on
Commit
306ab5e
·
verified ·
1 Parent(s): f745b5c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +49 -30
app.py CHANGED
@@ -5,11 +5,12 @@ from fastmcp import Client
5
  from fastmcp.client import StreamableHttpTransport
6
  import asyncio
7
  import ast
 
8
 
9
  # -------------------------------
10
  # MCP server info
11
  # -------------------------------
12
- ROBOT_ID = "Robot_MCP_Client" # Local client identifier
13
  MCP_SERVER_URL = "https://oppaai-robot-mcp-server.hf.space/gradio_api/mcp/"
14
  SERVER_NAME = "Robot_MCP_Server"
15
  TOOL_NAME = "Robot_MCP_Server_robot_watch"
@@ -20,44 +21,54 @@ TOOL_NAME = "Robot_MCP_Server_robot_watch"
20
  HTTP_TRANSPORT = StreamableHttpTransport(url=MCP_SERVER_URL)
21
  MCP_CLIENT = Client(transport=HTTP_TRANSPORT, name=SERVER_NAME)
22
 
23
-
24
  # -------------------------------
25
  # Async function using user's HF token
26
  # -------------------------------
27
- async def process_webcam_stream_async(image, oauth_token: gr.OAuthToken | None):
28
  """
29
  Send webcam image to MCP server using user's HF token and process the response.
30
  """
 
31
  if oauth_token is None:
32
- return "Please log in first.", "", "", "", "", "", "", ""
33
 
 
34
  if image is None:
35
  return "", "", "", "", "", "", "", ""
36
 
37
- # Convert image to Base64
38
- buffered = io.BytesIO()
39
- image.save(buffered, format="JPEG")
40
- b64_img = base64.b64encode(buffered.getvalue()).decode("utf-8")
41
-
42
- # Payload with user token
43
- payload = {
44
- "hf_token_input": oauth_token.token,
45
- "robot_id_input": ROBOT_ID,
46
- "image_b64_input": b64_img
47
- }
48
-
49
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  async with MCP_CLIENT:
51
  response = await MCP_CLIENT.call_tool(TOOL_NAME, payload)
 
52
  if response.is_error:
53
  error_text = response.content.text if response.content else "Unknown error"
54
  raise Exception(f"MCP Tool Error: {error_text}")
55
 
56
  raw_text = response.content.text
57
- response_dict = ast.literal_eval(raw_text)
 
 
 
 
 
 
 
58
  vlm_result = response_dict.get("result", {})
59
 
60
- # Extract all fields
61
  description_out = vlm_result.get("description", "")
62
  environment_out = vlm_result.get("environment", "")
63
  indoor_outdoor_out = vlm_result.get("indoor_or_outdoor", "")
@@ -67,7 +78,7 @@ async def process_webcam_stream_async(image, oauth_token: gr.OAuthToken | None):
67
  objects_list = vlm_result.get("objects", [])
68
  hazards_out = vlm_result.get("hazards", "")
69
 
70
- # Convert lists to strings
71
  objects_str = ", ".join(objects_list) if isinstance(objects_list, list) else str(objects_list)
72
 
73
  return (
@@ -83,8 +94,6 @@ async def process_webcam_stream_async(image, oauth_token: gr.OAuthToken | None):
83
 
84
  except Exception as e:
85
  print(f"Error calling MCP API: {e}")
86
- import traceback
87
- traceback.print_exc()
88
  return f"Error: {e}", "", "", "", "", "", "", ""
89
 
90
 
@@ -92,11 +101,20 @@ async def process_webcam_stream_async(image, oauth_token: gr.OAuthToken | None):
92
  # Gradio UI
93
  # -------------------------------
94
  with gr.Blocks() as demo:
95
- # Hugging Face OAuth login button
96
- gr.LoginButton()
97
  gr.Markdown("## 🎥 Robot Vision Webcam Stream (MCP Client)")
 
 
 
 
98
  with gr.Row():
99
- webcam_input = gr.Image(label="Captured from Web-Cam", sources=["upload", "webcam"], type="pil")
 
 
 
 
 
 
 
100
  with gr.Column():
101
  description_out = gr.Textbox(label="Description", lines=5)
102
  environment_out = gr.Textbox(label="Environment", lines=3)
@@ -107,13 +125,14 @@ with gr.Blocks() as demo:
107
  objects_out = gr.Textbox(label="Objects Detected", lines=2)
108
  hazards_out = gr.Textbox(label="Hazards Identified", lines=2)
109
 
110
- # Only webcam input in inputs; Gradio automatically injects oauth_token
 
 
 
 
111
  webcam_input.stream(
112
  process_webcam_stream_async,
113
- inputs=[
114
- webcam_input,
115
- gr.OAuthToken()
116
- ],
117
  outputs=[
118
  description_out,
119
  environment_out,
@@ -128,4 +147,4 @@ with gr.Blocks() as demo:
128
  )
129
 
130
  if __name__ == "__main__":
131
- demo.launch()
 
5
  from fastmcp.client import StreamableHttpTransport
6
  import asyncio
7
  import ast
8
+ import json
9
 
10
  # -------------------------------
11
  # MCP server info
12
  # -------------------------------
13
+ ROBOT_ID = "Robot_MCP_Client"
14
  MCP_SERVER_URL = "https://oppaai-robot-mcp-server.hf.space/gradio_api/mcp/"
15
  SERVER_NAME = "Robot_MCP_Server"
16
  TOOL_NAME = "Robot_MCP_Server_robot_watch"
 
21
  HTTP_TRANSPORT = StreamableHttpTransport(url=MCP_SERVER_URL)
22
  MCP_CLIENT = Client(transport=HTTP_TRANSPORT, name=SERVER_NAME)
23
 
 
24
  # -------------------------------
25
  # Async function using user's HF token
26
  # -------------------------------
27
+ async def process_webcam_stream_async(image, oauth_token: gr.OAuthToken | None = None):
28
  """
29
  Send webcam image to MCP server using user's HF token and process the response.
30
  """
31
+ # 1. CHECK LOGIN: If no token, ask user to log in
32
  if oauth_token is None:
33
+ return "Please log in using the button above.", "", "", "", "", "", "", ""
34
 
35
+ # 2. CHECK IMAGE: If camera hasn't loaded yet
36
  if image is None:
37
  return "", "", "", "", "", "", "", ""
38
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  try:
40
+ # 3. PREPARE IMAGE: Convert to Base64
41
+ buffered = io.BytesIO()
42
+ image.save(buffered, format="JPEG")
43
+ b64_img = base64.b64encode(buffered.getvalue()).decode("utf-8")
44
+
45
+ # 4. PREPARE PAYLOAD: Inject the user's token
46
+ payload = {
47
+ "hf_token_input": oauth_token.token, # <--- Token used here
48
+ "robot_id_input": ROBOT_ID,
49
+ "image_b64_input": b64_img
50
+ }
51
+
52
+ # 5. CALL MCP SERVER
53
  async with MCP_CLIENT:
54
  response = await MCP_CLIENT.call_tool(TOOL_NAME, payload)
55
+
56
  if response.is_error:
57
  error_text = response.content.text if response.content else "Unknown error"
58
  raise Exception(f"MCP Tool Error: {error_text}")
59
 
60
  raw_text = response.content.text
61
+
62
+ # 6. PARSE RESPONSE (Handle both JSON and Python Dict strings)
63
+ try:
64
+ response_dict = json.loads(raw_text)
65
+ except json.JSONDecodeError:
66
+ # Fallback if server returns single quotes
67
+ response_dict = ast.literal_eval(raw_text)
68
+
69
  vlm_result = response_dict.get("result", {})
70
 
71
+ # 7. EXTRACT DATA
72
  description_out = vlm_result.get("description", "")
73
  environment_out = vlm_result.get("environment", "")
74
  indoor_outdoor_out = vlm_result.get("indoor_or_outdoor", "")
 
78
  objects_list = vlm_result.get("objects", [])
79
  hazards_out = vlm_result.get("hazards", "")
80
 
81
+ # Convert list to string
82
  objects_str = ", ".join(objects_list) if isinstance(objects_list, list) else str(objects_list)
83
 
84
  return (
 
94
 
95
  except Exception as e:
96
  print(f"Error calling MCP API: {e}")
 
 
97
  return f"Error: {e}", "", "", "", "", "", "", ""
98
 
99
 
 
101
  # Gradio UI
102
  # -------------------------------
103
  with gr.Blocks() as demo:
 
 
104
  gr.Markdown("## 🎥 Robot Vision Webcam Stream (MCP Client)")
105
+
106
+ # The Login Button (Required for oauth_token)
107
+ gr.LoginButton()
108
+
109
  with gr.Row():
110
+ # Input: Webcam
111
+ webcam_input = gr.Image(
112
+ label="Captured from Web-Cam",
113
+ sources=["webcam"],
114
+ type="pil"
115
+ )
116
+
117
+ # Outputs
118
  with gr.Column():
119
  description_out = gr.Textbox(label="Description", lines=5)
120
  environment_out = gr.Textbox(label="Environment", lines=3)
 
125
  objects_out = gr.Textbox(label="Objects Detected", lines=2)
126
  hazards_out = gr.Textbox(label="Hazards Identified", lines=2)
127
 
128
+ # -------------------------------
129
+ # Event Trigger
130
+ # -------------------------------
131
+ # CRITICAL FIX: Do NOT include gr.OAuthToken() in inputs.
132
+ # Gradio automatically injects it because it's in the function signature.
133
  webcam_input.stream(
134
  process_webcam_stream_async,
135
+ inputs=[webcam_input],
 
 
 
136
  outputs=[
137
  description_out,
138
  environment_out,
 
147
  )
148
 
149
  if __name__ == "__main__":
150
+ demo.launch()