Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to UV #1280

Merged
merged 23 commits into from
Dec 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 9 additions & 25 deletions .github/workflows/pyright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,13 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Cache Poetry virtualenv
uses: actions/cache@v2
with:
path: ~/.cache/pypoetry/virtualenvs
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
restore-keys: |
${{ runner.os }}-poetry-

- name: Install Poetry
uses: snok/install-poetry@v1.3.1

- name: Install dependencies
run: poetry install --with dev,anthropic

- name: Add poetry to PATH
run: echo "$(poetry env info --path)/bin" >> $GITHUB_PATH

- uses: jakebailey/pyright-action@v2
- name: Install uv
uses: astral-sh/setup-uv@v4
with:
version: 1.1.373
enable-cache: true
- name: Set up Python
run: uv python install ${{ matrix.python-version }}
- name: Install the project
run: uv sync --all-extras
- name: Run pyright
run: uv run pyright
23 changes: 9 additions & 14 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,16 @@ jobs:

steps:
- uses: actions/checkout@v2

- name: Set up Python 3.10
uses: actions/setup-python@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
with:
python-version: '3.10'

- name: Install Poetry
uses: snok/install-poetry@v1.3.1
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true'

- name: Get release version
run: echo "RELEASE_VERSION=$(poetry version | awk '{print $2}')" >> $GITHUB_ENV
enable-cache: true
- name: Set up Python
run: uv python install 3.10
- name: Install the project
run: uv sync --all-extras

- name: Build and publish Python package
run: poetry publish --build
run: uv publish
env:
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_TOKEN }}
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
16 changes: 7 additions & 9 deletions .github/workflows/ruff.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,14 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Environment setup
uses: actions/setup-python@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
with:
python-version: 3.9
cache: "pip"
- name: Install dev dependencies
run: |
python3 -m pip install --upgrade pip setuptools wheel
python3 -m pip install -r requirements.txt
python3 -m pip install -r requirements-doc.txt
enable-cache: true
- name: Set up Python
run: uv python install 3.9
- name: Install the project
run: uv sync --all-extras
- name: Run Continuous Integration Action
uses: astral-sh/ruff-action@v1
- name: Upload Artifacts
Expand Down
37 changes: 13 additions & 24 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,45 +15,34 @@ jobs:

steps:
- uses: actions/checkout@v2

- name: Set up Python
uses: actions/setup-python@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
with:
python-version: ${{ matrix.python-version }}

- name: Cache Poetry virtualenv
uses: actions/cache@v2
with:
path: ~/.cache/pypoetry/virtualenvs
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
restore-keys: |
${{ runner.os }}-poetry-

- name: Install Poetry
uses: snok/install-poetry@v1.3.1

- name: Install dependencies
run: poetry install --with dev,anthropic

enable-cache: true
- name: Set up Python
run: uv python install ${{ matrix.python-version }}
- name: Install the project
run: uv sync --all-extras
- name: Run tests
if: matrix.python-version != '3.11'
run: poetry run pytest tests/ -k 'not llm and not openai and not gemini and not anthropic and not cohere and not vertexai' && poetry run pytest tests/llm/test_cohere
run: uv run pytest tests/ -k 'not llm and not openai and not gemini and not anthropic and not cohere and not vertexai'
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
COHERE_API_KEY: ${{ secrets.COHERE_API_KEY }}

- name: Run Gemini Tests
run: poetry run pytest tests/llm/test_gemini
if: matrix.python-version == '3.11'
run: uv run pytest tests/llm/test_gemini
env:
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}

- name: Generate coverage report
if: matrix.python-version == '3.11'
run: |
poetry run coverage run -m pytest tests/ -k "not docs and not anthropic and not gemini and not cohere and not vertexai and not fireworks"
poetry run coverage report
poetry run coverage html
uv run coverage run -m pytest tests/ -k "not docs and not anthropic and not gemini and not cohere and not vertexai and not fireworks"
uv run coverage report
uv run coverage html
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
16 changes: 4 additions & 12 deletions .github/workflows/test_docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,10 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
cache: "poetry"

- name: Cache Poetry virtualenv
uses: actions/cache@v2
with:
path: ~/.cache/pypoetry/virtualenvs
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
restore-keys: |
${{ runner.os }}-poetry-

- name: Install dependencies
run: poetry install --with dev,docs,test-docs,anthropic,google-generativeai

- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Install the project
run: uv sync --all-extras
- name: Run tests
run: poetry run pytest tests/llm/test_openai/docs
env:
Expand Down
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Instructor, The Most Popular Library for Simple Structured Outputs

