Repository: run-llama/llama_index
Pull request: Allow defining retrievable fields in Azure Vector Store 
# Description

Added a hidden_field_keys option which allows the user to define which fields should be retrievable. Hidden fields are not retrievable by the client, but they can still be used by the indexer.

Fixes #16765

## Version Bump?

Did I bump the version in the `pyproject.toml` file of the package I am updating? (Except for the `llama-index-core` package)

- [x] Yes
- [ ] No

## Type of Change

Please delete options that are not relevant.

- [x] New feature (non-breaking change which adds functionality)
- [x] This change requires a documentation update

## How Has This Been Tested?

Your pull-request will likely not be merged unless it is covered by some form of impactful unit testing.

- [x] I believe this change is already covered by existing unit tests

## Suggested Checklist:

- [x] I have performed a self-review of my own code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] New and existing unit tests pass locally with my changes
- [x] I ran `make format; make lint` to appease the lint gods


Problem statement:
[Feature Request]: Azure Vector Search - allow defining retrievable fields.
### Feature Description

By default, the embedding field is hidden, as in non retrievable by the client. This causes problems if the client needs the embedding vector of the nodes.

### Reason

This cannot be changed in the current implementation by the client.

### Value of Feature

The client will have more control over their created index, allowing them to fully utilize the retrievable attribute as well.

Hints from issue discussion:

Commit message: Azure Vector Store - hidden fields documentation

Patch to review:
diff --git a/llama-index-integrations/vector_stores/llama-index-vector-stores-azureaisearch/llama_index/vector_stores/azureaisearch/base.py b/llama-index-integrations/vector_stores/llama-index-vector-stores-azureaisearch/llama_index/vector_stores/azureaisearch/base.py
index 1af492d2c4..4ce95c202d 100644
--- a/llama-index-integrations/vector_stores/llama-index-vector-stores-azureaisearch/llama_index/vector_stores/azureaisearch/base.py
+++ b/llama-index-integrations/vector_stores/llama-index-vector-stores-azureaisearch/llama_index/vector_stores/azureaisearch/base.py
@@ -98,6 +98,7 @@ class AzureAISearchVectorStore(BasePydanticVectorStore):
         vector_store = AzureAISearchVectorStore(
             search_or_index_client=index_client,
             filterable_metadata_field_keys=metadata_fields,
+            hidden_field_keys=["embedding"],
             index_name=index_name,
             index_management=IndexManagement.CREATE_IF_NOT_EXISTS,
             id_field_key="id",
@@ -122,6 +123,7 @@ class AzureAISearchVectorStore(BasePydanticVectorStore):
     _async_search_client: AsyncSearchClient = PrivateAttr()
     _embedding_dimensionality: int = PrivateAttr()
     _language_analyzer: str = PrivateAttr()
+    _hidden_field_keys: List[str] = PrivateAttr()
     _field_mapping: Dict[str, str] = PrivateAttr()
     _index_management: IndexManagement = PrivateAttr()
     _index_mapping: Callable[
@@ -223,7 +225,7 @@ def _create_metadata_index_fields(self) -> List[Any]:
             elif field_type == MetadataIndexFieldType.COLLECTION:
                 index_field_type = "Collection(Edm.String)"
 
-            field = SimpleField(name=field_name, type=index_field_type, filterable=True)
+            field = SimpleField(name=field_name, type=index_field_type, filterable=True, hidden=field_name in self._hidden_field_keys)
             index_fields.append(field)
 
         return index_fields
@@ -391,6 +393,7 @@ async def _acreate_index(self, index_name: Optional[str]) -> None:
                 name=self._field_mapping["chunk"],
                 type="Edm.String",
                 analyzer_name=self._language_analyzer,
+                hidden=self._field_mapping["chunk"] in self._hidden_field_keys,
             ),
             SearchField(
                 name=self._field_mapping["embedding"],
@@ -398,10 +401,18 @@ async def _acreate_index(self, index_name: Optional[str]) -> None:
                 searchable=True,
                 vector_search_dimensions=self._embedding_dimensionality,
                 vector_search_profile_name=self._vector_profile_name,
+                hidden=self._field_mapping["embedding"] in self._hidden_field_keys,
             ),
-            SimpleField(name=self._field_mapping["metadata"], type="Edm.String"),
             SimpleField(
-                name=self._field_mapping["doc_id"], type="Edm.String", filterable=True
+                name=self._field_mapping["metadata"], 
+                type="Edm.String", 
+                hidden=self._field_mapping["metadata"] in self._hidden_field_keys
+            ),
+            SimpleField(
+                name=self._field_mapping["doc_id"], 
+                type="Edm.String", 
+                filterable=True,
+                hidden=self._field_mapping["doc_id"] in self._hidden_field_keys
             ),
         ]
         logger.info(f"Configuring {index_name} metadata fields")
