Daviddolor commited on
Commit
08ee52a
·
1 Parent(s): 1b12d0c

Real gateway: chat completions + Drive storage

Browse files
Files changed (3) hide show
  1. Dockerfile +14 -0
  2. app.py +73 -0
  3. requirements.txt +7 -0
Dockerfile ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10
2
+
3
+ RUN useradd -m -u 1000 user
4
+ USER user
5
+ ENV PATH="/home/user/.local/bin:$PATH"
6
+
7
+ WORKDIR /app
8
+
9
+ COPY --chown=user ./requirements.txt requirements.txt
10
+ RUN pip install --no-cache-dir --upgrade -r requirements.txt
11
+
12
+ COPY --chown=user . /app
13
+
14
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, UploadFile, File
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ import httpx, io, json, os
4
+ from googleapiclient.discovery import build
5
+ from googleapiclient.http import MediaIoBaseUpload
6
+ from google.oauth2 import service_account
7
+
8
+ app = FastAPI()
9
+ app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"])
10
+
11
+ DRIVE_FOLDER_ID = os.environ.get("DRIVE_FOLDER_ID", "")
12
+ _creds = None
13
+ drive = None
14
+
15
+ def get_drive():
16
+ global _creds, drive
17
+ if drive is None:
18
+ _creds = service_account.Credentials.from_service_account_info(
19
+ json.loads(os.environ["GOOGLE_SERVICE_ACCOUNT_JSON"]),
20
+ scopes=["https://www.googleapis.com/auth/drive"]
21
+ )
22
+ drive = build("drive", "v3", credentials=_creds)
23
+ return drive
24
+
25
+ @app.get("/")
26
+ def root():
27
+ return {"status": "Dolor D Prince API Gateway running"}
28
+
29
+ @app.post("/v1/chat/completions")
30
+ async def chat_completions(body: dict):
31
+ api_key = os.environ.get("OPENROUTER_API_KEY", "")
32
+ async with httpx.AsyncClient(timeout=60) as client:
33
+ res = await client.post(
34
+ "https://openrouter.ai/api/v1/chat/completions",
35
+ headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
36
+ json=body,
37
+ )
38
+ return res.json()
39
+
40
+ @app.post("/v1/projects/{page_id}")
41
+ async def save_project(page_id: str, body: dict):
42
+ d = get_drive()
43
+ fname = f"{page_id}.json"
44
+ media = MediaIoBaseUpload(io.BytesIO(json.dumps(body).encode()), mimetype="application/json")
45
+ existing = d.files().list(q=f"name='{fname}' and '{DRIVE_FOLDER_ID}' in parents").execute()
46
+ if existing["files"]:
47
+ d.files().update(fileId=existing["files"][0]["id"], media_body=media).execute()
48
+ else:
49
+ d.files().create(body={"name": fname, "parents": [DRIVE_FOLDER_ID]}, media_body=media).execute()
50
+ return {"status": "ok"}
51
+
52
+ @app.get("/v1/projects/{page_id}")
53
+ async def load_project(page_id: str):
54
+ d = get_drive()
55
+ fname = f"{page_id}.json"
56
+ res = d.files().list(q=f"name='{fname}' and '{DRIVE_FOLDER_ID}' in parents").execute()
57
+ if not res["files"]:
58
+ return {"data": {}}
59
+ content = d.files().get_media(fileId=res["files"][0]["id"]).execute()
60
+ return {"data": json.loads(content)}
61
+
62
+ @app.post("/v1/assets/upload")
63
+ async def upload_asset(files: list[UploadFile] = File(...)):
64
+ d = get_drive()
65
+ urls = []
66
+ for f in files:
67
+ media = MediaIoBaseUpload(io.BytesIO(await f.read()), mimetype=f.content_type)
68
+ created = d.files().create(
69
+ body={"name": f.filename, "parents": [DRIVE_FOLDER_ID]}, media_body=media, fields="id"
70
+ ).execute()
71
+ d.permissions().create(fileId=created["id"], body={"role": "reader", "type": "anyone"}).execute()
72
+ urls.append(f"https://drive.google.com/uc?id={created['id']}")
73
+ return {"data": [{"src": u} for u in urls]}
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn[standard]
3
+ httpx
4
+ python-multipart
5
+ google-api-python-client
6
+ google-auth
7
+ pydantic