Merge pull request #2517 from pipecat-ai/aleix/unify-get-messages-for-logging

unify get_messages_for_logging()
This commit is contained in:
Aleix Conchillo Flaqué
2025-08-27 12:49:36 -07:00
committed by GitHub
13 changed files with 33 additions and 30 deletions

View File

@@ -100,6 +100,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- Fixed some `get_messages_for_logging()` that were returning a JSON string
instead of a list.
- Fixed a `DailyTransport` issue that prevented DTMF tones from being sent. - Fixed a `DailyTransport` issue that prevented DTMF tones from being sent.
- Fixed a missing import in `SentryMetrics`. - Fixed a missing import in `SentryMetrics`.

View File

@@ -11,7 +11,7 @@ adapters that handle tool format conversion and standardization.
""" """
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import Any, Generic, List, TypeVar, Union, cast from typing import Any, Dict, Generic, List, TypeVar
from loguru import logger from loguru import logger
@@ -63,7 +63,7 @@ class BaseLLMAdapter(ABC, Generic[TLLMInvocationParams]):
pass pass
@abstractmethod @abstractmethod
def get_messages_for_logging(self, context: LLMContext) -> List[dict[str, Any]]: def get_messages_for_logging(self, context: LLMContext) -> List[Dict[str, Any]]:
"""Get messages from a universal LLM context in a format ready for logging about this provider. """Get messages from a universal LLM context in a format ready for logging about this provider.
Args: Args:

View File

@@ -43,7 +43,7 @@ class AnthropicLLMAdapter(BaseLLMAdapter[AnthropicLLMInvocationParams]):
""" """
raise NotImplementedError("Universal LLMContext is not yet supported for Anthropic.") raise NotImplementedError("Universal LLMContext is not yet supported for Anthropic.")
def get_messages_for_logging(self, context) -> List[dict[str, Any]]: def get_messages_for_logging(self, context) -> List[Dict[str, Any]]:
"""Get messages from a universal LLM context in a format ready for logging about Anthropic. """Get messages from a universal LLM context in a format ready for logging about Anthropic.
Removes or truncates sensitive data like image content for safe logging. Removes or truncates sensitive data like image content for safe logging.

View File

@@ -44,7 +44,7 @@ class AWSNovaSonicLLMAdapter(BaseLLMAdapter[AWSNovaSonicLLMInvocationParams]):
""" """
raise NotImplementedError("Universal LLMContext is not yet supported for AWS Nova Sonic.") raise NotImplementedError("Universal LLMContext is not yet supported for AWS Nova Sonic.")
def get_messages_for_logging(self, context) -> List[dict[str, Any]]: def get_messages_for_logging(self, context) -> List[Dict[str, Any]]:
"""Get messages from a universal LLM context in a format ready for logging about AWS Nova Sonic. """Get messages from a universal LLM context in a format ready for logging about AWS Nova Sonic.
Removes or truncates sensitive data like image content for safe logging. Removes or truncates sensitive data like image content for safe logging.

View File

@@ -43,7 +43,7 @@ class AWSBedrockLLMAdapter(BaseLLMAdapter[AWSBedrockLLMInvocationParams]):
""" """
raise NotImplementedError("Universal LLMContext is not yet supported for AWS Bedrock.") raise NotImplementedError("Universal LLMContext is not yet supported for AWS Bedrock.")
def get_messages_for_logging(self, context) -> List[dict[str, Any]]: def get_messages_for_logging(self, context) -> List[Dict[str, Any]]:
"""Get messages from a universal LLM context in a format ready for logging about AWS Bedrock. """Get messages from a universal LLM context in a format ready for logging about AWS Bedrock.
Removes or truncates sensitive data like image content for safe logging. Removes or truncates sensitive data like image content for safe logging.

View File

@@ -91,7 +91,7 @@ class GeminiLLMAdapter(BaseLLMAdapter[GeminiLLMInvocationParams]):
return formatted_standard_tools + custom_gemini_tools return formatted_standard_tools + custom_gemini_tools
def get_messages_for_logging(self, context: LLMContext) -> List[dict[str, Any]]: def get_messages_for_logging(self, context: LLMContext) -> List[Dict[str, Any]]:
"""Get messages from a universal LLM context in a format ready for logging about Gemini. """Get messages from a universal LLM context in a format ready for logging about Gemini.
Removes or truncates sensitive data like image content for safe logging. Removes or truncates sensitive data like image content for safe logging.

View File

