2023-12-29 19:10:31 +01:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2023-12-30 13:09:23 +01:00
|
|
|
"context"
|
2024-01-20 11:02:00 +01:00
|
|
|
"encoding/json"
|
2023-12-29 19:10:31 +01:00
|
|
|
"fmt"
|
|
|
|
"os"
|
2024-01-20 14:33:58 +01:00
|
|
|
"os/signal"
|
|
|
|
"syscall"
|
2023-12-29 19:10:31 +01:00
|
|
|
|
2024-03-08 09:25:02 +01:00
|
|
|
"code.ewintr.nl/emdb/client"
|
2024-01-20 11:02:00 +01:00
|
|
|
"github.com/tmc/langchaingo/chains"
|
2023-12-30 13:09:23 +01:00
|
|
|
"github.com/tmc/langchaingo/llms/ollama"
|
2024-01-20 11:02:00 +01:00
|
|
|
"github.com/tmc/langchaingo/prompts"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
mentionsTemplate = `The following text is a user comment about the movie {{.title}}. In it, the user may have referenced other movie titles. List them if you see any.
|
|
|
|
|
|
|
|
----
|
|
|
|
{{.review}}
|
|
|
|
----
|
|
|
|
|
2024-01-20 14:33:58 +01:00
|
|
|
If you found any movie titles other than {{.title}}, list them below in a JSON array. If there are other titles, like TV shows, books or games, ignore them. The format is as follows:
|
2024-01-20 11:02:00 +01:00
|
|
|
|
2024-01-20 14:33:58 +01:00
|
|
|
["movie title 1", "movie title 2"]
|
2024-01-20 11:02:00 +01:00
|
|
|
|
2024-01-20 14:33:58 +01:00
|
|
|
Just answer with the JSON and nothing else. If you don't see any other movie titles, just answer with an empty array.`
|
2023-12-29 19:10:31 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
2023-12-30 13:09:23 +01:00
|
|
|
emdb := client.NewEMDB(os.Getenv("EMDB_BASE_URL"), os.Getenv("EMDB_API_KEY"))
|
2024-01-20 11:19:15 +01:00
|
|
|
|
2024-01-20 14:33:58 +01:00
|
|
|
go Work(emdb)
|
2024-01-20 11:36:05 +01:00
|
|
|
|
2024-01-20 14:33:58 +01:00
|
|
|
c := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
|
|
|
|
<-c
|
|
|
|
}
|
2024-01-20 11:36:05 +01:00
|
|
|
|
2024-01-20 14:33:58 +01:00
|
|
|
func Work(emdb *client.EMDB) {
|
|
|
|
for {
|
|
|
|
j, err := emdb.GetNextAIJob()
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
review, err := emdb.GetReview(j.ActionID)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
movie, err := emdb.GetMovie(review.MovieID)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
llm, err := ollama.New(ollama.WithModel("mistral"))
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
prompt := prompts.NewPromptTemplate(
|
|
|
|
mentionsTemplate,
|
|
|
|
[]string{"title", "review"},
|
|
|
|
)
|
|
|
|
llmChain := chains.NewLLMChain(llm, prompt)
|
|
|
|
|
|
|
|
movieTitle := movie.Title
|
|
|
|
if movie.EnglishTitle != "" && movie.EnglishTitle != movie.Title {
|
|
|
|
movieTitle = fmt.Sprintf("%s (English title: %s)", movieTitle, movie.EnglishTitle)
|
|
|
|
}
|
|
|
|
fmt.Printf("Processing review for movie: %s\n", movieTitle)
|
|
|
|
fmt.Printf("Review: %s\n", review.Review)
|
|
|
|
|
|
|
|
outputValues, err := chains.Call(ctx, llmChain, map[string]any{
|
|
|
|
"title": movieTitle,
|
|
|
|
"review": review.Review,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
out, ok := outputValues[llmChain.OutputKey].(string)
|
|
|
|
if !ok {
|
|
|
|
fmt.Println("invalid chain return")
|
|
|
|
}
|
|
|
|
fmt.Println(out)
|
|
|
|
resp := struct {
|
|
|
|
Movies []string `json:"movies"`
|
|
|
|
TVShows []string `json:"tvShows"`
|
|
|
|
Games []string `json:"games"`
|
|
|
|
Books []string `json:"books"`
|
|
|
|
}{}
|
|
|
|
|
|
|
|
if err := json.Unmarshal([]byte(out), &resp); err != nil {
|
|
|
|
fmt.Printf("could not unmarshal llm response, skipping this one: %s", err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
review.Titles = resp
|
|
|
|
|
|
|
|
if err := emdb.UpdateReview(review); err != nil {
|
|
|
|
fmt.Printf("could not update review: %s\n", err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
2023-12-30 13:09:23 +01:00
|
|
|
}
|
2023-12-29 19:10:31 +01:00
|
|
|
}
|