Repository: Davidyz/VectorCode

Issue:
[BUG] doc says to install vectorcode via pipx but logger error says to use pip install for optimum
**Describe the bug**
I follow the doc and installs via pipx vectorcode.
I see vectorcode is crazy slow (40 seconds each request) so I enabled openvivo (I have amd but it works on CPU AMD acceleration, but not GPU) (I also have WSL but it should still work).
It then reads "Exception: Using the OpenVINO backend requires installing Optimum and OpenVINO. You can in
stall them with pip: `pip install optimum[openvino]`"
I do pip install (very slow, huge package) but still doesn't work. After long time realized pipx's installed pacakge can't access outside world by default (need special commands). 

**Expected behavior**
Either instead of logging an error saying pip install ... you log error with something akin to https://stackoverflow.com/a/79260177/5496376
or you just don't tell people to use pipx

**System Information:**

Ubuntu WSL 2 WIndows 11
It's more about python than anything else tho


Discussion:
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/Davidyz/VectorCode/pull/49?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Davidyz) Report
Attention: Patch coverage is `20.00000%` with `4 lines` in your changes missing coverage. Please review.
> Project coverage is 97.23%. Comparing base [(`43df44c`)](https://app.codecov.io/gh/Davidyz/VectorCode/commit/43df44ccf8bc43c1f0e9b0685bfdd8bf7446b3bd?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Davidyz) to head [(`21df99b`)](https://app.codecov.io/gh/Davidyz/VectorCode/commit/21df99b4dbf5b59809e3f787d66fa6502cdd8f2a?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Davidyz).

| [Files with missing lines](https://app.codecov.io/gh/Davidyz/VectorCode/pull/49?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Davidyz) | Patch % | Lines |
|---|---|---|
| [src/vectorcode/common.py](https://app.codecov.io/gh/Davidyz/VectorCode/pull/49?src=pr&el=tree&filepath=src%2Fvectorcode%2Fcommon.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Davidyz#diff-c3JjL3ZlY3RvcmNvZGUvY29tbW9uLnB5) | 20.00% | [4 Missing :warning: ](https://app.codecov.io/gh/Davidyz/VectorCode/pull/49?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Davidyz) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main      #49      +/-   ##
==========================================
- Coverage   97.57%   97.23%   -0.34%     
==========================================
  Files          18       18              
  Lines        1153     1157       +4     
==========================================
  Hits         1125     1125              
- Misses         28       32       +4     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/Davidyz/VectorCode/pull/49?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Davidyz).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Davidyz).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>

Patch:
diff --git a/src/vectorcode/common.py b/src/vectorcode/common.py
index 7d1941c..349cdff 100644
--- a/src/vectorcode/common.py
+++ b/src/vectorcode/common.py
@@ -134,7 +134,7 @@ def get_collection_name(full_path: str) -> str:
     return collection_id
 
 
-def get_embedding_function(configs: Config) -> chromadb.EmbeddingFunction:
+def get_embedding_function(configs: Config) -> chromadb.EmbeddingFunction | None:
     try:
         return getattr(embedding_functions, configs.embedding_function)(
             **configs.embedding_params
@@ -145,6 +145,16 @@ def get_embedding_function(configs: Config) -> chromadb.EmbeddingFunction:
             file=sys.stderr,
         )
         return embedding_functions.SentenceTransformerEmbeddingFunction()
+    except Exception as e:
+        print(
+            f"Failed to use {configs.embedding_function} with the following error:",
+            file=sys.stderr,
+        )
+        e.add_note(
+            "\nFor errors caused by missing dependency, consult the documentation of pipx (or whatever package manager that you installed VectorCode with) for instructions to inject libraries into the virtual environment."
+        )
+
+        raise
 
 
 __COLLECTION_CACHE: dict[str, AsyncCollection] = {}


Test patch:
diff --git a/tests/test_common.py b/tests/test_common.py
index 371daf0..930228f 100644
--- a/tests/test_common.py
+++ b/tests/test_common.py
@@ -9,6 +9,7 @@ import httpx
 import pytest
 from chromadb.api import AsyncClientAPI
 from chromadb.api.models.AsyncCollection import AsyncCollection
+from chromadb.utils import embedding_functions
 
 from vectorcode.cli_utils import Config
 from vectorcode.common import (
@@ -68,6 +69,34 @@ def test_get_embedding_function():
     assert "SentenceTransformerEmbeddingFunction" in str(type(embedding_function))
 
 
+def test_get_embedding_function_init_exception():
+    # Test when the embedding function exists but raises an error during initialization
+    config = Config(
+        embedding_function="SentenceTransformerEmbeddingFunction",
+        embedding_params={"model_name": "non_existent_model_should_cause_error"},
+    )
+
+    # Mock SentenceTransformerEmbeddingFunction.__init__ to raise a generic exception
+    with patch.object(
+        embedding_functions, "SentenceTransformerEmbeddingFunction", autospec=True
+    ) as mock_stef:
+        # Simulate an error during the embedding function's __init__
+        mock_stef.side_effect = Exception("Simulated initialization error")
+
+        with pytest.raises(Exception) as excinfo:
+            get_embedding_function(config)
+
+        # Check if the raised exception is the one we simulated
+        assert "Simulated initialization error" in str(excinfo.value)
+        # Check if the additional note was added
+        assert "For errors caused by missing dependency" in excinfo.value.__notes__[0]
+
+        # Verify that the constructor was called with the correct parameters
+        mock_stef.assert_called_once_with(
+            model_name="non_existent_model_should_cause_error"
+        )
+
+
 @pytest.mark.asyncio
 async def test_try_server():
     # This test requires a server to be running, so it's difficult to make it truly isolated.