Pierre Chapuis
commited on
factor + low priority
Browse files- src/app.py +10 -31
- src/fg.py +17 -1
src/app.py
CHANGED
|
@@ -25,7 +25,7 @@ with env.prefixed("ERASER_"):
|
|
| 25 |
|
| 26 |
assert API_USER is not None
|
| 27 |
assert API_PASSWORD is not None
|
| 28 |
-
CTX = EditorAPIContext(uri=API_URL, user=API_USER, password=API_PASSWORD)
|
| 29 |
if CA_BUNDLE:
|
| 30 |
CTX.verify = CA_BUNDLE
|
| 31 |
|
|
@@ -62,41 +62,19 @@ async def _process(ctx: EditorAPIContext, params: ProcessParams) -> Image.Image:
|
|
| 62 |
segment_params = {"bbox": list(params.bbox)}
|
| 63 |
else:
|
| 64 |
assert params.prompt
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
headers=ctx.auth_headers,
|
| 70 |
-
)
|
| 71 |
-
response.raise_for_status()
|
| 72 |
-
st_bbox = response.json()["state"]
|
| 73 |
-
await ctx.sse_await(st_bbox)
|
| 74 |
-
segment_input_st = st_bbox
|
| 75 |
segment_params = {}
|
| 76 |
|
| 77 |
-
|
| 78 |
-
response = await client.post(
|
| 79 |
-
f"{ctx.uri}/skills/segment/{segment_input_st}",
|
| 80 |
-
json=segment_params,
|
| 81 |
-
headers=ctx.auth_headers,
|
| 82 |
-
)
|
| 83 |
-
response.raise_for_status()
|
| 84 |
-
st_mask = response.json()["state"]
|
| 85 |
-
await ctx.sse_await(st_mask)
|
| 86 |
|
| 87 |
erase_params: dict[str, str | bool] = {
|
| 88 |
"mode": "free", # new API
|
| 89 |
"restore_original_resolution": False, # legacy API
|
| 90 |
}
|
| 91 |
-
|
| 92 |
-
response = await client.post(
|
| 93 |
-
f"{ctx.uri}/skills/erase/{st_input}/{st_mask}",
|
| 94 |
-
json=erase_params,
|
| 95 |
-
headers=ctx.auth_headers,
|
| 96 |
-
)
|
| 97 |
-
response.raise_for_status()
|
| 98 |
-
st_erased = response.json()["state"]
|
| 99 |
-
await ctx.sse_await(st_erased)
|
| 100 |
|
| 101 |
async with ctx as client:
|
| 102 |
response = await client.get(
|
|
@@ -158,8 +136,9 @@ TITLE = """
|
|
| 158 |
padding: 0.5rem 1rem;
|
| 159 |
font-size: 1.25rem;
|
| 160 |
">
|
| 161 |
-
🥳 We're launching our API! It's way faster and more accurate, so if you liked this space,
|
| 162 |
-
wanna check it out.
|
|
|
|
| 163 |
</div>
|
| 164 |
|
| 165 |
<h1 style="font-size: 1.5rem; margin-bottom: 0.5rem;">
|
|
|
|
| 25 |
|
| 26 |
assert API_USER is not None
|
| 27 |
assert API_PASSWORD is not None
|
| 28 |
+
CTX = EditorAPIContext(uri=API_URL, user=API_USER, password=API_PASSWORD, priority="low")
|
| 29 |
if CA_BUNDLE:
|
| 30 |
CTX.verify = CA_BUNDLE
|
| 31 |
|
|
|
|
| 62 |
segment_params = {"bbox": list(params.bbox)}
|
| 63 |
else:
|
| 64 |
assert params.prompt
|
| 65 |
+
segment_input_st = await ctx.call_skill(
|
| 66 |
+
f"infer-bbox/{st_input}",
|
| 67 |
+
{"product_name": params.prompt},
|
| 68 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
segment_params = {}
|
| 70 |
|
| 71 |
+
st_mask = await ctx.call_skill(f"segment/{segment_input_st}", segment_params)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
|
| 73 |
erase_params: dict[str, str | bool] = {
|
| 74 |
"mode": "free", # new API
|
| 75 |
"restore_original_resolution": False, # legacy API
|
| 76 |
}
|
| 77 |
+
st_erased = await ctx.call_skill(f"erase/{st_input}/{st_mask}", erase_params)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
|
| 79 |
async with ctx as client:
|
| 80 |
response = await client.get(
|
|
|
|
| 136 |
padding: 0.5rem 1rem;
|
| 137 |
font-size: 1.25rem;
|
| 138 |
">
|
| 139 |
+
🥳 We're launching our API! It's way faster and more accurate, so if you liked this space,
|
| 140 |
+
you'll definitely wanna check it out.
|
| 141 |
+
<a href="https://finegrain.ai/?utm_source=hf&utm_campaign=object-eraser" target="_blank">Try it now</a>! 🚀
|
| 142 |
</div>
|
| 143 |
|
| 144 |
<h1 style="font-size: 1.5rem; margin-bottom: 0.5rem;">
|
src/fg.py
CHANGED
|
@@ -3,11 +3,13 @@ import dataclasses as dc
|
|
| 3 |
import json
|
| 4 |
from collections import defaultdict
|
| 5 |
from collections.abc import Awaitable, Callable
|
| 6 |
-
from typing import Any
|
| 7 |
|
| 8 |
import httpx
|
| 9 |
import httpx_sse
|
| 10 |
|
|
|
|
|
|
|
| 11 |
|
| 12 |
def _new_future() -> asyncio.Future[Any]:
|
| 13 |
return asyncio.get_running_loop().create_future()
|
|
@@ -18,6 +20,7 @@ class EditorAPIContext:
|
|
| 18 |
uri: str
|
| 19 |
user: str
|
| 20 |
password: str
|
|
|
|
| 21 |
token: str | None = None
|
| 22 |
verify: bool | str = True
|
| 23 |
_client: httpx.AsyncClient | None = None
|
|
@@ -115,3 +118,16 @@ class EditorAPIContext:
|
|
| 115 |
asyncio.set_event_loop(loop)
|
| 116 |
|
| 117 |
return loop.run_until_complete(self.run_one(co, params))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
import json
|
| 4 |
from collections import defaultdict
|
| 5 |
from collections.abc import Awaitable, Callable
|
| 6 |
+
from typing import Any, Literal
|
| 7 |
|
| 8 |
import httpx
|
| 9 |
import httpx_sse
|
| 10 |
|
| 11 |
+
Priority = Literal["low", "standard", "high"]
|
| 12 |
+
|
| 13 |
|
| 14 |
def _new_future() -> asyncio.Future[Any]:
|
| 15 |
return asyncio.get_running_loop().create_future()
|
|
|
|
| 20 |
uri: str
|
| 21 |
user: str
|
| 22 |
password: str
|
| 23 |
+
priority: Priority = "standard"
|
| 24 |
token: str | None = None
|
| 25 |
verify: bool | str = True
|
| 26 |
_client: httpx.AsyncClient | None = None
|
|
|
|
| 118 |
asyncio.set_event_loop(loop)
|
| 119 |
|
| 120 |
return loop.run_until_complete(self.run_one(co, params))
|
| 121 |
+
|
| 122 |
+
async def call_skill(self, uri: str, params: dict[str, Any] | None) -> str:
|
| 123 |
+
params = {"priority": self.priority} | (params or {})
|
| 124 |
+
async with self as client:
|
| 125 |
+
response = await client.post(
|
| 126 |
+
f"{self.uri}/skills/{uri}",
|
| 127 |
+
json=params,
|
| 128 |
+
headers=self.auth_headers,
|
| 129 |
+
)
|
| 130 |
+
response.raise_for_status()
|
| 131 |
+
state_id = response.json()["state"]
|
| 132 |
+
await self.sse_await(state_id)
|
| 133 |
+
return state_id
|