免费POC, 零成本试错
AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


为 ONLYOFFICE AI 智能体开发自定义函数:实践指南&夺奖攻略!

发布日期:2025-09-09 17:21:30 浏览次数: 1524
作者:ONLYOFFICE

微信搜一搜,关注“ONLYOFFICE”

推荐语

解锁ONLYOFFICE AI智能体的无限可能,通过自定义函数打造专属文档处理神器,还能赢取开发大赛奖励!

核心内容:
1. AI函数的概念与核心价值解析
2. 自定义函数开发全流程分步指南
3. 开发大赛参与方式与奖励机制

杨芳贤
53AI创始人/腾讯云(TVP)最具价值专家

借助全新 AI 智能体, ONLYOFFICE 为快速发展的数字世界提供了前沿工具。作为开源项目,我们始终鼓励用户通过创新拓展能力边界。现在,您不仅可通过自定义 AI 函数提升文档处理效率,更能参与 ONLYOFFICE AI 智能体功能开发大赛,将创意直接转化为生产力! 本文提供详细实施指南(文末附大赛信息),助您快速掌握函数开发全流程。

什么是 AI 函数?AI 函数有什么用途?

AI 函数是 AI 智能体功能的核心构建模块。它们本质上是对 AI 助手发出的指令,可以告诉 AI 助手:

  • 要向 AI 模型发送什么请求;

  • 要对您的文档执行哪些操作。

借助 AI 函数,您可以扩展并控制 AI 与文档内容的交互方式。

如何使用 AI 函数

  1. 在 AI 插件中选择并添加模型。

  2. 按下 CTRL + / 打开 AI 智能体对话框
  3. 输入提示并按 Enter

示例:commentText 函数

commentText 函数可让您直接在文档中添加由 AI 生成的批注。工作流程如下:

  • 选中要添加批注的单词;

  • 打开 AI 智能体对话框(CTRL + B)

  • 输入指令,例如:“解释这段文字”;

  • 按下 Enter

AI 智能体将运行 commentText 函数,并在文档中插入相关批注:

为什么要为 AI 智能体添加自定义函数?

添加自定义 AI 函数可以扩展 AI 智能体能力,使其能精确满足个人需求。无论是处理文档、电子表格还是演示文稿,智能体的灵活性加上现代 AI 模型的强大功能,都能帮您把创意转化为现实,并整合进工作流中。

添加自定义 AI 函数的通用逻辑

智能体的所有 AI 函数都组织在 helpers 目录中,其结构如下:

  • cell.js – 电子表格编辑器的 AI 函数

  • slide.js – 演示文稿编辑器的 AI 函数

  • word.js – 文档编辑器的 AI 函数

创建新的自定义函数时,将其添加到其所属编辑器的适当文件中。

helpers 目录:https://github.com/ONLYOFFICE-PLUGINS/onlyoffice.github.io/tree/8a8b3e3237745bde2f99db5b8cee0abf2c637317/sdkjs-plugins/content/ai/scripts/helpers 

添加自定义函数的过程包括两大阶段:

  • 函数注册——在智能体环境中注册 AI 函数及其元数据。

  • 函数执行——实现核心逻辑,包括向 AI 模型发送请求,以及利用我们的 Office API 处理文档内容。https://api.onlyoffice.com/zh-CN/docs/office-api/get-started/overview/

下面将详细介绍这两个阶段。

函数注册

要添加新函数,我们需执行 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 文件中:https://github.com/ONLYOFFICE-PLUGINS/onlyoffice.github.io/blob/8a8b3e3237745bde2f99db5b8cee0abf2c637317/sdkjs-plugins/content/ai/scripts/helperFuncs.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 模型发送请求。

engine.js:https://github.com/ONLYOFFICE-PLUGINS/onlyoffice.github.io/blob/8a8b3e3237745bde2f99db5b8cee0abf2c637317/sdkjs-plugins/content/ai/scripts/engine/engine.js#L554

// 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 方法。

StartAction :https://api.onlyoffice.com/zh-CN/docs/plugin-and-macros/interacting-with-editors/text-document-api/Methods/StartAction/

EndAction:https://api.onlyoffice.com/zh-CN/docs/plugin-and-macros/interacting-with-editors/text-document-api/Methods/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 能力,直至能完全满足个人需求。我们期待您的创意与想法。

53AI,企业落地大模型首选服务商

产品:场景落地咨询+大模型应用平台+行业解决方案

承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

添加专属顾问

回到顶部

加载中...

扫码咨询