ernestyalumni commited on
Commit
c5bdd8b
1 Parent(s): 8cf99c7

1: Initial start for huggingface space for FLUX LoRA hackathon

Browse files
Files changed (5) hide show
  1. Dockerfile +24 -0
  2. README.md +20 -0
  3. app.py +57 -0
  4. public_instagram_loader.py +83 -0
  5. 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