Niansuh commited on
Commit
d80a70b
·
verified ·
1 Parent(s): b59c7b9

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +63 -43
main.py CHANGED
@@ -7,7 +7,6 @@ from typing import Any, Dict, List, Optional
7
 
8
  import httpx
9
  import uvicorn
10
- from dotenv import load_dotenv
11
  from fastapi import FastAPI, HTTPException, Depends
12
  from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
13
  from pydantic import BaseModel
@@ -20,26 +19,43 @@ logging.basicConfig(
20
  )
21
  logger = logging.getLogger(__name__)
22
 
23
- # Load Environment Variables
 
 
24
  load_dotenv()
 
25
  app = FastAPI()
26
 
27
- # Configuration Constants
28
- BASE_URL = "https://aichatonlineorg.erweima.ai/aichatonline"
 
 
 
 
 
 
 
 
 
29
  APP_SECRET = os.getenv("APP_SECRET", "666")
30
  ACCESS_TOKEN = os.getenv("SD_ACCESS_TOKEN", "")
31
- headers = {
 
 
 
 
 
32
  'accept': '*/*',
33
- 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
 
34
  'authorization': f'Bearer {ACCESS_TOKEN}',
35
- 'cache-control': 'no-cache',
36
- 'origin': 'chrome-extension://dhoenijjpgpeimemopealfcbiecgceod',
37
- 'pragma': 'no-cache',
38
  'priority': 'u=1, i',
39
  'sec-fetch-dest': 'empty',
40
  'sec-fetch-mode': 'cors',
41
  'sec-fetch-site': 'none',
42
- 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0',
43
  }
44
 
45
  # Updated ALLOWED_MODELS List (No Duplicates)
