-
-
Notifications
You must be signed in to change notification settings - Fork 613
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
256 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Handling Errors Within Function Calls | ||
|
||
You can create a wrapper class to hold either the result of an operation or an error message. This allows you to remain within a function call even if an error occurs, facilitating better error handling without breaking the code flow. | ||
|
||
```python | ||
class UserDetail(BaseModel): | ||
age: int | ||
name: str | ||
role: Optional[str] = Field(default=None) | ||
|
||
class MaybeUser(BaseModel): | ||
result: Optional[UserDetail] = Field(default=None) | ||
error: bool = Field(default=False) | ||
message: Optional[str] | ||
|
||
def __bool__(self): | ||
return self.result is not None | ||
``` | ||
|
||
With the `MaybeUser` class, you can either receive a `UserDetail` object in result or get an error message in message. | ||
|
||
## Simplification with the Maybe Pattern | ||
|
||
You can further simplify this using instructor to create the `Maybe` pattern. | ||
|
||
```python | ||
import instructor | ||
|
||
MaybeUser = instructor.Maybe(UserDetail) | ||
``` | ||
|
||
This allows you to quickly create a Maybe type for any class, streamlining the process. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import instructor | ||
import openai | ||
from pydantic import BaseModel, Field | ||
from typing import Optional, Type | ||
|
||
instructor.patch() | ||
|
||
|
||
class UserDetail(BaseModel): | ||
age: int | ||
name: str | ||
role: Optional[str] = Field(default=None) | ||
|
||
|
||
MaybeUser = instructor.Maybe(UserDetail) | ||
|
||
|
||
def get_user_detail(string) -> MaybeUser: # type: ignore | ||
return openai.ChatCompletion.create( | ||
model="gpt-3.5-turbo-0613", | ||
response_model=MaybeUser, | ||
messages=[ | ||
{ | ||
"role": "user", | ||
"content": f"Get user details for {string}", | ||
}, | ||
], | ||
) # type: ignore | ||
|
||
|
||
user = get_user_detail("Jason is 25 years old") | ||
print(user.model_dump_json(indent=2)) | ||
""" | ||
{ | ||
"user": { | ||
"age": 25, | ||
"name": "Jason", | ||
"role": null | ||
}, | ||
"error": false, | ||
"message": null | ||
} | ||
""" | ||
|
||
user = get_user_detail("Jason is a 25 years old scientist") | ||
print(user.model_dump_json(indent=2)) | ||
""" | ||
{ | ||
"user": { | ||
"age": 25, | ||
"name": "Jason", | ||
"role": "scientist" | ||
}, | ||
"error": false, | ||
"message": null | ||
} | ||
""" | ||
|
||
# ! notice that the string should not contain anything | ||
# ! but a user and age was still extracted ?! | ||
user = get_user_detail("User not found") | ||
print(user.model_dump_json(indent=2)) | ||
""" | ||
{ | ||
"user": null, | ||
"error": true, | ||
"message": "User not found" | ||
} | ||
""" | ||
|
||
# ! due to the __bool__ method, you can use the MaybeUser object as a boolean | ||
|
||
if not user: | ||
print("Detected error") | ||
""" | ||
Detected error | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import instructor | ||
import openai | ||
from pydantic import BaseModel, Field | ||
from typing import Optional | ||
|
||
instructor.patch() | ||
|
||
|
||
class UserDetail(BaseModel): | ||
age: int | ||
name: str | ||
role: Optional[str] = Field(default=None) | ||
|
||
|
||
def get_user_detail(string) -> UserDetail: | ||
return openai.ChatCompletion.create( | ||
model="gpt-3.5-turbo-0613", | ||
response_model=UserDetail, | ||
messages=[ | ||
{ | ||
"role": "user", | ||
"content": f"Get user details for {string}", | ||
}, | ||
], | ||
) # type: ignore | ||
|
||
|
||
user = get_user_detail("Jason is 25 years old") | ||
print(user.model_dump_json(indent=2)) | ||
""" | ||
{ | ||
"age": 25, | ||
"name": "Jason", | ||
"role": null | ||
} | ||
""" | ||
|
||
user = get_user_detail("Jason is a 25 years old scientist") | ||
print(user.model_dump_json(indent=2)) | ||
""" | ||
{ | ||
"age": 25, | ||
"name": "Jason", | ||
"role": "scientist" | ||
} | ||
""" | ||
|
||
# ! notice that the string should not contain anything | ||
# ! but a user and age was still extracted ?! | ||
user = get_user_detail("User not found") | ||
print(user.model_dump_json(indent=2)) | ||
""" | ||
{ | ||
"age": 25, | ||
"name": "John Doe", | ||
"role": "null" | ||
} | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,12 @@ | ||
from .function_calls import OpenAISchema, openai_function, openai_schema | ||
from .dsl.multitask import MultiTask | ||
from .dsl import MultiTask, Maybe | ||
from .patch import patch | ||
|
||
__all__ = [ | ||
"OpenAISchema", | ||
"openai_function", | ||
"MultiTask", | ||
"Maybe", | ||
"openai_schema", | ||
"patch", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
from .completion import ChatCompletion | ||
from .messages import * | ||
from .multitask import MultiTask | ||
from .maybe import Maybe | ||
|
||
__all__ = ["ChatCompletion", "MultiTask", "messages"] | ||
__all__ = ["ChatCompletion", "MultiTask", "messages", "Maybe"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
from pydantic import BaseModel, Field, create_model | ||
from typing import Type, Optional | ||
|
||
|
||
class MaybeBase(BaseModel): | ||
result: Optional[BaseModel] | ||
error: bool = Field(default=False) | ||
message: Optional[str] | ||
|
||
def __bool__(self): | ||
return self.result is not None # type: ignore | ||
|
||
|
||
def Maybe(model: Type[BaseModel]) -> MaybeBase: | ||
""" | ||
Create a Maybe model for a given Pydantic model. | ||
Parameters: | ||
model (Type[BaseModel]): The Pydantic model to wrap with Maybe. | ||
Returns: | ||
MaybeModel (Type[BaseModel]): A new Pydantic model that includes fields for `result`, `error`, and `message`. | ||
""" | ||
|
||
class MaybeBase(BaseModel): | ||
def __bool__(self): | ||
return self.result is not None # type: ignore | ||
|
||
fields = { | ||
"result": ( | ||
Optional[model], | ||
Field( | ||
default=None, | ||
description="Correctly extracted result from the model, if any, otherwise None", | ||
), | ||
), | ||
"error": (bool, Field(default=False)), | ||
"message": ( | ||
Optional[str], | ||
Field( | ||
default=None, | ||
description="Error message if no result was found, should be short and concise", | ||
), | ||
), | ||
} | ||
|
||
MaybeModel = create_model(f"Maybe{model.__name__}", __base__=MaybeBase, **fields) | ||
|
||
return MaybeModel |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters