Commit
·
387f325
1
Parent(s):
3937a09
Test next word v0.1.0(Build 1)
Browse files- Dockerfile +8 -4
- README.md +4 -3
- app.py +54 -0
- requirements.txt +3 -2
Dockerfile
CHANGED
|
@@ -5,12 +5,16 @@ FROM python:3.12
|
|
| 5 |
|
| 6 |
RUN useradd -m -u 1000 user
|
| 7 |
USER user
|
| 8 |
-
ENV
|
|
|
|
| 9 |
|
| 10 |
-
WORKDIR /app
|
|
|
|
|
|
|
| 11 |
|
| 12 |
COPY --chown=user ./requirements.txt requirements.txt
|
| 13 |
RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
| 14 |
|
| 15 |
-
COPY --chown=user .
|
| 16 |
-
|
|
|
|
|
|
| 5 |
|
| 6 |
RUN useradd -m -u 1000 user
|
| 7 |
USER user
|
| 8 |
+
ENV HOME=/home/user \
|
| 9 |
+
PATH="/home/user/.local/bin:$PATH"
|
| 10 |
|
| 11 |
+
WORKDIR $HOME/app
|
| 12 |
+
|
| 13 |
+
RUN pip install --no-cache-dir --upgrade pip
|
| 14 |
|
| 15 |
COPY --chown=user ./requirements.txt requirements.txt
|
| 16 |
RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
| 17 |
|
| 18 |
+
COPY --chown=user app.py app.py
|
| 19 |
+
|
| 20 |
+
ENTRYPOINT ["solara", "run", "app.py", "--host=0.0.0.0", "--port", "7860"]
|
README.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
| 1 |
---
|
| 2 |
title: NextTokenPrediction
|
| 3 |
-
emoji:
|
| 4 |
colorFrom: purple
|
| 5 |
-
colorTo:
|
| 6 |
sdk: docker
|
| 7 |
-
pinned:
|
| 8 |
license: gemma
|
| 9 |
short_description: Visualization of probabilities of the next token Gemma3:1b
|
|
|
|
| 10 |
---
|
| 11 |
|
| 12 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
|
| 1 |
---
|
| 2 |
title: NextTokenPrediction
|
| 3 |
+
emoji: 🔀
|
| 4 |
colorFrom: purple
|
| 5 |
+
colorTo: dark-blue
|
| 6 |
sdk: docker
|
| 7 |
+
pinned: true
|
| 8 |
license: gemma
|
| 9 |
short_description: Visualization of probabilities of the next token Gemma3:1b
|
| 10 |
+
app_port: 7860
|
| 11 |
---
|
| 12 |
|
| 13 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
app.py
CHANGED
|
@@ -1,7 +1,61 @@
|
|
| 1 |
from fastapi import FastAPI
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
app = FastAPI()
|
| 4 |
|
| 5 |
@app.get("/")
|
| 6 |
def greet_json():
|
| 7 |
return {"Hello": "World!"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
from fastapi import FastAPI
|
| 2 |
+
import solara
|
| 3 |
+
import random
|
| 4 |
+
import torch
|
| 5 |
+
import torch.nn.functional as F
|
| 6 |
+
import pandas as pd
|
| 7 |
+
from transformers import AutoTokenizer, AutoModelForCausalLM
|
| 8 |
|
| 9 |
app = FastAPI()
|
| 10 |
|
| 11 |
@app.get("/")
|
| 12 |
def greet_json():
|
| 13 |
return {"Hello": "World!"}
|
| 14 |
+
|
| 15 |
+
tokenizer = AutoTokenizer.from_pretrained('gemma-3-1b-it-qat-q4_0-gguf')
|
| 16 |
+
model = AutoModelForCausalLM.from_pretrained('gemma-3-1b-it-qat-q4_0-gguf')
|
| 17 |
+
text1 = solara.reactive("Never gonna give you up, never gonna let you")
|
| 18 |
+
@solara.component
|
| 19 |
+
def Page():
|
| 20 |
+
with solara.Column(margin=10):
|
| 21 |
+
solara.Markdown("#Next token prediction visualization")
|
| 22 |
+
solara.Markdown("I built this tool to help me understand autoregressive language models. For any given text, it gives the top 10 candidates to be the next token with their respective probabilities. The language model I'm using is the smallest version of google/gemma-3-1b-it-qat-q4_0-gguf, with 1B parameters.")
|
| 23 |
+
def on_action_cell(column, row_index):
|
| 24 |
+
text1.value += tokenizer.decode(top_10.indices[0][row_index])
|
| 25 |
+
cell_actions = [solara.CellAction(icon="mdi-thumb-up", name="Select", on_click=on_action_cell)]
|
| 26 |
+
solara.InputText("Enter text:", value=text1, continuous_update=True)
|
| 27 |
+
if text1.value != "":
|
| 28 |
+
tokens = tokenizer.encode(text1.value, return_tensors="pt")
|
| 29 |
+
spans1 = ""
|
| 30 |
+
spans2 = ""
|
| 31 |
+
for i, token in enumerate(tokens[0]):
|
| 32 |
+
random.seed(i)
|
| 33 |
+
random_color = ''.join([random.choice('0123456789ABCDEF') for k in range(6)])
|
| 34 |
+
spans1 += " " + f"<span style='font-family: helvetica; color: #{random_color}'>{token}</span>"
|
| 35 |
+
spans2 += " " + f"""<span style="
|
| 36 |
+
padding: 6px;
|
| 37 |
+
border-right: 3px solid white;
|
| 38 |
+
line-height: 3em;
|
| 39 |
+
font-family: courier;
|
| 40 |
+
background-color: #{random_color};
|
| 41 |
+
color: white;
|
| 42 |
+
position: relative;
|
| 43 |
+
"><span style="
|
| 44 |
+
position: absolute;
|
| 45 |
+
top: 5.5ch;
|
| 46 |
+
line-height: 1em;
|
| 47 |
+
left: -0.5px;
|
| 48 |
+
font-size: 0.45em"> {token}</span>{tokenizer.decode([token])}</span>"""
|
| 49 |
+
solara.Markdown(f'{spans2}')
|
| 50 |
+
solara.Markdown(f'{spans1}')
|
| 51 |
+
outputs = model.generate(tokens, max_new_tokens=1, output_scores=True, return_dict_in_generate=True, pad_token_id=tokenizer.eos_token_id)
|
| 52 |
+
scores = F.softmax(outputs.scores[0], dim=-1)
|
| 53 |
+
top_10 = torch.topk(scores, 10)
|
| 54 |
+
df = pd.DataFrame()
|
| 55 |
+
df["probs"] = top_10.values[0]
|
| 56 |
+
df["probs"] = [f"{value:.2%}" for value in df["probs"].values]
|
| 57 |
+
df["next token ID"] = [top_10.indices[0][i].numpy() for i in range(10)]
|
| 58 |
+
df["predicted next token"] = [tokenizer.decode(top_10.indices[0][i]) for i in range(10)]
|
| 59 |
+
solara.Markdown("###Prediction")
|
| 60 |
+
solara.DataFrame(df, items_per_page=10, cell_actions=cell_actions)
|
| 61 |
+
Page()
|
requirements.txt
CHANGED
|
@@ -1,2 +1,3 @@
|
|
| 1 |
-
|
| 2 |
-
|
|
|
|
|
|
| 1 |
+
solara
|
| 2 |
+
pandas
|
| 3 |
+
transformers[torch]
|