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:
|
||||
from anthropic import NOT_GIVEN, APITimeoutError, AsyncAnthropic
|
||||
from anthropic import NotGiven as AnthropicNotGiven
|
||||
except ModuleNotFoundError as e:
|
||||
logger.error(f"Exception: {e}")
|
||||
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)
|
||||
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
|
||||
)
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ from openai import (
|
||||
AsyncStream,
|
||||
DefaultAsyncHttpxClient,
|
||||
)
|
||||
from openai._types import NotGiven as OpenAINotGiven
|
||||
from openai.types.chat import ChatCompletionChunk
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
@@ -50,7 +51,24 @@ class OpenAILLMSettings(LLMSettings):
|
||||
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):
|
||||
|
||||
@@ -18,6 +18,7 @@ from typing import Any
|
||||
import httpx
|
||||
from loguru import logger
|
||||
from openai import NOT_GIVEN, AsyncOpenAI, AsyncStream, DefaultAsyncHttpxClient
|
||||
from openai._types import NotGiven as OpenAINotGiven
|
||||
from openai.types.responses import (
|
||||
ResponseCompletedEvent,
|
||||
ResponseFunctionCallArgumentsDeltaEvent,
|
||||
@@ -97,7 +98,16 @@ class OpenAIResponsesLLMSettings(LLMSettings):
|
||||
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