Skip to content

SDK Migration Guide (v0.7 → v1.0)

Upgrade your elluminate SDK code to the new v1.0 API

SDK v1.0 introduces significant improvements to developer experience:

  • Separate sync/async clients - No more a-prefix on async methods
  • Rich models with methods - collection.add_many() instead of client.template_variables.add_many(collection=...)
  • Top-level convenience methods - client.create_collection() instead of client.collections.create()
  • Cleaner API - Consistent patterns, better discoverability

Quick Reference

v0.7 v1.0
client.experiments.get(name) client.get_experiment(name=...)
client.experiments.get_by_id(id) client.get_experiment(id=...)
client.experiments.aget(name) await async_client.get_experiment(name=...)
client.collections.create(name="x") client.create_collection("x")
client.template_variables.add_many(collection=c, ...) collection.add_many(...)
client.experiments.run(experiment) client.run_experiment(...)
response.messages[-1].content response.response_str
rating.rating.value == "yes" rating.rating == RatingValue.YES

Step 1: Update Imports

Sync Usage (Unchanged)

from elluminate import Client

Async Usage (New Pattern)

# Async usage now requires AsyncClient
from elluminate import AsyncClient

Step 2: Update Client Usage

Sync Client (Unchanged)

# v0.7
client = Client(api_key="...", project_id=123)

# v1.0 - Same!
client = Client(api_key="...", project_id=123)

Async Client (New Pattern)

# v0.7 - Used same Client with a-prefixed methods
client = Client()
template = await client.prompt_templates.aget_or_create(...)
experiment = await client.experiments.acreate(...)

# v1.0 - Use separate AsyncClient, same method names
async_client = AsyncClient()
template, _ = await async_client.get_or_create_prompt_template(...)
experiment = await async_client.create_experiment(...)

Step 3: Update Resource Operations

Collections

# v0.7
collection = client.collections.create(name="Test Cases")
client.template_variables.add_many(
    collection=collection,
    variables=[{"topic": "AI"}, {"topic": "ML"}]
)

# v1.0
collection = client.create_collection("Test Cases")
collection.add_many(variables=[
    {"topic": "AI"},
    {"topic": "ML"},
])

Get or Create Pattern

The get_or_create methods now use a defaults dict for creation-only parameters:

# v0.7
collection, created = client.collections.get_or_create(name="Test Cases")

# v1.0 - Uses defaults dict for creation-only params
collection, created = client.get_or_create_collection(
    name="Test Cases",
    defaults={"description": "My test cases"},
)

Prompt Templates

# v0.7
template, created = client.prompt_templates.get_or_create(
    name="My Template",
    template="Write about {{topic}}",
)

# v1.0 - messages is part of lookup
# If name+content match: returns existing version
# If name exists but content differs: creates NEW version
template, created = client.get_or_create_prompt_template(
    name="My Template",
    messages=[{"role": "user", "content": "Write about {{topic}}"}],
)

Criterion Sets

# v0.7
criterion_set = client.criterionsets.create(name="Quality")
client.criteria.create(
    criterion_set=criterion_set,
    name="clarity",
    description="Is it clear?"
)

# v1.0
criterion_set = client.create_criterion_set("Quality")
criterion_set.add_criteria([
    "Is it clear?",
    "Is it accurate?",
])

Step 4: Update Experiment Workflow

Creating and Running Experiments

# v0.7
experiment = client.experiments.create(
    name="Test v1",
    prompt_template=template,
    collection=collection,
    criterion_set=criterion_set,
    llm_config="gpt-4",
)
result = client.experiments.run(experiment)

# v1.0 - Use run_experiment() shortcut (creates + runs in one call)
from elluminate.schemas import RatingMode

result = client.run_experiment(
    name="Test v1",
    prompt_template=template,
    collection=collection,
    criterion_set=criterion_set,
    llm_config="gpt-4",
    rating_mode=RatingMode.DETAILED,  # FAST or DETAILED (with reasoning)
)

Step 5: Update Async Method Calls

All a-prefixed methods are replaced by normal method names on AsyncClient:

# v0.7
client = Client()
template = await client.prompt_templates.aget(name)
experiments = await client.experiments.alist()
collection = await client.collections.acreate(name="Test")

# v1.0
async_client = AsyncClient()
template = await async_client.get_prompt_template(name)
experiments = await async_client.list_experiments()
collection = await async_client.create_collection("Test")
v0.7 v1.0
client.X.aget(...) await async_client.get_X(...)
client.X.alist(...) await async_client.list_X()
client.X.acreate(...) await async_client.create_X(...)
client.X.aget_or_create(...) await async_client.get_or_create_X(...)

Step 6: Update Response and Rating Access

Response Content Access

# v0.7 - Manual message extraction
for response in experiment.rated_responses:
    content = response.messages[-1].content

# v1.0 - Use response_str property
for response in experiment.responses():
    content = response.response_str  # Cleaner, handles edge cases

Rating Comparisons

# v0.7 - String comparison (error-prone)
for rating in response.ratings:
    if rating.rating.value == "yes":  # Case-sensitive!
        passed += 1

