Tous les produits
Search
Centre de documentation

Vector Retrieval Service for Milvus:Reconnaissance d'entités nommées

Dernière mise à jour :Aug 12, 2026

La fonction AI_ENTITY_EXTRACT identifie les entités nommées telles que les personnes, organisations, lieux, dates et montants dans des textes, images ou vidéos. Utilisez cette fonction pour l'indexation d'articles de presse, l'annotation de ressources multimédias et la recherche d'événements.

Format de la commande

Appelez AI_ENTITY_EXTRACT via l'API REST ou la Collection Function Python.

API REST

POST /v2/vectordb/ai/entity_extract
Content-Type: application/json

{
  "model_name": "<model name>",
  "texts": ["<text or media URL>"],
  "params": {"entity_types": ["PERSON", "ORGANIZATION"]}
}

Python

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("entities", DataType.JSON)
schema.add_field("dummy_vector", DataType.FLOAT_VECTOR, dim=2)
schema.add_function(
    Function(
        name="extract_entities",
        function_type=texttransform_function_type(),
        input_field_names=["content"],
        output_field_names=["entities"],
        params={
            "provider": "aliyun_milvus",
            "model_name": "<model name>",
            "task": "ai_entity_extract",
            "entity_types": "PERSON,ORGANIZATION,LOCATION,DATE,PRODUCT",
            "temperature": "0",
        },
    )
)

Paramètres

@id="p0082e6t1x" Paramètre @id="p0084e6t1x" Description
@id="p0003e6t1x" model_name @id="p0005e6t1x" Obligatoire. Nom du modèle. Pour l'extraction de texte, utilisez un modèle textuel (par exemple, qwen3.7-max). Pour les images et vidéos, utilisez un modèle multimodal configuré (par exemple, qwen3.7-plus).
@id="p0008e6t1x" texts @id="p0010e6t1x" Obligatoire pour l'API REST. Texte à analyser, ou URL d'images et de vidéos accessibles au modèle.
@id="p0013e6t1x" entity_types @id="p0015e6t1x" Facultatif. Types d'entités cibles. Accepte un tableau ou une chaîne séparée par des virgules, contenant entre 1 et 30 entrées. Par défaut, la fonction reconnaît les personnes, organisations, lieux, produits, événements, dates, heures, montants, pourcentages, URL, adresses e-mail, numéros de téléphone et adresses IP.
@id="p0018e6t1x" prompt @id="p0020e6t1x" Facultatif. Règles de reconnaissance supplémentaires (5 000 caractères maximum). La syntaxe ${...} n'est pas prise en charge. Pour les contenus multimédias, incluez des instructions telles que « ne pas déduire l'identité, la marque ou le lieu d'après l'apparence » (recommandé).
@id="p0023e6t1x" media_type @id="p0025e6t1x" Facultatif. Définissez cette valeur sur image ou video pour indiquer que l'entrée correspond à une URL de média.
@id="p0028e6t1x" temperature/max_concurrency/timeout_sec @id="p0030e6t1x" Facultatif. Paramètres de stabilité du modèle, de concurrence et de délai d'expiration.
@id="p0033e6t1x" provider/task @id="p0035e6t1x" Obligatoire uniquement pour la Collection Function. Valeurs fixes : aliyun_milvus et ai_entity_extract.

Valeur de retour

Chaque sortie est un objet JSON au format {"entities":[{"text":"entity text","type":"entity type"}]}, ou une chaîne JSON correspondant à cette même structure. Chaque élément du tableau entities comprend un champ text non vide ainsi qu'un champ type issu de la requête. En l'absence d'entité nommée valide, le résultat {"entities":[]} reste valide. Le schéma écrit alors un JSON valide dans le champ de sortie.

Exemple 1 : Création d'un index d'entités pour des articles de presse (texte)

Une plateforme de contenu extrait les personnes, organisations, lieux, dates et produits explicitement mentionnés dans des articles de presse afin de les utiliser comme filtres de recherche. Cet exemple vérifie la structure JSON et les types retournés, sans exiger que le modèle renvoie exactement la même liste d'entités.

API REST

