-
-
Notifications
You must be signed in to change notification settings - Fork 229
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
refactor: group all provider/model related logic into llm
directory
#254
Conversation
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.
❌ Changes requested. Reviewed everything up to da39f7f in 1 minute and 18 seconds
More details
- Looked at
761
lines of code in15
files - Skipped
0
files when reviewing. - Skipped posting
1
drafted comments based on config settings.
1. gptme/providers/llm_openai.py:40
- Draft comment:
supports_streaming
is defined as a method but used as a property inchat.py
. Consider changing it to a property or updating its usage. - Reason this comment was not posted:
Decided after close inspection that this draft comment was likely wrong and/or not actionable:
The comment is speculative and refers to a file not included in the diff. It does not provide strong evidence of an issue within the changes made in this diff. The comment is not actionable based on the information provided.
I might be missing the context of howsupports_streaming
is used elsewhere, but the comment should focus on the changes in this diff. Without seeingchat.py
, it's hard to verify the comment's validity.
The comment should be removed because it does not pertain to the changes in this diff and lacks strong evidence of an issue.
Remove the comment as it is speculative and not directly related to the changes in the diff.
Workflow ID: wflow_2xJEjSzRQfTUnaWF
Want Ellipsis to fix these issues? Tag @ellipsis-dev
in a comment. You can customize Ellipsis with 👍 / 👎 feedback, review rules, user-specific overrides, quiet
mode, and more.
da39f7f
to
13db6a5
Compare
provider
directoryproviders
directory
0c1ffbc
to
12a9067
Compare
gptme/providers/manager.py
Outdated
|
||
|
||
@dataclass() | ||
class ModelManager: |
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.
Why not just use ModelMeta?
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.
I wanted to change less code but happy to implement it use ModelMeta directly, what do you think of it now?
gptme/message.py
Outdated
file_content = get_model().manager.prepare_file(media_type, data) | ||
if file_content: | ||
content.append(file_content) |
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.
This is not valid, you cannot rely on get_model()
returning the correct model for a given call to to_dict
or _content_files_list
.
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.
To be fair, I knew you would notice that 😄. As I said in PR description it's more like a POC for now, but yeah I noticed that there are a few places where the logic is a bit different. Could we consider to return a " fake model" in these situations? May be you could give me more details to help me understand why we can't always use get_model() so that I can come up with a solution for that as well? I think it a good idea to have something consistent throughout the code.
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.
Left some comments about this on the rest of the PR, we can make it work!
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.
Overall, I don't think these changes make much sense. You seem to have underestimated things, as you cannot just use get_model
everywhere.
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.
❌ Changes requested. Reviewed everything up to 12a9067 in 1 minute and 7 seconds
More details
- Looked at
626
lines of code in16
files - Skipped
0
files when reviewing. - Skipped posting
1
drafted comments based on config settings.
1. gptme/providers/llm_openai.py:35
- Draft comment:
Consider moving the_prep_o1
logic into theOpenaiModelManager
class to encapsulate model-specific message preparation logic. - Reason this comment was not posted:
Confidence changes required:50%
The refactoring introduces a newModelManager
concept and moves model/provider-specific logic into theproviders
directory. This is a good step towards modularizing the code. However, there are some issues with the streaming logic inllm_openai.py
. The_prep_o1
function is used to prepare messages for OpenAI O1 models, which do not support the system role. This logic should be encapsulated within theModelManager
for OpenAI models.
Workflow ID: wflow_eHUd39kJaQYewjKF
Want Ellipsis to fix these issues? Tag @ellipsis-dev
in a comment. You can customize Ellipsis with 👍 / 👎 feedback, review rules, user-specific overrides, quiet
mode, and more.
gptme/chat.py
Outdated
@@ -56,8 +56,12 @@ def chat( | |||
# init | |||
init(model, interactive, tool_allowlist) | |||
|
|||
if model and model.startswith("openai/o1") and stream: | |||
logger.info("Disabled streaming for OpenAI's O1 (not supported)") | |||
if get_model().manager.supports_streaming and stream: |
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 condition here seems incorrect. It should check if streaming is NOT supported to disable it.
if get_model().manager.supports_streaming and stream: | |
if not get_model().manager.supports_streaming and stream: |
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.
Good catch. fixed.
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.
Overall, I don't think these changes make much sense. You seem to have underestimated things, as you cannot just use get_model everywhere.
The idea behind my changes is to establish a clear separation between provider/model-specific code and the rest. This would help contributors easily identify where they can add provider/model-specific code and where they shouldn't. I'm confident we can find a solution that aligns both with your vision and the changes I've proposed. Wouldn't it be beneficial to remove all these scattered specific codes and improve encapsulation?
I may have underestimated some aspects, given that I don't know the codebase and all its branches as well as you do. However, I'm eager to work on this because I truly believe it would enhance the readability and maintainability of the code in the long term.
gptme/chat.py
Outdated
@@ -56,8 +56,12 @@ def chat( | |||
# init | |||
init(model, interactive, tool_allowlist) | |||
|
|||
if model and model.startswith("openai/o1") and stream: | |||
logger.info("Disabled streaming for OpenAI's O1 (not supported)") | |||
if get_model().manager.supports_streaming and stream: |
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.
Good catch. fixed.
gptme/providers/manager.py
Outdated
|
||
|
||
@dataclass() | ||
class ModelManager: |
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.
I wanted to change less code but happy to implement it use ModelMeta directly, what do you think of it now?
gptme/message.py
Outdated
file_content = get_model().manager.prepare_file(media_type, data) | ||
if file_content: | ||
content.append(file_content) |
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.
To be fair, I knew you would notice that 😄. As I said in PR description it's more like a POC for now, but yeah I noticed that there are a few places where the logic is a bit different. Could we consider to return a " fake model" in these situations? May be you could give me more details to help me understand why we can't always use get_model() so that I can come up with a solution for that as well? I think it a good idea to have something consistent throughout the code.
9c4298b
to
7770a71
Compare
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.
Alright, I like that a lot better!
A few ideas on how we can get this merged, it will really be an improvement and I appreciate your efforts.
Sorry if I was grumpy before, I've been sick this week.
gptme/message.py
Outdated
file_content = get_model().manager.prepare_file(media_type, data) | ||
if file_content: | ||
content.append(file_content) |
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.
Left some comments about this on the rest of the PR, we can make it work!
7770a71
to
1f4b338
Compare
Hey @ErikBjare I think we are going in the right direction 🚀 . I applied your suggestions and it's much better and it makes a lot of sense. I hope I understood everything. My only doubt is about the code duplication in the file handling in each providers. We could do something, but I'm not sure it's necessary/a good idea. Let me know what you think. Same as before, it's not polished, i think one test is failing but I'll fix that when I'm sure what I've done is ok with you.
Sure, no problem. Happy to help. |
5d85bff
to
22be8eb
Compare
providers
directoryllm
directory
- Add 'unknown' as valid provider type in ModelMeta - Handle missing 'files' key in Anthropic message dict - Organize imports and improve type hints
- Fix: Remove 'files' field from message dict in anthropic provider - Refactor: Extract file processing logic in both providers - Split handle_files into smaller functions - Make internal functions private with underscore prefix - Improve code organization and readability
9d2f1fe
to
b4bc091
Compare
Rebased and force pushed. Typechecks and tests passing locally 🎉 |
Going to go ahead and merge this, I'll fix any remaining issues in follow-up PRs. Thanks a lot for pulling through with this @jrmi! 💪 You dropped this: 👑 |
llm
directoryllm
directory
This is a work in progress version of the refactoring I suggested. It's not well tested yet and there are probably a few regressions here and there but I wanted to show you the idea before going further.
I've introduced the concept of
ModelManager
. There is one implementation per API and they deal with the small differences we can have between model. The manager is instantiated with the model so it's available everywhere.The idea is that everything that is specific to a model or a provider should be in the provider directory.
Let me know what you think.
Important
Refactor codebase by moving provider/model logic to
providers
directory and introducingModelManager
for model-specific operations.providers
directory.ModelManager
for handling model-specific logic, instantiated with the model.chat.py
,commands.py
,init.py
,message.py
,reduce.py
,server/api.py
,tools/chats.py
,tools/youtube.py
, andtest_server.py
to reflect new directory structure.supports_file
andsupports_streaming
properties toModelManager
.prepare_file
method inAnthropicModelManager
andOpenaiModelManager
for handling file preparation.llm.py
,llm_anthropic.py
, andllm_openai.py
to useModelManager
for model-specific operations.get_model()
usage across various files to utilize the newModelManager
structure.This description was created by
for 12a9067. It will automatically update as commits are pushed.