From 3ce3b4fcce6d067af2a525c412385f97a5455f57 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmik Date: Wed, 8 Nov 2023 12:46:25 +0100 Subject: [PATCH 1/8] Update result parser --- .../openai/chat_completion_parsers.py | 4 ++-- src/comet_llm/autologgers/openai/patcher.py | 22 ++++++++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/comet_llm/autologgers/openai/chat_completion_parsers.py b/src/comet_llm/autologgers/openai/chat_completion_parsers.py index cf39eef702..c939f68a46 100644 --- a/src/comet_llm/autologgers/openai/chat_completion_parsers.py +++ b/src/comet_llm/autologgers/openai/chat_completion_parsers.py @@ -44,13 +44,13 @@ def parse_create_arguments(kwargs: Dict[str, Any]) -> Tuple[Inputs, Metadata]: def parse_create_result( - result: Union["OpenAIObject", Iterable["OpenAIObject"]] + result: Union["OpenAIObject", Iterable["OpenAIObject"]] # new object type ) -> Tuple[Outputs, Metadata]: if inspect.isgenerator(result): choices = "Generation is not logged when using stream mode" metadata = {} else: - result_dict = result.to_dict() # type: ignore + result_dict = result.dict() # type: ignore choices: List[Dict[str, Any]] = result_dict.pop("choices") # type: ignore metadata = result_dict diff --git a/src/comet_llm/autologgers/openai/patcher.py b/src/comet_llm/autologgers/openai/patcher.py index ade8a8ec42..6cdeb1521e 100644 --- a/src/comet_llm/autologgers/openai/patcher.py +++ b/src/comet_llm/autologgers/openai/patcher.py @@ -21,12 +21,28 @@ def patch(registry: "registry.Registry") -> None: + # registry.register_before( + # "openai", "ChatCompletion.create", hooks.before_chat_completion_create + # ) + # registry.register_after( + # "openai", "ChatCompletion.create", hooks.after_chat_completion_create + # ) + # registry.register_after_exception( + # "openai", "ChatCompletion.create", hooks.after_exception_chat_completion_create + # ) + registry.register_before( - "openai", "ChatCompletion.create", hooks.before_chat_completion_create + "openai.resources.chat.completions", + "Completions.create", + hooks.before_chat_completion_create, ) registry.register_after( - "openai", "ChatCompletion.create", hooks.after_chat_completion_create + "openai.resources.chat.completions", + "Completions.create", + hooks.after_chat_completion_create, ) registry.register_after_exception( - "openai", "ChatCompletion.create", hooks.after_exception_chat_completion_create + "openai.resources.chat.completions", + "Completions.create", + hooks.after_exception_chat_completion_create, ) From c660f0aa8e01e6416cddb9dad40309d9ee2a0375 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmik Date: Wed, 8 Nov 2023 17:33:45 +0100 Subject: [PATCH 2/8] Add deprecation logic --- .../openai/chat_completion_parsers.py | 42 ++++++++++++++++++- .../openai/test_chat_completion_parsers.py | 4 +- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/comet_llm/autologgers/openai/chat_completion_parsers.py b/src/comet_llm/autologgers/openai/chat_completion_parsers.py index c939f68a46..513e85480e 100644 --- a/src/comet_llm/autologgers/openai/chat_completion_parsers.py +++ b/src/comet_llm/autologgers/openai/chat_completion_parsers.py @@ -13,15 +13,22 @@ # ******************************************************* import inspect +import logging + from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Tuple, Union +from . import metadata if TYPE_CHECKING: from openai.openai_object import OpenAIObject + from openai import Stream Inputs = Dict[str, Any] Outputs = Dict[str, Any] Metadata = Dict[str, Any] +CreateCallResult = Union["OpenAIObject", Iterable["OpenAIObject"]] + +LOGGER = logging.getLogger(__file__) def create_arguments_supported(kwargs: Dict[str, Any]) -> bool: if "messages" not in kwargs: @@ -44,13 +51,42 @@ def parse_create_arguments(kwargs: Dict[str, Any]) -> Tuple[Inputs, Metadata]: def parse_create_result( - result: Union["OpenAIObject", Iterable["OpenAIObject"]] # new object type + result: Union["OpenAIObject", Iterable["OpenAIObject"]] # TODO: new object type +) -> Tuple[Outputs, Metadata]: + openai_version = metadata.openai_version() + + if openai_version is not None and openai_version.startswith("0."): + return _deprecated_parse_create_result(result) + + return _parse_create_result(result) + +def _deprecated_parse_create_result( + result: Union["OpenAIObject", Iterable["OpenAIObject"]] # TODO: new object type ) -> Tuple[Outputs, Metadata]: if inspect.isgenerator(result): choices = "Generation is not logged when using stream mode" metadata = {} else: - result_dict = result.dict() # type: ignore + result_dict = result.to_dict() + choices: List[Dict[str, Any]] = result_dict.pop("choices") # type: ignore + metadata = result_dict + + outputs = {"choices": choices} + + if "model" in metadata: + metadata["output_model"] = metadata.pop("model") + + return outputs, metadata + +def _parse_create_result( + result: Union["OpenAIObject", "Stream"] # TODO: new object type +) -> Tuple[Outputs, Metadata]: + stream_mode = not hasattr(result, "dict") + if stream_mode: + choices = "Generation is not logged when using stream mode" + metadata = {} + else: + result_dict = result.dict() choices: List[Dict[str, Any]] = result_dict.pop("choices") # type: ignore metadata = result_dict @@ -60,3 +96,5 @@ def parse_create_result( metadata["output_model"] = metadata.pop("model") return outputs, metadata + + \ No newline at end of file diff --git a/tests/unit/autologgers/openai/test_chat_completion_parsers.py b/tests/unit/autologgers/openai/test_chat_completion_parsers.py index 8ca3beb90d..853bca59df 100644 --- a/tests/unit/autologgers/openai/test_chat_completion_parsers.py +++ b/tests/unit/autologgers/openai/test_chat_completion_parsers.py @@ -64,7 +64,7 @@ def test_parse_create_arguments__only_messages_presented(): def test_parse_create_result__input_is_openai_object__input_parsed_successfully(): create_result = Fake("create_result") with Scenario() as s: - s.create_result.to_dict() >> { + s.create_result.dict() >> { "choices": "the-choices", "some-key": "some-value", } @@ -78,7 +78,7 @@ def test_parse_create_result__input_is_openai_object__input_parsed_successfully( def test_parse_create_result__input_is_openai_object__input_parsed_successfully__model_key_renamed_to_output_model(): create_result = Fake("create_result") with Scenario() as s: - s.create_result.to_dict() >> { + s.create_result.dict() >> { "choices": "the-choices", "some-key": "some-value", "model": "the-model", From 96c9f03d7b8730a6c3056cb6e12891331616e8a6 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmik Date: Thu, 9 Nov 2023 11:03:38 +0100 Subject: [PATCH 3/8] Update result parsing, add types --- .../openai/chat_completion_parsers.py | 26 +++++++++--------- src/comet_llm/autologgers/openai/metadata.py | 27 +++++++++++++++++++ .../openai/test_chat_completion_parsers.py | 4 +-- 3 files changed, 42 insertions(+), 15 deletions(-) create mode 100644 src/comet_llm/autologgers/openai/metadata.py diff --git a/src/comet_llm/autologgers/openai/chat_completion_parsers.py b/src/comet_llm/autologgers/openai/chat_completion_parsers.py index 513e85480e..be6c64b150 100644 --- a/src/comet_llm/autologgers/openai/chat_completion_parsers.py +++ b/src/comet_llm/autologgers/openai/chat_completion_parsers.py @@ -14,22 +14,22 @@ import inspect import logging - from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Tuple, Union + from . import metadata if TYPE_CHECKING: - from openai.openai_object import OpenAIObject from openai import Stream + from openai.openai_object import OpenAIObject + from openai.types.chat.chat_completion import ChatCompletion Inputs = Dict[str, Any] Outputs = Dict[str, Any] Metadata = Dict[str, Any] -CreateCallResult = Union["OpenAIObject", Iterable["OpenAIObject"]] - LOGGER = logging.getLogger(__file__) + def create_arguments_supported(kwargs: Dict[str, Any]) -> bool: if "messages" not in kwargs: return False @@ -51,23 +51,24 @@ def parse_create_arguments(kwargs: Dict[str, Any]) -> Tuple[Inputs, Metadata]: def parse_create_result( - result: Union["OpenAIObject", Iterable["OpenAIObject"]] # TODO: new object type + result: Union["OpenAIObject", Iterable["OpenAIObject"]] # TODO: new object type ) -> Tuple[Outputs, Metadata]: openai_version = metadata.openai_version() if openai_version is not None and openai_version.startswith("0."): return _deprecated_parse_create_result(result) - + return _parse_create_result(result) + def _deprecated_parse_create_result( - result: Union["OpenAIObject", Iterable["OpenAIObject"]] # TODO: new object type + result: Union["OpenAIObject", Iterable["OpenAIObject"]] # TODO: new object type ) -> Tuple[Outputs, Metadata]: if inspect.isgenerator(result): choices = "Generation is not logged when using stream mode" metadata = {} else: - result_dict = result.to_dict() + result_dict = result.to_dict() # type: ignore choices: List[Dict[str, Any]] = result_dict.pop("choices") # type: ignore metadata = result_dict @@ -78,15 +79,16 @@ def _deprecated_parse_create_result( return outputs, metadata + def _parse_create_result( - result: Union["OpenAIObject", "Stream"] # TODO: new object type + result: Union["ChatCompletion", "Stream"] # TODO: new object type ) -> Tuple[Outputs, Metadata]: - stream_mode = not hasattr(result, "dict") + stream_mode = not hasattr(result, "model_dump") if stream_mode: choices = "Generation is not logged when using stream mode" metadata = {} else: - result_dict = result.dict() + result_dict = result.model_dump() choices: List[Dict[str, Any]] = result_dict.pop("choices") # type: ignore metadata = result_dict @@ -96,5 +98,3 @@ def _parse_create_result( metadata["output_model"] = metadata.pop("model") return outputs, metadata - - \ No newline at end of file diff --git a/src/comet_llm/autologgers/openai/metadata.py b/src/comet_llm/autologgers/openai/metadata.py new file mode 100644 index 0000000000..e8971e413f --- /dev/null +++ b/src/comet_llm/autologgers/openai/metadata.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# ******************************************************* +# ____ _ _ +# / ___|___ _ __ ___ ___| |_ _ __ ___ | | +# | | / _ \| '_ ` _ \ / _ \ __| | '_ ` _ \| | +# | |__| (_) | | | | | | __/ |_ _| | | | | | | +# \____\___/|_| |_| |_|\___|\__(_)_| |_| |_|_| +# +# Sign up for free at https://www.comet.com +# Copyright (C) 2015-2023 Comet ML INC +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this package. +# ******************************************************* + +import functools +from typing import Optional + + +@functools.lru_cache(maxsize=1) +def openai_version() -> Optional[str]: + try: + import openai + + version: str = openai.__version__ + return version + except Exception: + return None diff --git a/tests/unit/autologgers/openai/test_chat_completion_parsers.py b/tests/unit/autologgers/openai/test_chat_completion_parsers.py index 853bca59df..9b7f55427d 100644 --- a/tests/unit/autologgers/openai/test_chat_completion_parsers.py +++ b/tests/unit/autologgers/openai/test_chat_completion_parsers.py @@ -64,7 +64,7 @@ def test_parse_create_arguments__only_messages_presented(): def test_parse_create_result__input_is_openai_object__input_parsed_successfully(): create_result = Fake("create_result") with Scenario() as s: - s.create_result.dict() >> { + s.create_result.model_dump() >> { "choices": "the-choices", "some-key": "some-value", } @@ -78,7 +78,7 @@ def test_parse_create_result__input_is_openai_object__input_parsed_successfully( def test_parse_create_result__input_is_openai_object__input_parsed_successfully__model_key_renamed_to_output_model(): create_result = Fake("create_result") with Scenario() as s: - s.create_result.dict() >> { + s.create_result.model_dump() >> { "choices": "the-choices", "some-key": "some-value", "model": "the-model", From 02a8580acca21b947662b8eed1c1f12704e38cec Mon Sep 17 00:00:00 2001 From: Alexander Kuzmik Date: Thu, 9 Nov 2023 11:06:48 +0100 Subject: [PATCH 4/8] Update types --- .../autologgers/openai/chat_completion_parsers.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/comet_llm/autologgers/openai/chat_completion_parsers.py b/src/comet_llm/autologgers/openai/chat_completion_parsers.py index be6c64b150..d808516fbf 100644 --- a/src/comet_llm/autologgers/openai/chat_completion_parsers.py +++ b/src/comet_llm/autologgers/openai/chat_completion_parsers.py @@ -27,6 +27,10 @@ Outputs = Dict[str, Any] Metadata = Dict[str, Any] +CreateCallResult = Union[ + "ChatCompletion", "Stream", "OpenAIObject", Iterable["OpenAIObject"] +] + LOGGER = logging.getLogger(__file__) @@ -50,9 +54,7 @@ def parse_create_arguments(kwargs: Dict[str, Any]) -> Tuple[Inputs, Metadata]: return inputs, metadata -def parse_create_result( - result: Union["OpenAIObject", Iterable["OpenAIObject"]] # TODO: new object type -) -> Tuple[Outputs, Metadata]: +def parse_create_result(result: CreateCallResult) -> Tuple[Outputs, Metadata]: openai_version = metadata.openai_version() if openai_version is not None and openai_version.startswith("0."): @@ -62,7 +64,7 @@ def parse_create_result( def _deprecated_parse_create_result( - result: Union["OpenAIObject", Iterable["OpenAIObject"]] # TODO: new object type + result: Union["OpenAIObject", Iterable["OpenAIObject"]] ) -> Tuple[Outputs, Metadata]: if inspect.isgenerator(result): choices = "Generation is not logged when using stream mode" @@ -81,7 +83,7 @@ def _deprecated_parse_create_result( def _parse_create_result( - result: Union["ChatCompletion", "Stream"] # TODO: new object type + result: Union["ChatCompletion", "Stream"] ) -> Tuple[Outputs, Metadata]: stream_mode = not hasattr(result, "model_dump") if stream_mode: From 26384edd86cbeb651776a2c13f465f3feb1213cb Mon Sep 17 00:00:00 2001 From: Alexander Kuzmik Date: Thu, 9 Nov 2023 11:28:07 +0100 Subject: [PATCH 5/8] Add deprecation warning --- .../openai/chat_completion_parsers.py | 8 ++++++++ src/comet_llm/autologgers/openai/patcher.py | 18 +++++++++--------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/comet_llm/autologgers/openai/chat_completion_parsers.py b/src/comet_llm/autologgers/openai/chat_completion_parsers.py index d808516fbf..d6107f15a7 100644 --- a/src/comet_llm/autologgers/openai/chat_completion_parsers.py +++ b/src/comet_llm/autologgers/openai/chat_completion_parsers.py @@ -16,8 +16,10 @@ import logging from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Tuple, Union +import comet_llm.logging from . import metadata + if TYPE_CHECKING: from openai import Stream from openai.openai_object import OpenAIObject @@ -58,6 +60,12 @@ def parse_create_result(result: CreateCallResult) -> Tuple[Outputs, Metadata]: openai_version = metadata.openai_version() if openai_version is not None and openai_version.startswith("0."): + comet_llm.logging.log_once_at_level( + LOGGER, + logging.WARNING, + message="You are using old API from openai < 1.0.0, " + "it's support will be deprecated. Please update via `pip install -U openai`" + ) return _deprecated_parse_create_result(result) return _parse_create_result(result) diff --git a/src/comet_llm/autologgers/openai/patcher.py b/src/comet_llm/autologgers/openai/patcher.py index 6cdeb1521e..f3870b3777 100644 --- a/src/comet_llm/autologgers/openai/patcher.py +++ b/src/comet_llm/autologgers/openai/patcher.py @@ -21,15 +21,15 @@ def patch(registry: "registry.Registry") -> None: - # registry.register_before( - # "openai", "ChatCompletion.create", hooks.before_chat_completion_create - # ) - # registry.register_after( - # "openai", "ChatCompletion.create", hooks.after_chat_completion_create - # ) - # registry.register_after_exception( - # "openai", "ChatCompletion.create", hooks.after_exception_chat_completion_create - # ) + registry.register_before( + "openai", "ChatCompletion.create", hooks.before_chat_completion_create + ) + registry.register_after( + "openai", "ChatCompletion.create", hooks.after_chat_completion_create + ) + registry.register_after_exception( + "openai", "ChatCompletion.create", hooks.after_exception_chat_completion_create + ) registry.register_before( "openai.resources.chat.completions", From 0ac9452489a87b4020c428ea30f481aab8a3eb7d Mon Sep 17 00:00:00 2001 From: Alexander Kuzmik Date: Thu, 9 Nov 2023 11:39:01 +0100 Subject: [PATCH 6/8] Fix problem when patcher didn't catch deprecation exception --- src/comet_llm/import_hooks/patcher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/comet_llm/import_hooks/patcher.py b/src/comet_llm/import_hooks/patcher.py index 19cdd44d1e..4b13135d02 100644 --- a/src/comet_llm/import_hooks/patcher.py +++ b/src/comet_llm/import_hooks/patcher.py @@ -30,7 +30,7 @@ def _get_object(module: ModuleType, callable_path: str) -> Any: for part in callable_path: try: current_object = getattr(current_object, part) - except AttributeError: + except Exception: return None return current_object From 6da11d6de6125a9c09e8c69c41d1ed056294df47 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmik Date: Thu, 9 Nov 2023 12:41:48 +0100 Subject: [PATCH 7/8] Remove deprecation warning, make some renamings in parsers, add unit tests for old openai version to a separate module --- .../openai/chat_completion_parsers.py | 14 ++---- .../openai/test_chat_completion_parsers.py | 6 +-- .../test_chat_completion_parsers_openai_v0.py | 50 +++++++++++++++++++ 3 files changed, 57 insertions(+), 13 deletions(-) create mode 100644 tests/unit/autologgers/openai/test_chat_completion_parsers_openai_v0.py diff --git a/src/comet_llm/autologgers/openai/chat_completion_parsers.py b/src/comet_llm/autologgers/openai/chat_completion_parsers.py index d6107f15a7..bdbe9f9057 100644 --- a/src/comet_llm/autologgers/openai/chat_completion_parsers.py +++ b/src/comet_llm/autologgers/openai/chat_completion_parsers.py @@ -60,18 +60,12 @@ def parse_create_result(result: CreateCallResult) -> Tuple[Outputs, Metadata]: openai_version = metadata.openai_version() if openai_version is not None and openai_version.startswith("0."): - comet_llm.logging.log_once_at_level( - LOGGER, - logging.WARNING, - message="You are using old API from openai < 1.0.0, " - "it's support will be deprecated. Please update via `pip install -U openai`" - ) - return _deprecated_parse_create_result(result) + return _v0_x_x__parse_create_result(result) - return _parse_create_result(result) + return _v1_x_x__parse_create_result(result) -def _deprecated_parse_create_result( +def _v0_x_x__parse_create_result( result: Union["OpenAIObject", Iterable["OpenAIObject"]] ) -> Tuple[Outputs, Metadata]: if inspect.isgenerator(result): @@ -90,7 +84,7 @@ def _deprecated_parse_create_result( return outputs, metadata -def _parse_create_result( +def _v1_x_x__parse_create_result( result: Union["ChatCompletion", "Stream"] ) -> Tuple[Outputs, Metadata]: stream_mode = not hasattr(result, "model_dump") diff --git a/tests/unit/autologgers/openai/test_chat_completion_parsers.py b/tests/unit/autologgers/openai/test_chat_completion_parsers.py index 9b7f55427d..5fa7e4e8d9 100644 --- a/tests/unit/autologgers/openai/test_chat_completion_parsers.py +++ b/tests/unit/autologgers/openai/test_chat_completion_parsers.py @@ -61,7 +61,7 @@ def test_parse_create_arguments__only_messages_presented(): ) -def test_parse_create_result__input_is_openai_object__input_parsed_successfully(): +def test_parse_create_result__input_is_ChatCompletion__input_parsed_successfully(): create_result = Fake("create_result") with Scenario() as s: s.create_result.model_dump() >> { @@ -75,7 +75,7 @@ def test_parse_create_result__input_is_openai_object__input_parsed_successfully( assert metadata == {"some-key": "some-value"} -def test_parse_create_result__input_is_openai_object__input_parsed_successfully__model_key_renamed_to_output_model(): +def test_parse_create_result__input_is_ChatCompletion__input_parsed_successfully__model_key_renamed_to_output_model(): create_result = Fake("create_result") with Scenario() as s: s.create_result.model_dump() >> { @@ -90,7 +90,7 @@ def test_parse_create_result__input_is_openai_object__input_parsed_successfully_ assert metadata == {"some-key": "some-value", "output_model": "the-model"} -def test_parse_create_result__input_is_generator_object__input_parsed_with_hardcoded_values_used(): +def test_parse_create_result__input_is_Stream__input_parsed_with_hardcoded_values_used(): create_result = (x for x in []) outputs, metadata = chat_completion_parsers.parse_create_result(create_result) diff --git a/tests/unit/autologgers/openai/test_chat_completion_parsers_openai_v0.py b/tests/unit/autologgers/openai/test_chat_completion_parsers_openai_v0.py new file mode 100644 index 0000000000..9294ca8f64 --- /dev/null +++ b/tests/unit/autologgers/openai/test_chat_completion_parsers_openai_v0.py @@ -0,0 +1,50 @@ +import box +import pytest +from testix import * + +from comet_llm.autologgers.openai import chat_completion_parsers + +@pytest.fixture(autouse=True) +def mock_imports(patch_module): + patch_module(chat_completion_parsers, "metadata") + +def test_parse_create_result__input_is_openai_object__input_parsed_successfully(): + create_result = Fake("create_result") + with Scenario() as s: + s.metadata.openai_version() >> "0.99.99" + s.create_result.to_dict() >> { + "choices": "the-choices", + "some-key": "some-value", + } + + outputs, metadata = chat_completion_parsers.parse_create_result(create_result) + + assert outputs == {"choices": "the-choices"} + assert metadata == {"some-key": "some-value"} + + +def test_parse_create_result__input_is_openai_object__input_parsed_successfully__model_key_renamed_to_output_model(): + create_result = Fake("create_result") + with Scenario() as s: + s.metadata.openai_version() >> "0.99.99" + s.create_result.to_dict() >> { + "choices": "the-choices", + "some-key": "some-value", + "model": "the-model", + } + + outputs, metadata = chat_completion_parsers.parse_create_result(create_result) + + assert outputs == {"choices": "the-choices"} + assert metadata == {"some-key": "some-value", "output_model": "the-model"} + + +def test_parse_create_result__input_is_generator_object__input_parsed_with_hardcoded_values_used(): + create_result = (x for x in []) + + with Scenario() as s: + s.metadata.openai_version() >> "0.99.99" + outputs, metadata = chat_completion_parsers.parse_create_result(create_result) + + assert outputs == {"choices": "Generation is not logged when using stream mode"} + assert metadata == {} From 84c0eb759c2e8f2daa2491df26fd95e21be90be4 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmik Date: Thu, 9 Nov 2023 12:42:49 +0100 Subject: [PATCH 8/8] Fix lint errors --- src/comet_llm/autologgers/openai/chat_completion_parsers.py | 2 +- .../openai/test_chat_completion_parsers_openai_v0.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/comet_llm/autologgers/openai/chat_completion_parsers.py b/src/comet_llm/autologgers/openai/chat_completion_parsers.py index bdbe9f9057..9c233ed577 100644 --- a/src/comet_llm/autologgers/openai/chat_completion_parsers.py +++ b/src/comet_llm/autologgers/openai/chat_completion_parsers.py @@ -17,8 +17,8 @@ from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Tuple, Union import comet_llm.logging -from . import metadata +from . import metadata if TYPE_CHECKING: from openai import Stream diff --git a/tests/unit/autologgers/openai/test_chat_completion_parsers_openai_v0.py b/tests/unit/autologgers/openai/test_chat_completion_parsers_openai_v0.py index 9294ca8f64..ab81c61ac9 100644 --- a/tests/unit/autologgers/openai/test_chat_completion_parsers_openai_v0.py +++ b/tests/unit/autologgers/openai/test_chat_completion_parsers_openai_v0.py @@ -4,6 +4,7 @@ from comet_llm.autologgers.openai import chat_completion_parsers + @pytest.fixture(autouse=True) def mock_imports(patch_module): patch_module(chat_completion_parsers, "metadata")