Contents

Docker部署kimi-free-api

简介

🚀 KIMI AI 长文本大模型逆向API【特长:长文本解读整理】,支持高速流式输出、智能体对话、联网搜索、探索版、K1思考模型、长文档解读、图像解析、多轮对话,零配置部署,多路token支持,自动清理会话痕迹,仅供测试,如需商用请前往官方开放平台。 GitHub项目页面

Docker部署

docker run -it -d --init \
--name kimi \
-p 7086:8000 \
-e TZ=Asia/Shanghai \
--restart=unless-stopped \
vinlic/kimi-free-api:latest

之后可访问http://localhost:7086进行测试

获取KIMI refresh_token

从 kimi.moonshot.cn  获取refresh_token

进入kimi随便发起一个对话,然后F12打开开发者工具,从Application应用 > Local Storage本地存储空间中找到refresh_token的值,这将作为Authorization的Bearer Token值:Authorization: Bearer TOKEN

如果你看到的refresh_token是一个数组,请使用.拼接起来再使用。

目前kimi限制普通账号每3小时内只能进行30轮长文本的问答(短文本不限),你可以通过提供多个账号的refresh_token并使用,拼接提供:

Authorization: Bearer TOKEN1,TOKEN2,TOKEN3

每次请求服务会从中挑选一个。

代码开发

代码用法示例,其他用法详见官方文档,很详细。

const axios = require('axios');
// 替换为你的refresh_token,获取方法见GitHub页面说明
const REFRESH_TOKEN = "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ1c2VyLWNlbnRlciIsImV4cCI6MTc1MDU2MTg4NywiaWF0IjoxNzQyNzg1ODg3LCJqdGkiOiJjdmdjcW5ydWEzZDVsb3RsM2U4ZyIsInR5cCI6InJlZnJlc2giLCJhcHBfaWQiOiJraW1pIiwic3ViIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANzAiLCJzcGFjZV9pZCI6ImNtcWkxdDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl9pZCI6ImNtcWkxdDAzcjA3Y2pzbGs1djYwIiwicm9sZXMiOlsidmlkZW9fZ2VuX2FjY2VzcyJdfQ.Yw07vOZfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA48w3llR4BAvtpGmqh-_WOJ6NPC70Gj76vc5A";
const API_URL = "https://kimi.xxxxxx.wang/v1/chat/completions"; // 如果是本地部署,使用localhost:8000;如果是远程部署,替换为实际的API地址
var CONVERSATION_ID = "none";//会话ID,开启新会话为none
  
/**
 *
 * @param {string} content 会话正文
 * @param {string} conversation_id 会话ID,可实现多轮上下文会话
 * @returns Object,id属性为会话id,msg属性为AI答复内容
 */
async function askAI(content, conversation_id = "none") {
  try {
    // 请求头
    const headers = {
      "Authorization": `Bearer ${REFRESH_TOKEN}`,
      "Content-Type": "application/json"
    };

    // 请求体
    const requestBody = {
      model: "kimi", // 使用默认模型
      conversation_id: conversation_id, // 如果是第一轮对话,不传conversation_id
      messages: [
        {
          role: "user",
          content: content
        }
      ],
      use_search: true, // 根据需求开启联网搜索
      stream: false // 不使用流式输出
    };

    // 发送POST请求
    const response = await axios.post(API_URL, requestBody, { headers });
    // 提取响应中的输出文本
    //console.log("API响应:");
    //console.log(response.data);
    //console.log(response.data.choices[0].message);
    //AI回答正文
    let outputText = response.data.choices[0].message.content;
    //移除引用
    if(outputText.split("\n搜索结果来自:\n")[0]){
      outputText=outputText.split("\n搜索结果来自:\n")[0];
    }

    return {
      id: response.data.id,
      msg: outputText
    };
  } catch (error) {
    console.error("POST到API时发生错误:", error.message);
    throw error; // 抛出错误以便调用者处理
  }
} 
  
  
/**
 * 发送推送消息到ntfy服务
 * @param {string} topic - 消息的主题(必填)
 * @param {string} message - 要发送的消息内容(必填)
 * @param {string} title - 消息的大标题(默认不使用大标题)
 * @param {int} [priority=3] - 消息的优先级(默认是3),可以是1-5的整数,分别是最小、小、默认、大、最大
 * @param {array} [tags] - 消息的标签,字符串数组(默认无)
 * @param {array} [attach] - 附件、图片URL(默认无)
 * @param {array} [click] - 消息被点击时跳转的url(默认无)
 * @param {string} [serverUrl='https://ntfy.sh'] - ntfy服务的URL,默认为官方服务器
 */
async function sendNtfyMessage(topic, message, title = null, priority = 3, tags = null, attach = null, click = null, serverUrl = 'https://ntfy.sh') {
    try {
        if (topic == null || message == null || priority > 5 || priority < 1) {
            console.error("topic、message不能为空,priority的值只能取1、2、3、4、5!");
        }

        // 构建请求的headers
        const headers = new Headers({
            'Content-Type': 'application/json',
        });

        // 创建消息Object
        const payload = { topic, message, priority };
        if (title) payload.title = title;
        if (tags) payload.tags = tags;
        if (attach) payload.attach = attach;
        if (click) payload.click = click;

        // 构建请求的body
        const body = JSON.stringify(payload);
        //console.log('拟发出的消息body:', body);
  
        // 发送POST请求到ntfy服务
        const response = await fetch(serverUrl, { method: 'POST', headers: headers, body: body });

        // 检查响应状态
        if (!response.ok) {
            throw new Error(`HTTP 错误! 状态: ${response.status}`);
        }

        // 获取响应数据
        const data = await response.json();
        //console.log('消息发送成功:\n', data);
    } catch (error) {
        console.error('消息发送失败:\n', error);
    }
}
/**
 * 把一个md格式的字符串转换成emoji的字符串
 */
function md_to_txt(string) {
    // 删除引用(假设引用是用 `>` 开头的行)
    string = string.replace(/^>.*\n?/gm, '');
    // 将 ### 替换为 🔶
    string = string.replace(/^####\s*/gm, '🔸 ');
    string = string.replace(/^###\s*/gm, '🔶 ');
    // 删除 Markdown 中的标题格式(如 #、## 等,但保留换行)
    string = string.replace(/^#{1,2}\s*/gm, '');
    // 删除 Markdown 中的加粗、斜体、下划线、删除线等格式
    string = string.replace(/\*\*|\*|__|_|~~/g, '');
    // 删除 Markdown 中的链接格式 [text](url)
    string = string.replace(/\[.*?\]\(.*?\)/g, '');
    // 保留无序列表符号,但将其替换为普通文本
    string = string.replace(/^\s*[-*+]\s/gm, '- ');
    // 保留有序列表符号
    string = string.replace(/^\s*(\d+\.)\s/gm, '$1 ');
    // 删除引用角标
    string = string.replace(/\[\^[^\]]+\^]/g, '');
    // 删除多余的空格(但保留换行和缩进)
    //string = string.replace(/\s+/g, ' ').trim();

    return string;
}
  

// 调用
(async () => {
  try {
    const result = await askAI("分析一下当前国内上海金价格,较上日变化,近期走势(包含影响金价走势的原因)。预测一下后续黄金价格是涨还是跌。给出投资建议。");
    let msg = result.msg;
    CONVERSATION_ID = result.id;
    //console.log(`AI回答: ${msg}\nc_id:${CONVERSATION_ID}`);
    sendNtfyMessage("hotine",md_to_txt(msg),"金价分析",3,["💰"]);
  } catch (error) {
    console.error("Error in askAI:", error);
  }
})();