Files
beelzebub/plugin/OpenAiGPT.go

114 lines
3.3 KiB
Go
Raw Normal View History

package plugin
import (
"encoding/json"
"errors"
"fmt"
"github.com/go-resty/resty/v2"
"strings"
)
const ChatGPTPluginName = "OpenAIGPTLinuxTerminal"
const openAIGPTEndpoint = "https://api.openai.com/v1/completions"
type History struct {
Input, Output string
}
type OpenAIGPTVirtualTerminal struct {
Histories []History
OpenAPIChatGPTSecretKey string
client *resty.Client
}
func (openAIGPTVirtualTerminal *OpenAIGPTVirtualTerminal) InjectDependency() {
if openAIGPTVirtualTerminal.client == nil {
openAIGPTVirtualTerminal.client = resty.New()
}
}
type Choice struct {
Text string `json:"text"`
Index int `json:"index"`
Logprobs interface{} `json:"logprobs"`
FinishReason string `json:"finish_reason"`
}
type gptResponse struct {
ID string `json:"id"`
Object string `json:"object"`
Created int `json:"created"`
Model string `json:"model"`
Choices []Choice `json:"choices"`
Usage struct {
PromptTokens int `json:"prompt_tokens"`
CompletionTokens int `json:"completion_tokens"`
TotalTokens int `json:"total_tokens"`
} `json:"usage"`
}
type gptRequest struct {
Model string `json:"model"`
Prompt string `json:"prompt"`
Temperature int `json:"temperature"`
MaxTokens int `json:"max_tokens"`
TopP int `json:"top_p"`
FrequencyPenalty int `json:"frequency_penalty"`
PresencePenalty int `json:"presence_penalty"`
Stop []string `json:"stop"`
}
//Reference: https://www.engraved.blog/building-a-virtual-machine-inside/
const promptVirtualizeLinuxTerminal = "I want you to act as a Linux terminal. I will type commands and you will reply with what the terminal should show. I want you to only reply with the terminal output inside one unique code block, and nothing else. Do no write explanations. Do not type commands unless I instruct you to do so.\n\nA:pwd\n\nQ:/home/user\n\n"
func buildPrompt(histories []History, command string) string {
var sb strings.Builder
sb.WriteString(promptVirtualizeLinuxTerminal)
for _, history := range histories {
sb.WriteString(fmt.Sprintf("A:%s\n\nQ:%s\n\n", history.Input, history.Output))
}
// Append command to evaluate
sb.WriteString(fmt.Sprintf("A:%s\n\nQ:", command))
return sb.String()
}
func (openAIGPTVirtualTerminal *OpenAIGPTVirtualTerminal) GetCompletions(command string) (string, error) {
requestJson, err := json.Marshal(gptRequest{
Model: "text-davinci-003",
Prompt: buildPrompt(openAIGPTVirtualTerminal.Histories, command),
Temperature: 0,
MaxTokens: 100,
TopP: 1,
FrequencyPenalty: 0,
PresencePenalty: 0,
Stop: []string{"\n"},
})
if err != nil {
return "", err
}
if openAIGPTVirtualTerminal.OpenAPIChatGPTSecretKey == "" {
return "", errors.New("OpenAPIChatGPTSecretKey is empty")
}
response, err := openAIGPTVirtualTerminal.client.R().
SetHeader("Content-Type", "application/json").
SetBody(requestJson).
SetAuthToken(openAIGPTVirtualTerminal.OpenAPIChatGPTSecretKey).
SetResult(&gptResponse{}).
Post(openAIGPTEndpoint)
if err != nil {
return "", err
}
if len(response.Result().(*gptResponse).Choices) == 0 {
return "", errors.New("no choices")
}
return response.Result().(*gptResponse).Choices[0].Text, nil
}