@@ -497,6 +508,7 @@ def __init__(
                 Dict[str, Tuple[str, MetadataIndexFieldType]],
             ]
         ] = None,
+        hidden_field_keys: List[str] = [],
         index_name: Optional[str] = None,
         index_mapping: Optional[
             Callable[[Dict[str, str], Dict[str, Any]], Dict[str, str]]
@@ -530,6 +542,10 @@ def __init__(
                 as separate fields in the index, use filterable_metadata_field_keys
                 to specify the metadata values that should be stored in these filterable fields
             doc_id_field_key (str): Index field storing doc_id
+            hidden_field_keys (List[str]):
+                List of index fields that should be hidden from the client.
+                This is useful for fields that are not needed for retrieving,
+                but are used for similarity search, like the embedding field.
             index_mapping:
                 Optional function with definition
                 (enriched_doc: Dict[str, str], metadata: Dict[str, Any]): Dict[str,str]
@@ -683,6 +699,7 @@ def __init__(
         }
 
         self._field_mapping = field_mapping
+        self._hidden_field_keys = hidden_field_keys
 
         self._index_mapping = (
             self._default_index_mapping if index_mapping is None else index_mapping
diff --git a/llama-index-integrations/vector_stores/llama-index-vector-stores-azureaisearch/pyproject.toml b/llama-index-integrations/vector_stores/llama-index-vector-stores-azureaisearch/pyproject.toml
index 8bd52c4f83..9b3ca8ef1d 100644
--- a/llama-index-integrations/vector_stores/llama-index-vector-stores-azureaisearch/pyproject.toml
+++ b/llama-index-integrations/vector_stores/llama-index-vector-stores-azureaisearch/pyproject.toml
@@ -28,7 +28,7 @@ exclude = ["**/BUILD"]
 license = "MIT"
 name = "llama-index-vector-stores-azureaisearch"
 readme = "README.md"
-version = "0.2.3"
+version = "0.2.4"
 
 [tool.poetry.dependencies]
 python = ">=3.8.1,<4.0"
diff --git a/llama-index-integrations/vector_stores/llama-index-vector-stores-azureaisearch/tests/test_azureaisearch.py b/llama-index-integrations/vector_stores/llama-index-vector-stores-azureaisearch/tests/test_azureaisearch.py
index a7c607bd37..8ec813c227 100644
--- a/llama-index-integrations/vector_stores/llama-index-vector-stores-azureaisearch/tests/test_azureaisearch.py
+++ b/llama-index-integrations/vector_stores/llama-index-vector-stores-azureaisearch/tests/test_azureaisearch.py
@@ -34,6 +34,7 @@ def create_mock_vector_store(
         metadata_string_field_key="metadata",
         doc_id_field_key="doc_id",
         filterable_metadata_field_keys=[],  # Added to match the updated constructor
+        hidden_field_keys=["embedding"],
         index_name=index_name,
         index_management=index_management,
         embedding_dimensionality=2,  # Assuming a dimensionality of 2 for simplicity


Code review comments:
diff_hunk: @@ -497,6 +508,7 @@ def __init__(
                 Dict[str, Tuple[str, MetadataIndexFieldType]],
             ]
         ] = None,
+        hidden_field_keys: List[str] = [],
path: llama-index-integrations/vector_stores/llama-index-vector-stores-azureaisearch/llama_index/vector_stores/azureaisearch/base.py
text: @user1:
default arguments should never be a list or dict due to how pass-by-reference works in python

@user1:
Pushed a fix