LangChain DeepAgents 使用入门(自定义Skill)

LangChain DeepAgents 使用入门(自定义 Skill)

环境安装

确保 Python 版本 >= 3.12,然后安装 deepagents:

pip install deepagents

快速开始

create_deep_agent 的用法与 LangChain 原生的 create_agent 类似:

from deepagents import create_deep_agent
from langchain_openai import ChatOpenAI

model = ChatOpenAI(
    api_key="your-api-key",
    model="minimax-m2.7",
    base_url="https://api.example.com/v1",
)

agent = create_deep_agent(
    model=model,
    system_prompt="你是我的 AI 助手"
)

result = agent.invoke(
    {"messages": [{"role": "user", "content": "你好,你是谁?"}]}
)

print(result["messages"][-1].content)

运行效果:

image

自定义 Skill

目录结构

skills/
└── get-weather/        # Skill 名称
    └── SKILL.md        # Skill 定义文件

image

子文件夹名称即 Skill 名称,SKILL.md 是对应的 Skill 文档。

SKILL.md 格式

---
name: get-weather
description: 用户需要获取天气、气温时使用。
license: MIT
---

## 何时使用
- 用户要求获取天气、询问气温等情况

## 输出格式
- 直接输出以下格式:

[城市]气温26摄氏度,天气晴朗

创建 Agent 并加载 Skill

from deepagents import create_deep_agent
from deepagents.backends.utils import create_file_data
from langchain_openai import ChatOpenAI
from langgraph.checkpoint.memory import MemorySaver
from pathlib import Path

checkpointer = MemorySaver()


def load_skills_from_disk():
    """从本地加载 skills"""
    all_files = {}
    skills_root = Path(__file__).parent / "skills"

    for skill_file in skills_root.rglob("SKILL.md"):
        relative_path = skill_file.relative_to(skills_root)
        virtual_path = "/skills/" + "/".join(relative_path.parts)

        with open(skill_file, "r", encoding="utf-8") as f:
            content = f.read()

        all_files[virtual_path] = create_file_data(content)

    return all_files


def create_agent():
    """创建 Deep Agent"""
    model = ChatOpenAI(
        api_key="your-api-key",
        model="minimax-m2.7",
        base_url="https://api.example.com/v1",
    )

    agent = create_deep_agent(
        model=model,
        skills=["/skills/"],
        checkpointer=checkpointer,
    )

    return agent


if __name__ == "__main__":
    agent = create_agent()
    skills_files = load_skills_from_disk()
    messages = []

    print("=" * 50)
    print("Deep Agent 连续对话模式(输入 q 退出)")
    print("=" * 50)

    while True:
        user_input = input("\n你: ").strip()
        if user_input.lower() in ("q", "quit", "exit"):
            print("再见!")
            break

        if not user_input:
            continue

        messages.append({"role": "user", "content": user_input})

        # files 和 messages 必须放在同一个字典里
        result = agent.invoke(
            {
                "messages": messages,
                "files": skills_files
            },
            config={"configurable": {"thread_id": "12345"}},
        )

        messages = result["messages"]
        latest_message = messages[-1]
        content = getattr(latest_message, "content", None)
        if content:
            print(f"\n助手: {content}")

关键点说明

  1. Skill 路径:通过 skills=["/skills/"] 指定,Agent 会自动扫描目录下所有 SKILL.md

  2. files 参数:files 必须与 messages 放在同一个字典里,作为 Agent 的输入

  3. checkpointer:MemorySaver() 将对话历史保存在内存中,支持同一线程内的多轮对话

运行效果

运行结果如Skill中的描述一致

image

Skill进阶(调用脚本)

要让 Agent能够执行调用脚本的任务,首先需要让Agent拥有脚本执行能力,也就是控制台执行命令

那么需要为Agent构建一个本地的Shell后端LocalShellBackend,同时,将技能和对应技能的脚本导入如后端,即可实现在skill中调用脚本

这里创建了一个获取当前时间的Skill
image

SKILL.md内容:

---
name: time-query
description: 获取当前日期和时间。当用户询问现在几点、今天日期、当前时间、或需要时间相关信息时使用。
---

# 时间查询技能

## 何时使用
- 用户问"现在几点"、"现在时间"、"几点几分"
- 用户问"今天是几号"、"今天星期几"、"今天日期"
- 需要返回精确时间信息的任何场景

## 执行流程

### 步骤 1:定位脚本
脚本路径:`/skills/time-query/scripts/get_time.py`

### 步骤 2:执行脚本
使用 `execute` 工具运行脚本(Windows 环境):

python /skills/time-query/scripts/get_time.py


### 步骤 3:返回结果
将脚本输出的时间信息以清晰格式返回给用户

## 注意事项
- 必须使用 execute 工具执行脚本,不要自己编造时间
- 如果 execute 失败,告知用户无法获取时间

完整代码:

"""
LangChain DeepAgents 调用自定义 Skill 示例

使用 LocalShellBackend 支持脚本执行。
"""

import sys
from pathlib import Path

# 设置编码
sys.stdout.reconfigure(encoding='utf-8')

from deepagents import create_deep_agent
from deepagents.backends.local_shell import LocalShellBackend
from deepagents.backends.utils import create_file_data
from langchain_openai import ChatOpenAI
from langgraph.checkpoint.memory import MemorySaver


checkpointer = MemorySaver()


def create_agent():
    """创建 Deep Agent,使用 LocalShellBackend 支持脚本执行"""
    model = ChatOpenAI(
        api_key="",
        model="minimax-m2.7",
        base_url="",
        timeout=120,
    )

    # 使用 LocalShellBackend,支持 execute 工具运行脚本
    # virtual_mode=True: 启用虚拟路径模式,阻止路径遍历
    backend = LocalShellBackend(virtual_mode=True)

    agent = create_deep_agent(
        model=model,
        backend=backend,
        skills=["/skills/"],
        checkpointer=checkpointer,
    )

    return agent, backend


def load_skills_with_backend(backend):
    """加载 skills 到指定后端"""
    skills_root = Path(__file__).parent / "skills"

    # 加载 SKILL.md
    for skill_file in skills_root.rglob("SKILL.md"):
        relative_path = skill_file.relative_to(skills_root)
        virtual_path = "/skills/" + "/".join(relative_path.parts)

        with open(skill_file, "r", encoding="utf-8") as f:
            content = f.read()

        backend.write(virtual_path, content)

    # 加载脚本文件
    for skill_dir in skills_root.iterdir():
        if skill_dir.is_dir():
            for file_path in skill_dir.rglob("*"):
                if file_path.is_file() and file_path.name != "SKILL.md":
                    relative_path = file_path.relative_to(skills_root)
                    virtual_path = "/skills/" + "/".join(relative_path.parts)

                    with open(file_path, "r", encoding="utf-8") as f:
                        content = f.read()

                    backend.write(virtual_path, content)


if __name__ == "__main__":
    agent, backend = create_agent()

    # 将 skills 加载到后端
    load_skills_with_backend(backend)

    # 初始化对话
    messages = []

    print("=" * 50)
    print("Deep Agent 连续对话(输入 q 退出)")
    print("=" * 50)

    while True:
        user_input = input("\n你: ").strip()
        if user_input.lower() in ("q", "quit", "exit"):
            print("再见!")
            break

        if not user_input:
            continue

        messages.append({"role": "user", "content": user_input})

        result = agent.invoke(
            {"messages": messages},
            config={"backend": backend, "configurable": {"thread_id": "12345"}},
        )

        # 更新消息历史
        messages = result["messages"]

        # 打印助手回复
        latest_message = messages[-1]
        content = getattr(latest_message, "content", None)
        token_cost = result["messages"][-1].response_metadata["token_usage"]["total_tokens"]
        if content:
            print(f"\n助手: {content}      -- token_cost: {token_cost}")

运行效果

image

posted @ 2026-05-11 14:46  风陵南  阅读(462)  评论(0)    收藏  举报