Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add coveralls #203

Merged
merged 5 commits into from
Nov 20, 2023
Merged

Add coveralls #203

merged 5 commits into from
Nov 20, 2023

Conversation

jxnl
Copy link
Owner

@jxnl jxnl commented Nov 20, 2023

Summary by CodeRabbit

  • New Features

    • Integrated test coverage reporting with Coveralls to enhance code quality insights.
    • Added a new badge in the README for displaying test coverage status.
  • Refactor

    • Simplified error handling in the extract_json method for better code readability.
  • Tests

    • Introduced new test functions to validate the interaction with OpenAI's GPT-3.5 model and entity extraction.
    • Added validation logic and custom validators in test modules to ensure data integrity.
  • Documentation

    • Updated documentation to reflect the presence of "response_model" in override docs.
  • Chores

    • Configured GitHub Actions to include test coverage in the continuous integration process.

Copy link
Contributor

coderabbitai bot commented Nov 20, 2023

Warning

Rate Limit Exceeded

@jxnl has exceeded the limit for the number of files or commits that can be reviewed per hour. Please wait 0 minutes and 49 seconds before requesting another review.

How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.
Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.
Please see our FAQ for further information.

Commits Files that changed from the base of the PR and between 56cc9ed and 469abec.

Walkthrough

The project has integrated test coverage reporting with Coveralls and updated its testing suite to include new tests and improve existing ones. The changes enhance code quality by simplifying error handling, adding validation logic, and adapting to asynchronous functions. Additionally, the documentation has been updated to reflect these changes.

Changes

File Path Change Summary
.github/workflows/test.yml Added step for test coverage using Poetry and Coveralls integration.
README.md Introduced Coveralls test coverage status badge.
instructor/dsl/multitask.py
tests/openai/test_multitask.py
Simplified error handling with try-except; added new multitasking test function.
tests/openai/test_patch.py
tests/test_patch.py
Added new classes and test functions; removed outdated tests; added async functionality and validation logic.

🐇 In the code's woven warren, coverage weaves its thread, 🧵
As autumn leaves 🍂 doth fall, our tests now fully spread.
With each assert and patch, our code becomes more keen,
In the dance of bytes and bits, a more robust scene. 🍃


Tips

Chat with CodeRabbit Bot (@coderabbitai)

  • If you reply to a review comment from CodeRabbit, the bot will automatically respond.
  • To engage with CodeRabbit bot directly around the specific lines of code in the PR, mention @coderabbitai in your review comment
  • Note: Review comments are made on code diffs or files, not on the PR overview.
  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Note: For conversation with the bot, please use the review comments on code diffs or files.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.v2.json

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 5d04684 and 1f01a77.
Files ignored due to filter (2)
  • poetry.lock
  • pyproject.toml
Files selected for processing (2)
  • .github/workflows/test.yml (2 hunks)
  • README.md (1 hunks)
Files skipped from review due to trivial changes (1)
  • README.md
Additional comments: 2
.github/workflows/test.yml (2)
  • 16-23: The checkout step and the setup for Python are correctly configured. However, it's important to ensure that the actions/checkout and actions/setup-python versions are compatible with the rest of the workflow and that they are the most stable versions available at the time of the pull request.

  • 29-43: The addition of the Coveralls integration is well implemented. The steps to install dependencies, run tests with coverage, and then report the coverage to Coveralls are correctly sequenced. However, it is crucial to ensure that the OPENAI_API_KEY is only used if necessary for the tests and that it is securely stored as a secret. Additionally, verify that the coverallsapp/github-action version is the most stable and appropriate for the project's needs.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 3

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 1f01a77 and 56cc9ed.
Files selected for processing (4)
  • instructor/dsl/multitask.py (1 hunks)
  • tests/openai/test_multitask.py (1 hunks)
  • tests/openai/test_patch.py (1 hunks)
  • tests/test_patch.py (2 hunks)
Files skipped from review due to trivial changes (1)
  • instructor/dsl/multitask.py
Additional comments: 2
tests/test_patch.py (1)
  • 2-14: The removal of imports and function calls related to instructor.patch, is_async, and wrap_chatcompletion suggests that these are no longer used in this file. Verify that these changes do not affect other parts of the code that may rely on these imports and functions. If these are indeed no longer needed, the removal is a good step towards simplifying the codebase and avoiding unused imports.
tests/openai/test_patch.py (1)
  • 1-108: The integration of the Coveralls service and the updates to the testing suite are significant improvements to the project. However, there are a few points to consider:
  • Ensure that the new dependencies, such as pytest, instructor, and pydantic, are properly added to the project's dependency management files (e.g., requirements.txt or pyproject.toml for Poetry).
  • Verify that the new test cases cover the expected functionality and that they pass consistently. It's important to ensure that the tests are reliable and not flaky.
  • The use of field_validator and BeforeValidator for input validation is a good practice, but ensure that all edge cases are covered in the tests.
  • The use of async functions in the tests is appropriate given the asynchronous nature of the AsyncOpenAI client. Ensure that the async tests are properly marked with @pytest.mark.asyncio and that they are awaited during execution.
  • The custom validator llm_validator is used to prevent objectionable content. Verify that this validator is thoroughly tested and that it effectively blocks the specified content.
  • The error handling in the tests appears to be correct, with the use of pytest.raises to check for expected exceptions.

Overall, the changes seem to be well thought out and should contribute positively to the project's code quality and maintainability.

Comment on lines 63 to 68

assert is_async(wrapped_function) is True


@pytest.mark.asyncio
async def test_async_runmodel_validator():
aclient = instructor.apatch(AsyncOpenAI())
from pydantic import field_validator

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

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"


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",
) No newline at end of file
def test_override_docs():
assert "response_model" in OVERRIDE_DOCS, "response_model should be in OVERRIDE_DOCS"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The addition of test_override_docs is a good practice to ensure that the OVERRIDE_DOCS dictionary contains the expected keys. However, it would be beneficial to also test the value associated with "response_model" to ensure it meets the expected criteria, not just the presence of the key.

Comment on lines +10 to +11
client = instructor.patch(OpenAI())

Copy link
Contributor

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 the client is used concurrently in a multi-threaded or asynchronous environment. Consider moving the instantiation of the client into a setup function or within the test function itself to ensure that each test has a clean state.

Comment on lines +16 to +47
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test function test_multi_user is well-structured and seems to correctly test the functionality of the instructor.MultiTask decorator with the OpenAI model. However, there is a potential issue with the string concatenation in lines 31-34. The lines are missing a space or a newline character between sentences, which could lead to incorrect input being sent to the OpenAI model. This should be corrected to ensure the input string is formatted as intended.

- "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

[!IMPORTANT]
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
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
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 entities. "
"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

@jxnl jxnl merged commit 2d06f5a into main Nov 20, 2023
7 of 8 checks passed
@jxnl jxnl deleted the add-coveralls branch November 20, 2023 02:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant