Skip to content

Commit 832f01c

Browse files
ChenJiahaoST陈家豪
andauthored
[Feature] Add Skills system, Skills-CLI management, and agent/tool integrations (#1001)
Co-authored-by: 陈家豪 <chenjiahao@60281493M.local>
1 parent 6c52bcf commit 832f01c

File tree

23 files changed

+2333
-232
lines changed

23 files changed

+2333
-232
lines changed

docs/en/API Reference/tools.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,14 @@
339339
members:
340340
exclude-members: forward
341341

342+
::: lazyllm.tools.LazyLLMAgentBase
343+
members:
344+
exclude-members: forward
345+
346+
::: lazyllm.tools.SkillManager
347+
members:
348+
exclude-members: forward
349+
342350
::: lazyllm.tools.FunctionCall
343351
members:
344352
exclude-members: forward

docs/en/Best Practice/functionCall.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,32 @@ print(f"ret: {ret}")
129129

130130
In the above example, if the input query triggers a function call, [FunctionCall][lazyllm.tools.agent.FunctionCall] returns the assistant message dictionary that includes both `tool_calls` and `tool_calls_results`. [ReactAgent][lazyllm.tools.agent.ReactAgent] will re-invoke the model with the tool outputs until the model concludes that the information is sufficient or the number of iterations, controlled by `max_retries` (default 5), is exhausted.
131131

132+
## Skills-aware agents
133+
134+
All built-in agents (`ReactAgent`, `PlanAndSolveAgent`, `ReWOOAgent`) share the same base class and can enable **Skills** via the `skills` parameter. `skills=True` enables Skills with auto selection; pass a `str`/`list` to enable specific skills.
135+
136+
```python
137+
import lazyllm
138+
from lazyllm.tools import ReactAgent
139+
140+
llm = lazyllm.OnlineChatModule()
141+
agent = ReactAgent(
142+
llm,
143+
tools=["get_current_weather"],
144+
skills=["docs-writer"], # set skills=True to enable auto selection
145+
)
146+
```
147+
148+
What changes when skills are enabled:
149+
- A skills guide prompt is automatically injected into the system prompt.
150+
- The agent can call skill tools: `get_skill`, `read_reference`, `run_script`.
151+
- A default toolset is auto-added for common operations (read/list/search/write/delete/move files, shell, download).
152+
153+
Approval flow for risky operations:
154+
- Tools return `{"status": "needs_approval", ...}` for dangerous actions.
155+
- The front-end (or orchestrator) should ask for confirmation.
156+
- Re-run the tool with `allow_unsafe=True` only after explicit user approval.
157+
132158
Complete code is as follows:
133159
```python
134160
from typing import Literal

docs/zh/API Reference/tools.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,14 @@
328328
members:
329329
exclude-members: forward
330330

331+
::: lazyllm.tools.LazyLLMAgentBase
332+
members:
333+
exclude-members: forward
334+
335+
::: lazyllm.tools.SkillManager
336+
members:
337+
exclude-members: forward
338+
331339
::: lazyllm.tools.FunctionCall
332340
members:
333341
exclude-members: forward

docs/zh/Best Practice/functionCall.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,32 @@ print(f"ret: {ret}")
126126

127127
在上面的例子中,如果输入的 query 触发了 function call,[FunctionCall][lazyllm.tools.agent.FunctionCall] 会返回包含 `tool_calls``tool_calls_results` 的助手消息字典。[ReactAgent][lazyllm.tools.agent.ReactAgent] 则会反复调用模型和工具,直到模型认定信息足以得出结论,或达到由 `max_retries`(默认 5)控制的最大迭代次数。
128128

129+
## Skills 智能体支持
130+
131+
所有内置 Agent(`ReactAgent``PlanAndSolveAgent``ReWOOAgent`)统一基于同一基类,可通过 `skills` 参数开启 Skills。`skills=True` 表示启用 Skills 并自动筛选;传入 `str`/`list` 表示只启用指定技能。
132+
133+
```python
134+
import lazyllm
135+
from lazyllm.tools import ReactAgent
136+
137+
llm = lazyllm.OnlineChatModule()
138+
agent = ReactAgent(
139+
llm,
140+
tools=["get_current_weather"],
141+
skills=["docs-writer"], # 传入 skills=True 启用自动筛选
142+
)
143+
```
144+
145+
启用 Skills 后的变化:
146+
- 系统提示词自动拼接 Skills 引导。
147+
- 智能体可调用技能工具:`get_skill``read_reference``run_script`
148+
- 默认注入一组通用工具(文件读写/检索、Shell 执行、下载等)。
149+
150+
危险操作的审批流程:
151+
- 工具对高风险操作返回 `{"status": "needs_approval", ...}`
152+
- 由前端/编排层进行用户确认。
153+
- 用户确认后再以 `allow_unsafe=True` 重新调用工具。
154+
129155
完整代码如下:
130156
```python
131157
from typing import Literal
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import os
2+
import tempfile
3+
4+
import lazyllm
5+
from lazyllm.tools import ReactAgent
6+
from lazyllm.tools.agent.skill_manager import SkillManager
7+
from lazyllm.cli.skills import skills as skills_cli
8+
9+
10+
def _prepare_sample_skill(root: str) -> str:
11+
skill_dir = os.path.join(root, 'demo-skill')
12+
os.makedirs(skill_dir, exist_ok=True)
13+
skill_md = os.path.join(skill_dir, 'SKILL.md')
14+
with open(skill_md, 'w', encoding='utf-8') as f:
15+
f.write(
16+
"---\n"
17+
"name: demo-skill\n"
18+
"description: A demo skill for showing how to import and use skills.\n"
19+
"---\n"
20+
"\n"
21+
"# demo-skill\n"
22+
"This is a minimal demo skill.\n"
23+
)
24+
return skill_dir
25+
26+
27+
def main():
28+
# 1) Prepare a local skill folder and import it into the default skills directory
29+
with tempfile.TemporaryDirectory() as tmp:
30+
skill_dir = _prepare_sample_skill(tmp)
31+
# CLI equivalents:
32+
# lazyllm skills init
33+
# lazyllm skills add /path/to/skill_folder
34+
skills_cli(['init'])
35+
skills_cli(['add', skill_dir])
36+
37+
# 2) Use SkillManager to show available skills
38+
manager = SkillManager()
39+
lazyllm.LOG.info(manager.list_skill())
40+
41+
# 3) Run ReactAgent with skills enabled
42+
llm = lazyllm.TrainableModule('Qwen2.5-32B-Instruct')
43+
agent = ReactAgent(
44+
llm=llm,
45+
tools=[],
46+
skills=['demo-skill'],
47+
)
48+
res = agent('What skills do you have?')
49+
lazyllm.LOG.info(res)
50+
51+
52+
if __name__ == '__main__':
53+
main()

lazyllm/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from .hook import LazyLLMHook, LazyLLMFuncHook
2020
from typing import TYPE_CHECKING
2121
if TYPE_CHECKING:
22-
from .tools import (Document, Reranker, Retriever, WebModule, ToolManager, FunctionCall,
22+
from .tools import (Document, Reranker, Retriever, WebModule, ToolManager, FunctionCall, SkillManager,
2323
FunctionCallAgent, fc_register, ReactAgent, PlanAndSolveAgent, ReWOOAgent, SentenceSplitter,
2424
LLMParser)
2525
from .patch import patch_os_env
@@ -93,6 +93,7 @@ def __getattr__(name: str):
9393
'Retriever',
9494
'Reranker',
9595
'ToolManager',
96+
'SkillManager',
9697
'FunctionCall',
9798
'FunctionCallAgent',
9899
'fc_register',

lazyllm/cli/main.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from deploy import deploy
55
from run import run
66
from skills import skills
7-
87
except ImportError:
98
from .install import install
109
from .deploy import deploy
@@ -16,7 +15,11 @@ def main():
1615
def exit():
1716
logging.error('Usage:\n lazyllm install <extra1> <extra2> <pkg1> ...\n'
1817
' lazyllm deploy modelname\n lazyllm deploy mcp_server <command> [args ...] [options]\n'
19-
' lazyllm run graph.json\n lazyllm run chatbot\n lazyllm run rag\n')
18+
' lazyllm run graph.json\n lazyllm run chatbot\n lazyllm run rag\n'
19+
' lazyllm skills init\n lazyllm skills list\n lazyllm skills info <name>\n'
20+
' lazyllm skills delete <name>\n lazyllm skills add <path> [-n NAME] [--dir DIR]\n'
21+
' lazyllm skills import <path> [--dir DIR] [--names a,b,c] [--overwrite]\n'
22+
' lazyllm skills install --agent <name> [--project] [--timeout SEC]\n')
2023
sys.exit(1)
2124

2225
if len(sys.argv) <= 1: exit()

0 commit comments

Comments
 (0)