Skip to content

Commit 1ab2fa6

Browse files
Support function edit sdk
Signed-off-by: junjie.jiang <junjie.jiang@zilliz.com>
1 parent afff26c commit 1ab2fa6

File tree

15 files changed

+997
-623
lines changed

15 files changed

+997
-623
lines changed

examples/function_edit.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
from pymilvus import (
2+
MilvusClient,
3+
Function, DataType, FunctionType,
4+
)
5+
6+
collection_name = "text_embedding"
7+
8+
milvus_client = MilvusClient("http://localhost:19530")
9+
10+
has_collection = milvus_client.has_collection(collection_name, timeout=5)
11+
if has_collection:
12+
milvus_client.drop_collection(collection_name)
13+
14+
schema = milvus_client.create_schema()
15+
schema.add_field("id", DataType.INT64, is_primary=True, auto_id=False)
16+
schema.add_field("document", DataType.VARCHAR, max_length=9000)
17+
schema.add_field("dense", DataType.FLOAT_VECTOR, dim=1536)
18+
19+
text_embedding_function = Function(
20+
name="openai",
21+
function_type=FunctionType.TEXTEMBEDDING,
22+
input_field_names=["document"],
23+
output_field_names="dense",
24+
params={
25+
"provider": "openai",
26+
"model_name": "text-embedding-3-small",
27+
}
28+
)
29+
30+
schema.add_function(text_embedding_function)
31+
32+
index_params = milvus_client.prepare_index_params()
33+
index_params.add_index(
34+
field_name="dense",
35+
index_name="dense_index",
36+
index_type="AUTOINDEX",
37+
metric_type="IP",
38+
)
39+
40+
ret = milvus_client.create_collection(collection_name, schema=schema, index_params=index_params, consistency_level="Strong")
41+
42+
ret = milvus_client.describe_collection(collection_name)
43+
print(ret["functions"][0])
44+
45+
text_embedding_function.params["user"] = "user123"
46+
47+
milvus_client.alter_collection_function(collection_name, "openai", text_embedding_function)
48+
49+
ret = milvus_client.describe_collection(collection_name)
50+
print(ret["functions"][0])
51+
52+
milvus_client.drop_collection_function(collection_name, "openai")
53+
54+
ret = milvus_client.describe_collection(collection_name)
55+
print(ret["functions"])
56+
57+
text_embedding_function.params["user"] = "user1234"
58+
59+
milvus_client.add_collection_function(collection_name, text_embedding_function)
60+
61+
ret = milvus_client.describe_collection(collection_name)
62+
print(ret["functions"][0])

pymilvus/client/async_grpc_handler.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,6 +1310,60 @@ async def add_collection_field(
13101310
)
13111311
check_status(status)
13121312

1313+
@retry_on_rpc_failure()
1314+
async def drop_collection_function(
1315+
self,
1316+
collection_name: str,
1317+
function_name: str,
1318+
timeout: Optional[float] = None,
1319+
**kwargs,
1320+
):
1321+
await self.ensure_channel_ready()
1322+
check_pass_param(collection_name=collection_name, timeout=timeout)
1323+
request = Prepare.drop_collection_function_request(collection_name, function_name)
1324+
1325+
status = await self._async_stub.DropCollectionFunction(
1326+
request, timeout=timeout, metadata=_api_level_md(**kwargs)
1327+
)
1328+
check_status(status)
1329+
1330+
@retry_on_rpc_failure()
1331+
async def add_collection_function(
1332+
self,
1333+
collection_name: str,
1334+
function: Function,
1335+
timeout: Optional[float] = None,
1336+
**kwargs,
1337+
):
1338+
await self.ensure_channel_ready()
1339+
check_pass_param(collection_name=collection_name, timeout=timeout)
1340+
request = Prepare.add_collection_function_request(collection_name, function)
1341+
1342+
status = await self._async_stub.AddCollectionFunction(
1343+
request, timeout=timeout, metadata=_api_level_md(**kwargs)
1344+
)
1345+
check_status(status)
1346+
1347+
@retry_on_rpc_failure()
1348+
async def alter_collection_function(
1349+
self,
1350+
collection_name: str,
1351+
function_name: str,
1352+
function: Function,
1353+
timeout: Optional[float] = None,
1354+
**kwargs,
1355+
):
1356+
await self.ensure_channel_ready()
1357+
check_pass_param(collection_name=collection_name, timeout=timeout)
1358+
request = Prepare.alter_collection_function_request(
1359+
collection_name, function_name, function
1360+
)
1361+
1362+
status = await self._async_stub.AlterCollectionFunction(
1363+
request, timeout=timeout, metadata=_api_level_md(**kwargs)
1364+
)
1365+
check_status(status)
1366+
13131367
@retry_on_rpc_failure()
13141368
async def list_indexes(self, collection_name: str, timeout: Optional[float] = None, **kwargs):
13151369
await self.ensure_channel_ready()

