跳转到内容

DeepSeek 与 WPS 联动

时光2025/8/310 0 m

提示

本教程实现 WPS 内嵌 DeepSeek,实现办公与 AI 联动,大幅提高效率。

注意

安装环境:

  • 系统:银河麒麟 V10SP1 2023(arm),理论上应该通用,包括 UOS。
  • WPS 版本号:19831(点我可下载 Arm 版本) ,也可到WPS365 官网自行下载。这里需要特别注意,已测试 15283,12219 版本不可用,也是踩了几个坑,本以为 linux 上 WPS 的 VBA 版本可能不完善,最后抱着试试看的想法安装了官网最新版,居然可用!喜大普奔!

准备工作:申请 API

近期,各大 AI 运营商均部署了 DeepSeek 模型,并在其网站后台提供了 API 密钥,当前大部分运营商的 API 可以免费申请,小编提供了目前 4 个可以免费部署的服务商供大家选择。用户可以将获取的 API 密钥复制并替换到相应的代码中以接入这些服务。这里以腾讯云为例进行说明,因为在我的测试中,它的响应速度较快。当然,你也可以根据实际需求和不同平台的表现进行相应调整。

1.注册并登录控制台

bash
https://console.cloud.tencent.com/lkeap
bash
https://cloud.siliconflow.cn
bash
https://platform.deepseek.com/usage
bash
https://cloud.baidu.com

2.开通大模型知识引擎服务

点击开通大模型知识引擎

ktzsyq

点击大模型知识引擎下面的立即使用

dmxzsyq

3.复制并保存 API-Key

点击侧边栏的 API-Key,再点击创建API KEY按钮,保存 API KEY 备用

dmxzsyq

配置宏代码

1.打开 WPS

新建一个文本文档,文档的格式没有要求,doc、docx 或者 wps 格式的均可,因为都适合用 VBA 处理。

点击菜单栏中的工具选项卡中的开发工具

djkfgj

再点击 WPS 宏编辑器(VBA)

djwpsh

2.配置宏代码

右键点击 Project(Normal.dotm)(这是 Word 的全局模板,适用于所有新建的文档)。需要注意的是,不要右键点击你当前正在编辑的新建文档或任何特定文档的项目,因为我们的目标是让新模块对所有文档生效。

d_crmk

将下面的代码复制到右边的代码编辑器(已折叠,点击显示)

点击查看代码
javascript
// DeepSeek与WPS联动教程:https://kylin.cxcare.top,使用技巧-DeepSeek与WPS联动
// API参数配置三项
// API key,请替换成你的API key
const OPENAI_API_KEY = "sk-*******************";

/* 以下为更换AI运营商中需要替换的区域 */
// 接口地址,这里填的是腾讯云的api地址,如果用其他的,请修改
const OPENAI_API_URL =
  "https://api.lkeap.cloud.tencent.com/v1/chat/completions";
// 调用模型名称,这里调用的是R1,如果用其他的,请修改
const OPENAI_MODEL = "deepseek-r1";
/* 以上为更换AI运营商中需要替换的区域 */

// 提示词模板
function PROMPT_TEMPLATE(text, requirements) {
  return `你是一位擅长文案写作的助手。请根据以下要求处理文本:
  	1. 保持原文的核心意思不变
  	2. 如果原文有要求要结合一下要求
${requirements}

请处理以下文本:
${text}`;
}

function expandText() {
  const selection = Application.Selection;

  // 检查是否有选中文本
  console.log("开始执行宏,检查选中文本...");
  if (!selection || !selection.Text) {
    console.log("未检测到选中文本");
    alert("请选择需要扩写的文本");
    return;
  }

  const originalText = selection.Text;
  console.log("检测到选中文本:", originalText);

  // 获取用户输入的要求
  const requirements = InputBox("请输入写作的具体要求:", "写作要求");
  if (requirements === null || requirements.trim() === "") {
    console.log("用户取消了输入或未输入任何要求");
    alert("请提供写作的具体要求");
    return;
  }

  try {
    // 显示加载提示
    alert("AI创作文本需要等待一段时间,单击确定后开始运行");

    // 调用OpenAI API
    console.log("开始调用OpenAI API...");
    callOpenAI(originalText, requirements)
      .then((response) => {
        // 检查API响应是否有效
        if (!response || typeof response !== "string") {
          throw new Error("API返回无效的响应");
        }

        console.log("成功获取API响应:", response);
        // 将生成的文本插入到选中文本的下方
        insertTextBelowSelection(selection, "\n" + response.trim());
        console.log("文本插入完成");
      })
      .catch((error) => {
        // 恢复原文本
        selection.Text = originalText;
        throw error;
      })
      .finally(() => {
        console.log("完成");
      });
  } catch (error) {
    console.error("扩写失败:", error);
    // 显示错误信息
    alert("扩写失败:" + error.message);
  }
}

