Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request: Add async support #74

Closed
creatorrr opened this issue Feb 26, 2023 · 17 comments · Fixed by #193
Closed

Request: Add async support #74

creatorrr opened this issue Feb 26, 2023 · 17 comments · Fixed by #193

Comments

@creatorrr
Copy link

Async support (maybe via aiorequests/aiohttp?) would be very appreciated. Esp since some of the predictions can take a while to complete.

@mohamed-ezz
Copy link

+1

@creatorrr
Copy link
Author

Created a PR to add support for this. cc/ @bfirsh

@0dminnimda
Copy link

0dminnimda commented Mar 11, 2023

@creatorrr How is the progress with #76? Do you need any help/assistance?

@creatorrr
Copy link
Author

It's ready for review, @0dminnimda

@antomin
Copy link

antomin commented Apr 20, 2023

It's ready for review, @0dminnimda

Hi. Thanks for your job. Code in your branch is woked?

@Delamcode

This comment was marked as off-topic.

@Paillat-dev
Copy link

1+

@osmanio2
Copy link

osmanio2 commented Nov 1, 2023

1+

@mattt mattt mentioned this issue Nov 8, 2023
@mattt mattt closed this as completed in #193 Nov 9, 2023
@mattt mattt closed this as completed in 6ed3cf7 Nov 9, 2023
@mattt
Copy link
Contributor

mattt commented Nov 9, 2023

Hi @creatorrr. Thank you for contributing #76. Thank you also for your patience, as this is a long time coming. I'm happy to report that async support landed in version 0.18.0.

Here's an example of how to run multiple predictions concurrently and wait for their results:

import asyncio
import replicate

# https://replicate.com/stability-ai/sdxl
model_version = "stability-ai/sdxl:39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b"
prompts = [
    f"A chariot pulled by a team of {count} rainbow unicorns"
    for count in ["two", "four", "six", "eight"]
]

async with asyncio.TaskGroup() as tg:
    tasks = [
        tg.create_task(replicate.async_run(model_version, input={"prompt": prompt}))
        for prompt in prompts
    ]

results = await asyncio.gather(*tasks)
print(results)

@githubloader
Copy link

When using async_run, is it possible to run different model_versions with different prompts? Or is it only limited to one model_version to different prompts for now?

@mattt
Copy link
Contributor

mattt commented Nov 28, 2023

@githubloader The example I shared uses the same model version for all predictions, but there's nothing to stop you from using different combinations of inputs and models and running them all in parallel.

@thomastraum
Copy link

thomastraum commented Dec 5, 2023

how does this work when reading images with aiofiles?

    async with aiofiles.open(os.path.join(settings.STATIC_DIR, "uploads", render_settings.filename), 'rb') as image:
        image_content = await image.read()
        image_string = base64.b64encode(image_content).decode('utf-8')
        input = {
            "image": image_string,                
            "width":768,
            "height":  768,
            "prompt": render_settings.prompt,
            "num_images": 1,
            "guidance_scale": 8,
            "archive_outputs": False,
            "prompt_strength": 0.45,
            "sizing_strategy": "width/height",
            "lcm_origin_steps": 50,
            "canny_low_threshold": 100,
            "num_inference_steps": 4,
            "canny_high_threshold": 200,
            "control_guidance_end": 1,
            "control_guidance_start": 0,
            "controlnet_conditioning_scale": 2
            }

    result = await replicate.async_run(
        "fofr/latent-consistency-model:a83d4056c205f4f62ae2d19f73b04881db59ce8b81154d314dd34ab7babaa0f1", 
        input=input
    )

I tried a few variations of

    image_content = await image.read()

I get either not serializeable when I open as binary or replicate.exceptions.ReplicateError: - input.image: Does not match format 'uri'

@mattt
Copy link
Contributor

mattt commented Dec 5, 2023