#!/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": [
    "In March 2024, Zhang San joined Alibaba in Hangzhou to work on Milvus."
  ],
  "params": {
    "entity_types": ["PERSON", "ORGANIZATION", "LOCATION", "DATE", "PRODUCT"],
    "temperature": 0
  }
}
JSON
)
RESPONSE_BODY="$(post_json "/v2/vectordb/ai/entity_extract" "$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

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, while 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_entity_extract_text",
    input_fields=[("content", DataType.VARCHAR, 4096)],
    output_field=("entities", DataType.JSON, None),
    function_name="extract_entities",
    function_params={"provider": "aliyun_milvus", "model_name": "qwen3.7-max", "task": "ai_entity_extract", "entity_types": "PERSON,ORGANIZATION,LOCATION,DATE,PRODUCT", "temperature": "0"},
    rows=[{"content": "In March 2024, Zhang San joined Alibaba in Hangzhou to work on Milvus.", "dummy_vector": [0.1, 0.2]}],
)

Vérification

Chaque élément du tableau entities contient un champ text non vide et une valeur type appartenant à l'ensemble demandé. Voici un exemple de résultat obtenu lors d'un test réel :

{"entities":[{"text":"March 2024","type":"DATE"},{"text":"Zhang San","type":"PERSON"},{"text":"Alibaba","type":"ORGANIZATION"},{"text":"Hangzhou","type":"LOCATION"},{"text":"Milvus","type":"PRODUCT"}]}

Les limites exactes des entités dépendent du modèle utilisé et des règles de reconnaissance appliquées.

Exemple 2 : Analyse d'entités nommées dans une image promotionnelle de mode (image)

Une médiathèque reçoit l'image d'une personne portant un haut rayé noir et blanc et tenant un sac noir. Ces éléments visuels ne permettent pas de confirmer un nom de personne, une marque, un nom de produit ou un lieu spécifique. Cet exemple interdit explicitement toute supposition et accepte un tableau d'entités vide comme résultat valide.

API REST

#!/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","entity_types":["PERSON","PRODUCT","LOCATION"],"temperature":0}}
JSON
)
RESPONSE_BODY="$(post_json "/v2/vectordb/ai/entity_extract" "$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

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, while 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_entity_extract_image",
    input_fields=[("image_url", DataType.VARCHAR, 4096)],
    output_field=("entities", DataType.JSON, None),
    function_name="extract_image_entities",
    function_params={"provider": "aliyun_milvus", "model_name": "qwen3.7-plus", "task": "ai_entity_extract", "media_type": "image", "entity_types": "PERSON,PRODUCT,LOCATION", "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]}],
)

Vérification

La sortie constitue un objet d'entités valide dont chaque élément possède un champ type appartenant à l'ensemble demandé. Si l'image ne fournit pas suffisamment d'éléments pour confirmer des entités nommées, le résultat {"entities":[]} est valide.

Exemple 3 : Analyse d'entités nommées dans une vidéo représentant un personnage cheval humanoïde (vidéo)

Une ressource vidéo montre en gros plan un personnage cheval humanoïde vêtu d'un costume. L'apparence de ce personnage ne permet pas d'établir l'identité d'une personne réelle, le titre d'une œuvre, une marque ou un lieu. Cet exemple applique la règle « extraire uniquement en présence de preuves tangibles » ; un tableau d'entités vide constitue donc un résultat valide.

API REST

#!/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","entity_types":["PERSON","PRODUCT","LOCATION"],"temperature":0}}
JSON
)
RESPONSE_BODY="$(post_json "/v2/vectordb/ai/entity_extract" "$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

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, while 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_entity_extract_video",
    input_fields=[("video_url", DataType.VARCHAR, 4096)],
    output_field=("entities", DataType.JSON, None),
    function_name="extract_video_entities",
    function_params={"provider": "aliyun_milvus", "model_name": "qwen3.7-plus", "task": "ai_entity_extract", "media_type": "video", "entity_types": "PERSON,PRODUCT,LOCATION", "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]}],
)

Vérification

La structure de sortie est correcte et tous les types d'entités appartiennent à l'ensemble demandé. Un tableau entities vide est valide lorsqu'aucune entité nommée confirmable n'est détectée. Le test réel a retourné {"entities":[]}.

Pour décrire des types de personnages, des vêtements ou des mouvements, privilégiez les fonctionnalités de résumé ou de classification de contenu plutôt que l'extraction d'entités.