15 aug 2023
for $0.19 i’ve used chatGPT API to create the summary for ~94 articles and automatically insert them.
the program to do so, which is below, was written in golang with copilot.
this scans all articles and picks those without a summary. it then uses the chatGPT API to create a summary and inserts it into the article.
package main
import (
"bufio"
"context"
"fmt"
"github.com/sashabaranov/go-openai"
"os"
"path/filepath"
"strings"
)
func main() {
var articles []string
(&articles, "C:\\Users\\qknight\\Desktop\\Projects\\pankat\\documents\\blog.lastlog.de\\posts\\")
FindArticlesfor _, article := range articles {
.Println("-> " + article)
fmt}
//var articles1 []string
//articles1 = append(articles1, "C:\\Users\\qknight\\Desktop\\Projects\\pankat\\documents\\blog.lastlog.de\\posts\\tcp.mdwn")
(&articles)
ProcessArticles}
func FindArticles(articles *[]string, d string) {
// Read the current directory
, err := os.ReadDir(d)
dirif err != nil {
.Println("Error reading directory:", err)
fmtreturn
}
// Loop through the files in the directory
for _, file := range dir {
// recursive
if file.IsDir() {
:= filepath.Join(d, file.Name())
full (articles, full)
FindArticles}
// Check if the file is a markdown file
if strings.HasSuffix(file.Name(), ".mdwn") {
// print absolute file path
:= filepath.Join(d, file.Name())
full //fmt.Println(full)
// check if it contains the string "[[!summary"
, err := os.Open(full)
ffdefer ff.Close()
if err != nil {
continue
}
:= bufio.NewScanner(ff)
scanner := false
found for scanner.Scan() {
if strings.Contains(scanner.Text(), "[[!summary") {
.Println("Found summary in " + full)
fmt.Println(scanner.Text())
fmt= true
found continue
}
}
// Add the file to the list of articles
if found == false {
*articles = append(*articles, full)
}
}
}
}
func ProcessArticles(articles *[]string) {
for _, article := range *articles {
// Read the content of the file
, err := readFileContents(article)
contentif err != nil {
.Println("Error reading file contents:", err)
fmtcontinue
}
// Make an API request to OpenAI
, err := createSummary(apiKey(), content)
summaryif err != nil {
.Println("Error making API request:", err)
fmtcontinue
}
// Print the summary from the API response
.Println("Summary:", summary)
fmt
// Write the summary to the file
= writeSummaryToFile(article, summary)
err if err != nil {
.Println("Error writing summary to file:", err)
fmtcontinue
}
}
}
func writeSummaryToFile(filename, summary string) error {
, err := os.Open(filename)
fileif err != nil {
return err
}
// read complete file into a string
var content string
:= bufio.NewScanner(file)
scanner for scanner.Scan() {
+= scanner.Text() + "\n"
content }
.Close()
file:= summary + "\n" + content
newArticle
, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
file1if err != nil {
return err
}
defer file1.Close()
// write to file
, err = file1.WriteString(newArticle)
_if err != nil {
return err
}
return nil
}
func readFileContents(filename string) (string, error) {
, err := os.Open(filename)
fileif err != nil {
return "", err
}
defer file.Close()
var content string
:= bufio.NewScanner(file)
scanner for scanner.Scan() {
+= scanner.Text() + "\n"
content }
return strings.TrimSpace(content), nil
}
func createSummary(apiKey, content string) (string, error) {
:= openai.NewClient(apiKey)
client := fmt.Sprintf("Create a one line summary, without linebreaks, of the content below using the format [\[!summary xxx]] where xxx is the summary text:\n%s", content)
p
, err := client.CreateChatCompletion(
resp.Background(),
context.ChatCompletionRequest{
openai: openai.GPT3Dot5Turbo,
Model: []openai.ChatCompletionMessage{
Messages{
: openai.ChatMessageRoleUser,
Role: p,
Content},
},
},
)
if err != nil {
.Printf("ChatCompletion error: %v\n", err)
fmtreturn "", err
}
return resp.Choices[0].Message.Content, nil
}
this is really quick’n’dirty code since it only needs to execute once.
the result can be found at https://lastlog.de/blog/timeline.html and the summaries are starting with chatGPT.
interestingly for three articles it did not add the closing ]] so the summary was broken. but that comes with using ML i guess, it never archives 100% accuracy.
thanks for the great library at https://github.com/sashabaranov/go-openai!