GordonHK commited on
Commit
b6f17bc
·
1 Parent(s): 0f5ff9f

feat: migrate LLM backend from HF InferenceAPI to Cerebras

Browse files

- Replace huggingface_hub InferenceClient → openai SDK (Cerebras-compatible)
- API endpoint: https://api.cerebras.ai/v1
- New models: llama3.3-70b, qwen-3-32b, llama3.1-8b (~1s each, free tier)
- Env var: CEREBRAS_API_KEY (was HF_TOKEN)
- requirements: huggingface_hub → openai>=1.30.0
- Expected speed: ~2100 tok/s vs ~100 tok/s on HF free tier

Files changed (2) hide show
  1. app.py +27 -25
  2. requirements.txt +1 -1
app.py CHANGED
@@ -1,7 +1,7 @@
1
  """
2
  HK UTM LLM Assistant — Hugging Face Spaces deployment
3
  ======================================================
4
- Pure RAG pipeline: FAISS + sentence-transformers + HF InferenceClient
5
  No langchain dependency — avoids pydantic v1/v2 conflicts on Python 3.13.
6
 
7
  Features:
@@ -13,7 +13,7 @@ Features:
13
  - Eager pipeline load at startup (background thread)
14
 
15
  Environment variables (set as HF Secrets):
16
- HF_TOKEN : Your HuggingFace API token
17
  HF_MODEL_ID : (optional) defaults to Qwen/Qwen2.5-72B-Instruct
18
  """
19
 
@@ -25,7 +25,7 @@ import gradio as gr
25
  from pathlib import Path
26
 
27
  # ── Config ────────────────────────────────────────────────────────────────────
28
- HF_TOKEN = os.environ.get("HF_TOKEN", "")
29
  INDEX_DIR = "data/processed/faiss_index"
30
  DATA_DIR = "data/raw"
31
  EMBED_MODEL = "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
@@ -41,25 +41,22 @@ CE_POOL = 6 # reduced from 12 → faster reranking, RRF pre-filters so qu
41
  CE_MODEL = "cross-encoder/ms-marco-MiniLM-L-6-v2"
42
 
43
  # ── Available LLM models (all free via HF Inference API) ─────────────────────
 
44
  LLM_MODELS = {
45
- "Qwen2.5-72B (Default ★)": {
46
- "id": "Qwen/Qwen2.5-72B-Instruct",
47
- "desc": "Best quality · strongest Chinese/English reasoning · ~20s",
48
  },
49
- "Llama-3.3-70B": {
50
- "id": "meta-llama/Llama-3.3-70B-Instruct",
51
- "desc": "Meta flagship · excellent English · fast ~5s",
52
  },
53
- "Qwen3-8B (Fast)": {
54
- "id": "Qwen/Qwen3-8B",
55
- "desc": "Lightweight · thinking-mode capable · ~3s",
56
- },
57
- "Qwen2.5-7B (Fastest)": {
58
- "id": "Qwen/Qwen2.5-7B-Instruct",
59
- "desc": "Fastest response · good for quick checks · ~2s",
60
  },
61
  }
62
- DEFAULT_MODEL_NAME = "Qwen2.5-72B (Default ★)"
63
  MODEL_NAMES = list(LLM_MODELS.keys())
64
 
65
  UTM_SYSTEM_PROMPT = """You are an expert assistant in UAS Traffic Management (UTM) \
@@ -155,7 +152,7 @@ def _load_pipeline():
155
  try:
156
  import faiss
157
  from sentence_transformers import SentenceTransformer
158
- from huggingface_hub import InferenceClient
159
 
160
  print("=== Loading pipeline at startup ===")
161
  print("Loading embedding model...")
@@ -188,11 +185,13 @@ def _load_pipeline():
188
  print("Cross-encoder (mxbai-rerank-large-v2) loaded.")
189
 
190
  print("Initialising LLM clients...")
191
- llm_clients = {
192
- name: InferenceClient(model=cfg["id"], token=HF_TOKEN)
193
- for name, cfg in LLM_MODELS.items()
194
- }
195
- print(f"LLM clients ready: {list(llm_clients.keys())}")
 
 
196
 
197
  _pipeline = {
198
  "embed_model": embed_model,
@@ -375,8 +374,11 @@ def chat(user_message: str, history: list, sidebar_state: str, model_name: str =
375
 
376
  # Non-streaming single call — more stable on mobile / weak connections
377
  try:
378
- response = llm_client.chat_completion(
379
- messages=messages, max_tokens=1024, temperature=0.3, stream=False
 
 
 
380
  )
381
  answer = response.choices[0].message.content or ""
382
  except Exception as e:
 
1
  """
