AIMaster7 commited on
Commit
393ce87
·
verified ·
1 Parent(s): a294533

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +31 -25
main.py CHANGED
@@ -1,6 +1,8 @@
1
  import base64
2
  import json
3
  import os
 
 
4
  import time
5
  from typing import List, Optional
6
 
@@ -15,25 +17,20 @@ from pydantic import BaseModel
15
  load_dotenv()
16
 
17
  # Env variables for external services
18
- IMAGE_API_URL = os.environ.get("IMAGE_API_URL", "https://image.api.example.com") # Add a default for safety
19
  SNAPZION_UPLOAD_URL = "https://upload.snapzion.com/api/public-upload"
20
- SNAPZION_API_KEY = os.environ.get("SNAP", "") # Add a default for safety
21
 
22
  # --- Dummy Model Definitions ---
23
  # In a real application, these would be defined properly.
24
- # For this example, we define them here.
25
-
26
  AVAILABLE_MODELS = [
27
  {"id": "gpt-4-turbo", "object": "model", "created": int(time.time()), "owned_by": "system"},
28
  {"id": "gpt-4o", "object": "model", "created": int(time.time()), "owned_by": "system"},
29
  {"id": "gpt-3.5-turbo", "object": "model", "created": int(time.time()), "owned_by": "system"},
30
  {"id": "dall-e-3", "object": "model", "created": int(time.time()), "owned_by": "system"},
31
- # Add any other models you support
32
  ]
33
 
34
- MODEL_ALIASES = {
35
- # Example: "gpt-4": "gpt-4-turbo"
36
- }
37
 
38
  # --- FastAPI Application ---
39
 
@@ -43,9 +40,19 @@ app = FastAPI(
43
  version="1.0.0"
44
  )
45
 
46
- def unix_id():
47
- """Generates a Unix timestamp-based ID."""
48
- return str(int(time.time() * 1000))
 
 
 
 
 
 
 
 
 
 
49
 
50
  # === API Endpoints ===
51
 
@@ -54,6 +61,7 @@ async def list_models():
54
  """Lists the available models."""
55
  return {"object": "list", "data": AVAILABLE_MODELS}
56
 
 
57
  # === Chat Completion ===
58
 
59
  class Message(BaseModel):
@@ -64,19 +72,17 @@ class ChatRequest(BaseModel):
64
  messages: List[Message]
65
  model: str
66
  stream: Optional[bool] = False
67
- # Add other common parameters for compatibility if needed
68
- # max_tokens: Optional[int] = None
69
- # temperature: Optional[float] = None
70
- # user: Optional[str] = None
71
-
72
 
73
  @app.post("/v1/chat/completions")
74
  async def chat_completion(request: ChatRequest):
75
  """
76
  Handles chat completion requests, supporting both streaming and non-streaming responses.
77
- This endpoint is updated to match the OpenAI streaming chunk format precisely.
78
  """
79
  model_id = MODEL_ALIASES.get(request.model, request.model)
 
 
 
80
 
