La fonction AI_SENTIMENT classe les textes, images ou vidéos dans la catégorie de sentiment la plus pertinente. Utilisez-la pour analyser les avis clients, étiqueter du contenu promotionnel et alimenter les tableaux de bord opérationnels.
Format de la commande
Cette rubrique présente deux méthodes d'utilisation de AI_SENTIMENT : un appel direct à l'API REST pour une analyse à la demande, et une fonction de collection Python qui associe l'analyse des sentiments au schéma d'une collection afin de classifier automatiquement les données lors de leur insertion.
REST API
REST API
@id="c0053k7q2t53"
POST /v2/vectordb/ai/sentiment
Content-Type: application/json
{
"model_name": "<model_name>",
"texts": ["<text or media URL>"],
"params": {"categories": ["positive", "negative", "neutral"]}
}
Python (collection function)
@id="cmdpysecsen01"
Python (collection function)
@id="cmdpycodsen01"
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("sentiment", DataType.VARCHAR, max_length=64)
schema.add_field("dummy_vector", DataType.FLOAT_VECTOR, dim=2)
schema.add_function(
Function(
name="analyze_sentiment",
function_type=texttransform_function_type(),
input_field_names=["content"],
output_field_names=["sentiment"],
params={
"provider": "aliyun_milvus",
"model_name": "<model_name>",
"task": "ai_sentiment",
"categories": "positive,negative,neutral",
"temperature": "0",
},
)
)
@id="cmdpyhsen0001"
Paramètres
| @id="p0060k7q2t60" Paramètre | @id="p0062k7q2t62" Description |
@id="p0003k7q2t03" model_name |
@id="p0005k7q2t05" Obligatoire. Nom du modèle. Pour les images et les vidéos, spécifiez un modèle multimodal tel que qwen3.7-plus. |
@id="p0008k7q2t08" texts |
@id="p0010k7q2t10" Obligatoire pour l'API REST. Contenu à analyser ou URL d'images ou de vidéos accessibles au modèle. |
@id="p0013k7q2t13" categories |
@id="p0015k7q2t15" Facultatif. Catégories de sentiments. Accepte un tableau ou une chaîne séparée par des virgules. De 1 à 10 catégories sont prises en charge. Valeurs par défaut : positive, negative, neutral et mixed. |
@id="p0018k7q2t18" prompt |
@id="p0020k7q2t20" Facultatif. Règles d'évaluation supplémentaires. Maximum de 5 000 caractères. La syntaxe ${...} n'est pas prise en charge. |
@id="p0023k7q2t23" media_type |
@id="p0025k7q2t25" Facultatif. Valeurs valides : image, video. |
@id="p0028k7q2t28" temperature / max_concurrency / timeout_sec |
@id="p0030k7q2t30" Facultatif. Paramètres de stabilité du modèle, de concurrence et de délai d'expiration. |
@id="p0033k7q2t33" provider / task |
@id="p0035k7q2t35" Obligatoire uniquement pour la fonction de collection. Valeurs fixes : aliyun_milvus et ai_sentiment. |
Réponse
data.output.outputs renvoie les catégories de sentiment dans le même ordre que les données d'entrée. Chaque résultat non nul correspond à l'une des catégories définies dans le champ categories de la requête. La valeur null est renvoyée lorsque le sentiment ne peut pas être déterminé. Avec une fonction de collection, le résultat s'écrit directement dans le champ texte cible.
Exemple 1 : Créer un tableau de bord des sentiments pour les avis après-vente (texte)
L'équipe après-vente classe les avis dans des catégories prédéfinies et les agrège dans un tableau de bord. Chaque résultat appartient soit à l'une des catégories spécifiées, soit à la valeur null.
REST API
REST API
@id="c0072k7q2t72"
#!/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",
"texts": [
"The food was excellent and the service was thoughtful.",
"The product arrived late and the package was damaged."
],
"params": {"temperature": 0}
}
JSON
)
RESPONSE_BODY="$(post_json "/v2/vectordb/ai/sentiment" "$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
Python
@id="pt0073k7q2t73"
Python
@id="c0075k7q2t75"
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 have this enum member built in, and Function(...) validates via 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_sentiment_text",
input_fields=[("content", DataType.VARCHAR, 4096)],
output_field=("sentiment", DataType.VARCHAR, 64),
function_name="analyze_sentiment",
function_params={"provider": "aliyun_milvus", "model_name": "qwen3.7-max", "task": "ai_sentiment", "categories": "positive,negative,neutral", "temperature": "0"},
rows=[{"content": "The food was excellent and the service was thoughtful.", "dummy_vector": [0.1, 0.2]}],
)
@id="h0074k7q2t74"
Résultat attendu : Les résultats sont renvoyés dans le même ordre que les entrées. Chaque résultat correspond à l'une des catégories déclarées ou à null. Côté métier, seules les catégories non nulles sont agrégées. La valeur null est comptabilisée comme indéterminée et dirigée vers une vérification manuelle.
Exemple 2 : Étiqueter le sentiment d'images promotionnelles de vêtements (image)
L'équipe opérationnelle utilise le modèle pour générer trois libellés de sentiment, puis les valide en fonction du ton de la marque. Aucune catégorie n'est imposée par défaut. Les retours avec la valeur null sont également acceptés.
REST API
REST API
@id="c0083k7q2t83"
#!/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","categories":["positive","negative","neutral"],"temperature":0}}
JSON
)
RESPONSE_BODY="$(post_json "/v2/vectordb/ai/sentiment" "$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
Python
@id="pt0084k7q2t84"
Python
@id="c0086k7q2t86"
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 have this enum member built in, and Function(...) validates via 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_sentiment_image",
input_fields=[("image_url", DataType.VARCHAR, 4096)],
output_field=("sentiment", DataType.VARCHAR, 64),
function_name="analyze_image_sentiment",
function_params={"provider": "aliyun_milvus", "model_name": "qwen3.7-plus", "task": "ai_sentiment", "media_type": "image", "categories": "positive,negative,neutral", "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="h0085k7q2t85"
Résultat attendu : Le résultat est soit positive, negative, neutral, soit null. Ce libellé de sentiment ne constitue pas un jugement factuel sur l'état psychologique de la personne représentée sur l'image.
Exemple 3 : Étiqueter le sentiment de vidéos courtes avec personnages anthropomorphes (vidéo)
Une plateforme de contenu applique un étiquetage initial des sentiments sur des vidéos courtes pour faciliter la recherche éditoriale et la vérification. Chaque résultat appartient à l'une des catégories déclarées ou prend la valeur null.
REST API
REST API
@id="c0094k7q2t94"
#!/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","categories":["positive","negative","neutral"],"temperature":0}}
JSON
)
RESPONSE_BODY="$(post_json "/v2/vectordb/ai/sentiment" "$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
Python
@id="pt0095k7q2t95"
Python
@id="c0097k7q2t00"
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 have this enum member built in, and Function(...) validates via 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_sentiment_video",
input_fields=[("video_url", DataType.VARCHAR, 4096)],
output_field=("sentiment", DataType.VARCHAR, 64),
function_name="analyze_video_sentiment",
function_params={"provider": "aliyun_milvus", "model_name": "qwen3.7-plus", "task": "ai_sentiment", "media_type": "video", "categories": "positive,negative,neutral", "temperature": "0"},
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="h0096k7q2t96"
Résultat attendu : Le résultat correspond à l'une des trois catégories déclarées ou à null. Seuls les libellés non nuls sont inclus dans l'agrégation. Une vérification manuelle reste recommandée avant toute action à fort impact.