Repository: langchain
Issue: [Azure CosmosDB NoSQL] similarity_search_with_score function returning CosmosHttpResponseError "bad request"
Labels: Ɑ: vector store,investigate

### Checked other resources

- [X] I added a very descriptive title to this issue.
- [X] I searched the LangChain documentation with the integrated search.
- [X] I used the GitHub search to find a similar question and didn't find it.
- [X] I am sure that this is a bug in LangChain rather than my code.
- [X] The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package).

### Example Code

Sample for reproducing the issue
```python
import os
from dotenv import load_dotenv
from azure.cosmos import CosmosClient, PartitionKey
from langchain_community.vectorstores.azure_cosmos_db_no_sql import (
    AzureCosmosDBNoSqlVectorSearch,
)
from langchain_openai import OpenAIEmbeddings

# from azure_cosmos_db_no_sql import AzureCosmosDBNoSqlVectorSearch # workarround with modifications to code

_ = load_dotenv()

HOST = os.environ['AZURE_COSMOS_URL']
KEY = os.environ['AZURE_COSMOS_KEY']

cosmos_client = CosmosClient(HOST, KEY)
database_name = "db"
container_name = "container1"
partition_key = PartitionKey(path="/id")
cosmos_container_properties = {"partition_key": partition_key}

openai_embeddings = OpenAIEmbeddings(model="text-embedding-3-large")

vectorstore = AzureCosmosDBNoSqlVectorSearch(
    cosmos_client=cosmos_client,
    embedding=openai_embeddings,
    vector_embedding_policy={
        "vectorEmbeddings": [
            {
                "path": "/embedding",
                "dataType": "float32",
                "distanceFunction": "cosine",
                "dimensions": 3072,
            }
        ]
    },
    indexing_policy={
        "indexingMode": "consistent",
        "includedPaths": [{"path": "/*"}],
        "excludedPaths": [{"path": '/"_etag"/?'}],
        "vectorIndexes": [{"path": "/embedding", "type": "quantizedFlat"}],
    },
    cosmos_container_properties=cosmos_container_properties,
    cosmos_database_properties={'id': database_name},
    database_name=database_name,
    container_name=container_name,
    create_container=False,
)

query = "What were the compute requirements for training GPT 4"

results = vectorstore.similarity_search_with_score(
    query=query,
)
````

### Error Message and Stack Trace (if applicable)

{
	"name": "CosmosHttpResponseError",
	"message": "(BadRequest) One of the input values is invalid.\r
ActivityId: 73e70e21-b8f3-4eb7-bb26-a85e03ae05fc, Windows/10.0.20348 cosmos-netstandard-sdk/3.18.0
Code: BadRequest
Message: One of the input values is invalid.\r
ActivityId: 73e70e21-b8f3-4eb7-bb26-a85e03ae05fc, Windows/10.0.20348 cosmos-netstandard-sdk/3.18.0",
	"stack": "---------------------------------------------------------------------------
CosmosHttpResponseError                   Traceback (most recent call last)
Cell In[7], line 3
      1 query = \"What were the compute requirements for training GPT 4\"
----> 3 results = vectorstore.similarity_search_with_score(
      4     query=query,
      5     k=5,
      6 )
      8 # Display results
      9 for result in results:

File ~/git/demos/.venv/lib/python3.10/site-packages/langchain_community/vectorstores/azure_cosmos_db_no_sql.py:322, in AzureCosmosDBNoSqlVectorSearch.similarity_search_with_score(self, query, k, pre_filter, with_embedding)
    314 def similarity_search_with_score(
    315     self,
    316     query: str,
   (...)
    319     with_embedding: bool = False,
    320 ) -> List[Tuple[Document, float]]:
    321     embeddings = self._embedding.embed_query(query)
--> 322     docs_and_scores = self._similarity_search_with_score(
    323         embeddings=embeddings,
    324         k=k,
    325         pre_filter=pre_filter,
    326         with_embedding=with_embedding,
    327     )
    328     return docs_and_scores

File ~/git/demos/.venv/lib/python3.10/site-packages/langchain_community/vectorstores/azure_cosmos_db_no_sql.py:298, in AzureCosmosDBNoSqlVectorSearch._similarity_search_with_score(self, embeddings, k, pre_filter, with_embedding)
    290 parameters = [
    291     {\"name\": \"@limit\", \"value\": k},
    292     {\"name\": \"@embeddingKey\", \"value\": self._embedding_key},
    293     {\"name\": \"@embeddings\", \"value\": embeddings},
    294 ]
    296 docs_and_scores = []
--> 298 items = list(
    299     self._container.query_items(
    300         query=query, parameters=parameters, enable_cross_partition_query=True
    301     )
    302 )
    303 for item in items:
    304     text = item[\"text\"]

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/core/paging.py:123, in ItemPaged.__next__(self)
    121 if self._page_iterator is None:
    122     self._page_iterator = itertools.chain.from_iterable(self.by_page())
--> 123 return next(self._page_iterator)

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/core/paging.py:75, in PageIterator.__next__(self)
     73     raise StopIteration(\"End of paging\")
     74 try:
---> 75     self._response = self._get_next(self.continuation_token)
     76 except AzureError as error:
     77     if not error.continuation_token:

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/cosmos/_query_iterable.py:99, in QueryIterable._fetch_next(self, *args)
     89 def _fetch_next(self, *args):  # pylint: disable=unused-argument
     90     \"\"\"Return a block of results with respecting retry policy.
     91 
     92     This method only exists for backward compatibility reasons. (Because
   (...)
     97     :rtype: list
     98     \"\"\"
---> 99     block = self._ex_context.fetch_next_block()
    100     if not block:
    101         raise StopIteration

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/cosmos/_execution_context/execution_dispatcher.py:110, in _ProxyQueryExecutionContext.fetch_next_block(self)
    108         self._execution_context = self._create_pipelined_execution_context(query_execution_info)
    109     else:
--> 110         raise e
    112 return self._execution_context.fetch_next_block()

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/cosmos/_execution_context/execution_dispatcher.py:102, in _ProxyQueryExecutionContext.fetch_next_block(self)
     93 \"\"\"Returns a block of results.
     94 
     95 This method only exists for backward compatibility reasons. (Because
   (...)
     99 :rtype: list
    100 \"\"\"
    101 try:
--> 102     return self._execution_context.fetch_next_block()
    103 except CosmosHttpResponseError as e:
    104     if _is_partitioned_execution_info(e):

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/cosmos/_execution_context/base_execution_context.py:79, in _QueryExecutionContextBase.fetch_next_block(self)
     70 def fetch_next_block(self):
     71     \"\"\"Returns a block of results with respecting retry policy.
     72 
     73     This method only exists for backward compatibility reasons. (Because
   (...)
     77     :rtype: list
     78     \"\"\"
---> 79     self._ensure()
     80     res = list(self._buffer)
     81     self._buffer.clear()

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/cosmos/_execution_context/base_execution_context.py:64, in _QueryExecutionContextBase._ensure(self)
     61     return
     63 if not self._buffer:
---> 64     results = self._fetch_next_block()
     65     self._buffer.extend(results)
     67 if not self._buffer:

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/cosmos/_execution_context/base_execution_context.py:175, in _DefaultQueryExecutionContext._fetch_next_block(self)
    173 def _fetch_next_block(self):  # pylint: disable=inconsistent-return-statements
    174     while super(_DefaultQueryExecutionContext, self)._has_more_pages() and not self._buffer:
--> 175         return self._fetch_items_helper_with_retries(self._fetch_function)

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/cosmos/_execution_context/base_execution_context.py:147, in _QueryExecutionContextBase._fetch_items_helper_with_retries(self, fetch_function)
    144 def callback():
    145     return self._fetch_items_helper_no_retries(fetch_function)
--> 147 return _retry_utility.Execute(self._client, self._client._global_endpoint_manager, callback)

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/cosmos/_retry_utility.py:87, in Execute(client, global_endpoint_manager, function, *args, **kwargs)
     85     result = ExecuteFunction(function, global_endpoint_manager, *args, **kwargs)
     86 else:
---> 87     result = ExecuteFunction(function, *args, **kwargs)
     88 if not client.last_response_headers:
     89     client.last_response_headers = {}

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/cosmos/_retry_utility.py:149, in ExecuteFunction(function, *args, **kwargs)
    142 def ExecuteFunction(function, *args, **kwargs):
    143     \"\"\"Stub method so that it can be used for mocking purposes as well.
    144     :param Callable function: the function to execute.
    145     :param list args: the explicit arguments for the function.
    146     :returns: the result of executing the function with the passed in arguments
    147     :rtype: tuple(dict, dict)
    148     \"\"\"
--> 149     return function(*args, **kwargs)

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/cosmos/_execution_context/base_execution_context.py:145, in _QueryExecutionContextBase._fetch_items_helper_with_retries.<locals>.callback()
    144 def callback():
--> 145     return self._fetch_items_helper_no_retries(fetch_function)

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/cosmos/_execution_context/base_execution_context.py:126, in _QueryExecutionContextBase._fetch_items_helper_no_retries(self, fetch_function)
    123 new_options[\"continuation\"] = self._continuation
    125 response_headers = {}
--> 126 (fetched_items, response_headers) = fetch_function(new_options)
    128 continuation_key = http_constants.HttpHeaders.Continuation
    129 # Use Etag as continuation token for change feed queries.

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/cosmos/_cosmos_client_connection.py:1065, in CosmosClientConnection.QueryItems.<locals>.fetch_fn(options)
   1064 def fetch_fn(options: Mapping[str, Any]) -> Tuple[List[Dict[str, Any]], Dict[str, Any]]:
-> 1065     return self.__QueryFeed(
   1066             path,
   1067             \"docs\",
   1068             collection_id,
   1069             lambda r: r[\"Documents\"],
   1070             lambda _, b: b,
   1071             query,
   1072             options,
   1073             response_hook=response_hook,
   1074             **kwargs)

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/cosmos/_cosmos_client_connection.py:3092, in CosmosClientConnection.__QueryFeed(self, path, resource_type, resource_id, result_fn, create_fn, query, options, partition_key_range_id, response_hook, is_query_plan, **kwargs)
   3089     if results:
   3090         return __GetBodiesFromQueryResult(results), last_response_headers
-> 3092 result, last_response_headers = self.__Post(path, request_params, query, req_headers, **kwargs)
   3093 if last_response_headers.get(http_constants.HttpHeaders.IndexUtilization) is not None:
   3094     INDEX_METRICS_HEADER = http_constants.HttpHeaders.IndexUtilization

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/cosmos/_cosmos_client_connection.py:2811, in CosmosClientConnection.__Post(self, path, request_params, body, req_headers, **kwargs)
   2801 \"\"\"Azure Cosmos 'POST' http request.
   2802 
   2803 :param str path: the url to be used for the request.
   (...)
   2808 :rtype: tuple of (dict, dict)
   2809 \"\"\"
   2810 request = self.pipeline_client.post(url=path, headers=req_headers)
-> 2811 return synchronized_request.SynchronizedRequest(
   2812     client=self,
   2813     request_params=request_params,
   2814     global_endpoint_manager=self._global_endpoint_manager,
   2815     connection_policy=self.connection_policy,
   2816     pipeline_client=self.pipeline_client,
   2817     request=request,
   2818     request_data=body,
   2819     **kwargs
   2820 )

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/cosmos/_synchronized_request.py:204, in SynchronizedRequest(client, request_params, global_endpoint_manager, connection_policy, pipeline_client, request, request_data, **kwargs)
    201     request.headers[http_constants.HttpHeaders.ContentLength] = 0
    203 # Pass _Request function with its parameters to retry_utility's Execute method that wraps the call with retries
--> 204 return _retry_utility.Execute(
    205     client,
    206     global_endpoint_manager,
    207     _Request,
    208     request_params,
    209     connection_policy,
    210     pipeline_client,
    211     request,
    212     **kwargs
    213 )

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/cosmos/_retry_utility.py:85, in Execute(client, global_endpoint_manager, function, *args, **kwargs)
     83 try:
     84     if args:
---> 85         result = ExecuteFunction(function, global_endpoint_manager, *args, **kwargs)
     86     else:
     87         result = ExecuteFunction(function, *args, **kwargs)

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/cosmos/_retry_utility.py:149, in ExecuteFunction(function, *args, **kwargs)
    142 def ExecuteFunction(function, *args, **kwargs):
    143     \"\"\"Stub method so that it can be used for mocking purposes as well.
    144     :param Callable function: the function to execute.
    145     :param list args: the explicit arguments for the function.
    146     :returns: the result of executing the function with the passed in arguments
    147     :rtype: tuple(dict, dict)
    148     \"\"\"
--> 149     return function(*args, **kwargs)

File ~/git/demos/.venv/lib/python3.10/site-packages/azure/cosmos/_synchronized_request.py:155, in _Request(global_endpoint_manager, request_params, connection_policy, pipeline_client, request, **kwargs)
    153     raise exceptions.CosmosAccessConditionFailedError(message=data, response=response)
    154 if response.status_code >= 400:
--> 155     raise exceptions.CosmosHttpResponseError(message=data, response=response)
    157 result = None
    158 if data:

CosmosHttpResponseError: (BadRequest) One of the input values is invalid.\r
ActivityId: 73e70e21-b8f3-4eb7-bb26-a85e03ae05fc, Windows/10.0.20348 cosmos-netstandard-sdk/3.18.0
Code: BadRequest
Message: One of the input values is invalid.\r
ActivityId: 73e70e21-b8f3-4eb7-bb26-a85e03ae05fc, Windows/10.0.20348 cosmos-netstandard-sdk/3.18.0"
}

### Description

I'm using langchain_community.vectorstores.azure_cosmos_db_no_sql to set up a document retriever or do similarity search. However, in my current case, every query fails, when it's being set up as shown in the code.

The container has been created using the .from_document() function. When using the returned object from this function, the similarity search works as expected. I didn't yet understand why this was the case. Anyway, I must be able to load and then access the vector store individually in my use case.

As of my current understanding, the issue relays in the query section of the code:

Original:
```python
# ...
# Line 276
query += (
            "c.id, c.{}, c.text, c.metadata, "
            "VectorDistance(c.@embeddingKey, @embeddings) AS SimilarityScore FROM c"
        )
