Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions litellm/proxy/lens/inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ def reserve(e: Lens) -> Lens:
current, active.model_copy(update=MappingProxyType({"cost": active.cost + estimate}))
).model_copy(update=MappingProxyType({"spent": current.spent + estimate}))

def settle(e: Lens, cost: float) -> Lens:
def settle(e: Lens, cost: float, step: Step | None = None) -> Lens:
charged: Final = next((j for j in e.jobs if j.id == job.id), None)
adjusted: Final = (
e.model_copy(update=MappingProxyType({"spent": max(0, e.spent - estimate + cost)}))
Expand All @@ -201,12 +201,10 @@ def settle(e: Lens, cost: float) -> Lens:
)
if charged is None:
return adjusted
settled: Final = charged.model_copy(update=MappingProxyType({"cost": max(0, charged.cost - estimate + cost)}))
return replace_job(
adjusted,
add_step(
charged.model_copy(update=MappingProxyType({"cost": max(0, charged.cost - estimate + cost)})),
model_step(response, body, job.settings.model, cost),
),
add_step(settled, step) if step else settled,
)

@asynccontextmanager
Expand Down Expand Up @@ -243,7 +241,8 @@ async def reserve_budget() -> AsyncIterator[None]:
response, billed_cost = await complete(worker.analysis_key_id, data, reserve_budget, request)
cost: Final = billed_cost if billed_cost is not None else completion_charge(deployments, response, estimate)

await repo.update(lens.id, lambda e: settle(e, cost))
step: Final = model_step(response, body, job.settings.model, cost)
await repo.update(lens.id, lambda e: settle(e, cost, step))
parsed: Final = Completion.model_validate_json(response.model_dump_json())
choice: Final = parsed.choices[0]
return ModelResult(
Expand Down
1 change: 1 addition & 0 deletions tests/proxy_behavior/lens/test_lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,7 @@ async def test_failed_model_requests_release_lens_budget_reservations(lens_datab
stored: Final = await endpoints.get_lens(lens.id, worker.scope)
assert stored.spent == 0
assert stored.jobs[0].cost == 0
assert not any(step.kind == "model" for step in stored.jobs[0].steps)
finally:
await lens_database.db.execute_raw('DELETE FROM "LiteLLM_LensRun" WHERE lens_id=$1', lens.id)
await lens_database.db.execute_raw('DELETE FROM "LiteLLM_Lens" WHERE id=$1', lens.id)
Expand Down
Loading