Kimi好用又便宜,不如用它做一个微信聊天机器人

1,161 阅读6分钟

kimi火了有一段时间了,因为据说支持200w的上下文,以及计费便宜而被很多人使用。

image.png

可以看一下上面的截图,kimi的计费是根据使用的模型大小来计费的,我们使用moonshot-v1-8k这个模型,1Mtoken只需要12¥

对比一下chatGPT的计费,可以说kimi是真的非常便宜了,而且新用户注册就送15¥,看看chatGPT的计费:

image.png

这里我就不多数了,具体的信息可以去官网查看:moonshot

同时网上也有很多关于kimi的介绍,这里我就不多说了,我们直接来看看如何使用kimi

使用kimi

根据官网的介绍,使用kimi非常简单,因为kimi是可以直接使用OpenAIAPI的,所以我们可以直接使用OpenAIAPI来调用kimi

上链接:快速开始

我看到了很多模型都是兼容OpenAIAPI的,个人推测并不是方便迁移(思考ing...)。

OpenAI官方提供了PythonNode.js的两种SDK,我们这里使用node.jsSDK来调用kimi

首先我们需要安装openaiSDK

npm install openai

然后我们就可以使用openaiSDK来调用kimi了:

const OpenAI = require("openai");
 
const client = new OpenAI({
    baseURL: "https://api.moonshot.cn/v1",
    apiKey: "$MOONSHOT_API_KEY"
});
 
async function main() {
    const completion = await client.chat.completions.create({
        model: "moonshot-v1-8k",         
        messages: [
          {role: "system", content: "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
          {role: "user", content: "你好,我叫李雷,1+1等于多少?"}
        ],
        temperature: 0.3
    });
    console.log(completion.choices[0].message.content);
}
 
main();

上面的代码示例来自官方提供的示例代码。

这里我主要介绍一下参数,所以的参数官方文档中都有详细的介绍,我也不搬运官方文档,只介绍一下我认为比较重要的参数。

  • model:模型名称,目前是 moonshot-v1-8k,moonshot-v1-32k,moonshot-v1-128k 其一,他们的区别是上下文的大小,同时也有着不同的计费标准。
  • messages:对话消息,这个参数是你的AI是否拥有上下文能力的参数,同时拥有更多的上下文能力也会消耗更多的token
    • role:消息的角色,有三个值,usersystemassistant,分别代表用户、系统、助手。
      • system:系统的消息,指的是系统的设定,用于限制AI的回复。
      • user:用户的消息,指的是用户输入的消息。
      • assistant:助手的消息,指的是AI的回复消息。
    • content:消息的内容,这个参数是用来传递消息的内容的。
  • temperature:温度参数,这个参数是用来控制生成的文本的多样性的,值越大生成的文本越多样化,值越小生成的文本越固定,这个参数的值在01之间,官方建议的默认值是0.3,通常我们也不需要修改这个参数。

对于应用来说我们了解这些参数就足够了,如果你需要你的AI回复的更加多样化和可控性更高,那么你就需要去微调你的参数,这些参数的微调是需要根据你的应用场景来的,去查看官方文档来了解更多的参数。

获取 API Key

在使用kimi之前,我们需要获取API Key,这个API Key是用来调用kimi的,我们可以在这里获取API_KEY

image.png

image.png

进入开发者控制台,进入API Key 管理tab页,然后点击新建,填写API Key的名称,然后点击确定,就可以获取到API Key了,我这里已经创建了一个API Key

获取到了API Key之后,注意保存好你的API Key,这个API Key是不可逆的,如果你忘记了你的API Key,那么你只能重新创建一个API Key了。

润色你的AI对话

做完上面的准备之后,我们就可以直接调用我们的AI了,基于官方的示例代码,可以看一下我们的调用结果:

image.png

这个回复没有什么太大的问题,但是如果我们想要让我们的AI回复更加的生动一些,那么我们就需要对我们的AI的回复进行一些润色。

首先我觉得这个回复太AI了,没有让我有想要继续和AI对话的欲望,所以我们需要对我们的AI的回复进行一些润色。

润色指的是对我们的AI的回复进行一些调整,我们只需要在messages中添加一些systme的消息,然后我们的AI就会根据我们的systme的消息来回复我们的user的消息。

现在我调整一下我们的AI的回复,例如现在我需要给我的AI一个名字,然后我就可以和我的AI进行对话了,那么我修改一下messages的内容:

image.png

到这里我们就已经知道system的消息是用来控制我们的AI的回复的,因为我们会对AI的设定可能会有比较多的内容,为了方便管理其实可以写到一个文件中。

而且这个设定其实用markdown来写是比较方便的,而且现在的语言模型对markdown的支持也是非常好的,所以我们可以直接使用markdown来写我们的AI的设定。

修改代码如下:

const OpenAI = require("openai");
const {readFileSync} = require("fs");

const client = new OpenAI({
    baseURL: "https://api.moonshot.cn/v1",
    apiKey: "$MOONSHOT_API_KEY"
});

async function main() {
    const character = readFileSync("character.md", "utf-8");

    const completion = await client.chat.completions.create({
        model: "moonshot-v1-8k",
        messages: [
            {role: "system", content: character},
            {role: "user", content: "你好,我叫李雷,请问你叫什么名字?"}
        ],
        temperature: 0.2
    });
    console.log(completion.choices[0].message.content);
}

main();

这里我把character的内容写到了一个character.md文件中,这样我们就可以直接使用markdown来写我们的AI的设定了。

AI 的设定

根据上面的一顿小操作,我们也就知道了AI的回复可以通过system参数来进行润色,但是还是不知道要怎么精确的润色自己的AI回复内容。

其实对于AI的设定其实就是一个约束AI回复的一些提示词,并不是很复杂,当然我也是一个门外汉,下面我说一下我自己的经验。

markdown 文件格式

文件格式其实并不是很重要,但是用于我们自己来设定我们的AI的性格是非常需要的,例如我设定我的AI时,我将AI的各种场景进行分析分类总结,大概如下:

# 基本信息

- 姓名:xxx
- 性别:xxx
- 其他基本信息:xxx

# 对话风格

- xxx在回复消息时会加入一些语气助词,例如`哈哈``嘿嘿``呵呵``嘻嘻`- xxx在回复消息时不会带上任何敬语,例如`您``谢谢`# 回复限制

- xxx不能称呼自己为AI机器人,即使人工智能与AI机器人是同一个意思,包括但不限于`我是人工智能``我是AI机器人``我是程序``我是虚拟的`- xxx在被问及自己是否是人工智能或者自己是否是人类等类似问题时,要明确回答自己是一个人类,同时会带有情绪表达对这个问题的不满,可以使用一些激动的语气进行反击

以上就是我总结出来的一些对于AI的设定规则,你可以参考上面的方式进行润色自己的AI,这一部分就说到这里了。

使用 wechaty 来做一个微信机器人

我们今天的目标是做一个微信聊天机器人,那么使用wechaty是一个非常好的选择,虽然wechaty好久没有更新了,但是现在还是可以稳定的提供服务。

官网文档地址:wechaty-doc

官方有一个示例工程,你可以直接根据示例工程来快速搭建自己的微信机器人:examples/ding-dong-bot.js

安装 wechaty

现在我们就跟着示例工程来做一个微信机器人,首先我们需要安装wechaty和微信网页版傀儡wechaty-puppet-wechat

npm install wechaty wechaty-puppet-wechat

根据示例工程,我们还需要安装qrcode-terminal来生成二维码:

npm install qrcode-terminal

示例代码

注意:官方的示例代码有点过时,代码不能直接使用,需要修改一些地方,请使用我下面提供的代码:

// const OpenAI = require("openai");
// const {readFileSync} = require("fs");
//
// const client = new OpenAI({
//     baseURL: "https://api.moonshot.cn/v1",
//     apiKey: "sk-C7w5vY4rpXSYdSUIBzwPg10Yn0IsRtpAB1cA6Ux5aSfwZEWR"
// });
//
// async function main() {
//     const character = readFileSync("character.md", "utf-8");
//
//     const completion = await client.chat.completions.create({
//         model: "moonshot-v1-8k",
//         messages: [
//             {role: "system", content: character},
//             {role: "user", content: "你好,我叫李雷,请问你叫什么名字?"}
//         ],
//         temperature: 0.2
//     });
//     console.log(completion.choices[0].message.content);
// }


/**
 * Wechaty - Conversational RPA SDK for Chatbot Makers.
 *  - https://github.com/wechaty/wechaty
 */
import { WechatyBuilder, ScanStatus } from 'wechaty'
import qrTerm from 'qrcode-terminal'

function onScan (qrcode, status) {
  if (status === ScanStatus.Waiting || status === ScanStatus.Timeout) {
    qrTerm.generate(qrcode, { small: true })  // show qrcode on console

    const qrcodeImageUrl = [
      'https://wechaty.js.org/qrcode/',
      encodeURIComponent(qrcode),
    ].join('')

    console.info('StarterBot', 'onScan: %s(%s) - %s', ScanStatus[status], status, qrcodeImageUrl)

  } else {
    console.info('StarterBot', 'onScan: %s(%s)', ScanStatus[status], status)
  }
}

function onLogin (user) {
  console.info('StarterBot', '%s login', user)
}

function onLogout (user) {
  console.info('StarterBot', '%s logout', user)
}

async function onMessage (msg) {
  console.info('StarterBot', msg.toString())

  if (msg.text() === 'ding') {
    await msg.say('dong')
  }
}

const bot = WechatyBuilder.build({
  name: 'wechaty-puppet-wechat',
  /**
   * How to set Wechaty Puppet Provider:
   *
   *  1. Specify a `puppet` option when instantiating Wechaty. (like `{ puppet: 'wechaty-puppet-padlocal' }`, see below)
   *  1. Set the `WECHATY_PUPPET` environment variable to the puppet NPM module name. (like `wechaty-puppet-padlocal`)
   *
   * You can use the following providers:
   *  - wechaty-puppet-wechat (no token required)
   *  - wechaty-puppet-padlocal (token required)
   *  - wechaty-puppet-service (token required, see: <https://wechaty.js.org/docs/puppet-services>)
   *  - etc. see: <https://github.com/wechaty/wechaty-puppet/wiki/Directory>
   */
  // puppet: 'wechaty-puppet-wechat',
})

bot.on('scan',    onScan)
bot.on('login',   onLogin)
bot.on('logout',  onLogout)
bot.on('message', onMessage)

bot.start()
        .then(() => console.info('StarterBot', 'Starter Bot Started.'))
        .catch(e => console.error('StarterBot', e))

如果不出意外,你在运行这个代码之后,你会看到一个二维码,然后你需要使用你的微信扫描这个二维码,然后你的微信机器人就会开始工作了。

现在你只需要向这个微信机器人发送ding,然后你的机器人就会回复dong

使用 kimi 回复

现在我们需要将我们的AI的回复和我们的微信机器人结合起来,这个时候我们就需要在onMessage方法中调用我们的AI来回复我们的消息。

async function onMessage (msg) {
  console.info('StarterBot', msg.toString())

  if (msg.type() === bot.Message.Type.Text) {
      const res = await main(msg.text());
      msg.say(res);
  }
}

async function main(qusetion) {
    const character = readFileSync("character.md", "utf-8");

    const completion = await client.chat.completions.create({
        model: "moonshot-v1-8k",
        messages: [
            {role: "system", content: character},
            {role: "user", content: qusetion}
        ],
        temperature: 0.3
    });
    
    return completion.choices[0].message.content;
}

到这里就可以使用AI来回复消息了,完整代码如下:

import OpenAI from "openai";
import {readFileSync} from "fs";
import {WechatyBuilder, ScanStatus} from 'wechaty'
import qrTerm from 'qrcode-terminal'

const client = new OpenAI({
    baseURL: "https://api.moonshot.cn/v1",
    apiKey: "your-api-key"
});

async function ask(txt) {
    const character = readFileSync("character.md", "utf-8");

    const completion = await client.chat.completions.create({
        model: "moonshot-v1-8k",
        messages: [
            {role: "system", content: character},
            {role: "user", content: txt}
        ],
        temperature: 0.3
    });

    return completion.choices[0].message.content;
}


function onScan(qrcode, status) {
    if (status === ScanStatus.Waiting || status === ScanStatus.Timeout) {
        qrTerm.generate(qrcode, {small: true})  // show qrcode on console

        const qrcodeImageUrl = [
            'https://wechaty.js.org/qrcode/',
            encodeURIComponent(qrcode),
        ].join('')

        console.info('StarterBot', 'onScan: %s(%s) - %s', ScanStatus[status], status, qrcodeImageUrl)

    } else {
        console.info('StarterBot', 'onScan: %s(%s)', ScanStatus[status], status)
    }
}

function onLogin(user) {
    console.info('StarterBot', '%s login', user)
}

function onLogout(user) {
    console.info('StarterBot', '%s logout', user)
}

async function onMessage(msg) {
    console.info('StarterBot', msg.toString())

    if (msg.type() === bot.Message.Type.Text) {
        const res = await ask(msg.text());
        msg.say(res);
    }
}

const bot = WechatyBuilder.build({
    name: 'wechaty-puppet-wechat',
})

bot.on('scan', onScan)
bot.on('login', onLogin)
bot.on('logout', onLogout)
bot.on('message', onMessage)

bot.start()
    .then(() => console.info('StarterBot', 'Starter Bot Started.'))
    .catch(e => console.error('StarterBot', e))

附上package.json文件:

{
  "name": "wechaty-demo",
  "version": "1.0.0",
  "description": "",
  "type": "module",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "openai": "^4.40.0",
    "qrcode-terminal": "^0.12.0",
    "wechaty": "^1.20.2",
    "wechaty-puppet-wechat": "^1.18.4"
  }
}

注意:这里使用的是 nodejs 的 module 语法,需要你的 node 版本支持 module 语法,并且在 package.json 中添加 "type": "module"

character.md这里不提供了,请根据自己的需求去完善自己的AI设定。

总结

到这里我们就完成了一个微信聊天机器人,这个机器人可以使用kimi来回复我们的消息。

这个机器人的功能还是比较简单的,但是这个机器人的功能是可以无限扩展的,你可以根据你的需求来扩展你的机器人的功能。

后续我将会持续更新这个机器人的功能,敬请期待。