Jade/Request.go
2024-05-16 20:10:57 +02:00

217 lines
5.4 KiB
Go

package main
import (
"context"
"fmt"
"log"
"strings"
"sync"
"time"
"github.com/edgedb/edgedb-go"
"github.com/flosch/pongo2"
"github.com/gofiber/fiber/v2"
)
var lastSelectedLLMs []LLM
func GeneratePlaceholderHandler(c *fiber.Ctx) error {
message := c.FormValue("message", "")
selectedLLMIds := []string{"1e5a07c4-12fe-11ef-8da6-67d29b408c53"} // TODO Hanle in the UI
var selectedLLMs []LLM
var selectedLLM LLM
for _, id := range selectedLLMIds {
idUUID, _ := edgedb.ParseUUID(id)
err := edgeClient.QuerySingle(context.Background(), `
SELECT LLM {
id,
name,
context,
temperature,
modelInfo : {
modelID,
company : {
icon,
name
}
}
}
FILTER
.id = <uuid>$0;
`, &selectedLLM, idUUID)
if err != nil {
fmt.Println("Error trying to select the unique LLM")
log.Fatal(err)
}
selectedLLMs = append(selectedLLMs, selectedLLM)
}
lastSelectedLLMs = selectedLLMs
_, position := insertArea()
messageID := insertUserMessage(message)
out := ""
messageOut, _ := userTmpl.Execute(pongo2.Context{"Content": markdownToHTML(message), "ID": messageID.String()})
out += messageOut
messageOut, _ = botTmpl.Execute(pongo2.Context{"IsPlaceholder": true, "SelectedLLMs": selectedLLMs, "ConversationAreaId": position + 1})
out += messageOut
return c.SendString(out)
}
func GenerateMultipleMessagesHandler(c *fiber.Ctx) error {
insertArea()
selectedLLMs := lastSelectedLLMs
// Create a wait group to synchronize the goroutines
var wg sync.WaitGroup
// Add the length of selectedModelIds goroutines to the wait group
wg.Add(len(selectedLLMs))
// Create a channel to receive the index of the first completed goroutine
firstDone := make(chan int, 1)
for i := range selectedLLMs {
idx := i
go func() {
defer wg.Done()
// Create a context with a 1-minute timeout
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel() // Ensure the context is cancelled to free resources
// Determine which message function to call based on the model
var addMessageFunc func(selectedLLM LLM, selected bool) edgedb.UUID
switch selectedLLMs[idx].Model.Company.Name {
case "openai":
addMessageFunc = addOpenaiMessage
case "anthropic":
addMessageFunc = addAnthropicMessage
case "mistral":
addMessageFunc = addMistralMessage
case "groq":
addMessageFunc = addGroqMessage
}
var messageID edgedb.UUID
if addMessageFunc != nil {
messageID = addMessageFunc(selectedLLMs[idx], idx == 0)
}
var message Message
err := edgeClient.QuerySingle(edgeCtx, `
SELECT Message {
id,
content,
area : {
id,
position
},
llm : {
modelInfo : {
modelID,
name,
company : {
icon,
}
}
}
}
FILTER .id = <uuid>$0;
`, &message, messageID)
if err != nil {
fmt.Println("Error in edgedb.QuerySingle: in HandleGenerateMultipleMessages 1")
log.Fatal(err)
}
templateMessage := TemplateMessage{
Icon: message.LLM.Model.Company.Icon,
Content: markdownToHTML(message.Content),
Hidden: false,
Id: message.ID.String(),
Name: message.LLM.Model.Name,
ModelID: message.LLM.Model.ModelID,
}
// Check if the context's deadline is exceeded
select {
case <-ctx.Done():
// The context's deadline was exceeded
fmt.Printf("Goroutine %d timed out\n", idx)
default:
// Send the index of the completed goroutine to the firstDone channel
select {
case firstDone <- idx:
// Generate the HTML content
outContent := "<div class='message-header'>"
outContent += "<p>"
outContent += templateMessage.Name
outContent += " </p>"
outContent += "</div>"
outContent += "<div class='message-body'>"
outContent += " <ct class='content'>"
outContent += templateMessage.Content
outContent += " </ct>"
outContent += "</div>"
outBtn, err := selectBtnTmpl.Execute(map[string]interface{}{
"message": templateMessage,
"ConversationAreaId": message.Area.Position,
})
if err != nil {
fmt.Println("Error in modelSelecBtnTmpl.Execute: in HandleGenerateMultipleMessages 3")
log.Fatal(err)
}
outBtn = strings.ReplaceAll(outBtn, "\n", "")
outIcon := `<img src="` + selectedLLMs[idx].Model.Company.Icon + `" alt="User Image">`
go sseChanel.SendEvent(
"swapContent-"+fmt.Sprintf("%d", message.Area.Position),
outContent,
)
go sseChanel.SendEvent(
"swapSelectionBtn-"+selectedLLMs[idx].ID.String(),
outBtn,
)
go sseChanel.SendEvent(
"swapIcon-"+fmt.Sprintf("%d", message.Area.Position),
outIcon,
)
default:
out, err := selectBtnTmpl.Execute(map[string]interface{}{
"message": templateMessage,
"ConversationAreaId": message.Area.Position,
})
if err != nil {
fmt.Println("Error in modelSelecBtnTmpl.Execute: in HandleGenerateMultipleMessages 3")
log.Fatal(err)
}
// Replace newline characters to prevent premature termination
out = strings.ReplaceAll(out, "\n", "")
fmt.Println("Sending event: swapSelectionBtn-" + templateMessage.ModelID)
// Send Content event
sseChanel.SendEvent(
"swapSelectionBtn-"+templateMessage.ModelID,
out,
)
}
}
}()
}
// Wait for all goroutines to finish
wg.Wait()
return c.SendString("")
}