81
  headers = {
82
  'accept': 'text/event-stream',
@@ -93,7 +99,6 @@ async def chat_completion(request: ChatRequest):
93
 
94
  if request.stream:
95
  async def event_stream():
96
- chat_id = f"chatcmpl-{unix_id()}"
97
  created = int(time.time())
98
 
99
  is_first_chunk = True
@@ -121,7 +126,7 @@ async def chat_completion(request: ChatRequest):
121
  is_first_chunk = False
122
 
123
  chunk_data = {
124
- "id": chat_id,
125
  "object": "chat.completion.chunk",
126
  "created": created,
127
  "model": model_id,
@@ -140,7 +145,6 @@ async def chat_completion(request: ChatRequest):
140
  pass
141
  break
142
 
143
- # After the loop, send the final chunk with finish_reason and usage
144
  final_usage = None
145
  if usage_info:
146
  prompt_tokens = usage_info.get("promptTokens", 0)
@@ -152,7 +156,7 @@ async def chat_completion(request: ChatRequest):
152
  }
153
 
154
  done_chunk = {
155
- "id": chat_id,
156
  "object": "chat.completion.chunk",
157
  "created": created,
158
  "model": model_id,
@@ -180,7 +184,7 @@ async def chat_completion(request: ChatRequest):
180
 
181
  return StreamingResponse(event_stream(), media_type="text/event-stream")
182
  else:
183
- # Non-streaming logic remains the same
184
  assistant_response = ""
185
  usage_info = {}
186
 
@@ -203,7 +207,7 @@ async def chat_completion(request: ChatRequest):
203
  continue
204
 
205
  return JSONResponse(content={
206
- "id": f"chatcmpl-{unix_id()}",
207
  "object": "chat.completion",
208
  "created": int(time.time()),
209
  "model": model_id,
@@ -291,8 +295,10 @@ async def generate_images(request: ImageGenerationRequest):
291
 
292
  return {"created": int(time.time()), "data": results}
293
 
 
294
  if __name__ == "__main__":
295
  import uvicorn
296
- # Make sure you have a .env file with SNAP and IMAGE_API_URL
297
- # Example: uvicorn your_script_name:app --reload --port 8000
 
298
  uvicorn.run(app, host="0.0.0.0", port=8000)
 
1
  import base64
2
  import json
3
  import os
4
+ import secrets # <-- Import secrets
5
+ import string # <-- Import string
6
  import time
7
  from typing import List, Optional
8
 
 
17
  load_dotenv()
18
 
19
  # Env variables for external services
20
+ IMAGE_API_URL = os.environ.get("IMAGE_API_URL", "https://image.api.example.com")
21
  SNAPZION_UPLOAD_URL = "https://upload.snapzion.com/api/public-upload"
22
+ SNAPZION_API_KEY = os.environ.get("SNAP", "")
23
 
24
  # --- Dummy Model Definitions ---
25
  # In a real application, these would be defined properly.
 
 
26
  AVAILABLE_MODELS = [
27
  {"id": "gpt-4-turbo", "object": "model", "created": int(time.time()), "owned_by": "system"},
28
  {"id": "gpt-4o", "object": "model", "created": int(time.time()), "owned_by": "system"},
29
  {"id": "gpt-3.5-turbo", "object": "model", "created": int(time.time()), "owned_by": "system"},
30
  {"id": "dall-e-3", "object": "model", "created": int(time.time()), "owned_by": "system"},
 
31
  ]
32
 
33
+ MODEL_ALIASES = {}
 
 
34
 
35
  # --- FastAPI Application ---
36
 
 
40
  version="1.0.0"
41
  )
42
 
43
+
44
+ # --- Helper Function for Random ID Generation ---
45
+ def generate_random_id(prefix: str, length: int = 29) -> str:
46
+ """
47
+ Generates a cryptographically secure, random alphanumeric ID.
48
+ The default length of 29 characters is common for OpenAI IDs.
49
+ The example 'bwvaLjbI0KEKMadGmFbSsjYNLgaI' is 30 characters.
50
+ You can adjust the length as needed.
51
+ """
52
+ population = string.ascii_letters + string.digits
53
+ random_part = "".join(secrets.choice(population) for _ in range(length))
54
+ return f"{prefix}{random_part}"
55
+
56
 
57
  # === API Endpoints ===
58
 
 
61
  """Lists the available models."""
62
  return {"object": "list", "data": AVAILABLE_MODELS}
63
 
64
+
65
  # === Chat Completion ===
66
 
67
  class Message(BaseModel):
 
72
  messages: List[Message]
73
  model: str
74
  stream: Optional[bool] = False
 
 
 
 
 
75
 
76
  @app.post("/v1/chat/completions")
77
  async def chat_completion(request: ChatRequest):
78
  """
79
  Handles chat completion requests, supporting both streaming and non-streaming responses.
80
+ This endpoint now uses a long, random ID for completions.
81
  """
82
  model_id = MODEL_ALIASES.get(request.model, request.model)
83
+
84
+ # Generate the ID once for the entire request
85
+ chat_id = generate_random_id("chatcmpl-")
86
 
87
  headers = {
88
  'accept': 'text/event-stream',
 
99
 
100
  if request.stream:
101
  async def event_stream():
 
102
  created = int(time.time())
103
 
104
  is_first_chunk = True
 
126
  is_first_chunk = False
127
 
128
  chunk_data = {
129
+ "id": chat_id, # Use the pre-generated ID
130
  "object": "chat.completion.chunk",
131
  "created": created,
132
  "model": model_id,
 
145
  pass
146
  break
147
 
 
148
  final_usage = None
149
  if usage_info:
150
  prompt_tokens = usage_info.get("promptTokens", 0)
 
156
  }
157
 
158
  done_chunk = {
159
+ "id": chat_id, # Use the pre-generated ID
160
  "object": "chat.completion.chunk",
161
  "created": created,
162
  "model": model_id,
 
184
 
185
  return StreamingResponse(event_stream(), media_type="text/event-stream")
186
  else:
187
+ # Non-streaming logic
188
  assistant_response = ""
189
  usage_info = {}
190
 
 
207
  continue
208
 
209
  return JSONResponse(content={
210
+ "id": chat_id, # Use the pre-generated ID
211
  "object": "chat.completion",
212
  "created": int(time.time()),
213
  "model": model_id,
 
295
 
296
  return {"created": int(time.time()), "data": results}
297
 
298
+
299
  if __name__ == "__main__":
300
  import uvicorn
301
+ # To run this file:
302
+ # 1. Make sure you have a .env file with your SNAP key.
303
+ # 2. Run in your terminal: uvicorn your_script_name:app --reload --port 8000
304
  uvicorn.run(app, host="0.0.0.0", port=8000)