首頁 > 軟體

如何將ChatGPT整合到Word中

2023-02-24 06:02:02

引言

自ChatGPT出現,各種基於它的軟體擴充套件紛至沓來,目前Word支援ChatGPT的add-in有兩款,可以通過:

插入->獲取載入項->搜尋openai檢視。

其中Ghostwriter從介紹上看功能比較單一,而且軟體需要購買,用自己的API-key,意味著呼叫API還要單獨出錢。

第二個,軟體似乎是免費的,應該也是用自己的API-key。從介紹的視訊上看符合使用的預期,可以傳送選取的文字到ChatGPT,並結合預設的prompt資訊返回所需功能,但是安全性未知。

這類軟體實際上是將內容傳送到OpenAI的伺服器,並將獲取返回內容呈現,於是產生了使用VBA在Word中整合ChatGPT的想法。雖然使用其他語言(比如python)呼叫API更加方便快捷,但VBA對內容的操作更直接。

需求

使用ChatGPT修改語言時,需要將文字複製到網頁版的chatGPT中。省掉複製貼上的過程,能提升效率。設想有以下需求:

基本需求(已實現)

  • 對選取的文字進行操作,包括修改語言,翻譯,檢查語法錯誤等
  • 可以選擇不同的模型
  • 用自己的api-key
  • token數目顯示和計費

進階需求(已放棄)

  • 提供add-in安裝或者可分享
  • 自定義Ribbon的圖示
  • 增加Ribbon下拉式選單,實現使用者選擇模型型別
  • 增加Ribbon選項,實現使用者提交api-key

作為野生程式猿,花了一下午完成基本需求,進階的內容只要花時間是可以實現的。不過相信微軟的攻城獅正在全力將ChatGPT的功能整合到Office全家桶中。類似這樣個人級別的應用,最終會被微軟釋出的新功能淘汰,因此無意投入過多。此專案作為VBA練手,基本需求已滿足,也可以作為微軟釋出新word前的過渡。

實現

一切的前提是有openAI的賬號並且繫結了付款方式。新註冊的賬號有$18自動到賬,因此無需繫結付款方式也可以呼叫。用完之後再決定需不需要單獨為此付費。

1. API模型選擇和費率

費用如下是按照1k token來算的,可以簡單理解為字數,但不完全相同。最新的模型是Davinci,收費也是最高的。注意這裡的token數量指的是傳送和返回的token的總和。ChatGPT告訴我6000字的文章,按照常規演演算法,會有10W的token。。好像還是網頁版香呀。。

具體呼叫中,使用模型名稱如下。

他們都是GPT3的模型,就自身使用感受來看,表現最好的還是davinci,它的速度也是最慢的,ada基本不能用,curie和babbage偶爾能用,不過有的時候連語法錯誤都修改不了,翻譯也是各種不通順。

2.程式碼

2.1.準備工作

採用新增宏的方式,首先要新增開發者索引標籤。

這也不是必須的,因為可以通過快捷鍵Alt+F11直接開啟VBA的介面。

如果只為當前的文字新增宏,就在當前的project下新增模組,如果是為所有的word檔案新增宏的話,就在Normal中新增。之後插入模組,就可以新增VBA的程式碼了。

其次,為了保證之後的程式碼正常執行,需要新增程式需要用的幾個Reference,它們的意思有點類似於R的library。不同的模組可以有不同的Reference,可以選擇專案後統一新增。

再次,由於VB處理起API的資訊就很麻煩,這裡需要單獨載入兩個檔案,主要是JsonConverter,它能將API返回的文字轉化為Dictionary的形式方便提取。如果對正則表達熟悉的話,完全不需要使用JsonConverter就可獲取到所需資訊。 

這裡通過匯入檔案的形式,將下載到的bas檔案匯入。另外要注意的是需要使用這個版本的VBA-JSON-2.3.0,否則會報錯。另外Dictionary定義了幾個物件的屬性,也需要匯入。

2.2. 呼叫API

CallOpenAI,該函數會將word中選取的文字,加上你自己寫的指示,一併提交給OpenAI的模型,函數返回值response是一個Dictionary,包括了model, choices, usage, created等各種欄位。

