Update OpenAILLMService subclasses to use the new build_chat_completion_params function

This commit is contained in:
Mark Backman
2025-08-07 11:21:42 -04:00
parent 5c86f8e687
commit 4c029fcfa7
7 changed files with 63 additions and 86 deletions

View File

@@ -106,6 +106,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`LLMUserContextAggregator` and `LLMAssistantResponseAggregator` (or
LLM-specific subclasses thereof) instead.
## [Unreleased]
### Added
- For `OpenAILLMService` and its subclasses, added the ability to retry
executing a chat completion after a timeout period. The new args are
`timeout` and `retry_on_timeout`. This feature is disabled by default.
## [0.0.78] - 2025-08-07
### Added

View File

@@ -9,8 +9,7 @@
from typing import List
from loguru import logger
from openai import AsyncStream
from openai.types.chat import ChatCompletionChunk, ChatCompletionMessageParam
from openai.types.chat import ChatCompletionMessageParam
from pipecat.processors.aggregators.openai_llm_context import OpenAILLMContext
from pipecat.services.openai.llm import OpenAILLMService
@@ -55,20 +54,13 @@ class CerebrasLLMService(OpenAILLMService):
logger.debug(f"Creating Cerebras client with api {base_url}")
return super().create_client(api_key, base_url, **kwargs)
async def get_chat_completions(
def build_chat_completion_params(
self, context: OpenAILLMContext, messages: List[ChatCompletionMessageParam]
) -> AsyncStream[ChatCompletionChunk]:
"""Create a streaming chat completion using Cerebras's API.
) -> dict:
"""Build parameters for Cerebras chat completion request.
Args:
context: The context object containing tools configuration
and other settings for the chat completion.
messages: The list of messages comprising
the conversation history and current request.
Returns:
A streaming response of chat completion
chunks that can be processed asynchronously.
Cerebras supports a subset of OpenAI parameters, focusing on core
completion settings without advanced features like frequency/presence penalties.
"""
params = {
"model": self.model_name,
@@ -83,6 +75,4 @@ class CerebrasLLMService(OpenAILLMService):
}
params.update(self._settings["extra"])
chunks = await self._client.chat.completions.create(**params)
return chunks
return params

View File

@@ -9,8 +9,7 @@
from typing import List
from loguru import logger
from openai import AsyncStream
from openai.types.chat import ChatCompletionChunk, ChatCompletionMessageParam
from openai.types.chat import ChatCompletionMessageParam
from pipecat.processors.aggregators.openai_llm_context import OpenAILLMContext
from pipecat.services.openai.llm import OpenAILLMService
@@ -55,20 +54,12 @@ class DeepSeekLLMService(OpenAILLMService):
logger.debug(f"Creating DeepSeek client with api {base_url}")
return super().create_client(api_key, base_url, **kwargs)
async def get_chat_completions(
def _build_chat_completion_params(
self, context: OpenAILLMContext, messages: List[ChatCompletionMessageParam]
) -> AsyncStream[ChatCompletionChunk]:
"""Create a streaming chat completion using DeepSeek's API.
) -> dict:
"""Build parameters for DeepSeek chat completion request.
Args:
context: The context object containing tools configuration
and other settings for the chat completion.
messages: The list of messages comprising the conversation
history and current request.
Returns:
A streaming response of chat completion chunks that can be
processed asynchronously.
DeepSeek doesn't support some OpenAI parameters like seed and max_completion_tokens.
"""
params = {
"model": self.model_name,
@@ -85,6 +76,4 @@ class DeepSeekLLMService(OpenAILLMService):
}
params.update(self._settings["extra"])
chunks = await self._client.chat.completions.create(**params)
return chunks
return params

View File

