swap to fly.io

This commit is contained in:
Adrien Bouvais 2024-05-29 13:01:20 +02:00
parent a5a322cd38
commit f2f6547b22
13 changed files with 129 additions and 124 deletions

View File

@ -1 +1 @@
data/
data

38
Chat.go
View File

@ -398,8 +398,8 @@ func generateLimitReachedChatHTML() string {
// TODO Replace by live API call
stripeTable := `
<stripe-pricing-table
pricing-table-id="prctbl_1OxrazP2nW0okNQymYvskUk7"
publishable-key="pk_test_51OxXuWP2nW0okNQy2jyS70vx7WHZzDskvQazsitSDJQ3ifVHPqAkMv7orCePwRGRTarNn8uMuaxbVqD2Zg80oRc600epN4ycQ4"
pricing-table-id="prctbl_1PJAxDP2nW0okNQyY0Q3mbg4"
publishable-key="pk_live_51OxXuWP2nW0okNQyme1qdwbL535jbMmM1uIUi6U5zcvEUUwKraktmpCzudXNdPSTxlHpw2FbCtxpwbyFFcasQ7aj000tJJGpWW"
customer-session-client-secret="` + clientSecretSession + `">
</stripe-pricing-table>`
@ -449,8 +449,7 @@ func GetEditMessageFormHandler(c *fiber.Ctx) error {
rows = 10
}
tmpl := pongo2.Must(pongo2.FromFile("views/partials/message-edit-form.html"))
out, err := tmpl.Execute(pongo2.Context{"Content": message.Content, "ID": id, "Rows": rows})
out, err := messageEditTmpl.Execute(pongo2.Context{"Content": message.Content, "ID": id, "Rows": rows})
if err != nil {
fmt.Println("Error executing user template")
panic(err)
@ -608,7 +607,7 @@ func LoadUsageKPIHandler(c *fiber.Ctx) error {
TotalCount += usage.TotalCount
}
out, err := pongo2.Must(pongo2.FromFile("views/partials/popover-usage.html")).Execute(pongo2.Context{
out, err := usagePopoverTmpl.Execute(pongo2.Context{
"usages": usages,
"TotalCost": TotalCost,
"TotalCount": TotalCount,
@ -624,29 +623,6 @@ func LoadUsageKPIHandler(c *fiber.Ctx) error {
return c.SendString(out)
}
func LoadKeysHandler(c *fiber.Ctx) error {
if !checkIfLogin() {
return c.SendString("")
}
openaiExists, anthropicExists, mistralExists, groqExists, gooseaiExists, googleExists := 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,
"GooseaiExists": gooseaiExists,
"GoogleExists": googleExists,
"AnyExists": openaiExists || anthropicExists || mistralExists || groqExists || gooseaiExists || googleExists,
})
if err != nil {
fmt.Println("Error loading keys")
panic(err)
}
return c.SendString(out)
}
func GenerateModelPopoverHTML(refresh bool) string {
openaiExists, anthropicExists, mistralExists, groqExists, gooseaiExists, googleExists := getExistingKeys()
@ -676,7 +652,7 @@ func GenerateModelPopoverHTML(refresh bool) string {
modelInfos := GetAvailableModels()
out, err := pongo2.Must(pongo2.FromFile("views/partials/popover-models.html")).Execute(pongo2.Context{
out, err := modelPopoverTmpl.Execute(pongo2.Context{
"IsLogin": checkIfLogin(),
"OpenaiExists": openaiExists,
"AnthropicExists": anthropicExists,
@ -720,7 +696,7 @@ func GenerateConversationPopoverHTML(isActive bool) string {
panic(err)
}
out, err := pongo2.Must(pongo2.FromFile("views/partials/popover-conversation.html")).Execute(pongo2.Context{
out, err := conversationPopoverTmpl.Execute(pongo2.Context{
"Conversations": conversations,
"IsActive": isActive,
})
@ -768,7 +744,7 @@ func LoadSettingsHandler(c *fiber.Ctx) error {
openaiExists, anthropicExists, mistralExists, groqExists, gooseaiExists, googleExists := getExistingKeys()
out, err := pongo2.Must(pongo2.FromFile("views/partials/popover-settings.html")).Execute(pongo2.Context{
out, err := settingPopoverTmpl.Execute(pongo2.Context{
"IsLogin": checkIfLogin(),
"OpenaiExists": openaiExists,
"AnthropicExists": anthropicExists,

View File

@ -72,11 +72,13 @@ func TestMistralKey(apiKey string) bool {
jsonBody, err := json.Marshal(requestBody)
if err != nil {
fmt.Println("Error marshalling request to Mistral")
return false
}
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody))
if err != nil {
fmt.Println("Error creating request to Mistral")
return false
}
@ -87,21 +89,25 @@ func TestMistralKey(apiKey string) bool {
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error sending request to Mistral")
return false
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error reading response from Mistral")
return false
}
var chatCompletionResponse MistralChatCompletionResponse
err = json.Unmarshal(body, &chatCompletionResponse)
if err != nil {
fmt.Println("Error unmarshalling response from Mistral")
return false
}
if chatCompletionResponse.Usage.CompletionTokens == 0 {
fmt.Println("No response from Mistral")
return false
}
return true

View File

@ -31,8 +31,8 @@ func generatePricingTableChatHTML() string {
// TODO Replace by live API call
stripeTable := `
<stripe-pricing-table
pricing-table-id="prctbl_1OxrazP2nW0okNQymYvskUk7"
publishable-key="pk_test_51OxXuWP2nW0okNQy2jyS70vx7WHZzDskvQazsitSDJQ3ifVHPqAkMv7orCePwRGRTarNn8uMuaxbVqD2Zg80oRc600epN4ycQ4"
pricing-table-id="prctbl_1PJAxDP2nW0okNQyY0Q3mbg4"
publishable-key="pk_live_51OxXuWP2nW0okNQyme1qdwbL535jbMmM1uIUi6U5zcvEUUwKraktmpCzudXNdPSTxlHpw2FbCtxpwbyFFcasQ7aj000tJJGpWW"
customer-session-client-secret="` + clientSecretSession + `">
</stripe-pricing-table>`

View File

@ -1,3 +0,0 @@
docker build -t mrbounty1/jade:jadeAlpha1 .
docker push mrbounty1/jade:jadeAlpha1

View File

@ -196,7 +196,7 @@ func insertUserMessage(content string) edgedb.UUID {
conversation := global currentConversation,
selected := true,
llm := (
SELECT LLM FILTER .id = <uuid>"32cb4f0c-1c3f-11ef-9247-2fac0086a7d1"
SELECT LLM FILTER .id = <uuid>"f777f024-1da9-11ef-afd4-bf1c8b177a62"
)
}
`, &inserted, "user", content, lastArea.ID)

21
fly.toml Normal file
View File

@ -0,0 +1,21 @@
# fly.toml app configuration file generated for jade-2-0 on 2024-05-28T19:35:25+02:00
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#
app = 'jade-2-0'
primary_region = 'cdg'
[build]
[http_service]
internal_port = 8080
force_https = true
auto_stop_machines = true
auto_start_machines = true
min_machines_running = 0
processes = ['app']
[[vm]]
size = 'shared-cpu-1x'
memory = "256MB"

41
main.go
View File

@ -32,19 +32,30 @@ import (
"bufio"
"fmt"
"log"
"os"
"sync"
"github.com/flosch/pongo2"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/favicon"
"github.com/gofiber/fiber/v2/middleware/logger"
"github.com/gofiber/fiber/v2/middleware/recover"
"github.com/gofiber/template/django/v3"
"github.com/stripe/stripe-go"
)
var userTmpl *pongo2.Template
var botTmpl *pongo2.Template
var selectBtnTmpl *pongo2.Template
var (
userTmpl *pongo2.Template
botTmpl *pongo2.Template
selectBtnTmpl *pongo2.Template
modelPopoverTmpl *pongo2.Template
usagePopoverTmpl *pongo2.Template
settingPopoverTmpl *pongo2.Template
messageEditTmpl *pongo2.Template
conversationPopoverTmpl *pongo2.Template
clients = make(map[chan SSE]bool)
mu sync.Mutex
)
// SSE event structure
type SSE struct {
@ -52,12 +63,6 @@ type SSE struct {
Data string
}
// Global channel and mutex
var (
clients = make(map[chan SSE]bool)
mu sync.Mutex
)
// Function to send events to all clients
func sendEvent(event, data string) {
mu.Lock()
@ -69,12 +74,17 @@ func sendEvent(event, data string) {
}
func main() {
// TODO Change key to env and the live one
stripe.Key = "sk_test_51OxXuWP2nW0okNQyiNAOcBTTWZSiyP1el5KOmV3yIv1DQR0415YPsH1eb89SLrsOFj80o9p2AxGOy042e53yDvZN00jHxHAbE6"
// Use STRIPE_KEY environment variable
stripe.Key = os.Getenv("STRIPE_KEY")
botTmpl = pongo2.Must(pongo2.FromFile("views/partials/message-bot.html"))
userTmpl = pongo2.Must(pongo2.FromFile("views/partials/message-user.html"))
selectBtnTmpl = pongo2.Must(pongo2.FromFile("views/partials/model-selection-btn.html"))
modelPopoverTmpl = pongo2.Must(pongo2.FromFile("views/partials/popover-models.html"))
conversationPopoverTmpl = pongo2.Must(pongo2.FromFile("views/partials/popover-conversation.html"))
usagePopoverTmpl = pongo2.Must(pongo2.FromFile("views/partials/popover-usage.html"))
settingPopoverTmpl = pongo2.Must(pongo2.FromFile("views/partials/popover-settings.html"))
messageEditTmpl = pongo2.Must(pongo2.FromFile("views/partials/message-edit-form.html"))
// Import HTML using django engine/template
engine := django.New("./views", ".html")
@ -82,11 +92,13 @@ func main() {
// Create new Fiber instance
app := fiber.New(fiber.Config{
Views: engine,
AppName: "JADE 2.0",
AppName: "JADE",
EnablePrintRoutes: true,
})
defer app.Shutdown()
// Add default logger
app.Use(favicon.New())
app.Use(logger.New())
app.Use(recover.New())
@ -118,7 +130,6 @@ func main() {
app.Get("/loadConversationSelection", LoadConversationSelectionHandler)
app.Get("/refreshConversationSelection", RefreshConversationSelectionHandler)
app.Get("/loadUsageKPI", LoadUsageKPIHandler)
app.Get("/loadKeys", LoadKeysHandler)
app.Get("/loadSettings", LoadSettingsHandler)
app.Post("/updateLLMPositionBatch", updateLLMPositionBatch)
app.Get("/createConversation", CreateConversationHandler)
@ -175,7 +186,9 @@ func main() {
})
// Start server
log.Fatal(app.Listen(":8080"))
if err := app.Listen(":8080"); err != nil {
log.Fatal(err)
}
}
// The route to add keys, idk where to put it so it's here

BIN
static/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

View File

@ -1,5 +1,5 @@
body {
padding-bottom: 155px;
padding-bottom: 40px;
}
html {

View File

@ -57,9 +57,7 @@
textarea.addEventListener('keydown', handleTextareaKeydown);
function toggleSendButton() {
const sendButton = document.getElementById('chat-input-send-btn');
const selectedLLMIds = JSON.parse(getSelectedModelsIDs());
sendButton.disabled = textarea.value.trim() === '' || selectedLLMIds.length === 0;
document.getElementById('chat-input-send-btn').disabled = textarea.value.trim().length === 0 || document.getElementsByClassName('selected icon-llm').length === 0;
}
function clearTextArea() {
@ -75,12 +73,10 @@
}
function handleTextareaKeydown(event) {
if (event.metaKey && event.key === 'Enter') {
if (event.metaKey && event.key === 'Enter' && event.target === textarea && textarea.value.trim() !== '' && document.getElementsByClassName('selected icon-llm').length !== 0) {
// 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();
}
// Trigger the same action as the send button
document.getElementById('chat-input-send-btn').click();
}
}
</script>

View File

@ -86,6 +86,63 @@
button.innerHTML = originalText;
}, 2000);
}
let lastSelectedIndex = null;
function toggleSelection(element) {
const elements = Array.from(document.getElementsByClassName('icon-llm'));
const index = elements.indexOf(element);
if (document.body.classList.contains('shift-pressed') && lastSelectedIndex !== null) {
const [start, end] = [lastSelectedIndex, index].sort((a, b) => a - b);
let allSelected = true;
for (let i = start; i <= end; i++) {
if (!elements[i].classList.contains('selected')) {
allSelected = false;
break;
}
}
for (let i = start; i <= end; i++) {
if (allSelected) {
elements[i].classList.remove('selected');
elements[i].classList.add('unselected');
} else {
elements[i].classList.add('selected');
elements[i].classList.remove('unselected');
}
}
lastSelectedIndex = null;
const elements2 = Array.from(document.getElementsByClassName('icon-text'));
for (let i = 0; i < elements2.length; i++) {
elements2[i].classList.remove('shiftselected');
}
} else if (document.body.classList.contains('shift-pressed') && lastSelectedIndex === null) {
lastSelectedIndex = index;
element.classList.toggle('shiftselected');
} else {
element.classList.toggle('selected');
element.classList.toggle('unselected');
}
// If at least one model is selected, enable the delete button
if (document.getElementsByClassName('selected icon-llm').length > 0) {
document.getElementById('delete-model-button').disabled = false;
} else {
document.getElementById('delete-model-button').disabled = true;
}
toggleSendButton();
}
function getSelectedModelsIDs() {
var selectedModelsIDs = [];
var selectedModels = document.getElementsByClassName('selected icon-llm');
for (var i = 0; i < selectedModels.length; i++) {
selectedModelsIDs.push(selectedModels[i].getAttribute('data-id'));
}
return selectedModelsIDs.length > 0 ? JSON.stringify(selectedModelsIDs) : '[]';
}
</script>
</body>

View File

@ -127,11 +127,13 @@
})
document.getElementById('create-model-button').addEventListener('click', function () {
console.log('create model');
document.getElementById('models-list').classList.add('is-hidden');
document.getElementById('models-creation').classList.remove('is-hidden');
});
document.getElementById('cancel-create-model-button').addEventListener('click', function () {
console.log('cancel create model');
document.getElementById('models-list').classList.remove('is-hidden');
document.getElementById('models-creation').classList.add('is-hidden');
});
@ -161,68 +163,5 @@
event.preventDefault();
}
});
let lastSelectedIndex = null;
function toggleSelection(element) {
const elements = Array.from(document.getElementsByClassName('icon-llm'));
const index = elements.indexOf(element);
if (document.body.classList.contains('shift-pressed') && lastSelectedIndex !== null) {
const [start, end] = [lastSelectedIndex, index].sort((a, b) => a - b);
let allSelected = true;
for (let i = start; i <= end; i++) {
if (!elements[i].classList.contains('selected')) {
allSelected = false;
break;
}
}
for (let i = start; i <= end; i++) {
if (allSelected) {
elements[i].classList.remove('selected');
elements[i].classList.add('unselected');
} else {
elements[i].classList.add('selected');
elements[i].classList.remove('unselected');
}
}
lastSelectedIndex = null;
const elements2 = Array.from(document.getElementsByClassName('icon-text'));
for (let i = 0; i < elements2.length; i++) {
elements2[i].classList.remove('shiftselected');
}
} else if (document.body.classList.contains('shift-pressed') && lastSelectedIndex === null) {
lastSelectedIndex = index;
element.classList.toggle('shiftselected');
} else {
element.classList.toggle('selected');
element.classList.toggle('unselected');
}
// If at least one model is selected, enable the delete button
if (document.getElementsByClassName('selected icon-llm').length > 0) {
document.getElementById('delete-model-button').disabled = false;
} else {
document.getElementById('delete-model-button').disabled = true;
}
toggleSendButton();
}
function getSelectedModelsIDs() {
var selectedModelsIDs = [];
var selectedModels = document.getElementsByClassName('selected icon-llm');
for (var i = 0; i < selectedModels.length; i++) {
selectedModelsIDs.push(selectedModels[i].getAttribute('data-id'));
}
return selectedModelsIDs.length > 0 ? JSON.stringify(selectedModelsIDs) : '[]';
}
function toggleSendButton() {
var selectedModels = document.getElementsByClassName('selected');
var sendButton = document.getElementById('chat-input-send-btn');
sendButton.disabled = selectedModels.length === 0;
}
</script>
</div>