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.注册并登录控制台
- 腾讯云(推荐)
- 硅基流动
- DeepSeek官方
- 百度云千帆
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
后面的数字保持一致,否则会提示如下报错。
- 腾讯云(推荐)
- 硅基流动
- DeepSeek官方
- 百度云千帆
// 接口地址,这里填的是腾讯云的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深度推理模型,所以感觉速度有点慢,其实正在推理,这个过程无法显示。