demo
This commit is contained in:
108
src/lib/skill-node-quality.ts
Normal file
108
src/lib/skill-node-quality.ts
Normal file
@ -0,0 +1,108 @@
|
||||
export type SkillQualityNodeKey =
|
||||
| "trigger"
|
||||
| "inputs"
|
||||
| "steps"
|
||||
| "output"
|
||||
| "constraints";
|
||||
|
||||
export type SkillNodeQuality = {
|
||||
complete: boolean;
|
||||
missing: string[];
|
||||
};
|
||||
|
||||
function normalizedContent(content: string) {
|
||||
return content.replace(/\s+/g, " ").trim();
|
||||
}
|
||||
|
||||
function hasOrderedSteps(content: string) {
|
||||
const numberedSteps =
|
||||
content.match(/(?:^|[\n;;。])\s*(?:步骤\s*)?\d+[.、)::]/g)?.length ?? 0;
|
||||
const sequenceMarkers = ["先", "再", "然后", "接着", "最后", "最终"].filter(
|
||||
(marker) => content.includes(marker),
|
||||
).length;
|
||||
const actionSegments = content
|
||||
.split(/[\n;;。]+/)
|
||||
.filter((segment) =>
|
||||
/(?:检查|识别|提取|分析|整理|比较|判断|生成|输出|复核|验证|标记)/.test(
|
||||
segment,
|
||||
),
|
||||
).length;
|
||||
|
||||
return numberedSteps >= 2 || sequenceMarkers >= 2 || actionSegments >= 2;
|
||||
}
|
||||
|
||||
export function evaluateSkillNodeQuality(
|
||||
nodeKey: SkillQualityNodeKey,
|
||||
content: string,
|
||||
): SkillNodeQuality {
|
||||
const normalized = normalizedContent(content);
|
||||
const missing: string[] = [];
|
||||
|
||||
if (normalized.length < 8) {
|
||||
missing.push("内容过短,尚未形成可执行规范");
|
||||
return { complete: false, missing };
|
||||
}
|
||||
|
||||
switch (nodeKey) {
|
||||
case "trigger":
|
||||
if (
|
||||
!/(?:当|如果|遇到|用户|场景|适用|触发|不处理|不适用|请求)/.test(
|
||||
normalized,
|
||||
)
|
||||
) {
|
||||
missing.push("需要说明何时触发或适用场景");
|
||||
}
|
||||
break;
|
||||
case "inputs":
|
||||
if (
|
||||
!/(?:必填|可选|输入|参数|提供|原文|材料|目标|字段|默认|缺失)/.test(
|
||||
normalized,
|
||||
)
|
||||
) {
|
||||
missing.push("需要列明执行所需的输入信息");
|
||||
}
|
||||
break;
|
||||
case "steps":
|
||||
if (!hasOrderedSteps(normalized)) {
|
||||
missing.push("需要至少两个有明确顺序的执行动作");
|
||||
}
|
||||
break;
|
||||
case "output":
|
||||
if (
|
||||
!/(?:输出|结果|格式|结构|标题|字段|表格|Markdown|JSON|列表|篇幅|语气|字数|包含)/i.test(
|
||||
normalized,
|
||||
)
|
||||
) {
|
||||
missing.push("需要明确结果结构、字段或格式");
|
||||
}
|
||||
break;
|
||||
case "constraints":
|
||||
if (
|
||||
!/(?:不得|不能|禁止|必须|至少|至多|缺少|不足|失败|异常|验收|测试|反例|确保|待确认|质量)/.test(
|
||||
normalized,
|
||||
)
|
||||
) {
|
||||
missing.push("需要至少一条约束、质量标准或验收条件");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return { complete: missing.length === 0, missing };
|
||||
}
|
||||
|
||||
export function getSkillNodeQualityIssues(
|
||||
nodes: Array<{
|
||||
key: SkillQualityNodeKey;
|
||||
title: string;
|
||||
content: string;
|
||||
}>,
|
||||
) {
|
||||
return nodes.flatMap((node) => {
|
||||
const quality = evaluateSkillNodeQuality(node.key, node.content);
|
||||
return quality.missing.map((missing) => `${node.title}:${missing}`);
|
||||
});
|
||||
}
|
||||
|
||||
export function skillNodeQualityErrorMessage(issues: string[]) {
|
||||
return `Skill 节点尚未达到可发布标准。需补充:${issues.join(";")}`;
|
||||
}
|
||||
Reference in New Issue
Block a user