ParthSadaria commited on
Commit
e0c64bd
·
verified ·
1 Parent(s): bd9598b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +67 -57
app.py CHANGED
@@ -6,10 +6,9 @@ from pydantic import BaseModel
6
  import httpx
7
  import secrets
8
  import os
9
- from typing import List, Dict, Any, Optional
10
 
11
- # Initialize FastAPI app
12
- app = FastAPI(title="AI Chat Application")
13
 
14
  # Mount static files
15
  app.mount("/static", StaticFiles(directory="static"), name="static")
@@ -19,18 +18,28 @@ security = HTTPBasic()
19
  ADMIN_USERNAME = os.environ.get("ADMIN_USERNAME", "admin")
20
  ADMIN_PASSWORD = os.environ.get("ADMIN_PASSWORD", "password") # Change in production!
21
 
22
- # Store active chats and settings in memory
23
- active_chats = {}
24
- chat_history = {}
25
- rules = [
 
 
 
 
 
 
 
 
 
 
26
  "Be respectful and helpful",
27
  "Do not generate harmful content",
28
  "Provide accurate information"
29
  ]
30
- available_models = ["mistral-large-latest", "gemini", "openai-xlarge"]
31
- current_model = "mistral-large-latest"
32
 
33
- # API endpoint for the chat
34
  class ChatMessage(BaseModel):
35
  message: str
36
  chat_id: Optional[str] = None
@@ -42,51 +51,38 @@ class Rule(BaseModel):
42
  class ModelRequest(BaseModel):
43
  model: str
44
 
45
- def get_admin_user(credentials: HTTPBasicCredentials = Depends(security)):
46
- is_username_correct = secrets.compare_digest(credentials.username, ADMIN_USERNAME)
47
- is_password_correct = secrets.compare_digest(credentials.password, ADMIN_PASSWORD)
48
- if not (is_username_correct and is_password_correct):
49
- raise HTTPException(
50
- status_code=status.HTTP_401_UNAUTHORIZED,
51
- detail="Incorrect username or password",
52
- headers={"WWW-Authenticate": "Basic"},
53
- )
54
- return credentials.username
55
-
56
  @app.get("/", response_class=HTMLResponse)
57
  async def read_root():
58
- with open("index.html", "r") as f:
59
- return f.read()
60
-
61
- @app.post("/api/chat")
 
 
 
 
 
62
  async def process_chat(chat_request: ChatMessage):
63
- # Generate a new chat ID if not provided
64
  chat_id = chat_request.chat_id or secrets.token_hex(8)
65
-
66
- # Initialize chat history if it doesn't exist
67
  if chat_id not in chat_history:
68
  chat_history[chat_id] = []
69
-
70
- # Store the message in chat history
71
  chat_history[chat_id].append({"role": "user", "content": chat_request.message})
72
-
73
- # Apply rules to message (simplified implementation)
74
  for rule in rules:
75
  if rule.startswith("Block:") and rule[6:].lower() in chat_request.message.lower():
76
- return {"response": "I cannot respond to that due to content rules.", "chat_id": chat_id}
77
-
78
- # Select model to use
79
  model_to_use = chat_request.model if chat_request.model in available_models else current_model
80
-
81
- # Prepare request to external API
82
  api_request = {
83
  "model": model_to_use,
84
  "messages": chat_history[chat_id],
85
  "temperature": 0.7,
86
  "max_tokens": 1000
87
  }
88
-
89
- # Call external API
90
  try:
91
  async with httpx.AsyncClient(timeout=60.0) as client:
92
  response = await client.post(
@@ -95,23 +91,36 @@ async def process_chat(chat_request: ChatMessage):
95
  headers={"Authorization": "sigma"}
96
  )
97
  response_data = response.json()
98
-
99
- if "choices" in response_data and len(response_data["choices"]) > 0:
100
- ai_message = response_data["choices"][0]["message"]["content"]
101
  chat_history[chat_id].append({"role": "assistant", "content": ai_message})
102
  return {"response": ai_message, "chat_id": chat_id, "model": model_to_use}
