The primitive layer for multi-modal AI
All modalities. All providers. One interface.
Primitives, not frameworks.
π This is the v1 Beta release. We're validating the new architecture before the stable v1.0 release. Feedback welcome!
Celeste AI
Type-safe, modality/provider-agnostic primitives.
- Unified Interface: One API for OpenAI, Anthropic, Gemini, Mistral, and 14+ others.
- True Multi-Modal: Text, Image, Audio, Video, Embeddings, Search βall first-class citizens.
- Type-Safe by Design: Full Pydantic validation and IDE autocomplete.
- Zero Lock-In: Switch providers instantly by changing a single config string.
- Primitives, Not Frameworks: No agents, no chains, no magic. Just clean I/O.
- Lightweight Architecture: No vendor SDKs. Pure, fast HTTP.
π Quick Start
import celeste # One SDK. Every modality. Any provider. text = await celeste.text.generate("Explain quantum computing", model="claude-opus-4-5") image = await celeste.images.generate("A serene mountain lake at dawn", model="flux-2-pro") speech = await celeste.audio.speak("Welcome to the future", model="eleven_v3") video = await celeste.videos.analyze(video_file, prompt="Summarize this clip", model="gemini-3-pro-preview") embeddings = await celeste.text.embed(["lorep ipsum", "dolor sit amet"], model="gemini-embedding-001")
Operations by Domain
| Action | Text | Images | Audio | Video |
|---|---|---|---|---|
| Generate | β | β | β | β |
| Edit | β | β | β | β |
| Analyze | β | β | β | β |
| Upscale | β | β | β | β |
| Speak | β | β | β | β |
| Transcribe | β | β | β | β |
| Embed | β | β | β | β |
β Available Β· β Planned
π Switch providers in one line
from pydantic import BaseModel class User(BaseModel): name: str age: int # Model IDs anthropic_model_id = "claude-4-5-sonnet" google_model_id = "gemini-2.5-flash"
# β Anthropic Way from anthropic import Anthropic import json client = Anthropic() response = client.messages.create( model=anthropic_model_id, messages=[ {"role": "user", "content": "Extract user info: John is 30"} ], output_format={ "type": "json_schema", "schema": User.model_json_schema() } ) user_data = json.loads(response.content[0].text)
# β Google Gemini Way from google import genai from google.genai import types client = genai.Client() response = await client.aio.models.generate_content( model=gemini_model_id, contents="Extract user info: John is 30", config=types.GenerateContentConfig( response_mime_type="application/json", response_schema=User ) ) user = response.parsed
# β Celeste Way import celeste response = await celeste.text.generate( "Extract user info: John is 30", model=google_model_id, # <--- Choose any model from any provider output_schema=User, # <--- Unified parameter working across all providers ) user = response.content # Already parsed as User instance
βοΈ Advanced: Create Client
For explicit configuration or client reuse, use create_client with modality + operation. This is modality-first: you choose the output type and operation explicitly.
from celeste import create_client, Modality, Operation, Provider client = create_client( modality=Modality.TEXT, operation=Operation.GENERATE, provider=Provider.OLLAMA, model="llama3.2", ) response = await client.generate("Extract user info: John is 30", output_schema=User)
capabilityis still supported but deprecated. Prefermodality+operation.
πͺΆ Install
uv add celeste-ai
# or
pip install celeste-aiπ§ Type-Safe by Design
# Full IDE autocomplete import celeste response = await celeste.text.generate( "Explain AI", model="gpt-4o-mini", temperature=0.7, # β Validated (0.0-2.0) max_tokens=100, # β Validated (int) ) # Typed response print(response.content) # str (IDE knows the type) print(response.usage.input_tokens) # int print(response.metadata["model"]) # str
Catch errors before production.
π€ Contributing
We welcome contributions! See CONTRIBUTING.md.
Request a provider: GitHub Issues Report bugs: GitHub Issues
π License
MIT license β see LICENSE for details.