Skill: mymrxu/auto-model-selector (version 1.0.1)

--- name: auto-model-selector 根据用户问题的复杂度自动选择合适的AI模型进行处理。使用本地模型处理简单任务，云端模型处理复杂任务。 metadata: {"clawdbot":{"emoji":"🤖","os":["linux","darwin","win32"]}} --- # 智能路由技能 ## 描述 根据用户问题的复杂度自动选择合适的AI模型进行处理。使用本地模型处理简单任务，云端模型处理复杂任务。 ## 功能 1. **智能路由**：分析用户请求的复杂度 2. **模型选择**：自动根据请求的任务复杂度选择模型 3. **自动切换**：在每次用户请求时自动设置合适的模型 ## 路由逻辑 ### 简单任务（使用本地模型） - 时间/日期查询 - 简单文件操作 - 状态检查 - 基础命令执行 - 简短回答 ### 复杂任务（使用云端模型） - 代码编写 - 复杂分析 - 创意写作 - 深度解释 - 多步骤任务 ## 配置要求 - 需要可用的本地模型服务 (Ollama) - 需要可用的云端模型API - 需要OpenClaw支持模型切换 ## 使用方法 1. 安装技能：`clawdhub install smart-router` 2. 技能会自动分析每个用户请求 3. 根据复杂度自动选择模型 4. 处理完成后会报告使用的模型 ## 示例 ``` 用户：现在几点了 技能：检测为简单任务 → 使用本地模型 → 回答时间 用户：帮我写一个Flutter登录页面 技能：检测为复杂任务 → 使用云端模型 → 生成代码 ``` ## 技术实现 - 使用关键词匹配进行快速判断 - 支持中英文关键词 - 可配置的路由规则 - 详细的日志输出 ## 更新日志 - 2026-03-05: 初始版本发布

path: README.md
content: # 智能路由技能使用指南

## 简介
智能路由技能可以根据用户问题的复杂度自动选择合适的AI模型进行处理。

## 快速开始

### 1. 测试技能
```bash
# 测试简单请求
./smart_router.sh "现在几点了"

# 测试复杂请求  
./smart_router.sh "帮我写一个Flutter登录页面"

# 使用Python直接测试
python3 main.py "现在几点了"
```

### 2. 输出示例
```json
{
  "complexity": "simple",
  "model": "ollama-local/deepseek-r1-7b",
  "reason": "简单请求，使用本地模型处理",
  "method": "pattern",
  "prompt_length": 5,
  "skill": "smart-router",
  "version": "1.0.0"
}
```

### 3. 集成到OpenClaw
将技能目录移动到OpenClaw技能目录：
```bash
# 复制到OpenClaw技能目录
cp -r smart-router ~/.openclaw/skills/

# 或者使用clawdhub安装（如果发布到clawdhub）
clawdhub install smart-router
```

## API接口

### Python API
```python
from smart_router import router

# 获取路由结果
result = router.route_request("现在几点了")
print(f"推荐模型: {result['model']}")

# 直接获取模型名称
model = router.get_recommended_model("现在几点了")
```

### Shell API
```bash
# 获取完整路由信息
./smart_router.sh "用户请求内容"

# 只获取模型名称（适合脚本使用）
./smart_router.sh "用户请求内容" | jq -r '.model'
```

## 配置

### 修改Ollama主机地址
编辑 `smart_router.py`：
```python
class SmartRouter:
    def __init__(self, ollama_host: str = "http://192.168.10.14:11434"):
        # 修改这里的地址
```

### 自定义路由规则
编辑 `smart_router.py` 中的模式列表：
- `simple_patterns`: 简单请求模式
- `complex_patterns`: 复杂请求模式

## 路由逻辑

### 判断流程
1. **快速模式匹配**：使用预定义关键词匹配
2. **模型判断**：如果快速匹配失败，使用deepseek-r1:1.5b模型判断
3. **缓存机制**：相同请求会缓存结果，提高性能

### 简单任务示例
- "现在几点了"
- "列出文件"
- "天气怎么样"
- "提醒我开会"

### 复杂任务示例
- "写一个登录页面"
- "解释量子力学"
- "分析代码性能"
- "设计系统架构"

## 性能优化

### 缓存机制
- 相同请求会缓存路由结果
- 减少模型调用次数
- 提高响应速度

### 快速匹配
- 使用正则表达式快速判断
- 避免不必要的模型调用
- 支持中英文关键词

## 故障排除

### 常见问题
1. **Ollama连接失败**
   - 检查Ollama服务是否运行
   - 检查网络连接
   - 修改`ollama_host`配置

2. **模型不可用**
   - 检查模型是否已下载：`ollama list`
   - 下载所需模型：`ollama pull deepseek-r1:7b`

3. **Python依赖问题**
   - 确保已安装requests库：`pip install requests`

### 日志输出
技能会输出详细日志，包括：
- 使用的判断方法（pattern/model）
- 判断结果
- 推荐模型和理由

## 扩展开发

### 添加新语言支持
在模式列表中添加新的语言关键词：
```python
simple_patterns = [
    # 中文
    r'^(你好|嗨)',
    # 英文
    r'^(hi|hello)',
    # 日文
    r'^(こんにちは|はい)',
]
```

### 添加自定义判断逻辑
继承`SmartRouter`类并重写方法：
```python
class CustomRouter(SmartRouter):
    def custom_check(self, prompt: str) -> Optional[str]:
        # 自定义判断逻辑
        pass
```

## 版本历史
- v1.0.0 (2026-03-05): 初始版本发布
  - 支持快速模式匹配
  - 支持模型判断
  - 缓存机制
  - 完整的API接口

## 许可证
MIT License

path: _meta.json
content: ownerId: kn76q1yg60daf6efs7b0jm78es82bmfp
slug: auto-model-selector
version: 1.0.0
publishedAt: 1772711157345