Instructor is the most popular Python library for working with structured outputs from large language models (LLMs), boasting over 600,000 monthly downloads. Built on top of Pydantic, it provides a simple, transparent, and user-friendly API to manage validation, retries, and streaming responses. Get ready to supercharge your LLM workflows with the community's top choice!
Instructor is the most popular Python library for working with structured outputs from large language models (LLMs), boasting over 1 million monthly downloads. Built on top of Pydantic, it provides a simple, transparent, and user-friendly API to manage validation, retries, and streaming responses. Get ready to supercharge your LLM workflows with the community's top choice!

[![Twitter Follow](https://img.shields.io/twitter/follow/jxnlco?style=social)](https://twitter.com/jxnlco)
[![Discord](https://img.shields.io/discord/1192334452110659664?label=discord)](https://discord.gg/bD9YE9JArw)
Expand Down Expand Up @@ -131,9 +131,10 @@ user_info = client.chat.completions.create(

print(f"Name: {user_info.name}, Age: {user_info.age}")
#> Name: John, Age: 20
```
```

This example demonstrates:

1. A pre-execution hook that logs all kwargs passed to the function.
2. An exception hook that logs any exceptions that occur during execution.

Expand Down Expand Up @@ -513,6 +514,14 @@ We invite you to contribute to evals in `pytest` as a way to monitor the quality

If you want to help, checkout some of the issues marked as `good-first-issue` or `help-wanted` found [here](https://github.com/jxnl/instructor/labels/good%20first%20issue). They could be anything from code improvements, a guest blog post, or a new cookbook.

Here's a quick list of commands that you can run to get started. We're using `uv` to manage our dependencies so make sure you have that installed.

1. `uv sync --all-extras --group <dependency groups you'd like to install>`: This should install all the dependencies for the project using `uv`, make sure to install the specific dependencies that you'd like to install

2. `uv run pytest` : This runs the tests in `pytest`. If you're pushing up a new PR, make sure that you've written some tests and that they're passing locally for you

We use `ruff` and `pyright` for linting and type checking so make sure those are passing when you push up a PR. You can check pyright by running `uv run pyright` and ruff with `uv run ruff check` locally.

## CLI

We also provide some added CLI functionality for easy convenience:
Expand Down
62 changes: 35 additions & 27 deletions docs/concepts/prompt_caching.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,16 @@ This optimization is especially useful for applications making multiple API call

Prompt Caching is enabled for the following models:

* gpt-4o
* gpt-4o-mini
* o1-preview
* o1-mini
- gpt-4o
- gpt-4o-mini
- o1-preview
- o1-mini

Caching is based on prefix matching, so if you're using a system prompt that contains a common set of instructions, you're likely to see a cache hit as long as you move all variable parts of the prompt to the end of the message when possible.


## Prompt Caching in Anthropic

The `anthropic.beta.prompt_caching.messages.create` method enables you to:

1. Cache specific prompt portions
2. Reuse cached content in subsequent calls
3. Reduce processed data per request

By implementing prompt caching, you can potentially enhance efficiency and reduce costs, especially when dealing with large, shared contexts across multiple API interactions.
Prompt Caching is now generally avaliable for Anthropic. This enables you to cache specific prompt portions, reuse cached content in subsequent calls, and reduce processed data per request.

??? note "Source Text"

Expand Down Expand Up @@ -182,18 +175,11 @@ By implementing prompt caching, you can potentially enhance efficiency and reduc
```

```python
from instructor import Instructor, Mode, patch
import instructor
from anthropic import Anthropic
from pydantic import BaseModel

client = Instructor( # (1)!
client=Anthropic(),
create=patch(
create=Anthropic().beta.prompt_caching.messages.create,
mode=Mode.ANTHROPIC_TOOLS,
),
mode=Mode.ANTHROPIC_TOOLS,
)
client = instructor.from_anthropic(Anthropic())


class Character(BaseModel):
Expand All @@ -204,16 +190,16 @@ class Character(BaseModel):
with open("./book.txt") as f:
book = f.read()

resp = client.chat.completions.create(
model="claude-3-haiku-20240307",
resp, completion = client.chat.completions.create_with_completion(
model="claude-3-5-sonnet-20240620",
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": "<book>" + book + "</book>",
"cache_control": {"type": "ephemeral"}, # (2)!
"cache_control": {"type": "ephemeral"}, #(1)!
},
{
"type": "text",
Expand All @@ -225,11 +211,33 @@ resp = client.chat.completions.create(
response_model=Character,
max_tokens=1000,
)
```

1. Since the feature is still in beta, we need to manually pass in the function that we're looking to patch.
print(completion)
# Message(
# id='msg_01QcqjktYc1PXL8nk7y5hkMV',
# content=[
# ToolUseBlock(
# id='toolu_019wABRzQxtSbXeuuRwvJo15',
# input={
# 'name': 'Jane Austen',
# 'description': 'A renowned English novelist of the early 19th century, known for her wit, humor, and keen observations of human nature. She is the author of
# several classic novels including "Pride and Prejudice," "Emma," "Sense and Sensibility," and "Mansfield Park." Austen\'s writing is characterized by its subtlety, delicate touch,
# and ability to create memorable characters. Her work often involves social commentary and explores themes of love, marriage, and societal expectations in Regency-era England.'
# },
# name='Character',
# type='tool_use'
# )
# ],
# model='claude-3-5-sonnet-20240620',
# role='assistant',
# stop_reason='tool_use',
# stop_sequence=None,
# type='message',
# usage=Usage(cache_creation_input_tokens=2777, cache_read_input_tokens=0, input_tokens=30, output_tokens=161)
# )
```

2. Anthropic requires that you explicitly pass in the `cache_control` parameter to indicate that you want to cache the content.
1. Anthropic requires that you explicitly pass in the `cache_control` parameter to indicate that you want to cache the content.

!!! Warning "Caching Considerations"

Expand Down
8 changes: 4 additions & 4 deletions instructor/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ def __init__(
self.provider = provider
self.hooks = hooks or Hooks()

async def create(
async def create( # type: ignore[override]
self,
response_model: type[T] | None,
messages: list[ChatCompletionMessageParam],
Expand All @@ -395,7 +395,7 @@ async def create(
**kwargs,
)

async def create_partial(
async def create_partial( # type: ignore[override]
self,
response_model: type[T],
messages: list[ChatCompletionMessageParam],
Expand All @@ -419,7 +419,7 @@ async def create_partial(
):
yield item

async def create_iterable(
async def create_iterable( # type: ignore[override]
self,
messages: list[ChatCompletionMessageParam],
response_model: type[T],
Expand All @@ -443,7 +443,7 @@ async def create_iterable(
):
yield item

async def create_with_completion(
async def create_with_completion( # type: ignore[override]
self,
messages: list[ChatCompletionMessageParam],
response_model: type[T],
Expand Down
12 changes: 1 addition & 11 deletions instructor/client_anthropic.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ def from_anthropic(
anthropic.Anthropic | anthropic.AnthropicBedrock | anthropic.AnthropicVertex
),
mode: instructor.Mode = instructor.Mode.ANTHROPIC_TOOLS,
enable_prompt_caching: bool = False,
beta: bool = False,
**kwargs: Any,
) -> instructor.Instructor: ...
Expand All @@ -26,7 +25,6 @@ def from_anthropic(
| anthropic.AsyncAnthropicVertex
),
mode: instructor.Mode = instructor.Mode.ANTHROPIC_TOOLS,
enable_prompt_caching: bool = False,
beta: bool = False,
**kwargs: Any,
) -> instructor.AsyncInstructor: ...
Expand All @@ -42,7 +40,6 @@ def from_anthropic(
| anthropic.AnthropicVertex
),
mode: instructor.Mode = instructor.Mode.ANTHROPIC_TOOLS,
enable_prompt_caching: bool = False,
beta: bool = False,
**kwargs: Any,
) -> instructor.Instructor | instructor.AsyncInstructor:
Expand Down Expand Up @@ -82,14 +79,7 @@ def from_anthropic(
),
), "Client must be an instance of {anthropic.Anthropic, anthropic.AsyncAnthropic, anthropic.AnthropicBedrock, anthropic.AsyncAnthropicBedrock, anthropic.AnthropicVertex, anthropic.AsyncAnthropicVertex}"

if enable_prompt_caching:
if isinstance(client, (anthropic.Anthropic, anthropic.AsyncAnthropic)):
create = client.beta.prompt_caching.messages.create
else:
raise TypeError(
"Client must be an instance of {anthropic.Anthropic, anthropic.AsyncAnthropic} to enable prompt caching"
)
elif beta:
if beta:
create = client.beta.messages.create
else:
create = client.messages.create
Expand Down
Loading
Loading