diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..64f23e0770da589d2949e1c24149405f5eda3d68 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,28 @@ +*.7z filter=lfs diff=lfs merge=lfs -text +*.arrow filter=lfs diff=lfs merge=lfs -text +*.bin filter=lfs diff=lfs merge=lfs -text +*.bin.* filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.ftz filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.h5 filter=lfs diff=lfs merge=lfs -text +*.joblib filter=lfs diff=lfs merge=lfs -text +*.lfs.* filter=lfs diff=lfs merge=lfs -text +*.model filter=lfs diff=lfs merge=lfs -text +*.msgpack filter=lfs diff=lfs merge=lfs -text +*.onnx filter=lfs diff=lfs merge=lfs -text +*.ot filter=lfs diff=lfs merge=lfs -text +*.parquet filter=lfs diff=lfs merge=lfs -text +*.pb filter=lfs diff=lfs merge=lfs -text +*.pt filter=lfs diff=lfs merge=lfs -text +*.pth filter=lfs diff=lfs merge=lfs -text +*.rar filter=lfs diff=lfs merge=lfs -text +saved_model/**/* filter=lfs diff=lfs merge=lfs -text +*.tar.* filter=lfs diff=lfs merge=lfs -text +*.tflite filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.wasm filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zstandard filter=lfs diff=lfs merge=lfs -text +*tfevents* filter=lfs diff=lfs merge=lfs -text diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..f91a85067f2cd099a0d4d72a356b36027f3d128c --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +--- +title: Flask + dev server +emoji: ⚗️ +colorFrom: gray +colorTo: gray +sdk: gradio +sdk_version: 2.9.1 +python_version: 3.10.4 +app_file: app.py +models: +- osanseviero/BigGAN-deep-128 +- t5-small +datasets: +- emotion +license: mit +pinned: false +duplicated_from: templates/flask +--- + +Check out the configuration reference at https://huggingface.co/docs/hub/spaces#reference diff --git a/app.py b/app.py new file mode 100644 index 0000000000000000000000000000000000000000..7f888759232c16cced6c464d3f7e31fe7bed896a --- /dev/null +++ b/app.py @@ -0,0 +1,60 @@ +import os +import requests +import json +from io import BytesIO + +from flask import Flask, jsonify, render_template, request, send_file + +from modules.inference import infer_t5 +from modules.dataset import query_emotion + +# https://huggingface.co/settings/tokens +# https://huggingface.co/spaces/{username}/{space}/settings +API_TOKEN = os.getenv("BIG_GAN_TOKEN") + +app = Flask(__name__) + + +@app.route("/") +def index(): + return render_template("index.html") + + +@app.route("/infer_biggan") +def biggan(): + input = request.args.get("input") + + output = requests.request( + "POST", + "https://api-inference.huggingface.co/models/osanseviero/BigGAN-deep-128", + headers={"Authorization": f"Bearer {API_TOKEN}"}, + data=json.dumps(input), + ) + + return send_file(BytesIO(output.content), mimetype="image/png") + + +@app.route("/infer_t5") +def t5(): + input = request.args.get("input") + + output = infer_t5(input) + + return jsonify({"output": output}) + + +@app.route("/query_emotion") +def emotion(): + start = request.args.get("start") + end = request.args.get("end") + + print(start) + print(end) + + output = query_emotion(int(start), int(end)) + + return jsonify({"output": output}) + + +if __name__ == "__main__": + app.run(host="0.0.0.0", port=7860) diff --git a/modules/dataset.py b/modules/dataset.py new file mode 100644 index 0000000000000000000000000000000000000000..066eb5b131ce4293c9ea9746db923e6b7d03964d --- /dev/null +++ b/modules/dataset.py @@ -0,0 +1,19 @@ +from datasets import load_dataset + +dataset = load_dataset("go_emotions", split="train") + +emotions = dataset.info.features['labels'].feature.names + +def query_emotion(start, end): + rows = dataset[start:end] + texts, labels = [rows[k] for k in rows.keys()] + + observations = [] + + for i, text in enumerate(texts): + observations.append({ + "text": text, + "emotion": emotions[labels[i]], + }) + + return observations diff --git a/modules/inference.py b/modules/inference.py new file mode 100644 index 0000000000000000000000000000000000000000..fbf5cce09c4dd0844bb300e7afb161a15f7b0149 --- /dev/null +++ b/modules/inference.py @@ -0,0 +1,11 @@ +from transformers import T5Tokenizer, T5ForConditionalGeneration + +tokenizer = T5Tokenizer.from_pretrained("t5-small") +model = T5ForConditionalGeneration.from_pretrained("t5-small") + + +def infer_t5(input): + input_ids = tokenizer(input, return_tensors="pt").input_ids + outputs = model.generate(input_ids) + + return tokenizer.decode(outputs[0], skip_special_tokens=True) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..7b8d3797e6cb936cb9770418f23e86d753f93dd0 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +datasets==2.* +flask==2.1.* +requests==2.27.* +sentencepiece==0.1.* +torch==1.11.* +transformers==4.* diff --git a/static/index.js b/static/index.js new file mode 100644 index 0000000000000000000000000000000000000000..da58d658fda06c7aed1a8384db3cd19e5f8f7a3e --- /dev/null +++ b/static/index.js @@ -0,0 +1,126 @@ +if (document.location.search.includes('dark-theme=true')) { + document.body.classList.add('dark-theme'); +} + +let cursor = 0; +const RANGE = 5; +const LIMIT = 16_000; + +const textToImage = async (text) => { + const inferenceResponse = await fetch(`infer_biggan?input=${text}`); + const inferenceBlob = await inferenceResponse.blob(); + + return URL.createObjectURL(inferenceBlob); +}; + +const translateText = async (text) => { + const inferResponse = await fetch(`infer_t5?input=${text}`); + const inferJson = await inferResponse.json(); + + return inferJson.output; +}; + +const queryDataset = async (start, end) => { + const queryResponse = await fetch(`query_emotion?start=${start}&end=${end}`); + const queryJson = await queryResponse.json(); + + return queryJson.output; +}; + +const updateTable = async (cursor, range = RANGE) => { + const table = document.querySelector('.dataset-output'); + + const fragment = new DocumentFragment(); + + const observations = await queryDataset(cursor, cursor + range); + + for (const observation of observations) { + let row = document.createElement('tr'); + let text = document.createElement('td'); + let emotion = document.createElement('td'); + + text.textContent = observation.text; + emotion.textContent = observation.emotion; + + row.appendChild(text); + row.appendChild(emotion); + fragment.appendChild(row); + } + + table.innerHTML = ''; + + table.appendChild(fragment); + + table.insertAdjacentHTML( + 'afterbegin', + ` + + text + emotion + + ` + ); +}; + +const imageGenSelect = document.getElementById('image-gen-input'); +const imageGenImage = document.querySelector('.image-gen-output'); +const textGenForm = document.querySelector('.text-gen-form'); +const tableButtonPrev = document.querySelector('.table-previous'); +const tableButtonNext = document.querySelector('.table-next'); + +imageGenSelect.addEventListener('change', async (event) => { + const value = event.target.value; + + try { + imageGenImage.src = await textToImage(value); + imageGenImage.alt = value + ' generated from BigGAN AI model'; + } catch (err) { + console.error(err); + } +}); + +textGenForm.addEventListener('submit', async (event) => { + event.preventDefault(); + + const textGenInput = document.getElementById('text-gen-input'); + const textGenParagraph = document.querySelector('.text-gen-output'); + + try { + textGenParagraph.textContent = await translateText(textGenInput.value); + } catch (err) { + console.error(err); + } +}); + +tableButtonPrev.addEventListener('click', () => { + cursor = cursor > RANGE ? cursor - RANGE : 0; + + if (cursor < RANGE) { + tableButtonPrev.classList.add('hidden'); + } + if (cursor < LIMIT - RANGE) { + tableButtonNext.classList.remove('hidden'); + } + + updateTable(cursor); +}); + +tableButtonNext.addEventListener('click', () => { + cursor = cursor < LIMIT - RANGE ? cursor + RANGE : cursor; + + if (cursor >= RANGE) { + tableButtonPrev.classList.remove('hidden'); + } + if (cursor >= LIMIT - RANGE) { + tableButtonNext.classList.add('hidden'); + } + + updateTable(cursor); +}); + +textToImage(imageGenSelect.value) + .then((image) => (imageGenImage.src = image)) + .catch(console.error); + +updateTable(cursor) + .catch(console.error); diff --git a/static/style.css b/static/style.css new file mode 100644 index 0000000000000000000000000000000000000000..6a3c98f8fab848caaaf7b844b24ce23c8c5c8dde --- /dev/null +++ b/static/style.css @@ -0,0 +1,79 @@ +body { + --text: hsl(0 0% 15%); + padding: 2.5rem; + font-family: sans-serif; + color: var(--text); +} +body.dark-theme { + --text: hsl(0 0% 90%); + background-color: hsl(223 39% 7%); +} + +main { + max-width: 80rem; + text-align: center; +} + +section { + display: flex; + flex-direction: column; + align-items: center; +} + +a { + color: var(--text); +} + +select, input, button, .text-gen-output { + padding: 0.5rem 1rem; +} + +select, img, input { + margin: 0.5rem auto 1rem; +} + +form { + width: 25rem; + margin: 0 auto; +} + +input { + width: 70%; +} + +button { + cursor: pointer; +} + +.text-gen-output { + min-height: 1.2rem; + margin: 1rem; + border: 0.5px solid grey; +} + +#dataset button { + width: 6rem; + margin: 0.5rem; +} + +#dataset button.hidden { + visibility: hidden; +} + +table { + max-width: 40rem; + text-align: left; + border-collapse: collapse; +} + +thead { + font-weight: bold; +} + +td { + padding: 0.5rem; +} + +td:not(thead td) { + border: 0.5px solid grey; +} diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000000000000000000000000000000000000..d7121e95522118e40ef0d7217228061d79250406 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,1929 @@ + + + + + + Flask 🤗 Space served with development server + + + + +
+

Flask 🤗 Space served with development server

+
+

Image generation from Inference API

+

+ Model: + osanseviero/BigGAN-deep-128 +

+ + + pelican generated from BigGAN AI model +
+
+

Text generation from transformers library

+

+ Model: + t5-small +

+
+ + + +

+
+
+
+

Dataset from datasets library

+

+ Dataset: + emotion +

+
+ + +
+
+
+
+ + +