# v1.0 - Use RatingValue enum (type-safe)
from elluminate.schemas import RatingValue

for rating in response.ratings:
    if rating.rating == RatingValue.YES:  # IDE autocomplete, catches typos
        passed += 1

Complete Before/After Example

Before (v0.7)

from elluminate import Client

client = Client()

# Get or create resources
template, _ = client.prompt_templates.get_or_create(
    name="Summarizer",
    template="Summarize: {{text}}",
)

collection, _ = client.collections.get_or_create(name="Test Texts")
client.template_variables.add_many(
    collection=collection,
    variables=[
        {"text": "Long article about AI..."},
        {"text": "Technical documentation..."},
    ]
)

criterion_set, _ = client.criterionsets.get_or_create(name="Summary Quality")
client.criteria.create(
    criterion_set=criterion_set,
    description="Is the summary concise?",
)

# Create and run experiment
experiment = client.experiments.create(
    name="Summary Test",
    prompt_template=template,
    collection=collection,
    criterion_set=criterion_set,
    llm_config="gpt-4",
)
result = client.experiments.run(experiment)

print(f"Average: {result.average_rating:.2%}")

After (v1.0)

from elluminate import Client

client = Client()

# Get or create resources
template, _ = client.get_or_create_prompt_template(
    name="Summarizer",
    messages=[{"role": "user", "content": "Summarize: {{text}}"}],
)

collection, _ = client.get_or_create_collection(
    name="Test Texts",
    defaults={"description": "Test texts for summarization"},
)
collection.add_many(variables=[
    {"text": "Long article about AI..."},
    {"text": "Technical documentation..."},
])

criterion_set, _ = client.get_or_create_criterion_set(
    name="Summary Quality",
    defaults={"description": "Quality criteria for summaries"},
)
criterion_set.add_criteria(["Is the summary concise?"])

# Run experiment (shortcut)
result = client.run_experiment(
    name="Summary Test",
    prompt_template=template,
    collection=collection,
    criterion_set=criterion_set,
    llm_config="gpt-4",
)

print(f"Average: {result.average_rating:.2%}")

Migration Checklist

Imports

  • [ ] Add from elluminate import AsyncClient if using async
  • [ ] Add from elluminate.schemas import RatingValue for rating comparisons

Client Usage

  • [ ] Keep sync Client() usage (unchanged)
  • [ ] Replace async method calls with AsyncClient()

Collections

  • [ ] client.collections.create(name="X")client.create_collection("X")
  • [ ] client.collections.get_or_create(name="X")client.get_or_create_collection("X", defaults={...})
  • [ ] client.template_variables.add_many(collection=c, ...)collection.add_many(...)

Prompt Templates

  • [ ] client.prompt_templates.get_or_create(...)client.get_or_create_prompt_template(...)
  • [ ] client.prompt_templates.get(name=X)client.get_prompt_template(X)

Criterion Sets

  • [ ] client.criterionsets.create(name="X")client.create_criterion_set("X")
  • [ ] client.criteria.create(criterion_set=cs, ...)criterion_set.add_criteria([...])

Experiments

  • [ ] client.experiments.create(...)client.create_experiment(...)
  • [ ] client.experiments.run(exp)client.run_experiment(...)

Async Methods

  • [ ] Replace all a-prefixed methods with AsyncClient + normal methods
  • [ ] client.X.aget(...)await async_client.get_X(...)
  • [ ] client.X.acreate(...)await async_client.create_X(...)

Response and Rating Access

  • [ ] response.messages[-1].contentresponse.response_str
  • [ ] rating.rating.value == "yes"rating.rating == RatingValue.YES

Exception Handling (Security)

  • [ ] exception.responseexception.response_info
  • [ ] exception.response.status_codeexception.response_info.status_code
  • [ ] exception.response.json()exception.response_info.body
  • [ ] Remove any code accessing exception.response.request.headers
  • [ ] Update error logging to use sanitized response_info

FAQ

Do I need to migrate immediately?

No. v0.7.x will receive security updates for 6 months after v1.0 release.

What if I only use sync methods?

Migration is simpler - mainly changing from resource-based to top-level methods:

  • client.collections.create()client.create_collection()
  • client.experiments.run(e)client.run_experiment(...)

Are there any breaking behavior changes?

Yes, a few:

  • get_or_create_*() methods now use defaults dict for creation-only parameters
  • get_or_create_prompt_template() creates a new version if the messages content differs
  • Use run_experiment() to create and run experiments in one call
  • Exception handling changed (see below)

Step 7: Update Exception Handling

Breaking Change: Exceptions no longer expose the full HTTP response object for security reasons.

# v0.7
try:
    client.get_experiment(id=999)
except APIError as e:
    print(e.response.status_code)

# v1.0
try:
    client.get_experiment(id=999)
except APIError as e:
    print(e.response_info.status_code)  # Use response_info

What changed:

v0.7 v1.0
e.response.status_code e.response_info.status_code
e.response.json() e.response_info.body
e.response.request.headers ❌ Not available

This prevents accidental API key leakage in logs and error tracking services.