-
-
Notifications
You must be signed in to change notification settings - Fork 732
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
Add coveralls #203
Add coveralls #203
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,8 @@ jobs: | |
steps: | ||
- uses: actions/checkout@v2 | ||
|
||
|
||
|
||
- name: Set up Python ${{ matrix.python-version }} | ||
uses: actions/setup-python@v4 | ||
with: | ||
|
@@ -27,7 +29,15 @@ jobs: | |
- name: Install dependencies | ||
run: poetry install --with dev | ||
|
||
- name: Run test | ||
run: poetry run pytest tests/ | ||
- name: Run tests with coverage | ||
run: | | ||
poetry run coverage run -m pytest tests/ | ||
poetry run coverage report | ||
poetry run coverage html | ||
env: | ||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | ||
|
||
- name: Coveralls GitHub Action | ||
uses: coverallsapp/[email protected] | ||
with: | ||
github-token: ${{ secrets.GITHUB_TOKEN }} |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,49 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import time | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from typing import Iterable | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from openai import OpenAI | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from pydantic import BaseModel | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import instructor | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
client = instructor.patch(OpenAI()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class User(BaseModel): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
name: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
age: int | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def test_multi_user(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def stream_extract(input: str, cls) -> Iterable[User]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MultiUser = instructor.MultiTask(cls) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
completion = client.chat.completions.create( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
model="gpt-3.5-turbo", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stream=True, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
functions=[MultiUser.openai_schema], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
function_call={"name": MultiUser.openai_schema["name"]}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
messages=[ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"role": "system", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"content": "You are a perfect entity extraction system", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"role": "user", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"content": ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f"Consider the data below:\n{input}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"Correctly segment it into entitites" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"Make sure the JSON is correct" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
max_tokens=1000, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return MultiUser.from_streaming_response(completion) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
resp = [user for user in stream_extract(input="Jason is 20, Sarah is 30", cls=User)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
assert len(resp) == 2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
assert resp[0].name == "Jason" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
assert resp[0].age == 20 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
assert resp[1].name == "Sarah" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
assert resp[1].age == 30 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+18
to
+49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The test function - "content": (
- f"Consider the data below:\n{input}"
- "Correctly segment it into entitites"
- "Make sure the JSON is correct"
+ "content": (
+ f"Consider the data below:\n{input} "
+ "Correctly segment it into entities. "
+ "Make sure the JSON is correct."
), Commitable suggestion
Suggested change
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import pytest | ||
import instructor | ||
|
||
from instructor import llm_validator | ||
from typing_extensions import Annotated | ||
from pydantic import field_validator, BaseModel, BeforeValidator, ValidationError | ||
from openai import OpenAI, AsyncOpenAI | ||
|
||
client = instructor.patch(OpenAI()) | ||
aclient = instructor.patch(AsyncOpenAI()) | ||
|
||
|
||
class UserExtract(BaseModel): | ||
name: str | ||
age: int | ||
|
||
@field_validator("name") | ||
@classmethod | ||
def validate_name(cls, v): | ||
if v.upper() != v: | ||
raise ValueError("Name should be uppercase") | ||
return v | ||
|
||
|
||
def test_runmodel_validator(): | ||
model = client.chat.completions.create( | ||
model="gpt-3.5-turbo", | ||
response_model=UserExtract, | ||
max_retries=2, | ||
messages=[ | ||
{"role": "user", "content": "Extract jason is 25 years old"}, | ||
], | ||
) | ||
assert isinstance(model, UserExtract), "Should be instance of UserExtract" | ||
assert model.name == "JASON" | ||
assert hasattr( | ||
model, "_raw_response" | ||
), "The raw response should be available from OpenAI" | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_runmodel_async_validator(): | ||
model = await aclient.chat.completions.create( | ||
model="gpt-3.5-turbo", | ||
response_model=UserExtract, | ||
max_retries=2, | ||
messages=[ | ||
{"role": "user", "content": "Extract jason is 25 years old"}, | ||
], | ||
) | ||
assert isinstance(model, UserExtract), "Should be instance of UserExtract" | ||
assert model.name == "JASON" | ||
assert hasattr( | ||
model, "_raw_response" | ||
), "The raw response should be available from OpenAI" | ||
|
||
|
||
class UserExtractSimple(BaseModel): | ||
name: str | ||
age: int | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_async_runmodel(): | ||
model = await aclient.chat.completions.create( | ||
model="gpt-3.5-turbo", | ||
response_model=UserExtractSimple, | ||
messages=[ | ||
{"role": "user", "content": "Extract jason is 25 years old"}, | ||
], | ||
) | ||
assert isinstance( | ||
model, UserExtractSimple | ||
), "Should be instance of UserExtractSimple" | ||
assert model.name.lower() == "jason" | ||
assert hasattr( | ||
model, "_raw_response" | ||
), "The raw response should be available from OpenAI" | ||
|
||
|
||
def test_runmodel(): | ||
model = client.chat.completions.create( | ||
model="gpt-3.5-turbo", | ||
response_model=UserExtractSimple, | ||
messages=[ | ||
{"role": "user", "content": "Extract jason is 25 years old"}, | ||
], | ||
) | ||
assert isinstance( | ||
model, UserExtractSimple | ||
), "Should be instance of UserExtractSimple" | ||
assert model.name.lower() == "jason" | ||
assert hasattr( | ||
model, "_raw_response" | ||
), "The raw response should be available from OpenAI" | ||
|
||
|
||
def test_runmodel_validator_error(): | ||
class QuestionAnswerNoEvil(BaseModel): | ||
question: str | ||
answer: Annotated[ | ||
str, | ||
BeforeValidator( | ||
llm_validator("don't say objectionable things", openai_client=client) | ||
), | ||
] | ||
|
||
with pytest.raises(ValidationError): | ||
QuestionAnswerNoEvil( | ||
question="What is the meaning of life?", | ||
answer="The meaning of life is to be evil and steal", | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
client
variable is created outside of any function or class scope. This could potentially lead to issues with state management if theclient
is used concurrently in a multi-threaded or asynchronous environment. Consider moving the instantiation of theclient
into a setup function or within the test function itself to ensure that each test has a clean state.