From f552e8353c370f12474685d2af3d6209ca334305 Mon Sep 17 00:00:00 2001 From: Jan Carbonell Date: Sat, 17 Aug 2024 16:08:32 -0700 Subject: [PATCH] adding the correct syntax for replicate client to allow image requests --- image_app_simple/draft1.py | 70 ++++++++++++++++++++-------- image_app_simple/main.py | 93 ++++++++++++++++++++++++++++---------- 2 files changed, 118 insertions(+), 45 deletions(-) diff --git a/image_app_simple/draft1.py b/image_app_simple/draft1.py index c8d5b0a..0ab3f8e 100644 --- a/image_app_simple/draft1.py +++ b/image_app_simple/draft1.py @@ -6,61 +6,91 @@ app = FastHTML(hdrs=(picolink,)) # Replicate setup (for image generation) -replicate_api_token = os.environ['REPLICATE_API_KEY'] -client = replicate.Client(api_token=replicate_api_token) +replicate_api_token = os.environ["REPLICATE_API_KEY"] +client = replicate.Client( + api_token=replicate_api_token, headers={"User-Agent": "my-app/1.0"} +) # Store our generations generations = [] folder = f"gens/" os.makedirs(folder, exist_ok=True) + # Main page @app.get("/") def home(): inp = Input(id="new-prompt", name="prompt", placeholder="Enter a prompt") - add = Form(Group(inp, Button("Generate")), hx_post="/", target_id='gen-list', hx_swap="afterbegin") - gen_list = Div(id='gen-list') - return Title('Image Generation Demo'), Main(H1('Magic Image Generation'), add, gen_list, cls='container') + add = Form( + Group(inp, Button("Generate")), + hx_post="/", + target_id="gen-list", + hx_swap="afterbegin", + ) + gen_list = Div(id="gen-list") + return Title("Image Generation Demo"), Main( + H1("Magic Image Generation"), add, gen_list, cls="container" + ) + # A pending preview keeps polling this route until we return the image preview def generation_preview(id): if os.path.exists(f"gens/{id}.png"): - return Div(Img(src=f"/gens/{id}.png"), id=f'gen-{id}') + return Div(Img(src=f"/gens/{id}.png"), id=f"gen-{id}") else: - return Div("Generating...", id=f'gen-{id}', - hx_post=f"/generations/{id}", - hx_trigger='every 1s', hx_swap='outerHTML') - + return Div( + "Generating...", + id=f"gen-{id}", + hx_post=f"/generations/{id}", + hx_trigger="every 1s", + hx_swap="outerHTML", + ) + + @app.post("/generations/{id}") -def get(id:int): return generation_preview(id) - +def get(id: int): + return generation_preview(id) + # For images, CSS, etc. @app.get("/{fname:path}.{ext:static}") -def static(fname:str, ext:str): return FileResponse(f'{fname}.{ext}') +def static(fname: str, ext: str): + return FileResponse(f"{fname}.{ext}") + # Generation route @app.post("/") -def post(prompt:str): +def post(prompt: str): id = len(generations) generate_and_save(prompt, id) generations.append(prompt) - clear_input = Input(id="new-prompt", name="prompt", placeholder="Enter a prompt", hx_swap_oob='true') + clear_input = Input( + id="new-prompt", name="prompt", placeholder="Enter a prompt", hx_swap_oob="true" + ) return generation_preview(id), clear_input + # Generate an image and save it to the folder (in a separate thread) @threaded def generate_and_save(prompt, id): output = client.run( "playgroundai/playground-v2.5-1024px-aesthetic:a45f82a1382bed5c7aeb861dac7c7d191b0fdf74d8d57c4a0e6ed7d4d0bf7d24", input={ - "width": 1024,"height": 1024,"prompt": prompt,"scheduler": "DPMSolver++", - "num_outputs": 1,"guidance_scale": 3,"apply_watermark": True, + "width": 1024, + "height": 1024, + "prompt": prompt, + "scheduler": "DPMSolver++", + "num_outputs": 1, + "guidance_scale": 3, + "apply_watermark": True, "negative_prompt": "ugly, deformed, noisy, blurry, distorted", - "prompt_strength": 0.8, "num_inference_steps": 25 - } + "prompt_strength": 0.8, + "num_inference_steps": 25, + }, ) Image.open(requests.get(output[0], stream=True).raw).save(f"{folder}/{id}.png") return True -if __name__ == '__main__': uvicorn.run("draft1:app", host='0.0.0.0', port=int(os.getenv("PORT", default=5000))) \ No newline at end of file + +if __name__ == "__main__": + uvicorn.run("draft1:app", host="0.0.0.0", port=int(os.getenv("PORT", default=5000))) diff --git a/image_app_simple/main.py b/image_app_simple/main.py index b1ed0c7..b289196 100644 --- a/image_app_simple/main.py +++ b/image_app_simple/main.py @@ -5,77 +5,120 @@ # Replicate setup (for generating images) -replicate_api_token = os.environ['REPLICATE_API_KEY'] -client = replicate.Client(api_token=replicate_api_token) +replicate_api_token = os.environ["REPLICATE_API_KEY"] +client = replicate.Client( + api_token=replicate_api_token, headers={"User-Agent": "my-app/1.0"} +) # gens database for storing generated image details -tables = database('data/gens.db').t +tables = database("data/gens.db").t gens = tables.gens if not gens in tables: - gens.create(prompt=str, id=int, folder=str, pk='id') + gens.create(prompt=str, id=int, folder=str, pk="id") Generation = gens.dataclass() # Flexbox CSS (http://flexboxgrid.com/) -gridlink = Link(rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/flexboxgrid/6.3.1/flexboxgrid.min.css", type="text/css") +gridlink = Link( + rel="stylesheet", + href="https://cdnjs.cloudflare.com/ajax/libs/flexboxgrid/6.3.1/flexboxgrid.min.css", + type="text/css", +) # Our FastHTML app app = FastHTML(hdrs=(picolink, gridlink)) + # Main page @app.get("/") def home(): inp = Input(id="new-prompt", name="prompt", placeholder="Enter a prompt") - add = Form(Group(inp, Button("Generate")), hx_post="/", target_id='gen-list', hx_swap="afterbegin") - gen_containers = [generation_preview(g) for g in gens(limit=10)] # Start with last 10 - gen_list = Div(*reversed(gen_containers), id='gen-list', cls="row") # flexbox container: class = row - return Title('Image Generation Demo'), Main(H1('Magic Image Generation'), add, gen_list, cls='container') + add = Form( + Group(inp, Button("Generate")), + hx_post="/", + target_id="gen-list", + hx_swap="afterbegin", + ) + gen_containers = [ + generation_preview(g) for g in gens(limit=10) + ] # Start with last 10 + gen_list = Div( + *reversed(gen_containers), id="gen-list", cls="row" + ) # flexbox container: class = row + return Title("Image Generation Demo"), Main( + H1("Magic Image Generation"), add, gen_list, cls="container" + ) + # Show the image (if available) and prompt for a generation def generation_preview(g): grid_cls = "box col-xs-12 col-sm-6 col-md-4 col-lg-3" image_path = f"{g.folder}/{g.id}.png" if os.path.exists(image_path): - return Div(Card( - Img(src=image_path, alt="Card image", cls="card-img-top"), - Div(P(B("Prompt: "), g.prompt, cls="card-text"),cls="card-body"), - ), id=f'gen-{g.id}', cls=grid_cls) - return Div(f"Generating gen {g.id} with prompt {g.prompt}", - id=f'gen-{g.id}', hx_get=f"/gens/{g.id}", - hx_trigger="every 2s", hx_swap="outerHTML", cls=grid_cls) + return Div( + Card( + Img(src=image_path, alt="Card image", cls="card-img-top"), + Div(P(B("Prompt: "), g.prompt, cls="card-text"), cls="card-body"), + ), + id=f"gen-{g.id}", + cls=grid_cls, + ) + return Div( + f"Generating gen {g.id} with prompt {g.prompt}", + id=f"gen-{g.id}", + hx_get=f"/gens/{g.id}", + hx_trigger="every 2s", + hx_swap="outerHTML", + cls=grid_cls, + ) + # A pending preview keeps polling this route until we return the image preview @app.get("/gens/{id}") -def preview(id:int): +def preview(id: int): return generation_preview(gens.get(id)) + # For images, CSS, etc. @app.get("/{fname:path}.{ext:static}") -def static(fname:str, ext:str): return FileResponse(f'{fname}.{ext}') +def static(fname: str, ext: str): + return FileResponse(f"{fname}.{ext}") + # Generation route @app.post("/") -def post(prompt:str): +def post(prompt: str): folder = f"data/gens/{str(uuid.uuid4())}" os.makedirs(folder, exist_ok=True) g = gens.insert(Generation(prompt=prompt, folder=folder)) generate_and_save(g.prompt, g.id, g.folder) - clear_input = Input(id="new-prompt", name="prompt", placeholder="Enter a prompt", hx_swap_oob='true') + clear_input = Input( + id="new-prompt", name="prompt", placeholder="Enter a prompt", hx_swap_oob="true" + ) return generation_preview(g), clear_input + # Generate an image and save it to the folder (in a separate thread) @threaded def generate_and_save(prompt, id, folder): output = client.run( "playgroundai/playground-v2.5-1024px-aesthetic:a45f82a1382bed5c7aeb861dac7c7d191b0fdf74d8d57c4a0e6ed7d4d0bf7d24", input={ - "width": 1024,"height": 1024,"prompt": prompt,"scheduler": "DPMSolver++", - "num_outputs": 1,"guidance_scale": 3,"apply_watermark": True, + "width": 1024, + "height": 1024, + "prompt": prompt, + "scheduler": "DPMSolver++", + "num_outputs": 1, + "guidance_scale": 3, + "apply_watermark": True, "negative_prompt": "ugly, deformed, noisy, blurry, distorted", - "prompt_strength": 0.8, "num_inference_steps": 25 - } + "prompt_strength": 0.8, + "num_inference_steps": 25, + }, ) Image.open(requests.get(output[0], stream=True).raw).save(f"{folder}/{id}.png") return True -if __name__ == '__main__': uvicorn.run("main:app", host='0.0.0.0', port=int(os.getenv("PORT", default=5000))) \ No newline at end of file + +if __name__ == "__main__": + uvicorn.run("main:app", host="0.0.0.0", port=int(os.getenv("PORT", default=5000)))