pymilvus/client/grpc_handler.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,57 @@ def add_collection_field(
346346
)
347347
check_status(status)
348348

349+
@retry_on_rpc_failure()
350+
def drop_collection_function(
351+
self,
352+
collection_name: str,
353+
function_name: str,
354+
timeout: Optional[float] = None,
355+
**kwargs,
356+
):
357+
check_pass_param(collection_name=collection_name, timeout=timeout)
358+
request = Prepare.drop_collection_function_request(collection_name, function_name)
359+
360+
status = self._stub.DropCollectionFunction(
361+
request, timeout=timeout, metadata=_api_level_md(**kwargs)
362+
)
363+
check_status(status)
364+
365+
@retry_on_rpc_failure()
366+
def add_collection_function(
367+
self,
368+
collection_name: str,
369+
function: Function,
370+
timeout: Optional[float] = None,
371+
**kwargs,
372+
):
373+
check_pass_param(collection_name=collection_name, timeout=timeout)
374+
request = Prepare.add_collection_function_request(collection_name, function)
375+
376+
status = self._stub.AddCollectionFunction(
377+
request, timeout=timeout, metadata=_api_level_md(**kwargs)
378+
)
379+
check_status(status)
380+
381+
@retry_on_rpc_failure()
382+
def alter_collection_function(
383+
self,
384+
collection_name: str,
385+
function_name: str,
386+
function: Function,
387+
timeout: Optional[float] = None,
388+
**kwargs,
389+
):
390+
check_pass_param(collection_name=collection_name, timeout=timeout)
391+
request = Prepare.alter_collection_function_request(
392+
collection_name, function_name, function
393+
)
394+
395+
status = self._stub.AlterCollectionFunction(
396+
request, timeout=timeout, metadata=_api_level_md(**kwargs)
397+
)
398+
check_status(status)
399+
349400
@retry_on_rpc_failure()
350401
def alter_collection_properties(
351402
self, collection_name: str, properties: List, timeout: Optional[float] = None, **kwargs

pymilvus/client/prepare.py

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -241,16 +241,7 @@ def get_schema_from_collection_schema(
241241
schema.struct_array_fields.append(struct_schema)
242242

243243
for f in fields.functions:
244-
function_schema = schema_types.FunctionSchema(
245-
name=f.name,
246-
description=f.description,
247-
type=f.type,
248-
input_field_names=f.input_field_names,
249-
output_field_names=f.output_field_names,
250-
)
251-
for k, v in f.params.items():
252-
kv_pair = common_types.KeyValuePair(key=str(k), value=str(v))
253-
function_schema.params.append(kv_pair)
244+
function_schema = cls.convert_function_to_function_schema(f)
254245
schema.functions.append(function_schema)
255246

256247
return schema
@@ -363,6 +354,34 @@ def get_schema(
363354
def drop_collection_request(cls, collection_name: str) -> milvus_types.DropCollectionRequest:
364355
return milvus_types.DropCollectionRequest(collection_name=collection_name)
365356

357+
@classmethod
358+
def drop_collection_function_request(
359+
cls, collection_name: str, function_name: str
360+
) -> milvus_types.DropCollectionFunctionRequest:
361+
return milvus_types.DropCollectionFunctionRequest(
362+
collection_name=collection_name, function_name=function_name
363+
)
364+
365+
@classmethod
366+
def add_collection_function_request(
367+
cls, collection_name: str, f: Function
368+
) -> milvus_types.AddCollectionFunctionRequest:
369+
function_schema = cls.convert_function_to_function_schema(f)
370+
return milvus_types.AddCollectionFunctionRequest(
371+
collection_name=collection_name, functionSchema=function_schema
372+
)
373+
374+
@classmethod
375+
def alter_collection_function_request(
376+
cls, collection_name: str, function_name: str, f: Function
377+
) -> milvus_types.AlterCollectionFunctionRequest:
378+
function_schema = cls.convert_function_to_function_schema(f)
379+
return milvus_types.AlterCollectionFunctionRequest(
380+
collection_name=collection_name,
381+
function_name=function_name,
382+
functionSchema=function_schema,
383+
)
384+
366385
@classmethod
367386
def add_collection_field_request(
368387
cls,
@@ -2424,3 +2443,17 @@ def update_replicate_configuration_request(
24242443
return milvus_types.UpdateReplicateConfigurationRequest(
24252444
replicate_configuration=replicate_configuration
24262445
)
2446+
2447+
@staticmethod
2448+
def convert_function_to_function_schema(f: Function) -> schema_types.FunctionSchema:
2449+
function_schema = schema_types.FunctionSchema(
2450+
name=f.name,
2451+
description=f.description,
2452+
type=f.type,
2453+
input_field_names=f.input_field_names,
2454+
output_field_names=f.output_field_names,
2455+
)
2456+
for k, v in f.params.items():
2457+
kv_pair = common_types.KeyValuePair(key=str(k), value=str(v))
2458+
function_schema.params.append(kv_pair)
2459+
return function_schema

pymilvus/grpc_gen/common_pb2.py

Lines changed: 24 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pymilvus/grpc_gen/common_pb2.pyi

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ class MsgType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
241241
AlterDatabase: _ClassVar[MsgType]
242242
DescribeDatabase: _ClassVar[MsgType]
243243
AddCollectionField: _ClassVar[MsgType]
244+
AlterWAL: _ClassVar[MsgType]
244245

245246
class DslType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
246247
__slots__ = ()
@@ -354,9 +355,7 @@ class ObjectPrivilege(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
354355
PrivilegeAddFileResource: _ClassVar[ObjectPrivilege]
355356
PrivilegeRemoveFileResource: _ClassVar[ObjectPrivilege]
356357
PrivilegeListFileResources: _ClassVar[ObjectPrivilege]
357-
PrivilegeAddCollectionFunction: _ClassVar[ObjectPrivilege]
358-
PrivilegeAlterCollectionFunction: _ClassVar[ObjectPrivilege]
359-
PrivilegeDropCollectionFunction: _ClassVar[ObjectPrivilege]
358+
PrivilegeUpdateReplicateConfiguration: _ClassVar[ObjectPrivilege]
360359

361360
class StateCode(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
362361
__slots__ = ()
@@ -608,6 +607,7 @@ ListDatabases: MsgType
608607
AlterDatabase: MsgType
609608
DescribeDatabase: MsgType
610609
AddCollectionField: MsgType
610+
AlterWAL: MsgType
611611
Dsl: DslType
612612
BoolExprV1: DslType
613613
UndefiedState: CompactionState
@@ -703,9 +703,7 @@ PrivilegeAddCollectionField: ObjectPrivilege
703703
PrivilegeAddFileResource: ObjectPrivilege
704704
PrivilegeRemoveFileResource: ObjectPrivilege
705705
PrivilegeListFileResources: ObjectPrivilege
706-
PrivilegeAddCollectionFunction: ObjectPrivilege
707-
PrivilegeAlterCollectionFunction: ObjectPrivilege
708-
PrivilegeDropCollectionFunction: ObjectPrivilege
706+
PrivilegeUpdateReplicateConfiguration: ObjectPrivilege
709707
Initializing: StateCode
710708
Healthy: StateCode
711709
Abnormal: StateCode

pymilvus/grpc_gen/milvus_pb2.py

Lines changed: 479 additions & 477 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pymilvus/grpc_gen/milvus_pb2.pyi

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ class ListAliasesResponse(_message.Message):
158158
def __init__(self, status: _Optional[_Union[_common_pb2.Status, _Mapping]] = ..., db_name: _Optional[str] = ..., collection_name: _Optional[str] = ..., aliases: _Optional[_Iterable[str]] = ...) -> None: ...
159159

160160
class CreateCollectionRequest(_message.Message):
161-
__slots__ = ("base", "db_name", "collection_name", "schema", "shards_num", "consistency_level", "properties", "num_partitions")
161+
__slots__ = ("base", "db_name", "collection_name", "schema", "shards_num", "consistency_level", "properties", "num_partitions", "external_source", "external_spec")
162162
BASE_FIELD_NUMBER: _ClassVar[int]
163163
DB_NAME_FIELD_NUMBER: _ClassVar[int]
164164
COLLECTION_NAME_FIELD_NUMBER: _ClassVar[int]
@@ -167,6 +167,8 @@ class CreateCollectionRequest(_message.Message):
167167
CONSISTENCY_LEVEL_FIELD_NUMBER: _ClassVar[int]
168168
PROPERTIES_FIELD_NUMBER: _ClassVar[int]
169169
NUM_PARTITIONS_FIELD_NUMBER: _ClassVar[int]
170+
EXTERNAL_SOURCE_FIELD_NUMBER: _ClassVar[int]
171+
EXTERNAL_SPEC_FIELD_NUMBER: _ClassVar[int]
170172
base: _common_pb2.MsgBase
171173
db_name: str
172174
collection_name: str
@@ -175,7 +177,9 @@ class CreateCollectionRequest(_message.Message):
175177
consistency_level: _common_pb2.ConsistencyLevel
176178
properties: _containers.RepeatedCompositeFieldContainer[_common_pb2.KeyValuePair]
177179
num_partitions: int
178-
def __init__(self, base: _Optional[_Union[_common_pb2.MsgBase, _Mapping]] = ..., db_name: _Optional[str] = ..., collection_name: _Optional[str] = ..., schema: _Optional[bytes] = ..., shards_num: _Optional[int] = ..., consistency_level: _Optional[_Union[_common_pb2.ConsistencyLevel, str]] = ..., properties: _Optional[_Iterable[_Union[_common_pb2.KeyValuePair, _Mapping]]] = ..., num_partitions: _Optional[int] = ...) -> None: ...
180+
external_source: str
181+
external_spec: str
182+
def __init__(self, base: _Optional[_Union[_common_pb2.MsgBase, _Mapping]] = ..., db_name: _Optional[str] = ..., collection_name: _Optional[str] = ..., schema: _Optional[bytes] = ..., shards_num: _Optional[int] = ..., consistency_level: _Optional[_Union[_common_pb2.ConsistencyLevel, str]] = ..., properties: _Optional[_Iterable[_Union[_common_pb2.KeyValuePair, _Mapping]]] = ..., num_partitions: _Optional[int] = ..., external_source: _Optional[str] = ..., external_spec: _Optional[str] = ...) -> None: ...
179183

180184
class DropCollectionRequest(_message.Message):
181185
__slots__ = ("base", "db_name", "collection_name")
@@ -1436,7 +1440,7 @@ class LoadBalanceRequest(_message.Message):
14361440
def __init__(self, base: _Optional[_Union[_common_pb2.MsgBase, _Mapping]] = ..., src_nodeID: _Optional[int] = ..., dst_nodeIDs: _Optional[_Iterable[int]] = ..., sealed_segmentIDs: _Optional[_Iterable[int]] = ..., collectionName: _Optional[str] = ..., db_name: _Optional[str] = ...) -> None: ...
14371441

14381442
class ManualCompactionRequest(_message.Message):
1439-
__slots__ = ("collectionID", "timetravel", "majorCompaction", "collection_name", "db_name", "partition_id", "channel", "segment_ids", "l0Compaction")
1443+
__slots__ = ("collectionID", "timetravel", "majorCompaction", "collection_name", "db_name", "partition_id", "channel", "segment_ids", "l0Compaction", "target_size")
14401444
COLLECTIONID_FIELD_NUMBER: _ClassVar[int]
14411445
TIMETRAVEL_FIELD_NUMBER: _ClassVar[int]
14421446
MAJORCOMPACTION_FIELD_NUMBER: _ClassVar[int]
@@ -1446,6 +1450,7 @@ class ManualCompactionRequest(_message.Message):
14461450
CHANNEL_FIELD_NUMBER: _ClassVar[int]
14471451
SEGMENT_IDS_FIELD_NUMBER: _ClassVar[int]
14481452
L0COMPACTION_FIELD_NUMBER: _ClassVar[int]
1453+
TARGET_SIZE_FIELD_NUMBER: _ClassVar[int]
14491454
collectionID: int
14501455
timetravel: int
14511456
majorCompaction: bool
@@ -1455,7 +1460,8 @@ class ManualCompactionRequest(_message.Message):
14551460
channel: str
14561461
segment_ids: _containers.RepeatedScalarFieldContainer[int]
14571462
l0Compaction: bool
1458-
def __init__(self, collectionID: _Optional[int] = ..., timetravel: _Optional[int] = ..., majorCompaction: bool = ..., collection_name: _Optional[str] = ..., db_name: _Optional[str] = ..., partition_id: _Optional[int] = ..., channel: _Optional[str] = ..., segment_ids: _Optional[_Iterable[int]] = ..., l0Compaction: bool = ...) -> None: ...
1463+
target_size: int
1464+
def __init__(self, collectionID: _Optional[int] = ..., timetravel: _Optional[int] = ..., majorCompaction: bool = ..., collection_name: _Optional[str] = ..., db_name: _Optional[str] = ..., partition_id: _Optional[int] = ..., channel: _Optional[str] = ..., segment_ids: _Optional[_Iterable[int]] = ..., l0Compaction: bool = ..., target_size: _Optional[int] = ...) -> None: ...
14591465

14601466
class ManualCompactionResponse(_message.Message):
14611467
__slots__ = ("status", "compactionID", "compactionPlanCount")

0 commit comments

Comments
 (0)