Repository: milvus-io/pymilvus

Issue:
[Bug]: It seems pymilvus==2.2.14 have bug with alter_collection
### Is there an existing issue for this?

- [X] I have searched the existing issues

### Describe the bug

See: https://github.com/matrixji/milvus-lite/actions/runs/5653197188/job/15314820137
```
collection created: demo
Traceback (most recent call last):
  File "/github/home/.local/lib/python3.10/site-packages/pymilvus/decorators.py", line 123, in handler
    return func(*args, **kwargs)
  File "/github/home/.local/lib/python3.10/site-packages/pymilvus/decorators.py", line 162, in handler
    return func(self, *args, **kwargs)
  File "/github/home/.local/lib/python3.10/site-packages/pymilvus/decorators.py", line [104](https://github.com/matrixji/milvus-lite/actions/runs/5653197188/job/15314820137#step:6:105), in handler
    raise e from e
  File "/github/home/.local/lib/python3.10/site-packages/pymilvus/decorators.py", line 68, in handler
    return func(*args, **kwargs)
  File "/github/home/.local/lib/python3.10/site-packages/pymilvus/client/grpc_handler.py", line 308, in alter_collection
    request = Prepare.alter_collection_request(collection_name, properties)
  File "/github/home/.local/lib/python3.10/site-packages/pymilvus/client/prepare.py", line 236, in alter_collection_request
    kvs = [common_types.KeyDataPair(key=k, value=str(v)) for k, v in properties.items()]
  File "/github/home/.local/lib/python3.10/site-packages/pymilvus/client/prepare.py", line 236, in <listcomp>
    kvs = [common_types.KeyDataPair(key=k, value=str(v)) for k, v in properties.items()]
ValueError: Protocol message KeyDataPair has no "value" field.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/__w/milvus-lite/milvus-lite/examples/example.py", line 188, in <module>
    main()
  File "/__w/milvus-lite/milvus-lite/examples/example.py", line 156, in main
    set_properties(collection)
  File "/__w/milvus-lite/milvus-lite/examples/example.py", line 141, in set_properties
    collection.set_properties(properties={"collection.ttl.seconds": 1800})
  File "/github/home/.local/lib/python3.10/site-packages/pymilvus/orm/collection.py", line 358, in set_properties
    conn.alter_collection(
  File "/github/home/.local/lib/python3.10/site-packages/pymilvus/decorators.py", line 145, in handler
    raise MilvusException(message=f"Unexpected error, message=<{e!s}>") from e
pymilvus.exceptions.MilvusException: <MilvusException: (code=1, message=Unexpected error, message=<Protocol message KeyDataPair has no "value" field.>)>
Error: Process completed with exit code 1.
```

the root cause is KeyDataPair only have `data` field but not the `value`

### Expected Behavior

Hope could run example.py from pymilvus.

### Steps/Code To Reproduce behavior

```markdown
See above
```


### Environment details

```markdown
- Hardware/Softward conditions (OS, CPU, GPU, Memory): N/A
- Method of installation (Docker, or from source): pip
- Milvus version (v0.3.1, or v0.4.0): 2.2.12
- Milvus configuration (Settings you made in `server_config.yaml`): N/A
```


### Anything else?

_No response_

Discussion:
sre-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/milvus-io/pymilvus/pull/1618#" title="Author self-approved">matrixji</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **longjiquan** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @longjiquan` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=milvus-io%2Fpymilvus).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/milvus-io/pymilvus/blob/2.2/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["longjiquan"]} -->

Patch:
diff --git a/pymilvus/client/prepare.py b/pymilvus/client/prepare.py
index 039426ae..512de479 100644
--- a/pymilvus/client/prepare.py
+++ b/pymilvus/client/prepare.py
@@ -233,7 +233,7 @@ class Prepare:
         collection_name: str,
         properties: Dict,
     ) -> milvus_types.AlterCollectionRequest:
-        kvs = [common_types.KeyDataPair(key=k, value=str(v)) for k, v in properties.items()]
+        kvs = [common_types.KeyValuePair(key=k, value=str(v)) for k, v in properties.items()]
 
         return milvus_types.AlterCollectionRequest(collection_name=collection_name, properties=kvs)
 
