Spaces:
Running on Zero
Running on Zero
Upload 4 files
Browse files- README.md +91 -8
- app.py +124 -0
- model_adapters.py +132 -0
- requirements.txt +7 -0
README.md
CHANGED
|
@@ -1,14 +1,97 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: gradio
|
| 7 |
-
sdk_version:
|
| 8 |
-
python_version: '3.13'
|
| 9 |
app_file: app.py
|
| 10 |
pinned: false
|
| 11 |
-
|
|
|
|
| 12 |
---
|
| 13 |
|
| 14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: RFAB Historic Chat Space
|
| 3 |
+
emoji: 🕰️
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: purple
|
| 6 |
sdk: gradio
|
| 7 |
+
sdk_version: 5.49.1
|
|
|
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
+
models:
|
| 11 |
+
- Pclanglais/MonadGPT
|
| 12 |
---
|
| 13 |
|
| 14 |
+
# RFAB Historic Chat Gradio Space Template
|
| 15 |
+
|
| 16 |
+
This template exposes the same Gradio API shape used by Talkie-1930:
|
| 17 |
+
|
| 18 |
+
- `POST /gradio_api/call/v2/_bot_reply`
|
| 19 |
+
- `GET /gradio_api/call/_bot_reply/{event_id}`
|
| 20 |
+
|
| 21 |
+
The Reality Fabricator backend expects `_bot_reply` to accept named params:
|
| 22 |
+
|
| 23 |
+
- `history`
|
| 24 |
+
- `system_prompt`
|
| 25 |
+
- `temperature`
|
| 26 |
+
- `max_tokens`
|
| 27 |
+
- `top_p`
|
| 28 |
+
- `top_k`
|
| 29 |
+
|
| 30 |
+
## Required Variables
|
| 31 |
+
|
| 32 |
+
Set these in the Space settings:
|
| 33 |
+
|
| 34 |
+
```bash
|
| 35 |
+
RFAB_HISTORIC_MODEL_ID=Pclanglais/MonadGPT
|
| 36 |
+
RFAB_HISTORIC_ADAPTER=transformers
|
| 37 |
+
DRY_RUN=true
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
For real model inference, set `DRY_RUN=false` and choose suitable hardware.
|
| 41 |
+
|
| 42 |
+
## Model Presets
|
| 43 |
+
|
| 44 |
+
MonadGPT:
|
| 45 |
+
|
| 46 |
+
```bash
|
| 47 |
+
RFAB_HISTORIC_MODEL_ID=Pclanglais/MonadGPT
|
| 48 |
+
RFAB_HISTORIC_ADAPTER=transformers
|
| 49 |
+
RFAB_HISTORIC_MODEL_KWARGS={"torch_dtype":"auto","device_map":"auto"}
|
| 50 |
+
```
|
| 51 |
+
|
| 52 |
+
TimeCapsule:
|
| 53 |
+
|
| 54 |
+
```bash
|
| 55 |
+
RFAB_HISTORIC_MODEL_ID=haykgrigorian/TimeCapsuleLLM-v2-llama-1.2B
|
| 56 |
+
RFAB_HISTORIC_ADAPTER=transformers
|
| 57 |
+
```
|
| 58 |
+
|
| 59 |
+
GPT-1900:
|
| 60 |
+
|
| 61 |
+
```bash
|
| 62 |
+
RFAB_HISTORIC_MODEL_ID=mhla/gpt1900-instruct-v3-sft
|
| 63 |
+
RFAB_HISTORIC_ADAPTER=transformers
|
| 64 |
+
```
|
| 65 |
+
|
| 66 |
+
Mr. Chatterbox:
|
| 67 |
+
|
| 68 |
+
```bash
|
| 69 |
+
RFAB_HISTORIC_MODEL_ID=tventurella/mr_chatterbox_model
|
| 70 |
+
RFAB_HISTORIC_ADAPTER=nanochat
|
| 71 |
+
RFAB_NANOCHAT_MODEL_TAG=d18
|
| 72 |
+
RFAB_NANOCHAT_SOURCE=sft
|
| 73 |
+
```
|
| 74 |
+
|
| 75 |
+
The `nanochat` adapter is scaffolded for the Mr. Chatterbox code path. The Space must include the same nanochat package/checkpoint layout as `tventurella/mr_chatterbox` before `DRY_RUN=false`.
|
| 76 |
+
|
| 77 |
+
## Hardware
|
| 78 |
+
|
| 79 |
+
- CPU Basic is free and good for build/API contract testing.
|
| 80 |
+
- ZeroGPU requires a personal PRO account or qualifying Team/organization setup.
|
| 81 |
+
- The same Space can be upgraded later in Settings or through `huggingface_hub`; hardware changes restart the Space.
|
| 82 |
+
- Keep `@spaces.GPU` in `app.py`; it is effect-free outside ZeroGPU and required once ZeroGPU is selected.
|
| 83 |
+
|
| 84 |
+
## Backend Activation
|
| 85 |
+
|
| 86 |
+
After the Space is live:
|
| 87 |
+
|
| 88 |
+
```bash
|
| 89 |
+
curl https://<space>.hf.space/gradio_api/info
|
| 90 |
+
npm run smoke:historic-hf -- --model <model>
|
| 91 |
+
```
|
| 92 |
+
|
| 93 |
+
Copy the smoke JSON into `HISTORIC_HF_SMOKE_RESULTS_JSON` and set the matching backend URL env var, for example:
|
| 94 |
+
|
| 95 |
+
```bash
|
| 96 |
+
HISTORIC_HF_SPACE_URL_MONAD_GPT=https://rfab-historic-monad-gpt.hf.space
|
| 97 |
+
```
|
app.py
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
|
| 3 |
+
import gradio as gr
|
| 4 |
+
|
| 5 |
+
try:
|
| 6 |
+
import spaces
|
| 7 |
+
except Exception:
|
| 8 |
+
spaces = None
|
| 9 |
+
|
| 10 |
+
from model_adapters import create_adapter
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
MODEL_LABEL = os.getenv("RFAB_HISTORIC_MODEL_LABEL", os.getenv("RFAB_HISTORIC_MODEL_ID", "RFAB Historic Model"))
|
| 14 |
+
GPU_DURATION_SECONDS = int(os.getenv("RFAB_GPU_DURATION_SECONDS", "60"))
|
| 15 |
+
|
| 16 |
+
adapter = create_adapter()
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def gpu(fn):
|
| 20 |
+
if spaces is None:
|
| 21 |
+
return fn
|
| 22 |
+
return spaces.GPU(duration=GPU_DURATION_SECONDS)(fn)
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def normalize_history(history):
|
| 26 |
+
if not isinstance(history, list):
|
| 27 |
+
return []
|
| 28 |
+
|
| 29 |
+
normalized = []
|
| 30 |
+
for message in history:
|
| 31 |
+
if not isinstance(message, dict):
|
| 32 |
+
continue
|
| 33 |
+
role = message.get("role")
|
| 34 |
+
if role not in {"user", "assistant"}:
|
| 35 |
+
continue
|
| 36 |
+
content = message.get("content") or []
|
| 37 |
+
if isinstance(content, str):
|
| 38 |
+
content = [{"type": "text", "text": content}]
|
| 39 |
+
normalized.append({
|
| 40 |
+
"role": role,
|
| 41 |
+
"metadata": message.get("metadata"),
|
| 42 |
+
"content": content,
|
| 43 |
+
"options": message.get("options")
|
| 44 |
+
})
|
| 45 |
+
return normalized
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
@gpu
|
| 49 |
+
def _bot_reply(history, system_prompt="", temperature=0.7, max_tokens=256, top_p=1.0, top_k=0):
|
| 50 |
+
history = normalize_history(history)
|
| 51 |
+
answer = adapter.generate(
|
| 52 |
+
history=history,
|
| 53 |
+
system_prompt=system_prompt or "",
|
| 54 |
+
temperature=float(temperature),
|
| 55 |
+
max_tokens=int(max_tokens),
|
| 56 |
+
top_p=float(top_p),
|
| 57 |
+
top_k=int(top_k),
|
| 58 |
+
)
|
| 59 |
+
history.append({
|
| 60 |
+
"role": "assistant",
|
| 61 |
+
"metadata": None,
|
| 62 |
+
"content": [{"type": "text", "text": answer}],
|
| 63 |
+
"options": None
|
| 64 |
+
})
|
| 65 |
+
return history
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
def preview_reply(message, system_prompt, temperature, max_tokens):
|
| 69 |
+
history = [{
|
| 70 |
+
"role": "user",
|
| 71 |
+
"metadata": None,
|
| 72 |
+
"content": [{"type": "text", "text": message}],
|
| 73 |
+
"options": None
|
| 74 |
+
}]
|
| 75 |
+
result = _bot_reply(history, system_prompt, temperature, max_tokens, 1.0, 0)
|
| 76 |
+
return result[-1]["content"][0]["text"] if result else ""
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
with gr.Blocks(title=MODEL_LABEL) as demo:
|
| 80 |
+
gr.Markdown(f"# {MODEL_LABEL}")
|
| 81 |
+
gr.Markdown("Reality Fabricator Historic Chat Space. The backend uses the `_bot_reply` API endpoint.")
|
| 82 |
+
|
| 83 |
+
with gr.Row():
|
| 84 |
+
user_message = gr.Textbox(label="Message", value="What is electricity?")
|
| 85 |
+
with gr.Row():
|
| 86 |
+
system_prompt_box = gr.Textbox(label="System prompt", value="")
|
| 87 |
+
with gr.Row():
|
| 88 |
+
temperature_slider = gr.Slider(0.0, 2.0, value=0.7, step=0.05, label="Temperature")
|
| 89 |
+
max_tokens_slider = gr.Slider(16, 1024, value=256, step=1, label="Max tokens")
|
| 90 |
+
preview_button = gr.Button("Generate")
|
| 91 |
+
preview_output = gr.Textbox(label="Response")
|
| 92 |
+
|
| 93 |
+
preview_button.click(
|
| 94 |
+
preview_reply,
|
| 95 |
+
inputs=[user_message, system_prompt_box, temperature_slider, max_tokens_slider],
|
| 96 |
+
outputs=preview_output,
|
| 97 |
+
api_name=False,
|
| 98 |
+
)
|
| 99 |
+
|
| 100 |
+
history_input = gr.JSON(visible=False)
|
| 101 |
+
system_prompt_input = gr.Textbox(visible=False)
|
| 102 |
+
temperature_input = gr.Number(visible=False)
|
| 103 |
+
max_tokens_input = gr.Number(visible=False)
|
| 104 |
+
top_p_input = gr.Number(visible=False)
|
| 105 |
+
top_k_input = gr.Number(visible=False)
|
| 106 |
+
history_output = gr.JSON(visible=False)
|
| 107 |
+
|
| 108 |
+
gr.Button("API", visible=False).click(
|
| 109 |
+
_bot_reply,
|
| 110 |
+
inputs=[
|
| 111 |
+
history_input,
|
| 112 |
+
system_prompt_input,
|
| 113 |
+
temperature_input,
|
| 114 |
+
max_tokens_input,
|
| 115 |
+
top_p_input,
|
| 116 |
+
top_k_input,
|
| 117 |
+
],
|
| 118 |
+
outputs=history_output,
|
| 119 |
+
api_name="_bot_reply",
|
| 120 |
+
)
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
if __name__ == "__main__":
|
| 124 |
+
demo.queue().launch()
|
model_adapters.py
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
import os
|
| 3 |
+
from typing import Any, Dict, List
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def env_bool(name: str, default: bool = False) -> bool:
|
| 7 |
+
value = os.getenv(name)
|
| 8 |
+
if value is None:
|
| 9 |
+
return default
|
| 10 |
+
return value.strip().lower() in {"1", "true", "yes", "on"}
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def messages_to_prompt(history: List[Dict[str, Any]], system_prompt: str = "") -> str:
|
| 14 |
+
parts = []
|
| 15 |
+
if system_prompt:
|
| 16 |
+
parts.append(system_prompt.strip())
|
| 17 |
+
|
| 18 |
+
for message in history or []:
|
| 19 |
+
role = message.get("role", "user")
|
| 20 |
+
text = extract_text(message)
|
| 21 |
+
if text:
|
| 22 |
+
parts.append(f"{role}: {text}")
|
| 23 |
+
|
| 24 |
+
parts.append("assistant:")
|
| 25 |
+
return "\n".join(parts)
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
def extract_text(message: Dict[str, Any]) -> str:
|
| 29 |
+
content = message.get("content") or ""
|
| 30 |
+
if isinstance(content, str):
|
| 31 |
+
return content
|
| 32 |
+
if isinstance(content, list):
|
| 33 |
+
return "".join(
|
| 34 |
+
item.get("text", "")
|
| 35 |
+
for item in content
|
| 36 |
+
if isinstance(item, dict) and item.get("type") == "text"
|
| 37 |
+
)
|
| 38 |
+
return str(content)
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
class DryRunAdapter:
|
| 42 |
+
def __init__(self, model_id: str):
|
| 43 |
+
self.model_id = model_id
|
| 44 |
+
|
| 45 |
+
def generate(self, history, system_prompt, temperature, max_tokens, top_p, top_k):
|
| 46 |
+
last_user = ""
|
| 47 |
+
for message in reversed(history or []):
|
| 48 |
+
if message.get("role") == "user":
|
| 49 |
+
last_user = extract_text(message)
|
| 50 |
+
break
|
| 51 |
+
return (
|
| 52 |
+
f"[DRY_RUN:{self.model_id}] Historic Chat Space contract is working. "
|
| 53 |
+
f"Last user message: {last_user or 'none'}"
|
| 54 |
+
)
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
class TransformersAdapter:
|
| 58 |
+
def __init__(self, model_id: str):
|
| 59 |
+
import torch
|
| 60 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 61 |
+
|
| 62 |
+
kwargs = parse_json_env("RFAB_HISTORIC_MODEL_KWARGS", {})
|
| 63 |
+
if "torch_dtype" in kwargs and kwargs["torch_dtype"] == "auto":
|
| 64 |
+
kwargs["torch_dtype"] = "auto"
|
| 65 |
+
elif "torch_dtype" not in kwargs and torch.cuda.is_available():
|
| 66 |
+
kwargs["torch_dtype"] = torch.float16
|
| 67 |
+
|
| 68 |
+
if "device_map" not in kwargs:
|
| 69 |
+
kwargs["device_map"] = "auto" if torch.cuda.is_available() else None
|
| 70 |
+
|
| 71 |
+
kwargs = {key: value for key, value in kwargs.items() if value is not None}
|
| 72 |
+
|
| 73 |
+
self.model_id = model_id
|
| 74 |
+
self.tokenizer = AutoTokenizer.from_pretrained(model_id)
|
| 75 |
+
self.model = AutoModelForCausalLM.from_pretrained(model_id, **kwargs)
|
| 76 |
+
if not torch.cuda.is_available() and kwargs.get("device_map") is None:
|
| 77 |
+
self.model.to("cpu")
|
| 78 |
+
|
| 79 |
+
def generate(self, history, system_prompt, temperature, max_tokens, top_p, top_k):
|
| 80 |
+
import torch
|
| 81 |
+
|
| 82 |
+
prompt = messages_to_prompt(history, system_prompt)
|
| 83 |
+
inputs = self.tokenizer(prompt, return_tensors="pt", return_token_type_ids=False)
|
| 84 |
+
device = next(self.model.parameters()).device
|
| 85 |
+
inputs = {key: value.to(device) for key, value in inputs.items()}
|
| 86 |
+
|
| 87 |
+
with torch.no_grad():
|
| 88 |
+
generate_kwargs = {
|
| 89 |
+
**inputs,
|
| 90 |
+
"max_new_tokens": int(max_tokens),
|
| 91 |
+
"temperature": float(temperature),
|
| 92 |
+
"top_p": float(top_p),
|
| 93 |
+
"do_sample": float(temperature) > 0,
|
| 94 |
+
"pad_token_id": self.tokenizer.eos_token_id,
|
| 95 |
+
}
|
| 96 |
+
if int(top_k) > 0:
|
| 97 |
+
generate_kwargs["top_k"] = int(top_k)
|
| 98 |
+
output = self.model.generate(**generate_kwargs)
|
| 99 |
+
|
| 100 |
+
generated = self.tokenizer.decode(output[0], skip_special_tokens=True)
|
| 101 |
+
if generated.startswith(prompt):
|
| 102 |
+
generated = generated[len(prompt):]
|
| 103 |
+
return generated.strip()
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
class NanochatAdapter:
|
| 107 |
+
def __init__(self, model_id: str):
|
| 108 |
+
raise RuntimeError(
|
| 109 |
+
"RFAB_HISTORIC_ADAPTER=nanochat is a scaffold. Copy the nanochat runtime "
|
| 110 |
+
"from tventurella/mr_chatterbox into this Space and replace NanochatAdapter "
|
| 111 |
+
"with that loader before setting DRY_RUN=false."
|
| 112 |
+
)
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
def parse_json_env(name: str, default):
|
| 116 |
+
raw = os.getenv(name)
|
| 117 |
+
if not raw:
|
| 118 |
+
return default
|
| 119 |
+
return json.loads(raw)
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
def create_adapter():
|
| 123 |
+
model_id = os.getenv("RFAB_HISTORIC_MODEL_ID", "dry-run-model")
|
| 124 |
+
if env_bool("DRY_RUN", True):
|
| 125 |
+
return DryRunAdapter(model_id)
|
| 126 |
+
|
| 127 |
+
adapter = os.getenv("RFAB_HISTORIC_ADAPTER", "transformers").strip().lower()
|
| 128 |
+
if adapter == "transformers":
|
| 129 |
+
return TransformersAdapter(model_id)
|
| 130 |
+
if adapter == "nanochat":
|
| 131 |
+
return NanochatAdapter(model_id)
|
| 132 |
+
raise ValueError(f"Unsupported RFAB_HISTORIC_ADAPTER: {adapter}")
|
requirements.txt
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
gradio>=5.0,<6
|
| 2 |
+
transformers>=4.46
|
| 3 |
+
accelerate>=1.0
|
| 4 |
+
torch
|
| 5 |
+
sentencepiece
|
| 6 |
+
huggingface_hub
|
| 7 |
+
spaces
|