swap to fly.io
This commit is contained in:
parent
a5a322cd38
commit
f2f6547b22
@ -1 +1 @@
|
||||
data/
|
||||
data
|
38
Chat.go
38
Chat.go
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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>`
|
||||
|
||||
|
@ -1,3 +0,0 @@
|
||||
|
||||
docker build -t mrbounty1/jade:jadeAlpha1 .
|
||||
docker push mrbounty1/jade:jadeAlpha1
|
@ -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
21
fly.toml
Normal 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
41
main.go
@ -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
BIN
static/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 203 KiB |
@ -1,5 +1,5 @@
|
||||
body {
|
||||
padding-bottom: 155px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
html {
|
||||
|
@ -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>
|
@ -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>
|
||||
|
@ -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>
|
Loading…
x
Reference in New Issue
Block a user