Skip to content

Conversation

@ghukill
Copy link
Collaborator

@ghukill ghukill commented Jan 8, 2026

Purpose and background context

This PR updates how the CLI is invoked inside the Docker container.

A recent PR removed the following lines from the cli.py:

if __name__ == "__main__":  # pragma: no cover
    logger = logging.getLogger("embeddings.main")
    main()

This approach was not ideal to begin with, but allowed invoking the CLI inside the Docker container with python -m embeddings.cli given it would default to this __main__ behavior.

Invoking the Docker container had no output, but was returning a valid zero exit code. This made this very easy to miss; I missed both during code review and working with the CLI locally (likely worth a test case of its own somehow, but out of scope here).

On a positive note, this provided an opportunity to refine how we call click CLI applications with uv.

Locally, we utilize a pattern like uv run embeddings, relying on embeddings being an available script in the uv virtual environment courtesy of this block in pyproject.toml:

[project.scripts]
embeddings = "embeddings.cli:main"

Turns out, we can use this embeddings script / callable in the Docker context as well. The key was adding PYTHONPATH=/app which ensures that the globally installed script /usr/local/bin/embeddings will have a working directory of /app where the embeddings module actually exists.

How can a reviewer manually see the effects of these changes?

1- Build the docker image:

make docker-build

2- Note the updated entrypoint for the Dockerfile:

ENTRYPOINT ["embeddings"]

3- Run the docker container, relying on the entrypoint, and testing the loading of the model:

docker run -it timdex-embeddings:latest --verbose test-model-load

Output:

2026-01-08 15:47:15,307 INFO embeddings.cli.main() line 44: Logger 'root' configured with level=WARNING
2026-01-08 15:47:15,307 INFO embeddings.cli.main() line 45: No Sentry DSN found, exceptions will not be sent to Sentry
2026-01-08 15:47:15,307 INFO embeddings.cli.main() line 46: Running process
2026-01-08 15:47:15,308 INFO embeddings.cli.wrapper() line 97: Embedding class 'OSNeuralSparseDocV3GTE' initialized from model URI 'opensearch-project/opensearch-neural-sparse-encoding-doc-v3-gte'.
2026-01-08 15:47:15,308 INFO embeddings.models.os_neural_sparse_doc_v3_gte.load() line 134: Loading model from: /model
2026-01-08 15:47:15,521 INFO embeddings.models.os_neural_sparse_doc_v3_gte.load() line 147: Model loaded successfully, 0.21s
OK
2026-01-08 15:47:15,522 INFO embeddings.cli._log_command_elapsed_time() line 50: Total time to complete process: 0:00:00.214758

Includes new or updated dependencies?

YES

  • picks up new TDA version

Changes expectations for external applications?

YES: Docker image has a valid entrypoint, unblocking some AWS Batch testing

What are the relevant tickets?

Code review

  • Code review best practices are documented here and you are encouraged to have a constructive dialogue with your reviewers about their preferences and expectations.

Why these changes are being introduced:

A subtle bug had crept in from some recent changes where the Docker
entrypoint of `python -m embeddings.cli` was not erroring, but it was not
actually invoking anything.   This was because a `if __name__ == "main"` was
removed from the cli.py file.

This had the positive side effect of revisiting how we invoke the CLI
with uv, exposing a way we could use the uv script `embeddings` which
is installed in the Docker container.

How this addresses that need:

Instead of calling `python -m embeddings.cli`, relying on __main__ behavior,
we can call the `embeddings` script that is installed both locally in the
uv virtual environment and in the Docker container at /usr/local/bin/embeddings.

Side effects of this change:
* Fixes a Docker container that was returning a zero exit code, but
doing nothing.

Relevant ticket(s):
* https://mitlibraries.atlassian.net/browse/USE-213
  * discovered while working on some spike deployments for this ticket
@ghukill ghukill requested a review from a team January 8, 2026 15:48
@jonavellecuerdo jonavellecuerdo self-assigned this Jan 9, 2026
@jonavellecuerdo
Copy link
Contributor

Hmm, where does the app/ folder come from -- as in is it just a folder uv searches for? 🤔 Asking out of curiosity!

@ghukill
Copy link
Collaborator Author

ghukill commented Jan 9, 2026

Hmm, where does the app/ folder come from -- as in is it just a folder uv searches for? 🤔 Asking out of curiosity!

It's created as part of the Dockerfile here: https://github.com/MITLibraries/timdex-embeddings/blob/USE-213-uv-cli-invocation/Dockerfile#L10.

In effect, it's where all files are copied to in th rest of the Dockerfile if not explicitly changed or the current working directory changed.

@jonavellecuerdo
Copy link
Contributor

Ah, thanks for clarifying! When reviewing "Files changed", I sometimes forget the Expand up option exists. 😅 Approved!

@ehanson8 ehanson8 self-assigned this Jan 9, 2026
Copy link

@ehanson8 ehanson8 left a comment

Choose a reason for hiding this comment

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

Good approach to standardize on as our uv practices evolve!

@ghukill ghukill merged commit b892703 into main Jan 9, 2026
4 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.

4 participants