fix(types): accept SDK NotGiven in LLM Settings fields used for passthrough
Three LLM services initialize certain Settings fields with the SDK's NOT_GIVEN (openai.NOT_GIVEN or anthropic.NOT_GIVEN) so the value flows unmodified into SDK API calls. The inherited field types from LLMSettings only admit pipecat's _NotGiven, so pyright flagged each constructor call as a flavor mismatch. Widen the field types in each service-specific Settings subclass so they accept both pipecat's _NotGiven (for delta-mode defaults) and the corresponding SDK NotGiven (for store-mode passthrough): - OpenAILLMSettings: frequency_penalty, presence_penalty, seed, temperature, top_p, max_tokens, max_completion_tokens. - OpenAIResponsesLLMSettings: temperature, top_p, max_completion_tokens. - AnthropicLLMSettings: temperature, top_k, top_p, thinking. Every overridden field is genuinely read from self._settings and passed directly to the SDK, so none of the overrides are vestigial. Clears 21 pyright errors and restores test_service_settings_complete parity with the pre-NOT_GIVEN-swap state.
This commit is contained in:
@@ -44,6 +44,7 @@ from pipecat.utils.tracing.service_decorators import traced_llm
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
from anthropic import NOT_GIVEN, APITimeoutError, AsyncAnthropic
|
from anthropic import NOT_GIVEN, APITimeoutError, AsyncAnthropic
|
||||||
|
from anthropic import NotGiven as AnthropicNotGiven
|
||||||
except ModuleNotFoundError as e:
|
except ModuleNotFoundError as e:
|
||||||
logger.error(f"Exception: {e}")
|
logger.error(f"Exception: {e}")
|
||||||
logger.error("In order to use Anthropic, you need to `pip install pipecat-ai[anthropic]`.")
|
logger.error("In order to use Anthropic, you need to `pip install pipecat-ai[anthropic]`.")
|
||||||
@@ -79,7 +80,15 @@ class AnthropicLLMSettings(LLMSettings):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
enable_prompt_caching: bool | _NotGiven = field(default_factory=lambda: _NOT_GIVEN)
|
enable_prompt_caching: bool | _NotGiven = field(default_factory=lambda: _NOT_GIVEN)
|
||||||
thinking: Union["AnthropicLLMService.ThinkingConfig", _NotGiven] = field(
|
# Override inherited LLMSettings fields to also accept anthropic's NotGiven
|
||||||
|
# sentinel. The service stores anthropic's NOT_GIVEN in these fields so
|
||||||
|
# they can be passed through unchanged to the AsyncAnthropic client.
|
||||||
|
temperature: float | None | _NotGiven | AnthropicNotGiven = field(
|
||||||
|
default_factory=lambda: _NOT_GIVEN
|
||||||
|
)
|
||||||
|
top_k: int | None | _NotGiven | AnthropicNotGiven = field(default_factory=lambda: _NOT_GIVEN)
|
||||||
|
top_p: float | None | _NotGiven | AnthropicNotGiven = field(default_factory=lambda: _NOT_GIVEN)
|
||||||
|
thinking: Union["AnthropicLLMService.ThinkingConfig", _NotGiven, AnthropicNotGiven] = field(
|
||||||
default_factory=lambda: _NOT_GIVEN
|
default_factory=lambda: _NOT_GIVEN
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ from openai import (
|
|||||||
AsyncStream,
|
AsyncStream,
|
||||||
DefaultAsyncHttpxClient,
|
DefaultAsyncHttpxClient,
|
||||||
)
|
)
|
||||||
|
from openai._types import NotGiven as OpenAINotGiven
|
||||||
from openai.types.chat import ChatCompletionChunk
|
from openai.types.chat import ChatCompletionChunk
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
@@ -50,7 +51,24 @@ class OpenAILLMSettings(LLMSettings):
|
|||||||
max_completion_tokens: Maximum completion tokens to generate.
|
max_completion_tokens: Maximum completion tokens to generate.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
max_completion_tokens: int | _NotGiven = field(default_factory=lambda: _NOT_GIVEN)
|
# Override inherited LLMSettings fields to also accept openai's NotGiven
|
||||||
|
# sentinel. The service stores openai's NOT_GIVEN in these fields so they
|
||||||
|
# can be passed through unchanged to the AsyncOpenAI client.
|
||||||
|
frequency_penalty: float | None | _NotGiven | OpenAINotGiven = field(
|
||||||
|
default_factory=lambda: _NOT_GIVEN
|
||||||
|
)
|
||||||
|
presence_penalty: float | None | _NotGiven | OpenAINotGiven = field(
|
||||||
|
default_factory=lambda: _NOT_GIVEN
|
||||||
|
)
|
||||||
|
seed: int | None | _NotGiven | OpenAINotGiven = field(default_factory=lambda: _NOT_GIVEN)
|
||||||
|
temperature: float | None | _NotGiven | OpenAINotGiven = field(
|
||||||
|
default_factory=lambda: _NOT_GIVEN
|
||||||
|
)
|
||||||
|
top_p: float | None | _NotGiven | OpenAINotGiven = field(default_factory=lambda: _NOT_GIVEN)
|
||||||
|
max_tokens: int | None | _NotGiven | OpenAINotGiven = field(default_factory=lambda: _NOT_GIVEN)
|
||||||
|
max_completion_tokens: int | _NotGiven | OpenAINotGiven = field(
|
||||||
|
default_factory=lambda: _NOT_GIVEN
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class BaseOpenAILLMService(LLMService):
|
class BaseOpenAILLMService(LLMService):
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ from typing import Any
|
|||||||
import httpx
|
import httpx
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from openai import NOT_GIVEN, AsyncOpenAI, AsyncStream, DefaultAsyncHttpxClient
|
from openai import NOT_GIVEN, AsyncOpenAI, AsyncStream, DefaultAsyncHttpxClient
|
||||||
|
from openai._types import NotGiven as OpenAINotGiven
|
||||||
from openai.types.responses import (
|
from openai.types.responses import (
|
||||||
ResponseCompletedEvent,
|
ResponseCompletedEvent,
|
||||||
ResponseFunctionCallArgumentsDeltaEvent,
|
ResponseFunctionCallArgumentsDeltaEvent,
|
||||||
@@ -97,7 +98,16 @@ class OpenAIResponsesLLMSettings(LLMSettings):
|
|||||||
max_completion_tokens: Maximum completion tokens to generate.
|
max_completion_tokens: Maximum completion tokens to generate.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
max_completion_tokens: int | _NotGiven = field(default_factory=lambda: _NOT_GIVEN)
|
# Override inherited LLMSettings fields to also accept openai's NotGiven
|
||||||
|
# sentinel. The service stores openai's NOT_GIVEN in these fields so they
|
||||||
|
# can be passed through unchanged to the AsyncOpenAI client.
|
||||||
|
temperature: float | None | _NotGiven | OpenAINotGiven = field(
|
||||||
|
default_factory=lambda: _NOT_GIVEN
|
||||||
|
)
|
||||||
|
top_p: float | None | _NotGiven | OpenAINotGiven = field(default_factory=lambda: _NOT_GIVEN)
|
||||||
|
max_completion_tokens: int | _NotGiven | OpenAINotGiven = field(
|
||||||
|
default_factory=lambda: _NOT_GIVEN
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user