我們試著使用Golang和GPT API,自動根據輸入的主題將部落格發布到WordPress上

首先

最近,OpenAI的chatGPT引起了很大的关注,它是一种能够进行对话的人工智能。我想利用它自动在WordPress上发布文章,并打算用我正在学习的Golang语言来制作它。
鉴于GPT API的文档主要是以Python为基础,所以一般情况下使用Python可能更常见。
顺便提一句,关于GPT API的使用方法,我已经在我个人的博客上做了介绍。

 

另外,所有代码都存放在这里。

 

请按照这个说明进行操作。

GPT API参考文档
WordPress API参考文档

先考虑一个提示。

为了预期的问答回答,请将回答用日语表示,问题用英语表示。这是因为与API费用有关的令牌数量会更多地涉及日语,所以用英语编写问题似乎更好。

首先,为了得到结果,请你用日语回答。

You are a helpful assistant that speaks Japanese

我将其设为角色的系统,这样会话将完全以日语回复。

接下来要求他们做什么以及如何设置条件呢?通过以下方式,让他们考虑博客标题和正文。

#Operation.
Write a blog post for me. Generate a blog title and content for the topic: {topic}.
#conditions
 {conditions}

上述中,我們可以輸入博客的主題至「{topic}」,以及輸入博客的字數限制等條件至「{conditions}」,並且使其生效。

目前关于提示符的问题就暂时完成了。

实施

首先建立GPT API的处理。

定义数据类型

type GptRequest struct {
	Model    string `json:"model"`
	Messages []struct {
		Role    string `json:"role"`
		Content string `json:"content"`
	} `json:"messages"`
}

type GptResponse struct {
	Usage struct {
		PromptTokens     int `json:"prompt_tokens"`
		CompletionTokens int `json:"completion_tokens"`
		TotalTokens      int `json:"total_tokens"`
	} `json:"usage"`
	Choices []struct {
		Message struct {
			Content string `json:"content"`
		} `json:"message"`
	} `json:"choices"`
}

在上述中,我们定义了用于访问API的数据类型,虽然可以使用字符串,但将其转换为json作为数据类型更容易理解,并且在golang中,转换json的方法也很简单,因此进行转换。

GptRequest的模型中包含要使用的模型(如gpt-4),Messages则是要问的内容。关于Role,它有system、user和assistant三个角色,system和user在向AI提问时扮演相同的角色,但如果使用GPT-4,则优先将设置在此处的问题应用到这里。

关于assistant,它似乎是用于补充提问内容的相关信息。

访问API

func GetContent(topic string, apiKey string) (string, string, error) {
	url := "https://api.openai.com/v1/chat/completions"
    prompt := "#Operation.\n Write a blog post for me. Generate a blog title and content for the topic: {topic}.\n#conditions \n {conditions}"

	fmt.Println("---------- this prompt create ----------")
	
	conditions := strings.Join(["At least 100 words of text"], "\n")
	prompt = strings.ReplaceAll(prompt, "{topic}", topic)
	prompt = strings.ReplaceAll(prompt, "{conditions}", conditions)
	fmt.Println(prompt)
	fmt.Println("---------- prompt end  ----------")
	payload := &GptRequest{
		Model: "gpt-4",
		Messages: []struct {
			Role    string `json:"role"`
			Content string `json:"content"`
		}{
			{
				Role:    "system",
				Content: "You are a helpful assistant that speaks Japanese",
			},
			{
				Role:    "user",
				Content: prompt,
			},
		},
	}

	jsonPayload, err := json.Marshal(payload)
	if err != nil {
		return "", "", err
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonPayload))
	if err != nil {
		return "", "", err
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", apiKey))

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return "", "", err
	}
	fmt.Println("http status " + resp.Status)

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", "", err
	}

	var gpt4Response GptResponse
	err = json.Unmarshal(body, &gpt4Response)
	if err != nil {
		return "", "", err
	}
	text := gpt4Response.Choices[0].Message.Content
	split := strings.SplitN(text, "\n", 2)
	title := split[0]
	content := ""
	if len(split) > 1 {
		content = split[1]
	}
	fmt.Println("usage PromptTokens =", gpt4Response.Usage.PromptTokens)
	fmt.Println("usage CompletionTokens =", gpt4Response.Usage.CompletionTokens)
	fmt.Println("usage TotalTokens =", gpt4Response.Usage.TotalTokens)
	return title, content, nil
}

