Mousiol commited on
Commit
88db80d
·
verified ·
1 Parent(s): f26be42

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +43 -15
app.py CHANGED
@@ -1,11 +1,15 @@
 
 
1
  import spaces
2
  import torch
3
  import gradio as gr
4
  from typing import List, Union, Optional
 
5
  from pydantic import BaseModel
6
  from sentence_transformers import SentenceTransformer
7
 
8
  MODEL_ID = "Dibachain/Diba-Embed"
 
9
  device = "cuda" if torch.cuda.is_available() else "cpu"
10
 
11
  print(f"Loading {MODEL_ID}...")
@@ -18,9 +22,26 @@ model = SentenceTransformer(
18
  model.max_seq_length = 512
19
  print("Model loaded successfully!")
20
 
21
- # 1. Put @spaces.GPU directly on the function bound to Gradio so ZeroGPU detects it at startup
 
 
 
 
 
 
 
 
 
22
  @spaces.GPU(duration=30)
23
- def compute_embeddings(texts: Union[str, List[str]], input_type: str = "document", normalize: bool = True):
 
 
 
 
 
 
 
 
24
  text_list = [texts] if isinstance(texts, str) else texts
25
  prompt_name = "query" if input_type == "query" else None
26
 
@@ -35,40 +56,47 @@ def compute_embeddings(texts: Union[str, List[str]], input_type: str = "document
35
  for i, emb in enumerate(embeddings)
36
  ]
37
 
38
- # 2. Wire compute_embeddings directly to gr.Interface (required by ZeroGPU scanner)
39
  demo = gr.Interface(
40
  fn=compute_embeddings,
41
  inputs=[
 
42
  gr.Textbox(label="Input Text", placeholder="Enter text to embed..."),
43
  gr.Radio(["document", "query"], value="document", label="Input Type"),
44
  gr.Checkbox(value=True, label="Normalize")
45
  ],
46
  outputs=gr.JSON(label="Output"),
47
- title="Diba-Embed API",
48
- description="POST to `/v1/embeddings` for standard OpenAI-compatible JSON responses."
49
  )
50
 
51
- # 3. Start Gradio non-blocking so it binds port 7860 once and registers ZeroGPU
52
- demo.launch(prevent_thread_lock=True)
53
 
54
- # 4. Attach your custom /v1/embeddings route directly to Gradio's internal FastAPI server (demo.app)
55
  class EmbedRequest(BaseModel):
56
  input: Union[str, List[str]]
57
  input_type: Optional[str] = "document"
58
  normalize: Optional[bool] = True
59
 
60
- @demo.app.get("/health")
61
- def health_check():
62
- return {"status": "online", "model": MODEL_ID}
63
-
64
  @demo.app.post("/v1/embeddings")
65
- def create_embeddings(req: EmbedRequest):
66
- data = compute_embeddings(req.input, req.input_type or "document", req.normalize)
 
 
 
 
 
 
 
 
 
 
 
67
  return {
68
  "object": "list",
69
  "model": MODEL_ID,
70
  "data": data
71
  }
72
 
73
- # Keep the main process alive
74
  demo.block_thread()
 
1
+ import os
2
+ import secrets
3
  import spaces
4
  import torch
5
  import gradio as gr
6
  from typing import List, Union, Optional
7
+ from fastapi import Header, HTTPException, status
8
  from pydantic import BaseModel
9
  from sentence_transformers import SentenceTransformer
10
 
11
  MODEL_ID = "Dibachain/Diba-Embed"
12
+ API_KEY = os.environ.get("MY_API_KEY", "")
13
  device = "cuda" if torch.cuda.is_available() else "cpu"
14
 
15
  print(f"Loading {MODEL_ID}...")
 
22
  model.max_seq_length = 512
23
  print("Model loaded successfully!")
24
 
25
+ def verify_key(provided_key: Optional[str]):
26
+ if not API_KEY:
27
+ raise RuntimeError("MY_API_KEY secret is not configured in Space Settings.")
28
+ if not provided_key or not secrets.compare_digest(provided_key, API_KEY):
29
+ raise HTTPException(
30
+ status_code=status.HTTP_401_UNAUTHORIZED,
31
+ detail="Invalid or missing API Key"
32
+ )
33
+
34
+ # 1. ZeroGPU function protected with an internal key check so random visitors can't use the UI
35
  @spaces.GPU(duration=30)
36
+ def compute_embeddings(
37
+ api_key: str,
38
+ texts: Union[str, List[str]],
39
+ input_type: str = "document",
40
+ normalize: bool = True
41
+ ):
42
+ if not API_KEY or not secrets.compare_digest(api_key or "", API_KEY):
43
+ raise gr.Error("Unauthorized: Invalid API Key")
44
+
45
  text_list = [texts] if isinstance(texts, str) else texts
46
  prompt_name = "query" if input_type == "query" else None
47
 
 
56
  for i, emb in enumerate(embeddings)
57
  ]
58
 
59
+ # 2. Gradio Interface (api_name=False hides it from public Gradio API clients)
60
  demo = gr.Interface(
61
  fn=compute_embeddings,
62
  inputs=[
63
+ gr.Textbox(label="API Key", type="password", placeholder="Enter MY_API_KEY..."),
64
  gr.Textbox(label="Input Text", placeholder="Enter text to embed..."),
65
  gr.Radio(["document", "query"], value="document", label="Input Type"),
66
  gr.Checkbox(value=True, label="Normalize")
67
  ],
68
  outputs=gr.JSON(label="Output"),
69
+ title="Diba-Embed Private API",
70
+ api_name=False
71
  )
72
 
73
+ # 3. Launch Gradio with show_api=False to disable public /gradio_api docs
74
+ demo.launch(prevent_thread_lock=True, show_api=False)
75
 
76
+ # 4. Protected FastAPI /v1/embeddings endpoint
77
  class EmbedRequest(BaseModel):
78
  input: Union[str, List[str]]
79
  input_type: Optional[str] = "document"
80
  normalize: Optional[bool] = True
81
 
 
 
 
 
82
  @demo.app.post("/v1/embeddings")
83
+ def create_embeddings(
84
+ req: EmbedRequest,
85
+ authorization: Optional[str] = Header(default=None),
86
+ x_api_key: Optional[str] = Header(default=None)
87
+ ):
88
+ # Accept either "Authorization: Bearer <MY_API_KEY>" or "X-API-Key: <MY_API_KEY>"
89
+ token = x_api_key
90
+ if not token and authorization and authorization.lower().startswith("bearer "):
91
+ token = authorization[7:].strip()
92
+
93
+ verify_key(token)
94
+
95
+ data = compute_embeddings(token, req.input, req.input_type or "document", req.normalize)
96
  return {
97
  "object": "list",
98
  "model": MODEL_ID,
99
  "data": data
100
  }
101
 
 
102
  demo.block_thread()