Skip to content

Commit 415de0a

Browse files
authored
Migrate to UV (#1280)
Migrating from Poetry to UV
1 parent 535cf57 commit 415de0a

20 files changed

+5094
-6263
lines changed

.github/workflows/pyright.yml

+9-25
Original file line numberDiff line numberDiff line change
@@ -21,29 +21,13 @@ jobs:
2121
steps:
2222
- name: Checkout code
2323
uses: actions/checkout@v3
24-
25-
- name: Set up Python
26-
uses: actions/setup-python@v4
27-
with:
28-
python-version: ${{ matrix.python-version }}
29-
30-
- name: Cache Poetry virtualenv
31-
uses: actions/cache@v2
32-
with:
33-
path: ~/.cache/pypoetry/virtualenvs
34-
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
35-
restore-keys: |
36-
${{ runner.os }}-poetry-
37-
38-
- name: Install Poetry
39-
uses: snok/[email protected]
40-
41-
- name: Install dependencies
42-
run: poetry install --with dev,anthropic
43-
44-
- name: Add poetry to PATH
45-
run: echo "$(poetry env info --path)/bin" >> $GITHUB_PATH
46-
47-
- uses: jakebailey/pyright-action@v2
24+
- name: Install uv
25+
uses: astral-sh/setup-uv@v4
4826
with:
49-
version: 1.1.373
27+
enable-cache: true
28+
- name: Set up Python
29+
run: uv python install ${{ matrix.python-version }}
30+
- name: Install the project
31+
run: uv sync --all-extras
32+
- name: Run pyright
33+
run: uv run pyright

.github/workflows/python-publish.yml

+9-14
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,16 @@ jobs:
2121

2222
steps:
2323
- uses: actions/checkout@v2
24-
25-
- name: Set up Python 3.10
26-
uses: actions/setup-python@v4
24+
- name: Install uv
25+
uses: astral-sh/setup-uv@v4
2726
with:
28-
python-version: '3.10'
29-
30-
- name: Install Poetry
31-
uses: snok/[email protected]
32-
env:
33-
ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true'
34-
35-
- name: Get release version
36-
run: echo "RELEASE_VERSION=$(poetry version | awk '{print $2}')" >> $GITHUB_ENV
27+
enable-cache: true
28+
- name: Set up Python
29+
run: uv python install 3.10
30+
- name: Install the project
31+
run: uv sync --all-extras
3732

3833
- name: Build and publish Python package
39-
run: poetry publish --build
34+
run: uv publish
4035
env:
41-
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_TOKEN }}
36+
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}

.github/workflows/ruff.yml

+7-9
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,14 @@ jobs:
2020
steps:
2121
- name: Checkout code
2222
uses: actions/checkout@v3
23-
- name: Environment setup
24-
uses: actions/setup-python@v4
23+
- name: Install uv
24+
uses: astral-sh/setup-uv@v4
2525
with:
26-
python-version: 3.9
27-
cache: "pip"
28-
- name: Install dev dependencies
29-
run: |
30-
python3 -m pip install --upgrade pip setuptools wheel
31-
python3 -m pip install -r requirements.txt
32-
python3 -m pip install -r requirements-doc.txt
26+
enable-cache: true
27+
- name: Set up Python
28+
run: uv python install 3.9
29+
- name: Install the project
30+
run: uv sync --all-extras
3331
- name: Run Continuous Integration Action
3432
uses: astral-sh/ruff-action@v1
3533
- name: Upload Artifacts

.github/workflows/test.yml

+13-24
Original file line numberDiff line numberDiff line change
@@ -15,45 +15,34 @@ jobs:
1515

1616
steps:
1717
- uses: actions/checkout@v2
18-
19-
- name: Set up Python
20-
uses: actions/setup-python@v4
18+
- name: Install uv
19+
uses: astral-sh/setup-uv@v4
2120
with:
22-
python-version: ${{ matrix.python-version }}
23-
24-
- name: Cache Poetry virtualenv
25-
uses: actions/cache@v2
26-
with:
27-
path: ~/.cache/pypoetry/virtualenvs
28-
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
29-
restore-keys: |
30-
${{ runner.os }}-poetry-
31-
32-
- name: Install Poetry
33-
uses: snok/[email protected]
34-
35-
- name: Install dependencies
36-
run: poetry install --with dev,anthropic
37-
21+
enable-cache: true
22+
- name: Set up Python
23+
run: uv python install ${{ matrix.python-version }}
24+
- name: Install the project
25+
run: uv sync --all-extras
3826
- name: Run tests
3927
if: matrix.python-version != '3.11'
40-
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
28+
run: uv run pytest tests/ -k 'not llm and not openai and not gemini and not anthropic and not cohere and not vertexai'
4129
env:
4230
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
4331
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
4432
COHERE_API_KEY: ${{ secrets.COHERE_API_KEY }}
4533