2
  HK UTM LLM Assistant — Hugging Face Spaces deployment
3
  ======================================================
4
+ Pure RAG pipeline: FAISS + sentence-transformers + Cerebras Inference API
5
  No langchain dependency — avoids pydantic v1/v2 conflicts on Python 3.13.
6
 
7
  Features:
 
13
  - Eager pipeline load at startup (background thread)
14
 
15
  Environment variables (set as HF Secrets):
16
+ CEREBRAS_API_KEY : Your Cerebras Cloud API key (csk-...)
17
  HF_MODEL_ID : (optional) defaults to Qwen/Qwen2.5-72B-Instruct
18
  """
19
 
 
25
  from pathlib import Path
26
 
27
  # ── Config ────────────────────────────────────────────────────────────────────
28
+ CEREBRAS_API_KEY = os.environ.get("CEREBRAS_API_KEY", "")
29
  INDEX_DIR = "data/processed/faiss_index"
30
  DATA_DIR = "data/raw"
31
  EMBED_MODEL = "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
 
41
  CE_MODEL = "cross-encoder/ms-marco-MiniLM-L-6-v2"
42
 
43
  # ── Available LLM models (all free via HF Inference API) ─────────────────────
44
+ # Cerebras Inference API — OpenAI-compatible, ~2100 tok/s, 1M tokens/day free
45
  LLM_MODELS = {
46
+ "Llama-3.3-70B (Default ★)": {
47
+ "id": "llama3.3-70b",
48
+ "desc": "最佳質素 · 強大中英文推理 · Cerebras ~1s",
49
  },
50
+ "Qwen3-32B": {
51
+ "id": "qwen-3-32b",
52
+ "desc": "Qwen3 旗艦 · 思維模式 · 強中文 · ~1s",
53
  },
54
+ "Llama-3.1-8B (Fast)": {
55
+ "id": "llama3.1-8b",
56
+ "desc": "輕量快速 · 適合快速測試 · <1s",
 
 
 
 
57
  },
58
  }
59
+ DEFAULT_MODEL_NAME = "Llama-3.3-70B (Default ★)"
60
  MODEL_NAMES = list(LLM_MODELS.keys())
61
 
62
  UTM_SYSTEM_PROMPT = """You are an expert assistant in UAS Traffic Management (UTM) \
 
152
  try:
153
  import faiss
154
  from sentence_transformers import SentenceTransformer
155
+ from openai import OpenAI # Cerebras is OpenAI-compatible
156
 
157
  print("=== Loading pipeline at startup ===")
158
  print("Loading embedding model...")
 
185
  print("Cross-encoder (mxbai-rerank-large-v2) loaded.")
186
 
187
  print("Initialising LLM clients...")
188
+ # Single Cerebras client — model is passed per-call
189
+ cerebras_client = OpenAI(
190
+ api_key=CEREBRAS_API_KEY,
191
+ base_url="https://api.cerebras.ai/v1",
192
+ )
193
+ llm_clients = {name: cerebras_client for name in LLM_MODELS}
194
+ print(f"Cerebras client ready: {list(llm_clients.keys())}")
195
 
196
  _pipeline = {
197
  "embed_model": embed_model,
 
374
 
375
  # Non-streaming single call — more stable on mobile / weak connections
376
  try:
377
+ response = llm_client.chat.completions.create(
378
+ model=LLM_MODELS[model_name]["id"],
379
+ messages=messages,
380
+ max_tokens=1024,
381
+ temperature=0.3,
382
  )
383
  answer = response.choices[0].message.content or ""
384
  except Exception as e:
requirements.txt CHANGED
@@ -1,4 +1,4 @@
1
- huggingface_hub>=0.23.0
2
  faiss-cpu>=1.7.4
3
  sentence-transformers>=3.0.0,<4.0.0
4
  rank_bm25>=0.2.2
 
1
+ openai>=1.30.0 # Cerebras OpenAI-compatible API
2
  faiss-cpu>=1.7.4
3
  sentence-transformers>=3.0.0,<4.0.0
4
  rank_bm25>=0.2.2