创建自定义函数(测试版)
AI 函数定义了 AI 代理的功能。它们指定:
- 要向 AI 模型发送什么请求;
- 要对文档执行什么操作。
添加自定义 AI 函数可以扩展 AI 代理的功能,并使其能够适应特定的使用场景。无论是处理文档、电子表格还是演示文稿,自定义函数都能让你将 AI 驱动的操作直接集成到工作流程中,并使代理的行为符合你的需求。
你可以在此处找到现成的自定义 AI 函数,也可以创建自己的函数。
如何使用 AI 函数
要使用 AI 函数,请按照以下步骤操作:
- 向 AI 插件添加模型。
- 按
CTRL + /打开 AI 代理对话框。 - 输入你的提示词并按 Enter。
示例:commentText 函数
commentText 函数允许直接向文档中添加 AI 生成的评论。其工作方式如下:
- 选择要添加评论的单词。
- 打开 AI 代理对话框(
CTRL + /)。 - 输入对 AI 代理的指令。例如:
解释这段文字。 - 按 Enter。


AI 代理将运行 commentText 函数,并在文档中插入相关评论。


如何添加自定义 AI 函数
添加自定义函数的过程包括两个主要阶段:
- 函数注册:在代理环境中注册 AI 函数及其元数据。
- 函数执行:实现核心逻辑,包括向 AI 模型发送请求以及使用我们的Office API操作文档内容。
函数注册
要添加新函数,需使用 RegisteredFunction 对象,该对象将自定义函数的元数据和逻辑添加到 AI 代理中。
参数
| 名称 | 类型 | 示例 | 描述 |
|---|---|---|---|
| name | string | "commentText" | 函数名称。 |
| params | 字符串列表 | ["type (string): 是作为 'comment'(评论)还是 'footnote'(脚注)添加(默认是 'comment')"] | 函数期望从 AI 获得的参数列表。 |
| examples | 字符串列表 | ["如果需要将选定文本作为评论进行解释,请回复:\n" + "[functionCalling (commentText)]: {'prompt' : '解释这段文字', 'type': 'comment'}"] | 供 AI 参考的正确函数调用示例。 |
| description | 字符串列表 | "当需要评论或解释任何内容时使用此函数。" | 向 AI 说明该函数用途的描述。 |
示例
let func = new RegisteredFunction();
func.name = "commentText";
func.params = [
"type (string): 是作为 'comment'(评论)还是 'footnote'(脚注)添加(默认是 'comment')"
];
func.examples = [
"如果需要将选定文本作为评论进行解释,请回复:\n" +
"[functionCalling (commentText)]: {\"prompt\" : \"解释这段文字\", \"type\": \"comment\"}",
"如果需要为选定文本添加脚注,请回复:\n" +
"[functionCalling (commentText)]: {\"prompt\" : \"为这段文字添加脚注\", \"type\": \"footnote\"}",
"如果需要对选定文本进行评论,请回复:\n" +
"[functionCalling (commentText)]: {\"prompt\" : \"评论这段文字\"}",
"如果需要将选定文本作为脚注进行解释,请回复:\n" +
"[functionCalling (commentText)]: {\"prompt\" : \"解释这段文字\", \"type\": \"footnote\"}"
]
这些参数供 AI 使用。RegisteredFunction() 对象在 helperFuncs.js 文件中定义。
函数执行
注册函数后,需实现当 AI 调用该函数时实际执行的逻辑:
-
使用
Asc.Editor.callCommand()检索选定的文本:func.call = async function(params) {
let type = params.type;
let isFootnote = "footnote" === type;
// 使用 office-js API 在编辑器上下文中中执行一段代码。
let text = await Asc.Editor.callCommand(function(){
let doc = Api.GetDocument();
// 获取当前选定的文本范围。
let range = doc.GetRangeBySelect();
let text = range ? range.GetText() : "";
if (!text)
{
text = doc.GetCurrentWord();
// 选中当前单词,以便对其添加评论。
doc.SelectCurrentWord();
}
return text;
});
}; -
结合
params.prompt和选定的文本构建给 AI 的提示词:let argPromt = params.prompt + ":\n" + text; -
使用
AI.Request.create初始化一个用于与 AI 模型通信的请求引擎。该对象在 engine.js 文件中定义。此对象有助于向 AI 模型发送请求:// 初始化用于与 AI 模型(如聊天、翻译)通信的请求引擎。
let requestEngine = AI.Request.create(AI.ActionType.Chat);
if (!requestEngine)
return; -
使用
chatRequest()发送请求,并在回调中接收结果:// 向 AI 模型发送提示词,并通过回调处理响应。可以流式传输或等待结果。
let result = await requestEngine.chatRequest(argPromt, false, async function(data) {
if (!data)
return;
}); -
使用 AddFootnote() 或 AddComment() 将响应作为评论或脚注插入。
AddFootnote实现:if (isFootnote)
{
let addFootnote = true;
// 向 AI 模型发送送提示词,并通过回调处理响应。可以流式传输或等待结果。
let result = await requestEngine.chatRequest(argPromt, false, async function(data) {
if (!data)
return;
// 标记编辑器中逻辑组或块操作的结束。
await checkEndAction();
Asc.scope.data = data;
Asc.scope.model = requestEngine.modelUI.name;
if (addFootnote)
{
// 使用文档模型 API 在编辑器上下文中执行一段代码。
await Asc.Editor.callCommand(function(){
// 返回主文档对象,通过它可以访问所有编辑、结构和选择 API。
Api.GetDocument().AddFootnote();
});
addFootnote = false;
}
// 将 AI 生成的结果插入到文档中当前选择或光标位置。
await Asc.Library.PasteText(data);
});
};AddComment实现:let commentId = null;
// 向 AI 模型发送提示词,并通过回调处理响应。可以流式传输或等待结果。
let result = await requestEngine.chatRequest(argPromt, false, async function(data) {
if (!data)
return;
// 标记编辑器中逻辑组或块操作的结束。
await checkEndAction();
Asc.scope.data = data;
Asc.scope.model = requestEngine.modelUI.name;
Asc.scope.commentId = commentId;
// 使用文档模型 API 在编辑器上下文中执行一段代码。
commentId = await Asc.Editor.callCommand(function(){
// 返回主文档对象,通过它可以访问所有编辑、结构和选择 API。
let doc = Api.GetDocument();
let commentId = Asc.scope.commentId;
if (!commentId)
{
// 获取当前选定的文本范围,该范围可以被修改或添加注释。
let range = doc.GetRangeBySelect();
if (!range)
return null;
let comment = range.AddComment(Asc.scope.data, Asc.scope.model, "uid" + Asc.scope.model);
if (!comment)
return null;
doc.ShowComment([comment.GetId()]);
return comment.GetId();
}
let comment = doc.GetCommentById(commentId);
if (!comment)
return commentId;
comment.SetText(comment.GetText() + scope.data);
return commentId;
});
});
为了确保在请求执行后可以回滚整个更改块,我们在
commentText函数中使用了 StartAction 和 EndAction 方法。
带注释的 commentText 函数完整实现:
(function(){
// 定义 commentText 函数 — 让 AI 使用 AI 响应为选定文本插入评论或脚注。
WORD_FUNCTIONS.commentText = function()
{
// 创建一个新的函数对象,该对象将被注册并暴露给 AI。
let func = new RegisteredFunction();
func.name = "commentText";
// 列出函数期望的参数。这些参数由 AI 代理作为 JSON 对象传递。
func.params = [
"type (string): 是作为 'comment'(评论)还是 'footnote'(脚注)添加(默认是 'comment')"
];
// 提供示例 JSON 输入,以教导 AI 如何正确调用此函数。
func.examples = [
"如果需要将选定文本作为评论进行解释,请回复:\n" +
"[functionCalling (commentText)]: {\"prompt\" : \"解释这段文字\", \"type\": \"comment\"}",
"如果需要为选定文本添加脚注,请回复:\n" +
"[functionCalling (commentText)]: {\"prompt\" : \"为这段文字添加脚注\", \"type\": \"footnote\"}",
"如果需要对选定文本进行评论,请回复:\n" +
"[functionCalling (commentText)]: {\"prompt\" : \"评论这段文字\"}",
"如果需要将选定文本作为脚注进行解释,请回复:\n" +
"[functionCalling (commentText)]: {\"prompt\" : \"解释这段文字\", \"type\": \"footnote\"}"
];
// 当 AI 调用此函数时实际执行的逻辑。
func.call = async function(params) {
let type = params.type;
let isFootnote = "footnote" === type;
// 使用 office-js API 在编辑器上下文中执行一段代码。
let text = await Asc.Editor.callCommand(function(){
let doc = Api.GetDocument();
// 获取当前选定的文本范围。
let range = doc.GetRangeBySelect();
let text = range ? range.GetText() : "";
if (!text)
{
text = doc.GetCurrentWord();
// 选中当前单词,以便对其添加评论。
doc.SelectCurrentWord();
}
return text;
});
let argPromt = params.prompt + ":\n" + text;
// 初始化用于与 AI 模型(如聊天、翻译)通信的请求引擎。
let requestEngine = AI.Request.create(AI.ActionType.Chat);
if (!requestEngine)
return;
let isSendedEndLongAction = false;
// 标记编辑器中逻辑组或块操作的结束。
async function checkEndAction() {
if (!isSendedEndLongAction) {
// 标记编辑器中逻辑组或块操作的结束。
await Asc.Editor.callMethod("EndAction", ["Block", "AI (" + requestEngine.modelUI.name + ")"]);
isSendedEndLongAction = true
}
}
// 在编辑器中启动块操作,用于撤销/重做
await Asc.Editor.callMethod("StartAction", ["Block", "AI (" + requestEngine.modelUI.name + ")"]);
// 在编辑器中启动组操作,用于撤销/重做
await Asc.Editor.callMethod("StartAction", ["GroupActions"]);
if (isFootnote)
{
let addFootnote = true;
// 向 AI 模型发送提示词,并通过回调处理响应
let result = await requestEngine.chatRequest(argPromt, false, async function(data) {
if (!data)
return;
// 标记编辑器中块操作的结束。
await checkEndAction();
Asc.scope.data = data;
Asc.scope.model = requestEngine.modelUI.name;
if (addFootnote)
{
// 使用 office-js API 在编辑器上下文中执行一段代码。
await Asc.Editor.callCommand(function(){
Api.GetDocument().AddFootnote();
});
addFootnote = false;
}
// 将 AI 生成的结果插入到文档中当前选择或光标位置。
await Asc.Library.PasteText(data);
});
}
else
{
let commentId = null;
// 向 AI 模型发送提示词,并通过回调处理响应。
let result = await requestEngine.chatRequest(argPromt, false, async function(data) {
if (!data)
return;
// 标记编辑器中块操作的结束。
await checkEndAction();
Asc.scope.data = data;
Asc.scope.model = requestEngine.modelUI.name;
Asc.scope.commentId = commentId;
// 使用 office-js API 在编辑器上下文中执行一段代码。
commentId = await Asc.Editor.callCommand(function(){
let doc = Api.GetDocument();
let commentId = Asc.scope.commentId;
if (!commentId)
{
// 获取当前选定的文本范围。
let range = doc.GetRangeBySelect();
if (!range)
return null;
let comment = range.AddComment(Asc.scope.data, Asc.scope.model, "uid" + Asc.scope.model);
if (!comment)
return null;
doc.ShowComment([comment.GetId()]);
return comment.GetId();
}
let comment = doc.GetCommentById(commentId);
if (!comment)
return commentId;
comment.SetText(comment.GetText() + scope.data);
return commentId;
});
});
}
// 标记编辑器中块操作的结束。
await checkEndAction();
// 标记编辑器中组操作的结束。
await Asc.Editor.callMethod("EndAction", ["GroupActions"]);
};
return func;
}
});
AI 代理功能随着当今数字世界的需求不断发展。通过创建适合特定使用场景的自定义函数来扩展其功能吧。