function callOpenAI(text, requirements) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    const url = OPENAI_API_URL;

    xhr.open("POST", url, true);
    xhr.setRequestHeader("Content-Type", "application/json");
    xhr.setRequestHeader("Authorization", `Bearer ${OPENAI_API_KEY}`);

    xhr.onreadystatechange = function () {
      console.log("XHR状态变化:", xhr.readyState);
      if (xhr.readyState === 4) {
        console.log("API请求完成,状态码:", xhr.status);
        try {
          console.log(
            "HTTP请求报文:",
            JSON.stringify({
              url: url,
              method: "POST",
              headers: {
                "Content-Type": "application/json",
                Authorization: `Bearer ${OPENAI_API_KEY}`,
              },
              body: JSON.stringify(data),
            })
          );
          console.log("API响应原始数据:", xhr.responseText);
          const json = JSON.parse(xhr.responseText);
          if (
            !json.choices ||
            !json.choices[0] ||
            !json.choices[0].message ||
            !json.choices[0].message.content
          ) {
            console.error("API返回无效的数据结构");
            reject(new Error("API返回无效的数据结构"));
          } else {
            console.log("成功解析API响应");
            console.log("完整扩写结果:", json.choices[0].message.content);
            resolve(json.choices[0].message.content.trim());
          }
        } catch (error) {
          console.error("解析API响应失败:", error);
          reject(new Error("解析API响应失败"));
        }
      }
    };

    const data = {
      model: OPENAI_MODEL,
      messages: [
        {
          role: "user",
          content: PROMPT_TEMPLATE(text, requirements),
        },
      ],
      temperature: 1.5,
    };

    xhr.send(JSON.stringify(data));
  });
}

function insertTextBelowSelection(selection, textToInsert) {
  // 移动光标到选中文本的结尾
  selection.Collapse(false);
  // 插入新文本
  selection.InsertAfter(textToInsert);
}
javascript
// DeepSeek与WPS联动教程:https://kylin.cxcare.top,使用技巧-DeepSeek与WPS联动
// API参数配置三项
// API key,请替换成你的API key
const OPENAI_API_KEY2 = "sk-****************";

/* 以下为更换AI运营商中需要替换的区域 */
// 接口地址,这里填的是腾讯云的api地址,如果用其他的,请修改
const OPENAI_API_URL2 =
  "https://api.lkeap.cloud.tencent.com/v1/chat/completions";
// 调用模型名称,这里调用的是R1,如果用其他的,请修改
const OPENAI_MODEL2 = "deepseek-r1";
/* 以上为更换AI运营商中需要替换的区域 */

// 提示词模板
function PROMPT_TEMPLATE(text) {
  return `你是一位擅长文案写作的助手。请根据以下要求处理文本:
  	1. 保持原文的核心意思不变
  	2. 从专业的角度对原文进行润色
请处理以下文本:
${text}`;
}

function expandText2() {
  const selection = Application.Selection;

  // 检查是否有选中文本
  console.log("开始执行宏,检查选中文本...");
  if (!selection || !selection.Text) {
    console.log("未检测到选中文本");
    alert("请选择需要处理的文本");
    return;
  }

  const originalText = selection.Text;
  console.log("检测到选中文本:", originalText);

  try {
    // 显示加载提示
    alert("AI创作文本需要等待一段时间,单击确定后开始运行");
    // 调用OpenAI API
    console.log("开始调用OpenAI API...");
    callOpenAI(originalText)
      .then((response) => {
        // 检查API响应是否有效
        if (!response || typeof response !== "string") {
          throw new Error("API返回无效的响应");
        }

        console.log("成功获取API响应:", response);
        // 将生成的文本插入到选中文本的下方
        insertTextBelowSelection(selection, "\n" + response.trim());
        console.log("文本插入完成");
      })
      .catch((error) => {
        // 恢复原文本
        selection.Text = originalText;
        throw error;
      })
      .finally(() => {
        console.log("完成");
      });
  } catch (error) {
    console.error("处理失败:", error);
    // 显示错误信息
    alert("处理失败:" + error.message);
  }
}