path: main.py
content: #!/usr/bin/env python3
"""
智能路由技能主程序
集成到OpenClaw技能系统，支持模型管理和成本优化
"""

import sys
import os
import json
import argparse
from pathlib import Path

# 添加当前目录到Python路径
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

from smart_router import router
try:
    from model_manager import model_manager, ModelManager
    MODEL_MANAGER_AVAILABLE = True
except ImportError:
    MODEL_MANAGER_AVAILABLE = False

def analyze_request(prompt: str) -> dict:
    """分析用户请求并返回路由结果"""
    try:
        result = router.route_request(prompt)
        
        # 添加技能标识
        result["skill"] = "smart-router"
        result["version"] = "2.0.0"
        
        # 添加模型配置信息
        if MODEL_MANAGER_AVAILABLE:
            result["model_config"] = {
                "total_models": len(model_manager.models),
                "enabled_models": len(model_manager.get_enabled_models()),
                "local_models": len(model_manager.get_local_models()),
                "cloud_models": len(model_manager.get_cloud_models())
            }
        
        return result
    except Exception as e:
        return {
            "error": str(e),
            "skill": "smart-router",
            "recommended_model": "deepseek/deepseek-chat",  # 出错时默认使用云端模型
            "reason": f"路由分析失败: {e}"
        }

def get_model_recommendation(prompt: str) -> str:
    """获取推荐的模型名称"""
    try:
        return router.get_recommended_model(prompt)
    except Exception:
        return "deepseek/deepseek-chat"  # 出错时默认使用云端模型

def list_models() -> dict:
    """列出所有模型配置"""
    if MODEL_MANAGER_AVAILABLE:
        return {
            "models": model_manager.models,
            "summary": {
                "total": len(model_manager.models),
                "enabled": len(model_manager.get_enabled_models()),
                "local": len(model_manager.get_local_models()),
                "cloud": len(model_manager.get_cloud_models())
            }
        }
    else:
        return {
            "error": "模型管理器不可用",
            "models": router.get_available_models()
        }

def update_models() -> dict:
    """更新模型配置（检测可用模型）"""
    if MODEL_MANAGER_AVAILABLE:
        model_manager.update_config_from_detection()
        return {
            "status": "success",
            "message": "模型配置已更新",
            "models": model_manager.models
        }
    else:
        return {
            "status": "error",
            "message": "模型管理器不可用"
        }

def add_model(model_id: str, model_type: str, name: str, priority: str = "normal") -> dict:
    """添加新模型"""
    if not MODEL_MANAGER_AVAILABLE:
        return {
            "status": "error",
            "message": "模型管理器不可用"
        }
    
    config = {
        "enable": True,
        "type": model_type,
        "name": name,
        "model_priority": priority,
        "description": f"用户添加的{model_type}模型",
        "cost_weight": 0.3 if model_type == "local" else 1.0
    }
    
    if model_manager.add_model(model_id, config):
        return {
            "status": "success",
            "message": f"已添加模型: {model_id}",
            "model_id": model_id,
            "config": config
        }
    else:
        return {
            "status": "error",
            "message": "添加模型失败"
        }

def remove_model(model_id: str) -> dict:
    """删除模型"""
    if not MODEL_MANAGER_AVAILABLE:
        return {
            "status": "error",
            "message": "模型管理器不可用"
        }
    
    if model_manager.remove_model(model_id):
        return {
            "status": "success",
            "message": f"已删除模型: {model_id}"
        }
    else:
        return {
            "status": "error",
            "message": f"删除模型失败: {model_id}"
        }

def main():
    """主函数：处理命令行参数"""
    parser = argparse.ArgumentParser(description="智能路由技能")
    parser.add_argument("command", nargs="?", help="命令: route, list, update, add, remove")
    parser.add_argument("args", nargs="*", help="命令参数")
    
    # 如果只有一个参数且不是命令，则视为路由请求
    if len(sys.argv) == 2 and sys.argv[1] not in ["list", "update", "add", "remove"]:
        prompt = sys.argv[1]
        result = analyze_request(prompt)
        print(json.dumps(result, ensure_ascii=False, indent=2))
        return
    
    args = parser.parse_args()
    
    if args.command == "route":
        if not args.args:
            print("错误: 需要提供用户请求")
            sys.exit(1)
        prompt = " ".join(args.args)
        result = analyze_request(prompt)
        print(json.dumps(result, ensure_ascii=False, indent=2))
    
    elif args.command == "list":
        result = list_models()
        print(json.dumps(result, ensure_ascii=False, indent=2))
    
    elif args.command == "update":
        result = update_models()
        print(json.dumps(result, ensure_ascii=False, indent=2))
    
    elif args.command == "add":
        if len(args.args) < 3:
            print("错误: 需要提供 model_id type name [priority]")
            print("示例: add ollama-local/new-model local '新模型' normal")
            sys.exit(1)
        
        model_id = args.args[0]
        model_type = args.args[1]
        name = args.args[2]
        priority = args.args[3] if len(args.args) > 3 else "normal"
        
        result = add_model(model_id, model_type, name, priority)
        print(json.dumps(result, ensure_ascii=False, indent=2))
    
    elif args.command == "remove":
        if not args.args:
            print("错误: 需要提供 model_id")
            sys.exit(1)
        
        model_id = args.args[0]
        result = remove_model(model_id)
        print(json.dumps(result, ensure_ascii=False, indent=2))
    
    else:
        print("智能路由技能 v2.0.0")
        print("=" * 40)
        print("用法:")
        print("  路由请求: python main.py <用户请求>")
        print("  列出模型: python main.py list")
        print("  更新配置: python main.py update")
        print("  添加模型: python main.py add <model_id> <type> <name> [priority]")
        print("  删除模型: python main.py remove <model_id>")
        print("")
        print("示例:")
        print("  python main.py '现在几点了'")
        print("  python main.py list")
        print("  python main.py add ollama-local/test local '测试模型' normal")

