mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-10-27 13:40:37 +00:00
* feat(examples): add a standalone text classification plugin A deployment-installed package contributes one model tool, classify_texts, and a status action through the full-stack plugin contract. The tool labels a list of texts against caller-supplied categories with a deployment-configured backend: Jev (one choice question per item over a shared batch state, checked per item) or an OpenAI-compatible chat endpoint (a JSON label list validated in code). Items are packed into requests under a size limit and sent with bounded concurrency; every failure is explicit per call or per item; credentials come only from deployment-named environment variables; item text never enters instructions, question keys, results or errors, and the served model name is kept to a short identifier. Each batch runs under an asyncio timeout bounded by the call deadline, so the whole call stays inside the host's 30-second limit, and ids and category names are bounded in bytes so 300 results fit the host's 64 KiB output limit. * docs(examples): add an opt-in live smoke test for the text classification plugin The script loads the package through the real extension path and classifies 20 synthetic English and Chinese sentences plus a blank and an over-long item with the configured backend, printing labels and statuses only. Against real Jev it agreed on all 20 labels in two requests and 1.6 seconds, with the served model reported as jev-1.13.0. * fix(examples): measure request size as sent and cover transport failures httpx serializes json= bodies with the json.dumps default, escaping every non-ASCII character as six bytes, while the size estimators measured raw UTF-8, so CJK batches could reach about twice the 256 KiB limit. The estimators now measure the same encoding; a test with CJK categories and texts checks the bytes the transport actually received. The network status gets a test through connect and protocol errors, and the deadline test's wall-clock slack is widened for loaded runners. * fix(examples): match classifier request wire encoding * fix(examples): bound classification output keys by JSON size --------- Co-authored-by: Totoro-qaq <279883115+Totoro-qaq@users.noreply.github.com>
39 lines
2.0 KiB
Python
39 lines
2.0 KiB
Python
"""Standalone text classification plugin. No imports from DeerFlow host internals."""
|
|
|
|
import os
|
|
|
|
from deerflow_extension_api import BackendAction, ModelTool, PluginContribution, SettingsField, extension
|
|
|
|
from .classify import INPUT_SCHEMA, TOOL_DESCRIPTION, Options, classify_texts
|
|
|
|
|
|
@extension(api="0.2.2", name="jev-classify")
|
|
def install(registry, config):
|
|
options = Options.model_validate(dict(config))
|
|
key_env = options.jev_api_key_env if options.backend == "jev" else options.llm_api_key_env
|
|
|
|
async def classify(payload, context):
|
|
return await classify_texts(payload, options)
|
|
|
|
async def status(payload, context):
|
|
if payload:
|
|
raise ValueError("Status takes no arguments")
|
|
# Configuration only: never keys, environment variable names or item text.
|
|
return {"enabled": options.enabled, "backend": options.backend, "configured": bool(os.environ.get(key_env)), "batch_size": options.batch_size, "max_items": options.max_items}
|
|
|
|
contribution = PluginContribution(
|
|
namespace="community.jev-classify",
|
|
title="文本分类 / Text classification",
|
|
description="按给定类别给文本列表打标签;后端由部署方配置为 Jev 或聊天模型。/ Label a list of texts with the deployment-configured Jev or chat-model backend.",
|
|
enabled=options.enabled,
|
|
fields=(
|
|
SettingsField("backend", "后端 / Backend", "string", options.backend, max_length=8),
|
|
SettingsField("batch_size", "每请求条数 / Items per request", "integer", options.batch_size, minimum=1, maximum=20),
|
|
SettingsField("max_items", "每次调用上限 / Items per call", "integer", options.max_items, minimum=1, maximum=300),
|
|
),
|
|
backend=(BackendAction("status", status),),
|
|
tools=(ModelTool("classify_texts", TOOL_DESCRIPTION, INPUT_SCHEMA, classify),),
|
|
)
|
|
if registry.plugin(contribution) is not True:
|
|
raise RuntimeError("Text classification requires the full-stack plugin host contract")
|