OpenClaw技能开发入门:千问3.5-9B定制天气查询

1. 为什么需要自定义技能?

去年冬天,我经常需要同时查看多个城市的天气情况来安排出差行程。每次手动打开天气网站、输入城市名、截图保存的操作让我不胜其烦。直到发现OpenClaw支持自定义技能开发,我决定用千问3.5-9B模型为它打造一个专属天气查询技能。

这个案例特别适合作为技能开发入门项目:一方面天气API接口规范清晰,另一方面结果格式化需求明确。更重要的是,通过这个项目可以掌握OpenClaw技能开发的三大核心环节:API封装、意图映射和结果呈现。

2. 开发环境准备

2.1 基础环境配置

我的开发环境是macOS Monterey 12.6,已经通过Homebrew安装了Node.js 18.x。建议先运行以下命令检查基础环境:

node -v  # 需v16+
npm -v   # 需8+
openclaw --version  # 需0.8.0+

如果尚未安装OpenClaw,可以通过官方脚本快速安装:

curl -fsSL https://openclaw.ai/install.sh | bash

2.2 创建技能脚手架

OpenClaw提供了标准的技能开发模板。在终端执行:

mkdir weather-skill && cd weather-skill
npx @openclaw/create-skill

这个交互式向导会生成以下核心文件:

  • skill.json:技能元数据声明文件
  • src/api.js:API封装模块
  • src/intent.js:自然语言意图处理器
  • src/formatter.js:结果格式化模块

3. 实现天气API封装层

3.1 选择天气数据源

经过对比,我选择了和风天气的免费API。注册开发者账号后,可以获得基础版的天气查询接口,每天1000次调用完全够个人使用。

api.js中封装获取天气的核心逻辑:

const axios = require('axios');

class WeatherAPI {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = 'https://devapi.qweather.com/v7/weather';
  }

  async getCurrentWeather(location) {
    try {
      const response = await axios.get(`${this.baseUrl}/now`, {
        params: {
          location,
          key: this.apiKey
        }
      });
      return response.data;
    } catch (error) {
      console.error('天气API调用失败:', error);
      throw new Error('获取天气信息时发生错误');
    }
  }
}

module.exports = WeatherAPI;

3.2 处理API密钥安全

千万不要将API密钥硬编码在代码中!我选择通过OpenClaw的环境变量管理功能来注入密钥。在技能目录下创建.env文件:

WEATHER_API_KEY=你的和风天气API密钥

然后在skill.json中声明需要注入的环境变量:

{
  "env": ["WEATHER_API_KEY"]
}

4. 设计自然语言交互逻辑

4.1 定义意图识别规则

intent.js中,我们需要教会OpenClaw如何理解用户的天气查询请求。千问3.5-9B模型已经具备基础的自然语言理解能力,我们只需要提供明确的意图匹配规则:

module.exports = {
  match: async (text, context) => {
    const weatherKeywords = ['天气', '气温', '温度', '气象'];
    const hasWeatherIntent = weatherKeywords.some(keyword => 
      text.includes(keyword)
    );
    
    return hasWeatherIntent ? { confidence: 0.9 } : null;
  },

  extract: async (text, context) => {
    // 使用千问模型提取城市名称
    const response = await context.models.qwen.generate({
      prompt: `从以下文本中提取城市名称,只需回答城市名:"${text}"`,
      max_tokens: 10
    });
    
    return {
      location: response.trim()
    };
  }
};

4.2 处理模糊查询

实际使用中,用户可能会说"北京明天天气怎么样"这样的模糊查询。我在代码中添加了时间处理逻辑:

// 在extract方法中添加
const timeResponse = await context.models.qwen.generate({
  prompt: `判断以下文本是否包含时间信息,只需回答是或否:"${text}"`,
  max_tokens: 2
});

if (timeResponse.trim() === '是') {
  params.forecast = '24h'; // 切换到天气预报接口
}

5. 美化天气信息展示

5.1 设计输出模板

formatter.js中,我创建了多种天气展示模板。根据不同的查询条件,返回最适合的展示方式:

function formatCurrentWeather(data) {
  const weather = data.now;
  return `
🌤️ *${data.location.name}当前天气*
--------------------
🌡️ 温度:${weather.temp}℃ (体感${weather.feelsLike}℃)
💧 湿度:${weather.humidity}%
🌬️ 风力:${weather.windDir} ${weather.windScale}级
☁️ 天气状况:${weather.text}
`;
}

5.2 添加可视化元素

为了让天气信息更直观,我整合了天气图标和预警信息。当出现极端天气时,会自动添加警告标志:

if (weather.category === '暴雨') {
  template += '\n⚠️ *暴雨红色预警* 请避免外出!';
}

6. 测试与调试技能

6.1 本地测试方法

OpenClaw提供了便捷的本地测试工具。在技能目录下运行:

openclaw skill test

这会启动一个交互式测试环境,可以输入各种天气查询语句验证技能响应。

6.2 常见问题排查

在开发过程中,我遇到了几个典型问题:

  1. API限流问题:添加了请求缓存逻辑,相同城市5分钟内不重复查询
  2. 城市名歧义:当模型无法确定城市时,会主动询问用户"您是指北京市还是北京县?"
  3. 空结果处理:对API返回的空结果添加了友好的错误提示

7. 发布到ClawHub社区

7.1 准备发布包

首先确保skill.json中的元数据完整:

{
  "name": "weather-skill",
  "version": "1.0.0",
  "description": "基于和风天气API的智能查询技能",
  "author": "你的名字",
  "keywords": ["weather", "qwen", "forecast"]
}

然后运行打包命令:

clawhub pack

这会生成一个weather-skill.claw的发布包。

7.2 发布到社区

注册ClawHub账号后,执行发布命令:

clawhub publish --token 你的发布令牌

发布成功后,其他用户就可以通过以下方式安装你的技能:

clawhub install weather-skill

8. 技能的实际应用效果

现在,我可以通过自然语言随时查询天气了。例如在OpenClaw控制台输入:

"上海今天会下雨吗?"

系统会返回格式化的天气信息,包括温度、湿度、降水概率等关键数据。更棒的是,这个技能会自动记住我常查的几个城市,后续查询只需要说"杭州天气"就能快速获取信息。

通过千问3.5-9B的语义理解能力,技能还能处理一些特殊查询,比如:

  • "哪个城市更热,北京还是广州?"
  • "周末适合去三亚玩吗?"

整个开发过程让我深刻体会到OpenClaw技能生态的灵活性。相比从头开发一个天气应用,这种基于现有API和AI模型的技能开发方式效率提升了至少10倍。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