-
Notifications
You must be signed in to change notification settings - Fork 108
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add apply, aapply functions * Split _iter_streamed_tool_calls from parse_streamed_tool_calls for OpenaiChatModel * Add _RawMessage class * Tidy: reuse tool_calls var across Parallel vs not * Join openai streamed tool call and include in error message * WIP: include messages in error, retry within prompt * WIP: Add TODOs * Switch FunctionResultMessage to use unique_id not FunctionCall * Rename unique_id -> function_call_id * Revert "Rename unique_id -> function_call_id" This reverts commit 5b4ba4d. * Revert "Switch FunctionResultMessage to use unique_id not FunctionCall" This reverts commit 80de9fc. * Add ToolResultMessage, parent of FunctionResultMessage * Add StringNotAllowedError. Update StructuredOutputError * Move retry logic into RetryChatModel * Add max_retries param to chatprompt * Move error handling into _parse_streamed_tool_calls * Handle str content in ToolResultMessage * Explicitly pass ValidationError to StructuredOutputError * Do not show _RawMessage in error msg * Rename StructuredOutputError to ToolSchemaParseError * Tidy by making _make_retry_messages * Update TODOs * Address mypy errors for OpenaiChatModel * Add init to _RawMessage * Remove unused cached_response from OpenaiChatModel.acomplete * Update LitellmChatModel for new error handling * Make AnthropicChatModel parse_streamed_functions private * Move error handling into _parse_streamed_tool_calls for AnthropicChatModel * Implement _join_streamed_response_to_message * Fix: avoid pydantic class name reused error * Add tests for AnthropicChatModel error handling, and fix it * Rename test for ToolSchemaParseError * Add tests for LitellmChatModel error handling * Fix mypy errors * Implement serialization of _RawMessage w/ Anthropic. Fix tool use id * Add tests for RetryChatModel with OpenaiChatModel * Add tests for RetryChatModel with AnthropicChatModel * Add tests for RetryChatModel with LitellmChatModel * Add tests for prompt max_retries param * Add Retrying docs page
- Loading branch information
1 parent
e017ce8
commit c7cb858
Showing
19 changed files
with
891 additions
and
170 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
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,74 @@ | ||
# Retrying | ||
|
||
## LLM-Assisted Retries | ||
|
||
Occasionally the LLM returns an output that cannot be parsed into any of the output types or function calls that were requested. Additionally, the pydantic models you define might have extra validation that is not represented by the type annotations alone. In these cases, LLM-assisted retries can be used to automatically resubmit the output as well as the associated error message back to the LLM, giving it another opportunity with more information to meet the output schema requirements. | ||
|
||
To enable retries, simply set the `max_retries` parameter to a non-zero value in `@prompt` or `@chatprompt`. | ||
|
||
In this example | ||
|
||
- the LLM first returns a country that is not Ireland | ||
- then the pydantic model validation fails with error "Country must be Ireland" | ||
- the original output as well as a message containing the error are resubmitted to the LLM | ||
- the LLM correctly meets the output requirement returning "Ireland" | ||
|
||
```python | ||
from typing import Annotated | ||
|
||
from magentic import prompt | ||
from pydantic import AfterValidator, BaseModel | ||
|
||
|
||
def assert_is_ireland(v: str) -> str: | ||
if v != "Ireland": | ||
raise ValueError("Country must be Ireland") | ||
return v | ||
|
||
|
||
class Country(BaseModel): | ||
name: Annotated[str, AfterValidator(assert_is_ireland)] | ||
capital: str | ||
|
||
|
||
@prompt( | ||
"Return a country", | ||
max_retries=3, | ||
) | ||
def get_country() -> Country: ... | ||
|
||
|
||
get_country() | ||
# 05:13:55.607 Calling prompt-function get_country | ||
# 05:13:55.622 LLM-assisted retries enabled. Max 3 | ||
# 05:13:55.627 Chat Completion with 'gpt-4o' [LLM] | ||
# 05:13:56.309 streaming response from 'gpt-4o' took 0.11s [LLM] | ||
# 05:13:56.310 Retrying Chat Completion. Attempt 1. | ||
# 05:13:56.322 Chat Completion with 'gpt-4o' [LLM] | ||
# 05:13:57.456 streaming response from 'gpt-4o' took 0.00s [LLM] | ||
# | ||
# Country(name='Ireland', capital='Dublin') | ||
``` | ||
|
||
LLM-Assisted retries are intended to address cases where the LLM failed to generate valid output. Errors due to LLM provider rate limiting, internet connectivity issues, or other issues that cannot be solved by reprompting the LLM should be handled using other methods. For example [jd/tenacity](https://github.com/jd/tenacity) or [hynek/stamina](https://github.com/hynek/stamina) to retry a Python function. | ||
|
||
### RetryChatModel | ||
|
||
Under the hood, LLM-assisted retries are implemented using the `RetryChatModel` which wraps any other `ChatModel`, catches exceptions, and resubmits them to the LLM. To implement your own retry handling you can follow the pattern of this class. Please file a [GitHub issue](https://github.com/jackmpcollins/magentic/issues) if you encounter exceptions that should be included in the LLM-assisted retries. | ||
|
||
To use the `RetryChatModel` directly rather than via the `max_retries` parameter, simply pass it as the `model` argument to the decorator. Extending the example above | ||
|
||
```python | ||
from magentic import OpenaiChatModel | ||
from magentic.chat_model.retry_chat_model import RetryChatModel | ||
|
||
|
||
@prompt( | ||
"Return a country", | ||
model=RetryChatModel(OpenaiChatModel("gpt-4o-mini"), max_retries=3), | ||
) | ||
def get_country() -> Country: ... | ||
|
||
|
||
get_country() | ||
``` |
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
Oops, something went wrong.