OrbitMC commited on
Commit
2b52af6
Β·
verified Β·
1 Parent(s): abd7bbc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +87 -47
app.py CHANGED
@@ -1,10 +1,14 @@
 
 
 
 
 
1
  import gradio as gr
2
  import spaces
3
- import torch
4
- from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
5
- from threading import Thread
6
 
7
- # 1. DUMMY GPU FUNCTION: satisfies the Hugging Face startup checker
8
  @spaces.GPU(duration=5)
9
  def dummy_gpu():
10
  print("ZeroGPU validation satisfied.")
@@ -13,69 +17,105 @@ def dummy_gpu():
13
  # Automatically execute it once right away
14
  dummy_gpu()
15
 
16
- # 2. LOAD NATIVE PYTORCH MODEL
17
- print("Loading model via native PyTorch & Transformers...")
18
- model_id = "Qwen/Qwen2.5-1.5B-Instruct"
 
 
 
19
 
20
- # Using standard safetensors natively supported by HF.
21
- tokenizer = AutoTokenizer.from_pretrained(model_id)
22
- model = AutoModelForCausalLM.from_pretrained(
23
- model_id,
24
- torch_dtype=torch.float32, # Safe for standard CPU execution
25
- device_map="cpu", # Force pure CPU execution
26
- low_cpu_mem_usage=True
 
27
  )
28
  print("Model loaded successfully!")
29
 
30
- # 3. CHAT FUNCTION WITH STREAMING
31
- def chat_with_hf(message, history):
32
- # Format the conversation for the model
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  messages = [{"role": "system", "content": "You are a helpful AI assistant."}]
 
34
  for user_msg, assistant_msg in history:
35
  messages.append({"role": "user", "content": user_msg})
36
  messages.append({"role": "assistant", "content": assistant_msg})
37
 
38
  messages.append({"role": "user", "content": message})
39
 
40
- # Convert chat to model tokens
41
- input_ids = tokenizer.apply_chat_template(
42
- messages,
43
- add_generation_prompt=True,
44
- return_tensors="pt"
45
- ).to("cpu")
46
-
47
- # Streamer to yield words one by one to Gradio
48
- streamer = TextIteratorStreamer(tokenizer, timeout=10.0, skip_prompt=True, skip_special_tokens=True)
49
-
50
- # Generation arguments
51
- generate_kwargs = dict(
52
- input_ids=input_ids,
53
- streamer=streamer,
54
- max_new_tokens=512,
55
  temperature=0.7,
56
- top_p=0.9,
57
- do_sample=True
58
  )
59
 
60
- # Start generation in a background thread so the streamer can yield in real-time
61
- t = Thread(target=model.generate, kwargs=generate_kwargs)
62
- t.start()
63
-
64
- # Yield the text back to Gradio UI
65
  partial_response = ""
66
- for new_text in streamer:
67
- partial_response += new_text
68
- yield partial_response
 
 
 
69
 
70
- # 4. LAUNCH GRADIO APP
71
  with gr.Blocks() as demo:
72
- gr.Markdown("# Native CPU PyTorch Execution on ZeroGPU Space")
73
- gr.Markdown("Running **Qwen2.5-1.5B** entirely via standard Hugging Face `transformers` and `torch`. No C++, no compilations, no GGUF.")
 
 
 
 
 
 
74
 
75
  gr.ChatInterface(
76
- fn=chat_with_hf,
77
  examples=["Who are you?", "Write a python script to reverse a string.", "Explain quantum computing."],
78
  )
79
 
 
 
 
 
80
  if __name__ == "__main__":
81
- demo.launch(server_name="0.0.0.0", server_port=7860)
 
1
+ import os
2
+ import json
3
+ import uvicorn
4
+ from fastapi import FastAPI, Request
5
+ from fastapi.responses import StreamingResponse, JSONResponse
6
  import gradio as gr
7
  import spaces
8
+ from huggingface_hub import hf_hub_download
9
+ from llama_cpp import Llama
 
10
 
11
+ # 1. DUMMY GPU FUNCTION: Satisfies the Hugging Face ZeroGPU checks
12
  @spaces.GPU(duration=5)
13
  def dummy_gpu():
14
  print("ZeroGPU validation satisfied.")
 
17
  # Automatically execute it once right away
18
  dummy_gpu()
19
 
20
+ # 2. DOWNLOAD LFM 2.5 8B A1B GGUF MODEL
21
+ print("Downloading LFM2.5-8B-A1B-GGUF model...")
22
+ model_path = hf_hub_download(
23
+ repo_id="LiquidAI/LFM2.5-8B-A1B-GGUF",
24
+ filename="LFM2.5-8B-A1B-Q4_K_M.gguf"
25
+ )
26
 
27
+ # 3. LOAD MODEL DIRECTLY IN PYTHON (CPU ONLY)
28
+ print("Loading model into memory via llama-cpp-python...")
29
+ llm = Llama(
30
+ model_path=model_path,
31
+ n_ctx=8192, # Safe context limit for RAM
32
+ n_threads=2, # Optimal for standard HF CPU Space
33
+ chat_format="chatml", # Native format used by LFM2.5
34
+ verbose=False
35
  )
36
  print("Model loaded successfully!")
37
 
38
+ # 4. BUILD FASTAPI APP FOR NATIVE OPENAI-COMPATIBLE ENDPOINTS
39
+ app = FastAPI(title="LFM2.5-8B API Server")
40
+
41
+ @app.post("/v1/chat/completions")
42
+ async def chat_api(request: Request):
43
+ """
44
+ OpenAI-compatible API Endpoint!
45
+ You can send JSON payloads here exactly as you would to the OpenAI API.
46
+ """
47
+ try:
48
+ body = await request.json()
49
+ messages = body.get("messages", [])
50
+ stream = body.get("stream", False)
51
+ temperature = body.get("temperature", 0.7)
52
+ max_tokens = body.get("max_tokens", 1024)
53
+
54
+ if stream:
55
+ def stream_generator():
56
+ for chunk in llm.create_chat_completion(
57
+ messages=messages,
58
+ stream=True,
59
+ temperature=temperature,
60
+ max_tokens=max_tokens
61
+ ):
62
+ yield f"data: {json.dumps(chunk)}\n\n"
63
+ yield "data: [DONE]\n\n"
64
+ return StreamingResponse(stream_generator(), media_type="text/event-stream")
65
+ else:
66
+ response = llm.create_chat_completion(
67
+ messages=messages,
68
+ stream=False,
69
+ temperature=temperature,
70
+ max_tokens=max_tokens
71
+ )
72
+ return JSONResponse(content=response)
73
+ except Exception as e:
74
+ return JSONResponse(status_code=500, content={"error": str(e)})
75
+
76
+ # 5. BUILD GRADIO UI (Fallback Web Interface)
77
+ def chat_with_llama(message, history):
78
  messages = [{"role": "system", "content": "You are a helpful AI assistant."}]
79
+
80
  for user_msg, assistant_msg in history:
81
  messages.append({"role": "user", "content": user_msg})
82
  messages.append({"role": "assistant", "content": assistant_msg})
83
 
84
  messages.append({"role": "user", "content": message})
85
 
86
+ stream = llm.create_chat_completion(
87
+ messages=messages,
88
+ stream=True,
 
 
 
 
 
 
 
 
 
 
 
 
89
  temperature=0.7,
90
+ max_tokens=1024
 
91
  )
92
 
 
 
 
 
 
93
  partial_response = ""
94
+ for chunk in stream:
95
+ if "choices" in chunk and len(chunk["choices"]) > 0:
96
+ delta = chunk["choices"][0].get("delta", {})
97
+ if "content" in delta:
98
+ partial_response += delta["content"]
99
+ yield partial_response
100
 
 
101
  with gr.Blocks() as demo:
102
+ gr.Markdown("# πŸš€ LiquidAI LFM2.5-8B-A1B (CPU & API Enabled)")
103
+ gr.Markdown("""
104
+ Running **LFM2.5-8B-A1B** natively via `llama-cpp-python` entirely on CPU! ZeroGPU is bypassed safely.
105
+
106
+ ### πŸ”Œ Developer API Available!
107
+ This Space also silently hosts a real API endpoint. You can query it using standard Python code without using the Web UI.
108
+ **Endpoint:** `POST /v1/chat/completions` (Supports Streaming & Non-Streaming)
109
+ """)
110
 
111
  gr.ChatInterface(
112
+ fn=chat_with_llama,
113
  examples=["Who are you?", "Write a python script to reverse a string.", "Explain quantum computing."],
114
  )
115
 
116
+ # 6. MOUNT GRADIO ON FASTAPI & LAUNCH
117
+ # This runs the API and the Web UI simultaneously on the same port!
118
+ app = gr.mount_gradio_app(app, demo, path="/")
119
+
120
  if __name__ == "__main__":
121
+ uvicorn.run(app, host="0.0.0.0", port=7860)