4634
- name: Run Gemini Tests
47-
run: poetry run pytest tests/llm/test_gemini
35+
if: matrix.python-version == '3.11'
36+
run: uv run pytest tests/llm/test_gemini
4837
env:
4938
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
5039

5140
- name: Generate coverage report
5241
if: matrix.python-version == '3.11'
5342
run: |
54-
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"
55-
poetry run coverage report
56-
poetry run coverage html
43+
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"
44+
uv run coverage report
45+
uv run coverage html
5746
env:
5847
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
5948
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

.github/workflows/test_docs.yml

+4-12
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,10 @@ jobs:
2828
with:
2929
python-version: ${{ matrix.python-version }}
3030
cache: "poetry"
31-
32-
- name: Cache Poetry virtualenv
33-
uses: actions/cache@v2
34-
with:
35-
path: ~/.cache/pypoetry/virtualenvs
36-
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
37-
restore-keys: |
38-
${{ runner.os }}-poetry-
39-
40-
- name: Install dependencies
41-
run: poetry install --with dev,docs,test-docs,anthropic,google-generativeai
42-
31+
- name: Install uv
32+
uses: astral-sh/setup-uv@v4
33+
- name: Install the project
34+
run: uv sync --all-extras
4335
- name: Run tests
4436
run: poetry run pytest tests/llm/test_openai/docs
4537
env:

README.md

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Instructor, The Most Popular Library for Simple Structured Outputs
22

3-
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!
3+
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!
44

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

132132
print(f"Name: {user_info.name}, Age: {user_info.age}")
133133
#> Name: John, Age: 20
134-
```
134+
```
135135

136136
This example demonstrates:
137+
137138
1. A pre-execution hook that logs all kwargs passed to the function.
138139
2. An exception hook that logs any exceptions that occur during execution.
139140

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

514515
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.
515516

517+
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.
518+
519+
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
520+
521+
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
522+
523+
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.
524+
516525
## CLI
517526

518527
We also provide some added CLI functionality for easy convenience:

docs/concepts/prompt_caching.md

+35-27
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,16 @@ This optimization is especially useful for applications making multiple API call
1717

1818
Prompt Caching is enabled for the following models:
1919

20-
* gpt-4o
21-
* gpt-4o-mini
22-
* o1-preview
23-
* o1-mini
20+
- gpt-4o
21+
- gpt-4o-mini
22+
- o1-preview
23+
- o1-mini
2424

2525
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.
2626

27-
2827
## Prompt Caching in Anthropic
2928

30-
The `anthropic.beta.prompt_caching.messages.create` method enables you to:
31-
32-
1. Cache specific prompt portions
33-
2. Reuse cached content in subsequent calls
34-
3. Reduce processed data per request
35-
36-
By implementing prompt caching, you can potentially enhance efficiency and reduce costs, especially when dealing with large, shared contexts across multiple API interactions.
29+
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.
3730

3831
??? note "Source Text"
3932

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

184177
```python
185-
from instructor import Instructor, Mode, patch
178+
import instructor
186179
from anthropic import Anthropic
187180
from pydantic import BaseModel
188181

189-
client = Instructor( # (1)!
190-
client=Anthropic(),
191-
create=patch(
192-
create=Anthropic().beta.prompt_caching.messages.create,
193-
mode=Mode.ANTHROPIC_TOOLS,
194-
),
195-
mode=Mode.ANTHROPIC_TOOLS,
196-
)
182+
client = instructor.from_anthropic(Anthropic())
197183

198184

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

207-
resp = client.chat.completions.create(
208-
model="claude-3-haiku-20240307",
193+
resp, completion = client.chat.completions.create_with_completion(
194+
model="claude-3-5-sonnet-20240620",
209195
messages=[
210196
{
211197
"role": "user",
212198
"content": [
213199
{
214200
"type": "text",
215201
"text": "<book>" + book + "</book>",
216-
"cache_control": {"type": "ephemeral"}, # (2)!
202+
"cache_control": {"type": "ephemeral"}, #(1)!
217203
},
218204
{
219205
"type": "text",
@@ -225,11 +211,33 @@ resp = client.chat.completions.create(
225211
response_model=Character,
226212
max_tokens=1000,
227213
)
228-
```
229214

