​借助全新 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 生成的批注。工作流程如下:

  1. 选中要添加批注的单词;
  2. 打开 AI 智能体对话框(CTRL + /)
  3. 输入指令,例如:“解释这段文字”;
  4. 按下 Enter
  5. AI 智能体将运行 commentText 函数,并在文档中插入相关批注

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

  • 扩展能力:让 AI 智能体能够执行官方未预置的、符合个人或团队特殊需求的任务。
  • 提升效率:将复杂的文档处理操作自动化,整合到自己的工作流中。

添加自定义 AI 函数的全局指南

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

  • 函数注册——在智能体环境中注册 AI 函数及其元数据。
  • 函数执行——实现核心逻辑,包括向 AI 模型发送请求,以及利用我们的 Office API 处理文档内容。

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

函数注册

要添加新函数,我们需执行 RegisteredFunction 对象。它允许我们为函数添加元数据和逻辑。以下示例展示了如何为文档编辑器添加 commentText 函数:

let func = new RegisteredFunction();

        func.name = "commentText";

        func.params = [             "type (string): 是以批注形式添加还是以脚注形式添加,默认为批注形式)"

        ];           func.examples = [             "如需以批注形式解释选中文本,请回复:\n" +

            "[functionCalling (commentText)]: {\"prompt\" : \"Explain this text\", \"type\": \"comment\"}",

            "如需为选中文本添加脚注,请回复:\n" +

            "[functionCalling (commentText)]: {\"prompt\" : \"Add a footnote to this text\", \"type\": \"footnote\"}",

            "如需为选中文本添加批注,请回复:\n" +

            "[functionCalling (commentText)]: {\"prompt\" : \"Comment this text\"}",

            "如需以脚注形式解释选中文本,请回复:\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;

// 使用 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.Request.create 对象(该对象在 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.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(){
    
    // 返回主文档对象,提供对所有编辑、结构和选择接口的访问。
    
                            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 函数中统一使用了 StartActionEndAction 方法。

    带完整注释的 commentText 函数:

    (function(){
    
    // 定义 commentText 函数 —— 让 AI 根据返回结果为选中文本插入批注或脚注。
    
        WORD_FUNCTIONS.commentText = function()
    
        {
    
    // 创建一个新的函数对象,该对象将被注册并暴露给 AI。
    
            let func = new RegisteredFunction();
    
            func.name = "commentText";
    
    // 列出函数期望的参数,这些参数由 AI 智能体以 JSON 对象的形式传入。
    
            func.params = [             "type (string): 以批注或以脚注形式添加(默认为 批注形式)"
    
            ];   // 提供示例,JSON 输入,指导 AI 如何正确调用此函数。
    
            func.examples = [             "如需将选中文本以批注形式解释,请回复:\n" +
    
                "[functionCalling (commentText)]: {\"prompt\" : \"Explain this text\", \"type\": \"comment\"}",
    
                "如需为选中文本添加脚注,请回复:\n" +
    
                "[functionCalling (commentText)]: {\"prompt\" : \"Add a footnote to this text\", \"type\": \"footnote\"}",
    
                "如需为选中文本添加批注,请回复:\n" +
    
                "[functionCalling (commentText)]: {\"prompt\" : \"Comment this text\"}",
    
                "如需将选中文本以脚注形式解释,请回复:\n" +
    
                "[functionCalling (commentText)]: {\"prompt\" : \"Explain this text\", \"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;
    
        }

    ONLYOFFICE 作为开源项目,始终致力于紧跟现代技术,确保智能 AI 智能体持续演进,以满足当今数字世界需求。通过创建自定义函数,您可以极大扩展 AI 智能体的能力满足更多办公需求。

    我们期待来自用户的更多创意与想法。更多相关功能您可以通过 GitHub 上的 ONLYOFFICE AI 智能体学习和了解。

    如有任何疑问、建议或反馈,欢迎随时与我们联系。我们希望帮助愿景变为现实祝愿探索 AI 功能过程一帆风顺。

    Logo

    有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

    更多推荐