Implement cost calculator for Tuber (#471)

* Adding cost calculation in tuner for BYOK

* fix

* implement cost calculator for Tuner

* Update api/services/integrations/tuner/completion.py

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>

* feat: expose render_options in node spec

* Update api/services/integrations/registry.py

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>

---------

Co-authored-by: mohamed salem <259547077+mohamedsalem-bot@users.noreply.github.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
This commit is contained in:
Mohamed-Mamdouh 2026-07-02 08:21:14 +01:00 committed by GitHub
parent 97803b8121
commit 65d46bc313
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 479 additions and 188 deletions

View file

@ -8,7 +8,7 @@ from api.services.integrations.base import (
IntegrationRuntimeSession,
)
from .collector import TunerCollector, mode_to_tuner_call_type
from .collector import DeferredTunerObserver, mode_to_tuner_call_type
def _format_model_label(provider: str | None, model: str | None) -> str:
@ -53,23 +53,25 @@ def _resolve_model_labels(context: IntegrationRuntimeContext) -> tuple[str, str,
class TunerRuntimeSession(IntegrationRuntimeSession):
name = "tuner"
def __init__(self, collector: TunerCollector) -> None:
self._collector = collector
def __init__(self, observer: DeferredTunerObserver) -> None:
self._observer = observer
def attach(self, task: Any) -> None:
self._collector.attach_turn_tracking_observer(task.turn_tracking_observer)
self._collector.attach_latency_observer(task.user_bot_latency_observer)
task.add_observer(self._collector)
self._observer.attach_turn_tracking_observer(task.turn_tracking_observer)
task.add_observer(self._observer)
# The SDK Observer wires latency into the accumulator via its own latency
# observer, which must itself be registered to receive frames.
task.add_observer(self._observer.latency_observer)
async def on_call_finished(
self,
*,
gathered_context: dict[str, Any],
) -> dict[str, Any] | None:
self._collector.set_disconnection_reason(
self._observer.set_disconnection_reason(
gathered_context.get("call_disposition")
)
payload = self._collector.build_payload_snapshot()
payload = self._observer.build_payload_snapshot()
if payload is None:
return None
return {"tuner_payload": payload}
@ -88,7 +90,7 @@ def create_runtime_sessions(
asr_model, llm_model, tts_model = _resolve_model_labels(context)
collector = TunerCollector(
observer = DeferredTunerObserver(
workflow_run_id=context.workflow_run_id,
call_type=mode_to_tuner_call_type(context.workflow_run.mode),
asr_model=asr_model,
@ -96,6 +98,5 @@ def create_runtime_sessions(
tts_model=tts_model,
agent_version=getattr(context.run_definition, "version_number", None),
)
collector.attach_context(context.context_messages_provider)
return [TunerRuntimeSession(collector)]
return [TunerRuntimeSession(observer)]