Mousiol commited on
Commit
4cbdd60
·
verified ·
1 Parent(s): ec8c19d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +101 -23
app.py CHANGED
@@ -1,27 +1,43 @@
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}...")
16
- model = SentenceTransformer(
17
- MODEL_ID,
 
18
  trust_remote_code=True,
19
  device=device,
20
  model_kwargs={"torch_dtype": torch.bfloat16}
21
  )
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.")
@@ -31,7 +47,7 @@ def verify_key(provided_key: Optional[str]):
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,
@@ -45,7 +61,7 @@ def compute_embeddings(
45
  text_list = [texts] if isinstance(texts, str) else texts
46
  prompt_name = "query" if input_type == "query" else None
47
 
48
- embeddings = model.encode(
49
  text_list,
50
  prompt_name=prompt_name,
51
  normalize_embeddings=normalize,
@@ -56,47 +72,109 @@ def compute_embeddings(
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()
 
1
  import os
2
+ import sys
3
  import secrets
4
  import spaces
5
  import torch
6
  import gradio as gr
7
+ from typing import List, Union, Optional, Dict, Any
8
  from fastapi import Header, HTTPException, status
9
  from pydantic import BaseModel
10
+ from huggingface_hub import snapshot_download
11
  from sentence_transformers import SentenceTransformer
12
 
13
+ EMBED_MODEL_ID = "Dibachain/Diba-Embed"
14
+ MIZAN_MODEL_ID = "Nimruz/Mizan-v3-3B"
15
  API_KEY = os.environ.get("MY_API_KEY", "")
16
  device = "cuda" if torch.cuda.is_available() else "cpu"
17
 
18
+ # 1. Load Diba-Embed
19
+ print(f"Loading {EMBED_MODEL_ID} on {device}...")
20
+ embed_model = SentenceTransformer(
21
+ EMBED_MODEL_ID,
22
  trust_remote_code=True,
23
  device=device,
24
  model_kwargs={"torch_dtype": torch.bfloat16}
25
  )
26
+ embed_model.max_seq_length = 512
27
+ print("Diba-Embed loaded successfully!")
28
 
29
+ # 2. Download and Load Nimruz/Mizan-v3-3B via its native joint_schema_model.py
30
+ print(f"Downloading and loading {MIZAN_MODEL_ID} on {device}...")
31
+ mizan_path = snapshot_download(MIZAN_MODEL_ID)
32
+ if mizan_path not in sys.path:
33
+ sys.path.insert(0, mizan_path)
34
+
35
+ from joint_schema_model import load_release_model, systemone
36
+
37
+ mizan_model, mizan_processor = load_release_model(mizan_path, device=device)
38
+ print("Mizan-v3-3B loaded successfully!")
39
+
40
+ # 3. API Key Helper
41
  def verify_key(provided_key: Optional[str]):
42
  if not API_KEY:
43
  raise RuntimeError("MY_API_KEY secret is not configured in Space Settings.")
 
47
  detail="Invalid or missing API Key"
48
  )
49
 
50
+ # 4. ZeroGPU Function 1: Embeddings
51
  @spaces.GPU(duration=30)
52
  def compute_embeddings(
53
  api_key: str,
 
61
  text_list = [texts] if isinstance(texts, str) else texts
62
  prompt_name = "query" if input_type == "query" else None
63
 
64
+ embeddings = embed_model.encode(
65
  text_list,
66
  prompt_name=prompt_name,
67
  normalize_embeddings=normalize,
 
72
  for i, emb in enumerate(embeddings)
73
  ]
74
 
75
+ # 5. ZeroGPU Function 2: Mizan-v3-3B Decision Inference
76
+ @spaces.GPU(duration=30)
77
+ def compute_decision(
78
+ api_key: str,
79
+ state: Any,
80
+ questions: Dict[str, Any]
81
+ ):
82
+ if not API_KEY or not secrets.compare_digest(api_key or "", API_KEY):
83
+ raise gr.Error("Unauthorized: Invalid API Key")
84
+
85
+ payload = {
86
+ "model": MIZAN_MODEL_ID,
87
+ "state": state,
88
+ "questions": questions
89
+ }
90
+ with torch.no_grad():
91
+ return systemone(mizan_model, mizan_processor, payload)
92
+
93
+ # 6. Build a Tabbed Gradio Interface so ZeroGPU scans and registers BOTH @spaces.GPU functions
94
+ embed_ui = gr.Interface(
95
  fn=compute_embeddings,
96
  inputs=[
97
+ gr.Textbox(label="API Key", type="password"),
98
+ gr.Textbox(label="Input Text"),
99
  gr.Radio(["document", "query"], value="document", label="Input Type"),
100
  gr.Checkbox(value=True, label="Normalize")
101
  ],
102
+ outputs=gr.JSON(label="Embeddings Output"),
103
+ api_name=False
104
+ )
105
+
106
+ mizan_ui = gr.Interface(
107
+ fn=compute_decision,
108
+ inputs=[
109
+ gr.Textbox(label="API Key", type="password"),
110
+ gr.Textbox(label="State (Text or JSON)"),
111
+ gr.JSON(label="Questions Dict")
112
+ ],
113
+ outputs=gr.JSON(label="Decision Output"),
114
  api_name=False
115
  )
116
 
117
+ demo = gr.TabbedInterface(
118
+ [embed_ui, mizan_ui],
119
+ ["Diba-Embed", "Mizan-v3-3B"],
120
+ title="Diba-Embed & Mizan-v3-3B Private API"
121
+ )
122
+
123
+ # Launch Gradio non-blocking on port 7860
124
  demo.launch(prevent_thread_lock=True, show_api=False)
125
 
126
+ # 7. FastAPI Schemas & Custom Endpoints attached to demo.app
127
  class EmbedRequest(BaseModel):
128
  input: Union[str, List[str]]
129
  input_type: Optional[str] = "document"
130
  normalize: Optional[bool] = True
131
 
132
+ class DecisionRequest(BaseModel):
133
+ model: Optional[str] = MIZAN_MODEL_ID
134
+ state: Any
135
+ questions: Dict[str, Any]
136
+
137
+ def extract_token(authorization: Optional[str], x_api_key: Optional[str]) -> Optional[str]:
138
+ if x_api_key:
139
+ return x_api_key
140
+ if authorization and authorization.lower().startswith("bearer "):
141
+ return authorization[7:].strip()
142
+ return None
143
+
144
+ @demo.app.get("/health")
145
+ def health_check():
146
+ return {
147
+ "status": "online",
148
+ "models": [EMBED_MODEL_ID, MIZAN_MODEL_ID],
149
+ "endpoints": ["/v1/embeddings", "/v1/systemone", "/v1/decide"]
150
+ }
151
+
152
  @demo.app.post("/v1/embeddings")
153
  def create_embeddings(
154
  req: EmbedRequest,
155
  authorization: Optional[str] = Header(default=None),
156
  x_api_key: Optional[str] = Header(default=None)
157
  ):
158
+ token = extract_token(authorization, x_api_key)
 
 
 
 
159
  verify_key(token)
160
 
161
  data = compute_embeddings(token, req.input, req.input_type or "document", req.normalize)
162
  return {
163
  "object": "list",
164
+ "model": EMBED_MODEL_ID,
165
  "data": data
166
  }
167
 
168
+ @demo.app.post("/v1/systemone")
169
+ @demo.app.post("/v1/decide")
170
+ def create_decision(
171
+ req: DecisionRequest,
172
+ authorization: Optional[str] = Header(default=None),
173
+ x_api_key: Optional[str] = Header(default=None)
174
+ ):
175
+ token = extract_token(authorization, x_api_key)
176
+ verify_key(token)
177
+
178
+ return compute_decision(token, req.state, req.questions)
179
+
180
  demo.block_thread()