DeepSeek 与 WPS 联动
提示
本教程实现 WPS 内嵌 DeepSeek,实现办公与 AI 联动,大幅提高效率。
注意
安装环境:
- 系统:银河麒麟 V10SP1 2023(arm),理论上应该通用,包括 UOS。
- WPS 版本号:19831(点我可下载 Arm 版本) ,也可到WPS365 官网自行下载。这里需要特别注意,已测试 15283,12219 版本不可用,也是踩了几个坑,本以为 linux 上 WPS 的 VBA 版本可能不完善,最后抱着试试看的想法安装了官网最新版,居然可用!喜大普奔!
准备工作:申请 API
近期,各大 AI 运营商均部署了 DeepSeek 模型,并在其网站后台提供了 API 密钥,当前大部分运营商的 API 可以免费申请,小编提供了目前 4 个可以免费部署的服务商供大家选择。用户可以将获取的 API 密钥复制并替换到相应的代码中以接入这些服务。这里以腾讯云为例进行说明,因为在我的测试中,它的响应速度较快。当然,你也可以根据实际需求和不同平台的表现进行相应调整。
1.注册并登录控制台
https://console.cloud.tencent.com/lkeap
https://cloud.siliconflow.cn
https://platform.deepseek.com/usage
https://cloud.baidu.com
2.开通大模型知识引擎服务
点击开通大模型知识引擎
点击大模型知识引擎下面的立即使用
3.复制并保存 API-Key
点击侧边栏的 API-Key,再点击创建API KEY
按钮,保存 API KEY 备用
配置宏代码
1.打开 WPS
新建一个文本文档,文档的格式没有要求,doc、docx 或者 wps 格式的均可,因为都适合用 VBA 处理。
点击菜单栏中的工具选项卡中的开发工具
再点击 WPS 宏编辑器(VBA)
2.配置宏代码
右键点击 Project(Normal.dotm)
(这是 Word 的全局模板,适用于所有新建的文档)。需要注意的是,不要右键点击你当前正在编辑的新建文档或任何特定文档的项目,因为我们的目标是让新模块对所有文档生效。
将下面的代码复制到右边的代码编辑器(已折叠,点击显示)
点击查看代码
// 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);
}
// 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);
}
// 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 左上方“文件”-“新建”-“本机上的模板”-“浏览模板位置”查看。
/home/kylin/.local/share/Kingsoft/office6/templates/wps/zh_CN
如果想部署其他运营商的 AI 服务,需要对下面部分进行替换,原文已标注替换的位置(API 地址和模型名称)
注意
特别要注意的是,在替换完成以后,需要将OPENAI_API_URL
和OPENAI_MODEL
后面加上数字,数字要与当前代码中OPENAI_API_KEY
后面的数字保持一致,否则会提示如下报错。
// 接口地址,这里填的是腾讯云的api地址,如果用其他的,请修改
const OPENAI_API_URL =
"https://api.lkeap.cloud.tencent.com/v1/chat/completions";
// 调用模型名称,这里调用的是R1,改为“deepseek-v3”后速度会加快,但缺少深度推理
const OPENAI_MODEL = "deepseek-r1";
// 接口地址,这里填的是硅基流动的api地址,如果用其他的,请修改
const OPENAI_API_URL = "https://api.siliconflow.cn/v1/chat/completions";
// 调用模型名称,这里调用的是R1,改为“deepseek-ai/DeepSeek-V3”后速度会加快,但缺少深度推理
const OPENAI_MODEL = "deepseek-ai/DeepSeek-R1";
// 接口地址,这里填的是DeepSeek官方的api地址,如果用其他的,请修改
const OPENAI_API_URL = "https://api.deepseek.com/v1/chat/completions";
// 调用模型名称,这里调用的是R1,如果用其他的,改为“deepseek-chat”后速度会加快,但缺少深度推理
const OPENAI_MODEL = "deepseek-reasoner";
// 接口地址,这里填的是百度云千帆api地址,如果用其他的,请修改
const OPENAI_API_URL = "https://qianfan.baidubce.com/v2/chat/completions";
// 调用模型名称,这里调用的是R1,改为“deepseek-v3”后速度会加快,但缺少深度推理
const OPENAI_MODEL = "deepseek-r1";
添加菜单栏按钮
在 WPS 中依次点击“文件”-“选项”-“自定义功能区”,按照顺序执行下面的操作,然后选中右边新添加的宏,再点击重命名,可以对其进行命名,命名结果就是选项卡中显示的效果。按需对“组”重命名(可以不用,微软的 Office 会显示组名,WPS 不显示)。
这样就部署完了
效果测试
使用就简单了!选中文本,单击工具里面的按钮,提出要求,输出结果会自动插入到选中文本的后面…… 因为使用的是 DeepSeek R1 深度推理模型,所以感觉速度有点慢,其实正在推理,这个过程无法显示。