QOL update

This commit is contained in:
Adrien Bouvais 2024-05-13 20:14:25 +02:00
parent d5c9ba6e21
commit c63813aff4
15 changed files with 186 additions and 47 deletions

61
Chat.go
View File

@ -258,8 +258,60 @@ func GetEditMessageFormHandler(c *fiber.Ctx) error {
return c.SendString(out)
}
func RedoMessageHandler(c *fiber.Ctx) error {
messageId := c.FormValue("id")
messageUUID, _ := edgedb.ParseUUID(messageId)
// Delete messages
err := edgeClient.Execute(edgeCtx, `
WITH
messageArea := (SELECT Message FILTER .id = <uuid>$0).area
DELETE Area
FILTER .position > messageArea.position AND .conversation = messageArea.conversation;
`, messageUUID)
if err != nil {
fmt.Println("Error in edgeClient.Execute: in DeleteMessageHandler")
fmt.Println(err)
}
messageOut, err := botTmpl.Execute(pongo2.Context{"IsPlaceholder": true})
if err != nil {
c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error rendering template",
})
}
selectedModelIds := []string{}
for ModelInfo := range ModelsInfos {
out := c.FormValue("model-check-" + ModelsInfos[ModelInfo].ID)
if out != "" {
selectedModelIds = append(selectedModelIds, ModelsInfos[ModelInfo].ID)
}
}
lastSelectedModelIds = selectedModelIds
return c.SendString(messageOut)
}
func ClearChatHandler(c *fiber.Ctx) error {
// Delete the default conversation
err := edgeClient.Execute(edgeCtx, `
DELETE Conversation
FILTER .user = global currentUser AND .name = "Default";
`)
if err != nil {
fmt.Println("Error in edgeClient.Execute: in ClearChatHandler")
fmt.Println(err)
}
return c.SendString(generateChatHTML())
}
// Popover stuff
func LoadUsageKPIHandler(c *fiber.Ctx) error {
if !checkIfLogin() {
return c.SendString("")
}
var TotalUsage float32
// Using the database. Get the sum of all usage.inputCost and outputCost
err := edgeClient.QuerySingle(edgeCtx, `
@ -326,6 +378,9 @@ func LoadUsageKPIHandler(c *fiber.Ctx) error {
}
func LoadKeysHandler(c *fiber.Ctx) error {
if !checkIfLogin() {
return c.SendString("")
}
openaiExists, anthropicExists, mistralExists, groqExists := getExistingKeys()
out, err := pongo2.Must(pongo2.FromFile("views/partials/popover-keys.html")).Execute(pongo2.Context{"IsLogin": checkIfLogin(), "OpenaiExists": openaiExists, "AnthropicExists": anthropicExists, "MistralExists": mistralExists, "GroqExists": groqExists})
@ -338,6 +393,9 @@ func LoadKeysHandler(c *fiber.Ctx) error {
}
func LoadModelSelectionHandler(c *fiber.Ctx) error {
if !checkIfLogin() {
return c.SendString("")
}
openaiExists, anthropicExists, mistralExists, groqExists := getExistingKeys()
var CompanyInfosAvailable []CompanyInfo
@ -398,6 +456,9 @@ func LoadModelSelectionHandler(c *fiber.Ctx) error {
}
func LoadSettingsHandler(c *fiber.Ctx) error {
if !checkIfLogin() {
return c.SendString("")
}
out, err := pongo2.Must(pongo2.FromFile("views/partials/popover-settings.html")).Execute(pongo2.Context{"IsLogin": checkIfLogin()})
if err != nil {
c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{

View File

@ -103,34 +103,34 @@ func GenerateMultipleMessages(c *fiber.Ctx) error {
return c.SendString(generateChatHTML())
}
func RequestMultipleMessages(c *fiber.Ctx) error {
message := c.FormValue("message")
if chatString, commandExecuted := DetectCommand(message, c); commandExecuted {
return c.SendString(chatString)
}
// Add an Area with the user message inside
insertArea()
messageID := insertUserMessage(message)
func RequestMultipleMessagesHandler(c *fiber.Ctx) error {
message := c.FormValue("message", "")
selectedModelIds := []string{}
for CompanyInfo := range CompanyInfos {
for ModelInfo := range CompanyInfos[CompanyInfo].ModelInfos {
out := c.FormValue("model-check-" + CompanyInfos[CompanyInfo].ModelInfos[ModelInfo].ID)
for ModelInfo := range ModelsInfos {
out := c.FormValue("model-check-" + ModelsInfos[ModelInfo].ID)
if out != "" {
selectedModelIds = append(selectedModelIds, CompanyInfos[CompanyInfo].ModelInfos[ModelInfo].ID)
}
selectedModelIds = append(selectedModelIds, ModelsInfos[ModelInfo].ID)
}
}
lastSelectedModelIds = selectedModelIds
out := ""
messageOut, _ := userTmpl.Execute(pongo2.Context{"Content": markdownToHTML(message), "ID": messageID.String()})
out += messageOut
messageOut, _ = botTmpl.Execute(pongo2.Context{"IsPlaceholder": true, "SelectedModelIds": selectedModelIds, "Message": message})
out += messageOut
out := RequestMultipleMessages(message, selectedModelIds)
return c.SendString(out)
}
func RequestMultipleMessages(message string, selectedModelIds []string) string {
// Add an Area with the user message inside
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})
out += messageOut
return out
}

View File

@ -85,7 +85,7 @@ func init() {
}
func addAnthropicMessage(modelID string, selected bool) edgedb.UUID {
Messages := getAllMessages()
Messages := getAllSelectedMessages()
chatCompletion, err := RequestAnthropic(modelID, Messages, 2048, 0.7) // TODO CHange parameters
if err != nil {

View File

@ -47,7 +47,7 @@ func init() {
modelInfo := ModelInfo{
ID: "llama3-8b-8192",
Name: "Llama 8B",
Name: "Llama 3 8B",
Icon: "groq",
MaxToken: 8192,
InputPrice: 0.00 / 1000000,
@ -58,7 +58,7 @@ func init() {
modelInfo = ModelInfo{
ID: "llama3-70b-8192",
Name: "Llama 70B",
Name: "Llama 3 70B",
Icon: "groq",
MaxToken: 8192,
InputPrice: 0.00 / 1000000,
@ -88,7 +88,7 @@ func init() {
}
func addGroqMessage(modelID string, selected bool) edgedb.UUID {
Messages := getAllMessages()
Messages := getAllSelectedMessages()
chatCompletion, err := RequestGroq(modelID, Messages, 0.7)
if err != nil {

View File

@ -121,7 +121,7 @@ func init() {
}
func addMistralMessage(modelID string, selected bool) edgedb.UUID {
Messages := getAllMessages()
Messages := getAllSelectedMessages()
chatCompletion, err := RequestMistral(modelID, Messages, 0.7)
if err != nil {

View File

@ -77,7 +77,7 @@ func init() {
}
func addOpenaiMessage(modelID string, selected bool) edgedb.UUID {
Messages := getAllMessages()
Messages := getAllSelectedMessages()
chatCompletion, err := RequestOpenai(modelID, Messages, 0.7)
if err != nil {

View File

@ -178,7 +178,8 @@ func insertUserMessage(content string) edgedb.UUID {
SELECT Conversation
FILTER .name = 'Default' AND .user = global currentUser
LIMIT 1
)
),
selected := true
}
`, &inserted, "user", content, lastAreaID)
if err != nil {
@ -243,6 +244,33 @@ func getAllMessages() []Message {
return messages
}
func getAllSelectedMessages() []Message {
// If no CurrentUser, return an empty array
if !checkIfLogin() {
return []Message{}
}
var messages []Message
err := edgeClient.Query(edgeCtx, `
SELECT Message {
id,
model_id,
selected,
role,
content,
date
} FILTER .conversation.name = 'Default' AND .conversation.user = global currentUser AND .selected = true
ORDER BY .date ASC
`, &messages)
if err != nil {
fmt.Println("Error in edgedb.Query: in getAllMessages")
fmt.Println(err)
}
return messages
}
func getCurrentUserKeys() []Key {
var result []Key
err := edgeClient.Query(edgeCtx, "SELECT global currentUser.setting.keys", &result)

View File

@ -32,7 +32,7 @@ module default {
type Conversation {
required name: str;
required user: User {
on target delete delete source;
on target delete allow;
};
required date: datetime {
default := datetime_current();
@ -54,7 +54,9 @@ module default {
required area: Area {
on target delete delete source;
};
required conversation: Conversation;
required conversation: Conversation {
on target delete delete source;
};
required date: datetime {
default := datetime_current();
}

View File

@ -0,0 +1,14 @@
CREATE MIGRATION m1uadgxoeuekkwaessyysetg27ov3wcdfmach7cq5k7vvqn6x6zmrq
ONTO m1nsazfltqdfklverxefbbufjwcq5gorhbovfeeugd7q67txrihd2q
{
ALTER TYPE default::Conversation {
ALTER LINK user {
ON TARGET DELETE ALLOW;
};
};
ALTER TYPE default::Message {
ALTER LINK conversation {
ON TARGET DELETE DELETE SOURCE;
};
};
};

View File

@ -32,6 +32,8 @@ func generatePKCE() (string, string) {
func handleUiSignIn(c *fiber.Ctx) error {
verifier, challenge := generatePKCE()
fmt.Println("Challenge: ", challenge)
c.Cookie(&fiber.Cookie{
Name: "jade-edgedb-pkce-verifier",
Value: verifier,
@ -121,6 +123,7 @@ func handleCallback(c *fiber.Ctx) error {
verifier := c.Cookies("jade-edgedb-pkce-verifier")
if verifier == "" {
fmt.Println("Could not find 'verifier' in the cookie store. Is this the same user agent/browser that started the authorization flow?")
return c.Status(fiber.StatusBadRequest).SendString("Could not find 'verifier' in the cookie store. Is this the same user agent/browser that started the authorization flow?")
}

View File

@ -37,11 +37,13 @@ func main() {
app.Get("/loadChat", LoadChatHandler)
// Chat routes
app.Post("/requestMultipleMessages", RequestMultipleMessages)
app.Post("/requestMultipleMessages", RequestMultipleMessagesHandler)
app.Post("/deleteMessage", DeleteMessageHandler)
app.Get("/generateMultipleMessages", GenerateMultipleMessages)
app.Get("/messageContent", GetMessageContentHandler)
app.Get("/editMessageForm", GetEditMessageFormHandler)
app.Post("/redoMessage", RedoMessageHandler)
app.Post("/clearChat", ClearChatHandler)
// Settings routes
app.Post("/addKeys", addKeys)

View File

@ -4,12 +4,20 @@
<div class="chat-input-container mb-5">
<div class="textarea-wrapper">
<textarea {% if not IsLogin or not HaveKey %}disabled{% endif %} class="textarea"
placeholder="Type your message here..." name="message" oninput="toggleSendButton(this)"></textarea>
placeholder="Type your message here..." name="message" oninput="toggleSendButton(this)"
id="chat-input-textarea"></textarea>
<div class="button-group">
<hx hx-get="/loadSettings" hx-trigger="load" hx-swap="outerHTML" hx-target="this"></hx>
<hx hx-get="/loadKeys" hx-trigger="load" hx-swap="outerHTML" hx-target="this"></hx>
<hx hx-get="/loadUsageKPI" hx-trigger="load" hx-swap="outerHTML" hx-target="this"></hx>
<hx hx-get="/loadModelSelection" hx-trigger="load" hx-swap="outerHTML" hx-target="this"></hx>
<button {% if not IsLogin or not HaveKey %}style="display: none;" {%endif%} class="button is-small"
onclick="clearTextArea()" id="clear-button" hx-post="/clearChat" hx-swap="outerHTML"
hx-target="#chat-container">
<span class="icon">
<i class="fa-solid fa-broom"></i>
</span>
</button>
<button disabled type="submit" class="send-button button is-primary is-small"
hx-post="/requestMultipleMessages" hx-swap="beforeend settle:200ms" hx-target="#chat-messages"
id="chat-input-send-btn" class="chat-input" hx-include="[name='message'], [name^='model-check-']"
@ -24,6 +32,9 @@
</div>
<script>
const textarea = document.querySelector('.textarea');
textarea.addEventListener('keydown', handleTextareaKeydown);
function toggleSendButton(textarea) {
var sendButton = document.getElementById('chat-input-send-btn');
sendButton.disabled = textarea.value.trim() === '';
@ -31,8 +42,18 @@
function clearTextArea() {
setTimeout(function () {
document.querySelector('.textarea').value = '';
toggleSendButton(document.querySelector('.textarea'));
textarea.value = '';
toggleSendButton(textarea);
}, 200);
}
function handleTextareaKeydown(event) {
if (event.metaKey && event.key === 'Enter') {
// Check if the cursor is in the textarea
if (event.target === textarea) {
// Trigger the same action as the send button
document.getElementById('chat-input-send-btn').click();
}
}
}
</script>

View File

@ -8,9 +8,15 @@
</figure>
{% endif %}
{% endfor %}
{% if IsPlaceholder %}
<figure class="image is-48x48" style="flex-shrink: 0;">
<img src="icons/bouvai2.png" alt="User Image">
</figure>
{% endif %}
</div>
<div class="column" id="content-column">
{% if not IsPlaceholder %}
<div class="is-flex is-align-items-start">
<div class="message-content" id="content-{{ ConversationAreaId }}">
{% for message in Messages %}
@ -50,7 +56,7 @@
{% endfor %}
{% endif %}
{% if IsPlaceholder %}
{% elif IsPlaceholder %}
<hx hx-get="/generateMultipleMessages" hx-trigger="load" hx-swap="outerHTML" hx-indicator="#spinner"
hx-target="#chat-container">
</hx>

View File

@ -22,7 +22,15 @@
</div>
</div>
<div class="is-flex is-justify-content mt-2">
<button id="redo-button-{{ ID }}" class="button is-small is-primary message-button is-outlined mr-2">
<button id="delete-button-{{ ID }}" hx-post="/deleteMessage?id={{ ID }}" hx-swap="outerHTML"
hx-target="#chat-container" class="button is-small is-danger message-button is-outlined mr-5">
<span class="icon">
<i class="fa-solid fa-trash"></i>
</span>
</button>
<button id="redo-button-{{ ID }}" class="button is-small is-primary message-button is-outlined mr-1"
hx-post="/redoMessage?id={{ ID }}" hx-swap="innerHTML settle:200ms" hx-target="next .message-bot"
hx-include="[name^='model-check-']">
<span class="icon">
<i class="fa-solid fa-arrows-rotate"></i>
</span>
@ -33,12 +41,6 @@
<i class="fa-solid fa-pen"></i>
</span>
</button>
<button id="delete-button-{{ ID }}" hx-post="/deleteMessage?id={{ ID }}" hx-swap="outerHTML"
hx-target="#chat-container" class="button is-small is-danger message-button is-outlined mr-2">
<span class="icon">
<i class="fa-solid fa-trash"></i>
</span>
</button>
</div>
</div>
</div>

View File

@ -7,13 +7,13 @@
<div class="dropdown-menu" id="dropdown-menu4" role="menu">
<div class="dropdown-content">
<div class="dropdown-item">
<a class="button is-small is-info is-outlined mb-1" href="/signout">
Log out
</a>
<a class="button is-small is-info is-outlined" href="https://artificialanalysis.ai/models"
<a class="button is-small is-primary is-outlined mb-1" href="https://artificialanalysis.ai/models"
target="_blank">
Compare models
</a>
<a class="button is-small is-primary is-outlined mb-1" href="/signout">
Log out
</a>
</div>
</div>
</div>