Spaces:
Runtime error
Runtime error
ernestyalumni
commited on
Commit
•
c5bdd8b
1
Parent(s):
8cf99c7
1: Initial start for huggingface space for FLUX LoRA hackathon
Browse files- Dockerfile +24 -0
- README.md +20 -0
- app.py +57 -0
- public_instagram_loader.py +83 -0
- requirements.txt +6 -0
Dockerfile
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Use Python 3.9 as the base image
|
2 |
+
FROM python:3.9
|
3 |
+
|
4 |
+
# Create a new user and set environment variables
|
5 |
+
RUN useradd -m -u 1000 user
|
6 |
+
USER user
|
7 |
+
ENV PATH="/home/user/.local/bin:$PATH"
|
8 |
+
|
9 |
+
# Set the working directory
|
10 |
+
WORKDIR /app
|
11 |
+
|
12 |
+
# Copy the requirements and install dependencies
|
13 |
+
COPY --chown=user ./requirements.txt requirements.txt
|
14 |
+
RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
15 |
+
|
16 |
+
# Copy the rest of the application code
|
17 |
+
COPY --chown=user . /app
|
18 |
+
|
19 |
+
# Expose both FastAPI and Gradio ports
|
20 |
+
EXPOSE 7860
|
21 |
+
EXPOSE 7861
|
22 |
+
|
23 |
+
# Run the Gradio app
|
24 |
+
CMD ["python", "app.py"]
|
README.md
CHANGED
@@ -9,3 +9,23 @@ license: mit
|
|
9 |
---
|
10 |
|
11 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
---
|
10 |
|
11 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
12 |
+
|
13 |
+
|
14 |
+
## Creating and starting a virtual environment for Python 3
|
15 |
+
|
16 |
+
Create a directory for a virtual environment:
|
17 |
+
|
18 |
+
```
|
19 |
+
/AI-InstagramPhotos$ python3 -m venv ./venv/
|
20 |
+
```
|
21 |
+
|
22 |
+
Activate it:
|
23 |
+
```
|
24 |
+
/AI-InstagramPhotos$ source ./venv/bin/activate
|
25 |
+
```
|
26 |
+
You should see the prompt have a prefix `(venv)`.
|
27 |
+
|
28 |
+
Deactivate it:
|
29 |
+
```
|
30 |
+
deactivate
|
31 |
+
```
|
app.py
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from fastapi import FastAPI
|
2 |
+
import fal_client
|
3 |
+
import gradio as gr
|
4 |
+
import threading
|
5 |
+
import os
|
6 |
+
from pathlib import Path
|
7 |
+
from public_instagram_loader import public_instagram_loader, InstagramData
|
8 |
+
|
9 |
+
app = FastAPI()
|
10 |
+
|
11 |
+
# Set up the FAL API Key
|
12 |
+
FAL_KEY = os.getenv("FAL_KEY")
|
13 |
+
#fal_client.set_api_key(FAL_KEY)
|
14 |
+
|
15 |
+
# FastAPI route
|
16 |
+
@app.get("/")
|
17 |
+
def greet_json():
|
18 |
+
return {"AI-InstagramPhotos": "Generate photos from your favorite Instagram account using FAL API."}
|
19 |
+
|
20 |
+
# Function to submit Instagram data to FAL API
|
21 |
+
def submit_to_fal(instagram_data: InstagramData):
|
22 |
+
handler = fal_client.submit(
|
23 |
+
"fal-ai/flux-lora-fast-training",
|
24 |
+
arguments={
|
25 |
+
"images_data_url": instagram_data.image_urls,
|
26 |
+
"trigger_word": instagram_data.profile_info['username'],
|
27 |
+
"is_style": True
|
28 |
+
},
|
29 |
+
)
|
30 |
+
result = handler.get()
|
31 |
+
return result
|
32 |
+
|
33 |
+
# Gradio interface for interacting with the Instagram loader and FAL
|
34 |
+
def gradio_interface():
|
35 |
+
def generate_lora_from_instagram(username: str):
|
36 |
+
# Load Instagram data
|
37 |
+
instagram_data = public_instagram_loader(username)
|
38 |
+
if instagram_data is None:
|
39 |
+
return "Profile not found or an error occurred."
|
40 |
+
# Pass Instagram data to FAL API for LoRA training
|
41 |
+
fal_result = submit_to_fal(instagram_data)
|
42 |
+
# Return the URL of the trained LoRA weights
|
43 |
+
return f"Trained LoRA weights: {fal_result['diffusers_lora_file']['url']}"
|
44 |
+
|
45 |
+
iface = gr.Interface(
|
46 |
+
fn=generate_lora_from_instagram,
|
47 |
+
inputs=gr.Textbox(label="Enter Instagram username"),
|
48 |
+
outputs=gr.Textbox(label="LoRA URL"),
|
49 |
+
title="Instagram LoRA Generator using FAL"
|
50 |
+
)
|
51 |
+
|
52 |
+
# Launch Gradio on a different port (7861)
|
53 |
+
iface.launch(server_name="0.0.0.0", server_port=7861)
|
54 |
+
|
55 |
+
# Run Gradio in a separate thread
|
56 |
+
thread = threading.Thread(target=gradio_interface)
|
57 |
+
thread.start()
|
public_instagram_loader.py
ADDED
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import tempfile
|
2 |
+
import os
|
3 |
+
from pathlib import Path
|
4 |
+
from instaloader import Instaloader, Profile
|
5 |
+
from dataclasses import dataclass, field
|
6 |
+
from typing import List, Dict, Tuple
|
7 |
+
import json
|
8 |
+
import zipfile
|
9 |
+
import io
|
10 |
+
import fal_client
|
11 |
+
|
12 |
+
@dataclass
|
13 |
+
class InstagramData:
|
14 |
+
profile_info: Dict
|
15 |
+
posts: List[Dict] = field(default_factory=list)
|
16 |
+
image_urls: List[str] = field(default_factory=list)
|
17 |
+
|
18 |
+
def public_instagram_loader(username: str) -> InstagramData:
|
19 |
+
with tempfile.TemporaryDirectory() as temp_dir:
|
20 |
+
profile_dir = Path(temp_dir) / username
|
21 |
+
profile_dir.mkdir(parents=True, exist_ok=True)
|
22 |
+
|
23 |
+
L = Instaloader(
|
24 |
+
download_pictures=True,
|
25 |
+
download_videos=False,
|
26 |
+
download_video_thumbnails=False,
|
27 |
+
download_geotags=False,
|
28 |
+
download_comments=False,
|
29 |
+
save_metadata=False,
|
30 |
+
compress_json=False,
|
31 |
+
dirname_pattern=str(profile_dir)
|
32 |
+
)
|
33 |
+
|
34 |
+
try:
|
35 |
+
profile = Profile.from_username(L.context, username)
|
36 |
+
except Exception:
|
37 |
+
return None
|
38 |
+
|
39 |
+
profile_info = {
|
40 |
+
'username': profile.username,
|
41 |
+
'full_name': profile.full_name,
|
42 |
+
'biography': profile.biography,
|
43 |
+
'followers': profile.followers,
|
44 |
+
'followees': profile.followees,
|
45 |
+
'mediacount': profile.mediacount,
|
46 |
+
}
|
47 |
+
|
48 |
+
instagram_data = InstagramData(profile_info=profile_info)
|
49 |
+
|
50 |
+
print(f"Downloading and uploading posts from {username}")
|
51 |
+
for post in profile.get_posts():
|
52 |
+
if post.typename == 'GraphImage':
|
53 |
+
post_data = {
|
54 |
+
'shortcode': post.shortcode,
|
55 |
+
'caption': post.caption,
|
56 |
+
'date': post.date_local,
|
57 |
+
'likes': post.likes,
|
58 |
+
'filename': f"{post.date_utc:%Y-%m-%d_%H-%M-%S}_UTC.jpg",
|
59 |
+
}
|
60 |
+
|
61 |
+
# Download the image
|
62 |
+
image_path = profile_dir / post_data['filename']
|
63 |
+
L.download_pic(filename=str(image_path), url=post.url, mtime=post.date_utc)
|
64 |
+
|
65 |
+
# Upload the image to FAL
|
66 |
+
with open(image_path, 'rb') as img_file:
|
67 |
+
url = fal_client.upload(img_file.read(), "image/jpeg")
|
68 |
+
|
69 |
+
instagram_data.posts.append(post_data)
|
70 |
+
instagram_data.image_urls.append(url)
|
71 |
+
|
72 |
+
print(f"Data and images uploaded for {username}")
|
73 |
+
return instagram_data
|
74 |
+
|
75 |
+
if __name__ == "__main__":
|
76 |
+
username = input("Enter Instagram username: ")
|
77 |
+
data = public_instagram_loader(username)
|
78 |
+
if data:
|
79 |
+
print(f"Collected data for {data.profile_info['username']}:")
|
80 |
+
print(f"Total posts: {len(data.posts)}")
|
81 |
+
print(f"Zip file size: {len(data.zip_file)} bytes")
|
82 |
+
else:
|
83 |
+
print("Profile not found or an error occurred.")
|
requirements.txt
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
fastapi
|
2 |
+
uvicorn[standard]
|
3 |
+
gradio
|
4 |
+
fal-client
|
5 |
+
pyyaml
|
6 |
+
instaloader
|