Merge branch 'simp/r3-26-G' into simp/integration3
This commit is contained in:
@@ -13,11 +13,7 @@ from dataclasses import dataclass
|
||||
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple
|
||||
|
||||
from agent.image_gen_provider import (
|
||||
ImageGenProvider,
|
||||
error_response,
|
||||
normalize_reference_images,
|
||||
save_b64_image,
|
||||
save_url_image,
|
||||
ImageGenProvider, error_response, normalize_reference_images, save_b64_image, save_url_image
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -79,13 +75,8 @@ def load_image_gen_config(sub: Optional[str] = None) -> Dict[str, Any]:
|
||||
|
||||
|
||||
def resolve_static_model(
|
||||
models: Dict[str, Dict[str, Any]],
|
||||
default: str,
|
||||
*,
|
||||
env_var: str,
|
||||
config_key: str,
|
||||
explicit: Optional[str] = None,
|
||||
include_top_level: bool = True,
|
||||
models: Dict[str, Dict[str, Any]], default: str, *, env_var: str, config_key: str,
|
||||
explicit: Optional[str] = None, include_top_level: bool = True,
|
||||
config: Optional[Dict[str, Any]] = None,
|
||||
) -> Tuple[str, Dict[str, Any]]:
|
||||
"""Pick ``(model_id, meta)`` from a fixed catalog.
|
||||
@@ -123,8 +114,7 @@ def collect_source_images(
|
||||
|
||||
def catalog_rows(
|
||||
models: Dict[str, Dict[str, Any]],
|
||||
fields: Iterable[str] = ("display", "speed", "strengths", "price"),
|
||||
*,
|
||||
fields: Iterable[str] = ("display", "speed", "strengths", "price"), *,
|
||||
price: Optional[str] = None,
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Picker rows: ``id`` plus ``fields`` from each meta (missing ``display`` →
|
||||
@@ -213,16 +203,8 @@ def import_openai(provider: str, aspect: str) -> Tuple[Any, Optional[Dict[str, A
|
||||
|
||||
|
||||
def materialize_image(
|
||||
b64: Optional[str],
|
||||
url: Optional[str],
|
||||
*,
|
||||
prefix: str,
|
||||
label: str,
|
||||
provider: str,
|
||||
model: str,
|
||||
prompt: str,
|
||||
aspect: str,
|
||||
log: logging.Logger = logger,
|
||||
b64: Optional[str], url: Optional[str], *, prefix: str, label: str, provider: str, model: str,
|
||||
prompt: str, aspect: str, log: logging.Logger = logger,
|
||||
) -> Tuple[Optional[str], Optional[Dict[str, Any]]]:
|
||||
"""``(image_ref, None)`` or ``(None, error_dict)`` for a ``(b64_json, url)`` pair.
|
||||
|
||||
@@ -274,12 +256,7 @@ class HttpFailure:
|
||||
|
||||
|
||||
def post_json(
|
||||
url: str,
|
||||
*,
|
||||
headers: Dict[str, str],
|
||||
payload: Dict[str, Any],
|
||||
timeout: Any,
|
||||
label: str,
|
||||
url: str, *, headers: Dict[str, str], payload: Dict[str, Any], timeout: Any, label: str,
|
||||
error_message: Callable[[Any, Exception], str] = requests_error_message,
|
||||
catch_request_exception: bool = False,
|
||||
) -> Tuple[Optional[Any], Optional[HttpFailure]]:
|
||||
|
||||
@@ -19,19 +19,11 @@ from typing import Any, Dict, List, Optional
|
||||
|
||||
from agent.secret_scope import get_secret
|
||||
from agent.image_gen_provider import (
|
||||
DEFAULT_ASPECT_RATIO,
|
||||
resolve_aspect_ratio,
|
||||
save_b64_image,
|
||||
save_url_image,
|
||||
success_response,
|
||||
DEFAULT_ASPECT_RATIO, resolve_aspect_ratio, save_b64_image, save_url_image, success_response
|
||||
)
|
||||
from plugins.image_gen._common import (
|
||||
StaticImageGenProvider,
|
||||
error_factory,
|
||||
import_openai,
|
||||
load_image_gen_config,
|
||||
prompt_required_error,
|
||||
size_for,
|
||||
StaticImageGenProvider, error_factory, import_openai, load_image_gen_config,
|
||||
prompt_required_error, size_for,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -68,12 +68,8 @@ class FalImageGenProvider(StaticImageGenProvider):
|
||||
return {"modalities": ["text"], "max_reference_images": 0, "supports_upscale": True}
|
||||
|
||||
def generate(
|
||||
self,
|
||||
prompt: str,
|
||||
aspect_ratio: str = DEFAULT_ASPECT_RATIO,
|
||||
*,
|
||||
image_url: Optional[str] = None,
|
||||
reference_image_urls: Optional[List[str]] = None,
|
||||
self, prompt: str, aspect_ratio: str = DEFAULT_ASPECT_RATIO, *,
|
||||
image_url: Optional[str] = None, reference_image_urls: Optional[List[str]] = None,
|
||||
**kwargs: Any,
|
||||
) -> Dict[str, Any]:
|
||||
"""Forward to :func:`tools.image_generation_tool.image_generate_tool` and
|
||||
|
||||
@@ -22,13 +22,8 @@ import requests
|
||||
from agent.secret_scope import get_secret
|
||||
from agent.image_gen_provider import DEFAULT_ASPECT_RATIO, resolve_aspect_ratio, save_url_image, success_response
|
||||
from plugins.image_gen._common import (
|
||||
StaticImageGenProvider,
|
||||
collect_source_images,
|
||||
error_factory,
|
||||
load_image_gen_config,
|
||||
post_json,
|
||||
prompt_required_error,
|
||||
resolve_static_model,
|
||||
ErrorFn, StaticImageGenProvider, collect_source_images, error_factory, load_image_gen_config,
|
||||
post_json, prompt_required_error, resolve_static_model,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -202,11 +197,7 @@ def _is_terminal(job: Any) -> bool:
|
||||
|
||||
|
||||
def _poll_krea_job(
|
||||
base_url: str,
|
||||
auth_token: str,
|
||||
job_id: str,
|
||||
*,
|
||||
timeout_seconds: float = _POLL_TIMEOUT_SECONDS,
|
||||
base_url: str, auth_token: str, job_id: str, *, timeout_seconds: float = _POLL_TIMEOUT_SECONDS,
|
||||
on_error: Optional[Any] = None,
|
||||
) -> Any:
|
||||
"""Poll ``/jobs/{job_id}`` until terminal.
|
||||
@@ -375,6 +366,68 @@ def _build_payload(
|
||||
return payload
|
||||
|
||||
|
||||
def _submit_job(
|
||||
base_url: str, auth_token: str, model_path: str, payload: Dict[str, Any],
|
||||
managed: bool, model_id: str, fail: ErrorFn,
|
||||
) -> Tuple[Optional[str], Optional[Dict[str, Any]]]:
|
||||
"""POST the generation request; ``(job_id, None)`` or ``(None, error)``."""
|
||||
submit_body, failure = post_json(
|
||||
f"{base_url}/generate/image/krea/krea-2/{model_path}",
|
||||
headers=_headers(auth_token, managed=managed, json_body=True),
|
||||
payload=payload, timeout=30, label="Krea", error_message=_submit_error_message,
|
||||
)
|
||||
if failure is not None:
|
||||
if failure.kind == "http":
|
||||
status, err_msg = failure.status, failure.message
|
||||
logger.error("Krea submit failed (%d): %s", status, err_msg)
|
||||
# Managed 4xx: the model may not be enabled/priced on the Nous
|
||||
# Portal, or the gateway's shared key hit its concurrency cap (429).
|
||||
if managed and 400 <= status < 500:
|
||||
hint = (
|
||||
"Krea's shared-key concurrency cap was hit — retry shortly."
|
||||
if status == 429
|
||||
else (
|
||||
f"Model '{model_id}' may not be enabled/priced on the "
|
||||
"Nous Portal's Krea gateway. Set KREA_API_KEY to use "
|
||||
"Krea directly, or pick a different model via "
|
||||
"`hermes tools` → Image Generation."
|
||||
)
|
||||
)
|
||||
return None, fail(
|
||||
f"Nous Subscription Krea gateway rejected '{model_id}' "
|
||||
f"(HTTP {status}): {err_msg}. {hint}",
|
||||
"api_error",
|
||||
)
|
||||
return None, fail(failure.error, "api_error")
|
||||
if failure.kind == "timeout":
|
||||
return None, fail("Krea submit timed out (30s)", "timeout")
|
||||
if failure.kind == "invalid_json":
|
||||
return None, fail(f"Krea returned invalid JSON on submit: {failure.message}", "invalid_response")
|
||||
return None, fail(failure.error, failure.error_type)
|
||||
job_id = submit_body.get("job_id")
|
||||
if not isinstance(job_id, str) or not job_id:
|
||||
return None, fail("Krea submit response missing job_id", "invalid_response")
|
||||
return job_id, None
|
||||
|
||||
|
||||
def _terminal_result_url(
|
||||
job: Dict[str, Any], job_id: str, fail: ErrorFn
|
||||
) -> Tuple[Optional[str], Optional[Dict[str, Any]]]:
|
||||
"""Result URL of a terminal job; ``(url, None)`` or ``(None, error)``."""
|
||||
result = job.get("result")
|
||||
if job.get("status") == "failed":
|
||||
err = result.get("error") if isinstance(result, dict) else None
|
||||
return None, fail(f"Krea job {job_id} failed: {err or 'unknown error'}", "api_error")
|
||||
if job.get("status") == "cancelled":
|
||||
return None, fail(f"Krea job {job_id} was cancelled", "cancelled")
|
||||
if not isinstance(result, dict):
|
||||
return None, fail("Krea job completed but result was missing", "empty_response")
|
||||
result_image_url = _extract_result_url(job)
|
||||
if result_image_url is None:
|
||||
return None, fail("Krea result contained no image URL", "empty_response")
|
||||
return result_image_url, None
|
||||
|
||||
|
||||
class KreaImageGenProvider(StaticImageGenProvider):
|
||||
"""Krea ``Krea 2`` foundation image model backend (Medium + Large)."""
|
||||
|
||||
@@ -401,12 +454,8 @@ class KreaImageGenProvider(StaticImageGenProvider):
|
||||
}
|
||||
|
||||
def generate(
|
||||
self,
|
||||
prompt: str,
|
||||
aspect_ratio: str = DEFAULT_ASPECT_RATIO,
|
||||
*,
|
||||
image_url: Optional[str] = None,
|
||||
reference_image_urls: Optional[List[str]] = None,
|
||||
self, prompt: str, aspect_ratio: str = DEFAULT_ASPECT_RATIO, *,
|
||||
image_url: Optional[str] = None, reference_image_urls: Optional[List[str]] = None,
|
||||
**kwargs: Any,
|
||||
) -> Dict[str, Any]:
|
||||
prompt = (prompt or "").strip()
|
||||
@@ -456,42 +505,9 @@ class KreaImageGenProvider(StaticImageGenProvider):
|
||||
)
|
||||
|
||||
# 1. Submit job.
|
||||
submit_body, failure = post_json(
|
||||
f"{base_url}/generate/image/krea/krea-2/{meta['path']}",
|
||||
headers=_headers(auth_token, managed=managed is not None, json_body=True),
|
||||
payload=payload, timeout=30, label="Krea", error_message=_submit_error_message,
|
||||
)
|
||||
if failure is not None:
|
||||
if failure.kind == "http":
|
||||
status, err_msg = failure.status, failure.message
|
||||
logger.error("Krea submit failed (%d): %s", status, err_msg)
|
||||
# Managed 4xx: the model may not be enabled/priced on the Nous
|
||||
# Portal, or the gateway's shared key hit its concurrency cap (429).
|
||||
if managed is not None and 400 <= status < 500:
|
||||
hint = (
|
||||
"Krea's shared-key concurrency cap was hit — retry shortly."
|
||||
if status == 429
|
||||
else (
|
||||
f"Model '{model_id}' may not be enabled/priced on the "
|
||||
"Nous Portal's Krea gateway. Set KREA_API_KEY to use "
|
||||
"Krea directly, or pick a different model via "
|
||||
"`hermes tools` → Image Generation."
|
||||
)
|
||||
)
|
||||
return fail(
|
||||
f"Nous Subscription Krea gateway rejected '{model_id}' "
|
||||
f"(HTTP {status}): {err_msg}. {hint}",
|
||||
"api_error",
|
||||
)
|
||||
return fail(failure.error, "api_error")
|
||||
if failure.kind == "timeout":
|
||||
return fail("Krea submit timed out (30s)", "timeout")
|
||||
if failure.kind == "invalid_json":
|
||||
return fail(f"Krea returned invalid JSON on submit: {failure.message}", "invalid_response")
|
||||
return fail(failure.error, failure.error_type)
|
||||
job_id = submit_body.get("job_id")
|
||||
if not isinstance(job_id, str) or not job_id:
|
||||
return fail("Krea submit response missing job_id", "invalid_response")
|
||||
job_id, err = _submit_job(base_url, auth_token, meta["path"], payload, managed is not None, model_id, fail)
|
||||
if err is not None:
|
||||
return err
|
||||
|
||||
# 2. Poll. Polling is bound to the same principal at the gateway, so the
|
||||
# managed path polls the gateway's ``/jobs/{id}`` with the Nous token.
|
||||
@@ -509,17 +525,9 @@ class KreaImageGenProvider(StaticImageGenProvider):
|
||||
return fail("Krea returned non-dict job body", "invalid_response")
|
||||
|
||||
# 3. Terminal — extract result.
|
||||
result = job.get("result")
|
||||
if job.get("status") == "failed":
|
||||
err = result.get("error") if isinstance(result, dict) else None
|
||||
return fail(f"Krea job {job_id} failed: {err or 'unknown error'}", "api_error")
|
||||
if job.get("status") == "cancelled":
|
||||
return fail(f"Krea job {job_id} was cancelled", "cancelled")
|
||||
if not isinstance(result, dict):
|
||||
return fail("Krea job completed but result was missing", "empty_response")
|
||||
result_image_url = _extract_result_url(job)
|
||||
if result_image_url is None:
|
||||
return fail("Krea result contained no image URL", "empty_response")
|
||||
result_image_url, err = _terminal_result_url(job, job_id, fail)
|
||||
if err is not None:
|
||||
return err
|
||||
|
||||
# Krea Enhance pass. Precedence: explicit kwarg > ``image_gen.krea.upscale``
|
||||
# config > per-model catalog default. Best-effort: failure falls back to
|
||||
|
||||
@@ -15,20 +15,11 @@ from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
from agent.secret_scope import get_secret
|
||||
from agent.image_gen_provider import (
|
||||
DEFAULT_ASPECT_RATIO,
|
||||
resolve_aspect_ratio,
|
||||
save_b64_image,
|
||||
save_url_image,
|
||||
success_response,
|
||||
DEFAULT_ASPECT_RATIO, resolve_aspect_ratio, save_b64_image, save_url_image, success_response
|
||||
)
|
||||
from plugins.image_gen._common import (
|
||||
StaticImageGenProvider,
|
||||
error_factory,
|
||||
import_openai,
|
||||
openai_importable,
|
||||
prompt_required_error,
|
||||
resolve_static_model,
|
||||
size_for,
|
||||
StaticImageGenProvider, error_factory, import_openai, openai_importable, prompt_required_error,
|
||||
resolve_static_model, size_for,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -90,12 +81,8 @@ class MetaImageGenProvider(StaticImageGenProvider):
|
||||
return {"modalities": ["text"], "max_reference_images": 0}
|
||||
|
||||
def generate(
|
||||
self,
|
||||
prompt: str,
|
||||
aspect_ratio: str = DEFAULT_ASPECT_RATIO,
|
||||
*,
|
||||
image_url: Optional[str] = None,
|
||||
reference_image_urls: Optional[List[str]] = None,
|
||||
self, prompt: str, aspect_ratio: str = DEFAULT_ASPECT_RATIO, *,
|
||||
image_url: Optional[str] = None, reference_image_urls: Optional[List[str]] = None,
|
||||
**kwargs: Any,
|
||||
) -> Dict[str, Any]:
|
||||
prompt = (prompt or "").strip()
|
||||
|
||||
@@ -22,15 +22,9 @@ from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
from agent.image_gen_provider import DEFAULT_ASPECT_RATIO, resolve_aspect_ratio, save_b64_image, success_response
|
||||
from plugins.image_gen._common import (
|
||||
GPT_IMAGE_2_API_MODEL as API_MODEL,
|
||||
GPT_IMAGE_2_DEFAULT as DEFAULT_MODEL,
|
||||
GPT_IMAGE_2_TIERS,
|
||||
StaticImageGenProvider,
|
||||
collect_source_images,
|
||||
error_factory,
|
||||
prompt_required_error,
|
||||
resolve_static_model,
|
||||
size_for,
|
||||
GPT_IMAGE_2_API_MODEL as API_MODEL, GPT_IMAGE_2_DEFAULT as DEFAULT_MODEL, GPT_IMAGE_2_TIERS,
|
||||
StaticImageGenProvider, collect_source_images, error_factory, prompt_required_error,
|
||||
resolve_static_model, size_for,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -364,12 +358,8 @@ class OpenAICodexImageGenProvider(StaticImageGenProvider):
|
||||
return {"modalities": ["text", "image"], "max_reference_images": _MAX_REFERENCE_IMAGES}
|
||||
|
||||
def generate(
|
||||
self,
|
||||
prompt: str,
|
||||
aspect_ratio: str = DEFAULT_ASPECT_RATIO,
|
||||
*,
|
||||
image_url: Optional[str] = None,
|
||||
reference_image_urls: Optional[List[str]] = None,
|
||||
self, prompt: str, aspect_ratio: str = DEFAULT_ASPECT_RATIO, *,
|
||||
image_url: Optional[str] = None, reference_image_urls: Optional[List[str]] = None,
|
||||
**kwargs: Any,
|
||||
) -> Dict[str, Any]:
|
||||
prompt = (prompt or "").strip()
|
||||
|
||||
@@ -13,18 +13,9 @@ from typing import Any, Dict, List, Optional, Tuple
|
||||
from agent.secret_scope import get_secret
|
||||
from agent.image_gen_provider import DEFAULT_ASPECT_RATIO, resolve_aspect_ratio, success_response
|
||||
from plugins.image_gen._common import (
|
||||
GPT_IMAGE_2_API_MODEL as API_MODEL,
|
||||
GPT_IMAGE_2_DEFAULT as DEFAULT_MODEL,
|
||||
GPT_IMAGE_2_TIERS,
|
||||
StaticImageGenProvider,
|
||||
collect_source_images,
|
||||
error_factory,
|
||||
import_openai,
|
||||
materialize_image,
|
||||
openai_importable,
|
||||
prompt_required_error,
|
||||
resolve_static_model,
|
||||
size_for,
|
||||
GPT_IMAGE_2_API_MODEL as API_MODEL, GPT_IMAGE_2_DEFAULT as DEFAULT_MODEL, GPT_IMAGE_2_TIERS,
|
||||
StaticImageGenProvider, collect_source_images, error_factory, import_openai, materialize_image,
|
||||
openai_importable, prompt_required_error, resolve_static_model, size_for,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -84,12 +75,8 @@ class OpenAIImageGenProvider(StaticImageGenProvider):
|
||||
return {"modalities": ["text", "image"], "max_reference_images": 16}
|
||||
|
||||
def generate(
|
||||
self,
|
||||
prompt: str,
|
||||
aspect_ratio: str = DEFAULT_ASPECT_RATIO,
|
||||
*,
|
||||
image_url: Optional[str] = None,
|
||||
reference_image_urls: Optional[List[str]] = None,
|
||||
self, prompt: str, aspect_ratio: str = DEFAULT_ASPECT_RATIO, *,
|
||||
image_url: Optional[str] = None, reference_image_urls: Optional[List[str]] = None,
|
||||
**kwargs: Any,
|
||||
) -> Dict[str, Any]:
|
||||
prompt = (prompt or "").strip()
|
||||
|
||||
@@ -20,19 +20,11 @@ from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
from agent.image_gen_provider import (
|
||||
DEFAULT_ASPECT_RATIO,
|
||||
ImageGenProvider,
|
||||
error_response,
|
||||
resolve_aspect_ratio,
|
||||
save_b64_image,
|
||||
save_url_image,
|
||||
success_response,
|
||||
DEFAULT_ASPECT_RATIO, ImageGenProvider, error_response, resolve_aspect_ratio, save_b64_image,
|
||||
save_url_image, success_response,
|
||||
)
|
||||
from plugins.image_gen._common import (
|
||||
HttpFailure as HttpFailure,
|
||||
error_factory,
|
||||
load_image_gen_config,
|
||||
post_json,
|
||||
HttpFailure as HttpFailure, error_factory, load_image_gen_config, post_json
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -574,15 +566,8 @@ class OpenRouterCompatImageProvider(ImageGenProvider):
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
provider_name: str,
|
||||
display_name: str,
|
||||
runtime_name: str,
|
||||
config_key: str,
|
||||
model_env_var: str,
|
||||
setup_schema: Dict[str, Any],
|
||||
supports_image_api: bool = False,
|
||||
self, *, provider_name: str, display_name: str, runtime_name: str, config_key: str,
|
||||
model_env_var: str, setup_schema: Dict[str, Any], supports_image_api: bool = False,
|
||||
) -> None:
|
||||
self._name = provider_name
|
||||
self._display = display_name
|
||||
@@ -861,12 +846,8 @@ class OpenRouterCompatImageProvider(ImageGenProvider):
|
||||
), None
|
||||
|
||||
def generate(
|
||||
self,
|
||||
prompt: str,
|
||||
aspect_ratio: str = DEFAULT_ASPECT_RATIO,
|
||||
*,
|
||||
image_url: Optional[str] = None,
|
||||
reference_image_urls: Optional[List[str]] = None,
|
||||
self, prompt: str, aspect_ratio: str = DEFAULT_ASPECT_RATIO, *,
|
||||
image_url: Optional[str] = None, reference_image_urls: Optional[List[str]] = None,
|
||||
**kwargs: Any,
|
||||
) -> Dict[str, Any]:
|
||||
fail = error_factory(self._name, aspect_ratio)
|
||||
|
||||
@@ -19,21 +19,12 @@ import requests
|
||||
|
||||
from agent.image_gen_provider import DEFAULT_ASPECT_RATIO, resolve_aspect_ratio, success_response
|
||||
from plugins.image_gen._common import (
|
||||
StaticImageGenProvider,
|
||||
catalog_rows,
|
||||
collect_source_images,
|
||||
error_factory,
|
||||
load_image_gen_config,
|
||||
materialize_image,
|
||||
post_json,
|
||||
StaticImageGenProvider, catalog_rows, collect_source_images, error_factory,
|
||||
load_image_gen_config, materialize_image, post_json,
|
||||
)
|
||||
from tools.xai_http import (
|
||||
build_xai_storage_options,
|
||||
hermes_xai_user_agent,
|
||||
maybe_mark_xai_storage_notice_seen,
|
||||
read_xai_imagine_storage_config,
|
||||
resolve_xai_http_credentials,
|
||||
xai_storage_notice_text,
|
||||
build_xai_storage_options, hermes_xai_user_agent, maybe_mark_xai_storage_notice_seen,
|
||||
read_xai_imagine_storage_config, resolve_xai_http_credentials, xai_storage_notice_text,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -242,12 +233,8 @@ class XAIImageGenProvider(StaticImageGenProvider):
|
||||
}
|
||||
|
||||
def generate(
|
||||
self,
|
||||
prompt: str,
|
||||
aspect_ratio: str = DEFAULT_ASPECT_RATIO,
|
||||
*,
|
||||
image_url: Optional[str] = None,
|
||||
reference_image_urls: Optional[List[str]] = None,
|
||||
self, prompt: str, aspect_ratio: str = DEFAULT_ASPECT_RATIO, *,
|
||||
image_url: Optional[str] = None, reference_image_urls: Optional[List[str]] = None,
|
||||
**kwargs: Any,
|
||||
) -> Dict[str, Any]:
|
||||
"""Text-to-image, or image editing via ``/v1/images/edits`` (JSON body —
|
||||
|
||||
Reference in New Issue
Block a user