toecm commited on
Commit
b9493b2
·
verified ·
1 Parent(s): e2ddbfb

Create bridge_agent.py

Browse files

The frustration is completely understandable—you shouldn't have to downgrade your entire system just because one library is fighting with another.

The "Headless" architecture we were using (where one ux_agent.py tries to be both an Admin Dashboard and an API for React) is the root cause of these conflicts.

The Pro Solution is to split the interface into two distinct agents. This is a standard Microservices pattern:

BridgeAgent (New): A dedicated, lightweight API agent strictly for your React Game. It has no visual interface, uses no themes, and purely handles data.

DashboardAgent (Old UX): Your Admin Dashboard. It runs separately and can use whatever fancy UI libraries it wants without breaking the React connection.

This allows us to Upgrade back to the latest Python and Gradio versions.

Files changed (1) hide show
  1. src/bridge_agent.py +94 -0
src/bridge_agent.py ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import json
3
+ import os
4
+ import shutil
5
+ import pandas as pd
6
+ import datetime
7
+
8
+ class BridgeAgent:
9
+ def __init__(self, input_agent, brain_agent, trust_agent):
10
+ print("🌉 Bridge Agent (React API) Online.")
11
+ self.input = input_agent
12
+ self.brain = brain_agent
13
+ self.trust = trust_agent
14
+ self.PENDING_FILE = "pending_reviews.csv"
15
+
16
+ # --- 1. MISSION GENERATOR ---
17
+ def api_generate_mission(self, context):
18
+ """React calls this to get the mission text."""
19
+ mission_data = self.brain.generate_mission(context)
20
+ return json.dumps(mission_data)
21
+
22
+ # --- 2. DIALECT LIST ---
23
+ def api_get_dialects(self):
24
+ """React calls this to populate the dropdown."""
25
+ try:
26
+ if not os.path.exists(self.brain.config.DATASET_DIR): return []
27
+ csv_files = [f for f in os.listdir(self.brain.config.DATASET_DIR) if f.endswith(".csv")]
28
+ return sorted([f.replace(".csv", "") for f in csv_files])
29
+ except: return []
30
+
31
+ # --- 3. SUBMISSION HANDLER ---
32
+ def api_submit_entry(self, orig, d_drop, d_new, clar, tone, context, user_key, audio_blob):
33
+ """React calls this to submit a new recording."""
34
+ try:
35
+ # 1. Handle Audio
36
+ saved_path = "No Audio"
37
+ if audio_blob:
38
+ os.makedirs("saved_audio", exist_ok=True)
39
+ timestamp = int(pd.Timestamp.now().timestamp())
40
+ saved_path = f"saved_audio/mobile_{timestamp}.wav"
41
+ shutil.copy(audio_blob, saved_path)
42
+
43
+ # Transcribe if needed
44
+ if not orig or orig == "":
45
+ segments = self.input.transcribe(saved_path)
46
+ orig = " ".join([s["text"] for s in segments]).strip()
47
+
48
+ # 2. Determine Dialect Name
49
+ final_dialect = d_new.strip() if d_drop == "+ Add New Dialect" else d_drop
50
+
51
+ # 3. Save to Pending Queue
52
+ new_row = {
53
+ "User": user_key, "Utterance": orig, "Dialect": final_dialect,
54
+ "Clarification": clar, "Tone": tone, "Context": context,
55
+ "Audio": saved_path, "Timestamp": str(datetime.datetime.now())
56
+ }
57
+
58
+ df = pd.DataFrame([new_row])
59
+ if os.path.exists(self.PENDING_FILE):
60
+ df.to_csv(self.PENDING_FILE, mode='a', header=False, index=False)
61
+ else:
62
+ df.to_csv(self.PENDING_FILE, index=False)
63
+
64
+ return f"✅ Received: {orig[:20]}..."
65
+ except Exception as e:
66
+ print(f"Bridge Error: {e}")
67
+ return f"❌ Error: {str(e)}"
68
+
69
+ def launch(self):
70
+ """
71
+ This launches a specialized, invisible Gradio app just for the API.
72
+ """
73
+ with gr.Blocks() as api:
74
+ # Define the Inputs/Outputs invisible to the human eye, but visible to React
75
+ in_txt = gr.Textbox()
76
+ in_aud = gr.Audio(type="filepath")
77
+ out_json = gr.JSON()
78
+ out_txt = gr.Textbox()
79
+
80
+ # 1. Mission Bridge
81
+ btn_miss = gr.Button("Mission")
82
+ btn_miss.click(self.api_generate_mission, [in_txt], [out_json], api_name="generate_mission")
83
+
84
+ # 2. Dialect Bridge
85
+ btn_list = gr.Button("List")
86
+ btn_list.click(self.api_get_dialects, [], [out_json], api_name="get_dialects")
87
+
88
+ # 3. Submit Bridge (8 Arguments)
89
+ # Args: orig, d_drop, d_new, clar, tone, context, user_key, audio
90
+ args = [gr.Textbox() for _ in range(7)] + [in_aud]
91
+ btn_sub = gr.Button("Submit")
92
+ btn_sub.click(self.api_submit_entry, args, [out_txt], api_name="check_and_submit_logic")
93
+
94
+ return api