if __name__ == "__main__":
    main()

path: model_cli.py
content: #!/usr/bin/env python3
"""
模型管理CLI工具
用于管理模型配置的独立命令行工具
"""

import sys
import json
import argparse
from pathlib import Path

# 添加当前目录到Python路径
sys.path.insert(0, str(Path(__file__).parent))

try:
    from model_manager import model_manager, ModelManager
    MODEL_MANAGER_AVAILABLE = True
except ImportError as e:
    print(f"错误: 无法导入模型管理器: {e}")
    MODEL_MANAGER_AVAILABLE = False
    sys.exit(1)

def print_colored(text: str, color: str = "reset") -> None:
    """打印彩色文本"""
    colors = {
        "red": "\033[91m",
        "green": "\033[92m",
        "yellow": "\033[93m",
        "blue": "\033[94m",
        "magenta": "\033[95m",
        "cyan": "\033[96m",
        "reset": "\033[0m"
    }
    print(f"{colors.get(color, colors['reset'])}{text}{colors['reset']}")

def command_list(args):
    """列出所有模型"""
    print_colored("\n📋 模型配置列表", "cyan")
    print("=" * 60)
    
    enabled_models = model_manager.get_enabled_models()
    disabled_models = {k: v for k, v in model_manager.models.items() 
                      if not v.get("enable", False)}
    
    print_colored(f"总模型数: {len(model_manager.models)}", "yellow")
    print_colored(f"启用模型: {len(enabled_models)}", "green")
    print_colored(f"禁用模型: {len(disabled_models)}", "red")
    
    if enabled_models:
        print_colored("\n✅ 启用模型:", "green")
        for i, (model_id, config) in enumerate(enabled_models.items(), 1):
            type_color = "blue" if config.get("type") == "local" else "magenta"
            priority_color = "yellow" if config.get("model_priority") == "normal" else "red"
            
            print(f"  {i}. {model_id}")
            print(f"     名称: {config.get('name', 'N/A')}")
            print(f"     类型: {print_colored(config.get('type', 'N/A'), type_color)}")
            print(f"     优先级: {print_colored(config.get('model_priority', 'N/A'), priority_color)}")
            print(f"     成本权重: {config.get('cost_weight', 'N/A')}")
            print(f"     描述: {config.get('description', 'N/A')}")
    
    if disabled_models:
        print_colored("\n❌ 禁用模型:", "red")
        for i, (model_id, config) in enumerate(disabled_models.items(), 1):
            print(f"  {i}. {model_id} - {config.get('name', 'N/A')}")

def command_show(args):
    """显示单个模型详情"""
    model_id = args.model_id
    if model_id not in model_manager.models:
        print_colored(f"错误: 模型不存在: {model_id}", "red")
        return
    
    config = model_manager.models[model_id]
    
    print_colored(f"\n🔍 模型详情: {model_id}", "cyan")
    print("=" * 60)
    
    status = "✅ 启用" if config.get("enable", False) else "❌ 禁用"
    status_color = "green" if config.get("enable", False) else "red"
    
    print_colored(f"状态: {status}", status_color)
    print(f"名称: {config.get('name', 'N/A')}")
    print(f"类型: {config.get('type', 'N/A')}")
    print(f"优先级: {config.get('model_priority', 'N/A')}")
    print(f"成本权重: {config.get('cost_weight', 'N/A')}")
    print(f"描述: {config.get('description', 'N/A')}")
    
    # 显示所有字段
    print_colored("\n📄 完整配置:", "yellow")
    print(json.dumps(config, ensure_ascii=False, indent=2))

def command_detect(args):
    """检测可用模型"""
    print_colored("\n🔍 检测可用模型中...", "cyan")
    
    detected_models = model_manager.detect_available_models()
    
    print_colored(f"检测到 {len(detected_models)} 个可用模型:", "green")
    for model_id, config in detected_models.items():
        status = "✅" if config.get("detected", False) else "❌"
        print(f"  {status} {model_id} - {config.get('name', 'N/A')}")
    
    if args.update:
        print_colored("\n🔄 更新配置中...", "yellow")
        model_manager.update_config_from_detection()
        print_colored("✅ 配置已更新", "green")
        command_list(args)

def command_enable(args):
    """启用模型"""
    model_id = args.model_id
    if model_id not in model_manager.models:
        print_colored(f"错误: 模型不存在: {model_id}", "red")
        return
    
    if model_manager.enable_model(model_id):
        print_colored(f"✅ 已启用模型: {model_id}", "green")
    else:
        print_colored(f"❌ 启用模型失败: {model_id}", "red")

def command_disable(args):
    """禁用模型"""
    model_id = args.model_id
    if model_id not in model_manager.models:
        print_colored(f"错误: 模型不存在: {model_id}", "red")
        return
    
    if model_manager.disable_model(model_id):
        print_colored(f"✅ 已禁用模型: {model_id}", "yellow")
    else:
        print_colored(f"❌ 禁用模型失败: {model_id}", "red")

def command_add(args):
    """添加新模型"""
    model_id = args.model_id
    model_type = args.type
    name = args.name
    priority = args.priority
    
    if model_id in model_manager.models:
        print_colored(f"警告: 模型已存在: {model_id}", "yellow")
        if not args.force:
            print_colored("使用 --force 参数覆盖", "yellow")
            return
    
    config = {
        "enable": True,
        "type": model_type,
        "name": name,
        "model_priority": priority,
        "description": args.description or f"用户添加的{model_type}模型",
        "cost_weight": args.cost_weight or (0.3 if model_type == "local" else 1.0)
    }
    
    if model_manager.add_model(model_id, config):
        print_colored(f"✅ 已添加模型: {model_id}", "green")
        command_show(argparse.Namespace(model_id=model_id))
    else:
        print_colored(f"❌ 添加模型失败: {model_id}", "red")

