Skip to content

Commit b30f816

Browse files
committed
update the skill system for inner abilities
1 parent 40880cb commit b30f816

12 files changed

Lines changed: 169 additions & 20 deletions

File tree

src/agent/Agent.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export const DEFAULT_AGENT: AgentProps = {
2727
knowledges: [],
2828
workflows: [],
2929
agents: [],
30+
skills: [],
3031
};
3132

3233
export const AgentStore = new Echo<Record<string, AgentProps>>({}).indexed({

src/agent/engine/Engine.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export class Engine {
9393
...(await ToolsHandler.transformKnowledgeToModelFormat(
9494
props.knowledges || [],
9595
)),
96+
...(await ToolsHandler.transformSkillToModelFormat(props.skills)),
9697
]);
9798

9899
// 初始化内存和上下文

src/agent/types/agent.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ export interface AgentProps {
6464
workflows: string[];
6565
/* 允许调用的其他agents */
6666
agents: string[];
67+
/* 可调用的技能 */
68+
skills: string[];
6769
/* 配置 */
6870
configs?: {
6971
/* 温度 */

src/assets/const.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export const TOOL_NAME_SPLIT = "--";
22
export const WORKFLOW_TOOL_NAME_PREFIX = "executeFlow";
33
export const KNOWLEDGE_TOOL_NAME_PREFIX = "knowledge";
44
export const AGENT_TOOL_NAME_PREFIX = "agent";
5+
export const SKILL_TOOL_NAME_PREFIX = "skill";
56
export const WORKFLOW_BODY_DATABASE = "workflow_bodies";
67
export const WORKFLOW_DATABASE = "workflows";
78
export const KNOWLEDGE_DATABASE = "knowledge";

src/main.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import "./model/chat/provider";
1010
import "./model/embedding/provider";
1111
import "./model/image/provider";
1212
import "./model/vision/provider";
13+
import "./skills/instance";
1314
import App from "./page/App";
1415

1516
const element = document.getElementById("root") as HTMLElement;

src/model/chat/ChatModel.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,11 @@ export class ChatModel {
267267
created_at: Date.now(),
268268
},
269269
]);
270-
toolResult = await ToolsHandler.call(tool_call, this.otherModels);
270+
toolResult = await ToolsHandler.call(
271+
tool_call,
272+
this.otherModels,
273+
this,
274+
);
271275
console.log(toolResult);
272276

273277
if (

src/model/chat/ToolsHandler.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { AgentMCPProps, AgentProps, AgentToolProps } from "@/agent/types/agent";
33
import {
44
AGENT_TOOL_NAME_PREFIX,
55
KNOWLEDGE_TOOL_NAME_PREFIX,
6+
SKILL_TOOL_NAME_PREFIX,
67
TOOL_NAME_SPLIT,
78
WORKFLOW_BODY_DATABASE,
89
WORKFLOW_TOOL_NAME_PREFIX,
@@ -22,6 +23,8 @@ import {
2223
ToolRequestBody,
2324
} from "../types/chatModel";
2425
import { VisionModel } from "../vision/VisionModel";
26+
import { SkillManager } from "@/skills/SkillManager";
27+
import { ChatModel } from "./ChatModel";
2528

2629
export class ToolsHandler {
2730
static async transformAgentToolToModelFormat(
@@ -235,9 +238,35 @@ export class ToolsHandler {
235238
return toolRequestBody;
236239
}
237240

241+
static async transformSkillToModelFormat(
242+
skills: string[],
243+
): Promise<ToolRequestBody> {
244+
const toolRequestBody: ToolRequestBody = [];
245+
if (skills.length) {
246+
/* 获取代理 */
247+
const list = SkillManager.getSkills();
248+
249+
/* 将知识库变成工具 */
250+
skills.forEach((skill) => {
251+
const skillDoc = list[skill];
252+
if (!skillDoc) return;
253+
toolRequestBody.push({
254+
type: "function",
255+
function: {
256+
name: `${SKILL_TOOL_NAME_PREFIX}${TOOL_NAME_SPLIT}${skill}`,
257+
description: skillDoc.description,
258+
parameters: skillDoc.params,
259+
},
260+
});
261+
});
262+
}
263+
return toolRequestBody;
264+
}
265+
238266
static async call(
239267
tool_call: ToolCallReply,
240268
otherModels: AgentProps["models"],
269+
chatModel: ChatModel,
241270
): Promise<FunctionCallResult | undefined> {
242271
if (!tool_call) return;
243272

@@ -343,7 +372,14 @@ export class ToolsHandler {
343372
result,
344373
};
345374
}
346-
375+
if (firstName === SKILL_TOOL_NAME_PREFIX) {
376+
const result = await SkillManager.execute(secondName, query, chatModel);
377+
return {
378+
name: tool_call.function.name,
379+
arguments: tool_call.function.arguments,
380+
result,
381+
};
382+
}
347383
if (firstName === KNOWLEDGE_TOOL_NAME_PREFIX) {
348384
if (!query.query) {
349385
return {
@@ -402,6 +438,13 @@ export class ToolsHandler {
402438
name: `calling agent: ${list[secondName].name}`,
403439
};
404440
}
441+
if (firstName === SKILL_TOOL_NAME_PREFIX) {
442+
const list = SkillManager.getSkills();
443+
return {
444+
type: "skill",
445+
name: `calling skill: ${list[secondName].name}`,
446+
};
447+
}
405448

406449
if (firstName === WORKFLOW_TOOL_NAME_PREFIX) {
407450
const list = await WorkflowsStore.getCurrent();

src/page/agent/AgentEditor.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { TbListSearch, TbUpload } from "react-icons/tb";
2626
import { toast } from "sonner";
2727
import { MCPTool, MCP_Actived } from "../mcp/MCP";
2828
import { SettingItem } from "../settings/components/SettingItem";
29+
import { SkillManager } from "@/skills/SkillManager";
2930

3031
export const AgentEditor = ({ agent }: { agent: Agent }) => {
3132
const list = KnowledgesStore.use();
@@ -296,6 +297,24 @@ export const AgentEditor = ({ agent }: { agent: Agent }) => {
296297
multiple
297298
placeholder="Select MCP..."
298299
/>
300+
<DrawerSelector
301+
title="Select Skill"
302+
value={props.skills}
303+
items={Object.entries(SkillManager.getSkills()).map(
304+
([id, skill]) => ({
305+
label: skill.name,
306+
value: id,
307+
description: skill.description,
308+
}),
309+
)}
310+
onSelect={(value) =>
311+
agent.update({
312+
skills: value,
313+
})
314+
}
315+
multiple
316+
placeholder="Select Skill..."
317+
/>
299318
<DrawerSelector
300319
title="Select Knowledge"
301320
value={props.knowledges || []}

src/skills/Skill.ts

Lines changed: 0 additions & 4 deletions
This file was deleted.

src/skills/SkillManager.ts

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,42 @@
1-
import { Skill } from "./Skill";
1+
/* 技能方法接口 */
2+
import { ChatModel } from "@/model/chat/ChatModel";
3+
import { ToolParameters } from "@/plugin/types";
24

3-
export interface SkillProps {
5+
/** 方法元数据 */
6+
export interface Skill {
47
name: string;
58
description: string;
9+
params: ToolParameters;
10+
execute: (params: Record<string, any>, chatModel: ChatModel) => any;
611
}
712

8-
/** Skill 管理器 */
9-
export class SkillManager {
10-
/** 已注册的 Engine */
11-
private static readonly skills: Record<string, Skill> = {};
13+
/** 方法管理器 */
14+
export const SkillManager = {
15+
/** 已注册的方法 */
16+
skills: {} as Record<string, Skill>,
1217

13-
/** 注册 Engine */
14-
public static register(type: string, skill: Skill): void {
18+
/** 获取所有已注册的技能 */
19+
getSkills(): Record<string, Skill> {
20+
return this.skills;
21+
},
22+
/** 注册技能 */
23+
register(type: string, skill: Skill): void {
1524
this.skills[type] = skill;
16-
}
17-
18-
/** 获取指定的 Engine */
19-
public static getSkill(type: string): Skill | undefined {
25+
},
26+
/** 获取指定的技能 */
27+
getSkill(type: string): Skill | undefined {
2028
return this.skills[type];
21-
}
22-
}
29+
},
30+
/** 执行指定方法 */
31+
execute(
32+
skillType: string,
33+
params: Record<string, any> = {},
34+
chatModel: ChatModel,
35+
): any {
36+
const skill = this.getSkill(skillType);
37+
if (!skill) {
38+
throw new Error(`技能 ${skillType} 不存在`);
39+
}
40+
return skill.execute(params, chatModel);
41+
},
42+
};

0 commit comments

Comments
 (0)