@@ -59,25 +75,28 @@ ALLOWED_MODELS = [
59
  # Configure CORS
60
  app.add_middleware(
61
  CORSMiddleware,
62
- allow_origins=["*"], # Restrict this to specific origins in production
63
  allow_credentials=True,
64
- allow_methods=["*"], # All methods allowed
65
  allow_headers=["*"], # Allow all headers
66
  )
67
 
68
- # Security Configuration
69
  security = HTTPBearer()
70
 
 
71
  # Pydantic Models
72
  class Message(BaseModel):
73
  role: str
74
  content: str
75
 
 
76
  class ChatRequest(BaseModel):
77
  model: str
78
  messages: List[Message]
79
  stream: Optional[bool] = False
80
 
 
81
  # Utility Functions
82
  def create_chat_completion_data(content: str, model: str, finish_reason: Optional[str] = None) -> Dict[str, Any]:
83
  return {
@@ -95,6 +114,7 @@ def create_chat_completion_data(content: str, model: str, finish_reason: Optiona
95
  "usage": None,
96
  }
97
 
 
98
  def verify_app_secret(credentials: HTTPAuthorizationCredentials = Depends(security)):
99
  if credentials.credentials != APP_SECRET:
100
  logger.warning(f"Invalid APP_SECRET provided: {credentials.credentials}")
@@ -102,6 +122,7 @@ def verify_app_secret(credentials: HTTPAuthorizationCredentials = Depends(securi
102
  logger.info("APP_SECRET verified successfully.")
103
  return credentials.credentials
104
 
 
105
  # CORS Preflight Options Endpoint
106
  @app.options("/hf/v1/chat/completions")
107
  async def chat_completions_options():
@@ -114,15 +135,13 @@ async def chat_completions_options():
114
  },
115
  )
116
 
117
- # Replace Escaped Newlines
118
- def replace_escaped_newlines(input_string: str) -> str:
119
- return input_string.replace("\\n", "\n")
120
 
121
  # List Available Models
122
  @app.get("/hf/v1/models")
123
  async def list_models():
124
  return {"object": "list", "data": ALLOWED_MODELS}
125
 
 
126
  # Chat Completions Endpoint
127
  @app.post("/hf/v1/chat/completions")
128
  async def chat_completions(
@@ -133,7 +152,7 @@ async def chat_completions(
133
  # Validate Selected Model
134
  if request.model not in [model['id'] for model in ALLOWED_MODELS]:
135
  allowed = ', '.join(model['id'] for model in ALLOWED_MODELS)
136
- logger.error(f"Model {request.model} is not allowed.")
137
  raise HTTPException(
138
  status_code=400,
139
  detail=f"Model '{request.model}' is not allowed. Allowed models are: {allowed}",
@@ -141,48 +160,48 @@ async def chat_completions(
141
 
142
  logger.info(f"Using model: {request.model}")
143
 
144
- # Generate a UUID
145
- original_uuid = uuid.uuid4()
146
- uuid_str = str(original_uuid).replace("-", "")
147
- logger.debug(f"Generated UUID: {uuid_str}")
148
 
149
  # Prepare JSON Payload for External API
150
- json_data = {
151
- 'prompt': "\n".join(
 
 
152
  [
153
  f"{'User' if msg.role == 'user' else 'Assistant'}: {msg.content}"
154
  for msg in request.messages
155
  ]
156
- ),
157
- 'stream': True,
158
- 'app_name': 'ChitChat_Edge_Ext',
159
- 'app_version': '4.26.1',
160
- 'tz_name': 'Asia/Karachi',
161
- 'cid': '',
162
- 'model': request.model, # Use the selected model directly
 
 
 
163
  'search': False,
164
  'auto_search': False,
165
  'filter_search_history': False,
166
  'from': 'chat',
167
  'group_id': 'default',
168
- 'chat_models': [request.model], # Include the model in chat_models
169
  'files': [],
170
  'prompt_template': {
171
- 'key': '',
172
  'attributes': {
173
- 'lang': 'original',
174
  },
175
  },
176
  'tools': {
177
- 'auto': [
178
- 'search',
179
- 'text_to_image',
180
- 'data_analysis',
181
- ],
182
  },
183
  'extra_info': {
184
- 'origin_url': '',
185
- 'origin_title': '',
186
  },
187
  }
188
 
@@ -193,8 +212,8 @@ async def chat_completions(
193
  try:
194
  async with client.stream(
195
  'POST',
196
- 'https://sider.ai/api/v2/completion/text',
197
- headers=headers,
198
  json=json_data,
199
  timeout=120.0
200
  ) as response:
@@ -237,7 +256,7 @@ async def chat_completions(
237
  full_response += data["choices"][0]["delta"]["content"]
238
  except json.JSONDecodeError:
239
  logger.warning(f"Failed to decode JSON from chunk: {chunk}")
240
-
241
  # Final Response Structure
242
  return {
243
  "id": f"chatcmpl-{uuid.uuid4()}",
@@ -254,6 +273,7 @@ async def chat_completions(
254
  "usage": None,
255
  }
256
 
 
257
  # Entry Point
258
  if __name__ == "__main__":
259
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
7
 
8
  import httpx
9
  import uvicorn
 
10
  from fastapi import FastAPI, HTTPException, Depends
11
  from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
12
  from pydantic import BaseModel
 
19
  )
20
  logger = logging.getLogger(__name__)
21
 
22
+ # Load Environment Variables for Sensitive Information
23
+ from dotenv import load_dotenv
24
+
25
  load_dotenv()
26
+
27
  app = FastAPI()
28
 
29
+ # Configuration Constants (Hardcoded as per requirements)
30
+ APP_NAME = "ChitChat_Chrome_Ext"
31
+ APP_VERSION = "4.28.0"
32
+ ORIGIN_URL = "chrome-extension://difoiogjjojoaoomphldepapgpbgkhkb/standalone.html?from=sidebar"
33
+ ORIGIN_TITLE = "Sider"
34
+ TZ_NAME = "Asia/Karachi"
35
+ PROMPT_TEMPLATE_KEY = "artifacts"
36
+ PROMPT_TEMPLATE_LANG = "original"
37
+ TOOLS_AUTO = ["search", "text_to_image", "data_analysis"]
38
+
39
+ # Security Configuration
40
  APP_SECRET = os.getenv("APP_SECRET", "666")
41
  ACCESS_TOKEN = os.getenv("SD_ACCESS_TOKEN", "")
42
+ if not ACCESS_TOKEN:
43
+ logger.error("SD_ACCESS_TOKEN is not set in the environment variables.")
44
+ raise RuntimeError("SD_ACCESS_TOKEN is required but not set.")
45
+
46
+ # Outgoing Request Headers (As per provided sample)
47
+ OUTGOING_HEADERS = {
48
  'accept': '*/*',
49
+ 'accept-encoding': 'gzip, deflate, br, zstd',
50
+ 'accept-language': 'en-US,en;q=0.9',
51
  'authorization': f'Bearer {ACCESS_TOKEN}',
52
+ 'content-type': 'application/json',
53
+ 'origin': 'chrome-extension://difoiogjjojoaoomphldepapgpbgkhkb',
 
54
  'priority': 'u=1, i',
55
  'sec-fetch-dest': 'empty',
56
  'sec-fetch-mode': 'cors',
57
  'sec-fetch-site': 'none',
58
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
59
  }
60
 
61
  # Updated ALLOWED_MODELS List (No Duplicates)
 
75
  # Configure CORS
76
  app.add_middleware(
77
  CORSMiddleware,
78
+ allow_origins=["*"], # ⚠️ IMPORTANT: Restrict this to specific origins in production for security
79
  allow_credentials=True,
80
+ allow_methods=["*"], # Allow all HTTP methods
81
  allow_headers=["*"], # Allow all headers
82
  )
83
 
84
+ # Security Dependency
85
  security = HTTPBearer()
86
 
87
+
88
  # Pydantic Models
89
  class Message(BaseModel):
90
  role: str
91
  content: str
92
 
93
+
94
  class ChatRequest(BaseModel):
95
  model: str
96
  messages: List[Message]
97
  stream: Optional[bool] = False
98
 
99
+
100
  # Utility Functions
101
  def create_chat_completion_data(content: str, model: str, finish_reason: Optional[str] = None) -> Dict[str, Any]:
102
  return {
 
114
  "usage": None,
115
  }
116
 
117
+
118
  def verify_app_secret(credentials: HTTPAuthorizationCredentials = Depends(security)):
119
  if credentials.credentials != APP_SECRET:
120
  logger.warning(f"Invalid APP_SECRET provided: {credentials.credentials}")
 
122
  logger.info("APP_SECRET verified successfully.")
123
  return credentials.credentials
124
 
125
+
126
  # CORS Preflight Options Endpoint
127
  @app.options("/hf/v1/chat/completions")
128
  async def chat_completions_options():
 
135
  },
136
  )
137
 
 
 
 
138
 
139
  # List Available Models
140
  @app.get("/hf/v1/models")
141
  async def list_models():
142
  return {"object": "list", "data": ALLOWED_MODELS}
143
 
144
+
145
  # Chat Completions Endpoint
146
  @app.post("/hf/v1/chat/completions")
147
  async def chat_completions(
 
152
  # Validate Selected Model
153
  if request.model not in [model['id'] for model in ALLOWED_MODELS]:
154
  allowed = ', '.join(model['id'] for model in ALLOWED_MODELS)
155
+ logger.error(f"Model '{request.model}' is not allowed.")
156
  raise HTTPException(
157
  status_code=400,
158
  detail=f"Model '{request.model}' is not allowed. Allowed models are: {allowed}",
 
160
 
161
  logger.info(f"Using model: {request.model}")
162
 
163
+ # Generate a unique CID for each request
164
+ cid = str(uuid.uuid4()).replace("-", "").upper()[:12] # Example: C0MES13070J1
165
+ logger.debug(f"Generated CID: {cid}")
 
166
 
167
  # Prepare JSON Payload for External API
168
+ if not request.messages:
169
+ prompt_text = "make a dog"
170
+ else:
171
+ prompt_text = "\n".join(
172
  [
173
  f"{'User' if msg.role == 'user' else 'Assistant'}: {msg.content}"
174
  for msg in request.messages
175
  ]
176
+ )
177
+
178
+ json_data = {
179
+ 'prompt': prompt_text,
180
+ 'stream': request.stream,
181
+ 'app_name': APP_NAME,
182
+ 'app_version': APP_VERSION,
183
+ 'tz_name': TZ_NAME,
184
+ 'cid': cid,
185
+ 'model': request.model,
186
  'search': False,
187
  'auto_search': False,
188
  'filter_search_history': False,
189
  'from': 'chat',
190
  'group_id': 'default',
191
+ 'chat_models': [], # As per the sample payload
192
  'files': [],
193
  'prompt_template': {
194
+ 'key': PROMPT_TEMPLATE_KEY,
195
  'attributes': {
196
+ 'lang': PROMPT_TEMPLATE_LANG,
197
  },
198
  },
199
  'tools': {
200
+ 'auto': TOOLS_AUTO,
 
 
 
 
201
  },
202
  'extra_info': {
203
+ 'origin_url': ORIGIN_URL,
204
+ 'origin_title': ORIGIN_TITLE,
205
  },
206
  }
207
 
 
212
  try:
213
  async with client.stream(
214
  'POST',
215
+ 'https://sider.ai/api/v3/completion/text', # Updated endpoint
216
+ headers=OUTGOING_HEADERS,
217
  json=json_data,
218
  timeout=120.0
219
  ) as response:
 
256
  full_response += data["choices"][0]["delta"]["content"]
257
  except json.JSONDecodeError:
258
  logger.warning(f"Failed to decode JSON from chunk: {chunk}")
259
+
260
  # Final Response Structure
261
  return {
262
  "id": f"chatcmpl-{uuid.uuid4()}",
 
273
  "usage": None,
274
  }
275
 
276
+
277
  # Entry Point
278
  if __name__ == "__main__":
279
  uvicorn.run(app, host="0.0.0.0", port=7860)