wrapper fixes
This commit is contained in:
@@ -23,7 +23,6 @@ from pipecat.processors.aggregators.llm_response_universal import (
|
|||||||
)
|
)
|
||||||
from pipecat.runner.types import RunnerArguments
|
from pipecat.runner.types import RunnerArguments
|
||||||
from pipecat.runner.utils import create_transport
|
from pipecat.runner.utils import create_transport
|
||||||
from pipecat.services.openai.base_llm import OpenAILLMSettings
|
|
||||||
from pipecat.services.sarvam.llm import SarvamLLMService
|
from pipecat.services.sarvam.llm import SarvamLLMService
|
||||||
from pipecat.services.sarvam.stt import SarvamSTTService
|
from pipecat.services.sarvam.stt import SarvamSTTService
|
||||||
from pipecat.services.sarvam.tts import SarvamTTSService
|
from pipecat.services.sarvam.tts import SarvamTTSService
|
||||||
@@ -60,34 +59,24 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
|||||||
logger.info("Starting bot")
|
logger.info("Starting bot")
|
||||||
|
|
||||||
stt = SarvamSTTService(
|
stt = SarvamSTTService(
|
||||||
model="saaras:v3",
|
settings=SarvamSTTService.Settings(model="saaras:v3"),
|
||||||
api_key=_require_env("SARVAM_API_KEY"),
|
api_key=_require_env("SARVAM_API_KEY"),
|
||||||
)
|
)
|
||||||
|
|
||||||
tts = SarvamTTSService(
|
tts = SarvamTTSService(
|
||||||
model="bulbul:v3",
|
settings=SarvamTTSService.Settings(model="bulbul:v3"),
|
||||||
api_key=_require_env("SARVAM_API_KEY"),
|
api_key=_require_env("SARVAM_API_KEY"),
|
||||||
)
|
)
|
||||||
|
|
||||||
llm = SarvamLLMService(
|
llm = SarvamLLMService(
|
||||||
api_key=_require_env("SARVAM_API_KEY"),
|
api_key=_require_env("SARVAM_API_KEY"),
|
||||||
model="sarvam-30b",
|
settings=SarvamLLMService.Settings(model="sarvam-30b"),
|
||||||
|
system_instruction=(
|
||||||
|
"You are a helpful LLM in a WebRTC call. Your goal is to demonstrate your capabilities in a succinct way. Your output will be spoken aloud, so avoid special characters that can't easily be spoken, such as emojis or bullet points. Respond to what the user said in a creative and helpful way."
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
messages: list[Any] = [
|
context = LLMContext()
|
||||||
{
|
|
||||||
"role": "system",
|
|
||||||
"content": (
|
|
||||||
"You are a helpful LLM in a WebRTC call. Your goal is to "
|
|
||||||
"demonstrate your capabilities in a succinct way. Your output "
|
|
||||||
"will be spoken aloud, so avoid special characters that can't "
|
|
||||||
"easily be spoken, such as emojis or bullet points. Respond to "
|
|
||||||
"what the user said in a creative and helpful way."
|
|
||||||
),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
context = LLMContext(messages)
|
|
||||||
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
|
||||||
context,
|
context,
|
||||||
user_params=LLMUserAggregatorParams(vad_analyzer=SileroVADAnalyzer()),
|
user_params=LLMUserAggregatorParams(vad_analyzer=SileroVADAnalyzer()),
|
||||||
@@ -117,12 +106,14 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
|
|||||||
@transport.event_handler("on_client_connected")
|
@transport.event_handler("on_client_connected")
|
||||||
async def on_client_connected(transport, client):
|
async def on_client_connected(transport, client):
|
||||||
logger.info("Client connected")
|
logger.info("Client connected")
|
||||||
messages.append({"role": "system", "content": "Please introduce yourself to the user."})
|
context.add_message({"role": "user", "content": "Please introduce yourself to the user."})
|
||||||
await task.queue_frames([LLMRunFrame()])
|
await task.queue_frames([LLMRunFrame()])
|
||||||
|
|
||||||
await asyncio.sleep(10)
|
await asyncio.sleep(10)
|
||||||
logger.info("Updating Sarvam LLM settings: temperature=0.1")
|
logger.info("Updating Sarvam LLM settings: temperature=0.1")
|
||||||
await task.queue_frame(LLMUpdateSettingsFrame(delta=OpenAILLMSettings(temperature=0.1)))
|
await task.queue_frame(
|
||||||
|
LLMUpdateSettingsFrame(delta=SarvamLLMService.Settings(temperature=0.1))
|
||||||
|
)
|
||||||
|
|
||||||
@transport.event_handler("on_client_disconnected")
|
@transport.event_handler("on_client_disconnected")
|
||||||
async def on_client_disconnected(transport, client):
|
async def on_client_disconnected(transport, client):
|
||||||
|
|||||||
@@ -4,5 +4,4 @@
|
|||||||
# SPDX-License-Identifier: BSD 2-Clause License
|
# SPDX-License-Identifier: BSD 2-Clause License
|
||||||
#
|
#
|
||||||
|
|
||||||
from .llm import SarvamLLMService
|
|
||||||
from .tts import *
|
from .tts import *
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ from pipecat.services.sarvam._sdk import sdk_headers
|
|||||||
from pipecat.services.settings import NOT_GIVEN as _NOT_GIVEN
|
from pipecat.services.settings import NOT_GIVEN as _NOT_GIVEN
|
||||||
from pipecat.services.settings import _NotGiven, _warn_deprecated_param, is_given
|
from pipecat.services.settings import _NotGiven, _warn_deprecated_param, is_given
|
||||||
|
|
||||||
__all__ = ["SarvamLLMService", "SarvamLLMSettings"]
|
|
||||||
_T = TypeVar("_T")
|
_T = TypeVar("_T")
|
||||||
|
|
||||||
|
|
||||||
@@ -56,10 +55,10 @@ class SarvamLLMService(OpenAILLMService):
|
|||||||
- raw Sarvam server error passthrough
|
- raw Sarvam server error passthrough
|
||||||
"""
|
"""
|
||||||
|
|
||||||
SUPPORTED_MODELS = frozenset({"sarvam-30b", "sarvam-30b-16k", "sarvam-105b", "sarvam-105b-32k"})
|
_SUPPORTED_MODELS = frozenset(
|
||||||
TOOL_CALLING_MODELS = frozenset(
|
|
||||||
{"sarvam-30b", "sarvam-30b-16k", "sarvam-105b", "sarvam-105b-32k"}
|
{"sarvam-30b", "sarvam-30b-16k", "sarvam-105b", "sarvam-105b-32k"}
|
||||||
)
|
)
|
||||||
|
_TOOL_CALLING_MODELS = _SUPPORTED_MODELS
|
||||||
Settings = SarvamLLMSettings
|
Settings = SarvamLLMSettings
|
||||||
_settings: SarvamLLMSettings
|
_settings: SarvamLLMSettings
|
||||||
|
|
||||||
@@ -94,6 +93,8 @@ class SarvamLLMService(OpenAILLMService):
|
|||||||
|
|
||||||
# 2. Apply direct init arg overrides (deprecated)
|
# 2. Apply direct init arg overrides (deprecated)
|
||||||
if model is not None:
|
if model is not None:
|
||||||
|
# Keep deprecated init arg for backward compatibility while steering callers
|
||||||
|
# to settings=SarvamLLMService.Settings(model=...).
|
||||||
_warn_deprecated_param("model", SarvamLLMSettings, "model")
|
_warn_deprecated_param("model", SarvamLLMSettings, "model")
|
||||||
default_settings.model = model
|
default_settings.model = model
|
||||||
|
|
||||||
@@ -101,8 +102,9 @@ class SarvamLLMService(OpenAILLMService):
|
|||||||
if settings is not None:
|
if settings is not None:
|
||||||
default_settings.apply_update(settings)
|
default_settings.apply_update(settings)
|
||||||
|
|
||||||
# BaseOpenAILLMService stores settings as OpenAILLMSettings, so keep
|
# BaseOpenAILLMService currently stores settings as OpenAILLMSettings.
|
||||||
# Sarvam-specific runtime knobs in ``extra``.
|
# Preserve Sarvam-only runtime knobs in ``extra`` so they survive
|
||||||
|
# initialization and future update frames.
|
||||||
default_settings.extra = dict(default_settings.extra)
|
default_settings.extra = dict(default_settings.extra)
|
||||||
default_settings.extra.update(self._extract_sarvam_extra_from_settings(default_settings))
|
default_settings.extra.update(self._extract_sarvam_extra_from_settings(default_settings))
|
||||||
|
|
||||||
@@ -158,6 +160,7 @@ class SarvamLLMService(OpenAILLMService):
|
|||||||
params.pop("max_completion_tokens", None)
|
params.pop("max_completion_tokens", None)
|
||||||
params.pop("service_tier", None)
|
params.pop("service_tier", None)
|
||||||
|
|
||||||
|
# Sarvam-only fields are bridged through settings.extra (see __init__ and _update_settings).
|
||||||
extra = self._settings.extra if isinstance(self._settings.extra, dict) else {}
|
extra = self._settings.extra if isinstance(self._settings.extra, dict) else {}
|
||||||
if "wiki_grounding" in extra and extra["wiki_grounding"] is not None:
|
if "wiki_grounding" in extra and extra["wiki_grounding"] is not None:
|
||||||
params["wiki_grounding"] = extra["wiki_grounding"]
|
params["wiki_grounding"] = extra["wiki_grounding"]
|
||||||
@@ -168,6 +171,8 @@ class SarvamLLMService(OpenAILLMService):
|
|||||||
|
|
||||||
async def _update_settings(self, delta: OpenAILLMSettings) -> dict[str, Any]:
|
async def _update_settings(self, delta: OpenAILLMSettings) -> dict[str, Any]:
|
||||||
"""Apply settings updates, preserving Sarvam-specific runtime knobs."""
|
"""Apply settings updates, preserving Sarvam-specific runtime knobs."""
|
||||||
|
# LLMUpdateSettingsFrame commonly carries OpenAILLMSettings deltas.
|
||||||
|
# Lift Sarvam-only fields into delta.extra before delegating to base.
|
||||||
sarvam_extra = self._extract_sarvam_extra_from_settings(delta)
|
sarvam_extra = self._extract_sarvam_extra_from_settings(delta)
|
||||||
if sarvam_extra:
|
if sarvam_extra:
|
||||||
delta.extra = dict(delta.extra)
|
delta.extra = dict(delta.extra)
|
||||||
@@ -176,7 +181,13 @@ class SarvamLLMService(OpenAILLMService):
|
|||||||
return await super()._update_settings(delta)
|
return await super()._update_settings(delta)
|
||||||
|
|
||||||
async def _call_with_raw_sarvam_errors(self, awaitable: Awaitable[_T]) -> _T:
|
async def _call_with_raw_sarvam_errors(self, awaitable: Awaitable[_T]) -> _T:
|
||||||
"""Await an OpenAI call while preserving Sarvam raw error payloads."""
|
"""Await an OpenAI call while preserving Sarvam raw error payloads.
|
||||||
|
|
||||||
|
BaseOpenAILLMService handles pipeline-frame exceptions via push_error(),
|
||||||
|
but direct helper methods like ``get_chat_completions`` and
|
||||||
|
``run_inference`` are often consumed directly. We normalize those errors
|
||||||
|
here so applications consistently receive server-provided messages.
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
return await awaitable
|
return await awaitable
|
||||||
except (APITimeoutError, asyncio.TimeoutError, httpx.TimeoutException):
|
except (APITimeoutError, asyncio.TimeoutError, httpx.TimeoutException):
|
||||||
@@ -208,8 +219,8 @@ class SarvamLLMService(OpenAILLMService):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def _validate_model(self, model: str):
|
def _validate_model(self, model: str):
|
||||||
if model not in self.SUPPORTED_MODELS:
|
if model not in self._SUPPORTED_MODELS:
|
||||||
allowed = ", ".join(sorted(self.SUPPORTED_MODELS))
|
allowed = ", ".join(sorted(self._SUPPORTED_MODELS))
|
||||||
raise ValueError(f"Unsupported Sarvam LLM model '{model}'. Allowed values: {allowed}.")
|
raise ValueError(f"Unsupported Sarvam LLM model '{model}'. Allowed values: {allowed}.")
|
||||||
|
|
||||||
def _extract_sarvam_extra_from_settings(self, settings_obj: Any) -> dict[str, Any]:
|
def _extract_sarvam_extra_from_settings(self, settings_obj: Any) -> dict[str, Any]:
|
||||||
@@ -238,8 +249,9 @@ class SarvamLLMService(OpenAILLMService):
|
|||||||
if has_tool_choice and not has_tools:
|
if has_tool_choice and not has_tools:
|
||||||
raise ValueError("Sarvam requires non-empty `tools` when `tool_choice` is provided.")
|
raise ValueError("Sarvam requires non-empty `tools` when `tool_choice` is provided.")
|
||||||
|
|
||||||
if has_tools and self._settings.model not in self.TOOL_CALLING_MODELS:
|
# Validate early to provide deterministic errors before network calls.
|
||||||
allowed = ", ".join(sorted(self.TOOL_CALLING_MODELS))
|
if has_tools and self._settings.model not in self._TOOL_CALLING_MODELS:
|
||||||
|
allowed = ", ".join(sorted(self._TOOL_CALLING_MODELS))
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Model '{self._settings.model}' does not support tools. "
|
f"Model '{self._settings.model}' does not support tools. "
|
||||||
f"Supported models: {allowed}."
|
f"Supported models: {allowed}."
|
||||||
|
|||||||
Reference in New Issue
Block a user