admin08077 commited on
Commit
e032c7b
·
verified ·
1 Parent(s): 5476612

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +60 -71
app.py CHANGED
@@ -6,7 +6,7 @@ from fastapi import FastAPI, HTTPException, Depends
6
  from fastapi.security import OAuth2PasswordBearer
7
  from pydantic import BaseModel
8
  from typing import List, Dict, Any
9
- import uvicorn # Ensure uvicorn is imported
10
  from supabase import create_client, Client
11
  import jwt
12
  from datetime import datetime, timedelta
@@ -46,34 +46,11 @@ def save_chat_turn(supabase_user_client: Client, user_id: str, session_id: str,
46
  except Exception as e:
47
  return {"error": f"Database insert failed: {str(e)}"}
48
 
49
- # --- FastAPI Application ---
50
- app = FastAPI()
51
-
52
- class LoginRequest(BaseModel):
53
- user_id: str
54
-
55
- class AgentRequest(BaseModel):
56
- prompt: str
57
- user_id: str
58
- session_id: str = "default-session"
59
-
60
- oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")
61
-
62
- @app.post("/login")
63
- async def login(request: LoginRequest):
64
- if not supabase_admin:
65
- raise HTTPException(status_code=500, detail="Authentication service is not configured.")
66
- user_id = request.user_id
67
- payload = { "sub": user_id, "aud": "authenticated", "exp": datetime.utcnow() + timedelta(hours=1), "role": "authenticated", }
68
- access_token = jwt.encode(payload, JWT_SECRET, algorithm="HS256")
69
- return {"access_token": access_token, "token_type": "bearer"}
70
-
71
- @app.post("/agent/invoke")
72
- async def invoke_gemini_agent(request: AgentRequest, token: str = Depends(oauth2_scheme)):
73
  try:
74
  decoded_token = jwt.decode(token, JWT_SECRET, algorithms=["HS256"], audience="authenticated")
75
- user_id = decoded_token.get("sub")
76
- if not user_id or user_id != request.user_id:
77
  raise HTTPException(status_code=401, detail="Invalid token or user mismatch.")
78
 
79
  supabase_user_client = create_client(SUPABASE_URL, SUPABASE_KEY)
@@ -82,7 +59,6 @@ async def invoke_gemini_agent(request: AgentRequest, token: str = Depends(oauth2
82
  raise HTTPException(status_code=401, detail=f"Invalid token: {e}")
83
 
84
  def get_my_chat_history():
85
- """Fetches my most recent conversation history to provide context."""
86
  return get_ai_advisor_chat_history(supabase_user_client, user_id)
87
 
88
  tools_for_gemini = [get_my_chat_history]
@@ -96,75 +72,89 @@ async def invoke_gemini_agent(request: AgentRequest, token: str = Depends(oauth2
96
  role = "user" if turn['role'] == 'user' else "model"
97
  conversation_history.append({'role': role, 'parts': [{'text': turn['content']}]})
98
 
99
- conversation_history.append({'role': 'user', 'parts': [{'text': request.prompt}]})
100
 
101
  model = genai.GenerativeModel('gemini-pro')
102
  response = model.generate_content(
103
- conversation_history,
104
- tools=tools_for_gemini,
105
- safety_settings={
106
- 'HARM_CATEGORY_DANGEROUS_CONTENT': 'BLOCK_NONE', 'HARM_CATEGORY_HARASSMENT': 'BLOCK_NONE',
107
- 'HARM_CATEGORY_HATE_SPEECH': 'BLOCK_NONE', 'HARM_CATEGORY_SEXUALLY_EXPLICIT': 'BLOCK_NONE',
108
- }
109
  )
110
  final_response_text = response.text
111
- save_chat_turn(supabase_user_client, user_id, request.session_id, request.prompt, final_response_text)
112
- return {"response": final_response_text}
113
  except Exception as e:
114
  print(f"Error in agent invocation: {e}")
115
- raise HTTPException(status_code=500, detail=str(e))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
  # --- Gradio UI ---
118
  with gr.Blocks() as demo:
119
- gr.Markdown("# 💎 Secure, Multi-User AI Agent (Upgraded)")
120
- gr.Markdown("First, 'log in' with a User ID (e.g., 'user-a', 'user-b'). This will generate a secure token. Then, you can chat with the agent, and your conversation will be saved securely to your own user record in Supabase.")
121
 
122
  user_id_state = gr.State("")
123
  token_state = gr.State("")
124
  session_id_state = gr.State("session-" + os.urandom(8).hex())
125
 
126
  with gr.Row():
127
- user_id_input = gr.Textbox(label="Enter a User ID to Log In", placeholder="e.g., user-a")
128
  login_button = gr.Button("Login")
129
  login_status = gr.Markdown("")
130
 
131
  chatbot = gr.Chatbot(label="Agent Chat", visible=False, height=500)
132
  msg_input = gr.Textbox(label="Your Message", visible=False, show_label=False, placeholder="Type your message here...")
133
 
134
- def login_fn(user_id):
 
135
  if not user_id:
136
- return {login_status: gr.update(value="<p style='color:red;'>Please enter a User ID.</p>"), user_id_state: ""}
137
  try:
138
- # For HF Spaces, the app runs on a specific port, but we call it internally via its name
139
- response = requests.post("http://localhost:7860/login", json={"user_id": user_id})
140
- if response.status_code == 200:
141
- token = response.json()["access_token"]
142
- status_html = f"<p style='color:green;'>Logged in as: {user_id}. You can start chatting now.</p>"
143
- return {
144
- login_status: gr.update(value=status_html), user_id_state: user_id, token_state: token,
145
- chatbot: gr.update(visible=True), msg_input: gr.update(visible=True),
146
- }
147
- else:
148
- return {login_status: gr.update(value=f"<p style='color:red;'>Login failed: {response.text}</p>"), user_id_state: ""}
149
- except requests.RequestException as e:
150
- return {login_status: gr.update(value=f"<p style='color:red;'>Error connecting to backend: {e}</p>"), user_id_state: ""}
151
-
152
- def chat_fn(message, chat_history, user_id, token, session_id):
153
  if not token:
154
  chat_history.append((message, "Error: You are not logged in."))
155
  return "", chat_history
156
- try:
157
- headers = {"Authorization": f"Bearer {token}"}
158
- payload = {"prompt": message, "user_id": user_id, "session_id": session_id}
159
- response = requests.post("http://localhost:7860/agent/invoke", json=payload, headers=headers)
160
-
161
- if response.status_code == 200:
162
- bot_message = response.json()["response"]
163
- else:
164
- bot_message = f"Error from agent: {response.text}"
165
- except requests.RequestException as e:
166
- bot_message = f"Error connecting to agent: {e}"
167
-
168
  chat_history.append((message, bot_message))
169
  return "", chat_history
170
 
@@ -173,6 +163,5 @@ with gr.Blocks() as demo:
173
 
174
  app = gr.mount_gradio_app(app, demo, path="/")
175
 
176
- # --- ADD THIS BLOCK AT THE VERY END ---
177
  if __name__ == "__main__":
178
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
6
  from fastapi.security import OAuth2PasswordBearer
7
  from pydantic import BaseModel
8
  from typing import List, Dict, Any
9
+ import uvicorn
10
  from supabase import create_client, Client
11
  import jwt
12
  from datetime import datetime, timedelta
 
46
  except Exception as e:
47
  return {"error": f"Database insert failed: {str(e)}"}
48
 
49
+ # --- Core Agent Logic (Refactored) ---
50
+ async def _run_agent_logic(prompt: str, user_id: str, session_id: str, token: str):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  try:
52
  decoded_token = jwt.decode(token, JWT_SECRET, algorithms=["HS256"], audience="authenticated")
53
+ if not decoded_token.get("sub") or decoded_token.get("sub") != user_id:
 
54
  raise HTTPException(status_code=401, detail="Invalid token or user mismatch.")
55
 
56
  supabase_user_client = create_client(SUPABASE_URL, SUPABASE_KEY)
 
59
  raise HTTPException(status_code=401, detail=f"Invalid token: {e}")
60
 
61
  def get_my_chat_history():
 
62
  return get_ai_advisor_chat_history(supabase_user_client, user_id)
63
 
64
  tools_for_gemini = [get_my_chat_history]
 
72
  role = "user" if turn['role'] == 'user' else "model"
73
  conversation_history.append({'role': role, 'parts': [{'text': turn['content']}]})
74
 
75
+ conversation_history.append({'role': 'user', 'parts': [{'text': prompt}]})
76
 
77
  model = genai.GenerativeModel('gemini-pro')
78
  response = model.generate_content(
79
+ conversation_history, tools=tools_for_gemini,
80
+ safety_settings={'HARM_CATEGORY_DANGEROUS_CONTENT': 'BLOCK_NONE', 'HARM_CATEGORY_HARASSMENT': 'BLOCK_NONE', 'HARM_CATEGORY_HATE_SPEECH': 'BLOCK_NONE', 'HARM_CATEGORY_SEXUALLY_EXPLICIT': 'BLOCK_NONE'}
 
 
 
 
81
  )
82
  final_response_text = response.text
83
+ save_chat_turn(supabase_user_client, user_id, session_id, prompt, final_response_text)
84
+ return final_response_text
85
  except Exception as e:
86
  print(f"Error in agent invocation: {e}")
87
+ # Return error as a string to be displayed in chat
88
+ return f"An error occurred while processing your request: {e}"
89
+
90
+ # --- FastAPI Endpoints ---
91
+ app = FastAPI()
92
+
93
+ class LoginRequest(BaseModel):
94
+ user_id: str
95
+
96
+ class AgentRequest(BaseModel):
97
+ prompt: str
98
+ user_id: str
99
+ session_id: str = "default-session"
100
+
101
+ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")
102
+
103
+ @app.post("/login")
104
+ async def login(request: LoginRequest):
105
+ if not supabase_admin: raise HTTPException(status_code=500, detail="Auth service not configured.")
106
+ user_id = request.user_id
107
+ payload = { "sub": user_id, "aud": "authenticated", "exp": datetime.utcnow() + timedelta(hours=1), "role": "authenticated" }
108
+ access_token = jwt.encode(payload, JWT_SECRET, algorithm="HS256")
109
+ return {"access_token": access_token, "token_type": "bearer"}
110
+
111
+ @app.post("/agent/invoke")
112
+ async def invoke_gemini_agent(request: AgentRequest, token: str = Depends(oauth2_scheme)):
113
+ response_text = await _run_agent_logic(request.prompt, request.user_id, request.session_id, token)
114
+ return {"response": response_text}
115
 
116
  # --- Gradio UI ---
117
  with gr.Blocks() as demo:
118
+ gr.Markdown("# 💎 Secure, Multi-User AI Agent (Live)")
119
+ gr.Markdown("Log in with a User ID (e.g., 'user-a'). This creates a secure token. Your chat history is then saved to your own user record in Supabase.")
120
 
121
  user_id_state = gr.State("")
122
  token_state = gr.State("")
123
  session_id_state = gr.State("session-" + os.urandom(8).hex())
124
 
125
  with gr.Row():
126
+ user_id_input = gr.Textbox(label="Enter User ID to Log In", placeholder="e.g., user-a")
127
  login_button = gr.Button("Login")
128
  login_status = gr.Markdown("")
129
 
130
  chatbot = gr.Chatbot(label="Agent Chat", visible=False, height=500)
131
  msg_input = gr.Textbox(label="Your Message", visible=False, show_label=False, placeholder="Type your message here...")
132
 
133
+ # CHANGED: login_fn now calls the login function directly
134
+ async def login_fn(user_id):
135
  if not user_id:
136
+ return {login_status: gr.update(value="<p style='color:red;'>Please enter a User ID.</p>")}
137
  try:
138
+ # Direct async call, no requests
139
+ token_data = await login(LoginRequest(user_id=user_id))
140
+ token = token_data["access_token"]
141
+ status_html = f"<p style='color:green;'>Logged in as: {user_id}. You can start chatting.</p>"
142
+ return {
143
+ login_status: gr.update(value=status_html), user_id_state: user_id, token_state: token,
144
+ chatbot: gr.update(visible=True), msg_input: gr.update(visible=True),
145
+ }
146
+ except Exception as e:
147
+ return {login_status: gr.update(value=f"<p style='color:red;'>Login failed: {e}</p>")}
148
+
149
+ # CHANGED: chat_fn now calls the agent logic function directly
150
+ async def chat_fn(message, chat_history, user_id, token, session_id):
 
 
151
  if not token:
152
  chat_history.append((message, "Error: You are not logged in."))
153
  return "", chat_history
154
+
155
+ # Direct async call, no requests or headers
156
+ bot_message = await _run_agent_logic(message, user_id, session_id, token)
157
+
 
 
 
 
 
 
 
 
158
  chat_history.append((message, bot_message))
159
  return "", chat_history
160
 
 
163
 
164
  app = gr.mount_gradio_app(app, demo, path="/")
165
 
 
166
  if __name__ == "__main__":
167
  uvicorn.run(app, host="0.0.0.0", port=7860)