@@ -54,20 +54,13 @@ class FireworksLLMService(OpenAILLMService):
logger.debug(f"Creating Fireworks client with api {base_url}")
return super().create_client(api_key, base_url, **kwargs)
async def get_chat_completions(
def build_chat_completion_params(
self, context: OpenAILLMContext, messages: List[ChatCompletionMessageParam]
):
"""Get chat completions from Fireworks API.
) -> dict:
"""Build parameters for Fireworks chat completion request.
Removes OpenAI-specific parameters not supported by Fireworks and
configures the request with Fireworks-compatible settings.
Args:
context: The OpenAI LLM context containing tools and settings.
messages: List of chat completion message parameters.
Returns:
Async generator yielding chat completion chunks from Fireworks API.
Fireworks doesn't support some OpenAI parameters like seed, max_completion_tokens,
and stream_options.
"""
params = {
"model": self.model_name,
@@ -83,6 +76,4 @@ class FireworksLLMService(OpenAILLMService):
}
params.update(self._settings["extra"])
chunks = await self._client.chat.completions.create(**params)
return chunks
return params

View File

@@ -13,14 +13,13 @@ enabling integration with OpenPipe's fine-tuning and monitoring capabilities.
from typing import Dict, List, Optional
from loguru import logger
from openai.types.chat import ChatCompletionChunk, ChatCompletionMessageParam
from openai.types.chat import ChatCompletionMessageParam
from pipecat.processors.aggregators.openai_llm_context import OpenAILLMContext
from pipecat.services.openai.llm import OpenAILLMService
try:
from openpipe import AsyncOpenAI as OpenPipeAI
from openpipe import AsyncStream
except ModuleNotFoundError as e:
logger.error(f"Exception: {e}")
logger.error("In order to use OpenPipe, you need to `pip install pipecat-ai[openpipe]`.")
@@ -87,22 +86,27 @@ class OpenPipeLLMService(OpenAILLMService):
)
return client
async def get_chat_completions(
def build_chat_completion_params(
self, context: OpenAILLMContext, messages: List[ChatCompletionMessageParam]
) -> AsyncStream[ChatCompletionChunk]:
"""Generate streaming chat completions with OpenPipe logging.
) -> dict:
"""Build parameters for OpenPipe chat completion request.
Adds OpenPipe-specific logging and tagging parameters.
Args:
context: The OpenAI LLM context containing conversation state.
messages: List of chat completion message parameters.
context: The LLM context containing tools and configuration.
messages: List of chat completion messages to send.
Returns:
Async stream of chat completion chunks.
Dictionary of parameters for the chat completion request.
"""
chunks = await self._client.chat.completions.create(
model=self.model_name,
stream=True,
messages=messages,
openpipe={"tags": self._tags, "log_request": True},
)
return chunks
# Start with base parameters
params = super().build_chat_completion_params(context, messages)
# Add OpenPipe-specific parameters
params["openpipe"] = {
"tags": self._tags,
"log_request": True,
}
return params

View File

@@ -13,8 +13,8 @@ reporting patterns while maintaining compatibility with the Pipecat framework.
from typing import List
from openai import NOT_GIVEN, AsyncStream
from openai.types.chat import ChatCompletionChunk, ChatCompletionMessageParam
from openai import NOT_GIVEN
from openai.types.chat import ChatCompletionMessageParam
from pipecat.metrics.metrics import LLMTokenUsage
from pipecat.processors.aggregators.openai_llm_context import OpenAILLMContext
@@ -53,17 +53,12 @@ class PerplexityLLMService(OpenAILLMService):
self._has_reported_prompt_tokens = False
self._is_processing = False
async def get_chat_completions(
def build_chat_completion_params(
self, context: OpenAILLMContext, messages: List[ChatCompletionMessageParam]
) -> AsyncStream[ChatCompletionChunk]:
"""Get chat completions from Perplexity API using OpenAI-compatible parameters.
) -> dict:
"""Build parameters for Perplexity chat completion request.
Args:
context: The context containing conversation history and settings.
messages: The messages to send to the API.
Returns:
A stream of chat completion chunks from the Perplexity API.
Perplexity uses a subset of OpenAI parameters and doesn't support tools.
"""
params = {
"model": self.model_name,
@@ -83,8 +78,7 @@ class PerplexityLLMService(OpenAILLMService):
if self._settings["max_tokens"] is not NOT_GIVEN:
params["max_tokens"] = self._settings["max_tokens"]
chunks = await self._client.chat.completions.create(**params)
return chunks
return params
async def _process_context(self, context: OpenAILLMContext):
"""Process a context through the LLM and accumulate token usage metrics.

View File

@@ -68,17 +68,20 @@ class SambaNovaLLMService(OpenAILLMService): # type: ignore
logger.debug(f"Creating SambaNova client with API {base_url}")
return super().create_client(api_key, base_url, **kwargs)
async def get_chat_completions(
def build_chat_completion_params(
self, context: OpenAILLMContext, messages: List[ChatCompletionMessageParam]
) -> Any:
"""Get chat completions from SambaNova API endpoint.
) -> dict:
"""Build parameters for SambaNova chat completion request.
SambaNova doesn't support some OpenAI parameters like frequency_penalty,
presence_penalty, and seed.
Args:
context: OpenAI LLM context containing tools and configuration.
messages: List of chat completion message parameters.
context: The LLM context containing tools and configuration.
messages: List of chat completion messages to send.
Returns:
Chat completion response stream from SambaNova API.
Dictionary of parameters for the chat completion request.
"""
params = {
"model": self.model_name,
@@ -94,9 +97,7 @@ class SambaNovaLLMService(OpenAILLMService): # type: ignore
}
params.update(self._settings["extra"])
chunks = await self._client.chat.completions.create(**params)
return chunks
return params
@traced_llm # type: ignore
async def _process_context(self, context: OpenAILLMContext) -> AsyncStream[ChatCompletionChunk]: