AI_CLASSIFY identifie le libellé correspondant le mieux à un texte, une image ou une vidéo parmi un ensemble de candidats. Cette fonctionnalité facilite le routage des tickets, la modération de contenu et l'étiquetage des catégories de produits. Configurée en tant que Collection Function, AI_CLASSIFY renseigne automatiquement le champ de classification lors de l'écriture des données.
Format de la commande
Appelez l'API REST pour classifier du contenu directement, ou configurez une Collection Function pour automatiser cette opération lors des écritures. L'API REST propose deux endpoints :
/v2/vectordb/ai/text_transform— Ajoutez"task": "ai_classify"dans le corps de la requête./v2/vectordb/ai/classify— Le champtaskest facultatif.
REST API
@id="cmdtabbcls001"
REST API
@id="c0004c9x7t"
Envoyez la requête suivante pour classifier le contenu en entrée :
POST /v2/vectordb/ai/text_transform
Content-Type: application/json
{
"model_name": "<model name>",
"task": "ai_classify",
"texts": ["<text or media URL>"],
"params": {"labels": ["<label1>", "<label2>"]}
}
@id="cmdrestscls01"
@id="cmdresthcls01"
Python
@id="cmdpyseccls01"
Python
@id="cmdpycodcls01"
Définissez une Collection Function pour classifier automatiquement le contenu lors de l'écriture des données :
schema = MilvusClient.create_schema(auto_id=True, enable_dynamic_field=False)
schema.add_field("id", DataType.INT64, is_primary=True)
schema.add_field("content", DataType.VARCHAR, max_length=4096)
schema.add_field("category", DataType.VARCHAR, max_length=64)
schema.add_field("dummy_vector", DataType.FLOAT_VECTOR, dim=2)
schema.add_function(
Function(
name="classify_content",
function_type=texttransform_function_type(),
input_field_names=["content"],
output_field_names=["category"],
params={
"provider": "aliyun_milvus",
"model_name": "<model name>",
"task": "ai_classify",
"labels": "accounts,inquiries,faults,billing",
"prompt": "Classify by the topic of the customer's question.",
"temperature": "0",
"max_concurrency": "2",
},
)
)
@id="cmdpyhcls0001"
Paramètres
| @id="p0046c9x7t" Paramètre | @id="p0048c9x7t" Description |
@id="p0008c9x7t" model_name |
@id="p0010c9x7t" Obligatoire. Nom du modèle. Pour les images et vidéos, sélectionnez un modèle multimodal configuré (par exemple, qwen3.7-plus). |
@id="p0013c9x7t" texts |
@id="p0015c9x7t" Obligatoire pour l'API REST. Contenu à classifier, ou URL d'une image ou d'une vidéo. |
@id="p0018c9x7t" labels |
@id="p0020c9x7t" Obligatoire. Libellés candidats fournis sous forme de tableau JSON ou de chaîne séparée par des virgules. De 2 à 20 libellés sont pris en charge. |
@id="p0023c9x7t" prompt |
@id="p0025c9x7t" Facultatif. Règles de routage supplémentaires, jusqu'à 5 000 caractères. La syntaxe ${...} n'est pas prise en charge. |
@id="p0028c9x7t" media_type |
@id="p0030c9x7t" Facultatif. Définissez ce paramètre sur image ou video pour indiquer que l'entrée correspond à une URL de média. |
@id="p0033c9x7t" temperature / max_concurrency / timeout_sec |
@id="p0035c9x7t" Facultatif. Contrôle la stabilité du modèle, la concurrence et le délai d'expiration. La classification vidéo étant longue, définissez timeout_sec sur 300 ou plus pour éviter les dépassements de délai. |
@id="p0038c9x7t" provider / task |
@id="p0040c9x7t" Obligatoire uniquement pour Collection Function. Valeurs fixes : aliyun_milvus et ai_classify. |
Valeurs de retour
data.output.outputs renvoie le texte du libellé dans le même ordre que l'entrée, sans autre contenu. Le schéma inscrit ensuite ce libellé dans le champ texte cible.
Exemple 1 : Routage automatique des tickets clients (texte)
Un système de service client doit diriger les tickets d'incident et de demande vers des files d'attente distinctes. Lors de l'appel à l'endpoint unifié /v2/vectordb/ai/text_transform, ajoutez le champ task au niveau supérieur de la requête.
REST API
@id="tab0057c9x7t"
REST API
@id="c0052c9x7t"
#!/usr/bin/env bash
set -euo pipefail
MILVUS_REST_BASE_URL="http://c-xxxx.milvus.aliyuncs.com:19530"
MILVUS_AUTH_TOKEN="<yourUsername>:<yourPassword>"
post_json() {
local path="$1"
local body="$2"
curl -X POST \
"$MILVUS_REST_BASE_URL$path" \
-H "Authorization: Bearer $MILVUS_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d "$body"
}
BODY=$(cat <<'JSON'
{
"model_name": "qwen3.7-max",
"task": "ai_classify",
"texts": [
"Cannot log in to the Milvus console; verification code error keeps appearing.",
"How do I enable public network access for a Serverless Milvus instance?"
],
"params": {
"labels": ["accounts", "inquiries", "faults", "billing"],
"prompt": "Classify by the topic of the customer's question.",
"temperature": 0,
"max_concurrency": 2
}
}
JSON
)
RESPONSE_BODY="$(post_json "/v2/vectordb/ai/text_transform" "$BODY")"
if command -v jq >/dev/null 2>&1; then
echo "$RESPONSE_BODY" | jq .
[ "$(echo "$RESPONSE_BODY" | jq -r '.code // -1')" = "0" ] || exit 1
else
echo "$RESPONSE_BODY"
fi
@id="rt0058c9x7t"
@id="h0059c9x7t"
Python
@id="pt0060c9x7t"
Python
@id="c0053c9x7t"
from __future__ import annotations
from typing import Any
from pymilvus import DataType, Function, FunctionType, MilvusClient
MILVUS_URI = "http://c-xxxx.milvus.aliyuncs.com:19530"
MILVUS_TOKEN = "<yourUsername>:<yourPassword>"
DUMMY_VECTOR_DIM = 2
TEXTTRANSFORM_FUNCTION_TYPE = 9
def texttransform_function_type() -> Any:
for type_name in ("TEXTTRANSFORM", "TEXT_TRANSFORM", "TextTransform"):
function_type = getattr(FunctionType, type_name, None)
if function_type is not None:
return function_type
# Alibaba Cloud Milvus provides TEXTTRANSFORM as a managed extension (function type value 9);
# some pymilvus versions do not include this enum member, while Function(...) validates through FunctionType(...).
existing = getattr(FunctionType, "_value2member_map_", {}).get(TEXTTRANSFORM_FUNCTION_TYPE)
if existing is not None:
return existing
extension = int.__new__(FunctionType, TEXTTRANSFORM_FUNCTION_TYPE)
extension._name_ = "TEXTTRANSFORM"
extension._value_ = TEXTTRANSFORM_FUNCTION_TYPE
FunctionType._value2member_map_[TEXTTRANSFORM_FUNCTION_TYPE] = extension
FunctionType._member_map_["TEXTTRANSFORM"] = extension
return extension
def add_id(schema: Any) -> None:
schema.add_field("id", DataType.INT64, is_primary=True)
def add_dummy_vector(schema: Any) -> None:
schema.add_field("dummy_vector", DataType.FLOAT_VECTOR, dim=DUMMY_VECTOR_DIM)
def run_texttransform_example(*, client, collection_name, input_fields, output_field, function_name, function_params, rows) -> None:
if client.has_collection(collection_name):
client.drop_collection(collection_name)
schema = MilvusClient.create_schema(auto_id=True, enable_dynamic_field=False)
add_id(schema)
for name, data_type, max_length in input_fields:
field_params = {"max_length": max_length} if max_length is not None else {}
schema.add_field(name, data_type, **field_params)
output_name, output_data_type, output_max_length = output_field
output_params = {"max_length": output_max_length} if output_max_length is not None else {}
schema.add_field(output_name, output_data_type, **output_params)
add_dummy_vector(schema)
schema.add_function(
Function(
name=function_name,
function_type=texttransform_function_type(),
input_field_names=[name for name, _, _ in input_fields],
output_field_names=[output_name],
params=function_params,
)
)
index_params = client.prepare_index_params()
index_params.add_index(field_name="dummy_vector", index_type="AUTOINDEX", metric_type="COSINE")
client.create_collection(collection_name=collection_name, schema=schema, index_params=index_params)
client.insert(collection_name, rows)
client.flush(collection_name)
fields = [name for name, _, _ in input_fields] + [output_name]
for row in client.query(collection_name, filter="", output_fields=fields, limit=len(rows)):
print(row)
client = MilvusClient(uri=MILVUS_URI, token=MILVUS_TOKEN)
run_texttransform_example(
client=client,
collection_name="simple_ai_classify",
input_fields=[("content", DataType.VARCHAR, 4096)],
output_field=("category", DataType.VARCHAR, 64),
function_name="simple_ai_classify_fn",
function_params={"provider": "aliyun_milvus", "model_name": "qwen3.7-max", "task": "ai_classify", "labels": "accounts,inquiries,faults,billing", "prompt": "Classify by the topic of the customer's question.", "temperature": "0", "max_concurrency": "2"},
rows=[{"content": "Cannot log in to the Milvus console; verification code error keeps appearing.", "dummy_vector": [0.1, 0.2]}, {"content": "How do I enable public network access for a Serverless Milvus instance?", "dummy_vector": [0.1, 0.2]}],
)
@id="h0061c9x7t"
Résultat attendu : Chaque entrée REST renvoie un libellé candidat (lors des tests : accounts et inquiries). Dans les enregistrements Python, le champ category contient le libellé candidat correspondant. Les problèmes liés à la connexion et aux codes de vérification sont dirigés vers accounts ou faults selon l'analyse du modèle.
Exemple 2 : Classification d'images de produits (image)
Un système de modération de contenu doit attribuer automatiquement les images aux catégories vêtements, nourriture, paysage ou animaux.
REST API
@id="tab0068c9x7t"
REST API
@id="c0063c9x7t"
#!/usr/bin/env bash
set -euo pipefail
MILVUS_REST_BASE_URL="http://c-xxxx.milvus.aliyuncs.com:19530"
MILVUS_AUTH_TOKEN="<yourUsername>:<yourPassword>"
post_json() {
local path="$1"
local body="$2"
curl -X POST \
"$MILVUS_REST_BASE_URL$path" \
-H "Authorization: Bearer $MILVUS_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d "$body"
}
BODY=$(cat <<JSON
{"model_name":"qwen3.7-plus","texts":["https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20260415/hynnff/wan-video-edit-clothes.webp"],"params":{"media_type":"image","labels":["clothing","food","landscape","animal"],"temperature":0}}
JSON
)
RESPONSE_BODY="$(post_json "/v2/vectordb/ai/classify" "$BODY")"
if command -v jq >/dev/null 2>&1; then
echo "$RESPONSE_BODY" | jq .
[ "$(echo "$RESPONSE_BODY" | jq -r '.code // -1')" = "0" ] || exit 1
else
echo "$RESPONSE_BODY"
fi
@id="rt0069c9x7t"
@id="h0070c9x7t"
Python
@id="pt0071c9x7t"
Python
@id="c0064c9x7t"
from __future__ import annotations
from typing import Any
from pymilvus import DataType, Function, FunctionType, MilvusClient
MILVUS_URI = "http://c-xxxx.milvus.aliyuncs.com:19530"
MILVUS_TOKEN = "<yourUsername>:<yourPassword>"
DUMMY_VECTOR_DIM = 2
TEXTTRANSFORM_FUNCTION_TYPE = 9
def texttransform_function_type() -> Any:
for type_name in ("TEXTTRANSFORM", "TEXT_TRANSFORM", "TextTransform"):
function_type = getattr(FunctionType, type_name, None)
if function_type is not None:
return function_type
# Alibaba Cloud Milvus provides TEXTTRANSFORM as a managed extension (function type value 9);
# some pymilvus versions do not include this enum member, while Function(...) validates through FunctionType(...).
existing = getattr(FunctionType, "_value2member_map_", {}).get(TEXTTRANSFORM_FUNCTION_TYPE)
if existing is not None:
return existing
extension = int.__new__(FunctionType, TEXTTRANSFORM_FUNCTION_TYPE)
extension._name_ = "TEXTTRANSFORM"
extension._value_ = TEXTTRANSFORM_FUNCTION_TYPE
FunctionType._value2member_map_[TEXTTRANSFORM_FUNCTION_TYPE] = extension
FunctionType._member_map_["TEXTTRANSFORM"] = extension
return extension
def add_id(schema: Any) -> None:
schema.add_field("id", DataType.INT64, is_primary=True)
def add_dummy_vector(schema: Any) -> None:
schema.add_field("dummy_vector", DataType.FLOAT_VECTOR, dim=DUMMY_VECTOR_DIM)
def run_texttransform_example(*, client, collection_name, input_fields, output_field, function_name, function_params, rows) -> None:
if client.has_collection(collection_name):
client.drop_collection(collection_name)
schema = MilvusClient.create_schema(auto_id=True, enable_dynamic_field=False)
add_id(schema)
for name, data_type, max_length in input_fields:
field_params = {"max_length": max_length} if max_length is not None else {}
schema.add_field(name, data_type, **field_params)
output_name, output_data_type, output_max_length = output_field
output_params = {"max_length": output_max_length} if output_max_length is not None else {}
schema.add_field(output_name, output_data_type, **output_params)
add_dummy_vector(schema)
schema.add_function(
Function(
name=function_name,
function_type=texttransform_function_type(),
input_field_names=[name for name, _, _ in input_fields],
output_field_names=[output_name],
params=function_params,
)
)
index_params = client.prepare_index_params()
index_params.add_index(field_name="dummy_vector", index_type="AUTOINDEX", metric_type="COSINE")
client.create_collection(collection_name=collection_name, schema=schema, index_params=index_params)
client.insert(collection_name, rows)
client.flush(collection_name)
fields = [name for name, _, _ in input_fields] + [output_name]
for row in client.query(collection_name, filter="", output_fields=fields, limit=len(rows)):
print(row)
client = MilvusClient(uri=MILVUS_URI, token=MILVUS_TOKEN)
run_texttransform_example(
client=client,
collection_name="simple_ai_classify_image",
input_fields=[("image_url", DataType.VARCHAR, 4096)],
output_field=("category", DataType.VARCHAR, 64),
function_name="simple_ai_classify_image_fn",
function_params={"provider": "aliyun_milvus", "model_name": "qwen3.7-plus", "task": "ai_classify", "media_type": "image", "labels": "clothing,food,landscape,animal", "temperature": "0"},
rows=[{"image_url": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20260415/hynnff/wan-video-edit-clothes.webp", "dummy_vector": [0.1, 0.2]}],
)
@id="h0072c9x7t"
Résultat attendu : Le champ category renvoie l'une des valeurs suivantes : clothing, food, landscape ou animal (lors des tests : clothing).
Exemple 3 : Classification de contenus vidéo (vidéo)
Une équipe chargée des opérations vidéo doit filtrer les contenus selon les catégories mode, sport, voyage et animation. L'inférence vidéo étant longue, définissez timeout_sec sur 300 ou plus.
REST API
@id="tab0079c9x7t"
REST API
@id="c0074c9x7t"
#!/usr/bin/env bash
set -euo pipefail
MILVUS_REST_BASE_URL="http://c-xxxx.milvus.aliyuncs.com:19530"
MILVUS_AUTH_TOKEN="<yourUsername>:<yourPassword>"
post_json() {
local path="$1"
local body="$2"
curl -X POST \
"$MILVUS_REST_BASE_URL$path" \
-H "Authorization: Bearer $MILVUS_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d "$body"
}
BODY=$(cat <<JSON
{"model_name":"qwen3.7-plus","texts":["https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20260409/dozxak/Wan_Video_Edit_33_1.mp4"],"params":{"media_type":"video","labels":["fashion","sports","travel","animation"],"temperature":0,"timeout_sec":300}}
JSON
)
RESPONSE_BODY="$(post_json "/v2/vectordb/ai/classify" "$BODY")"
if command -v jq >/dev/null 2>&1; then
echo "$RESPONSE_BODY" | jq .
[ "$(echo "$RESPONSE_BODY" | jq -r '.code // -1')" = "0" ] || exit 1
else
echo "$RESPONSE_BODY"
fi
@id="rt0080c9x7t"
@id="h0081c9x7t"
Python
@id="pt0082c9x7t"
Python
@id="c0075c9x7t"
from __future__ import annotations
from typing import Any
from pymilvus import DataType, Function, FunctionType, MilvusClient
MILVUS_URI = "http://c-xxxx.milvus.aliyuncs.com:19530"
MILVUS_TOKEN = "<yourUsername>:<yourPassword>"
DUMMY_VECTOR_DIM = 2
TEXTTRANSFORM_FUNCTION_TYPE = 9
def texttransform_function_type() -> Any:
for type_name in ("TEXTTRANSFORM", "TEXT_TRANSFORM", "TextTransform"):
function_type = getattr(FunctionType, type_name, None)
if function_type is not None:
return function_type
# Alibaba Cloud Milvus provides TEXTTRANSFORM as a managed extension (function type value 9);
# some pymilvus versions do not include this enum member, while Function(...) validates through FunctionType(...).
existing = getattr(FunctionType, "_value2member_map_", {}).get(TEXTTRANSFORM_FUNCTION_TYPE)
if existing is not None:
return existing
extension = int.__new__(FunctionType, TEXTTRANSFORM_FUNCTION_TYPE)
extension._name_ = "TEXTTRANSFORM"
extension._value_ = TEXTTRANSFORM_FUNCTION_TYPE
FunctionType._value2member_map_[TEXTTRANSFORM_FUNCTION_TYPE] = extension
FunctionType._member_map_["TEXTTRANSFORM"] = extension
return extension
def add_id(schema: Any) -> None:
schema.add_field("id", DataType.INT64, is_primary=True)
def add_dummy_vector(schema: Any) -> None:
schema.add_field("dummy_vector", DataType.FLOAT_VECTOR, dim=DUMMY_VECTOR_DIM)
def run_texttransform_example(*, client, collection_name, input_fields, output_field, function_name, function_params, rows) -> None:
if client.has_collection(collection_name):
client.drop_collection(collection_name)
schema = MilvusClient.create_schema(auto_id=True, enable_dynamic_field=False)
add_id(schema)
for name, data_type, max_length in input_fields:
field_params = {"max_length": max_length} if max_length is not None else {}
schema.add_field(name, data_type, **field_params)
output_name, output_data_type, output_max_length = output_field
output_params = {"max_length": output_max_length} if output_max_length is not None else {}
schema.add_field(output_name, output_data_type, **output_params)
add_dummy_vector(schema)
schema.add_function(
Function(
name=function_name,
function_type=texttransform_function_type(),
input_field_names=[name for name, _, _ in input_fields],
output_field_names=[output_name],
params=function_params,
)
)
index_params = client.prepare_index_params()
index_params.add_index(field_name="dummy_vector", index_type="AUTOINDEX", metric_type="COSINE")
client.create_collection(collection_name=collection_name, schema=schema, index_params=index_params)
client.insert(collection_name, rows)
client.flush(collection_name)
fields = [name for name, _, _ in input_fields] + [output_name]
for row in client.query(collection_name, filter="", output_fields=fields, limit=len(rows)):
print(row)
client = MilvusClient(uri=MILVUS_URI, token=MILVUS_TOKEN)
run_texttransform_example(
client=client,
collection_name="simple_ai_classify_video",
input_fields=[("video_url", DataType.VARCHAR, 4096)],
output_field=("category", DataType.VARCHAR, 64),
function_name="simple_ai_classify_video_fn",
function_params={"provider": "aliyun_milvus", "model_name": "qwen3.7-plus", "task": "ai_classify", "media_type": "video", "labels": "fashion,sports,travel,animation", "temperature": "0", "timeout_sec": "300"},
rows=[{"video_url": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20260409/dozxak/Wan_Video_Edit_33_1.mp4", "dummy_vector": [0.1, 0.2]}],
)
@id="h0083c9x7t"
Résultat attendu : Le champ category renvoie l'une des valeurs suivantes : fashion, sports, travel ou animation (lors des tests : animation). Si le message {"code":10001,"message":"request timeout"} s'affiche, augmentez la valeur de timeout_sec.