逐步指南:向 ONLYOFFICE AI 智能体中添加自定义 AI 函数
借助全新 AI 智能体,ONLYOFFICE 为当下快速发展的数字世界提供了前沿工具。作为开源项目,我们欢迎用户的创新。本文将展示如何向 AI 智能体添加自定义函数,使处理文档更快更便捷。
什么是 AI 函数?AI 函数有什么用途?
AI 函数是 AI 智能体功能的核心构建模块。它们本质上是对 AI 助手发出的指令,可以告诉 AI 助手:
- 要向 AI 模型发送什么请求;
- 要对您的文档执行哪些操作。
借助 AI 函数,您可以扩展并控制 AI 与文档内容的交互方式。
如何使用 AI 函数
- 在 AI 插件中选择并添加模型。
- 按下 CTRL + B 打开 AI 智能体对话框。
- 输入提示并按 Enter。
示例:commentText 函数
commentText 函数可让您直接在文档中添加由 AI 生成的批注。工作流程如下:
- 选中要添加批注的单词;
- 打开 AI 智能体对话框(CTRL + B);
- 输入指令,例如:“解释这段文字”;
- 按下 Enter。
AI 智能体将运行 commentText 函数,并在文档中插入相关批注:
为什么要为 AI 智能体添加自定义函数?
添加自定义 AI 函数可以扩展 AI 智能体能力,使其能精确满足个人需求。无论是处理文档、电子表格还是演示文稿,智能体的灵活性加上现代 AI 模型的强大功能,都能帮您把创意转化为现实,并整合进工作流中。
添加自定义 AI 函数的总体逻辑
添加自定义函数的过程包括两大阶段:
- 函数注册——在智能体环境中注册 AI 函数及其元数据。
- 函数执行——实现核心逻辑,包括向 AI 模型发送请求,以及利用我们的 Office API 处理文档内容。
下面将详细介绍这两个阶段。
函数注册
要添加新函数,我们需执行 RegisteredFunction 对象。它允许我们为函数添加元数据和逻辑。以下示例展示了如何为文档编辑器添加 commentText 函数:
let func = new RegisteredFunction();
func.name = "commentText";
func.params = [
"type (string): whether to add as a 'comment' or as a 'footnote' default is 'comment')"
];
func.examples = [
"If you need to explain selected text as a comment, respond with:\n" +
"[functionCalling (commentText)]: {\"prompt\" : \"Explain this text\", \"type\": \"comment\"}",
"If you need to add a footnote to selected text, respond with:\n" +
"[functionCalling (commentText)]: {\"prompt\" : \"Add a footnote to this text\", \"type\": \"footnote\"}",
"If you need to comment selected text, respond with:\n" +
"[functionCalling (commentText)]: {\"prompt\" : \"Comment this text\"}",
"If you need to explain selected text as a footnote, respond with:\n" +
"[functionCalling (commentText)]: {\"prompt\" : \"Explain this text\", \"type\": \"footnote\"}"
]
其中:
- func.name:AI 调用此函数时使用的名称(如 “commentText”)。
- func.params:函数期望从 AI 处获得的参数列表。例如:
– prompt (string):批注的描述或指令,为字符串格式。
– type (string):您需要指定插入“批注” 还是 “脚注”类型,为字符串格式。
- func.examples:提供给 AI 的正确函数调用示例。
- func.description:向 AI 说明该函数的用途。
AI 使用这些参数。RegisteredFunction() 对象被定义在 helperFunc.js 文件中。
函数执行逻辑
注册函数后,我们要编写当 AI 被调用时该函数真正执行的逻辑。
- 使用 Asc.Editor.callCommand() 获取选中的文本。
func.call = async function(params) {
let type = params.type;
let isFootnote = "footnote" === type;
// Executes a block of code inside the editor's context using the office=js API.
let text = await Asc.Editor.callCommand(function(){
let doc = Api.GetDocument();
// Gets the current selected text range.
let range = doc.GetRangeBySelect();
let text = range ? range.GetText() : "";
if (!text)
{
text = doc.GetCurrentWord();
// Selects the current word so comments can be applied to it.
doc.SelectCurrentWord();
}
return text;
});
- 通过组合 params.prompt 与所选文本,为 AI 构建提示。
let argPromt = params.prompt + ":\n" + text;
- 使用 AI.Request.create 初始化 AI.Request.create 对象(该对象在 engine.js 文件中被定义),用于向 AI 模型发送请求。
// Initializes a request engine for communicating with the AI model (e.g. Chat, Translation).
let requestEngine = AI.Request.create(AI.ActionType.Chat);
if (!requestEngine)
return;
- 调用 chatRequest() 发送请求,并在回调中接收结果。
// Sends a prompt to the AI model and processes the response via callback. Can stream or wait.
let result = await requestEngine.chatRequest(argPromt, false, async function(data) {
if (!data)
return;
- 使用 AddFootnote() 或 AddComment() 将回复插入为脚注或批注。
AddFootnote 执行:
if (isFootnote)
{
let addFootnote = true;
// Sends a prompt to the AI model and processes the response via callback. Can stream or wait.
let result = await requestEngine.chatRequest(argPromt, false, async function(data) {
if (!data)
return;
// Marks the end of a logical group or block action in the editor.
await checkEndAction();
Asc.scope.data = data;
Asc.scope.model = requestEngine.modelUI.name;
if (addFootnote)
{
// Executes a block of code inside the editor's context using the document model API.
await Asc.Editor.callCommand(function(){
// Returns the main document object, which gives access to all editing, structure, and selection APIs.
Api.GetDocument().AddFootnote();
});
addFootnote = false;
}
// Inserts the AI-generated result into the document at the current selection or cursor.
await Asc.Library.PasteText(data);
});
AddComment 执行:
let commentId = null;
// Sends a prompt to the AI model and processes the response via callback. Can stream or wait.
let result = await requestEngine.chatRequest(argPromt, false, async function(data) {
if (!data)
return;
// Marks the end of a logical group or block action in the editor.
await checkEndAction();
Asc.scope.data = data;
Asc.scope.model = requestEngine.modelUI.name;
Asc.scope.commentId = commentId;
// Executes a block of code inside the editor's context using the document model API.
commentId = await Asc.Editor.callCommand(function(){
// Returns the main document object, which gives access to all editing, structure, and selection APIs.
let doc = Api.GetDocument();
let commentId = Asc.scope.commentId;
if (!commentId)
{
// Gets the current selected text range, which can be modified or annotated.
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(){
// Defines the commentText function — lets AI insert a comment or footnote for selected text using AI response.
WORD_FUNCTIONS.commentText = function()
{
// Creates a new function object that will be registered and exposed to the AI.
let func = new RegisteredFunction();
func.name = "commentText";
// Lists the parameters expected by the function. These are passed as a JSON object by the AI agent.
func.params = [
"type (string): whether to add as a 'comment' or as a 'footnote' (default is 'comment')"
];
// Gives example JSON inputs to teach the AI how to correctly invoke this function.
func.examples = [
"If you need to explain selected text as a comment, respond with:\n" +
"[functionCalling (commentText)]: {\"prompt\" : \"Explain this text\", \"type\": \"comment\"}",
"If you need to add a footnote to selected text, respond with:\n" +
"[functionCalling (commentText)]: {\"prompt\" : \"Add a footnote to this text\", \"type\": \"footnote\"}",
"If you need to comment selected text, respond with:\n" +
"[functionCalling (commentText)]: {\"prompt\" : \"Comment this text\"}",
"If you need to explain selected text as a footnote, respond with:\n" +
"[functionCalling (commentText)]: {\"prompt\" : \"Explain this text\", \"type\": \"footnote\"}"
];
// The actual logic that gets executed when the AI calls this function.
func.call = async function(params) {
let type = params.type;
let isFootnote = "footnote" === type;
// Executes a block of code inside the editor's context using the office-js API.
let text = await Asc.Editor.callCommand(function(){
let doc = Api.GetDocument();
// Gets the current selected text range.
let range = doc.GetRangeBySelect();
let text = range ? range.GetText() : "";
if (!text)
{
text = doc.GetCurrentWord();
// Selects the current word so comments can be applied to it.
doc.SelectCurrentWord();
}
return text;
});
let argPromt = params.prompt + ":\n" + text;
// Initializes a request engine for communicating with the AI model (e.g. Chat, Translation).
let requestEngine = AI.Request.create(AI.ActionType.Chat);
if (!requestEngine)
return;
let isSendedEndLongAction = false;
// Marks the end of a logical group or block action in the editor.
async function checkEndAction() {
if (!isSendedEndLongAction) {
// Marks the end of a logical group or block action in the editor.
await Asc.Editor.callMethod("EndAction", ["Block", "AI (" + requestEngine.modelUI.name + ")"]);
isSendedEndLongAction = true
}
}
// Starts a block action in the editor, used for undo/redo
await Asc.Editor.callMethod("StartAction", ["Block", "AI (" + requestEngine.modelUI.name + ")"]);
// Starts a block action in the editor, used for undo/redo
await Asc.Editor.callMethod("StartAction", ["GroupActions"]);
if (isFootnote)
{
let addFootnote = true;
// Sends a prompt to the AI model and processes the response via callback
let result = await requestEngine.chatRequest(argPromt, false, async function(data) {
if (!data)
return;
// Marks the end of a block action in the editor.
await checkEndAction();
Asc.scope.data = data;
Asc.scope.model = requestEngine.modelUI.name;
if (addFootnote)
{
// Executes a block of code inside the editor's context using the office-js API.
await Asc.Editor.callCommand(function(){
Api.GetDocument().AddFootnote();
});
addFootnote = false;
}
// Inserts the AI-generated result into the document at the current selection or cursor.
await Asc.Library.PasteText(data);
});
}
else
{
let commentId = null;
// Sends a prompt to the AI model and processes the response via callback.
let result = await requestEngine.chatRequest(argPromt, false, async function(data) {
if (!data)
return;
// Marks the end of a block action in the editor.
await checkEndAction();
Asc.scope.data = data;
Asc.scope.model = requestEngine.modelUI.name;
Asc.scope.commentId = commentId;
// Executes a block of code inside the editor's context using the office-js API.
commentId = await Asc.Editor.callCommand(function(){
let doc = Api.GetDocument();
let commentId = Asc.scope.commentId;
if (!commentId)
{
// Gets the current selected text range.
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;
});
});
}
// Marks the end of a block action in the editor.
await checkEndAction();
// Marks the end of a block action in the editor.
await Asc.Editor.callMethod("EndAction", ["GroupActions"]);
};
return func;
}
我们始终致力于紧跟现代技术,确保智能 AI 智能体持续演进,以满足当今数字世界需求。通过创建自定义函数,您可以扩展 AI 能力,直至能完全满足个人需求。我们期待您的创意与想法。
如有任何疑问、建议或反馈,欢迎随时与我们联系。我们希望帮助您将愿景变为现实,祝愿您在探索 AI 功能的过程中一帆风顺。
创建免费的 ONLYOFFICE 账户
在线查看并协作编辑文本文档、电子表格、幻灯片、表单和 PDF 文件。