@@ -596,14 +596,24 @@ class Prepare:
         params = param.get("params", {})
         if not isinstance(params, dict):
             raise ParamError(message=f"Search params must be a dict, got {type(params)}")
+
         search_params = {
             "topk": limit,
             "params": params,
             "round_decimal": round_decimal,
-            "offset": param.get("offset", 0),
             "ignore_growing": ignore_growing,
         }
 
+        # parse offset
+        if "offset" in kwargs and "offset" in param:
+            raise ParamError(message="Provide offset both in kwargs and param, expect just one")
+
+        offset = kwargs.get("offset") or param.get("offset")
+        if offset is not None:
+            if not isinstance(offset, int):
+                raise ParamError(message=f"wrong type for offset, expect int, got {type(offset)}")
+            search_params["offset"] = offset
+
         if param.get("metric_type", None) is not None:
             search_params["metric_type"] = param["metric_type"]
 
diff --git a/pymilvus/client/types.py b/pymilvus/client/types.py
index 49dd6c2c..40736277 100644
--- a/pymilvus/client/types.py
+++ b/pymilvus/client/types.py
@@ -521,8 +521,8 @@ class BulkInsertState:
         auto generated ids if the primary key is auto generated
 
         the id list of response is id ranges
-        for example, if the response return [1, 100, 200, 250]
-        the full id list should be [1, 2, 3 ... , 99, 100, 200, 201, 202 ... , 249, 250]
+        for example, if the response return [1, 100, 200, 250], the id ranges: [1,100),[200,250)
+        the full id list should be [1, 2, 3 ... , 99, 200, 201, 202 ... , 249]
         """
 
         if len(self._id_ranges) % 2 != 0:
@@ -531,7 +531,7 @@ class BulkInsertState:
         ids = []
         for i in range(int(len(self._id_ranges) / 2)):
             begin = self._id_ranges[i * 2]
-            end = self._id_ranges[i * 2 + 1] + 1
+            end = self._id_ranges[i * 2 + 1]
             for j in range(begin, end):
                 ids.append(j)
 
diff --git a/pymilvus/orm/collection.py b/pymilvus/orm/collection.py
index 4dc0d8d3..b63a409e 100644
--- a/pymilvus/orm/collection.py
+++ b/pymilvus/orm/collection.py
@@ -589,8 +589,6 @@ class Collection:
                     similar metricy types, the value must be of type str.
                 * *offset* (``int``, optional)
                     offset for pagination.
-                * *limit* (``int``, optional)
-                    limit for the search results and pagination.
                 * *params of index: *nprobe*, *ef*, *search_k*, etc
                     Corresponding search params for a certain index.
                 example for param::
@@ -602,7 +600,7 @@ class Collection:
                     }
 
             limit (``int``): The max number of returned record, also known as `topk`.
-            expr (``str``): The boolean expression used to filter attribute. Default to None.
+            expr (``str``, Optional): The boolean expression used to filter attribute.
 
                 example for expr::
 
@@ -627,6 +625,9 @@ class Collection:
                     The callback function which is invoked after server response successfully.
                     It functions only if _async is set to True.
 
+                * *offset* (``int``, optinal)
+                    offset for pagination.
+
                 * *consistency_level* (``str/int``, optional)
                     Which consistency level to use when searching in the collection.
 


Test patch:
diff --git a/tests/test_prepare.py b/tests/test_prepare.py
index 7183eddb..f696de57 100644
--- a/tests/test_prepare.py
+++ b/tests/test_prepare.py
@@ -179,3 +179,9 @@ class TestCreateCollectionRequest:
         ]
 
         Prepare.row_insert_param("", rows, "", fields_info=schema.to_dict()["fields"], enable_dynamic=True)
+
+
+class TestAlterCollectionRequest:
+    def test_alter_collection_request(self):
+        schema = Prepare.alter_collection_request('foo', {'collection.ttl.seconds': 1800})
+