@@ -8,7 +8,7 @@
import copy import copy
import json import json
from typing import Any, List, TypedDict from typing import Any, Dict, List, TypedDict
from openai._types import NOT_GIVEN as OPEN_AI_NOT_GIVEN from openai._types import NOT_GIVEN as OPEN_AI_NOT_GIVEN
from openai._types import NotGiven as OpenAINotGiven from openai._types import NotGiven as OpenAINotGiven
@@ -79,7 +79,7 @@ class OpenAILLMAdapter(BaseLLMAdapter[OpenAILLMInvocationParams]):
for func in functions_schema for func in functions_schema
] ]
def get_messages_for_logging(self, context: LLMContext) -> List[dict[str, Any]]: def get_messages_for_logging(self, context: LLMContext) -> List[Dict[str, Any]]:
"""Get messages from a universal LLM context in a format ready for logging about OpenAI. """Get messages from a universal LLM context in a format ready for logging about OpenAI.
Removes or truncates sensitive data like image content for safe logging. Removes or truncates sensitive data like image content for safe logging.
@@ -102,7 +102,7 @@ class OpenAILLMAdapter(BaseLLMAdapter[OpenAILLMInvocationParams]):
if "mime_type" in msg and msg["mime_type"].startswith("image/"): if "mime_type" in msg and msg["mime_type"].startswith("image/"):
msg["data"] = "..." msg["data"] = "..."
msgs.append(msg) msgs.append(msg)
return json.dumps(msgs, ensure_ascii=False) return msgs
def _get_messages(self, context: LLMContext) -> List[LLMContextMessage]: def _get_messages(self, context: LLMContext) -> List[LLMContextMessage]:
return context.get_messages("openai") return context.get_messages("openai")

View File

@@ -6,7 +6,7 @@
"""OpenAI Realtime LLM adapter for Pipecat.""" """OpenAI Realtime LLM adapter for Pipecat."""
from typing import Any, Dict, List, TypedDict, Union from typing import Any, Dict, List, TypedDict
from pipecat.adapters.base_llm_adapter import BaseLLMAdapter from pipecat.adapters.base_llm_adapter import BaseLLMAdapter
from pipecat.adapters.schemas.function_schema import FunctionSchema from pipecat.adapters.schemas.function_schema import FunctionSchema
@@ -43,7 +43,7 @@ class OpenAIRealtimeLLMAdapter(BaseLLMAdapter):
""" """
raise NotImplementedError("Universal LLMContext is not yet supported for OpenAI Realtime.") raise NotImplementedError("Universal LLMContext is not yet supported for OpenAI Realtime.")
def get_messages_for_logging(self, context) -> List[dict[str, Any]]: def get_messages_for_logging(self, context) -> List[Dict[str, Any]]:
"""Get messages from a universal LLM context in a format ready for logging about OpenAI Realtime. """Get messages from a universal LLM context in a format ready for logging about OpenAI Realtime.
Removes or truncates sensitive data like image content for safe logging. Removes or truncates sensitive data like image content for safe logging.

View File

