remove langchain

This commit is contained in:
Erik Winter 2024-03-09 21:13:32 +01:00
parent 002702745d
commit 2d8fee2c05
5 changed files with 81 additions and 59 deletions

64
client/ollama.go Normal file
View File

@ -0,0 +1,64 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
type Ollama struct {
baseURL string
c *http.Client
}
func NewOllama(baseURL string) *Ollama {
return &Ollama{
baseURL: baseURL,
c: &http.Client{},
}
}
func (o *Ollama) Generate(model, prompt string) (string, error) {
url := fmt.Sprintf("%s/api/generate", o.baseURL)
reqBody := struct {
Model string
Prompt string
Format string
Stream bool
}{
Model: model,
Prompt: prompt,
Format: "json",
Stream: false,
}
reqBodyJSON, err := json.Marshal(reqBody)
if err != nil {
return "", err
}
req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(reqBodyJSON))
if err != nil {
return "", err
}
res, err := o.c.Do(req)
if err != nil {
return "", err
}
body, err := io.ReadAll(res.Body)
if err != nil {
return "", err
}
defer res.Body.Close()
resBody := struct {
Response string
}{}
if err := json.Unmarshal(body, &resBody); err != nil {
return "", err
}
return resBody.Response, nil
}

View File

@ -12,13 +12,6 @@ const (
type ReviewSource string
type Titles struct {
Movies []string `json:"movies"`
TVShows []string `json:"tvShows"`
Games []string `json:"games"`
Books []string `json:"books"`
}
type Review struct {
ID string
MovieID string
@ -27,7 +20,7 @@ type Review struct {
Review string
MovieRating int
Quality int
Titles Titles
Titles []string
}
type ReviewRepository struct {

View File

@ -42,8 +42,9 @@ func main() {
movieRepo := storage.NewMovieRepository(dbPostgres)
reviewRepo := storage.NewReviewRepository(dbPostgres)
jobQueue := job.NewJobQueue(dbPostgres, logger)
ollama := client.NewOllama("http://localhost:11434")
w := worker.NewWorker(jobQueue, movieRepo, reviewRepo, client.NewIMDB(), logger)
w := worker.NewWorker(jobQueue, movieRepo, reviewRepo, client.NewIMDB(), ollama, logger)
go w.Run()

View File

@ -1,27 +1,22 @@
package worker
import (
"context"
"encoding/json"
"fmt"
"github.com/tmc/langchaingo/chains"
"github.com/tmc/langchaingo/llms/ollama"
"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.
mentionsTemplate = `The following text is a user comment about the movie %s. In it, the user may have referenced other movie titles. List them if you see any.
----
{{.review}}
%s
----
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:
If you found any movie titles other than %s, 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:
["movie title 1", "movie title 2"]
Just answer with the JSON and nothing else. If you don't see any other movie titles, just answer with an empty array.`
Just answer with the JSON and nothing else. If you don't see any other movie titles, just answer with an empty JSON array.`
)
func (w *Worker) FindTitles(jobID int, reviewID string) {
@ -40,53 +35,20 @@ func (w *Worker) FindTitles(jobID int, reviewID string) {
w.jq.MarkFailed(jobID)
return
}
llm, err := ollama.New(ollama.WithModel("mistral"))
if err != nil {
logger.Error("could not create llm", "error", err)
w.jq.MarkFailed(jobID)
return
}
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,
})
prompt := fmt.Sprintf(mentionsTemplate, movieTitle, review.Review, movieTitle)
titles, err := w.ollama.Generate("mistral", prompt)
if err != nil {
logger.Error("could not call chain", "error", err)
w.jq.MarkFailed(jobID)
return
logger.Error("could not find titles: %w", err)
}
out, ok := outputValues[llmChain.OutputKey].(string)
if !ok {
logger.Error("chain output is not valid")
w.jq.MarkFailed(jobID)
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 {
logger.Info("checked review", "found", titles)
var resp []string
if err := json.Unmarshal([]byte(titles), &resp); err != nil {
logger.Error("could not unmarshal llm response", "error", err)
w.jq.MarkFailed(jobID)
return

View File

@ -20,15 +20,17 @@ type Worker struct {
movieRepo *storage.MovieRepository
reviewRepo *storage.ReviewRepository
imdb *client.IMDB
ollama *client.Ollama
logger *slog.Logger
}
func NewWorker(jq *job.JobQueue, movieRepo *storage.MovieRepository, reviewRepo *storage.ReviewRepository, imdb *client.IMDB, logger *slog.Logger) *Worker {
func NewWorker(jq *job.JobQueue, movieRepo *storage.MovieRepository, reviewRepo *storage.ReviewRepository, imdb *client.IMDB, ollama *client.Ollama, logger *slog.Logger) *Worker {
return &Worker{
jq: jq,
movieRepo: movieRepo,
reviewRepo: reviewRepo,
imdb: imdb,
ollama: ollama,
logger: logger.With("service", "worker"),
}
}
@ -57,7 +59,7 @@ func (w *Worker) Run() {
case job.ActionRefreshAllIMDBReviews:
w.RefreshAllReviews(j.ID)
case job.ActionFindTitles:
//w.FindTitles(j.ID, j.ActionID)
w.FindTitles(j.ID, j.ActionID)
case job.ActionFindAllTitles:
w.FindAllTitles(j.ID)
default: