# Skills 渐进式展开实现方案(LangChain 1.0+) ## 一、需求概述 用 **Skills** 替代零散的工具调用,实现**渐进式展开**(Progressive Disclosure): Agent 在 system prompt 中只看到技能摘要,按需加载详细技能内容,减少 token 消耗、提升扩展性。 | 技能 | 英文标识 | 职责 | |------|----------|------| | 查找相关商品 | lookup_related | 基于文本/图片查找相似或相关商品 | | 搜索商品 | search_products | 按自然语言描述搜索商品 | | 检验商品 | check_product | 检验商品是否符合用户要求 | | 结果包装 | result_packaging | 格式化、排序、筛选并呈现结果 | | 售后相关 | after_sales | 退换货、物流、保修等售后问题 | --- ## 二、LangChain 1.0 中的 Skills 实现方式 ### 2.1 两种实现路线 | 方式 | 适用场景 | 依赖 | |------|----------|------| | **方式 A:create_agent + 自定义 Skill 中间件** | 购物导购等业务 Agent | `langchain>=1.0`、`langgraph>=1.0` | | **方式 B:Deep Agents + SKILL.md** | 依赖文件系统、多技能目录 | `deepagents` | 购物导购场景推荐**方式 A**,更易与现有 Milvus、CLIP 等服务集成。 ### 2.2 核心思路:Progressive Disclosure ``` 用户请求 → Agent 看轻量描述 → 判断需要的技能 → load_skill → 拿到完整说明 → 执行工具 → 回复 ``` - **启动时**:只注入技能名称 + 简短描述(1–2 句) - **按需加载**:Agent 调用 `load_skill(skill_name)` 获取完整指令 - **执行**:按技能说明调用对应工具 --- ## 三、实现架构 ### 3.1 技能定义结构 ```python from typing import TypedDict class Skill(TypedDict): """可渐进式展开的技能""" name: str # 唯一标识 description: str # 1-2 句,展示在 system prompt content: str # 完整指令,仅在 load_skill 时返回 ``` ### 3.2 五个技能定义示例 ```python SKILLS: list[Skill] = [ { "name": "lookup_related", "description": "查找与某商品相关的其他商品,支持以图搜图、文本相似、同品类推荐。", "content": """# 查找相关商品 ## 适用场景 - 用户上传图片要求「找类似的」 - 用户说「和这个差不多」「搭配的裤子」 - 用户已有一件商品,想找相关款 ## 操作步骤 1. **有图片**:先调用 `analyze_image_style` 理解风格,再调用 `search_by_image` 或 `search_products` 2. **无图片**:用 `search_products` 描述品类+风格+颜色 3. 可结合上下文中的商品 ID、品类做同品类推荐 ## 可用工具 - `search_by_image(image_path, limit)`:以图搜图 - `search_products(query, limit)`:文本搜索 - `analyze_image_style(image_path)`:分析图片风格""", }, { "name": "search_products", "description": "按自然语言描述搜索商品,如「红色连衣裙」「运动鞋」等。", "content": """# 搜索商品 ## 适用场景 - 用户用文字描述想要什么 - 如「冬天穿的外套」「正装衬衫」「跑步鞋」 ## 操作步骤 1. 将用户描述整理成结构化 query(品类+颜色+风格+场景) 2. 调用 `search_products(query, limit)`,limit 默认 5–10 3. 如有图片,可先 `analyze_image_style` 提炼关键词再搜索 ## 可用工具 - `search_products(query, limit)`:自然语言搜索""", }, { "name": "check_product", "description": "检验商品是否符合用户要求,如尺寸、材质、场合、价格区间等。", "content": """# 检验商品是否符合要求 ## 适用场景 - 用户问「这款适合我吗」「有没有 XX 材质的」 - 用户提出约束:尺寸、价格、场合、材质 ## 操作步骤 1. 从对话中提取约束条件(尺寸、材质、场合、价格等) 2. 对已召回商品做筛选或二次搜索 3. 调用 `search_products` 时在 query 中带上约束 4. 回复时明确说明哪些符合、哪些不符合 ## 注意 - 无专门工具时,用 search_products 的 query 表达约束 - 可结合商品元数据(baseColour, season, usage 等)做简单筛选""", }, { "name": "result_packaging", "description": "对搜索结果进行格式化、排序、筛选并呈现给用户。", "content": """# 结果包装 ## 适用场景 - 工具返回多条商品后需要整理呈现 - 用户要求「按价格排序」「只要前 3 个」 ## 操作步骤 1. 按相关性/相似度排序 2. 限制展示数量(通常 3–5 个) 3. **必须使用以下格式**呈现每个商品: ``` 1. [Product Name] ID: [Product ID Number] Category: [Category] Color: [Color] Gender: [Gender] Season: [Season] Usage: [Usage] Relevance: [XX%] ``` 4. ID 字段不可省略,用于前端展示图片""", }, { "name": "after_sales", "description": "处理退换货、物流、保修、尺码建议等售后问题。", "content": """# 售后相关 ## 适用场景 - 退换货政策、运费、签收时间 - 尺码建议、洗涤说明 - 保修、客服联系方式 ## 操作步骤 1. 此类问题无需调用商品搜索工具 2. 按平台统一售后政策回答 3. 涉及具体商品时,可结合商品 ID 查询详情后再回答 4. 复杂问题引导用户联系客服""", }, ] ``` --- ## 四、核心代码实现 ### 4.1 load_skill 工具 ```python from langchain.tools import tool @tool def load_skill(skill_name: str) -> str: """加载技能的完整内容到 Agent 上下文中。 当需要处理特定类型请求时,调用此工具获取该技能的详细说明和操作步骤。 Args: skill_name: 技能名称,可选值:lookup_related, search_products, check_product, result_packaging, after_sales """ for skill in SKILLS: if skill["name"] == skill_name: return f"Loaded skill: {skill_name}\n\n{skill['content']}" available = ", ".join(s["name"] for s in SKILLS) return f"Skill '{skill_name}' not found. Available: {available}" ``` ### 4.2 SkillMiddleware(注入技能描述) ```python from langchain.agents.middleware import AgentMiddleware, ModelRequest, ModelResponse from langchain.messages import SystemMessage from typing import Callable class ShoppingSkillMiddleware(AgentMiddleware): """将技能描述注入 system prompt,使 Agent 能发现并按需加载技能""" tools = [load_skill] def __init__(self): skills_list = [] for skill in SKILLS: skills_list.append(f"- **{skill['name']}**: {skill['description']}") self.skills_prompt = "\n".join(skills_list) def wrap_model_call( self, request: ModelRequest, handler: Callable[[ModelRequest], ModelResponse], ) -> ModelResponse: skills_addendum = ( f"\n\n## 可用技能(按需加载)\n\n{self.skills_prompt}\n\n" "在需要详细说明时,使用 load_skill 工具加载对应技能。" ) new_content = list(request.system_message.content_blocks) + [ {"type": "text", "text": skills_addendum} ] new_system_message = SystemMessage(content=new_content) modified_request = request.override(system_message=new_system_message) return handler(modified_request) ``` ### 4.3 创建带 Skills 的 Agent ```python from langchain.agents import create_agent from langgraph.checkpoint.memory import MemorySaver # 基础工具(搜索、以图搜图、风格分析等) from app.tools.search_tools import search_products, search_by_image, analyze_image_style agent = create_agent( model="gpt-4o-mini", tools=[ load_skill, # 技能加载 search_products, search_by_image, analyze_image_style, ], system_prompt="""你是智能时尚购物助手。根据用户需求,先判断使用哪个技能,必要时用 load_skill 加载技能详情。 处理商品结果时,必须遵守 result_packaging 技能中的格式要求。""", middleware=[ShoppingSkillMiddleware()], checkpointer=MemorySaver(), ) ``` --- ## 五、与工具的关系 | 能力 | 技能 | 工具 | |------|------|------| | 查找相关 | lookup_related | search_by_image, search_products, analyze_image_style | | 搜索商品 | search_products | search_products | | 检验商品 | check_product | search_products(用 query 表达约束) | | 结果包装 | result_packaging | 无(纯 prompt 约束) | | 售后 | after_sales | 无(或对接客服 API) | - **技能**:提供「何时用、怎么用」的说明,支持渐进式加载。 - **工具**:实际执行搜索、分析等操作。 --- ## 六、可选:技能约束(进阶) 若希望「先加载技能再使用工具」,可结合 `ToolRuntime` 和 state 做约束: ```python from langchain.tools import tool, ToolRuntime from langgraph.types import Command from langchain.messages import ToolMessage from typing_extensions import NotRequired class CustomState(AgentState): skills_loaded: NotRequired[list[str]] @tool def load_skill(skill_name: str, runtime: ToolRuntime) -> Command: """...""" for skill in SKILLS: if skill["name"] == skill_name: content = f"Loaded skill: {skill_name}\n\n{skill['content']}" return Command(update={ "messages": [ToolMessage(content=content, tool_call_id=runtime.tool_call_id)], "skills_loaded": [skill_name], }) # ... # 在 check_product 等工具中检查 skills_loaded ``` --- ## 七、依赖与版本 ```text # requirements.txt langchain>=1.0.0 langchain-openai>=0.2.0 langchain-core>=0.3.0 langgraph>=1.0.0 ``` - Python 3.10+ - 若使用 Deep Agents 的 SKILL.md,需额外安装 `deepagents` --- ## 八、总结 | 项目 | 说明 | |------|------| | **效果** | 系统 prompt 只放简短技能描述,按需加载完整内容,减少 token、便于扩展 | | **流程** | 轻量描述 → load_skill → 完整说明 → 调用工具 → 回复 | | **实现** | `SkillMiddleware` + `load_skill` + `create_agent` | | **技能** | lookup_related, search_products, check_product, result_packaging, after_sales | 完整示例可参考官方教程:[Build a SQL assistant with on-demand skills](https://docs.langchain.com/oss/python/langchain/multi-agent/skills-sql-assistant)。