Hi @thomastraum. The async part of your code looks fine. I think the issue is that you're passing the raw, base64-encoded string to the image parameter. If you make it a data URI, that should work.

image_string = f"data:,{base64.b64encode(image_content).decode('utf-8')}"

@thomastraum
Copy link

Ah amazing. Thanks so much for helping a beginner

@PrateekRajan
Copy link

Hi @mattt . Beginner question. I have been trying to test out async_run with clip_interrogator but also seem to run into AttributeError: module 'replicate' has no attribute 'async_run'. I have made sure that I have the latest replicate version but I think I am missing something here. For reference I am referring to this code in README

import asyncio
import replicate

# https://replicate.com/stability-ai/sdxl
model_version = "stability-ai/sdxl:39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b"
prompts = [
    f"A chariot pulled by a team of {count} rainbow unicorns"
    for count in ["two", "four", "six", "eight"]
]

async with asyncio.TaskGroup() as tg:
    tasks = [
        tg.create_task(replicate.async_run(model_version, input={"prompt": prompt}))
        for prompt in prompts
    ]

results = await asyncio.gather(*tasks)
print(results)

Appreciate any insights you can provide here.

@mattt
Copy link
Contributor

mattt commented Dec 21, 2023

@PrateekRajan Hmm, the only reason I can think of is that your program is importing an old version of the client library. We have automated tests for replicate.async_run here that pass. And this code works locally for me. Maybe its loading from the system packages instead of a virtual environment or vice-versa?

@githubloader
Copy link

githubloader commented Jan 14, 2024

Hi,
Is there a way for replicate.async_run to also return prediction id? It seems to only return output (url to file)?

Chris000102 added a commit to Chris000102/replicate-python that referenced this issue May 3, 2024
This PR adds support for async operations to the Replicate client.
Namespace operations like `predictions.list` and `models.create` now
have async variants with the `async_` prefix (`predictions.async_list`
and `models.async_create`).

Here's an example of what that looks like in practice:

```python
import replicate

model = await replicate.models.async_get("stability-ai/sdxl")

input = {
  "prompt": "A chariot pulled by a team of rainbow unicorns, driven by an astronaut, dramatic lighting",
}

output = await replicate.async_run(f"stability-ai/sdxl:{model.latest_version.id}", input)
```

<details>

<summary>Output</summary>

<img
src="https://github.com/replicate/replicate-python/assets/7659/6927f8b4-5f92-495d-a87c-135f31aa1847"/>


</details>

One of the most common questions I hear is how to run a bunch of
predictions in parallel. The async functionality provided by this PR
makes it really straightforward:

```python
import asyncio
import replicate

# https://replicate.com/stability-ai/sdxl
model_version = "stability-ai/sdxl:39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b"
prompts = [
    f"A chariot pulled by a team of {count} rainbow unicorns"
    for count in ["two", "four", "six", "eight"]
]

async with asyncio.TaskGroup() as tg:
    tasks = [
        tg.create_task(replicate.async_run(model_version, input={"prompt": prompt}))
        for prompt in prompts
    ]

results = await asyncio.gather(*tasks)
print(results)
```

Under the hood, `Client` manages an `httpx.Client` and an
`httpx.AsyncClient`, which handle calls to `_request` and
`_async_request`, respectively. Both are created lazily, so API
consumers using only sync or only async functionality won't be affected
by functionality they aren't using.

Implementation-wise, sync and async variants have separate code paths.
This creates nontrivial amounts of duplication, but its benefits to
clarity and performance justify those costs. For instance, it'd have
been nice if the sync variant were implemented as a blocking call to the
async variant, but that would require starting an event loop, which has
additional overhead and causes problems if done within an existing event
loop.

Alternative to replicate/replicate-python#76
Resolves replicate/replicate-python#145
Resolves replicate/replicate-python#107
Resolves replicate/replicate-python#74

---------

Signed-off-by: Mattt Zmuda <mattt@replicate.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.