摘要:本文由葡萄城技術團隊於部落格園原創並首發。葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者。
在《大火的ChatGPT與SpreadJS結合會有哪些意想不到的效果》一文中提到ChatGPT外掛的一個明顯的問題,那就是「返回的結果格式可能外掛也無法進行分析使用,從而是使得後續的操作無法繼續執行」。造成這個問題原因與ChatGPT的技術原理有一定的關係。
模型預言的限制:ChatGPT是基於語言模型的,其效能受模型訓練和資料集的限制。對於複雜的問題可能並不能準確返回結果,同時返回的結果格式可能外掛也無法分析使用。
但隨著6月13日釋出Chat Completions API 的function calling能力,這個問題得到了很好的解決。此次更新帶來了新的模型,更大的內容,更低的價格,而Function calling更是帶來了革命性的互動方式。
通過Function calling,OpenAI model可以根據你對系統中functions的描述來生成外部系統可以直接使用的結構化的JSON引數,這樣GPT就可以更好的和外部系統結合。
以前文中「建議的資料透視表」為例,對於提供的表格資料,text-davinci-003 model會返回建議的文字內容:
"text": "\n\n行:銷售人員\n列:品牌\n值:銷售額\n\n通過這樣設定可以分析出每個銷售人員銷售的不同品牌的總銷售額。"
雖然有換行等符號可以解析所需要的行列值,但是穩定性十分不確定,程式很難直接使用。
通過使用Function calling,資料透視表的建立就會變得非常簡單。還是以OpenAI官方提供的nodejs支援為例。
在對話中加入functions描述
1. let messages = [
2. {"role": "user", "content": "最後的JSON資料第一行是資料欄位,建立有分析意義的資料透視表\\n" + JSON.stringify(data)}
3. ]
4. let functions = [{
5. "name": "pivot_talbe_analyze",
6. "description": "對資料建立資料透視表,返回資料透視表結果",
7. "parameters": {
8. "type": "object",
9. "properties": {
10. "rowFieldName": {
11. "type": "string",
12. "description": "行欄位名稱"
13. },
14. "columnFieldName": {
15. "type": "string",
16. "description": "列段名稱"
17. },
18. "dataFieldName": {
19. "type": "string",
20. "description": "值欄位名稱"
21. },
22. },
23. },
24. "required": ["rowFieldName", "dataFieldName"]
25. }]
26.
27. var response = openai.createChatCompletion({
28. "model": "gpt-3.5-turbo-0613",
29. "messages": messages,
30. "functions": functions,
31. "functions_call": {"name": "pivot_talbe_analyze"}
32. });
一次對話可以有多個function描述,每個function描述包含名稱,描述,方法引數(描述規則是JSON Schema),以及那些parameter是必選的。
對於選擇區域建立資料透視表,需要提供行、列、值三個維度的欄位名稱,因此需要rowFieldName、columnFieldName和dataFieldName三個paramenter。
另外,可以通過function_call設定選擇function的模式,當functions欄位不為空時預設為「auto」,範例中指定了function pivot_talbe_analyze。
完成呼叫直接返回了function name 和parameters中的三個引數:
{name: 'pivot_talbe_analyze', arguments: '{\\n "rowFieldName": "銷售人員",\\n "columnFieldName": "品牌",\\n "dataFieldName": "銷售額"\\n}'}
通過返回的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);
1. 給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)
});
將歷史和獲取到的透視表資訊新增到messages中,這裡message rule多了function型別,content就是呼叫function的返回結果。
呼叫時function_call設定none,不要使用function calling, GPT根據上下文返回瞭如下資訊:
{role: 'assistant', content: '以下是建立的資料透視表:\n\n\`\`\`\n[\n ["求和項:銷售額", "品牌", null, null…\n]\n\`\`\`\n\n該資料透視表按照銷售人員和品牌對銷售額進行了彙總,可以更方便地進行資料分析和比較。'}
接下來可以傳送新的請求讓GPT對資料做進一步的分析處理,當然對於一些系統操作,我們做到步驟2就可以了。
總結一下,通過Function calling,自身系統和openai model互動更加簡便,耦合的更加緊密,系統通過互動的方式向ChatGPT model發起請求,model可以智慧選擇需要呼叫的系統function,進一步提升了系統的創造性。
不過還是需要提醒,對於呼叫系統資料更新刪除的方法,還是要做好確認再去執行。
擴充套件連結: