Agent-JAE/default-skills/venice-list-image-models/scripts/list_image_models.py
jae 7fe886fea5
Some checks are pending
CI / build-check-test (push) Waiting to run
feat: add 11 Venice AI skills as bundled defaults
Skills included:
- venice-chat: Chat with Venice LLM models, vision, reasoning
- venice-chat-benchmark: Benchmark chat models with infographics
- venice-image-gen: Generate images via Venice API
- venice-list-image-models: List available image models
- venice-list-text-models: List available text models
- venice-list-video-models: List available video models
- venice-tts: Text-to-speech via Venice API
- venice-video-generate: Generate videos from text/images
- venice-video-queue: Queue video generation jobs
- venice-video-quote: Get video generation cost quotes
- venice-video-retrieve: Retrieve completed videos

All rebranded from Agent Zero paths to Agent JAE (~/.jae/agent/skills/).
Requires VENICE_API_KEY environment variable.
2026-03-23 18:47:33 +01:00

156 lines
5.3 KiB
Python

"""# Venice.ai List Image Models Instrument
List available image generation models from Venice.ai API.
Returns model names, pricing, constraints, and capabilities.
Usage: list_image_models() - returns all image models with pricing and constraints
"""
import os
import requests
from typing import Optional
from pydantic import BaseModel, Field
# API Configuration
VENICE_API_URL = "https://api.venice.ai/api/v1/models"
VENICE_API_KEY = os.getenv("VENICE_API_KEY")
# Pydantic Models
class PricePoint(BaseModel):
usd: float
diem: float
class UpscalePricing(BaseModel):
x2: Optional[PricePoint] = Field(default=None, alias="2x")
x4: Optional[PricePoint] = Field(default=None, alias="4x")
class ResolutionPricing(BaseModel):
r1k: Optional[PricePoint] = Field(default=None, alias="1K")
r2k: Optional[PricePoint] = Field(default=None, alias="2K")
r4k: Optional[PricePoint] = Field(default=None, alias="4K")
class ImagePricing(BaseModel):
generation: Optional[PricePoint] = None
resolutions: Optional[ResolutionPricing] = None
upscale: Optional[UpscalePricing] = None
class StepsConstraint(BaseModel):
default: int
max: int
class ImageConstraints(BaseModel):
promptCharacterLimit: int = 1500
steps: Optional[StepsConstraint] = None
widthHeightDivisor: int = 1
defaultResolution: Optional[str] = None
resolutions: Optional[list[str]] = None
class ImageModelSpec(BaseModel):
pricing: ImagePricing
constraints: ImageConstraints
supportsWebSearch: bool = False
name: str
modelSource: Optional[str] = None
offline: bool = False
privacy: str = "private"
traits: list[str] = Field(default_factory=list)
class ImageModel(BaseModel):
created: int
id: str
model_spec: ImageModelSpec
object: str = "model"
owned_by: str = ""
type: str = "image"
class ImageModelsResponse(BaseModel):
data: list[ImageModel]
object: str = "list"
type: str = "image"
def list_image_models() -> ImageModelsResponse:
"""
Fetch image generation models from Venice.ai API.
Returns:
ImageModelsResponse with list of available image models
"""
headers = {
"Authorization": f"Bearer {VENICE_API_KEY}",
"Content-Type": "application/json"
}
params = {"type": "image"}
response = requests.get(VENICE_API_URL, headers=headers, params=params, timeout=30)
response.raise_for_status()
data = response.json()
return ImageModelsResponse(**data)
def get_generation_price(spec: ImageModelSpec) -> float:
"""Get the base generation price (handles both flat and resolution-based pricing)."""
if spec.pricing.generation:
return spec.pricing.generation.usd
elif spec.pricing.resolutions and spec.pricing.resolutions.r1k:
return spec.pricing.resolutions.r1k.usd
return 0.0
def format_models_table(models: ImageModelsResponse) -> str:
"""Format models as a readable table."""
lines = []
lines.append(f"{'Model ID':<25} {'Name':<25} {'Gen $':<10} {'2x Up $':<8} {'4x Up $':<8} {'Steps':<12} {'Prompt Limit'}")
lines.append("-" * 115)
for m in sorted(models.data, key=lambda x: get_generation_price(x.model_spec)):
spec = m.model_spec
# Handle both pricing formats
if spec.pricing.generation:
gen_price = f"{spec.pricing.generation.usd:.2f}"
elif spec.pricing.resolutions:
prices = []
if spec.pricing.resolutions.r1k: prices.append(f"1K:{spec.pricing.resolutions.r1k.usd:.2f}")
if spec.pricing.resolutions.r2k: prices.append(f"2K:{spec.pricing.resolutions.r2k.usd:.2f}")
if spec.pricing.resolutions.r4k: prices.append(f"4K:{spec.pricing.resolutions.r4k.usd:.2f}")
gen_price = ",".join(prices) if prices else "-"
else:
gen_price = "-"
up2x = f"{spec.pricing.upscale.x2.usd:.2f}" if spec.pricing.upscale and spec.pricing.upscale.x2 else "-"
up4x = f"{spec.pricing.upscale.x4.usd:.2f}" if spec.pricing.upscale and spec.pricing.upscale.x4 else "-"
steps = f"{spec.constraints.steps.default}/{spec.constraints.steps.max}" if spec.constraints.steps else "-"
prompt_limit = spec.constraints.promptCharacterLimit
lines.append(
f"{m.id:<25} {spec.name:<25} {gen_price:<10} {up2x:<8} {up4x:<8} {steps:<12} {prompt_limit}"
)
return "\n".join(lines)
def get_models_summary(models: ImageModelsResponse) -> dict:
"""Get summary statistics for image models."""
prices = [get_generation_price(m.model_spec) for m in models.data]
return {
"total_models": len(models.data),
"min_price": min(prices),
"max_price": max(prices),
"avg_price": sum(prices) / len(prices),
"with_web_search": sum(1 for m in models.data if m.model_spec.supportsWebSearch),
"offline_models": sum(1 for m in models.data if m.model_spec.offline)
}
if __name__ == "__main__":
print("Fetching Venice.ai image models...\n")
models = list_image_models()
print(f"Total image models available: {len(models.data)}\n")
print(format_models_table(models))
print("\n=== Summary ===")
summary = get_models_summary(models)
print(f" Total models: {summary['total_models']}")
print(f" Price range: ${summary['min_price']:.2f} - ${summary['max_price']:.2f}")
print(f" Average price: ${summary['avg_price']:.3f}")