Skip to content

Commit

Permalink
Addresses Issue langchain-ai#245
Browse files Browse the repository at this point in the history
Added `logger_util` to enable package and class wide logging in `langchain-aws`.
Added logging for `invoke` and `ainvoke`.
  • Loading branch information
Vishal Patil committed Jan 15, 2025
1 parent 94cb00b commit 55aeab9
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 1 deletion.
6 changes: 5 additions & 1 deletion libs/aws/langchain_aws/chat_models/bedrock.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,14 @@
BedrockBase,
_combine_generation_info_for_llm_result,
)
from langchain_aws.logger_util import get_logger
from langchain_aws.utils import (
get_num_tokens_anthropic,
get_token_ids_anthropic,
)

logger = get_logger(__name__)


def _convert_one_message_to_text_llama(message: BaseMessage) -> str:
if isinstance(message, ChatMessage):
Expand Down Expand Up @@ -520,6 +523,7 @@ def _generate(
run_manager: Optional[CallbackManagerForLLMRun] = None,
**kwargs: Any,
) -> ChatResult:
logger.info(f"The input message sent by user: {messages}")
if self.beta_use_converse_api:
return self._as_converse._generate(
messages, stop=stop, run_manager=run_manager, **kwargs
Expand Down Expand Up @@ -595,7 +599,7 @@ def _generate(
tool_calls=cast(List[ToolCall], tool_calls),
usage_metadata=usage_metadata,
)

logger.info(f"The output message sent by user: {msg}")
return ChatResult(
generations=[
ChatGeneration(
Expand Down
5 changes: 5 additions & 0 deletions libs/aws/langchain_aws/chat_models/bedrock_converse.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,13 @@
from typing_extensions import Self

from langchain_aws.function_calling import ToolsOutputParser
from langchain_aws.logger_util import get_logger

_BM = TypeVar("_BM", bound=BaseModel)
_DictOrPydanticClass = Union[Dict[str, Any], Type[_BM], Type]

logger = get_logger(__name__)


class ChatBedrockConverse(BaseChatModel):
"""Bedrock chat model integration built on the Bedrock converse API.
Expand Down Expand Up @@ -495,13 +498,15 @@ def _generate(
) -> ChatResult:
"""Top Level call"""
bedrock_messages, system = _messages_to_bedrock(messages)
logger.debug(f"input message: {bedrock_messages}")
params = self._converse_params(
stop=stop, **_snake_to_camel_keys(kwargs, excluded_keys={"inputSchema"})
)
response = self.client.converse(
messages=bedrock_messages, system=system, **params
)
response_message = _parse_response(response)
logger.info(f"output message: {response_message}")
return ChatResult(generations=[ChatGeneration(message=response_message)])

def _stream(
Expand Down
107 changes: 107 additions & 0 deletions libs/aws/langchain_aws/logger_util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import logging
import os

# Environment variable to set the application logger(s) in debug mode during runtime
__DEBUG = True if os.environ.get("LANGCHAIN_AWS_DEBUG") else False

# Flag for root debug logger to set the root debug logger in debug mode during runtime
# Root debug logger will print boto3 as well as application debug logs if set to true
# This flag will be set to true if LANGCHAIN_AWS_DEBUG = LANGCHAIN_AWS_DEBUG_ROOT = true
__ROOT_DEBUG = __DEBUG if os.environ.get("LANGCHAIN_AWS_DEBUG_ROOT") else False

# If application level debug flag is set, set the default logging level to DEBUG
# else ERROR
if __DEBUG:
DEFAULT_LOG_LEVEL: int = logging.DEBUG
else:
DEFAULT_LOG_LEVEL: int = logging.INFO

# Checking if we have a log file handler available, if not, setting default handler
# to None
DEFAULT_LOG_FILE = os.environ.get("LANGCHAIN_AWS_LOG_OUTPUT", "-")
if DEFAULT_LOG_FILE == "-":
DEFAULT_LOG_HANDLER: logging.Handler = None
else:
DEFAULT_LOG_HANDLER: logging.Handler = logging.FileHandler(DEFAULT_LOG_FILE)

# If application debug mode set then include filename and line numbers in the log format
if __DEBUG:
DEFAULT_LOG_FORMAT: str = (
"%(asctime)s %(levelname)s | [%(filename)s:%(lineno)s] | %(name)s - %(message)s"
)
else:
DEFAULT_LOG_FORMAT: str = "%(asctime)s %(levelname)s | %(name)s - %(message)s"


# This block is to set a log formatter. colorama is used to print colored logs
try:
import colorama
import coloredlogs

colorama.init()

# If a DEFAULT_LOG_HANDLER is set in the LANGCHAIN_AWS_LOG_OUTPUT env var, skip
# colored logs format
if DEFAULT_LOG_HANDLER:
DEFAULT_LOG_FORMATTER: logging.Formatter = logging.Formatter(DEFAULT_LOG_FORMAT)
else:
DEFAULT_LOG_FORMATTER: logging.Formatter = coloredlogs.ColoredFormatter(
DEFAULT_LOG_FORMAT
)
# If colorama is not present, use the logging lib formatter without colored logs
except ImportError:
colorama = None
coloredlogs = None

DEFAULT_LOG_FORMATTER: logging.Formatter = logging.Formatter(DEFAULT_LOG_FORMAT)

def get_logger(
logger_name: str = None,
log_handler: logging.Handler = DEFAULT_LOG_HANDLER,
log_formatter: logging.Formatter = DEFAULT_LOG_FORMATTER,
log_level: int = DEFAULT_LOG_LEVEL,
) -> logging.Logger:
"""
Creates a logger with the passed logger_name at module level or function level
Args:
logger_name: Optional arg. Module/function name for the logger object. If the
same logger_name is passed again in the function, the same logger object will
be returned for the __LOGGER_CACHE
log_handler: Optional arg. None by default. If default is None, sys.out is set
as the default for a logger that has not been initialized (i.e. logger object
not in __LOGGER_CACHE). Only one handler is supported per logger object in
this implementation
log_formatter: Optional arg. Default format is determined by __DEBUG flag. If
set, then include file and lines info. colorama is being used for coleredLogs.
colored logs are only displayed in standard streams. Logging into files will
display regular log format
log_level: Optional arg. Log level to be set. default value will be
DEFAULT_LOG_LEVEL. The variable is set as DEBUG if LANGCHAIN_AWS_DEBUG
environment variable is True else it is set as INFO
If logger_name is None or if the __DEBUG_ROOT flag is set, by default we want
to initialize the root logger
"""

if not logger_name or __ROOT_DEBUG:
logger = logging.getLogger()
else:
logger = logging.getLogger(logger_name)

# If log handler is None, set default stream as std.out
if not log_handler:
log_handler = logging.StreamHandler()

# add formatter to handler
log_handler.setFormatter(log_formatter)

# Making sure only a single handler is present even if we have multiple
# initializations with the same logger name
if not len(logger.handlers):
logger.addHandler(log_handler)

logger.setLevel(log_level)
return logger

0 comments on commit 55aeab9

Please sign in to comment.