Added firework ai and improved some logo
12
Chat.go
@ -531,7 +531,7 @@ func generateLimitReachedChatHTML(c *fiber.Ctx) string {
|
|||||||
return htmlString
|
return htmlString
|
||||||
}
|
}
|
||||||
|
|
||||||
// Buton actions
|
// Button actions
|
||||||
func GetEditMessageFormHandler(c *fiber.Ctx) error {
|
func GetEditMessageFormHandler(c *fiber.Ctx) error {
|
||||||
id := c.FormValue("id")
|
id := c.FormValue("id")
|
||||||
idUUID, _ := edgedb.ParseUUID(id)
|
idUUID, _ := edgedb.ParseUUID(id)
|
||||||
@ -727,7 +727,7 @@ func LoadUsageKPIHandler(c *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GenerateModelPopoverHTML(refresh bool, c *fiber.Ctx) string {
|
func GenerateModelPopoverHTML(refresh bool, c *fiber.Ctx) string {
|
||||||
openaiExists, anthropicExists, mistralExists, groqExists, gooseaiExists, googleExists, perplexityExists := getExistingKeys(c)
|
openaiExists, anthropicExists, mistralExists, groqExists, gooseaiExists, googleExists, perplexityExists, fireworksExists := getExistingKeys(c)
|
||||||
|
|
||||||
var llms []LLM
|
var llms []LLM
|
||||||
err := edgeGlobalClient.WithGlobals(map[string]interface{}{"ext::auth::client_token": c.Cookies("jade-edgedb-auth-token")}).Query(edgeCtx, `
|
err := edgeGlobalClient.WithGlobals(map[string]interface{}{"ext::auth::client_token": c.Cookies("jade-edgedb-auth-token")}).Query(edgeCtx, `
|
||||||
@ -765,7 +765,8 @@ func GenerateModelPopoverHTML(refresh bool, c *fiber.Ctx) string {
|
|||||||
"GooseaiExists": gooseaiExists,
|
"GooseaiExists": gooseaiExists,
|
||||||
"GoogleExists": googleExists,
|
"GoogleExists": googleExists,
|
||||||
"PerplexityExists": perplexityExists,
|
"PerplexityExists": perplexityExists,
|
||||||
"AnyExists": openaiExists || anthropicExists || mistralExists || groqExists || gooseaiExists || googleExists || perplexityExists,
|
"FireworksExists": fireworksExists,
|
||||||
|
"AnyExists": fireworksExists || openaiExists || anthropicExists || mistralExists || groqExists || gooseaiExists || googleExists || perplexityExists,
|
||||||
"LLMs": llms,
|
"LLMs": llms,
|
||||||
"ModelInfos": modelInfos,
|
"ModelInfos": modelInfos,
|
||||||
"DeleteUpdate": refresh,
|
"DeleteUpdate": refresh,
|
||||||
@ -856,7 +857,7 @@ func LoadSettingsHandler(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
stripeSubLink := "https://billing.stripe.com/p/login/6oE6sc0PTfvq1Hi288?prefilled_email=" + user.Email
|
stripeSubLink := "https://billing.stripe.com/p/login/6oE6sc0PTfvq1Hi288?prefilled_email=" + user.Email
|
||||||
|
|
||||||
openaiExists, anthropicExists, mistralExists, groqExists, gooseaiExists, googleExists, perplexityExists := getExistingKeys(c)
|
openaiExists, anthropicExists, mistralExists, groqExists, gooseaiExists, googleExists, perplexityExists, fireworksExists := getExistingKeys(c)
|
||||||
isPremium, isBasic := IsCurrentUserSubscribed(c)
|
isPremium, isBasic := IsCurrentUserSubscribed(c)
|
||||||
|
|
||||||
out, err := settingPopoverTmpl.Execute(pongo2.Context{
|
out, err := settingPopoverTmpl.Execute(pongo2.Context{
|
||||||
@ -868,7 +869,8 @@ func LoadSettingsHandler(c *fiber.Ctx) error {
|
|||||||
"GooseaiExists": gooseaiExists,
|
"GooseaiExists": gooseaiExists,
|
||||||
"GoogleExists": googleExists,
|
"GoogleExists": googleExists,
|
||||||
"PerplexityExists": perplexityExists,
|
"PerplexityExists": perplexityExists,
|
||||||
"AnyExists": openaiExists || anthropicExists || mistralExists || groqExists || gooseaiExists || googleExists || perplexityExists,
|
"FireworksExists": fireworksExists,
|
||||||
|
"AnyExists": fireworksExists || openaiExists || anthropicExists || mistralExists || groqExists || gooseaiExists || googleExists || perplexityExists,
|
||||||
"isPremium": isPremium,
|
"isPremium": isPremium,
|
||||||
"isBasic": isBasic,
|
"isBasic": isBasic,
|
||||||
"StripeSubLink": stripeSubLink,
|
"StripeSubLink": stripeSubLink,
|
||||||
|
18
MyUtils.go
@ -78,9 +78,9 @@ func addCodeHeader(htmlContent string, languages []string) string {
|
|||||||
return updatedHTML
|
return updatedHTML
|
||||||
}
|
}
|
||||||
|
|
||||||
func getExistingKeys(c *fiber.Ctx) (bool, bool, bool, bool, bool, bool, bool) {
|
func getExistingKeys(c *fiber.Ctx) (bool, bool, bool, bool, bool, bool, bool, bool) {
|
||||||
if edgeGlobalClient.WithGlobals(map[string]interface{}{"ext::auth::client_token": c.Cookies("jade-edgedb-auth-token")}) == nil {
|
if edgeGlobalClient.WithGlobals(map[string]interface{}{"ext::auth::client_token": c.Cookies("jade-edgedb-auth-token")}) == nil {
|
||||||
return false, false, false, false, false, false, false
|
return false, false, false, false, false, false, false, false
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -91,6 +91,7 @@ func getExistingKeys(c *fiber.Ctx) (bool, bool, bool, bool, bool, bool, bool) {
|
|||||||
gooseaiExists bool
|
gooseaiExists bool
|
||||||
googleExists bool
|
googleExists bool
|
||||||
perplexityExists bool
|
perplexityExists bool
|
||||||
|
fireworksExists bool
|
||||||
)
|
)
|
||||||
|
|
||||||
err := edgeGlobalClient.WithGlobals(map[string]interface{}{"ext::auth::client_token": c.Cookies("jade-edgedb-auth-token")}).QuerySingle(edgeCtx, `
|
err := edgeGlobalClient.WithGlobals(map[string]interface{}{"ext::auth::client_token": c.Cookies("jade-edgedb-auth-token")}).QuerySingle(edgeCtx, `
|
||||||
@ -170,7 +171,18 @@ func getExistingKeys(c *fiber.Ctx) (bool, bool, bool, bool, bool, bool, bool) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return openaiExists, anthropicExists, mistralExists, groqExists, gooseaiExists, googleExists, perplexityExists
|
err = edgeGlobalClient.WithGlobals(map[string]interface{}{"ext::auth::client_token": c.Cookies("jade-edgedb-auth-token")}).QuerySingle(edgeCtx, `
|
||||||
|
select exists (
|
||||||
|
select global currentUser.setting.keys
|
||||||
|
filter .company.name = "fireworks"
|
||||||
|
);
|
||||||
|
`, &fireworksExists)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error checking if Fireworks key exists")
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return openaiExists, anthropicExists, mistralExists, groqExists, gooseaiExists, googleExists, perplexityExists, fireworksExists
|
||||||
}
|
}
|
||||||
|
|
||||||
func Message2RequestMessage(messages []Message, context string) []RequestMessage {
|
func Message2RequestMessage(messages []Message, context string) []RequestMessage {
|
||||||
|
@ -164,6 +164,8 @@ func GenerateMultipleMessagesHandler(c *fiber.Ctx) error {
|
|||||||
addMessageFunc = addGoogleMessage
|
addMessageFunc = addGoogleMessage
|
||||||
case "perplexity":
|
case "perplexity":
|
||||||
addMessageFunc = addPerplexityMessage
|
addMessageFunc = addPerplexityMessage
|
||||||
|
case "fireworks":
|
||||||
|
addMessageFunc = addFireworkMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
var messageID edgedb.UUID
|
var messageID edgedb.UUID
|
||||||
|
184
RequestFirework.go
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/edgedb/edgedb-go"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FireworkChatCompletionRequest struct {
|
||||||
|
Model string `json:"model"`
|
||||||
|
Messages []RequestMessage `json:"messages"`
|
||||||
|
Temperature float64 `json:"temperature"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FireworkChatCompletionResponse struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Object string `json:"object"`
|
||||||
|
Created int64 `json:"created"`
|
||||||
|
Model string `json:"model"`
|
||||||
|
Usage FireworkUsage `json:"usage"`
|
||||||
|
Choices []FireworkChoice `json:"choices"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FireworkUsage struct {
|
||||||
|
PromptTokens int32 `json:"prompt_tokens"`
|
||||||
|
CompletionTokens int32 `json:"completion_tokens"`
|
||||||
|
TotalTokens int32 `json:"total_tokens"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FireworkChoice struct {
|
||||||
|
Message Message `json:"message"`
|
||||||
|
FinishReason string `json:"finish_reason"`
|
||||||
|
Index int `json:"index"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func addFireworkMessage(c *fiber.Ctx, llm LLM, selected bool) edgedb.UUID {
|
||||||
|
Messages := getAllSelectedMessages(c)
|
||||||
|
|
||||||
|
chatCompletion, err := RequestFirework(c, llm.Model.ModelID, Messages, float64(llm.Temperature), llm.Context)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error fetching user profile")
|
||||||
|
panic(err)
|
||||||
|
} else if len(chatCompletion.Choices) == 0 {
|
||||||
|
fmt.Println("No response from OpenAI")
|
||||||
|
id := insertBotMessage(c, "No response from Firework", selected, llm.ID)
|
||||||
|
return id
|
||||||
|
} else {
|
||||||
|
Content := chatCompletion.Choices[0].Message.Content
|
||||||
|
id := insertBotMessage(c, Content, selected, llm.ID)
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFireworkKey(apiKey string) bool {
|
||||||
|
url := "https://api.fireworks.ai/inference/v1/chat/completions"
|
||||||
|
|
||||||
|
// Convert messages to OpenAI format
|
||||||
|
fireworkMessages := []RequestMessage{
|
||||||
|
{
|
||||||
|
Role: "user",
|
||||||
|
Content: "Hello",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
requestBody := OpenaiChatCompletionRequest{
|
||||||
|
Model: "accounts/fireworks/models/llama-v2-7b-chat",
|
||||||
|
Messages: fireworkMessages,
|
||||||
|
Temperature: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonBody, err := json.Marshal(requestBody)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody))
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
req.Header.Set("Authorization", "Bearer "+apiKey)
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var chatCompletionResponse FireworkChatCompletionResponse
|
||||||
|
err = json.Unmarshal(body, &chatCompletionResponse)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if chatCompletionResponse.Usage.CompletionTokens == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func RequestFirework(c *fiber.Ctx, model string, messages []Message, temperature float64, context string) (FireworkChatCompletionResponse, error) {
|
||||||
|
var apiKey string
|
||||||
|
err := edgeGlobalClient.WithGlobals(map[string]interface{}{"ext::auth::client_token": c.Cookies("jade-edgedb-auth-token")}).QuerySingle(edgeCtx, `
|
||||||
|
with
|
||||||
|
filtered_keys := (
|
||||||
|
select Key {
|
||||||
|
key
|
||||||
|
} filter .company.name = <str>$0 AND .<keys[is Setting].<setting[is User] = global currentUser
|
||||||
|
)
|
||||||
|
select filtered_keys.key limit 1
|
||||||
|
`, &apiKey, "openai")
|
||||||
|
if err != nil {
|
||||||
|
return FireworkChatCompletionResponse{}, fmt.Errorf("error getting OpenAI API key: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "https://api.fireworks.ai/inference/v1/chat/completions"
|
||||||
|
|
||||||
|
requestBody := FireworkChatCompletionRequest{
|
||||||
|
Model: model,
|
||||||
|
Messages: Message2RequestMessage(messages, context),
|
||||||
|
Temperature: temperature,
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonBody, err := json.Marshal(requestBody)
|
||||||
|
if err != nil {
|
||||||
|
return FireworkChatCompletionResponse{}, fmt.Errorf("error marshaling JSON: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody))
|
||||||
|
if err != nil {
|
||||||
|
return FireworkChatCompletionResponse{}, fmt.Errorf("error creating request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
req.Header.Set("Authorization", "Bearer "+apiKey)
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return FireworkChatCompletionResponse{}, fmt.Errorf("error sending request: %w", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return FireworkChatCompletionResponse{}, fmt.Errorf("error reading response body: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var chatCompletionResponse FireworkChatCompletionResponse
|
||||||
|
err = json.Unmarshal(body, &chatCompletionResponse)
|
||||||
|
if err != nil {
|
||||||
|
return FireworkChatCompletionResponse{}, fmt.Errorf("error unmarshaling JSON: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var usedModelInfo ModelInfo
|
||||||
|
err = edgeGlobalClient.WithGlobals(map[string]interface{}{"ext::auth::client_token": c.Cookies("jade-edgedb-auth-token")}).QuerySingle(edgeCtx, `
|
||||||
|
SELECT ModelInfo {
|
||||||
|
inputPrice,
|
||||||
|
outputPrice
|
||||||
|
}
|
||||||
|
FILTER .modelID = <str>$0
|
||||||
|
LIMIT 1
|
||||||
|
`, &usedModelInfo, model)
|
||||||
|
if err != nil {
|
||||||
|
return FireworkChatCompletionResponse{}, fmt.Errorf("error getting model info: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var inputCost float32 = float32(chatCompletionResponse.Usage.PromptTokens) * usedModelInfo.InputPrice
|
||||||
|
var outputCost float32 = float32(chatCompletionResponse.Usage.CompletionTokens) * usedModelInfo.OutputPrice
|
||||||
|
addUsage(c, inputCost, outputCost, chatCompletionResponse.Usage.PromptTokens, chatCompletionResponse.Usage.CompletionTokens, model)
|
||||||
|
|
||||||
|
return chatCompletionResponse, nil
|
||||||
|
}
|
2
main.go
@ -191,6 +191,7 @@ func addKeys(c *fiber.Ctx) error {
|
|||||||
"gooseai": c.FormValue("goose_key"),
|
"gooseai": c.FormValue("goose_key"),
|
||||||
"google": c.FormValue("google_key"),
|
"google": c.FormValue("google_key"),
|
||||||
"perplexity": c.FormValue("perplexity_key"),
|
"perplexity": c.FormValue("perplexity_key"),
|
||||||
|
"fireworks": c.FormValue("fireworks_key"),
|
||||||
}
|
}
|
||||||
|
|
||||||
testFunctions := map[string]func(string) bool{
|
testFunctions := map[string]func(string) bool{
|
||||||
@ -201,6 +202,7 @@ func addKeys(c *fiber.Ctx) error {
|
|||||||
"gooseai": TestGooseaiKey,
|
"gooseai": TestGooseaiKey,
|
||||||
"google": TestGoogleKey,
|
"google": TestGoogleKey,
|
||||||
"perplexity": TestPerplexityKey,
|
"perplexity": TestPerplexityKey,
|
||||||
|
"fireworks": TestFireworkKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
for company, key := range keys {
|
for company, key := range keys {
|
||||||
|
BIN
static/icons/fireworks.png
Normal file
After Width: | Height: | Size: 213 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 172 KiB |
Before Width: | Height: | Size: 30 KiB |
BIN
static/icons/old/fireworks.png
Normal file
After Width: | Height: | Size: 88 KiB |
BIN
static/icons/old/groq.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
static/icons/old/perplexity.png
Normal file
After Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 210 KiB |
Before Width: | Height: | Size: 40 KiB |
@ -23,13 +23,26 @@
|
|||||||
<script src="https://unpkg.com/@highlightjs/cdn-assets@11.9.0/highlight.min.js"></script>
|
<script src="https://unpkg.com/@highlightjs/cdn-assets@11.9.0/highlight.min.js"></script>
|
||||||
<script>hljs.highlightAll();</script>
|
<script>hljs.highlightAll();</script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||||
|
|
||||||
|
<script src="wasm_exec.js"></script>
|
||||||
|
<script>
|
||||||
|
const go = new Go();
|
||||||
|
WebAssembly.instantiateStreaming(fetch("main-v1.wasm"), go.importObject).then((result) => {
|
||||||
|
go.run(result.instance);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body hx-ext="sse" sse-connect="/sse">
|
<body>
|
||||||
|
|
||||||
{{ embed }}
|
{{ embed }}
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
// run printHello(); every 5 seconds
|
||||||
|
setInterval(function () {
|
||||||
|
printHello();
|
||||||
|
}, 5000);
|
||||||
|
|
||||||
function generateMessagePlaceholder(content) {
|
function generateMessagePlaceholder(content) {
|
||||||
marked.setOptions({
|
marked.setOptions({
|
||||||
highlight: function (code, lang) {
|
highlight: function (code, lang) {
|
||||||
|
@ -69,6 +69,15 @@
|
|||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="field has-addons is-hidden" id="fireworks-field">
|
||||||
|
<p class="control has-icons-left is-expanded">
|
||||||
|
<input class="input is-small {% if FireworksExists %}is-success{% endif %}" type="text"
|
||||||
|
placeholder="Fireworks API key" name="fireworks_key" autocomplete="off">
|
||||||
|
<span class="icon is-small is-left">
|
||||||
|
<i class="fas fa-lock"></i>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
<div class="field has-addons is-hidden" id="goose-field"
|
<div class="field has-addons is-hidden" id="goose-field"
|
||||||
title="GooseAI chat API will be available soon">
|
title="GooseAI chat API will be available soon">
|
||||||
<p class="control has-icons-left is-expanded">
|
<p class="control has-icons-left is-expanded">
|
||||||
|