103
  else:
104
  error_msg = "No response from AI model"
105
  chat_history[chat_id].append({"role": "assistant", "content": error_msg})
106
  return {"response": error_msg, "chat_id": chat_id}
107
-
108
- except Exception as e:
109
  error_msg = f"Error communicating with AI service: {str(e)}"
110
  chat_history[chat_id].append({"role": "assistant", "content": error_msg})
111
  return {"response": error_msg, "chat_id": chat_id}
112
 
 
113
  @app.get("/admin", response_class=HTMLResponse)
114
  async def admin_panel(username: str = Depends(get_admin_user)):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  html_content = f"""
116
  <!DOCTYPE html>
117
  <html>
@@ -122,30 +131,27 @@ async def admin_panel(username: str = Depends(get_admin_user)):
122
  </head>
123
  <body class="admin-page">
124
  <h1>Admin Panel</h1>
125
-
126
  <section class="admin-section">
127
  <h2>Active Model: <span id="current-model">{current_model}</span></h2>
128
  <select id="model-selector">
129
- {"".join(f'<option value="{model}">{model}</option>' for model in available_models)}
130
  </select>
131
  <button onclick="updateModel()">Update Model</button>
132
  </section>
133
-
134
  <section class="admin-section">
135
  <h2>Rules</h2>
136
  <ul id="rules-list">
137
- {"".join(f'<li>{rule} <button onclick="deleteRule({i})">Delete</button></li>' for i, rule in enumerate(rules))}
138
  </ul>
139
  <div>
140
  <input type="text" id="new-rule" placeholder="Add new rule">
141
  <button onclick="addRule()">Add Rule</button>
142
  </div>
143
  </section>
144
-
145
  <section class="admin-section">
146
  <h2>Active Chats</h2>
147
  <ul id="active-chats">
148
- {"".join(f'<li><a href="#" onclick="viewChat(\'{chat_id}\')">{chat_id}</a></li>' for chat_id in chat_history)}
149
  </ul>
150
  <div id="chat-viewer"></div>
151
  </section>
@@ -154,23 +160,25 @@ async def admin_panel(username: str = Depends(get_admin_user)):
154
  """
155
  return HTMLResponse(content=html_content)
156
 
157
- @app.get("/api/rules")
 
158
  async def get_rules(username: str = Depends(get_admin_user)):
159
  return {"rules": rules}
160
 
161
- @app.post("/api/rules")
162
  async def add_rule(rule_request: Rule, username: str = Depends(get_admin_user)):
163
  rules.append(rule_request.rule)
164
  return {"status": "success", "rules": rules}
165
 
166
- @app.delete("/api/rules/{rule_id}")
167
  async def delete_rule(rule_id: int, username: str = Depends(get_admin_user)):
168
  if 0 <= rule_id < len(rules):
169
  rules.pop(rule_id)
170
  return {"status": "success", "rules": rules}
171
  raise HTTPException(status_code=404, detail="Rule not found")
172
 
173
- @app.post("/api/model")
 
174
  async def set_model(model_request: ModelRequest, username: str = Depends(get_admin_user)):
175
  global current_model
176
  if model_request.model in available_models:
@@ -178,11 +186,12 @@ async def set_model(model_request: ModelRequest, username: str = Depends(get_adm
178
  return {"status": "success", "model": current_model}
179
  raise HTTPException(status_code=400, detail="Invalid model")
180
 
181
- @app.get("/api/chats")
 
182
  async def get_chats(username: str = Depends(get_admin_user)):
183
  return {"chats": list(chat_history.keys())}
184
 
185
- @app.get("/api/chats/{chat_id}")
186
  async def get_chat_history(chat_id: str, username: str = Depends(get_admin_user)):
187
  if chat_id in chat_history:
188
  return {"history": chat_history[chat_id]}
@@ -190,5 +199,6 @@ async def get_chat_history(chat_id: str, username: str = Depends(get_admin_user)
190
 
191
  # Run the app (for local development)
192
  if __name__ == "__main__":
 
193
  import uvicorn
194
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
6
  import httpx
7
  import secrets
8
  import os
9
+ from typing import List, Dict, Optional
10
 
11
+ # Initialize FastAPI app\ napp = FastAPI(title="AI Chat Application")
 
12
 
13
  # Mount static files
14
  app.mount("/static", StaticFiles(directory="static"), name="static")
 
18
  ADMIN_USERNAME = os.environ.get("ADMIN_USERNAME", "admin")
19
  ADMIN_PASSWORD = os.environ.get("ADMIN_PASSWORD", "password") # Change in production!
20
 
21
+ def get_admin_user(credentials: HTTPBasicCredentials = Depends(security)):
22
+ valid_user = secrets.compare_digest(credentials.username, ADMIN_USERNAME)
23
+ valid_pass = secrets.compare_digest(credentials.password, ADMIN_PASSWORD)
24
+ if not (valid_user and valid_pass):
25
+ raise HTTPException(
26
+ status_code=status.HTTP_401_UNAUTHORIZED,
27
+ detail="Incorrect username or password",
28
+ headers={"WWW-Authenticate": "Basic"},
29
+ )
30
+ return credentials.username
31
+
32
+ # In-memory storage
33
+ chat_history: Dict[str, List[Dict[str, str]]] = {}
34
+ rules: List[str] = [
35
  "Be respectful and helpful",
36
  "Do not generate harmful content",
37
  "Provide accurate information"
38
  ]
39
+ available_models: List[str] = ["mistral-large-latest", "gemini", "openai-xlarge"]
40
+ current_model: str = available_models[0]
41
 
42
+ # Request models
43
  class ChatMessage(BaseModel):
44
  message: str
45
  chat_id: Optional[str] = None
 
51
  class ModelRequest(BaseModel):
52
  model: str
53
 
54
+ # Root endpoint to serve index.html
 
 
 
 
 
 
 
 
 
 
55
  @app.get("/", response_class=HTMLResponse)
56
  async def read_root():
57
+ try:
58
+ with open("index.html", "r") as f:
59
+ content = f.read()
60
+ return HTMLResponse(content=content)
61
+ except FileNotFoundError:
62
+ raise HTTPException(status_code=404, detail="index.html not found")
63
+
64
+ # Chat API endpoint
65
+ @app.post("/api/chat", response_class=JSONResponse)
66
  async def process_chat(chat_request: ChatMessage):
 
67
  chat_id = chat_request.chat_id or secrets.token_hex(8)
 
 
68
  if chat_id not in chat_history:
69
  chat_history[chat_id] = []
 
 
70
  chat_history[chat_id].append({"role": "user", "content": chat_request.message})
71
+
72
+ # Content rules
73
  for rule in rules:
74
  if rule.startswith("Block:") and rule[6:].lower() in chat_request.message.lower():
75
+ return JSONResponse({"response": "I cannot respond to that due to content rules.", "chat_id": chat_id})
76
+
 
77
  model_to_use = chat_request.model if chat_request.model in available_models else current_model
78
+
 
79
  api_request = {
80
  "model": model_to_use,
81
  "messages": chat_history[chat_id],
82
  "temperature": 0.7,
83
  "max_tokens": 1000
84
  }
85
+
 
86
  try:
87
  async with httpx.AsyncClient(timeout=60.0) as client:
88
  response = await client.post(
 
91
  headers={"Authorization": "sigma"}
92
  )
93
  response_data = response.json()
94
+ if choices := response_data.get("choices"):
95
+ ai_message = choices[0]["message"]["content"]
 
96
  chat_history[chat_id].append({"role": "assistant", "content": ai_message})
97
  return {"response": ai_message, "chat_id": chat_id, "model": model_to_use}
98
  else:
99
  error_msg = "No response from AI model"
100
  chat_history[chat_id].append({"role": "assistant", "content": error_msg})
101
  return {"response": error_msg, "chat_id": chat_id}
102
+ except httpx.RequestError as e:
 
103
  error_msg = f"Error communicating with AI service: {str(e)}"
104
  chat_history[chat_id].append({"role": "assistant", "content": error_msg})
105
  return {"response": error_msg, "chat_id": chat_id}
106
 
107
+ # Admin panel
108
  @app.get("/admin", response_class=HTMLResponse)
109
  async def admin_panel(username: str = Depends(get_admin_user)):
110
+ # Precompute HTML fragments
111
+ model_options = "".join(
112
+ f'<option value="{model}"{" selected" if model == current_model else ""}>{model}</option>'
113
+ for model in available_models
114
+ )
115
+ rules_list = "".join(
116
+ f'<li>{rule} <button onclick="deleteRule({i})">Delete</button></li>'
117
+ for i, rule in enumerate(rules)
118
+ )
119
+ chats_list = "".join(
120
+ f'''<li><a href="#" onclick="viewChat('{chat_id}')">{chat_id}</a></li>'''
121
+ for chat_id in chat_history
122
+ )
123
+
124
  html_content = f"""
125
  <!DOCTYPE html>
126
  <html>
 
131
  </head>
132
  <body class="admin-page">
133
  <h1>Admin Panel</h1>
 
134
  <section class="admin-section">
135
  <h2>Active Model: <span id="current-model">{current_model}</span></h2>
136
  <select id="model-selector">
137
+ {model_options}
138
  </select>
139
  <button onclick="updateModel()">Update Model</button>
140
  </section>
 
141
  <section class="admin-section">
142
  <h2>Rules</h2>
143
  <ul id="rules-list">
144
+ {rules_list}
145
  </ul>
146
  <div>
147
  <input type="text" id="new-rule" placeholder="Add new rule">
148
  <button onclick="addRule()">Add Rule</button>
149
  </div>
150
  </section>
 
151
  <section class="admin-section">
152
  <h2>Active Chats</h2>
153
  <ul id="active-chats">
154
+ {chats_list}
155
  </ul>
156
  <div id="chat-viewer"></div>
157
  </section>
 
160
  """
161
  return HTMLResponse(content=html_content)
162
 
163
+ # Rules management
164
+ @app.get("/api/rules", response_class=JSONResponse)
165
  async def get_rules(username: str = Depends(get_admin_user)):
166
  return {"rules": rules}
167
 
168
+ @app.post("/api/rules", response_class=JSONResponse)
169
  async def add_rule(rule_request: Rule, username: str = Depends(get_admin_user)):
170
  rules.append(rule_request.rule)
171
  return {"status": "success", "rules": rules}
172
 
173
+ @app.delete("/api/rules/{rule_id}", response_class=JSONResponse)
174
  async def delete_rule(rule_id: int, username: str = Depends(get_admin_user)):
175
  if 0 <= rule_id < len(rules):
176
  rules.pop(rule_id)
177
  return {"status": "success", "rules": rules}
178
  raise HTTPException(status_code=404, detail="Rule not found")
179
 
180
+ # Model selection endpoint
181
+ @app.post("/api/model", response_class=JSONResponse)
182
  async def set_model(model_request: ModelRequest, username: str = Depends(get_admin_user)):
183
  global current_model
184
  if model_request.model in available_models:
 
186
  return {"status": "success", "model": current_model}
187
  raise HTTPException(status_code=400, detail="Invalid model")
188
 
189
+ # Chat history retrieval
190
+ @app.get("/api/chats", response_class=JSONResponse)
191
  async def get_chats(username: str = Depends(get_admin_user)):
192
  return {"chats": list(chat_history.keys())}
193
 
194
+ @app.get("/api/chats/{chat_id}", response_class=JSONResponse)
195
  async def get_chat_history(chat_id: str, username: str = Depends(get_admin_user)):
196
  if chat_id in chat_history:
197
  return {"history": chat_history[chat_id]}
 
199
 
200
  # Run the app (for local development)
201
  if __name__ == "__main__":
202
+ port = int(os.environ.get("PORT", 7860))
203
  import uvicorn
204
+ uvicorn.run(app, host="0.0.0.0", port=port)