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

First stab at minimal mypy implementation #738

Merged
merged 13 commits into from
Apr 12, 2024

Conversation

ryanpeach
Copy link
Contributor

@ryanpeach ryanpeach commented Apr 2, 2024

Issue: #729 #257

  • Set up the structure of mypy installs, now to start typing things
  • fixed guidance/library/_regex.py:13: SyntaxWarning: invalid escape sequence '['
  • First stab at minimal mypy implementation

This is a non-strict implementation of mypy, with cicd integrated.

After this is approved, we can either slowly move towards a strict implementation, or each PR can simply
choose how much they want/need to contribute to the typing system to help themselves understand the codebase.

@@ -739,7 +739,7 @@ def select(options: List[_T], name=None, list_append=False, recurse=False, skip_
assert not isinstance(value, RawFunction), "You cannot select between stateful functions in the current guidance implementation!"
assert not isinstance(value, types.FunctionType), "Did you pass a function without calling it to select? You need to pass the results of a called guidance function to select."
if isinstance(value, int) or isinstance(value, float):
options[i] = str(value)
options[i] = str(value) # type: ignore[assignment]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I didn't understand this, because options is type List[_T] but this is inserting a string.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I may have gotten the type wrong when I was trying to figure it out. Something like Union[List[_T], str] might be correct.

@@ -380,7 +382,7 @@ def __repr__(self, state_sets=None) -> str:
rs += "•"
else:
assert False
s += f"{rs:40} ({state.start}) {'nullable' if state.node.nullable else ''}\n"
s += f"{rs:40} ({state.start}) {'nullable' if state.node.nullable else ''}\n" # type: ignore[attr-defined]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

It thinks that node doesn't have a nullable. I couldn't find out what state was. Next person to touch this function should type it.

guidance/library/_block.py Outdated Show resolved Hide resolved
@@ -10,7 +10,7 @@
@guidance(stateless=True, dedent=False)
def regex(lm, pattern):
# find all of the brackets we'll need to negate later
nots = re.findall('\[\^(.*?)\]', pattern)
nots = re.findall(r'\[\^(.*?)\]', pattern)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was resulting in an actual error

@@ -1,17 +1,19 @@
try:
from IPython.display import clear_output, display, HTML
ipython_is_imported = True
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a much cleaner way to do dynamic import.

clear_output(wait=True)
display(HTML(self._html()))
else:
pprint(self._state)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

pprint is the best I could think of. Should fix #708

@ryanpeach
Copy link
Contributor Author

E TypeError: 'module' object is not callable

I don't think that's me.

@riedgar-ms
Copy link
Collaborator

Thank you for starting on this. I've authorised this for running in GH Actions.

@ryanpeach
Copy link
Contributor Author

@riedgar-ms can you understand why it's giving:

TypeError: 'module' object is not callable

mypy is passing and I didn't change anything like that

Copy link
Collaborator

Choose a reason for hiding this comment

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

What's the purpose of this file?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This indicates to people who are installing this library that it can be analyzed by mypy.

https://peps.python.org/pep-0561/

@riedgar-ms
Copy link
Collaborator

I'm not quite sure why that is happening. The magic that is supposed to make the module callable is:

# This makes the guidance module callable

but you haven't edited that file.

Are you able to run the tests on your own machine?

@ryanpeach
Copy link
Contributor Author

Do you have local testing instructions anywhere?

@riedgar-ms
Copy link
Collaborator

I'm not sure they're written out. You'll need the [test] extras packages, plus transformers. Then you should be able to run:

python -m pytest -m "not (needs_credentials or use_gpu or server)" tests/

@ryanpeach
Copy link
Contributor Author

Ok so it does run on main and not in this branch, so it must be something in my pr. I'll try to fix it.

@ryanpeach
Copy link
Contributor Author

ryanpeach commented Apr 10, 2024

@riedgar-ms ok fixed it. Importing from ..library._block import ContextBlock from _model creates a circular reference because __init__.py imports library. This is mostly fine except I think it makes the guidance class edits load later than the call in zero_or_more. Or something like that.

@riedgar-ms
Copy link
Collaborator

@riedgar-ms ok fixed it. Importing from ..library._block import ContextBlock from _model creates a circular reference because __init__.py imports library. This is mostly fine except I think it makes the guidance class edits load later than the call in zero_or_more. Or something like that.

I would not be averse to such a change (although perhaps not for this PR). Thoughts @Harsha-Nori ?

@ryanpeach
Copy link
Contributor Author

@riedgar-ms ok fixed it. Importing from ..library._block import ContextBlock from _model creates a circular reference because __init__.py imports library. This is mostly fine except I think it makes the guidance class edits load later than the call in zero_or_more. Or something like that.

I would not be averse to such a change (although perhaps not for this PR). Thoughts @Harsha-Nori ?

Oh I edited the comment to not include the suggestion about the from guidance import guidance api change. But I've also already got a PR ready after this one for consideration to that end. It should be backwards compatible.

@codecov-commenter
Copy link

codecov-commenter commented Apr 10, 2024

Codecov Report

Attention: Patch coverage is 65.85366% with 14 lines in your changes are missing coverage. Please review.

Project coverage is 65.55%. Comparing base (c366498) to head (2106a87).

Files Patch % Lines
guidance/models/_model.py 68.18% 7 Missing ⚠️
guidance/_parser.py 0.00% 4 Missing ⚠️
guidance/_grammar.py 87.50% 1 Missing ⚠️
guidance/_utils.py 0.00% 1 Missing ⚠️
guidance/models/_azure_openai.py 50.00% 1 Missing ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #738      +/-   ##
==========================================
- Coverage   69.69%   65.55%   -4.15%     
==========================================
  Files          54       54              
  Lines        4029     4038       +9     
==========================================
- Hits         2808     2647     -161     
- Misses       1221     1391     +170     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@Harsha-Nori
Copy link
Collaborator

@riedgar-ms ok fixed it. Importing from ..library._block import ContextBlock from _model creates a circular reference because __init__.py imports library. This is mostly fine except I think it makes the guidance class edits load later than the call in zero_or_more. Or something like that.

I would not be averse to such a change (although perhaps not for this PR). Thoughts @Harsha-Nori ?

Oh I edited the comment to not include the suggestion about the from guidance import guidance api change. But I've also already got a PR ready after this one for consideration to that end. It should be backwards compatible.

I generally like of how simple/clean "import guidance" being used for the decorator looks, but I appreciate that it causes some complexity in the developer onboarding here. I could definitely be persuaded against it but agree that we should discuss it in a separate issue/PR in more detail.

The mypy typing infrastructure looks great, and I appreciate the incremental approach you've taken here @ryanpeach! Happy to do a full review once the tests finish running (which it seems like they will). Thanks for the great contribution!

Copy link
Collaborator

@riedgar-ms riedgar-ms left a comment

Choose a reason for hiding this comment

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

I'm OK with this.... @Harsha-Nori ?

.github/workflows/qa_tests.yml Outdated Show resolved Hide resolved
python-version: 3.8
- name: Install mypy
run: pip install mypy
- uses: tsuyoshicho/action-mypy@v4
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should this be producing a comment on the PR? Or does that only happen if there's an error?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It should if there's an error, but I realize it's hard to test prior to release

@ryanpeach
Copy link
Contributor Author

Anyway you can just run the qa_tests to see if my latest commit fixes the last commits problem?

@ryanpeach
Copy link
Contributor Author

ryanpeach commented Apr 12, 2024

I assume the reason you manually run workflows is some of them cost money? We should make it so some workflows run on approval/workflow_dispatch and others run on push.

@riedgar-ms
Copy link
Collaborator

Cost is a reason; as is keeping secrets secret. There is some GH security setting we have on that means that external contributions need a member of the repo to approve before things run.

@ryanpeach
Copy link
Contributor Author

Ok let me work on this at ryanpeach#1 since this custom action is behaving oddly

@ryanpeach
Copy link
Contributor Author

@riedgar-ms ok now it works in my PR to my own repo.

@ryanpeach
Copy link
Contributor Author

Ready. Also rebased so that it should have a linear history.

@ryanpeach
Copy link
Contributor Author

Passed, except one got canceled somehow, resulting in a red X.

@Harsha-Nori Harsha-Nori merged commit 5c9776e into guidance-ai:main Apr 12, 2024
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

4 participants