Skip to content

Commit

Permalink
Merge branch 'main' into logfire
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanleomk authored May 1, 2024
2 parents be14f5b + ab5b48d commit 4dce2c3
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 7 deletions.
14 changes: 8 additions & 6 deletions instructor/function_calls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,22 @@

from docstring_parser import parse
from openai.types.chat import ChatCompletion
from pydantic import BaseModel, Field, TypeAdapter, create_model # type: ignore - remove once Pydantic is updated
from pydantic import BaseModel, Field, TypeAdapter, ConfigDict, create_model # type: ignore - remove once Pydantic is updated
from instructor.exceptions import IncompleteOutputException
from instructor.mode import Mode
from instructor.utils import extract_json_from_codeblock
from instructor.utils import extract_json_from_codeblock, classproperty


T = TypeVar("T")

logger = logging.getLogger("instructor")


class OpenAISchema(BaseModel):
@classmethod
@property
# Ignore classproperty, since Pydantic doesn't understand it like it would a normal property.
model_config = ConfigDict(ignored_types=(classproperty,))

@classproperty
def openai_schema(cls) -> dict[str, Any]:
"""
Return the schema in the format of OpenAI's schema as jsonschema
Expand Down Expand Up @@ -58,8 +61,7 @@ def openai_schema(cls) -> dict[str, Any]:
"parameters": parameters,
}

@classmethod
@property
@classproperty
def anthropic_schema(cls) -> dict[str, Any]:
return {
"name": cls.openai_schema["name"],
Expand Down
29 changes: 29 additions & 0 deletions instructor/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
import inspect
import json
import logging
from typing import (
Callable,
Generic,
Protocol,
TypeVar,
)
from collections.abc import Generator, Iterable, AsyncGenerator
from typing import Callable, Protocol, TypeVar
from collections.abc import Generator, Iterable, AsyncGenerator
from openai.types.completion_usage import CompletionUsage
Expand All @@ -16,6 +23,7 @@
)

logger = logging.getLogger("instructor")
R_co = TypeVar("R_co", covariant=True)
T_Model = TypeVar("T_Model", bound="Response")

from enum import Enum
Expand Down Expand Up @@ -180,3 +188,24 @@ def merge_consecutive_messages(messages: list[dict[str, Any]]) -> list[dict[str,
)

return new_messages


class classproperty(Generic[R_co]):
"""Descriptor for class-level properties.
Examples:
>>> from instructor.utils import classproperty
>>> class MyClass:
... @classproperty
... def my_property(cls):
... return cls
>>> assert MyClass.my_property
"""

def __init__(self, method: Callable[[Any], R_co]) -> None:
self.cproperty = method

def __get__(self, instance: object, cls: type[Any]) -> R_co:
return self.cproperty(cls)
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,3 @@ typeCheckingMode = "strict"
# Allow "redundant" runtime type-checking.
reportUnnecessaryIsInstance = "none"
reportUnnecessaryTypeIgnoreComment = "error"
reportDeprecated = "warning"
21 changes: 21 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
import pytest
from instructor.utils import (
classproperty,
extract_json_from_codeblock,
extract_json_from_stream,
extract_json_from_stream_async,
Expand Down Expand Up @@ -170,3 +171,23 @@ def test_merge_consecutive_messages_single():
{"role": "user", "content": [{"type": "text", "text": "Hello"}]},
{"role": "assistant", "content": [{"type": "text", "text": "Hello"}]},
]


def test_classproperty():
"""Test custom `classproperty` descriptor."""

class MyClass:
@classproperty
def my_property(cls):
return cls

assert MyClass.my_property is MyClass

class MyClass:
clvar = 1

@classproperty
def my_property(cls):
return cls.clvar

assert MyClass.my_property == 1

0 comments on commit 4dce2c3

Please sign in to comment.