# ...
````

Modified
```python
query += (
            "c.id, c.{}, c.text, c.metadata, "
            "VectorDistance(c[@embeddingKey], @embeddings) AS SimilarityScore FROM c"
        )
#...

# Check and remove any remaining empty placeholder (if there are any)
        if "c.{}" in query:
            query = query.replace("c.{},", "")  # Clean up empty placeholders
# ...
````
Note the change in syntax for the embeddingKey parameter. As of my research, Cosmos DB's SQL query syntax doesn't support parameterizing field names, like 'c.@embeddingKey'. It should work with 'c[@embeddingKey]'. (https://stackoverflow.com/questions/56121759/parameterized-input-with-document-fields-with-cosmos-db, sadly the links to MS Docs are broken).
Thereafter, the 'c.{}' in the query, which I honestly didn't fully understand why it's used, causes another syntax issue. After reviewing the query while debugging, I found it to be never replaced in my case. So I added a silly line to strip it, if "empty". Probably not the best solution.

I tried with a modified version of azure_cosmos_db_no_sql.py in my app, and then the similarity search as well as the retriever started working as expected.

### System Info

System Information
------------------
> OS:  Linux
> OS Version:  #1 SMP Fri Mar 29 23:14:13 UTC 2024
> Python Version:  3.10.12 (main, Sep 11 2024, 15:47:36) [GCC 11.4.0]

Package Information
-------------------
> langchain_core: 0.3.10
> langchain: 0.3.3
> langchain_community: 0.3.2
> langsmith: 0.1.132
> langchain_experimental: 0.3.2
> langchain_openai: 0.2.2
> langchain_pinecone: 0.2.0
> langchain_text_splitters: 0.3.0
> langchainhub: 0.1.21

Optional packages not installed
-------------------------------
> langgraph
> langserve

Other Dependencies
------------------
> aiohttp: 3.9.5
> async-timeout: 4.0.3
> dataclasses-json: 0.6.7
> httpx: 0.27.2
> jsonpatch: 1.33
> numpy: 1.26.4
> openai: 1.51.1
> orjson: 3.10.7
> packaging: 23.2
> pinecone-client: 5.0.1
> pydantic: 2.9.2
> pydantic-settings: 2.5.2
> PyYAML: 6.0.2
> requests: 2.32.3
> requests-toolbelt: 1.0.0
> SQLAlchemy: 2.0.35
> tenacity: 8.5.0
> tiktoken: 0.8.0
> types-requests: 2.32.0.20240914
> typing-extensions: 4.12.2