diff --git a/README.md b/README.md index b5ec281e..96835504 100644 --- a/README.md +++ b/README.md @@ -214,6 +214,7 @@ To add a new template/resource: - [Akash Trainer](akash-trainer) - [Gradio](gradio-demo) - [Ray Cluster](ray) +- [Streamlit](https://github.com/akash-network/awesome-akash/tree/master/streamlit-demo) - [Jupyter Notebook](jupyter) - [Jupyter Notebook with ezkl](tensorflow-jupyter-ezkl) - [Jupyter Notebook with Python Kernel](tensorflow-jupyter-mnist) diff --git a/streamlit-demo/README.md b/streamlit-demo/README.md new file mode 100644 index 00000000..a6be1947 --- /dev/null +++ b/streamlit-demo/README.md @@ -0,0 +1,144 @@ +# Streamlit Demo on Akash + +[![Deploy on Akash](https://raw.githubusercontent.com/akash-network/console/refs/heads/main/apps/deploy-web/public/images/deploy-with-akash-btn.svg)](https://console.akash.network/new-deployment?step=edit-deployment&templateId=akash-network-awesome-akash-streamlit-demo) +streamlit-logo-primary-colormark-darktext + +Deploy interactive machine learning apps and data dashboards using Streamlit on Akash Network's decentralized cloud. + +## What is Streamlit? + +[Streamlit](https://streamlit.io) is an open-source Python library that lets you turn data scripts into shareable web apps in minutes — with no frontend experience required. It's the go-to tool for ML engineers and data scientists who want to: + +- Demo machine learning models interactively +- Build data visualization dashboards +- Prototype and share AI-powered tools +- Create internal apps without writing HTML/CSS/JS + +## What's Included + +This template deploys a simple Streamlit application with two demo interfaces: + +1. **Text Analysis** — Mock sentiment analysis with confidence scoring +2. **Image Captioning** — Mock image description generator with file upload + +You can easily swap in your own models or logic by editing `app.py`. + +## Deployment + +### Deploy on Akash Console (Recommended) + +1. Go to [console.akash.network](https://console.akash.network) +2. Click **Deploy** → **Build Your Template** +3. Upload the `deploy.yaml` file or use the one-click button above +4. Review resources and set your pricing bid +5. Sign and deploy +6. Access your Streamlit app at the provided URL on port 80 + +### Deploy via Akash CLI + +1. **Clone the repository:** + +```bash +git clone https://github.com/akash-network/awesome-akash.git +cd awesome-akash/streamlit-demo +``` + +2. **Create the deployment:** + +```bash +akash tx deployment create deploy.yaml \ + --from \ + --node https://rpc.akashnet.net:443 \ + --chain-id akashnet-2 +``` + +3. **Accept a bid and create a lease**, then fetch your deployment URL from the lease status. + +## Customization + +### Use Your Own Model + +Replace the demo functions in `app.py` with real ML logic. Example using HuggingFace Transformers: + +```python +import streamlit as st +from transformers import pipeline + +@st.cache_resource +def load_model(): + return pipeline("sentiment-analysis") + +classifier = load_model() + +st.title("Sentiment Analysis") +text = st.text_area("Enter text") + +if st.button("Analyze"): + result = classifier(text)[0] + st.success(f"**{result['label']}** — {result['score']:.2%} confidence") +``` + +Then build a custom Docker image with your dependencies and update the `image:` field in `deploy.yaml`. + +### Adjust Resources + +Edit `deploy.yaml` to allocate more CPU or memory for heavier workloads: + +```yaml +resources: + cpu: + units: 2.0 # Increase for CPU-intensive models + memory: + size: 4Gi # Increase for larger models or datasets + storage: + size: 5Gi # Increase if loading model weights from disk +``` + +### Add GPU Support + +To run GPU-accelerated models, add a GPU resource block and use a CUDA-enabled base image: + +```yaml +resources: + cpu: + units: 4.0 + memory: + size: 16Gi + storage: + size: 20Gi + gpu: + units: 1 + attributes: + vendor: + nvidia: + - model: rtx3090 +``` + +## Port Reference + +| Service | Container Port | Exposed As | +|-----------|---------------|------------| +| Streamlit | 8501 | 80 (HTTP) | + +## Cost Estimate + +Typical cost on Akash: **~$5–15/month** depending on provider and resource allocation — significantly cheaper than equivalent workloads on AWS, GCP, or Heroku. + +## Example Use Cases + +- Deploy HuggingFace models for text generation, classification, or translation +- Build interactive dashboards for data exploration +- Share ML research demos without provisioning servers +- Host internal tools accessible from anywhere + +## Resources + +- [Streamlit Documentation](https://docs.streamlit.io) +- [Akash Network Documentation](https://docs.akash.network) +- [Akash Console](https://console.akash.network) +- [HuggingFace Models](https://huggingface.co/models) + +## Support + +- Akash Discord: [discord.akash.network](https://discord.akash.network) +- Streamlit Community: [discuss.streamlit.io](https://discuss.streamlit.io) diff --git a/streamlit-demo/app.py b/streamlit-demo/app.py new file mode 100644 index 00000000..49ca4d86 --- /dev/null +++ b/streamlit-demo/app.py @@ -0,0 +1,54 @@ +import streamlit as st +import random +import time + +st.set_page_config( + page_title="Streamlit Demo on Akash", + page_icon="🚀", + layout="centered" +) + +st.title("Streamlit Demo — Deployed on Akash Network") +st.markdown( + "This is a simple demo showing how to deploy Streamlit apps on Akash's decentralized cloud." +) + +tab1, tab2 = st.tabs(["Text Analysis", "Image Captioning"]) + +# --- Tab 1: Sentiment Analysis --- +with tab1: + st.subheader("Sentiment Analysis") + text_input = st.text_area("Enter text", placeholder="Type something here...") + + if st.button("Analyze", key="text_btn"): + if not text_input.strip(): + st.warning("Please enter some text!") + else: + with st.spinner("Analyzing..."): + time.sleep(0.5) # simulate processing + sentiments = ["Positive 😊", "Negative 😞", "Neutral 😐"] + confidence = random.randint(60, 99) + result = random.choice(sentiments) + st.success(f"**Sentiment:** {result}") + st.metric(label="Confidence", value=f"{confidence}%") + +# --- Tab 2: Image Captioning --- +with tab2: + st.subheader("Image Captioning") + uploaded = st.file_uploader("Upload an image", type=["png", "jpg", "jpeg", "webp"]) + + if st.button("Generate Caption", key="img_btn"): + if uploaded is None: + st.warning("Please upload an image!") + else: + st.image(uploaded, caption="Uploaded Image", use_column_width=True) + with st.spinner("Generating caption..."): + time.sleep(0.5) + captions = [ + "A beautiful landscape with mountains", + "A person standing in front of a building", + "An abstract colorful composition", + "A close-up of nature", + "A cityscape at sunset", + ] + st.success(f"**Caption:** {random.choice(captions)}") diff --git a/streamlit-demo/config.json b/streamlit-demo/config.json new file mode 100644 index 00000000..2f39d4cd --- /dev/null +++ b/streamlit-demo/config.json @@ -0,0 +1,9 @@ +{ + "title": "Streamlit Demo", + "description": "Deploy interactive machine learning apps and data dashboards using Streamlit on Akash's decentralized cloud.", + "category": "Machine Learning", + "tags": ["streamlit", "machine-learning", "data-visualization", "python", "ai", "dashboard"], + "logoUrl": "https://streamlit.io/images/brand/streamlit-mark-color.svg", + "websiteUrl": "https://streamlit.io", + "docsUrl": "https://docs.streamlit.io" +} diff --git a/streamlit-demo/deploy.yaml b/streamlit-demo/deploy.yaml new file mode 100644 index 00000000..acb16051 --- /dev/null +++ b/streamlit-demo/deploy.yaml @@ -0,0 +1,81 @@ +--- +version: "2.0" + +services: + streamlit: + image: python:3.11-slim + command: + - "bash" + - "-c" + args: + - | + pip install streamlit --quiet && + cat << 'EOF' > /app/app.py + import streamlit as st + import random, time + st.set_page_config(page_title="Streamlit Demo on Akash", page_icon="🚀") + st.title("Streamlit Demo — Deployed on Akash Network") + st.markdown("This is a simple demo showing how to deploy Streamlit apps on Akash's decentralized cloud.") + tab1, tab2 = st.tabs(["Text Analysis", "Image Captioning"]) + with tab1: + st.subheader("Sentiment Analysis") + text_input = st.text_area("Enter text", placeholder="Type something here...") + if st.button("Analyze"): + if not text_input.strip(): + st.warning("Please enter some text!") + else: + with st.spinner("Analyzing..."): + time.sleep(0.5) + sentiments = ["Positive 😊", "Negative 😞", "Neutral 😐"] + confidence = random.randint(60, 99) + st.success(f"**Sentiment:** {random.choice(sentiments)}") + st.metric(label="Confidence", value=f"{confidence}%") + with tab2: + st.subheader("Image Captioning") + uploaded = st.file_uploader("Upload an image", type=["png","jpg","jpeg","webp"]) + if st.button("Generate Caption"): + if uploaded is None: + st.warning("Please upload an image!") + else: + st.image(uploaded, use_column_width=True) + with st.spinner("Generating caption..."): + time.sleep(0.5) + captions = ["A beautiful landscape with mountains","A person standing in front of a building","An abstract colorful composition","A close-up of nature","A cityscape at sunset"] + st.success(f"**Caption:** {random.choice(captions)}") + EOF + mkdir -p /root/.streamlit + echo '[server]\nheadless = true\naddress = "0.0.0.0"\nport = 8501\nenableCORS = false\nenableXsrfProtection = false' > /root/.streamlit/config.toml + streamlit run /app/app.py + expose: + - port: 8501 + as: 80 + to: + - global: true + +profiles: + compute: + streamlit: + resources: + cpu: + units: 1.0 + memory: + size: 1Gi + storage: + size: 1Gi + placement: + akash: + attributes: + host: akash + signedBy: + anyOf: + - "akash1365yvmc4s7awdyj3n2sav7xfx76adc6dnmlx63" + pricing: + streamlit: + denom: uakt + amount: 10000 + +deployment: + streamlit: + akash: + profile: streamlit + count: 1 diff --git a/streamlit-demo/streamlit-logo-primary-colormark-darktext.png b/streamlit-demo/streamlit-logo-primary-colormark-darktext.png new file mode 100644 index 00000000..e9c0a873 Binary files /dev/null and b/streamlit-demo/streamlit-logo-primary-colormark-darktext.png differ