def command_remove(args):
    """删除模型"""
    model_id = args.model_id
    if model_id not in model_manager.models:
        print_colored(f"错误: 模型不存在: {model_id}", "red")
        return
    
    if not args.force:
        confirm = input(f"确认删除模型 '{model_id}'? [y/N]: ")
        if confirm.lower() != 'y':
            print_colored("取消删除", "yellow")
            return
    
    if model_manager.remove_model(model_id):
        print_colored(f"✅ 已删除模型: {model_id}", "green")
    else:
        print_colored(f"❌ 删除模型失败: {model_id}", "red")

def command_cost(args):
    """成本优化分析"""
    print_colored("\n💰 成本优化分析", "cyan")
    print("=" * 60)
    
    enabled_models = model_manager.get_enabled_models()
    
    if not enabled_models:
        print_colored("没有启用的模型", "red")
        return
    
    # 按成本排序
    sorted_models = sorted(
        enabled_models.items(),
        key=lambda x: x[1].get("cost_weight", 1.0)
    )
    
    print_colored("成本从低到高排序:", "yellow")
    for i, (model_id, config) in enumerate(sorted_models, 1):
        cost = config.get("cost_weight", 1.0)
        cost_bar = "█" * int(cost * 10)
        
        type_icon = "🖥️ " if config.get("type") == "local" else "☁️ "
        priority_icon = "⭐" if config.get("model_priority") == "max" else "⚪"
        
        print(f"  {i}. {type_icon} {model_id}")
        print(f"     成本: {cost:.2f} {cost_bar}")
        print(f"     优先级: {priority_icon} {config.get('model_priority', 'N/A')}")
    
    # 推荐模型
    print_colored("\n🎯 推荐使用:", "green")
    print(f"  简单任务: {model_manager.get_cost_effective_model('simple')}")
    print(f"  复杂任务: {model_manager.get_cost_effective_model('complex')}")

def command_test(args):
    """测试路由"""
    prompt = args.prompt
    if not prompt:
        print_colored("错误: 需要提供测试文本", "red")
        return
    
    print_colored(f"\n🧪 路由测试: '{prompt}'", "cyan")
    print("=" * 60)
    
    # 导入路由器
    try:
        from smart_router import router
    except ImportError:
        print_colored("错误: 无法导入路由器", "red")
        return
    
    result = router.route_request(prompt)
    
    print(f"请求: {result.get('prompt_length', 0)} 字符")
    print(f"复杂度: {result.get('complexity', 'unknown')}")
    print(f"判断方法: {result.get('method', 'unknown')}")
    print(f"推荐模型: {result.get('model', 'unknown')}")
    print(f"模型类型: {result.get('model_type', 'unknown')}")
    print(f"成本权重: {result.get('cost_weight', 1.0):.2f}")
    print(f"理由: {result.get('reason', 'N/A')}")
    print(f"成本优化: {'✅ 是' if result.get('cost_optimized', False) else '❌ 否'}")

