Skip to content

Commit 318ffbb

Browse files
chore(workflow): add markdown header check rules and update readme te… (#104)
2 parents 54f5ff3 + 75dc494 commit 318ffbb

File tree

2 files changed

+160
-21
lines changed

2 files changed

+160
-21
lines changed

template/README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,44 @@
11
# AgentKit 样例模板
22

3+
您提交的样例应当在 README.md 中添加 Yaml 格式的元数据,用于描述您的样例,具体内容包括:
4+
5+
```markdown
6+
---
7+
name: # 中文名称(255字符)
8+
name_en: # 英文名称(255字符)
9+
description: # 简介(10-20字)
10+
details: # 详细介绍(10-40字)
11+
type: # 类型,可选项为 tutorial | application
12+
senarios: # 应用场景(2-6个),type 为 application 时必填
13+
- name: # 应用场景名称(2-15字)
14+
desc: # 应用场景描述(10-20字)
15+
- name:
16+
desc:
17+
prompts: # Prompt 样例
18+
- text: # Prompt 文本(简洁精炼)
19+
resource_url: # 必要的多模态数据 URL(公网可访问)
20+
- prompt:
21+
resource_url:
22+
envs: # 所需的环境变量(用于第三方依赖服务)
23+
- name: # 环境变量中文名
24+
key: # 环境变量名
25+
url: # 引导链接
26+
components: # Agentkit 依赖服务
27+
- type: # 服务类型,可选项为 tool | knowledgebase | memory
28+
# 对应产品(不区分大小写)
29+
# tool: AIO_Sandbox | Skills_Sandbox
30+
# knowledgebase: VikingKnowledge
31+
# memory: VikingMem | Mem0
32+
product:
33+
models: # 涉及到的具体模型列表
34+
- doubao-seed-1-8-251215
35+
---
36+
37+
# Markdown 正文
38+
39+
...
40+
```
41+
342
> 您向 `agentkit-samples` 项目提交的样例,需要符合以下目录结构,并保证内容完整:
443
>
544
> ```bash

workflow_utils/check_readme_metadata.py

Lines changed: 121 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
# pip install python-frontmatter
2-
from typing import Any
3-
from pathlib import Path
42
import argparse
53
import subprocess
64
import sys
5+
from pathlib import Path
6+
from typing import Any
7+
78
import frontmatter
89

10+
SAMPLE_TYPES = ["tutorial", "application"]
11+
12+
COMPONENT_OPTIONS = {
13+
"sandbox": ["AIO_Sandbox", "Skills_Sandbox"],
14+
"knowledgebase": ["VikingKnowledge"],
15+
"memory": ["VikingMem", "Mem0"],
16+
}
17+
918

1019
def should_skip(metadata: dict[str, Any]) -> bool:
1120
return not metadata
@@ -16,37 +25,122 @@ def check_name(metadata: dict[str, Any]):
1625
if not name:
1726
raise ValueError("name is required")
1827

28+
if len(name) > 255:
29+
raise ValueError("name should be less than 255 characters")
30+
31+
32+
def check_name_en(metadata: dict[str, Any]):
33+
name_en = metadata.get("name_en")
34+
if not name_en:
35+
raise ValueError("name_en is required")
36+
37+
if len(name_en) > 255:
38+
raise ValueError("name_en should be less than 255 characters")
39+
1940

2041
def check_description(metadata: dict[str, Any]):
2142
description = metadata.get("description")
2243
if not description:
2344
raise ValueError("description is required")
2445

46+
if len(description) < 10 or len(description) > 20:
47+
raise ValueError("description should be between 10-20 characters")
48+
49+
50+
def check_details(metadata: dict[str, Any]):
51+
details = metadata.get("details")
52+
if not details:
53+
raise ValueError("details is required")
54+
55+
if len(details) < 10 or len(details) > 40:
56+
raise ValueError("details should be between 10-40 characters")
57+
58+
59+
def check_type(metadata: dict[str, Any]):
60+
type = metadata.get("type")
61+
if not type:
62+
raise ValueError("type is required")
63+
64+
if type not in SAMPLE_TYPES:
65+
raise ValueError(f"type should be one of {SAMPLE_TYPES}")
66+
2567

2668
def check_senarios(metadata: dict[str, Any]):
27-
senarios = metadata.get("senarios")
28-
if not senarios:
29-
raise ValueError("senarios is required")
30-
if len(senarios) != 4:
31-
raise ValueError("senarios should have 4 items")
69+
type = metadata.get("type")
70+
senarios: list = metadata.get("senarios", [])
71+
if not senarios and type == "application":
72+
raise ValueError("senarios is required when type is `application`")
3273

74+
if len(senarios) < 2 or len(senarios) > 6:
75+
raise ValueError("senarios should have 2-6 items")
3376

34-
def check_components(metadata: dict[str, Any]):
35-
standard_components = ["Identity", "MCP Toolset"]
36-
components = metadata.get("components")
37-
if not components:
38-
raise ValueError("components is required")
39-
if len(components) == 0:
40-
raise ValueError("components should have at least 1 item")
41-
for component in components:
42-
name = component.get("name")
77+
for scenario in senarios:
78+
name = scenario.get("name")
4379
if not name:
44-
raise ValueError("component name is required")
45-
desc = component.get("desc")
80+
raise ValueError("scenario name is required")
81+
if len(name) < 2 or len(name) > 15:
82+
raise ValueError("scenario name should be between 2-15 characters")
83+
84+
desc = scenario.get("desc")
4685
if not desc:
47-
raise ValueError("component desc is required")
48-
if component["name"] not in standard_components:
49-
raise ValueError(f"component name should be one of {standard_components}")
86+
raise ValueError("scenario desc is required")
87+
if len(desc) < 10 or len(desc) > 20:
88+
raise ValueError("scenario desc should be between 10-20 characters")
89+
90+
91+
def check_prompts(metadata: dict[str, Any]):
92+
prompts: list = metadata.get("prompts", [])
93+
if not prompts:
94+
raise ValueError("prompts field is required")
95+
96+
for prompt in prompts:
97+
text = prompt.get("text")
98+
if not text:
99+
raise ValueError("prompt text is required")
100+
101+
resource_url = prompt.get("resource_url")
102+
if resource_url:
103+
assert resource_url.startswith("https://") or resource_url.startswith(
104+
"http://"
105+
), "resource_url must start with `https://` or `http://`"
106+
107+
108+
def check_models(metadata: dict[str, Any]):
109+
models: list = metadata.get("models", [])
110+
if not models:
111+
raise ValueError("models field is required")
112+
113+
114+
def check_envs(metadata: dict[str, Any]):
115+
envs: list = metadata.get("envs", [])
116+
117+
for env in envs:
118+
assert env.get("name"), "env name is required"
119+
assert env.get("key"), "env key is required"
120+
121+
url = env.get("url")
122+
assert url, "env url is required"
123+
assert url.startswith("https://") or url.startswith("http://"), (
124+
"env url must start with `https://` or `http://`"
125+
)
126+
127+
128+
def check_components(metadata: dict[str, Any]):
129+
components = metadata.get("components", [])
130+
131+
for component in components:
132+
assert component.get("type"), "component type is required"
133+
assert component.get("product"), "component product is required"
134+
135+
component_type = component["type"].lower()
136+
component_product = component["product"].lower()
137+
138+
assert component_type in COMPONENT_OPTIONS, (
139+
f"component type should be one of {COMPONENT_OPTIONS.keys()}"
140+
)
141+
assert component_product in COMPONENT_OPTIONS[component_type], (
142+
f"component product should be one of {COMPONENT_OPTIONS[component_type]}"
143+
)
50144

51145

52146
def main(argv: list[str] | None = None) -> int:
@@ -109,8 +203,14 @@ def main(argv: list[str] | None = None) -> int:
109203

110204
try:
111205
check_name(post.metadata)
206+
check_name_en(post.metadata)
112207
check_description(post.metadata)
208+
check_details(post.metadata)
209+
check_type(post.metadata)
113210
check_senarios(post.metadata)
211+
check_prompts(post.metadata)
212+
check_models(post.metadata)
213+
check_envs(post.metadata)
114214
check_components(post.metadata)
115215
except ValueError as exc:
116216
sys.stderr.write(f"{rel}: {exc}\n")

0 commit comments

Comments
 (0)