diff --git a/template/README.md b/template/README.md index 3415867..7ed6334 100644 --- a/template/README.md +++ b/template/README.md @@ -1,5 +1,44 @@ # AgentKit 样例模板 +您提交的样例应当在 README.md 中添加 Yaml 格式的元数据,用于描述您的样例,具体内容包括: + +```markdown +--- +name: # 中文名称(255字符) +name_en: # 英文名称(255字符) +description: # 简介(10-20字) +details: # 详细介绍(10-40字) +type: # 类型,可选项为 tutorial | application +senarios: # 应用场景(2-6个),type 为 application 时必填 + - name: # 应用场景名称(2-15字) + desc: # 应用场景描述(10-20字) + - name: + desc: +prompts: # Prompt 样例 + - text: # Prompt 文本(简洁精炼) + resource_url: # 必要的多模态数据 URL(公网可访问) + - prompt: + resource_url: +envs: # 所需的环境变量(用于第三方依赖服务) + - name: # 环境变量中文名 + key: # 环境变量名 + url: # 引导链接 +components: # Agentkit 依赖服务 + - type: # 服务类型,可选项为 tool | knowledgebase | memory + # 对应产品(不区分大小写) + # tool: AIO_Sandbox | Skills_Sandbox + # knowledgebase: VikingKnowledge + # memory: VikingMem | Mem0 + product: +models: # 涉及到的具体模型列表 + - doubao-seed-1-8-251215 +--- + +# Markdown 正文 + +... +``` + > 您向 `agentkit-samples` 项目提交的样例,需要符合以下目录结构,并保证内容完整: > > ```bash diff --git a/workflow_utils/check_readme_metadata.py b/workflow_utils/check_readme_metadata.py index a61f0f5..d476e7c 100644 --- a/workflow_utils/check_readme_metadata.py +++ b/workflow_utils/check_readme_metadata.py @@ -1,48 +1,142 @@ # pip install python-frontmatter -from typing import Any -from pathlib import Path import argparse import subprocess import sys +from pathlib import Path +from typing import Any + import frontmatter +SAMPLE_TYPES = ["tutorial", "application"] + +COMPONENT_OPTIONS = { + "sandbox": ["AIO_Sandbox", "Skills_Sandbox"], + "knowledgebase": ["VikingKnowledge"], + "memory": ["VikingMem", "Mem0"], +} + def check_name(metadata: dict[str, Any]): name = metadata.get("name") if not name: raise ValueError("name is required") + if len(name) > 255: + raise ValueError("name should be less than 255 characters") + + +def check_name_en(metadata: dict[str, Any]): + name_en = metadata.get("name_en") + if not name_en: + raise ValueError("name_en is required") + + if len(name_en) > 255: + raise ValueError("name_en should be less than 255 characters") + def check_description(metadata: dict[str, Any]): description = metadata.get("description") if not description: raise ValueError("description is required") + if len(description) < 10 or len(description) > 20: + raise ValueError("description should be between 10-20 characters") + + +def check_details(metadata: dict[str, Any]): + details = metadata.get("details") + if not details: + raise ValueError("details is required") + + if len(details) < 10 or len(details) > 40: + raise ValueError("details should be between 10-40 characters") + + +def check_type(metadata: dict[str, Any]): + type = metadata.get("type") + if not type: + raise ValueError("type is required") + + if type not in SAMPLE_TYPES: + raise ValueError(f"type should be one of {SAMPLE_TYPES}") + def check_senarios(metadata: dict[str, Any]): - senarios = metadata.get("senarios") - if not senarios: - raise ValueError("senarios is required") - if len(senarios) != 4: - raise ValueError("senarios should have 4 items") + type = metadata.get("type") + senarios: list = metadata.get("senarios", []) + if not senarios and type == "application": + raise ValueError("senarios is required when type is `application`") + if len(senarios) < 2 or len(senarios) > 6: + raise ValueError("senarios should have 2-6 items") -def check_components(metadata: dict[str, Any]): - standard_components = ["Identity", "MCP Toolset"] - components = metadata.get("components") - if not components: - raise ValueError("components is required") - if len(components) == 0: - raise ValueError("components should have at least 1 item") - for component in components: - name = component.get("name") + for scenario in senarios: + name = scenario.get("name") if not name: - raise ValueError("component name is required") - desc = component.get("desc") + raise ValueError("scenario name is required") + if len(name) < 2 or len(name) > 15: + raise ValueError("scenario name should be between 2-15 characters") + + desc = scenario.get("desc") if not desc: - raise ValueError("component desc is required") - if component["name"] not in standard_components: - raise ValueError(f"component name should be one of {standard_components}") + raise ValueError("scenario desc is required") + if len(desc) < 10 or len(desc) > 20: + raise ValueError("scenario desc should be between 10-20 characters") + + +def check_prompts(metadata: dict[str, Any]): + prompts: list = metadata.get("prompts", []) + if not prompts: + raise ValueError("prompts field is required") + + for prompt in prompts: + text = prompt.get("text") + if not text: + raise ValueError("prompt text is required") + + resource_url = prompt.get("resource_url") + if resource_url: + assert resource_url.startswith("https://") or resource_url.startswith( + "http://" + ), "resource_url must start with `https://` or `http://`" + + +def check_models(metadata: dict[str, Any]): + models: list = metadata.get("models", []) + if not models: + raise ValueError("models field is required") + + +def check_envs(metadata: dict[str, Any]): + envs: list = metadata.get("envs", []) + + for env in envs: + assert env.get("name"), "env name is required" + assert env.get("key"), "env key is required" + + url = env.get("url") + assert url, "env url is required" + assert url.startswith("https://") or url.startswith("http://"), ( + "env url must start with `https://` or `http://`" + ) + + +def check_components(metadata: dict[str, Any]): + components = metadata.get("components", []) + + for component in components: + assert component.get("type"), "component type is required" + assert component.get("product"), "component product is required" + + component_type = component["type"].lower() + component_product = component["product"].lower() + + assert component_type in COMPONENT_OPTIONS, ( + f"component type should be one of {COMPONENT_OPTIONS.keys()}" + ) + assert component_product in COMPONENT_OPTIONS[component_type], ( + f"component product should be one of {COMPONENT_OPTIONS[component_type]}" + ) def main(argv: list[str] | None = None) -> int: @@ -100,8 +194,14 @@ def main(argv: list[str] | None = None) -> int: try: check_name(post.metadata) + check_name_en(post.metadata) check_description(post.metadata) + check_details(post.metadata) + check_type(post.metadata) check_senarios(post.metadata) + check_prompts(post.metadata) + check_models(post.metadata) + check_envs(post.metadata) check_components(post.metadata) except ValueError as exc: sys.stderr.write(f"{rel}: {exc}\n")