230-
1. Since the feature is still in beta, we need to manually pass in the function that we're looking to patch.
215+
print(completion)
216+
# Message(
217+
# id='msg_01QcqjktYc1PXL8nk7y5hkMV',
218+
# content=[
219+
# ToolUseBlock(
220+
# id='toolu_019wABRzQxtSbXeuuRwvJo15',
221+
# input={
222+
# 'name': 'Jane Austen',
223+
# '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
224+
# several classic novels including "Pride and Prejudice," "Emma," "Sense and Sensibility," and "Mansfield Park." Austen\'s writing is characterized by its subtlety, delicate touch,
225+
# 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.'
226+
# },
227+
# name='Character',
228+
# type='tool_use'
229+
# )
230+
# ],
231+
# model='claude-3-5-sonnet-20240620',
232+
# role='assistant',
233+
# stop_reason='tool_use',
234+
# stop_sequence=None,
235+
# type='message',
236+
# usage=Usage(cache_creation_input_tokens=2777, cache_read_input_tokens=0, input_tokens=30, output_tokens=161)
237+
# )
238+
```
231239

232-
2. Anthropic requires that you explicitly pass in the `cache_control` parameter to indicate that you want to cache the content.
240+
1. Anthropic requires that you explicitly pass in the `cache_control` parameter to indicate that you want to cache the content.
233241

234242
!!! Warning "Caching Considerations"
235243

instructor/client.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ def __init__(
373373
self.provider = provider
374374
self.hooks = hooks or Hooks()
375375

376-
async def create(
376+
async def create( # type: ignore[override]
377377
self,
378378
response_model: type[T] | None,
379379
messages: list[ChatCompletionMessageParam],
@@ -395,7 +395,7 @@ async def create(
395395
**kwargs,
396396
)
397397

398-
async def create_partial(
398+
async def create_partial( # type: ignore[override]
399399
self,
400400
response_model: type[T],
401401
messages: list[ChatCompletionMessageParam],
@@ -419,7 +419,7 @@ async def create_partial(
419419
):
420420
yield item
421421

422-
async def create_iterable(
422+
async def create_iterable( # type: ignore[override]
423423
self,
424424
messages: list[ChatCompletionMessageParam],
425425
response_model: type[T],
@@ -443,7 +443,7 @@ async def create_iterable(
443443
):
444444
yield item
445445

446-
async def create_with_completion(
446+
async def create_with_completion( # type: ignore[override]
447447
self,
448448
messages: list[ChatCompletionMessageParam],
449449
response_model: type[T],

instructor/client_anthropic.py

+1-11
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ def from_anthropic(
1212
anthropic.Anthropic | anthropic.AnthropicBedrock | anthropic.AnthropicVertex
1313
),
1414
mode: instructor.Mode = instructor.Mode.ANTHROPIC_TOOLS,
15-
enable_prompt_caching: bool = False,
1615
beta: bool = False,
1716
**kwargs: Any,
1817
) -> instructor.Instructor: ...
@@ -26,7 +25,6 @@ def from_anthropic(
2625
| anthropic.AsyncAnthropicVertex
2726
),
2827
mode: instructor.Mode = instructor.Mode.ANTHROPIC_TOOLS,
29-
enable_prompt_caching: bool = False,
3028
beta: bool = False,
3129
**kwargs: Any,
3230
) -> instructor.AsyncInstructor: ...
@@ -42,7 +40,6 @@ def from_anthropic(
4240
| anthropic.AnthropicVertex
4341
),
4442
mode: instructor.Mode = instructor.Mode.ANTHROPIC_TOOLS,
45-
enable_prompt_caching: bool = False,
4643
beta: bool = False,
4744
**kwargs: Any,
4845
) -> instructor.Instructor | instructor.AsyncInstructor:
@@ -82,14 +79,7 @@ def from_anthropic(
8279
),
8380
), "Client must be an instance of {anthropic.Anthropic, anthropic.AsyncAnthropic, anthropic.AnthropicBedrock, anthropic.AsyncAnthropicBedrock, anthropic.AnthropicVertex, anthropic.AsyncAnthropicVertex}"
8481

85-
if enable_prompt_caching:
86-
if isinstance(client, (anthropic.Anthropic, anthropic.AsyncAnthropic)):
87-
create = client.beta.prompt_caching.messages.create
88-
else:
89-
raise TypeError(
90-
"Client must be an instance of {anthropic.Anthropic, anthropic.AsyncAnthropic} to enable prompt caching"
91-
)
92-
elif beta:
82+
if beta:
9383
create = client.beta.messages.create
9484
else:
9585
create = client.messages.create

0 commit comments

Comments
 (0)