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