function callOpenAI(text) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    const url = OPENAI_API_URL;

    xhr.open("POST", url, true);
    xhr.setRequestHeader("Content-Type", "application/json");
    xhr.setRequestHeader("Authorization", `Bearer ${OPENAI_API_KEY}`);

    xhr.onreadystatechange = function () {
      console.log("XHR状态变化:", xhr.readyState);
      if (xhr.readyState === 4) {
        console.log("API请求完成,状态码:", xhr.status);
        try {
          console.log(
            "HTTP请求报文:",
            JSON.stringify({
              url: url,
              method: "POST",
              headers: {
                "Content-Type": "application/json",
                Authorization: `Bearer ${OPENAI_API_KEY}`,
              },
              body: JSON.stringify(data),
            })
          );
          console.log("API响应原始数据:", xhr.responseText);
          const json = JSON.parse(xhr.responseText);
          if (
            !json.choices ||
            !json.choices[0] ||
            !json.choices[0].message ||
            !json.choices[0].message.content
          ) {
            console.error("API返回无效的数据结构");
            reject(new Error("API返回无效的数据结构"));
          } else {
            console.log("成功解析API响应");
            console.log("完整扩写结果:", json.choices[0].message.content);
            resolve(json.choices[0].message.content.trim());
          }
        } catch (error) {
          console.error("解析API响应失败:", error);
          reject(new Error("解析API响应失败"));
        }
      }
    };

    const data = {
      model: OPENAI_MODEL,
      messages: [
        {
          role: "user",
          content: PROMPT_TEMPLATE(text),
        },
      ],
      temperature: 1.5,
    };

    xhr.send(JSON.stringify(data));
  });
}

function insertTextBelowSelection(selection, textToInsert) {
  // 移动光标到选中文本的结尾
  selection.Collapse(false);
  // 插入新文本
  selection.InsertAfter(textToInsert);
}
javascript
// DeepSeek与WPS联动教程:https://kylin.cxcare.top,使用技巧-DeepSeek与WPS联动
// API参数配置三项
// API key,请替换成你的API key
const OPENAI_API_KEY3 = "sk-****************";

/* 以下为更换AI运营商中需要替换的区域 */
// 接口地址,这里填的是腾讯云的api地址,如果用其他的,请修改
const OPENAI_API_URL3 =
  "https://api.lkeap.cloud.tencent.com/v1/chat/completions";
// 调用模型名称,这里调用的是R1,如果用其他的,请修改
const OPENAI_MODEL3 = "deepseek-r1";
/* 以上为更换AI运营商中需要替换的区域 */

// 提示词模板
function PROMPT_TEMPLATE(text) {
  return `你是一位擅长文案写作的助手。请根据以下要求处理文本:
  	1. 保持原文的核心意思不变
  	2. 从专业的角度对原文进行扩写
请处理以下文本:
${text}`;
}

function expandText3() {
  const selection = Application.Selection;

  // 检查是否有选中文本
  console.log("开始执行宏,检查选中文本...");
  if (!selection || !selection.Text) {
    console.log("未检测到选中文本");
    alert("请选择需要处理的文本");
    return;
  }

  const originalText = selection.Text;
  console.log("检测到选中文本:", originalText);

  try {
    // 显示加载提示
    alert("AI创作文本需要等待一段时间,单击确定后开始运行");
    // 调用OpenAI API
    console.log("开始调用OpenAI API...");
    callOpenAI(originalText)
      .then((response) => {
        // 检查API响应是否有效
        if (!response || typeof response !== "string") {
          throw new Error("API返回无效的响应");
        }

        console.log("成功获取API响应:", response);
        // 将生成的文本插入到选中文本的下方
        insertTextBelowSelection(selection, "\n" + response.trim());
        console.log("文本插入完成");
      })
      .catch((error) => {
        // 恢复原文本
        selection.Text = originalText;
        throw error;
      })
      .finally(() => {
        console.log("完成");
      });
  } catch (error) {
    console.error("处理失败:", error);
    // 显示错误信息
    alert("处理失败:" + error.message);
  }
}

