随笔 – 当ChatGPT遇见SpreadJS (续)

发布时间:2023/06/21 15:06 发布者:Leo

返回博客中心

在之前的《随笔-当ChatGPT遇见SpreadJS》一文中,我们提到了ChatGPT插件存在一个明显的问题,即返回的结果可能无法以可分析和使用的格式呈现给插件。

这个问题是由于ChatGPT是基于语言模型构建的,其性能受限于模型的训练和数据集的限制所致。对于复杂的问题,模型可能无法准确返回结果,并且返回的结果格式可能无法被插件理解和处理。

然而,随着于6月13日发布的Chat Completions API的function calling能力,这个问题得到了很好的解决。此次更新引入了全新的模型,具备更大的内容容量,并且价格更低廉。而function calling的功能更是带来了一种革命性的互动方式。

通过function calling,OpenAI模型可以根据您对系统中函数的描述生成结构化的JSON参数,这样外部系统就能够直接使用这些参数。这种方式使得GPT能够更好地与外部系统进行集成。

让我们以前文中提到的"建议的数据透视表"为例。对于提供的表格数据,text-davinci-003模型会返回以下文本内容:

"text": "\n\n行:销售人员\n列:品牌\n值:销售额\n\n通过这样设置可以分析出每个销售人员销售的不同品牌的总销售额。"

虽然这段文本中包含了换行和其他符号来描述所需的行、列和值,但其稳定性并不确定,因此很难直接被程序使用。

现在,借助function calling的能力,我们可以改善这个问题。您可以描述您期望的表格结构,然后OpenAI模型将生成一组结构化的JSON参数,这些参数可以直接被外部系统解析和使用。这样,GPT就能够更好地与外部系统无缝衔接了。

修改后的ChatGPT示例

通过利用Function calling,创建数据透视表将变得非常简单。让我们以OpenAI官方提供的Node.js支持为例进行改写。

在对话中加入functions描述

   let messages = [
       { "role": "user", "content": "最后的JSON数据第一行是数据字段,创建有分析意义的数据透视表\n" + JSON.stringify(data) }
   ]

   let functions = [{
       "name": "pivot_talbe_analyze",
       "description": "对数据创建数据透视表,返回数据透视表结果",
       "parameters": {
           "type": "object",
           "properties": {
               "rowFieldName": {
                   "type": "string",
                   "description": "行字段名称"
               },
               "columnFieldName": {
                   "type": "string",
                   "description": "列段名称"
               },
               "dataFieldName": {
                   "type": "string",
                   "description": "值字段名称"
               },
           },
       },
       "required": ["rowFieldName", "dataFieldName"]
   }]

   var response = openai.createChatCompletion({
       "model": "gpt-3.5-turbo-0613",
       "messages": messages,
       "functions": functions,
       "functions_call": { "name": "pivot_talbe_analyze" }
   });

在一次对话中,我们可以包含多个函数描述,每个函数描述都包含名称、描述、方法参数(使用JSON Schema进行描述)以及哪些参数是必选的信息。在我们的例子中,我们需要使用三个参数来选择区域并创建数据透视表,这些参数是rowFieldName(行字段名称)、columnFieldName(列字段名称)和dataFieldName(数据字段名称)。

此外,我们还可以通过functioncall设置函数选择的模式。当functions字段不为空时,默认模式为"auto"。在我们的示例中,我们指定了function为"pivottable_analyze"。

完成函数调用后,我们将直接返回函数名称和参数中的这三个参数。

{name: 'pivot_talbe_analyze', arguments: '{\n "rowFieldName": "销售人员",\n "columnFieldName": "品牌",\n "dataFieldName": "销售额"\n}'}

使用GPT返回结果创建透视表

通过返回的function name 和parameters就可以直接调用系统中的对应方法创建的透视表了

let args = JSON.parse(completion.data.choices[0].message.function_call.arguments);
let pivotTable = sheet.pivotTables.add("PivotTable", "Table1", 2, 7, GC.Spread.Pivot.PivotTableLayoutType.outline, GC.Spread.Pivot.PivotTableThemes.medium2);

pivotTable.add(args.rowFieldName, args.rowFieldName, GC.Spread.Pivot.PivotTableFieldType.rowField);
if(args.columnFieldName){
    pivotTable.add(args.columnFieldName, args.columnFieldName, GC.Spread.Pivot.PivotTableFieldType.columnField);
} 
pivotTable.add(args.dataFieldName, "求和项:" + args.dataFieldName, GC.Spread.Pivot.PivotTableFieldType.valueField, GC.Pivot.SubtotalType.sum);

获取SpreadJS透视表结果

let ptRange = pivotTable.getRange().content;
let ptData = sheet.getArray(ptRange.row, ptRange.col, ptRange.rowCount, ptRange.colCount);

给GPT反馈公式调用结果

messages.push(completion.data.choices[0].message);
messages.push({ "role": "function", "name": "pivot_talbe_analyze", "content": JSON.stringify({ pivotTable: ptData }) });
response = openai.createChatCompletion({
    "model": "gpt-3.5-turbo-0613",
    "messages": messages,
    "functions": functions,
    function_call: "none"
});
response.then(function (completion) {
    let desc = completion.data.choices[0].message.content;
    GC.Spread.Sheets.Designer.showMessageBox(desc, "分析结果", GC.Spread.Sheets.Designer.MessageBoxIcon.info)
});

在处理过程中,我们将历史记录和获取到的数据透视表信息都添加到了对话消息中。这里的消息规则中多了一个function类型,其中content表示调用函数后返回的结果。

在调用函数时,我们使用了function_call设置为"none",即不使用函数调用。根据上下文,GPT返回了以下信息:

{role: 'assistant', content: '以下是创建的数据透视表:\n\n\n[\n ["求和项:销售额", "品牌", null, null…\n]\n\n\n该数据透视表按照销售人员和品牌对销售额进行了汇总,可以更方便地进行数据分析和比较。'}

接下来,您可以发送新的请求,让GPT对数据进行进一步的分析处理。当然,对于一些系统操作,我们只需完成前面的步骤2即可。

总结一下,通过使用ChatGPT Function calling,我们能够更方便地与OpenAI模型进行互动,并实现系统与模型之间更紧密的耦合。我们的系统可以通过互动方式向ChatGPT模型发送请求,而模型则能够智能地选择需要调用的系统函数,从而进一步提升系统的创造性。

然而,我们仍然需要注意,在涉及到调用系统的数据更新和删除方法时,仍然需要进行仔细确认后才执行操作。

通过这种改进,我们能够更好地利用ChatGPT Function calling的能力,使系统与模型之间的交互变得更加高效和智能化。这为我们的应用程序提供了更广阔的创新空间。


SpreadJS | 下载试用

纯前端表格控件SpreadJS,兼容 450 种以上的 Excel 公式,具备“高性能、跨平台、与 Excel 高度兼容”的产品特性,备受华为、苏宁易购、天弘基金等行业龙头企业的青睐,并被中国软件行业协会认定为“中国优秀软件产品”。SpreadJS 可为用户提供类 Excel 的功能,满足表格文档协同编辑、 数据填报、 类 Excel 报表设计等业务场景需求,极大的降低企业研发成本和项目交付风险。

如下资源列表,可以为您评估产品提供帮助: