Skip to content

Cleanup of legacy model code - Part 1#1598

Merged
dadmobile merged 54 commits intomainfrom
fix/model_api_cleanup
Mar 26, 2026
Merged

Cleanup of legacy model code - Part 1#1598
dadmobile merged 54 commits intomainfrom
fix/model_api_cleanup

Conversation

@dadmobile
Copy link
Copy Markdown
Member

@dadmobile dadmobile commented Mar 20, 2026

Step 1 of big cleanup of code for handling models in the API.

There is a lot but this should be mostly safe as it's primarily just deleting and moving things into the right place.

Remove:

  • importing models
  • downloading models
  • provenance building and listing

Reorganize:

  • create a model_service
  • kill all the weird legacy basemodel and subclasses from transformerlab/models directory
  • move any remaining required services from router

Added model_service test: this almost certainly tests conditions we don't support now, but will clean that up with the final model_service and router clean up in part 2. (Makes changing things easier)

@sentry
Copy link
Copy Markdown

sentry bot commented Mar 20, 2026

Codecov Report

❌ Patch coverage is 57.77778% with 38 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
api/transformerlab/services/model_service.py 61.03% 26 Missing and 4 partials ⚠️
api/transformerlab/routers/model.py 38.46% 8 Missing ⚠️

📢 Thoughts on this report? Let us know!

@dadmobile dadmobile changed the title DRAFT: Cleanup of legacy model code Cleanup of legacy model code - Part 1 Mar 24, 2026
@dadmobile
Copy link
Copy Markdown
Member Author

Will write a test for model list and then undraft this.

@dadmobile dadmobile marked this pull request as ready for review March 25, 2026 15:50
@aliasaria
Copy link
Copy Markdown
Member

Code Review

Review Summary

This PR removes ~2,000 lines of legacy model management code (class hierarchy, unused endpoints, import modals) and replaces the core list_installed_models logic with a new service layer function. The cleanup is well-motivated and the deletion is clean. The new model_service.py has one real bug and several complexity/robustness issues worth addressing before merge.


Must Fix (blocks merge)

  • [Correctness] Mutating a list while iterating over it skips entriesmodel_service.py:34-39: The for model in models loop calls models.remove(model) inside the loop body. This is a classic Python bug — removing from a list during for iteration causes the iterator to skip the next element. If two bad entries are adjacent, the second one won't be filtered.

    Fix: filter before iterating, or build a new list:

    models = await ModelService.list_all()
    models = [m for m in models if m and m != {} and m != ""]
    
    models_dir = await get_models_dir()
    for model in models:
        # ... rest of the logic, no need for the remove/continue block

Should Fix (important but not blocking)

  • [Correctness] embedding parameter dropped silentlymodel.py:29-31: model_local_list still accepts embedding=False and uses it in the cache key (models:list:{embedding}), but model_service.list_installed_models() no longer accepts or uses it. This means the embedding=True and embedding=False cache entries will return identical results, and any caller expecting filtered results gets unfiltered data. Either pass embedding through to the service and filter, or remove the parameter from the endpoint and cache key.

  • [Correctness] model_local_delete shadows imported model_service modulemodel.py:68: Inside model_local_delete, the line model_service = await ModelService.get(model_id) shadows the module-level from transformerlab.services import model_service. This means the model_service.delete_model_from_hf_cache(model_id) call on line 107 will call .delete_model_from_hf_cache() on the ModelService instance (SDK object), not the service module — which will likely raise AttributeError at runtime. Rename the local variable:

    model_obj = await ModelService.get(model_id)
    model_dir = await model_obj.get_dir()
  • [Maintainability] model_local_create and get_pipeline_tag also shadow model_service — Same pattern at model.py:54 and model.py:192. While these don't reach the shadowed module later in the same function, it's confusing and fragile. Use model_obj or model_instance consistently.


Consider Improving

  1. GGUF path resolution is deeply nested and hard to followmodel_service.py:94-131 has 4+ levels of nesting with repeated .gguf filtering logic. Consider extracting a helper like resolve_gguf_path(base_path, model_filename) to make intent clearer.

  2. Dead code: self-assignmentmodel_service.py:93 (model["local_path"] = model["local_path"]) and line 137 are no-ops. Remove the if branch or just use pass to make the intent explicit.

  3. cache_dir type hintmodel_service.py:142: Use str | None = None instead of str = None per the project's type hint convention.


What's Working Well

  1. Clean separation into service layer — Moving list_installed_models and delete_model_from_hf_cache into model_service.py follows the project's service pattern convention and keeps the router thin.

  2. Thorough test coverage for the new service — The 8 test cases in test_model_service.py cover empty lists, bad entries, HF vs non-HF models, directory vs file models, and edge cases like model_filename=".". Good use of monkeypatch and parametrize.

  3. Aggressive removal of dead code — Deleting 2,000+ lines across the legacy model class hierarchy, unused endpoints, and the frontend ImportModelsModal is a significant cleanup that reduces maintenance burden.

  4. Proper use of logging instead of print — The new service uses logger.info/logger.debug instead of bare print() statements.

@dadmobile
Copy link
Copy Markdown
Member Author

Re: code review comments:

  • I can fix the embedding thing now. Was goign to do in next PR. It's not used by the app anymore
  • I will fix the model_service naming thing. THis is because for some reason we call the Lab SDK import model service as well, which I think we shouldn't have...but I'm not going to change that in this PR.
  • I will look at the "Must Fix" error it mentioned although I just copied that code from before so it's no worse than it was previously

The rest I think isn't worse than before and I think will get cleaned up anyways on next pass.

@dadmobile
Copy link
Copy Markdown
Member Author

OK fixed all of the stuff I said above (all Must Fix and Should Fix).
As mentioned, I believe the Consider Improving will get cleaned up on the next step.

@dadmobile dadmobile requested a review from aliasaria March 26, 2026 18:56
@dadmobile dadmobile merged commit 9614e69 into main Mar 26, 2026
12 checks passed
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.

3 participants