在上述的代码中,我们通过指定的主题和API密钥创建一个提示,并将其发送到GPT API进行POST请求,然后将返回的响应的json数据转换为GptResponse类型,然后提取标题和正文并返回。

作为请求,将json数据转换为jsonData, _ := json.Marshal(payload)非常简单,将响应转换为数据类型是json.Unmarshal(body, &gpt4Response)一次完成。

创建WordPress的处理程序。

数据类型的定义

与GPT类似,创建请求和响应的数据类型

type WPRequest struct {
	Title   string `json:"title"`
	Content string `json:"content"`
	Status  string `json:"status"`
}

type WPResponse struct {
	ID int `json:"id"`
}

这次需要的是标题、正文和是否公开。因此,在请求中定义了Title、Content和Status这三个参数,并且在响应中可以获取到所创建文章的ID。

访问API

func PostBlog(title string, content string, siteName string, apiKey string, postUserName string) error {
	url := siteName + "/wp-json/wp/v2/posts"
	payload := &WPRequest{
		Title:   title,
		Content: content,
		Status:  "publish",
	}
	jsonPayload, err := json.Marshal(payload)
	if err != nil {
		return err
	}

	req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonPayload))

	req.Header.Add("Content-Type", "application/json")

	req.SetBasicAuth(postUserName, apiKey)

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}

	fmt.Println("http status " + resp.Status)

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	var wpResponse WPResponse
	json.Unmarshal(body, &wpResponse)

	fmt.Printf("Posted new blog with ID: %d\n", wpResponse.ID)
	return nil
}

我們將基於所提供的標題、內容、網站名稱(域名)、API金鑰和作者使用者名稱來發布文章。
我們將進行發布設置,將狀態設為”發布”,以便公開它。

创建main.go文件

创建一个名为main.go的入口文件,通过使用最后创建的函数来实际进行发布。

func main() {
	openAIKey := os.Getenv("OPENAI_API_KEY")
	siteName := os.Getenv("WORDPRESS_SITE_NAME")
	postUserName := os.Getenv("WORDPRESS_USER_NAME")
	wordpressKey := os.Getenv("WORDPRESS_API_KEY")

	reader := bufio.NewReader(os.Stdin)
	fmt.Println("Enter the topic for the blog post:")
	topic, _ := reader.ReadString('\n')

	fmt.Println("Thank you input topic")
	topicLog := fmt.Sprintf("generating blog for gpt [topic = %s\n]", topic)
	fmt.Println(topicLog)
	title, content, err := openai.GetContent(topic, openAIKey)
	fmt.Println("completing generating blog for gpt")
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println("posting blog")
	wordpress.PostBlog(title, content, siteName, wordpressKey, postUserName)
	fmt.Println("complete posting blog")
}

在上述代码中,通过使用os.Getenv从环境变量中获取必要的信息,如API密钥和网站名称。然后通过使用reader := bufio.NewReader(os.Stdin)从命令行界面输入的主题信息来创建文章。

执行

我想要使用环境变量,因此我想要创建.env文件并在makefile中执行。

OPENAI_API_KEY=your_openai_api_key_here
WORDPRESS_SITE_NAME=your_wordpress_site_name_here
WORDPRESS_USER_NAME=your_wordpress_user_name_here
WORDPRESS_API_KEY=your_wordpress_api_key_here
include .env
export

.PHONY: build run

build:
	go build -o build/auto-blog-wordpress

run: build
	./build/auto-blog-wordpress

我将尝试运行上述的make run命令。

make run
go build -o build/auto-blog-wordpress
./build/auto-blog-wordpress
Enter the topic for the blog post:
sample
Thank you input topic
generating blog for gpt topic = sample

---------- the topics ----------
generating blog for gpt [topic = sample
]
---------- end  ----------
---------- this prompt create ----------
#Operation.
 Write a blog post for me. Generate a blog title and content for the topic: sample
.
#conditions 
 content is 'sample'
---------- prompt end  ----------
http status 200 OK
usage PromptTokens = 50
usage CompletionTokens = 882
usage TotalTokens = 932
completing generating blog for gpt
posting blog
http status 201 Created
Posted new blog with ID: 2152
complete posting blog

我感觉日志有些奇怪,但是已经成功了。
我在WordPress上看到了可以创建相应内容的文章。

然而,由于返回的内容不是HTML,所以在源代码和段落指定等方面仍然有很多工作要做。我希望通过调整提示符和WordPress设置来尽力使文章能够以漂亮的方式发布。

广告
将在 10 秒后关闭
bannerAds