Spaces:
Sleeping
Sleeping
Commit ·
dd678c1
1
Parent(s): b911f86
app model check
Browse files- Dockerfile +8 -1
- README.md +46 -50
- apps/gradio-space/pyproject.toml +2 -0
- apps/gradio-space/src/gradio_space/app.py +0 -3
- apps/gradio-space/src/gradio_space/model_loading.py +23 -0
- apps/gradio-space/src/gradio_space/tabs/chat.py +2 -29
- libs/agent/tests/test_runner.py +23 -0
- models.yaml +1 -1
- pyproject.toml +2 -0
- scripts/upload_trace.py +54 -0
Dockerfile
CHANGED
|
@@ -16,8 +16,11 @@ WORKDIR /app
|
|
| 16 |
COPY pyproject.toml uv.lock .python-version README.md models.yaml ./
|
| 17 |
COPY apps/gradio-space/pyproject.toml apps/gradio-space/README.md apps/gradio-space/
|
| 18 |
COPY libs/inference/pyproject.toml libs/inference/README.md libs/inference/
|
|
|
|
| 19 |
COPY apps/gradio-space/src apps/gradio-space/src
|
| 20 |
COPY libs/inference/src libs/inference/src
|
|
|
|
|
|
|
| 21 |
|
| 22 |
RUN useradd -m -u 1000 user && \
|
| 23 |
uv sync --frozen --no-dev --package gradio-space && \
|
|
@@ -25,7 +28,11 @@ RUN useradd -m -u 1000 user && \
|
|
| 25 |
|
| 26 |
USER user
|
| 27 |
ENV HOME=/home/user \
|
| 28 |
-
PATH="/app/.venv/bin:$PATH"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
|
| 30 |
EXPOSE 7860
|
| 31 |
|
|
|
|
| 16 |
COPY pyproject.toml uv.lock .python-version README.md models.yaml ./
|
| 17 |
COPY apps/gradio-space/pyproject.toml apps/gradio-space/README.md apps/gradio-space/
|
| 18 |
COPY libs/inference/pyproject.toml libs/inference/README.md libs/inference/
|
| 19 |
+
COPY libs/agent/pyproject.toml libs/agent/README.md libs/agent/
|
| 20 |
COPY apps/gradio-space/src apps/gradio-space/src
|
| 21 |
COPY libs/inference/src libs/inference/src
|
| 22 |
+
COPY libs/agent/src libs/agent/src
|
| 23 |
+
COPY skills skills
|
| 24 |
|
| 25 |
RUN useradd -m -u 1000 user && \
|
| 26 |
uv sync --frozen --no-dev --package gradio-space && \
|
|
|
|
| 28 |
|
| 29 |
USER user
|
| 30 |
ENV HOME=/home/user \
|
| 31 |
+
PATH="/app/.venv/bin:$PATH" \
|
| 32 |
+
AGENT_OUTPUTS_DIR=/tmp/agent_outputs \
|
| 33 |
+
AGENT_TRACES_DIR=/tmp/agent_traces
|
| 34 |
+
|
| 35 |
+
RUN mkdir -p /tmp/agent_outputs /tmp/agent_traces
|
| 36 |
|
| 37 |
EXPOSE 7860
|
| 38 |
|
README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
---
|
| 2 |
|
| 3 |
-
## title:
|
| 4 |
-
emoji:
|
| 5 |
colorFrom: blue
|
| 6 |
colorTo: green
|
| 7 |
sdk: docker
|
|
@@ -9,11 +9,13 @@ app_port: 7860
|
|
| 9 |
pinned: false
|
| 10 |
license: apache-2.0
|
| 11 |
|
| 12 |
-
#
|
| 13 |
|
| 14 |
-
|
| 15 |
|
| 16 |
-
|
|
|
|
|
|
|
| 17 |
|
| 18 |
## Prerequisites
|
| 19 |
|
|
@@ -26,81 +28,75 @@ See **[USAGE.md](USAGE.md)** for local run, Docker smoke test, and HF Space depl
|
|
| 26 |
uv sync --all-packages
|
| 27 |
cp .env.example .env # optional: edit model settings
|
| 28 |
|
| 29 |
-
# Download GGUF for offline dev (optional)
|
| 30 |
-
uv run python scripts/download_model.py
|
| 31 |
-
|
| 32 |
# Run Gradio locally
|
| 33 |
uv run --package gradio-space python -m gradio_space.app
|
| 34 |
```
|
| 35 |
|
| 36 |
-
Open [http://localhost:7860](http://localhost:7860).
|
| 37 |
-
|
| 38 |
-
## Environment variables
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
| Variable | Default | Description |
|
| 42 |
-
| ------------------- | --------------------------------- | ------------------------------------------ |
|
| 43 |
-
| `INFERENCE_BACKEND` | `llama_cpp` | `llama_cpp` or `transformers` |
|
| 44 |
-
| `MODEL_REPO` | `Qwen/Qwen2.5-3B-Instruct-GGUF` | Hub repo for GGUF |
|
| 45 |
-
| `MODEL_FILE` | `qwen2.5-3b-instruct-q4_k_m.gguf` | GGUF filename |
|
| 46 |
-
| `MODEL_PATH` | — | Local GGUF path (skips Hub download) |
|
| 47 |
-
| `N_CTX` | `4096` | Context window |
|
| 48 |
-
| `N_GPU_LAYERS` | `0` | GPU layers for llama.cpp (0 = CPU) |
|
| 49 |
-
| `MODEL_ID` | `Qwen/Qwen2.5-3B-Instruct` | Used when `INFERENCE_BACKEND=transformers` |
|
| 50 |
-
|
| 51 |
|
| 52 |
-
|
| 53 |
|
| 54 |
-
|
|
|
|
|
|
|
|
|
|
| 55 |
|
| 56 |
```text
|
| 57 |
-
apps/gradio-space/ # Gradio
|
| 58 |
-
libs/
|
| 59 |
-
|
|
|
|
| 60 |
```
|
| 61 |
|
| 62 |
-
##
|
| 63 |
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
```
|
|
|
|
|
|
|
| 70 |
|
| 71 |
## Hugging Face Space deployment
|
| 72 |
|
| 73 |
1. Create a Space under [build-small-hackathon](https://huggingface.co/build-small-hackathon) with **Docker** SDK.
|
| 74 |
2. Link this repository (root `Dockerfile` + root `README.md` YAML above).
|
| 75 |
-
3. Hardware:
|
| 76 |
-
4.
|
| 77 |
|
| 78 |
```bash
|
| 79 |
-
# Optional local Docker smoke test
|
| 80 |
docker build -t hackathon-space .
|
| 81 |
-
docker run --rm -p 7860:7860 -e
|
| 82 |
```
|
| 83 |
|
| 84 |
## Hackathon checklist
|
| 85 |
|
| 86 |
-
-
|
| 87 |
- Space live under build-small-hackathon
|
| 88 |
-
- Demo video
|
| 89 |
- Social post published
|
| 90 |
-
- Submission
|
| 91 |
|
| 92 |
### Badge targets
|
| 93 |
|
| 94 |
-
- **
|
| 95 |
-
- **
|
| 96 |
-
- **
|
| 97 |
-
- **Sharing is Caring** —
|
|
|
|
|
|
|
| 98 |
|
| 99 |
-
##
|
| 100 |
|
| 101 |
```bash
|
| 102 |
-
uv
|
| 103 |
-
INFERENCE_BACKEND=transformers MODEL_ID=Qwen/Qwen2.5-3B-Instruct \
|
| 104 |
-
uv run --package gradio-space python -m gradio_space.app
|
| 105 |
```
|
| 106 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
|
| 3 |
+
## title: Lesson Agent
|
| 4 |
+
emoji: 📚
|
| 5 |
colorFrom: blue
|
| 6 |
colorTo: green
|
| 7 |
sdk: docker
|
|
|
|
| 9 |
pinned: false
|
| 10 |
license: apache-2.0
|
| 11 |
|
| 12 |
+
# Lesson Agent
|
| 13 |
|
| 14 |
+
**Backyard AI** Gradio Space for the [Build Small Hackathon](https://huggingface.co/build-small-hackathon).
|
| 15 |
|
| 16 |
+
A local skill-based agent helps a teacher you know turn a **topic + grade level** into a downloadable **PowerPoint** — powered by a small transformers model (`MiniCPM5-1B` by default), no cloud LLM API.
|
| 17 |
+
|
| 18 |
+
See **[USAGE.md](USAGE.md)** for local run, Docker smoke test, and HF Space deployment.
|
| 19 |
|
| 20 |
## Prerequisites
|
| 21 |
|
|
|
|
| 28 |
uv sync --all-packages
|
| 29 |
cp .env.example .env # optional: edit model settings
|
| 30 |
|
|
|
|
|
|
|
|
|
|
| 31 |
# Run Gradio locally
|
| 32 |
uv run --package gradio-space python -m gradio_space.app
|
| 33 |
```
|
| 34 |
|
| 35 |
+
Open [http://localhost:7860](http://localhost:7860). Use the **Lesson slides** tab: enter a topic, grade, and slide count. The model loads on first generate.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
|
| 37 |
+
## How it works
|
| 38 |
|
| 39 |
+
1. **Skill** — `skills/education-pptx/SKILL.md` (Hermes / agentskills.io format)
|
| 40 |
+
2. **LLM** — local model drafts a JSON slide outline
|
| 41 |
+
3. **Tool** — `create_pptx` builds the file with `python-pptx`
|
| 42 |
+
4. **Trace** — JSON log saved under `outputs/traces/` for the Sharing is Caring badge
|
| 43 |
|
| 44 |
```text
|
| 45 |
+
apps/gradio-space/ # Gradio tabs (Lesson slides + Chat debug)
|
| 46 |
+
libs/agent/ # Skill agent runner, tools, trace recorder
|
| 47 |
+
libs/inference/ # Transformers + llama.cpp backends
|
| 48 |
+
skills/ # SKILL.md task definitions
|
| 49 |
```
|
| 50 |
|
| 51 |
+
## Environment variables
|
| 52 |
|
| 53 |
+
| Variable | Default | Description |
|
| 54 |
+
| -------- | ------- | ----------- |
|
| 55 |
+
| `ACTIVE_MODEL` | `minicpm5-1b` | Preset key from `models.yaml` |
|
| 56 |
+
| `AGENT_OUTPUTS_DIR` | `/tmp/agent_outputs` | Generated `.pptx` files |
|
| 57 |
+
| `AGENT_TRACES_DIR` | `outputs/traces` | Agent trace JSON |
|
| 58 |
+
| `SKILLS_DIR` | `./skills` | Skill definitions root |
|
| 59 |
+
|
| 60 |
+
See [`.env.example`](.env.example) and [`models.yaml`](models.yaml) for model presets.
|
| 61 |
|
| 62 |
## Hugging Face Space deployment
|
| 63 |
|
| 64 |
1. Create a Space under [build-small-hackathon](https://huggingface.co/build-small-hackathon) with **Docker** SDK.
|
| 65 |
2. Link this repository (root `Dockerfile` + root `README.md` YAML above).
|
| 66 |
+
3. Hardware: **GPU basic** recommended for transformers (`minicpm5-1b`).
|
| 67 |
+
4. Optional secrets: `ACTIVE_MODEL`, `N_GPU_LAYERS` (if using GGUF preset).
|
| 68 |
|
| 69 |
```bash
|
|
|
|
| 70 |
docker build -t hackathon-space .
|
| 71 |
+
docker run --rm -p 7860:7860 -e ACTIVE_MODEL=minicpm5-1b hackathon-space
|
| 72 |
```
|
| 73 |
|
| 74 |
## Hackathon checklist
|
| 75 |
|
| 76 |
+
- **Track:** Backyard AI — lesson slide builder for a teacher you know
|
| 77 |
- Space live under build-small-hackathon
|
| 78 |
+
- Demo video: real user enters topic → download `.pptx` → show agent trace
|
| 79 |
- Social post published
|
| 80 |
+
- Submission by **June 15, 2026**
|
| 81 |
|
| 82 |
### Badge targets
|
| 83 |
|
| 84 |
+
- **Best Agent** — skill loop + `create_pptx` tool
|
| 85 |
+
- **Tiny Titan** — MiniCPM5 1B (≤4B)
|
| 86 |
+
- **OpenBMB** — `openbmb/MiniCPM5-1B`
|
| 87 |
+
- **Sharing is Caring** — upload traces with `scripts/upload_trace.py`
|
| 88 |
+
- **Off-the-Grid** — local inference only (no cloud LLM API)
|
| 89 |
+
- **Well-Tuned** — optional fine-tuned preset in `models.yaml` (Phase 2)
|
| 90 |
|
| 91 |
+
## Agent trace upload
|
| 92 |
|
| 93 |
```bash
|
| 94 |
+
uv run python scripts/upload_trace.py --repo-id YOUR_USER/build-small-agent-traces
|
|
|
|
|
|
|
| 95 |
```
|
| 96 |
|
| 97 |
+
## Demo video script
|
| 98 |
+
|
| 99 |
+
1. Introduce the teacher and the problem (building a 5-slide lesson takes 30+ minutes).
|
| 100 |
+
2. Open **Lesson slides**, enter topic + grade, click **Generate**.
|
| 101 |
+
3. Show outline preview and download the `.pptx`.
|
| 102 |
+
4. Expand the agent trace JSON — local model, no cloud API.
|
apps/gradio-space/pyproject.toml
CHANGED
|
@@ -8,11 +8,13 @@ authors = [
|
|
| 8 |
]
|
| 9 |
requires-python = ">=3.12"
|
| 10 |
dependencies = [
|
|
|
|
| 11 |
"gradio>=5.0.0",
|
| 12 |
"inference",
|
| 13 |
]
|
| 14 |
|
| 15 |
[tool.uv.sources]
|
|
|
|
| 16 |
inference = { workspace = true }
|
| 17 |
|
| 18 |
[build-system]
|
|
|
|
| 8 |
]
|
| 9 |
requires-python = ">=3.12"
|
| 10 |
dependencies = [
|
| 11 |
+
"agent",
|
| 12 |
"gradio>=5.0.0",
|
| 13 |
"inference",
|
| 14 |
]
|
| 15 |
|
| 16 |
[tool.uv.sources]
|
| 17 |
+
agent = { workspace = true }
|
| 18 |
inference = { workspace = true }
|
| 19 |
|
| 20 |
[build-system]
|
apps/gradio-space/src/gradio_space/app.py
CHANGED
|
@@ -2,7 +2,6 @@ import os
|
|
| 2 |
|
| 3 |
import gradio as gr
|
| 4 |
|
| 5 |
-
from gradio_space.model_loading import warmup
|
| 6 |
from gradio_space.tabs import build_chat_tab, build_education_pptx_tab
|
| 7 |
from inference.config import get_app_config
|
| 8 |
|
|
@@ -38,8 +37,6 @@ Part of the [Build Small Hackathon](https://huggingface.co/build-small-hackathon
|
|
| 38 |
with gr.Tab("Chat (debug)"):
|
| 39 |
build_chat_tab()
|
| 40 |
|
| 41 |
-
demo.load(lambda: warmup(_app_config.active_model))
|
| 42 |
-
|
| 43 |
return demo
|
| 44 |
|
| 45 |
|
|
|
|
| 2 |
|
| 3 |
import gradio as gr
|
| 4 |
|
|
|
|
| 5 |
from gradio_space.tabs import build_chat_tab, build_education_pptx_tab
|
| 6 |
from inference.config import get_app_config
|
| 7 |
|
|
|
|
| 37 |
with gr.Tab("Chat (debug)"):
|
| 38 |
build_chat_tab()
|
| 39 |
|
|
|
|
|
|
|
| 40 |
return demo
|
| 41 |
|
| 42 |
|
apps/gradio-space/src/gradio_space/model_loading.py
CHANGED
|
@@ -76,3 +76,26 @@ def warmup(model_key: str | None = None) -> str:
|
|
| 76 |
def model_status(model_key: str) -> str:
|
| 77 |
model = get_model_config(model_key)
|
| 78 |
return f"**{model.label}**\n\n- Backend: `{model.backend}`\n- {warmup(model_key)}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
def model_status(model_key: str) -> str:
|
| 77 |
model = get_model_config(model_key)
|
| 78 |
return f"**{model.label}**\n\n- Backend: `{model.backend}`\n- {warmup(model_key)}"
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
def _history_to_messages(history: list) -> list[dict[str, str]]:
|
| 82 |
+
messages: list[dict[str, str]] = []
|
| 83 |
+
for item in history:
|
| 84 |
+
if isinstance(item, dict):
|
| 85 |
+
messages.append({"role": item["role"], "content": item["content"]})
|
| 86 |
+
else:
|
| 87 |
+
user_msg, assistant_msg = item
|
| 88 |
+
messages.append({"role": "user", "content": user_msg})
|
| 89 |
+
if assistant_msg:
|
| 90 |
+
messages.append({"role": "assistant", "content": assistant_msg})
|
| 91 |
+
return messages
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def chat(message: str, history: list, model_key: str) -> str:
|
| 95 |
+
load_error = ensure_model_loaded(model_key)
|
| 96 |
+
if load_error:
|
| 97 |
+
return load_error
|
| 98 |
+
|
| 99 |
+
messages = _history_to_messages(history)
|
| 100 |
+
messages.append({"role": "user", "content": message})
|
| 101 |
+
return get_backend(model_key).chat(messages)
|
apps/gradio-space/src/gradio_space/tabs/chat.py
CHANGED
|
@@ -1,37 +1,11 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
|
| 3 |
-
from gradio_space.model_loading import
|
| 4 |
-
chat as chat_fn,
|
| 5 |
-
ensure_model_loaded,
|
| 6 |
-
get_active_model_key,
|
| 7 |
-
model_status,
|
| 8 |
-
warmup,
|
| 9 |
-
)
|
| 10 |
from inference.config import get_app_config
|
| 11 |
|
| 12 |
_app_config = get_app_config()
|
| 13 |
|
| 14 |
|
| 15 |
-
def _history_to_messages(history: list) -> list[dict[str, str]]:
|
| 16 |
-
messages: list[dict[str, str]] = []
|
| 17 |
-
for item in history:
|
| 18 |
-
if isinstance(item, dict):
|
| 19 |
-
messages.append({"role": item["role"], "content": item["content"]})
|
| 20 |
-
else:
|
| 21 |
-
user_msg, assistant_msg = item
|
| 22 |
-
messages.append({"role": "user", "content": user_msg})
|
| 23 |
-
if assistant_msg:
|
| 24 |
-
messages.append({"role": "assistant", "content": assistant_msg})
|
| 25 |
-
return messages
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
def chat(message: str, history: list, model_key: str) -> str:
|
| 29 |
-
load_error = ensure_model_loaded(model_key)
|
| 30 |
-
if load_error:
|
| 31 |
-
return load_error
|
| 32 |
-
return chat_fn(message, history, model_key)
|
| 33 |
-
|
| 34 |
-
|
| 35 |
def build_chat_tab() -> None:
|
| 36 |
gr.Markdown(
|
| 37 |
"""
|
|
@@ -41,7 +15,7 @@ Test the active local model with a simple chat interface.
|
|
| 41 |
"""
|
| 42 |
)
|
| 43 |
|
| 44 |
-
model_key =
|
| 45 |
|
| 46 |
if _app_config.allow_model_switch and len(_app_config.models) > 1:
|
| 47 |
model_dropdown = gr.Dropdown(
|
|
@@ -68,4 +42,3 @@ Test the active local model with a simple chat interface.
|
|
| 68 |
"Explain photosynthesis in one sentence.",
|
| 69 |
],
|
| 70 |
)
|
| 71 |
-
gr.on(fn=lambda: warmup(model_key), outputs=status)
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
|
| 3 |
+
from gradio_space.model_loading import chat, model_status, warmup
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
from inference.config import get_app_config
|
| 5 |
|
| 6 |
_app_config = get_app_config()
|
| 7 |
|
| 8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
def build_chat_tab() -> None:
|
| 10 |
gr.Markdown(
|
| 11 |
"""
|
|
|
|
| 15 |
"""
|
| 16 |
)
|
| 17 |
|
| 18 |
+
model_key = _app_config.active_model
|
| 19 |
|
| 20 |
if _app_config.allow_model_switch and len(_app_config.models) > 1:
|
| 21 |
model_dropdown = gr.Dropdown(
|
|
|
|
| 42 |
"Explain photosynthesis in one sentence.",
|
| 43 |
],
|
| 44 |
)
|
|
|
libs/agent/tests/test_runner.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from agent.models import SlideOutline, SlideSpec
|
| 2 |
+
from agent.runner import AgentRunner
|
| 3 |
+
from agent.tools.pptx import create_pptx
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def test_extract_json_from_fenced_block():
|
| 7 |
+
raw = '```json\n{"title": "T", "slides": [{"title": "S", "bullets": ["a"]}]}\n```'
|
| 8 |
+
data = AgentRunner._extract_json(raw)
|
| 9 |
+
assert data["title"] == "T"
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def test_create_pptx_writes_file(tmp_path, monkeypatch):
|
| 13 |
+
monkeypatch.setenv("AGENT_OUTPUTS_DIR", str(tmp_path))
|
| 14 |
+
outline = SlideOutline(
|
| 15 |
+
title="Photosynthesis",
|
| 16 |
+
slides=[
|
| 17 |
+
SlideSpec(title="What is it?", bullets=["Plants make food", "Uses sunlight"]),
|
| 18 |
+
SlideSpec(title="Why it matters", bullets=["Oxygen", "Food chain"]),
|
| 19 |
+
],
|
| 20 |
+
)
|
| 21 |
+
path = create_pptx(outline, run_id="test")
|
| 22 |
+
assert path.exists()
|
| 23 |
+
assert path.suffix == ".pptx"
|
models.yaml
CHANGED
|
@@ -2,7 +2,7 @@
|
|
| 2 |
# Select active preset with ACTIVE_MODEL; override any field via .env (see .env.example).
|
| 3 |
|
| 4 |
defaults:
|
| 5 |
-
active_model:
|
| 6 |
# Dev: set ALLOW_MODEL_SWITCH=true in .env to expose a dropdown in Gradio.
|
| 7 |
# Space: keep false so visitors use one pinned model.
|
| 8 |
allow_model_switch: false
|
|
|
|
| 2 |
# Select active preset with ACTIVE_MODEL; override any field via .env (see .env.example).
|
| 3 |
|
| 4 |
defaults:
|
| 5 |
+
active_model: minicpm5-1b
|
| 6 |
# Dev: set ALLOW_MODEL_SWITCH=true in .env to expose a dropdown in Gradio.
|
| 7 |
# Space: keep false so visitors use one pinned model.
|
| 8 |
allow_model_switch: false
|
pyproject.toml
CHANGED
|
@@ -5,6 +5,7 @@ description = "Build Small Hackathon — Gradio Space with local llama.cpp infer
|
|
| 5 |
readme = "README.md"
|
| 6 |
requires-python = ">=3.12"
|
| 7 |
dependencies = [
|
|
|
|
| 8 |
"gradio-space",
|
| 9 |
"inference",
|
| 10 |
]
|
|
@@ -22,5 +23,6 @@ members = [
|
|
| 22 |
]
|
| 23 |
|
| 24 |
[tool.uv.sources]
|
|
|
|
| 25 |
gradio-space = { workspace = true }
|
| 26 |
inference = { workspace = true }
|
|
|
|
| 5 |
readme = "README.md"
|
| 6 |
requires-python = ">=3.12"
|
| 7 |
dependencies = [
|
| 8 |
+
"agent",
|
| 9 |
"gradio-space",
|
| 10 |
"inference",
|
| 11 |
]
|
|
|
|
| 23 |
]
|
| 24 |
|
| 25 |
[tool.uv.sources]
|
| 26 |
+
agent = { workspace = true }
|
| 27 |
gradio-space = { workspace = true }
|
| 28 |
inference = { workspace = true }
|
scripts/upload_trace.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Upload the latest agent trace JSON to a Hugging Face dataset repo."""
|
| 3 |
+
|
| 4 |
+
from __future__ import annotations
|
| 5 |
+
|
| 6 |
+
import argparse
|
| 7 |
+
import json
|
| 8 |
+
import os
|
| 9 |
+
from pathlib import Path
|
| 10 |
+
|
| 11 |
+
from huggingface_hub import HfApi
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def _latest_trace(traces_dir: Path) -> Path:
|
| 15 |
+
files = sorted(traces_dir.glob("*.json"), key=lambda p: p.stat().st_mtime, reverse=True)
|
| 16 |
+
if not files:
|
| 17 |
+
raise FileNotFoundError(f"No trace files in {traces_dir}")
|
| 18 |
+
return files[0]
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def main() -> None:
|
| 22 |
+
parser = argparse.ArgumentParser(description="Upload agent trace to HF dataset")
|
| 23 |
+
parser.add_argument(
|
| 24 |
+
"--traces-dir",
|
| 25 |
+
type=Path,
|
| 26 |
+
default=Path(os.environ.get("AGENT_TRACES_DIR", "outputs/traces")),
|
| 27 |
+
)
|
| 28 |
+
parser.add_argument(
|
| 29 |
+
"--repo-id",
|
| 30 |
+
required=True,
|
| 31 |
+
help="HF dataset repo, e.g. username/build-small-agent-traces",
|
| 32 |
+
)
|
| 33 |
+
parser.add_argument("--trace", type=Path, default=None, help="Specific trace file")
|
| 34 |
+
args = parser.parse_args()
|
| 35 |
+
|
| 36 |
+
trace_path = args.trace or _latest_trace(args.traces_dir)
|
| 37 |
+
data = json.loads(trace_path.read_text())
|
| 38 |
+
|
| 39 |
+
api = HfApi()
|
| 40 |
+
api.create_repo(args.repo_id, repo_type="dataset", exist_ok=True)
|
| 41 |
+
api.upload_file(
|
| 42 |
+
path_or_fileobj=trace_path.read_bytes(),
|
| 43 |
+
path_in_repo=f"traces/{trace_path.name}",
|
| 44 |
+
repo_id=args.repo_id,
|
| 45 |
+
repo_type="dataset",
|
| 46 |
+
commit_message=f"Add agent trace {trace_path.stem}",
|
| 47 |
+
)
|
| 48 |
+
|
| 49 |
+
print(f"Uploaded {trace_path} -> {args.repo_id}/traces/{trace_path.name}")
|
| 50 |
+
print(f"Skill: {data.get('skill')} | Model: {data.get('model')} | Run: {data.get('run_id')}")
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
if __name__ == "__main__":
|
| 54 |
+
main()
|