From bc32f6c581de84217f180befffc955c0e785d202 Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Thu, 24 Oct 2024 06:07:30 -0400 Subject: [PATCH 1/8] feat: add blog post and example for LLM-based reranker (#1115) Co-authored-by: Ivan Leo --- docs/blog/posts/llm-as-reranker.md | 187 +++++++++++++++++++++++++++++ examples/reranker/run.py | 121 +++++++++++++++++++ 2 files changed, 308 insertions(+) create mode 100644 docs/blog/posts/llm-as-reranker.md create mode 100644 examples/reranker/run.py diff --git a/docs/blog/posts/llm-as-reranker.md b/docs/blog/posts/llm-as-reranker.md new file mode 100644 index 000000000..823f84034 --- /dev/null +++ b/docs/blog/posts/llm-as-reranker.md @@ -0,0 +1,187 @@ +--- +authors: +- jxnl +categories: +- LLM +- Pydantic +comments: true +date: 2024-10-23 +description: Learn how to use Instructor and Pydantic to create an LLM-based reranker for improving search results relevance. +draft: false +tags: +- LLM +- Pydantic +- Instructor +- Search Relevance +- Reranking +--- + +# Building an LLM-based Reranker for your RAG pipeline + +Are you struggling with irrelevant search results in your Retrieval-Augmented Generation (RAG) pipeline? + +Imagine having a powerful tool that can intelligently reassess and reorder your search results, significantly improving their relevance to user queries. + +In this blog post, we'll show you how to create an LLM-based reranker using Instructor and Pydantic. This approach will: + +- Enhance the accuracy of your search results +- Leverage the power of large language models (LLMs) +- Utilize structured outputs for precise information retrieval + +By the end of this tutorial, you'll be able to implement a llm reranker to label your synthetic data for fine-tuning a traditional reranker, or to build out an evaluation pipeline for your RAG system. Let's dive in! + +## Setting Up the Environment + +First, let's set up our environment with the necessary imports: + +```python +import instructor +from openai import OpenAI +from pydantic import BaseModel, Field, field_validator + +client = instructor.from_openai(OpenAI()) +``` + +We're using the `instructor` library, which integrates seamlessly with OpenAI's API and Pydantic for structured outputs. + +## Defining the Reranking Models + +We'll use Pydantic to define our `Label` and `RerankedResults` models that structure the output of our LLM: + +Notice that not only do I reference the chunk_id in the label class, I also asked a language model to use chain of thought. This is very useful for using models like 4o Mini or Claude, but not necessarily if we plan to use the `o1-mini` and `o1-preview` models. + +```python +class Label(BaseModel): + chunk_id: int = Field(description="The unique identifier of the text chunk") + chain_of_thought: str = Field(description="The reasoning process used to evaluate the relevance") + relevancy: int = Field( + description="Relevancy score from 0 to 10, where 10 is most relevant", + ge=0, + le=10, + ) + + +class RerankedResults(BaseModel): + labels: list[Label] = Field(description="List of labeled and ranked chunks") + + @field_validator("labels") + @classmethod + def model_validate(cls, v: list[Label]) -> list[Label]: + return sorted(v, key=lambda x: x.relevancy, reverse=True) +``` + +These models ensure that our LLM's output is structured and includes a list of labeled chunks with their relevancy scores. The `RerankedResults` model includes a validator that automatically sorts the labels by relevancy in descending order. + +## Creating the Reranker Function + +Next, we'll create a function that uses our LLM to rerank a list of text chunks based on their relevance to a query: + +```python +def rerank_results(query: str, chunks: list[dict]) -> RerankedResults: + return client.chat.completions.create( + model="gpt-4o-mini", + response_model=RerankedResults, + messages=[ + { + "role": "system", + "content": """ + You are an expert search result ranker. Your task is to evaluate the relevance of each text chunk to the given query and assign a relevancy score. + + For each chunk: + 1. Analyze its content in relation to the query. + 2. Provide a chain of thought explaining your reasoning. + 3. Assign a relevancy score from 0 to 10, where 10 is most relevant. + + Be objective and consistent in your evaluations. + """, + }, + { + "role": "user", + "content": """ + {{ query }} + + + {% for chunk in chunks %} + + {{ chunk.text }} + + {% endfor %} + + + Please provide a RerankedResults object with a Label for each chunk. + """, + }, + ], + context={"query": query, "chunks": chunks}, + ) +``` + +This function takes a query and a list of text chunks as input, sends them to the LLM with a predefined prompt, and returns a structured `RerankedResults` object. Thanks to instructor we can use jinja templating to inject the query and chunks into the prompt by passing in the `context` parameter. + +## Testing the Reranker + +To test our LLM-based reranker, we can create a sample query and a list of text chunks. Here's an example of how to use the reranker: + +```python +def main(): + query = "What are the health benefits of regular exercise?" + chunks = [ + { + "id": 0, + "text": "Regular exercise can improve cardiovascular health and reduce the risk of heart disease.", + }, + { + "id": 1, + "text": "The price of gym memberships varies widely depending on location and facilities.", + }, + { + "id": 2, + "text": "Exercise has been shown to boost mood and reduce symptoms of depression and anxiety.", + }, + { + "id": 3, + "text": "Proper nutrition is essential for maintaining a healthy lifestyle.", + }, + { + "id": 4, + "text": "Strength training can increase muscle mass and improve bone density, especially important as we age.", + }, + ] + + results = rerank_results(query, chunks) + + print("Reranked results:") + for label in results.labels: + print(f"Chunk {label.chunk_id} (Relevancy: {label.relevancy}):") + print(f"Text: {chunks[label.chunk_id]['text']}") + print(f"Reasoning: {label.chain_of_thought}") + print() + +if __name__ == "__main__": + main() +``` + +This test demonstrates how the reranker evaluates and sorts the chunks based on their relevance to the query. The full implementation can be found in the `examples/reranker/run.py` file. + +If you want to extend this example, you could use the `rerank_results` function to label synthetic data for fine-tuning a traditional reranker, or to build out an evaluation pipeline for your RAG system. + +Moreover, we could also add validators to the `Label.chunk_id` field to ensure that the chunk_id is present in the `chunks` list. This might be useful if labels are `uuids` or complex strings and we want to ensure that the chunk_id is a valid index for the chunks list. + +heres an example + +```python +class Label(BaseModel): + chunk_id: int = Field(description="The unique identifier of the text chunk") + ... + + @field_validator("chunk_id") + @classmethod + def validate_chunk_id(cls, v: int, info: ValidationInfo) -> int: + context = info.context + chunks = context["chunks"] + if v not in [chunk["id"] for chunk in chunks]: + raise ValueError(f"Chunk with id {v} not found, must be one of {[chunk['id'] for chunk in chunks]}") + return v +``` + +This will automatically check that the `chunk_id` is present in the `chunks` list and raise a `ValueError` if it is not, where `context` is the context dictionary that we passed into the `rerank_results` function. \ No newline at end of file diff --git a/examples/reranker/run.py b/examples/reranker/run.py new file mode 100644 index 000000000..bdd3d716a --- /dev/null +++ b/examples/reranker/run.py @@ -0,0 +1,121 @@ +import instructor +from openai import OpenAI +from pydantic import BaseModel, Field, field_validator, ValidationInfo + +# Initialize the OpenAI client with Instructor +client = instructor.from_openai(OpenAI()) + + +class Label(BaseModel): + chunk_id: str = Field(description="The unique identifier of the text chunk") + chain_of_thought: str = Field( + description="The reasoning process used to evaluate the relevance" + ) + relevancy: int = Field( + description="Relevancy score from 0 to 10, where 10 is most relevant", + ge=0, + le=10, + ) + + @field_validator("chunk_id") + @classmethod + def validate_chunk_id(cls, v: str, info: ValidationInfo) -> str: + context = info.context + chunks = context.get("chunks", []) + if v not in [chunk["id"] for chunk in chunks]: + raise ValueError( + f"Chunk with id {v} not found, must be one of {[chunk['id'] for chunk in chunks]}" + ) + return v + + +class RerankedResults(BaseModel): + labels: list[Label] = Field(description="List of labeled and ranked chunks") + + @field_validator("labels") + @classmethod + def model_validate(cls, v: list[Label]) -> list[Label]: + return sorted(v, key=lambda x: x.relevancy, reverse=True) + + +def rerank_results(query: str, chunks: list[dict]) -> RerankedResults: + return client.chat.completions.create( + model="gpt-4o-mini", + response_model=RerankedResults, + messages=[ + { + "role": "system", + "content": """ + You are an expert search result ranker. Your task is to evaluate the relevance of each text chunk to the given query and assign a relevancy score. + + For each chunk: + 1. Analyze its content in relation to the query. + 2. Provide a chain of thought explaining your reasoning. + 3. Assign a relevancy score from 0 to 10, where 10 is most relevant. + + Be objective and consistent in your evaluations. + """, + }, + { + "role": "user", + "content": """ + {{ query }} + + + {% for chunk in chunks %} + + {{ chunk.text }} + + {% endfor %} + + + Please provide a RerankedResults object with a Label for each chunk. + """, + }, + ], + context={"query": query, "chunks": chunks}, + ) + + +def main(): + # Sample query and chunks + query = "What are the health benefits of regular exercise?" + chunks = [ + { + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "text": "Regular exercise can improve cardiovascular health and reduce the risk of heart disease.", + }, + { + "id": "b2c3d4e5-f6g7-8901-bcde-fg2345678901", + "text": "The price of gym memberships varies widely depending on location and facilities.", + }, + { + "id": "c3d4e5f6-g7h8-9012-cdef-gh3456789012", + "text": "Exercise has been shown to boost mood and reduce symptoms of depression and anxiety.", + }, + { + "id": "d4e5f6g7-h8i9-0123-defg-hi4567890123", + "text": "Proper nutrition is essential for maintaining a healthy lifestyle.", + }, + { + "id": "e5f6g7h8-i9j0-1234-efgh-ij5678901234", + "text": "Strength training can increase muscle mass and improve bone density, especially important as we age.", + }, + ] + + # Rerank the results + results = rerank_results(query, chunks) + + # Print the reranked results + print("Reranked results:") + for label in results.labels: + print(f"Chunk {label.chunk_id} (Relevancy: {label.relevancy}):") + print( + f"Text: {next(chunk['text'] for chunk in chunks if chunk['id'] == label.chunk_id)}" + ) + print(f"Reasoning: {label.chain_of_thought}") + print() + + +if __name__ == "__main__": + main() From a4c9d20f5bb240756a6be43a855287056c829e88 Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Mon, 28 Oct 2024 11:51:02 -0400 Subject: [PATCH 2/8] ci: add AI labeler workflow for issues and pull requests (#1126) --- .github/workflows/ai-label.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/workflows/ai-label.yml diff --git a/.github/workflows/ai-label.yml b/.github/workflows/ai-label.yml new file mode 100644 index 000000000..e8c868090 --- /dev/null +++ b/.github/workflows/ai-label.yml @@ -0,0 +1,20 @@ +name: AI Labeler + +on: +issues: + types: [opened, reopened] +pull_request: + types: [opened, reopened] + +jobs: +ai-labeler: + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + pull-requests: write + steps: + - uses: actions/checkout@v4 + - uses: jlowin/ai-labeler@v0.2.0 + with: + openai-api-key: ${{ secrets.OPENAI_API_KEY }} \ No newline at end of file From ae6847bbdea2217b6164455a83a82e0122d00d7b Mon Sep 17 00:00:00 2001 From: Nawed Ali Date: Mon, 28 Oct 2024 21:21:13 +0530 Subject: [PATCH 3/8] fix: typo changes (#1125) --- docs/examples/extracting_tables.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/examples/extracting_tables.md b/docs/examples/extracting_tables.md index 8af763e60..c0bcaf03d 100644 --- a/docs/examples/extracting_tables.md +++ b/docs/examples/extracting_tables.md @@ -138,7 +138,7 @@ MarkdownDataFrame = Annotated[ WithJsonSchema( { "type": "string", - "description": "The markdown representation of the table, each one should be tidy, do not try to join tables that should be seperate", + "description": "The markdown representation of the table, each one should be tidy, do not try to join tables that should be separate", } ), ] @@ -152,7 +152,7 @@ class Table(BaseModel): # <%hide%> # Apply the patch to the OpenAI client to support response_model -# Also use MD_JSON mode since the visino model does not support any special structured output mode +# Also use MD_JSON mode since the vision model does not support any special structured output mode client = instructor.from_openai(OpenAI(), mode=instructor.function_calls.Mode.MD_JSON) @@ -213,7 +213,7 @@ MarkdownDataFrame = Annotated[ WithJsonSchema( { "type": "string", - "description": "The markdown representation of the table, each one should be tidy, do not try to join tables that should be seperate", + "description": "The markdown representation of the table, each one should be tidy, do not try to join tables that should be separate", } ), ] From bdd2b189854023de1f1f7c73c260bf445c308bd7 Mon Sep 17 00:00:00 2001 From: sahibpreet singh Date: Mon, 28 Oct 2024 11:51:47 -0400 Subject: [PATCH 4/8] =?UTF-8?q?gpt=203.5=20turbo=20updated=20to=20gpt-40-m?= =?UTF-8?q?ini=20since=20July=202024=20it=20is=20recommende=E2=80=A6=20(#1?= =?UTF-8?q?122)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bde5396a8..d550d26a7 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ client = instructor.from_openai(OpenAI()) # Extract structured data from natural language user_info = client.chat.completions.create( - model="gpt-3.5-turbo", + model="gpt-4o-mini", response_model=UserInfo, messages=[{"role": "user", "content": "John Doe is 30 years old."}], ) @@ -84,7 +84,7 @@ client.on("completion:kwargs", log_kwargs) client.on("completion:error", log_exception) user_info = client.chat.completions.create( - model="gpt-3.5-turbo", + model="gpt-4o-mini", response_model=UserInfo, messages=[{"role": "user", "content": "Extract the user name: 'John is 20 years old'"}], ) @@ -99,7 +99,7 @@ user_info = client.chat.completions.create( 'content': "Extract the user name: 'John is 20 years old'", } ], - 'model': 'gpt-3.5-turbo', + 'model': 'gpt-4o-mini', 'tools': [ { 'type': 'function', From bae6c788d2937f11fe449c886cf01e624c0c09fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 11:53:15 -0400 Subject: [PATCH 5/8] chore(deps): bump the poetry group across 1 directory with 18 updates (#1117) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 257 ++++++++++++++++++++------------------ pyproject.toml | 22 ++-- requirements-examples.txt | 6 +- requirements.txt | 6 +- 4 files changed, 152 insertions(+), 139 deletions(-) diff --git a/poetry.lock b/poetry.lock index 597501dbd..afd103740 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -150,13 +150,13 @@ files = [ [[package]] name = "anthropic" -version = "0.36.2" +version = "0.37.1" description = "The official Python library for the anthropic API" optional = false python-versions = ">=3.7" files = [ - {file = "anthropic-0.36.2-py3-none-any.whl", hash = "sha256:308ddc6c538de03c081552e456bc0b387b6f7c7d1dea0c20122cc11c7cdbaf6a"}, - {file = "anthropic-0.36.2.tar.gz", hash = "sha256:d5a3fa56d1c82a51944f9dc7b0dc72048deb89f8df5ebfd09e2d1b59c62eb8eb"}, + {file = "anthropic-0.37.1-py3-none-any.whl", hash = "sha256:8f550f88906823752e2abf99fbe491fbc8d40bce4cb26b9663abdf7be990d721"}, + {file = "anthropic-0.37.1.tar.gz", hash = "sha256:99f688265795daa7ba9256ee68eaf2f05d53cd99d7417f4a0c2dc292c106d00a"}, ] [package.dependencies] @@ -428,13 +428,13 @@ test = ["flake8", "isort", "pytest"] [[package]] name = "cerebras-cloud-sdk" -version = "1.7.0" +version = "1.8.0" description = "The official Python library for the cerebras API" optional = false python-versions = ">=3.7" files = [ - {file = "cerebras_cloud_sdk-1.7.0-py3-none-any.whl", hash = "sha256:48ce4d2ebac24772969263828c4a7031ebbd69b47c82e67ed9b7811322609667"}, - {file = "cerebras_cloud_sdk-1.7.0.tar.gz", hash = "sha256:8db3f7d51e00fe70a971b2d59f580d643ae8b7457a91b679fdb08f6b01fce976"}, + {file = "cerebras_cloud_sdk-1.8.0-py3-none-any.whl", hash = "sha256:a2edcf65f1264234284d7d5f5c3845b1408348eeb25c22cda1715ddca7a3b7f2"}, + {file = "cerebras_cloud_sdk-1.8.0.tar.gz", hash = "sha256:567af063ccbd6cf2063db8ce5d796c9e5e9c06dfc57199ac0dd03d0f0f51b18a"}, ] [package.dependencies] @@ -841,22 +841,22 @@ test = ["flake8", "isort", "pytest"] [[package]] name = "datasets" -version = "3.0.1" +version = "3.0.2" description = "HuggingFace community-driven open-source library of datasets" optional = false python-versions = ">=3.8.0" files = [ - {file = "datasets-3.0.1-py3-none-any.whl", hash = "sha256:db080aab41c8cc68645117a0f172e5c6789cbc672f066de0aa5a08fc3eebc686"}, - {file = "datasets-3.0.1.tar.gz", hash = "sha256:40d63b09e76a3066c32e746d6fdc36fd3f29ed2acd49bf5b1a2100da32936511"}, + {file = "datasets-3.0.2-py3-none-any.whl", hash = "sha256:220bfbea0be9bf81d121bd2ac76fe4ef3f7defe0e8586ce1e7f66dcaaf69f88d"}, + {file = "datasets-3.0.2.tar.gz", hash = "sha256:07204c389ce0491ef3ad50dd79966d3fd40422a12b831cf84a117323ac74fbc1"}, ] [package.dependencies] aiohttp = "*" dill = ">=0.3.0,<0.3.9" filelock = "*" -fsspec = {version = ">=2023.1.0,<=2024.6.1", extras = ["http"]} -huggingface-hub = ">=0.22.0" -multiprocess = "*" +fsspec = {version = ">=2023.1.0,<=2024.9.0", extras = ["http"]} +huggingface-hub = ">=0.23.0" +multiprocess = "<0.70.17" numpy = ">=1.17" packaging = "*" pandas = "*" @@ -1038,22 +1038,23 @@ tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipyth [[package]] name = "fastapi" -version = "0.109.2" +version = "0.115.3" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false python-versions = ">=3.8" files = [ - {file = "fastapi-0.109.2-py3-none-any.whl", hash = "sha256:2c9bab24667293b501cad8dd388c05240c850b58ec5876ee3283c47d6e1e3a4d"}, - {file = "fastapi-0.109.2.tar.gz", hash = "sha256:f3817eac96fe4f65a2ebb4baa000f394e55f5fccdaf7f75250804bc58f354f73"}, + {file = "fastapi-0.115.3-py3-none-any.whl", hash = "sha256:8035e8f9a2b0aa89cea03b6c77721178ed5358e1aea4cd8570d9466895c0638c"}, + {file = "fastapi-0.115.3.tar.gz", hash = "sha256:c091c6a35599c036d676fa24bd4a6e19fa30058d93d950216cdc672881f6f7db"}, ] [package.dependencies] pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" -starlette = ">=0.36.3,<0.37.0" +starlette = ">=0.40.0,<0.42.0" typing-extensions = ">=4.8.0" [package.extras] -all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] +all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] +standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=2.11.2)", "python-multipart (>=0.0.7)", "uvicorn[standard] (>=0.12.0)"] [[package]] name = "fastavro" @@ -1133,13 +1134,13 @@ typing = ["typing-extensions (>=4.12.2)"] [[package]] name = "fireworks-ai" -version = "0.15.6" +version = "0.15.7" description = "Python client library for the Fireworks.ai Generative AI Platform" optional = false python-versions = ">=3.7" files = [ - {file = "fireworks_ai-0.15.6-py3-none-any.whl", hash = "sha256:54da135113324bc6632e5c1f8e15ce7ac3952151491bd49c35c53f3bcc4c2238"}, - {file = "fireworks_ai-0.15.6.tar.gz", hash = "sha256:9d136709451c533227fe7af8f5b29ea23b8f2952ee89de7b4d6e0b2b592b3904"}, + {file = "fireworks_ai-0.15.7-py3-none-any.whl", hash = "sha256:44d6985e245b70e3417c5800a3ef1a1710e2827469f42dab356a82d17d44a45e"}, + {file = "fireworks_ai-0.15.7.tar.gz", hash = "sha256:70193f1f81954f49a88ba85d77f4a7f42bdb5ac5ffc9f9aa72ba83aef20df22f"}, ] [package.dependencies] @@ -1361,12 +1362,12 @@ files = [ google-auth = ">=2.14.1,<3.0.dev0" googleapis-common-protos = ">=1.56.2,<2.0.dev0" grpcio = [ - {version = ">=1.49.1,<2.0dev", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, {version = ">=1.33.2,<2.0dev", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, + {version = ">=1.49.1,<2.0dev", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, ] grpcio-status = [ - {version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, {version = ">=1.33.2,<2.0.dev0", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, + {version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, ] proto-plus = ">=1.22.3,<2.0.0dev" protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" @@ -1787,13 +1788,13 @@ colorama = ">=0.4" [[package]] name = "groq" -version = "0.4.2" +version = "0.11.0" description = "The official Python library for the groq API" optional = false python-versions = ">=3.7" files = [ - {file = "groq-0.4.2-py3-none-any.whl", hash = "sha256:5b2b472c64d9f35210e0487db465415d47162da3a114031ecbfc8843d26302a5"}, - {file = "groq-0.4.2.tar.gz", hash = "sha256:42e8b0abd0f2b2da024b9a747d28960d62951a5364f078e1537c9fceeca8259d"}, + {file = "groq-0.11.0-py3-none-any.whl", hash = "sha256:e328531c979542e563668c62260aec13b43a6ee0ca9e2fb22dff1d26f8c8ce54"}, + {file = "groq-0.11.0.tar.gz", hash = "sha256:dbb9aefedf388ddd4801ec7bf3eba7f5edb67948fec0cd2829d97244059f42a7"}, ] [package.dependencies] @@ -2225,72 +2226,84 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "jiter" -version = "0.5.0" +version = "0.6.1" description = "Fast iterable JSON parser." optional = false python-versions = ">=3.8" files = [ - {file = "jiter-0.5.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b599f4e89b3def9a94091e6ee52e1d7ad7bc33e238ebb9c4c63f211d74822c3f"}, - {file = "jiter-0.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a063f71c4b06225543dddadbe09d203dc0c95ba352d8b85f1221173480a71d5"}, - {file = "jiter-0.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:acc0d5b8b3dd12e91dd184b87273f864b363dfabc90ef29a1092d269f18c7e28"}, - {file = "jiter-0.5.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c22541f0b672f4d741382a97c65609332a783501551445ab2df137ada01e019e"}, - {file = "jiter-0.5.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63314832e302cc10d8dfbda0333a384bf4bcfce80d65fe99b0f3c0da8945a91a"}, - {file = "jiter-0.5.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a25fbd8a5a58061e433d6fae6d5298777c0814a8bcefa1e5ecfff20c594bd749"}, - {file = "jiter-0.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:503b2c27d87dfff5ab717a8200fbbcf4714516c9d85558048b1fc14d2de7d8dc"}, - {file = "jiter-0.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6d1f3d27cce923713933a844872d213d244e09b53ec99b7a7fdf73d543529d6d"}, - {file = "jiter-0.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c95980207b3998f2c3b3098f357994d3fd7661121f30669ca7cb945f09510a87"}, - {file = "jiter-0.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:afa66939d834b0ce063f57d9895e8036ffc41c4bd90e4a99631e5f261d9b518e"}, - {file = "jiter-0.5.0-cp310-none-win32.whl", hash = "sha256:f16ca8f10e62f25fd81d5310e852df6649af17824146ca74647a018424ddeccf"}, - {file = "jiter-0.5.0-cp310-none-win_amd64.whl", hash = "sha256:b2950e4798e82dd9176935ef6a55cf6a448b5c71515a556da3f6b811a7844f1e"}, - {file = "jiter-0.5.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d4c8e1ed0ef31ad29cae5ea16b9e41529eb50a7fba70600008e9f8de6376d553"}, - {file = "jiter-0.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c6f16e21276074a12d8421692515b3fd6d2ea9c94fd0734c39a12960a20e85f3"}, - {file = "jiter-0.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5280e68e7740c8c128d3ae5ab63335ce6d1fb6603d3b809637b11713487af9e6"}, - {file = "jiter-0.5.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:583c57fc30cc1fec360e66323aadd7fc3edeec01289bfafc35d3b9dcb29495e4"}, - {file = "jiter-0.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:26351cc14507bdf466b5f99aba3df3143a59da75799bf64a53a3ad3155ecded9"}, - {file = "jiter-0.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4829df14d656b3fb87e50ae8b48253a8851c707da9f30d45aacab2aa2ba2d614"}, - {file = "jiter-0.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a42a4bdcf7307b86cb863b2fb9bb55029b422d8f86276a50487982d99eed7c6e"}, - {file = "jiter-0.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04d461ad0aebf696f8da13c99bc1b3e06f66ecf6cfd56254cc402f6385231c06"}, - {file = "jiter-0.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e6375923c5f19888c9226582a124b77b622f8fd0018b843c45eeb19d9701c403"}, - {file = "jiter-0.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2cec323a853c24fd0472517113768c92ae0be8f8c384ef4441d3632da8baa646"}, - {file = "jiter-0.5.0-cp311-none-win32.whl", hash = "sha256:aa1db0967130b5cab63dfe4d6ff547c88b2a394c3410db64744d491df7f069bb"}, - {file = "jiter-0.5.0-cp311-none-win_amd64.whl", hash = "sha256:aa9d2b85b2ed7dc7697597dcfaac66e63c1b3028652f751c81c65a9f220899ae"}, - {file = "jiter-0.5.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9f664e7351604f91dcdd557603c57fc0d551bc65cc0a732fdacbf73ad335049a"}, - {file = "jiter-0.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:044f2f1148b5248ad2c8c3afb43430dccf676c5a5834d2f5089a4e6c5bbd64df"}, - {file = "jiter-0.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:702e3520384c88b6e270c55c772d4bd6d7b150608dcc94dea87ceba1b6391248"}, - {file = "jiter-0.5.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:528d742dcde73fad9d63e8242c036ab4a84389a56e04efd854062b660f559544"}, - {file = "jiter-0.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8cf80e5fe6ab582c82f0c3331df27a7e1565e2dcf06265afd5173d809cdbf9ba"}, - {file = "jiter-0.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:44dfc9ddfb9b51a5626568ef4e55ada462b7328996294fe4d36de02fce42721f"}, - {file = "jiter-0.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c451f7922992751a936b96c5f5b9bb9312243d9b754c34b33d0cb72c84669f4e"}, - {file = "jiter-0.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:308fce789a2f093dca1ff91ac391f11a9f99c35369117ad5a5c6c4903e1b3e3a"}, - {file = "jiter-0.5.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7f5ad4a7c6b0d90776fdefa294f662e8a86871e601309643de30bf94bb93a64e"}, - {file = "jiter-0.5.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ea189db75f8eca08807d02ae27929e890c7d47599ce3d0a6a5d41f2419ecf338"}, - {file = "jiter-0.5.0-cp312-none-win32.whl", hash = "sha256:e3bbe3910c724b877846186c25fe3c802e105a2c1fc2b57d6688b9f8772026e4"}, - {file = "jiter-0.5.0-cp312-none-win_amd64.whl", hash = "sha256:a586832f70c3f1481732919215f36d41c59ca080fa27a65cf23d9490e75b2ef5"}, - {file = "jiter-0.5.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:f04bc2fc50dc77be9d10f73fcc4e39346402ffe21726ff41028f36e179b587e6"}, - {file = "jiter-0.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6f433a4169ad22fcb550b11179bb2b4fd405de9b982601914ef448390b2954f3"}, - {file = "jiter-0.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad4a6398c85d3a20067e6c69890ca01f68659da94d74c800298581724e426c7e"}, - {file = "jiter-0.5.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6baa88334e7af3f4d7a5c66c3a63808e5efbc3698a1c57626541ddd22f8e4fbf"}, - {file = "jiter-0.5.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ece0a115c05efca597c6d938f88c9357c843f8c245dbbb53361a1c01afd7148"}, - {file = "jiter-0.5.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:335942557162ad372cc367ffaf93217117401bf930483b4b3ebdb1223dbddfa7"}, - {file = "jiter-0.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:649b0ee97a6e6da174bffcb3c8c051a5935d7d4f2f52ea1583b5b3e7822fbf14"}, - {file = "jiter-0.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f4be354c5de82157886ca7f5925dbda369b77344b4b4adf2723079715f823989"}, - {file = "jiter-0.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5206144578831a6de278a38896864ded4ed96af66e1e63ec5dd7f4a1fce38a3a"}, - {file = "jiter-0.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8120c60f8121ac3d6f072b97ef0e71770cc72b3c23084c72c4189428b1b1d3b6"}, - {file = "jiter-0.5.0-cp38-none-win32.whl", hash = "sha256:6f1223f88b6d76b519cb033a4d3687ca157c272ec5d6015c322fc5b3074d8a5e"}, - {file = "jiter-0.5.0-cp38-none-win_amd64.whl", hash = "sha256:c59614b225d9f434ea8fc0d0bec51ef5fa8c83679afedc0433905994fb36d631"}, - {file = "jiter-0.5.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:0af3838cfb7e6afee3f00dc66fa24695199e20ba87df26e942820345b0afc566"}, - {file = "jiter-0.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:550b11d669600dbc342364fd4adbe987f14d0bbedaf06feb1b983383dcc4b961"}, - {file = "jiter-0.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:489875bf1a0ffb3cb38a727b01e6673f0f2e395b2aad3c9387f94187cb214bbf"}, - {file = "jiter-0.5.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b250ca2594f5599ca82ba7e68785a669b352156260c5362ea1b4e04a0f3e2389"}, - {file = "jiter-0.5.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ea18e01f785c6667ca15407cd6dabbe029d77474d53595a189bdc813347218e"}, - {file = "jiter-0.5.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:462a52be85b53cd9bffd94e2d788a09984274fe6cebb893d6287e1c296d50653"}, - {file = "jiter-0.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:92cc68b48d50fa472c79c93965e19bd48f40f207cb557a8346daa020d6ba973b"}, - {file = "jiter-0.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1c834133e59a8521bc87ebcad773608c6fa6ab5c7a022df24a45030826cf10bc"}, - {file = "jiter-0.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab3a71ff31cf2d45cb216dc37af522d335211f3a972d2fe14ea99073de6cb104"}, - {file = "jiter-0.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cccd3af9c48ac500c95e1bcbc498020c87e1781ff0345dd371462d67b76643eb"}, - {file = "jiter-0.5.0-cp39-none-win32.whl", hash = "sha256:368084d8d5c4fc40ff7c3cc513c4f73e02c85f6009217922d0823a48ee7adf61"}, - {file = "jiter-0.5.0-cp39-none-win_amd64.whl", hash = "sha256:ce03f7b4129eb72f1687fa11300fbf677b02990618428934662406d2a76742a1"}, - {file = "jiter-0.5.0.tar.gz", hash = "sha256:1d916ba875bcab5c5f7d927df998c4cb694d27dceddf3392e58beaf10563368a"}, + {file = "jiter-0.6.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:d08510593cb57296851080018006dfc394070178d238b767b1879dc1013b106c"}, + {file = "jiter-0.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:adef59d5e2394ebbad13b7ed5e0306cceb1df92e2de688824232a91588e77aa7"}, + {file = "jiter-0.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3e02f7a27f2bcc15b7d455c9df05df8ffffcc596a2a541eeda9a3110326e7a3"}, + {file = "jiter-0.6.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed69a7971d67b08f152c17c638f0e8c2aa207e9dd3a5fcd3cba294d39b5a8d2d"}, + {file = "jiter-0.6.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2019d966e98f7c6df24b3b8363998575f47d26471bfb14aade37630fae836a1"}, + {file = "jiter-0.6.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:36c0b51a285b68311e207a76c385650322734c8717d16c2eb8af75c9d69506e7"}, + {file = "jiter-0.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:220e0963b4fb507c525c8f58cde3da6b1be0bfddb7ffd6798fb8f2531226cdb1"}, + {file = "jiter-0.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aa25c7a9bf7875a141182b9c95aed487add635da01942ef7ca726e42a0c09058"}, + {file = "jiter-0.6.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e90552109ca8ccd07f47ca99c8a1509ced93920d271bb81780a973279974c5ab"}, + {file = "jiter-0.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:67723a011964971864e0b484b0ecfee6a14de1533cff7ffd71189e92103b38a8"}, + {file = "jiter-0.6.1-cp310-none-win32.whl", hash = "sha256:33af2b7d2bf310fdfec2da0177eab2fedab8679d1538d5b86a633ebfbbac4edd"}, + {file = "jiter-0.6.1-cp310-none-win_amd64.whl", hash = "sha256:7cea41c4c673353799906d940eee8f2d8fd1d9561d734aa921ae0f75cb9732f4"}, + {file = "jiter-0.6.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b03c24e7da7e75b170c7b2b172d9c5e463aa4b5c95696a368d52c295b3f6847f"}, + {file = "jiter-0.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:47fee1be677b25d0ef79d687e238dc6ac91a8e553e1a68d0839f38c69e0ee491"}, + {file = "jiter-0.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25f0d2f6e01a8a0fb0eab6d0e469058dab2be46ff3139ed2d1543475b5a1d8e7"}, + {file = "jiter-0.6.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0b809e39e342c346df454b29bfcc7bca3d957f5d7b60e33dae42b0e5ec13e027"}, + {file = "jiter-0.6.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e9ac7c2f092f231f5620bef23ce2e530bd218fc046098747cc390b21b8738a7a"}, + {file = "jiter-0.6.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e51a2d80d5fe0ffb10ed2c82b6004458be4a3f2b9c7d09ed85baa2fbf033f54b"}, + {file = "jiter-0.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3343d4706a2b7140e8bd49b6c8b0a82abf9194b3f0f5925a78fc69359f8fc33c"}, + {file = "jiter-0.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82521000d18c71e41c96960cb36e915a357bc83d63a8bed63154b89d95d05ad1"}, + {file = "jiter-0.6.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3c843e7c1633470708a3987e8ce617ee2979ee18542d6eb25ae92861af3f1d62"}, + {file = "jiter-0.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a2e861658c3fe849efc39b06ebb98d042e4a4c51a8d7d1c3ddc3b1ea091d0784"}, + {file = "jiter-0.6.1-cp311-none-win32.whl", hash = "sha256:7d72fc86474862c9c6d1f87b921b70c362f2b7e8b2e3c798bb7d58e419a6bc0f"}, + {file = "jiter-0.6.1-cp311-none-win_amd64.whl", hash = "sha256:3e36a320634f33a07794bb15b8da995dccb94f944d298c8cfe2bd99b1b8a574a"}, + {file = "jiter-0.6.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:1fad93654d5a7dcce0809aff66e883c98e2618b86656aeb2129db2cd6f26f867"}, + {file = "jiter-0.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4e6e340e8cd92edab7f6a3a904dbbc8137e7f4b347c49a27da9814015cc0420c"}, + {file = "jiter-0.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:691352e5653af84ed71763c3c427cff05e4d658c508172e01e9c956dfe004aba"}, + {file = "jiter-0.6.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:defee3949313c1f5b55e18be45089970cdb936eb2a0063f5020c4185db1b63c9"}, + {file = "jiter-0.6.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:26d2bdd5da097e624081c6b5d416d3ee73e5b13f1703bcdadbb1881f0caa1933"}, + {file = "jiter-0.6.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18aa9d1626b61c0734b973ed7088f8a3d690d0b7f5384a5270cd04f4d9f26c86"}, + {file = "jiter-0.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a3567c8228afa5ddcce950631c6b17397ed178003dc9ee7e567c4c4dcae9fa0"}, + {file = "jiter-0.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e5c0507131c922defe3f04c527d6838932fcdfd69facebafd7d3574fa3395314"}, + {file = "jiter-0.6.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:540fcb224d7dc1bcf82f90f2ffb652df96f2851c031adca3c8741cb91877143b"}, + {file = "jiter-0.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e7b75436d4fa2032b2530ad989e4cb0ca74c655975e3ff49f91a1a3d7f4e1df2"}, + {file = "jiter-0.6.1-cp312-none-win32.whl", hash = "sha256:883d2ced7c21bf06874fdeecab15014c1c6d82216765ca6deef08e335fa719e0"}, + {file = "jiter-0.6.1-cp312-none-win_amd64.whl", hash = "sha256:91e63273563401aadc6c52cca64a7921c50b29372441adc104127b910e98a5b6"}, + {file = "jiter-0.6.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:852508a54fe3228432e56019da8b69208ea622a3069458252f725d634e955b31"}, + {file = "jiter-0.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f491cc69ff44e5a1e8bc6bf2b94c1f98d179e1aaf4a554493c171a5b2316b701"}, + {file = "jiter-0.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc56c8f0b2a28ad4d8047f3ae62d25d0e9ae01b99940ec0283263a04724de1f3"}, + {file = "jiter-0.6.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:51b58f7a0d9e084a43b28b23da2b09fc5e8df6aa2b6a27de43f991293cab85fd"}, + {file = "jiter-0.6.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5f79ce15099154c90ef900d69c6b4c686b64dfe23b0114e0971f2fecd306ec6c"}, + {file = "jiter-0.6.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:03a025b52009f47e53ea619175d17e4ded7c035c6fbd44935cb3ada11e1fd592"}, + {file = "jiter-0.6.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c74a8d93718137c021d9295248a87c2f9fdc0dcafead12d2930bc459ad40f885"}, + {file = "jiter-0.6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:40b03b75f903975f68199fc4ec73d546150919cb7e534f3b51e727c4d6ccca5a"}, + {file = "jiter-0.6.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:825651a3f04cf92a661d22cad61fc913400e33aa89b3e3ad9a6aa9dc8a1f5a71"}, + {file = "jiter-0.6.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:928bf25eb69ddb292ab8177fe69d3fbf76c7feab5fce1c09265a7dccf25d3991"}, + {file = "jiter-0.6.1-cp313-none-win32.whl", hash = "sha256:352cd24121e80d3d053fab1cc9806258cad27c53cad99b7a3cac57cf934b12e4"}, + {file = "jiter-0.6.1-cp313-none-win_amd64.whl", hash = "sha256:be7503dd6f4bf02c2a9bacb5cc9335bc59132e7eee9d3e931b13d76fd80d7fda"}, + {file = "jiter-0.6.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:31d8e00e1fb4c277df8ab6f31a671f509ebc791a80e5c61fdc6bc8696aaa297c"}, + {file = "jiter-0.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:77c296d65003cd7ee5d7b0965f6acbe6cffaf9d1fa420ea751f60ef24e85fed5"}, + {file = "jiter-0.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aeeb0c0325ef96c12a48ea7e23e2e86fe4838e6e0a995f464cf4c79fa791ceeb"}, + {file = "jiter-0.6.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a31c6fcbe7d6c25d6f1cc6bb1cba576251d32795d09c09961174fe461a1fb5bd"}, + {file = "jiter-0.6.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59e2b37f3b9401fc9e619f4d4badcab2e8643a721838bcf695c2318a0475ae42"}, + {file = "jiter-0.6.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bae5ae4853cb9644144e9d0755854ce5108d470d31541d83f70ca7ecdc2d1637"}, + {file = "jiter-0.6.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9df588e9c830b72d8db1dd7d0175af6706b0904f682ea9b1ca8b46028e54d6e9"}, + {file = "jiter-0.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:15f8395e835cf561c85c1adee72d899abf2733d9df72e9798e6d667c9b5c1f30"}, + {file = "jiter-0.6.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a99d4e0b5fc3b05ea732d67eb2092fe894e95a90e6e413f2ea91387e228a307"}, + {file = "jiter-0.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a311df1fa6be0ccd64c12abcd85458383d96e542531bafbfc0a16ff6feda588f"}, + {file = "jiter-0.6.1-cp38-none-win32.whl", hash = "sha256:81116a6c272a11347b199f0e16b6bd63f4c9d9b52bc108991397dd80d3c78aba"}, + {file = "jiter-0.6.1-cp38-none-win_amd64.whl", hash = "sha256:13f9084e3e871a7c0b6e710db54444088b1dd9fbefa54d449b630d5e73bb95d0"}, + {file = "jiter-0.6.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:f1c53615fcfec3b11527c08d19cff6bc870da567ce4e57676c059a3102d3a082"}, + {file = "jiter-0.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f791b6a4da23238c17a81f44f5b55d08a420c5692c1fda84e301a4b036744eb1"}, + {file = "jiter-0.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c97e90fec2da1d5f68ef121444c2c4fa72eabf3240829ad95cf6bbeca42a301"}, + {file = "jiter-0.6.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3cbc1a66b4e41511209e97a2866898733c0110b7245791ac604117b7fb3fedb7"}, + {file = "jiter-0.6.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4e85f9e12cd8418ab10e1fcf0e335ae5bb3da26c4d13a0fd9e6a17a674783b6"}, + {file = "jiter-0.6.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08be33db6dcc374c9cc19d3633af5e47961a7b10d4c61710bd39e48d52a35824"}, + {file = "jiter-0.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:677be9550004f5e010d673d3b2a2b815a8ea07a71484a57d3f85dde7f14cf132"}, + {file = "jiter-0.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e8bd065be46c2eecc328e419d6557bbc37844c88bb07b7a8d2d6c91c7c4dedc9"}, + {file = "jiter-0.6.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bd95375ce3609ec079a97c5d165afdd25693302c071ca60c7ae1cf826eb32022"}, + {file = "jiter-0.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db459ed22d0208940d87f614e1f0ea5a946d29a3cfef71f7e1aab59b6c6b2afb"}, + {file = "jiter-0.6.1-cp39-none-win32.whl", hash = "sha256:d71c962f0971347bd552940ab96aa42ceefcd51b88c4ced8a27398182efa8d80"}, + {file = "jiter-0.6.1-cp39-none-win_amd64.whl", hash = "sha256:d465db62d2d10b489b7e7a33027c4ae3a64374425d757e963f86df5b5f2e7fc5"}, + {file = "jiter-0.6.1.tar.gz", hash = "sha256:e19cd21221fc139fb032e4112986656cb2739e9fe6d84c13956ab30ccc7d4449"}, ] [[package]] @@ -2459,13 +2472,13 @@ lxml = {version = ">=4.4.2", extras = ["html-clean"]} [[package]] name = "litellm" -version = "1.50.0" +version = "1.50.4" description = "Library to easily interface with LLM API providers" optional = false python-versions = "!=2.7.*,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,!=3.7.*,>=3.8" files = [ - {file = "litellm-1.50.0-py3-none-any.whl", hash = "sha256:97e25a2df273fdac012334515d84ce732ffa14f07582db2898fdd90bb85f35fe"}, - {file = "litellm-1.50.0.tar.gz", hash = "sha256:2202506b842e6048222d284f8b07c0491460cd256136202dd0da74a9aec2fcce"}, + {file = "litellm-1.50.4-py3-none-any.whl", hash = "sha256:cc6992275e24a0bbb4a3b377e6842d45a8510fc85d7f255930a64bb872980a36"}, + {file = "litellm-1.50.4.tar.gz", hash = "sha256:a7e68ef614f631b58969c2c7a5154a565ba5974558d437c8cd6c8623654880ea"}, ] [package.dependencies] @@ -2921,13 +2934,13 @@ pyyaml = ">=5.1" [[package]] name = "mkdocs-jupyter" -version = "0.24.8" +version = "0.25.1" description = "Use Jupyter in mkdocs websites" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "mkdocs_jupyter-0.24.8-py3-none-any.whl", hash = "sha256:36438a0a653eee2c27c6a8f7006e645f18693699c9b8ac44ffde830ddb08fa16"}, - {file = "mkdocs_jupyter-0.24.8.tar.gz", hash = "sha256:09a762f484d540d9c0e944d34b28cb536a32869e224b460e2fc791b143f76940"}, + {file = "mkdocs_jupyter-0.25.1-py3-none-any.whl", hash = "sha256:3f679a857609885d322880e72533ef5255561bbfdb13cfee2a1e92ef4d4ad8d8"}, + {file = "mkdocs_jupyter-0.25.1.tar.gz", hash = "sha256:0e9272ff4947e0ec683c92423a4bfb42a26477c103ab1a6ab8277e2dcc8f7afe"}, ] [package.dependencies] @@ -3018,13 +3031,13 @@ test = ["autoflake", "black", "isort", "pytest"] [[package]] name = "mkdocs-rss-plugin" -version = "1.15.0" +version = "1.16.0" description = "MkDocs plugin which generates a static RSS feed using git log and page.meta." optional = false -python-versions = "<4,>=3.8" +python-versions = "<4,>=3.9" files = [ - {file = "mkdocs_rss_plugin-1.15.0-py2.py3-none-any.whl", hash = "sha256:7308ac13f0976c0479db5a62cb7ef9b10fdd74b6521e459bb66a13e2cfe69d4b"}, - {file = "mkdocs_rss_plugin-1.15.0.tar.gz", hash = "sha256:92995ed6c77b2ae1f5f2913e62282c27e50c35d618c4291b5b939e50badd7504"}, + {file = "mkdocs_rss_plugin-1.16.0-py2.py3-none-any.whl", hash = "sha256:be66b11300f1e951d3393ce8da60ca6d730108f731434cc256670b3b8e0cffb3"}, + {file = "mkdocs_rss_plugin-1.16.0.tar.gz", hash = "sha256:f0e275c933be69a77ee7af92256d88e2969e10c36c5ee1ecdb663a4ea4aa08ea"}, ] [package.dependencies] @@ -3454,13 +3467,13 @@ files = [ [[package]] name = "openai" -version = "1.52.0" +version = "1.52.2" description = "The official Python library for the openai API" optional = false python-versions = ">=3.7.1" files = [ - {file = "openai-1.52.0-py3-none-any.whl", hash = "sha256:0c249f20920183b0a2ca4f7dba7b0452df3ecd0fa7985eb1d91ad884bc3ced9c"}, - {file = "openai-1.52.0.tar.gz", hash = "sha256:95c65a5f77559641ab8f3e4c3a050804f7b51d278870e2ec1f7444080bfe565a"}, + {file = "openai-1.52.2-py3-none-any.whl", hash = "sha256:57e9e37bc407f39bb6ec3a27d7e8fb9728b2779936daa1fcf95df17d3edfaccc"}, + {file = "openai-1.52.2.tar.gz", hash = "sha256:87b7d0f69d85f5641678d414b7ee3082363647a5c66a462ed7f3ccb59582da0d"}, ] [package.dependencies] @@ -3555,9 +3568,9 @@ files = [ [package.dependencies] numpy = [ - {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, - {version = ">=1.23.2", markers = "python_version == \"3.11\""}, {version = ">=1.22.4", markers = "python_version < \"3.11\""}, + {version = ">=1.23.2", markers = "python_version == \"3.11\""}, + {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, ] python-dateutil = ">=2.8.2" pytz = ">=2020.1" @@ -3655,13 +3668,13 @@ ptyprocess = ">=0.5" [[package]] name = "phonenumbers" -version = "8.13.47" +version = "8.13.48" description = "Python version of Google's common library for parsing, formatting, storing and validating international phone numbers." optional = false python-versions = "*" files = [ - {file = "phonenumbers-8.13.47-py2.py3-none-any.whl", hash = "sha256:5d3c0142ef7055ca5551884352e3b6b93bfe002a0bc95b8eaba39b0e2184541b"}, - {file = "phonenumbers-8.13.47.tar.gz", hash = "sha256:53c5e7c6d431cafe4efdd44956078404ae9bc8b0eacc47be3105d3ccc88aaffa"}, + {file = "phonenumbers-8.13.48-py2.py3-none-any.whl", hash = "sha256:5c51939acefa390eb74119750afb10a85d3c628dc83fd62c52d6f532fcf5d205"}, + {file = "phonenumbers-8.13.48.tar.gz", hash = "sha256:62d8df9b0f3c3c41571c6b396f044ddd999d61631534001b8be7fdf7ba1b18f3"}, ] [[package]] @@ -4107,8 +4120,8 @@ files = [ annotated-types = ">=0.4.0" pydantic-core = "2.20.1" typing-extensions = [ - {version = ">=4.12.2", markers = "python_version >= \"3.13\""}, {version = ">=4.6.1", markers = "python_version < \"3.13\""}, + {version = ">=4.12.2", markers = "python_version >= \"3.13\""}, ] [package.extras] @@ -4635,13 +4648,13 @@ cffi = {version = "*", markers = "implementation_name == \"pypy\""} [[package]] name = "redis" -version = "5.1.1" +version = "5.2.0" description = "Python client for Redis database and key-value store" optional = false python-versions = ">=3.8" files = [ - {file = "redis-5.1.1-py3-none-any.whl", hash = "sha256:f8ea06b7482a668c6475ae202ed8d9bcaa409f6e87fb77ed1043d912afd62e24"}, - {file = "redis-5.1.1.tar.gz", hash = "sha256:f6c997521fedbae53387307c5d0bf784d9acc28d9f1d058abeac566ec4dbed72"}, + {file = "redis-5.2.0-py3-none-any.whl", hash = "sha256:ae174f2bb3b1bf2b09d54bf3e51fbc1469cf6c10aa03e21141f51969801a7897"}, + {file = "redis-5.2.0.tar.gz", hash = "sha256:0b1087665a771b1ff2e003aa5bdd354f15a70c9e25d5a7dbf9c722c16528a7b0"}, ] [package.dependencies] @@ -4792,13 +4805,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "rich" -version = "13.9.2" +version = "13.9.3" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false python-versions = ">=3.8.0" files = [ - {file = "rich-13.9.2-py3-none-any.whl", hash = "sha256:8c82a3d3f8dcfe9e734771313e606b39d8247bb6b826e196f4914b333b743cf1"}, - {file = "rich-13.9.2.tar.gz", hash = "sha256:51a2c62057461aaf7152b4d611168f93a9fc73068f8ded2790f29fe2b5366d0c"}, + {file = "rich-13.9.3-py3-none-any.whl", hash = "sha256:9836f5096eb2172c9e77df411c1b009bace4193d6a481d534fea75ebba758283"}, + {file = "rich-13.9.3.tar.gz", hash = "sha256:bc1e01b899537598cf02579d2b9f4a415104d3fc439313a7a2c165d76557a08e"}, ] [package.dependencies] @@ -5206,13 +5219,13 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] [[package]] name = "starlette" -version = "0.36.3" +version = "0.41.0" description = "The little ASGI library that shines." optional = false python-versions = ">=3.8" files = [ - {file = "starlette-0.36.3-py3-none-any.whl", hash = "sha256:13d429aa93a61dc40bf503e8c801db1f1bca3dc706b10ef2434a36123568f044"}, - {file = "starlette-0.36.3.tar.gz", hash = "sha256:90a671733cfb35771d8cc605e0b679d23b992f8dcfad48cc60b38cb29aeb7080"}, + {file = "starlette-0.41.0-py3-none-any.whl", hash = "sha256:a0193a3c413ebc9c78bff1c3546a45bb8c8bcb4a84cae8747d650a65bd37210a"}, + {file = "starlette-0.41.0.tar.gz", hash = "sha256:39cbd8768b107d68bfe1ff1672b38a2c38b49777de46d2a592841d58e3bf7c2a"}, ] [package.dependencies] @@ -5727,13 +5740,13 @@ h11 = ">=0.9.0,<1" [[package]] name = "xmltodict" -version = "0.13.0" +version = "0.14.2" description = "Makes working with XML feel like you are working with JSON" optional = false -python-versions = ">=3.4" +python-versions = ">=3.6" files = [ - {file = "xmltodict-0.13.0-py2.py3-none-any.whl", hash = "sha256:aa89e8fd76320154a40d19a0df04a4695fb9dc5ba977cbb68ab3e4eb225e7852"}, - {file = "xmltodict-0.13.0.tar.gz", hash = "sha256:341595a488e3e01a85a9d8911d8912fd922ede5fecc4dce437eb4b6c8d037e56"}, + {file = "xmltodict-0.14.2-py2.py3-none-any.whl", hash = "sha256:20cc7d723ed729276e808f26fb6b3599f786cbc37e06c65e192ba77c40f20aac"}, + {file = "xmltodict-0.14.2.tar.gz", hash = "sha256:201e7c28bb210e374999d1dde6382923ab0ed1a8a5faeece48ab525b7810a553"}, ] [[package]] @@ -5998,4 +6011,4 @@ vertexai = ["google-cloud-aiplatform", "jsonref"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "c22ee43b3c92a6875abfd6ac29481cb4a517147a95e03f0396284ad568cc517a" +content-hash = "e1a99439af86fa4689c019b6530664f9b3eb45535eac738e342446bc1c33d849" diff --git a/pyproject.toml b/pyproject.toml index edb8aaec2..8638e3bdd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,21 +18,21 @@ rich = "^13.7.0" aiohttp = "^3.9.1" tenacity = ">=9.0.0,<10.0.0" pydantic-core = "^2.18.0" -jiter = "^0.5.0" +jiter = ">=0.5,<0.7" jinja2 = "^3.1.4" requests = "^2.32.3" # dependency versions for extras -fastapi = { version = "^0.109.2", optional = true } +fastapi = { version = ">=0.109.2,<0.116.0", optional = true } redis = { version = "^5.0.1", optional = true } diskcache = { version = "^5.6.3", optional = true } pandas = { version = "^2.2.0", optional = true } tabulate = { version = "^0.9.0", optional = true } pydantic_extra_types = { version = "^2.6.0", optional = true } litellm = { version = "^1.35.31", optional = true } -anthropic = { version = "^0.36.2", optional = true } -xmltodict = { version = "^0.13.0", optional = true } -groq = { version = "^0.4.2", optional = true } +anthropic = { version = ">=0.36.2,<0.38.0", optional = true } +xmltodict = { version = ">=0.13,<0.15", optional = true } +groq = { version = ">=0.4.2,<0.12.0", optional = true } cohere = { version = "^5.1.8", optional = true } mistralai = { version = "^1.0.3", optional = true } google-generativeai = { version = "^0.8.2", optional = true } @@ -81,25 +81,25 @@ mkdocs-material = { extras = ["imaging"], version = "^9.5.9" } mkdocstrings = "^0.26.1" mkdocstrings-python = "^1.11.1" pytest-examples = "^0.0.13" -mkdocs-jupyter = "^0.24.6" +mkdocs-jupyter = ">=0.24.6,<0.26.0" mkdocs-rss-plugin = "^1.12.0" mkdocs-minify-plugin = "^0.8.0" mkdocs-redirects = "^1.2.1" [tool.poetry.group.anthropic.dependencies] -anthropic = "^0.36.2" +anthropic = ">=0.36.2,<0.38.0" [tool.poetry.group.test-docs.dependencies] -fastapi = "^0.109.2" +fastapi = ">=0.109.2,<0.116.0" redis = "^5.0.1" diskcache = "^5.6.3" pandas = "^2.2.0" tabulate = "^0.9.0" pydantic_extra_types = "^2.6.0" litellm = "^1.35.31" -anthropic = "^0.36.2" -xmltodict = "^0.13.0" -groq = "^0.4.2" +anthropic = ">=0.36.2,<0.38.0" +xmltodict = ">=0.13,<0.15" +groq = ">=0.4.2,<0.12.0" phonenumbers = "^8.13.33" cohere = "^5.1.8" mistralai = "^1.0.3" diff --git a/requirements-examples.txt b/requirements-examples.txt index d4cb132a3..6bc8542f2 100644 --- a/requirements-examples.txt +++ b/requirements-examples.txt @@ -3,9 +3,9 @@ pydantic docstring-parser rich aiohttp -ruff==0.1.7 -pre-commit==3.5.0 -pyright==1.1.360 +ruff==0.7.1 +pre-commit==4.0.1 +pyright==1.1.386 typer cohere datasets diff --git a/requirements.txt b/requirements.txt index 99efad98a..fd1cc9899 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,8 +3,8 @@ pydantic docstring-parser rich aiohttp -ruff==0.1.7 -pre-commit==3.5.0 -pyright==1.1.360 +ruff==0.7.1 +pre-commit==4.0.1 +pyright==1.1.386 typer cohere \ No newline at end of file From 97b09176394c2544153d011402dd84679aa1ae51 Mon Sep 17 00:00:00 2001 From: Thierry Jean <68975210+zilto@users.noreply.github.com> Date: Mon, 28 Oct 2024 11:54:42 -0400 Subject: [PATCH 6/8] doc(blog): added Burr link; fixed date and formatting (#1099) Co-authored-by: zilto --- docs/blog/posts/openai-multimodal.md | 6 +++--- docs/blog/posts/youtube-flashcards.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/blog/posts/openai-multimodal.md b/docs/blog/posts/openai-multimodal.md index 4d7a9cb9c..49f3706b3 100644 --- a/docs/blog/posts/openai-multimodal.md +++ b/docs/blog/posts/openai-multimodal.md @@ -5,7 +5,7 @@ categories: - OpenAI - Audio comments: true -date: 2025-10-17 +date: 2024-10-17 description: Explore the new audio capabilities in OpenAI's Chat Completions API using the gpt-4o-audio-preview model. draft: false tags: @@ -33,7 +33,7 @@ The new audio support in the Chat Completions API offers several compelling feat To demonstrate how to use this new functionality, let's look at a simple example using the `instructor` library: -"""python +```python from openai import OpenAI from pydantic import BaseModel import instructor @@ -64,7 +64,7 @@ resp = client.chat.completions.create( print(resp) # Expected output: Person(name='Jason', age=20) -""" +``` In this example, we're using the `gpt-4o-audio-preview` model to extract information from an audio file. The API processes the audio input and returns structured data (a Person object with name and age) based on the content of the audio. diff --git a/docs/blog/posts/youtube-flashcards.md b/docs/blog/posts/youtube-flashcards.md index c0057d372..b12f3d5f3 100644 --- a/docs/blog/posts/youtube-flashcards.md +++ b/docs/blog/posts/youtube-flashcards.md @@ -23,7 +23,7 @@ Flashcards help break down complex topics and learn anything from biology to a n language or lines for a play. This blog will show how to use LLMs to generate flashcards and kickstart your learning! -**Instructor** lets us get structured outputs from LLMs reliably, and **Burr** helps +**Instructor** lets us get structured outputs from LLMs reliably, and [Burr](https://github.com/dagworks-inc/burr) helps create an LLM application that's easy to understand and debug. It comes with **Burr UI**, a free, open-source, and local-first tool for observability, annotations, and more! From b9c5cc3d4356ed82857b1ad0c78715d5b57326d9 Mon Sep 17 00:00:00 2001 From: Ivan Leo Date: Mon, 28 Oct 2024 23:55:00 +0800 Subject: [PATCH 7/8] docs: lint errors in concepts including hooks (#1088) --- docs/concepts/hooks.md | 284 ++++++++++++++---------------------- docs/concepts/multimodal.md | 25 +++- 2 files changed, 135 insertions(+), 174 deletions(-) diff --git a/docs/concepts/hooks.md b/docs/concepts/hooks.md index 6fccae429..7999f480e 100644 --- a/docs/concepts/hooks.md +++ b/docs/concepts/hooks.md @@ -82,7 +82,7 @@ resp = client.chat.completions.create( response_model=str, ) print(resp) -#> Hello! How can I assist you today? +#> Hello, world! ``` ### Emitting Events @@ -94,6 +94,25 @@ Events are automatically emitted by the Instructor library at appropriate times. You can remove a specific hook using the `off` method: ```python +# <%hide%> +import instructor +import openai +import pprint + +client = instructor.from_openai(openai.OpenAI()) +resp = client.chat.completions.create( + model="gpt-3.5-turbo", + messages=[{"role": "user", "content": "Hello, world!"}], + response_model=str, +) + + +def log_completion_kwargs(*args, **kwargs): + pprint.pprint({"args": args, "kwargs": kwargs}) + + +client.on("completion:kwargs", log_completion_kwargs) +# <%hide%> client.off("completion:kwargs", log_completion_kwargs) ``` @@ -102,6 +121,17 @@ client.off("completion:kwargs", log_completion_kwargs) To remove all hooks for a specific event or all events: ```python +# <%hide%> +import instructor +import openai + +client = instructor.from_openai(openai.OpenAI()) +resp = client.chat.completions.create( + model="gpt-3.5-turbo", + messages=[{"role": "user", "content": "Hello, world!"}], + response_model=str, +) +# <%hide%> # Clear hooks for a specific event client.clear("completion:kwargs") @@ -119,214 +149,108 @@ import openai import pydantic -def log_completion_kwargs(*args, **kwargs) -> None: - """Log the completion kwargs.""" +def log_completion_kwargs(kwargs) -> None: print("## Completion kwargs:") - #> ## Completion kwargs: + print(kwargs) """ { - 'args': (), - 'kwargs': { - 'messages': [ - { - 'role': 'user', - 'content': "Extract the user name and age from the following text: 'John is -1 years old'", - } - ], - 'model': 'gpt-3.5-turbo', - 'tools': [ - { - 'type': 'function', - 'function': { - 'name': 'User', - 'description': 'Correctly extracted `User` with all the required parameters with correct types', - 'parameters': { - 'properties': { - 'name': {'title': 'Name', 'type': 'string'}, - 'age': {'title': 'Age', 'type': 'integer'}, - }, - 'required': ['age', 'name'], - 'type': 'object', + "messages": [ + { + "role": "user", + "content": "Extract the user name and age from the following text: 'John is 20 years old'", + } + ], + "model": "gpt-4o-mini", + "tools": [ + { + "type": "function", + "function": { + "name": "User", + "description": "Correctly extracted `User` with all the required parameters with correct types", + "parameters": { + "properties": { + "name": {"title": "Name", "type": "string"}, + "age": {"title": "Age", "type": "integer"}, }, + "required": ["age", "name"], + "type": "object", }, - } - ], - 'tool_choice': {'type': 'function', 'function': {'name': 'User'}}, - }, - } - """ - print({"args": args, "kwargs": kwargs}) - """ - { - 'args': (), - 'kwargs': { - 'messages': [ - { - 'role': 'user', - 'content': "Extract the user name and age from the following text: 'John is -1 years old'", }, - { - 'role': 'assistant', - 'content': '', - 'tool_calls': [ - { - 'id': 'call_GamMbnNfWFCHPHGgZy2VxD09', - 'function': { - 'arguments': '{"name":"John","age":-1}', - 'name': 'User', - }, - 'type': 'function', - } - ], - }, - { - 'role': 'tool', - 'tool_call_id': 'call_GamMbnNfWFCHPHGgZy2VxD09', - 'name': 'User', - 'content': 'Validation Error found:\n1 validation error for User\nage\n Value error, Age cannot be negative [type=value_error, input_value=-1, input_type=int]\n For further information visit https://errors.pydantic.dev/2.8/v/value_error\nRecall the function correctly, fix the errors', - }, - ], - 'model': 'gpt-3.5-turbo', - 'tools': [ - { - 'type': 'function', - 'function': { - 'name': 'User', - 'description': 'Correctly extracted `User` with all the required parameters with correct types', - 'parameters': { - 'properties': { - 'name': {'title': 'Name', 'type': 'string'}, - 'age': {'title': 'Age', 'type': 'integer'}, - 'error_message': { - 'anyOf': [{'type': 'string'}, {'type': 'null'}], - 'default': None, - 'title': 'Error Message', - }, - }, - 'required': ['age', 'name'], - 'type': 'object', - }, - }, - } - ], - 'tool_choice': {'type': 'function', 'function': {'name': 'User'}}, - }, + } + ], + "tool_choice": {"type": "function", "function": {"name": "User"}}, } """ - #> ## Completion response: def log_completion_response(response) -> None: - """ - { - 'id': 'chatcmpl-AH1sl7JTZ37B8RrriiFBjH1n3mNVL', - 'choices': [ - { - 'finish_reason': 'stop', - 'index': 0, - 'logprobs': None, - 'message': { - 'content': None, - 'refusal': None, - 'role': 'assistant', - 'function_call': None, - 'tool_calls': [ - { - 'id': 'call_GamMbnNfWFCHPHGgZy2VxD09', - 'function': { - 'arguments': '{"name":"John","age":-1}', - 'name': 'User', - }, - 'type': 'function', - } - ], - }, - } - ], - 'created': 1728622175, - 'model': 'gpt-3.5-turbo-0125', - 'object': 'chat.completion', - 'service_tier': None, - 'system_fingerprint': None, - 'usage': { - 'completion_tokens': 9, - 'prompt_tokens': 106, - 'total_tokens': 115, - 'completion_tokens_details': {'audio_tokens': None, 'reasoning_tokens': 0}, - 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, - }, - } - """ print("## Completion response:") - #> ## Completion response: print(response.model_dump()) """ { - 'id': 'chatcmpl-AH1smoYP5X5dR7JM83lU78BQemcy1', - 'choices': [ + "id": "chatcmpl-AJHKkGTSwkxdmxBuaz69q4yCeqIZK", + "choices": [ { - 'finish_reason': 'stop', - 'index': 0, - 'logprobs': None, - 'message': { - 'content': None, - 'refusal': None, - 'role': 'assistant', - 'function_call': None, - 'tool_calls': [ + "finish_reason": "stop", + "index": 0, + "logprobs": None, + "message": { + "content": None, + "refusal": None, + "role": "assistant", + "function_call": None, + "tool_calls": [ { - 'id': 'call_VlkoWrL5PMcBd4JIR6cdqxu6', - 'function': { - 'arguments': '{"name":"John","age":1}', - 'name': 'User', + "id": "call_glxG7L23PiVLHWBT2nxvh4Vs", + "function": { + "arguments": '{"name":"John","age":20}', + "name": "User", }, - 'type': 'function', + "type": "function", } ], }, } ], - 'created': 1728622176, - 'model': 'gpt-3.5-turbo-0125', - 'object': 'chat.completion', - 'service_tier': None, - 'system_fingerprint': None, - 'usage': { - 'completion_tokens': 9, - 'prompt_tokens': 193, - 'total_tokens': 202, - 'completion_tokens_details': {'audio_tokens': None, 'reasoning_tokens': 0}, - 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, + "created": 1729158226, + "model": "gpt-4o-mini-2024-07-18", + "object": "chat.completion", + "service_tier": None, + "system_fingerprint": "fp_e2bde53e6e", + "usage": { + "completion_tokens": 9, + "prompt_tokens": 87, + "total_tokens": 96, + "completion_tokens_details": {"audio_tokens": None, "reasoning_tokens": 0}, + "prompt_tokens_details": {"audio_tokens": None, "cached_tokens": 0}, }, - } + } """ def log_completion_error(error) -> None: - """Log the completion error.""" print("## Completion error:") print({"error": error}) - #> ## Parse error: +def log_parse_error(error) -> None: + print("## Parse error:") + #> ## Parse error: + print(error) """ - {'error': 1 validation error for User + 1 validation error for User age - Value error, Age cannot be negative [type=value_error, input_value=-1, input_type=int] - For further information visit https://errors.pydantic.dev/2.8/v/value_error} + Value error, Age cannot be negative [type=value_error, input_value=-10, input_type=int] + For further information visit https://errors.pydantic.dev/2.8/v/value_error """ -def log_parse_error(error) -> None: - """Log the parse error.""" - print("## Parse error:") - print({"error": error}) # Create an Instructor client client = instructor.from_openai(openai.OpenAI()) -# Register hooks client.on("completion:kwargs", log_completion_kwargs) client.on("completion:response", log_completion_response) + client.on("completion:error", log_completion_error) client.on("parse:error", log_parse_error) @@ -343,20 +267,36 @@ class User(pydantic.BaseModel): return v -# Use the client to create a completion +try: + # Use the client to create a completion + user = client.chat.completions.create( + model="gpt-4o-mini", + messages=[ + { + "role": "user", + "content": "Extract the user name and age from the following text: 'John is -1 years old'", + } + ], + response_model=User, + max_retries=1, + ) +except Exception as e: + print(f"Error: {e}") + + user = client.chat.completions.create( - model="gpt-3.5-turbo", + model="gpt-4o-mini", messages=[ { "role": "user", - "content": "Extract the user name and age from the following text: 'John is -1 years old'", + "content": "Extract the user name and age from the following text: 'John is 10 years old'", } ], response_model=User, + max_retries=1, ) - print(user) -#> name='John' age=1 +#> name='John' age=10 ``` This example demonstrates: diff --git a/docs/concepts/multimodal.md b/docs/concepts/multimodal.md index a18dcec31..f57470f90 100644 --- a/docs/concepts/multimodal.md +++ b/docs/concepts/multimodal.md @@ -20,9 +20,25 @@ You can create an `Image` instance from a URL or file path using the `from_url` ```python import instructor import openai +from pydantic import BaseModel + + +class ImageAnalyzer(BaseModel): + description: str + -image1 = instructor.Image.from_url("https://example.com/image.jpg") -image2 = instructor.Image.from_path("path/to/image.jpg") +# <%hide%> +import requests + +url = "https://static01.nyt.com/images/2017/04/14/dining/14COOKING-RITZ-MUFFINS/14COOKING-RITZ-MUFFINS-jumbo.jpg" +response = requests.get(url) + +with open("muffin.jpg", "wb") as file: + file.write(response.content) +# <%hide%> + +image1 = instructor.Image.from_url(url) +image2 = instructor.Image.from_path("muffin.jpg") client = instructor.from_openai(openai.OpenAI()) @@ -33,6 +49,11 @@ response = client.chat.completions.create( {"role": "user", "content": ["What is in this two images?", image1, image2]} ], ) + +print(response.model_dump_json()) +""" +{"description":"A tray of blueberry muffins, some appear whole while one is partially broken showing its soft texture, all have golden-brown tops and are placed on a delicate, patterned surface."} +""" ``` The `Image` class takes care of the necessary conversions and formatting, ensuring that your code remains clean and provider-agnostic. This flexibility is particularly valuable when you're experimenting with different models or when you need to switch providers based on specific project requirements. From 651465bc22812668b1c992c7c43ee26b1c98ac40 Mon Sep 17 00:00:00 2001 From: terrchen Date: Mon, 28 Oct 2024 11:55:15 -0400 Subject: [PATCH 8/8] docs: spelling and grammar error (#1121) --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d550d26a7..0b9473781 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Instructor is the most popular Python library for working with structured output ## Want your logo on our website? -If your company use instructor a lot, we'd love to have your logo on our website! Please fill out [this form](https://q7gjsgfstrp.typeform.com/to/wluQlVVQ) +If your company uses Instructor a lot, we'd love to have your logo on our website! Please fill out [this form](https://q7gjsgfstrp.typeform.com/to/wluQlVVQ) ## Key Features @@ -235,7 +235,7 @@ client = instructor.from_gemini( ) ``` -Alternatively, you can [call Gemini from the OpenAI client](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/call-gemini-using-openai-library#python).You'll have to setup [`gcloud`](https://cloud.google.com/docs/authentication/provide-credentials-adc#local-dev), get setup on Vertex AI, and install the Google Auth library. +Alternatively, you can [call Gemini from the OpenAI client](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/call-gemini-using-openai-library#python). You'll have to setup [`gcloud`](https://cloud.google.com/docs/authentication/provide-credentials-adc#local-dev), get setup on Vertex AI, and install the Google Auth library. ```sh pip install google-auth @@ -321,7 +321,7 @@ assert resp.age == 25 ## Types are inferred correctly -This was the dream of instructor but due to the patching of openai, it wasnt possible for me to get typing to work well. Now, with the new client, we can get typing to work well! We've also added a few `create_*` methods to make it easier to create iterables and partials, and to access the original completion. +This was the dream of Instructor but due to the patching of OpenAI, it wasn't possible for me to get typing to work well. Now, with the new client, we can get typing to work well! We've also added a few `create_*` methods to make it easier to create iterables and partials, and to access the original completion. ### Calling `create` @@ -500,7 +500,7 @@ for user in users: ## [Evals](https://github.com/jxnl/instructor/tree/main/tests/llm/test_openai/evals#how-to-contribute-writing-and-running-evaluation-tests) -We invite you to contribute to evals in `pytest` as a way to monitor the quality of the OpenAI models and the `instructor` library. To get started check out the evals for [anthropic](https://github.com/jxnl/instructor/blob/main/tests/llm/test_anthropic/evals/test_simple.py) and [OpenAI](https://github.com/jxnl/instructor/tree/main/tests/llm/test_openai/evals#how-to-contribute-writing-and-running-evaluation-tests) and contribute your own evals in the form of pytest tests. These evals will be run once a week and the results will be posted. +We invite you to contribute to evals in `pytest` as a way to monitor the quality of the OpenAI models and the `instructor` library. To get started check out the evals for [Anthropic](https://github.com/jxnl/instructor/blob/main/tests/llm/test_anthropic/evals/test_simple.py) and [OpenAI](https://github.com/jxnl/instructor/tree/main/tests/llm/test_openai/evals#how-to-contribute-writing-and-running-evaluation-tests) and contribute your own evals in the form of pytest tests. These evals will be run once a week and the results will be posted. ## Contributing @@ -508,13 +508,13 @@ If you want to help, checkout some of the issues marked as `good-first-issue` or ## CLI -We also provide some added CLI functionality for easy convinience: +We also provide some added CLI functionality for easy convenience: -- `instructor jobs` : This helps with the creation of fine-tuning jobs with OpenAI. Simple use `instructor jobs create-from-file --help` to get started creating your first fine-tuned GPT3.5 model +- `instructor jobs` : This helps with the creation of fine-tuning jobs with OpenAI. Simple use `instructor jobs create-from-file --help` to get started creating your first fine-tuned GPT-3.5 model - `instructor files` : Manage your uploaded files with ease. You'll be able to create, delete and upload files all from the command line -- `instructor usage` : Instead of heading to the OpenAI site each time, you can monitor your usage from the cli and filter by date and time period. Note that usage often takes ~5-10 minutes to update from OpenAI's side +- `instructor usage` : Instead of heading to the OpenAI site each time, you can monitor your usage from the CLI and filter by date and time period. Note that usage often takes ~5-10 minutes to update from OpenAI's side ## License