model的選擇和名稱見上文。

prompt可以是任何指示,比如幫我修改這段文字。(變數名用instruction更合理)。

selectedText是Word檔案中選取的文字。

Function CallOpenAI(model As String, prompt As String, selectedText As String) As Dictionary
    Dim url As String
    Dim headers As Object
    Dim body As Object
    Dim client As Object
    Dim response As Object
 
    ' Set up the API endpoint URL, headers, and request body
    url = "https://api.openai.com/v1/completions"
    Set headers = CreateObject("Scripting.Dictionary")
    headers.Add "Content-Type", "application/json"
    headers.Add "Authorization", "Bearer <API_KEY>"
    Set body = CreateObject("Scripting.Dictionary")
    
    body.Add "model", model
    body.Add "prompt", prompt & "{" & selectedText & "}"
    body.Add "max_tokens", 1000
    ' Send the API request and get the response
    Set client = CreateObject("MSXML2.XMLHTTP")
    client.Open "POST", url, False
    For Each key In headers.Keys
        client.setRequestHeader key, headers(key)
    Next
    client.send JsonConverter.ConvertToJson(body)
    
    'Debug.Print client.responseText
    ' Parse the response JSON and return the completed text
    Set response = JsonConverter.ParseJson(client.responseText)
    Set CallOpenAI = response
    
End Function

這裡需要在header變數中新增自己的OpenAI的API-Key,具體而言是在12行將<API_KEY> 替換為自己的API_key。

此外,body變數可以新增而外的模型引數比如n, temperature等控制結果的輸出,具體見API檔案。

2.3.提取資訊

一眾函數分別從response的以下欄位提取相應資訊。

"model"-模型名稱

'usage"-模型使用情況,用了多少個token

”choices"-模型返回的文字資訊,這就是ChatGPT的回答。

Function GetModel(response As Dictionary) As String
GetModel = response("model")
End Function
 
 
Function GetUsage(response As Dictionary) As Integer
GetUsage = response("usage")("total_tokens")
End Function
 
 
Function GetResponseText(response As Dictionary) As String
Dim resp As String
resp = response("choices")(1)("text")
resp = Trim(resp)
    resp = Replace(resp, vbNewLine, "")
    'resp = Replace(resp, "nn", "")
    'resp = Replace(resp, vbLf, "")
    'resp = Replace(resp, vbCrLf, "")
    'resp = Replace(resp, Chr(10), "")
    'resp = Replace(resp, Chr(13), "")
    'resp = Replace(resp, vbCr, "")
    'resp = Replace(resp, vbLf, "")
GetResponseText = resp
End Function

Dictornay的變數中,字典的字典是無法直接獲取的,大部分操作都可能會報錯,用Debug.Print也無法顯示。比如choices下包括了一個字典,就需要使用類似的方式獲取:response("choices")(1)("text")

2.4.計算模型使用費用

有必要根據模型的名稱和使用量,計算一下使用成本。

Function GetEstimatedFee(model As String, totalTokens As Integer) As Double
    ' Set the token prices for each model
    Dim tokenPrices As Object
    Set tokenPrices = CreateObject("Scripting.Dictionary")
    tokenPrices.Add "text-davinci-003", 0.02
    tokenPrices.Add "text-curie-001", 0.002
    tokenPrices.Add "text-babbage-001", 0.0005
    
    ' Calculate the estimated fee
    Dim tokenPrice As Double
    If tokenPrices.Exists(model) Then
        tokenPrice = tokenPrices(model)
    Else
        'Defaultto the davinci token price if the modelisnot recognized
        tokenPrice = tokenPrices("text-davinci-003")
    End If
    GetEstimatedFee = totalTokens * tokenPrice * 0.001
End Function

2.5.返回資訊到Word介面

該部分程式碼的輸入為,提取到文字(也就是chatGPT給你的答案),費用以及模式。

這裡考慮了三種模式:

第一種,track, 是將文字使用修訂的方式放到word中,事實證明並不好用,會將所選文字刪除並加上提取的文字。並不是哪裡不同修訂哪裡。

第二種, append, 是在所選文字後面加入提取的文字,並以藍色標註。

第三種, replace, 是直接替換所選文字。