def main():
    """主函数"""
    parser = argparse.ArgumentParser(
        description="模型管理CLI工具",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
示例:
  %(prog)s list                    # 列出所有模型
  %(prog)s show <model_id>         # 显示模型详情
  %(prog)s detect --update         # 检测并更新模型
  %(prog)s add <id> <type> <name>  # 添加新模型
  %(prog)s remove <model_id>       # 删除模型
  %(prog)s cost                    # 成本分析
  %(prog)s test "现在几点了"       # 测试路由
        """
    )
    
    subparsers = parser.add_subparsers(dest="command", help="命令")
    
    # list 命令
    list_parser = subparsers.add_parser("list", help="列出所有模型")
    list_parser.set_defaults(func=command_list)
    
    # show 命令
    show_parser = subparsers.add_parser("show", help="显示模型详情")
    show_parser.add_argument("model_id", help="模型ID")
    show_parser.set_defaults(func=command_show)
    
    # detect 命令
    detect_parser = subparsers.add_parser("detect", help="检测可用模型")
    detect_parser.add_argument("--update", action="store_true", help="检测后更新配置")
    detect_parser.set_defaults(func=command_detect)
    
    # enable 命令
    enable_parser = subparsers.add_parser("enable", help="启用模型")
    enable_parser.add_argument("model_id", help="模型ID")
    enable_parser.set_defaults(func=command_enable)
    
    # disable 命令
    disable_parser = subparsers.add_parser("disable", help="禁用模型")
    disable_parser.add_argument("model_id", help="模型ID")
    disable_parser.set_defaults(func=command_disable)
    
    # add 命令
    add_parser = subparsers.add_parser("add", help="添加新模型")
    add_parser.add_argument("model_id", help="模型ID")
    add_parser.add_argument("type", choices=["local", "cloud"], help="模型类型")
    add_parser.add_argument("name", help="模型名称")
    add_parser.add_argument("--priority", choices=["normal", "max"], default="normal", help="模型优先级")
    add_parser.add_argument("--description", help="模型描述")
    add_parser.add_argument("--cost-weight", type=float, help="成本权重")
    add_parser.add_argument("--force", action="store_true", help="强制覆盖已存在的模型")
    add_parser.set_defaults(func=command_add)
    
    # remove 命令
    remove_parser = subparsers.add_parser("remove", help="删除模型")
    remove_parser.add_argument("model_id", help="模型ID")
    remove_parser.add_argument("--force", action="store_true", help="强制删除")
    remove_parser.set_defaults(func=command_remove)
    
    # cost 命令
    cost_parser = subparsers.add_parser("cost", help="成本优化分析")
    cost_parser.set_defaults(func=command_cost)
    
    # test 命令
    test_parser = subparsers.add_parser("test", help="测试路由")
    test_parser.add_argument("prompt", help="测试文本")
    test_parser.set_defaults(func=command_test)
    
    # 如果没有参数，显示帮助
    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(0)
    
    args = parser.parse_args()
    
    # 执行命令
    try:
        args.func(args)
    except AttributeError:
        parser.print_help()
    except Exception as e:
        print_colored(f"错误: {e}", "red")
        sys.exit(1)

if __name__ == "__main__":
    main()

path: model_manager.py
content: #!/usr/bin/env python3
"""
模型配置文件管理器
管理本地和云端模型配置，支持成本优化
"""

import json
import os
from pathlib import Path
from typing import Dict, List, Any, Optional
import subprocess

class ModelManager:
    def __init__(self, config_path: str = None):
        """初始化模型管理器"""
        if config_path:
            self.config_path = Path(config_path)
        else:
            # 默认路径：技能目录下的models.json
            self.config_path = Path(__file__).parent / "models.json"
        
        self.models = {}
        self.load_config()
    
    def load_config(self) -> None:
        """加载模型配置"""
        if self.config_path.exists():
            try:
                with open(self.config_path, 'r', encoding='utf-8') as f:
                    self.models = json.load(f)
                print(f"[模型管理器] 已加载 {len(self.models)} 个模型配置")
            except Exception as e:
                print(f"[模型管理器] 加载配置失败: {e}")
                self.models = {}
        else:
            print("[模型管理器] 配置文件不存在，将创建默认配置")
            self.models = {}
            self.create_default_config()
    
    def save_config(self) -> None:
        """保存模型配置"""
        try:
            with open(self.config_path, 'w', encoding='utf-8') as f:
                json.dump(self.models, f, ensure_ascii=False, indent=2)
            print(f"[模型管理器] 配置已保存到 {self.config_path}")
        except Exception as e:
            print(f"[模型管理器] 保存配置失败: {e}")
    
    def create_default_config(self) -> None:
        """创建默认模型配置"""
        default_models = {
           
        }
        
        self.models = default_models
        self.save_config()
    
    def detect_available_models(self) -> Dict[str, Dict[str, Any]]:
        """检测当前可用的模型"""
        available_models = {}
        
        # 检测本地模型 (Ollama)
        local_models = self._detect_local_models()
        available_models.update(local_models)
        
        # 检测云端模型 (基于配置)
        cloud_models = self._detect_cloud_models()
        available_models.update(cloud_models)
        
        return available_models
    
    def _detect_local_models(self) -> Dict[str, Dict[str, Any]]:
        """检测本地Ollama模型"""
        local_models = {}
        
        try:
            # 尝试获取Ollama模型列表
            result = subprocess.run(
                ["curl", "-s", "http://192.168.10.14:11434/api/tags"],
                capture_output=True,
                text=True,
                timeout=5
            )
            
            if result.returncode == 0:
                data = json.loads(result.stdout)
                for model_info in data.get("models", []):
                    model_name = model_info.get("name", "")
                    model_id = f"ollama-local/{model_name.replace(':', '-')}"
                    
                    # 确定模型优先级
                    if "1.5b" in model_name.lower():
                        priority = "normal"
                        model_type = "local"
                    elif "7b" in model_name.lower():
                        priority = "normal"
                        model_type = "local"
                    else:
                        priority = "normal"
                        model_type = "local"
                    
                    local_models[model_id] = {
                        "enable": True,
                        "type": model_type,
                        "name": f"Ollama: {model_name}",
                        "model_priority": priority,
                        "description": f"本地Ollama模型: {model_name}",
                        "cost_weight": 0.3 if "7b" in model_name.lower() else 0.1,
                        "detected": True
                    }
                
                print(f"[模型管理器] 检测到 {len(local_models)} 个本地模型")
            else:
                print("[模型管理器] 无法连接到Ollama服务")
                
        except Exception as e:
            print(f"[模型管理器] 检测本地模型失败: {e}")
        
        return local_models
    
    def _detect_cloud_models(self) -> Dict[str, Dict[str, Any]]:
        """检测云端模型（基于当前配置）"""
        cloud_models = {}
        
        # 从当前配置中提取云端模型
        for model_id, config in self.models.items():
            if config.get("type") == "cloud":
                cloud_models[model_id] = {
                    "enable": config.get("enable", True),
                    "type": "cloud",
                    "name": config.get("name", model_id),
                    "model_priority": config.get("model_priority", "normal"),
                    "description": config.get("description", "云端模型"),
                    "cost_weight": config.get("cost_weight", 1.0),
                    "detected": True
                }
        
        return cloud_models
    
    def update_config_from_detection(self) -> None:
        """根据检测结果更新配置"""
        detected_models = self.detect_available_models()
        
        # 更新或添加新检测到的模型
        for model_id, detected_config in detected_models.items():
            if model_id not in self.models:
                # 新模型，添加到配置
                self.models[model_id] = detected_config
                print(f"[模型管理器] 添加新模型: {model_id}")
            else:
                # 更新现有模型的enable状态
                if detected_config.get("detected", False):
                    self.models[model_id]["enable"] = True
                else:
                    self.models[model_id]["enable"] = False
        
        # 标记未检测到的模型为禁用
        for model_id in list(self.models.keys()):
            if model_id not in detected_models:
                self.models[model_id]["enable"] = False
        
        self.save_config()
    
    def get_enabled_models(self, model_type: str = None) -> Dict[str, Dict[str, Any]]:
        """获取启用的模型"""
        enabled_models = {}
        
        for model_id, config in self.models.items():
            if config.get("enable", False):
                if model_type is None or config.get("type") == model_type:
                    enabled_models[model_id] = config
        
        return enabled_models
    
    def get_local_models(self) -> Dict[str, Dict[str, Any]]:
        """获取本地模型"""
        return self.get_enabled_models("local")
    
    def get_cloud_models(self) -> Dict[str, Dict[str, Any]]:
        """获取云端模型"""
        return self.get_enabled_models("cloud")
    
    def get_model_by_priority(self, priority: str = "normal") -> List[str]:
        """根据优先级获取模型ID列表"""
        model_ids = []
        
        for model_id, config in self.models.items():
            if config.get("enable", False) and config.get("model_priority") == priority:
                model_ids.append(model_id)
        
        return model_ids
    
    def add_model(self, model_id: str, config: Dict[str, Any]) -> bool:
        """添加新模型"""
        # 验证必需字段
        required_fields = ["enable", "type", "name", "model_priority"]
        for field in required_fields:
            if field not in config:
                print(f"[模型管理器] 错误: 缺少必需字段 '{field}'")
                return False
        
        # 验证字段值
        if config["type"] not in ["local", "cloud"]:
            print(f"[模型管理器] 错误: type必须是 'local' 或 'cloud'")
            return False
        
        if config["model_priority"] not in ["normal", "max"]:
            print(f"[模型管理器] 错误: model_priority必须是 'normal' 或 'max'")
            return False
        
        # 添加模型
        self.models[model_id] = config
        self.save_config()
        print(f"[模型管理器] 已添加模型: {model_id}")
        return True
    
    def remove_model(self, model_id: str) -> bool:
        """删除模型"""
        if model_id in self.models:
            del self.models[model_id]
            self.save_config()
            print(f"[模型管理器] 已删除模型: {model_id}")
            return True
        else:
            print(f"[模型管理器] 错误: 模型不存在: {model_id}")
            return False
    
    def update_model(self, model_id: str, updates: Dict[str, Any]) -> bool:
        """更新模型配置"""
        if model_id not in self.models:
            print(f"[模型管理器] 错误: 模型不存在: {model_id}")
            return False
        
        # 保护必需字段不被修改
        protected_fields = ["enable", "type", "name", "model_priority"]
        for field in protected_fields:
            if field in updates:
                print(f"[模型管理器] 警告: 字段 '{field}' 受保护，无法修改")
                del updates[field]
        
        # 更新其他字段
        self.models[model_id].update(updates)
        self.save_config()
        print(f"[模型管理器] 已更新模型: {model_id}")
        return True
    
    def enable_model(self, model_id: str) -> bool:
        """启用模型"""
        if model_id in self.models:
            self.models[model_id]["enable"] = True
            self.save_config()
            print(f"[模型管理器] 已启用模型: {model_id}")
            return True
        else:
            print(f"[模型管理器] 错误: 模型不存在: {model_id}")
            return False
    
    def disable_model(self, model_id: str) -> bool:
        """禁用模型"""
        if model_id in self.models:
            self.models[model_id]["enable"] = False
            self.save_config()
            print(f"[模型管理器] 已禁用模型: {model_id}")
            return True
        else:
            print(f"[模型管理器] 错误: 模型不存在: {model_id}")
            return False
    
    def get_cost_effective_model(self, task_complexity: str = "simple") -> str:
        """根据任务复杂度和成本获取最经济的模型"""
        enabled_models = self.get_enabled_models()
        
        if not enabled_models:
            return "deepseek/deepseek-chat"  # 默认回退
        
        # 根据任务复杂度选择策略
        if task_complexity == "simple":
            # 简单任务：优先使用成本最低的本地模型
            local_models = self.get_local_models()
            if local_models:
                # 按成本权重排序
                sorted_models = sorted(
                    local_models.items(),
                    key=lambda x: x[1].get("cost_weight", 1.0)
                )
                return sorted_models[0][0]  # 返回成本最低的本地模型
        
        # 复杂任务或没有本地模型：使用云端模型
        cloud_models = self.get_cloud_models()
        if cloud_models:
            # 如果有max优先级模型，优先使用
            max_models = [m for m, c in cloud_models.items() 
                         if c.get("model_priority") == "max"]
            if max_models:
                return max_models[0]
            
            # 否则使用第一个可用的云端模型
            return list(cloud_models.keys())[0]
        
        # 没有可用模型，返回第一个启用的模型
        return list(enabled_models.keys())[0]
    
    def print_summary(self) -> None:
        """打印模型配置摘要"""
        print("\n" + "="*60)
        print("模型配置摘要")
        print("="*60)
        
        enabled_models = self.get_enabled_models()
        disabled_models = {k: v for k, v in self.models.items() 
                          if not v.get("enable", False)}
        
        print(f"总模型数: {len(self.models)}")
        print(f"启用模型: {len(enabled_models)}")
        print(f"禁用模型: {len(disabled_models)}")
        
        print("\n启用模型列表:")
        for i, (model_id, config) in enumerate(enabled_models.items(), 1):
            print(f"  {i}. {model_id}")
            print(f"     名称: {config.get('name', 'N/A')}")
            print(f"     类型: {config.get('type', 'N/A')}")
            print(f"     优先级: {config.get('model_priority', 'N/A')}")
            print(f"     成本权重: {config.get('cost_weight', 'N/A')}")
        
        if disabled_models:
            print("\n禁用模型列表:")
            for i, (model_id, config) in enumerate(disabled_models.items(), 1):
                print(f"  {i}. {model_id}")

# 单例实例
model_manager = ModelManager()

if __name__ == "__main__":
    # 测试函数
    manager = ModelManager()
    
    # 打印当前配置
    manager.print_summary()
    
    # 检测并更新配置
    print("\n检测可用模型...")
    manager.update_config_from_detection()
    
    # 打印更新后的配置
    manager.print_summary()
    
    # 测试成本优化选择
    print("\n成本优化测试:")
    print(f"简单任务推荐模型: {manager.get_cost_effective_model('simple')}")
    print(f"复杂任务推荐模型: {manager.get_cost_effective_model('complex')}")

path: models.json
content: {
  "ollama-local/deepseek-r1-1.5b": {
    "enable": true,
    "type": "local",
    "name": "DeepSeek R1 1.5B (任务分拣)",
    "model_priority": "normal",
    "description": "本地小模型，适合简单任务分拣",
    "cost_weight": 0.1
  },
  "ollama-local/deepseek-r1-7b": {
    "enable": true,
    "type": "local",
    "name": "DeepSeek R1 7B (本地任务处理)",
    "model_priority": "normal",
    "description": "本地中等模型，适合大多数任务",
    "cost_weight": 0.3
  },
  "deepseek/deepseek-chat": {
    "enable": true,
    "type": "cloud",
    "name": "DeepSeek Chat (云端复杂任务)",
    "model_priority": "max",
    "description": "云端大模型，适合复杂任务",
    "cost_weight": 1.0
  }
}

path: smart_router.py
content: #!/usr/bin/env python3
"""
智能路由系统核心
根据问题复杂度自动选择模型，集成成本优化
"""

import re
import json
from typing import Dict, Any, Optional

# 尝试导入requests，如果失败则使用备用方案
try:
    import requests
    REQUESTS_AVAILABLE = True
except ImportError:
    REQUESTS_AVAILABLE = False
    print("[警告] requests库未安装，将使用纯关键词匹配模式")

# 导入模型管理器
try:
    from model_manager import model_manager
    MODEL_MANAGER_AVAILABLE = True
except ImportError:
    MODEL_MANAGER_AVAILABLE = False
    print("[警告] 模型管理器不可用，将使用默认模型选择")

class SmartRouter:
    def __init__(self, ollama_host: str = "http://192.168.10.14:11434"):
        self.ollama_host = ollama_host
        self.judge_model = "deepseek-r1:1.5b"
        
        # 初始化模型管理器
        if MODEL_MANAGER_AVAILABLE:
            # 自动检测并更新模型配置
            model_manager.update_config_from_detection()
            print("[智能路由] 模型管理器已初始化")
        else:
            print("[智能路由] 警告: 使用默认模型配置")
        
        # 缓存判断结果，提高性能
        self.cache = {}
        
        # 预定义简单请求模式（快速判断）
        self.simple_patterns = [
            r'^(hi|hello|hey|你好|嗨)',
            r'^(what.*time|几点了|现在几点|时间)',
            r'^(weather|天气)',
            r'^(remind|提醒)',
            r'^(note|笔记)',
            r'^(list|列出|显示|查看)',
            r'^(search|搜索|查找)',
            r'^(file|文件)',
            r'^(read|读取|打开)',
            r'^(copy|复制)',
            r'^(move|移动)',
            r'^(delete|删除)',
            r'^(rename|重命名)',
            r'^[0-9\+\-\*\/\s]+[=?]$',  # 简单数学计算
            r'^(yes|no|ok|好的|不行|可以)',
            r'^.{1,50}$',  # 非常短的请求
            r'(status|状态|检查)',
            r'(pwd|ls|cd|cat|echo)',
            r'(简单|基础|快速)',
        ]
        
        # 预定义复杂请求模式
        self.complex_patterns = [
            r'(explain|解释)',
            r'(analyze|分析|解析)',
            r'(compare|比较|对比)',
            r'(write|编写|创作).*(code|代码|程序|文章)',
            r'(debug|调试|排错)',
            r'(design|设计|规划)',
            r'(philosophy|哲学|思考)',
            r'(creative|创意|创作)',
            r'(long|长篇|详细)',
            r'(summary|总结|概括)',
            r'(translate|翻译).{20,}',  # 长文本翻译
            r'(how to|如何|怎样).*(step|步骤|流程)',
            r'(复杂|困难|难题)',
            r'(架构|系统|框架)',
            r'(算法|数据结构)',
            r'(机器学习|人工智能|AI)',
            r'(项目|工程|开发)',
            r'(代码|编程|开发)',  # 添加代码相关关键词
            r'(原理|理论|机制)',  # 添加原理相关关键词
        ]
    
    def quick_check(self, prompt: str) -> Optional[str]:
        """快速检查，使用预定义模式"""
        prompt_lower = prompt.lower().strip()
        
        # 检查缓存
        cache_key = f"quick_{hash(prompt_lower)}"
        if cache_key in self.cache:
            return self.cache[cache_key]
        
        # 先检查是否明确复杂（优先级更高）
        for pattern in self.complex_patterns:
            if re.search(pattern, prompt_lower, re.IGNORECASE):
                self.cache[cache_key] = "complex"
                return "complex"
        
        # 再检查是否明确简单
        for pattern in self.simple_patterns:
            if re.match(pattern, prompt_lower, re.IGNORECASE):
                self.cache[cache_key] = "simple"
                return "simple"
        
        # 无法快速判断，需要小模型判断
        return None
    
    def judge_with_model(self, prompt: str) -> str:
        """使用小模型判断复杂度"""
        if not REQUESTS_AVAILABLE:
            # 如果没有requests库，使用扩展的关键词匹配
            return self._fallback_judge(prompt)
        
        try:
            cache_key = f"model_{hash(prompt)}"
            if cache_key in self.cache:
                return self.cache[cache_key]
            
            response = requests.post(
                f"{self.ollama_host}/api/generate",
                json={
                    "model": self.judge_model,
                    "prompt": f"""请判断以下用户请求是简单请求还是复杂请求：

用户请求：{prompt}

简单请求通常包括：问候、简单查询、文件操作、提醒设置、简短回答等。
复杂请求通常包括：代码编写、复杂分析、创意写作、详细解释、逻辑推理等。

请只回答一个字："简单" 或 "复杂"，不要其他任何内容。""",
                    "stream": False,
                    "options": {
                        "temperature": 0.1,
                        "max_tokens": 10
                    }
                },
                timeout=5
            )
            
            if response.status_code == 200:
                result = response.json()["response"].strip()
                if "复杂" in result:
                    self.cache[cache_key] = "complex"
                    return "complex"
                else:
                    self.cache[cache_key] = "simple"
                    return "simple"
        except Exception as e:
            print(f"[智能路由] 小模型判断失败: {e}")
            # 失败时使用备用方案
            return self._fallback_judge(prompt)
        
        # 默认返回简单（保守策略）
        return "simple"
    
    def _fallback_judge(self, prompt: str) -> str:
        """备用判断方案：扩展关键词匹配"""
        prompt_lower = prompt.lower()
        
        # 扩展的复杂关键词
        complex_keywords = [
            '代码', '编程', '开发', '算法', '数据结构',
            '解释', '分析', '解析', '原理', '理论',
            '设计', '架构', '系统', '框架',
            '比较', '对比', '差异',
            '如何', '怎样', '步骤', '流程',
            '机器学习', '人工智能', 'AI', '深度学习',
            '项目', '工程', '应用', '实现'
        ]
        
        # 检查是否包含复杂关键词
        for keyword in complex_keywords:
            if keyword in prompt_lower:
                return "complex"
        
        # 检查长度 - 长文本更可能是复杂请求
        if len(prompt) > 100:
            return "complex"
        
        return "simple"
    
    def route_request(self, prompt: str) -> Dict[str, Any]:
        """路由请求，返回模型选择建议（集成成本优化）"""
        # 先尝试快速检查
        quick_result = self.quick_check(prompt)
        
        if quick_result:
            complexity = quick_result
            method = "pattern"
        else:
            # 使用小模型判断
            complexity = self.judge_with_model(prompt)
            method = "model"
        
        # 根据复杂度和成本优化选择模型
        if MODEL_MANAGER_AVAILABLE:
            # 使用模型管理器进行成本优化选择
            model = model_manager.get_cost_effective_model(complexity)
            
            # 获取模型详细信息
            model_info = model_manager.models.get(model, {})
            model_name = model_info.get("name", model)
            model_type = model_info.get("type", "unknown")
            model_priority = model_info.get("model_priority", "normal")
            
            if complexity == "simple":
                reason = f"简单请求，使用{model_type}模型处理（{model_name}）"
            else:
                reason = f"复杂请求，使用{model_type}模型处理（{model_name}，优先级：{model_priority}）"
            
            cost_weight = model_info.get("cost_weight", 1.0)
            
        else:
            # 回退到默认逻辑
            if complexity == "simple":
                model = "ollama-local/deepseek-r1-7b"
                reason = "简单请求，使用本地模型处理"
                model_type = "local"
                cost_weight = 0.3
            else:
                model = "deepseek/deepseek-chat"
                reason = "复杂请求，使用云端模型处理"
                model_type = "cloud"
                cost_weight = 1.0
        
        return {
            "complexity": complexity,
            "model": model,
            "model_type": model_type,
            "cost_weight": cost_weight,
            "reason": reason,
            "method": method,
            "prompt_length": len(prompt),
            "cost_optimized": MODEL_MANAGER_AVAILABLE
        }
    
    def get_recommended_model(self, prompt: str) -> str:
        """获取推荐的模型"""
        route_info = self.route_request(prompt)
        return route_info["model"]
    
    def get_available_models(self) -> Dict[str, Dict[str, Any]]:
        """获取当前可用的模型配置"""
        if MODEL_MANAGER_AVAILABLE:
            return model_manager.models
        else:
            # 返回默认配置
            return {
                "ollama-local/deepseek-r1-7b": {
                    "enable": True,
                    "type": "local",
                    "name": "DeepSeek R1 7B (本地任务处理)",
                    "model_priority": "normal",
                    "description": "本地中等模型，适合大多数任务",
                    "cost_weight": 0.3
                },
                "deepseek/deepseek-chat": {
                    "enable": True,
                    "type": "cloud",
                    "name": "DeepSeek Chat (云端复杂任务)",
                    "model_priority": "max",
                    "description": "云端大模型，适合复杂任务",
                    "cost_weight": 1.0
                }
            }

# 单例实例
router = SmartRouter()

if __name__ == "__main__":
    # 测试函数
    test_cases = [
        "现在几点了",
        "帮我列出桌面上的文件",
        "提醒我下午3点开会",
        "请解释量子纠缠的基本原理",
        "帮我写一个Flutter的登录页面代码",
        "比较React和Vue的优缺点",
        "2+2等于多少？",
        "请详细分析Android内存泄漏的常见原因和解决方案",
    ]
    
    print("=== 智能路由测试 ===\n")
    for i, prompt in enumerate(test_cases, 1):
        print(f"测试 {i}: {prompt}")
        result = router.route_request(prompt)
        print(f"  复杂度: {result['complexity']} ({result['method']})")
        print(f"  推荐模型: {result['model']}")
        print(f"  理由: {result['reason']}")
        print()

path: smart_router.sh
content: #!/bin/bash
# 智能路由技能Shell包装脚本 v2.0

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PYTHON_SCRIPT="$SCRIPT_DIR/main.py"

# 检查Python脚本是否存在
if [ ! -f "$PYTHON_SCRIPT" ]; then
    echo "错误: 找不到Python脚本 $PYTHON_SCRIPT"
    exit 1
fi

# 检查Python3
if ! command -v python3 &> /dev/null; then
    echo "错误: 需要Python3"
    exit 1
fi

# 执行Python脚本
python3 "$PYTHON_SCRIPT" "$@"

# 返回Python脚本的退出码
exit $?

Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (HIGH)