@@ -15,7 +15,7 @@ import copy
import io import io
import json import json
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any, List, Optional from typing import Any, Dict, List, Optional
from openai._types import NOT_GIVEN, NotGiven from openai._types import NOT_GIVEN, NotGiven
from openai.types.chat import ( from openai.types.chat import (
@@ -183,13 +183,13 @@ class OpenAILLMContext:
""" """
return json.dumps(self._messages, cls=CustomEncoder, ensure_ascii=False, indent=2) return json.dumps(self._messages, cls=CustomEncoder, ensure_ascii=False, indent=2)
def get_messages_for_logging(self) -> str: def get_messages_for_logging(self) -> List[Dict[str, Any]]:
"""Get sanitized messages suitable for logging. """Get sanitized messages suitable for logging.
Removes or truncates sensitive data like image content for safe logging. Removes or truncates sensitive data like image content for safe logging.
Returns: Returns:
JSON string with sanitized message content for logging. List of messages in a format ready for logging.
""" """
msgs = [] msgs = []
for message in self.messages: for message in self.messages:
@@ -203,7 +203,7 @@ class OpenAILLMContext:
if "mime_type" in msg and msg["mime_type"].startswith("image/"): if "mime_type" in msg and msg["mime_type"].startswith("image/"):
msg["data"] = "..." msg["data"] = "..."
msgs.append(msg) msgs.append(msg)
return json.dumps(msgs, ensure_ascii=False) return msgs
def from_standard_message(self, message): def from_standard_message(self, message):
"""Convert from OpenAI message format to OpenAI message format (passthrough). """Convert from OpenAI message format to OpenAI message format (passthrough).

View File

@@ -295,7 +295,7 @@ class AnthropicLLMService(LLMService):
await self.start_processing_metrics() await self.start_processing_metrics()
logger.debug( logger.debug(
f"{self}: Generating chat [{context.system}] | [{context.get_messages_for_logging()}]" f"{self}: Generating chat [{context.system}] | {context.get_messages_for_logging()}"
) )
messages = context.messages messages = context.messages
@@ -933,13 +933,13 @@ class AnthropicLLMContext(OpenAILLMContext):
messages.insert(0, {"role": "system", "content": self.system}) messages.insert(0, {"role": "system", "content": self.system})
return messages return messages
def get_messages_for_logging(self) -> str: def get_messages_for_logging(self) -> List[Dict[str, Any]]:
"""Get messages formatted for logging with sensitive data redacted. """Get messages formatted for logging with sensitive data redacted.
Replaces image data with placeholder text for cleaner logs. Replaces image data with placeholder text for cleaner logs.
Returns: Returns:
JSON string representation of messages for logging. List of messages in a format ready for logging.
""" """
msgs = [] msgs = []
for message in self.messages: for message in self.messages:
@@ -950,7 +950,7 @@ class AnthropicLLMContext(OpenAILLMContext):
if item["type"] == "image": if item["type"] == "image":
item["source"]["data"] = "..." item["source"]["data"] = "..."
msgs.append(msg) msgs.append(msg)
return json.dumps(msgs) return msgs
class AnthropicUserContextAggregator(LLMUserContextAggregator): class AnthropicUserContextAggregator(LLMUserContextAggregator):

View File

@@ -556,11 +556,11 @@ class AWSBedrockLLMContext(OpenAILLMContext):
messages.insert(0, {"role": "system", "content": self.system}) messages.insert(0, {"role": "system", "content": self.system})
return messages return messages
def get_messages_for_logging(self) -> str: def get_messages_for_logging(self) -> List[Dict[str, Any]]:
"""Get messages formatted for logging with sensitive data redacted. """Get messages formatted for logging with sensitive data redacted.
Returns: Returns:
JSON string representation of messages with image data redacted. List of messages in a format ready for logging.
""" """
msgs = [] msgs = []
for message in self.messages: for message in self.messages:
@@ -571,7 +571,7 @@ class AWSBedrockLLMContext(OpenAILLMContext):
if item.get("image"): if item.get("image"):
item["source"]["bytes"] = "..." item["source"]["bytes"] = "..."
msgs.append(msg) msgs.append(msg)
return json.dumps(msgs) return msgs
class AWSBedrockUserContextAggregator(LLMUserContextAggregator): class AWSBedrockUserContextAggregator(LLMUserContextAggregator):

View File

@@ -292,11 +292,11 @@ class GoogleLLMContext(OpenAILLMContext):
# Add the converted messages to our existing messages # Add the converted messages to our existing messages
self._messages.extend(converted_messages) self._messages.extend(converted_messages)
def get_messages_for_logging(self): def get_messages_for_logging(self) -> List[Dict[str, Any]]:
"""Get messages formatted for logging with sensitive data redacted. """Get messages formatted for logging with sensitive data redacted.
Returns: Returns:
List of message dictionaries with inline data redacted. List of messages in a format ready for logging.
""" """
msgs = [] msgs = []
for message in self.messages: for message in self.messages:
@@ -858,8 +858,8 @@ class GoogleLLMService(LLMService):
self, context: OpenAILLMContext self, context: OpenAILLMContext
) -> AsyncIterator[GenerateContentResponse]: ) -> AsyncIterator[GenerateContentResponse]:
logger.debug( logger.debug(
# f"{self}: Generating chat [{self._system_instruction}] | [{context.get_messages_for_logging()}]" # f"{self}: Generating chat [{self._system_instruction}] | {context.get_messages_for_logging()}"
f"{self}: Generating chat from OpenAI context [{context.get_messages_for_logging()}]" f"{self}: Generating chat from OpenAI context {context.get_messages_for_logging()}"
) )
params = GeminiLLMInvocationParams( params = GeminiLLMInvocationParams(
@@ -875,8 +875,8 @@ class GoogleLLMService(LLMService):
) -> AsyncIterator[GenerateContentResponse]: ) -> AsyncIterator[GenerateContentResponse]:
adapter = self.get_llm_adapter() adapter = self.get_llm_adapter()
logger.debug( logger.debug(
# f"{self}: Generating chat [{self._system_instruction}] | [{context.get_messages_for_logging()}]" # f"{self}: Generating chat [{self._system_instruction}] | {context.get_messages_for_logging()}"
f"{self}: Generating chat from universal context [{adapter.get_messages_for_logging(context)}]" f"{self}: Generating chat from universal context {adapter.get_messages_for_logging(context)}"
) )
params: GeminiLLMInvocationParams = adapter.get_llm_invocation_params(context) params: GeminiLLMInvocationParams = adapter.get_llm_invocation_params(context)

View File

@@ -279,7 +279,7 @@ class BaseOpenAILLMService(LLMService):
self, context: OpenAILLMContext self, context: OpenAILLMContext
) -> AsyncStream[ChatCompletionChunk]: ) -> AsyncStream[ChatCompletionChunk]:
logger.debug( logger.debug(
f"{self}: Generating chat from OpenAI context [{context.get_messages_for_logging()}]" f"{self}: Generating chat from OpenAI context {context.get_messages_for_logging()}"
) )
messages: List[ChatCompletionMessageParam] = context.get_messages() messages: List[ChatCompletionMessageParam] = context.get_messages()
@@ -311,7 +311,7 @@ class BaseOpenAILLMService(LLMService):
) -> AsyncStream[ChatCompletionChunk]: ) -> AsyncStream[ChatCompletionChunk]:
adapter = self.get_llm_adapter() adapter = self.get_llm_adapter()
logger.debug( logger.debug(
f"{self}: Generating chat from universal context [{adapter.get_messages_for_logging(context)}]" f"{self}: Generating chat from universal context {adapter.get_messages_for_logging(context)}"
) )
params: OpenAILLMInvocationParams = adapter.get_llm_invocation_params(context) params: OpenAILLMInvocationParams = adapter.get_llm_invocation_params(context)