function callOpenAI(text) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    const url = OPENAI_API_URL;

    xhr.open("POST", url, true);
    xhr.setRequestHeader("Content-Type", "application/json");
    xhr.setRequestHeader("Authorization", `Bearer ${OPENAI_API_KEY}`);

    xhr.onreadystatechange = function () {
      console.log("XHR状态变化:", xhr.readyState);
      if (xhr.readyState === 4) {
        console.log("API请求完成,状态码:", xhr.status);
        try {
          console.log(
            "HTTP请求报文:",
            JSON.stringify({
              url: url,
              method: "POST",
              headers: {
                "Content-Type": "application/json",
                Authorization: `Bearer ${OPENAI_API_KEY}`,
              },
              body: JSON.stringify(data),
            })
          );
          console.log("API响应原始数据:", xhr.responseText);
          const json = JSON.parse(xhr.responseText);
          if (
            !json.choices ||
            !json.choices[0] ||
            !json.choices[0].message ||
            !json.choices[0].message.content
          ) {
            console.error("API返回无效的数据结构");
            reject(new Error("API返回无效的数据结构"));
          } else {
            console.log("成功解析API响应");
            console.log("完整扩写结果:", json.choices[0].message.content);
            resolve(json.choices[0].message.content.trim());
          }
        } catch (error) {
          console.error("解析API响应失败:", error);
          reject(new Error("解析API响应失败"));
        }
      }
    };

    const data = {
      model: OPENAI_MODEL,
      messages: [
        {
          role: "user",
          content: PROMPT_TEMPLATE(text),
        },
      ],
      temperature: 1.5,
    };

    xhr.send(JSON.stringify(data));
  });
}

function insertTextBelowSelection(selection, textToInsert) {
  // 移动光标到选中文本的结尾
  selection.Collapse(false);
  // 插入新文本
  selection.InsertAfter(textToInsert);
}

点击保存,此时弹出的对话框并不是模板文件所在的位置,我们要进行切换,银河麒麟可直接复制下面地址,其他系统可通过点击 WPS 左上方“文件”-“新建”-“本机上的模板”-“浏览模板位置”查看。

shell
/home/kylin/.local/share/Kingsoft/office6/templates/wps/zh_CN

d_mbwjwz

如果想部署其他运营商的 AI 服务,需要对下面部分进行替换,原文已标注替换的位置(API 地址和模型名称)

注意

特别要注意的是,在替换完成以后,需要将OPENAI_API_URLOPENAI_MODEL后面加上数字,数字要与当前代码中OPENAI_API_KEY后面的数字保持一致,否则会提示如下报错。

d_mbwjwz

javascript
// 接口地址,这里填的是腾讯云的api地址,如果用其他的,请修改
const OPENAI_API_URL =
  "https://api.lkeap.cloud.tencent.com/v1/chat/completions";
// 调用模型名称,这里调用的是R1,改为“deepseek-v3”后速度会加快,但缺少深度推理
const OPENAI_MODEL = "deepseek-r1";
javascript
// 接口地址,这里填的是硅基流动的api地址,如果用其他的,请修改
const OPENAI_API_URL = "https://api.siliconflow.cn/v1/chat/completions";
// 调用模型名称,这里调用的是R1,改为“deepseek-ai/DeepSeek-V3”后速度会加快,但缺少深度推理
const OPENAI_MODEL = "deepseek-ai/DeepSeek-R1";
javascript
// 接口地址,这里填的是DeepSeek官方的api地址,如果用其他的,请修改
const OPENAI_API_URL = "https://api.deepseek.com/v1/chat/completions";
// 调用模型名称,这里调用的是R1,如果用其他的,改为“deepseek-chat”后速度会加快,但缺少深度推理
const OPENAI_MODEL = "deepseek-reasoner";
javascript
// 接口地址,这里填的是百度云千帆api地址,如果用其他的,请修改
const OPENAI_API_URL = "https://qianfan.baidubce.com/v2/chat/completions";
// 调用模型名称,这里调用的是R1,改为“deepseek-v3”后速度会加快,但缺少深度推理
const OPENAI_MODEL = "deepseek-r1";

添加菜单栏按钮

在 WPS 中依次点击“文件”-“选项”-“自定义功能区”,按照顺序执行下面的操作,然后选中右边新添加的宏,再点击重命名,可以对其进行命名,命名结果就是选项卡中显示的效果。按需对“组”重命名(可以不用,微软的 Office 会显示组名,WPS 不显示)。

d_tjdpan

这样就部署完了

效果测试

使用就简单了!选中文本,单击工具里面的按钮,提出要求,输出结果会自动插入到选中文本的后面…… 因为使用的是 DeepSeek R1 深度推理模型,所以感觉速度有点慢,其实正在推理,这个过程无法显示。

d_csxg

VitePress Algolia Twikoo EdgeOne Copyright