另外,使用量以及費用會以對話方塊的形式出現。

Sub ProcessChatGPTResponse(responseText As String, feeText As String, mode As String)
 
 
    Dim newRange As Range
    Dim resp As String
    resp = responseText
    'resp = responseText & "**" & feeText
    ' Get the current selection
    Dim currentSelection As Range
    Set currentSelection = Selection.Range
    
    ' Determine how to handle the corrected text based on the mode parameter
    If mode = "track" Then
        ' Create a new range and insert the corrected text
        Set newRange = ActiveDocument.Range(currentSelection.End, currentSelection.End)
        newRange.Text = resp
        ' Track changes on the new range
        ActiveDocument.TrackRevisions = True
        currentSelection.Text = resp
        ActiveDocument.TrackRevisions = False
    ElseIf mode = "append" Then
        Dim insertText As String
        insertText = vbCr & resp
        ' Insert the corrected text in a new paragraph after the selection
        currentSelection.InsertAfter insertText
        '~~> Remove selection. This will move the cursor at end of selected word
        Selection.MoveRight Unit:=wdCharacter, Count:=1
        '~~> Select the inserted word
        Selection.MoveRight Unit:=wdCharacter, Count:=Len(insertText), Extend:=wdExtend
        Selection.Font.Color = wdColorBlue
    ElseIf mode = "replace" Then
        ' Replace the selected text with the corrected text
        currentSelection.Text = resp
    End If
    MsgBox "Estimated Cost:" & vbCrLf & feeText, vbInformation, "Estimated Cost"
    
End Sub

3.介面

由於不同的按鈕目前只是使用者的指示不同,剩下內容均一致,所以這裡建立了一個函數,簡化後面的流程。輸入是model和prompt。這裡統一使用了"append"的顯示方式,即在選取文字之後新增chatGPT回答。

Sub RinbbonFun(model As String, prompt As String)
    Dim selectedText As String
    Dim response As Dictionary
    Dim modelName As String
    Dim tokenN As Integer
    Dim feeText As String
    Dim responseText As String
    selectedText = Selection.Text
    Set response = CallOpenAI(model, prompt, selectedText)
    responseText = GetResponseText(response)
    modelName = GetModel(response)
    tokenN = GetUsage(response)
    EstimatedFee = GetEstimatedFee(modelName, tokenN)
    feeText = "Model: " & modelName & ", estimated cost: $" & EstimatedFee & "(Tokens:" & tokenN & ")"
    'Debug.Print responseText
    ' Do something with the response, such as replace the selection with the returned text
    ProcessChatGPTResponse responseText, feeText, "append"
    
End Sub

建立相應的函數,用於不同的按鈕。

Sub ImproveEmail()
RinbbonFun "text-davinci-003", "Improve my writing in the email:"
End Sub
Sub RewordIt()
RinbbonFun "text-davinci-003", "Rephrase the following texts and avoid Plagiarism:"
End Sub
Sub SummarizeIt()
RinbbonFun "text-davinci-003", "Summarize the following texts for me:"
End Sub
Sub Translate2CN()
RinbbonFun "text-davinci-003", "Translate the following texts into simplified Chinese:"
End Sub
Sub Translate2EN()
RinbbonFun "text-davinci-003", "Translate the following texts into English:"
End Sub
Sub ImproveWriting()
RinbbonFun "text-davinci-003", "Improve my writing:"
End Sub
Sub ElaborateIt()
RinbbonFun "text-davinci-003", "Elaborate the following content:"
End Sub

然後在Ribbon選項中將這些宏新增成按鈕。

修改名稱和圖示即可。

4.實際使用效果

找了一個改錯題,選取整段文字,點選按鈕,返回修改好的文字,以及使用資訊。

之後用修改過的文字,測試其他按鍵。

至此,基本功能實現。其他的一些功能,比如使用下拉式選單選擇想要的模型,新增輸入框錄入使用組的API-key,新增自定義的按鈕圖案等功能,需要通過XML客製化Ribbon內容,就不浪費時間了。

到此這篇關於如何將ChatGPT整合到Word中的文章就介紹到這了,更多相關ChatGPT整合到Word內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com