Added firework ai and improved some logo
12
Chat.go
@ -531,7 +531,7 @@ func generateLimitReachedChatHTML(c *fiber.Ctx) string {
|
||||
return htmlString
|
||||
}
|
||||
|
||||
// Buton actions
|
||||
// Button actions
|
||||
func GetEditMessageFormHandler(c *fiber.Ctx) error {
|
||||
id := c.FormValue("id")
|
||||
idUUID, _ := edgedb.ParseUUID(id)
|
||||
@ -727,7 +727,7 @@ func LoadUsageKPIHandler(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
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
|
||||
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,
|
||||
"GoogleExists": googleExists,
|
||||
"PerplexityExists": perplexityExists,
|
||||
"AnyExists": openaiExists || anthropicExists || mistralExists || groqExists || gooseaiExists || googleExists || perplexityExists,
|
||||
"FireworksExists": fireworksExists,
|
||||
"AnyExists": fireworksExists || openaiExists || anthropicExists || mistralExists || groqExists || gooseaiExists || googleExists || perplexityExists,
|
||||
"LLMs": llms,
|
||||
"ModelInfos": modelInfos,
|
||||
"DeleteUpdate": refresh,
|
||||
@ -856,7 +857,7 @@ func LoadSettingsHandler(c *fiber.Ctx) error {
|
||||
|
||||
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)
|
||||
|
||||
out, err := settingPopoverTmpl.Execute(pongo2.Context{
|
||||
@ -868,7 +869,8 @@ func LoadSettingsHandler(c *fiber.Ctx) error {
|
||||
"GooseaiExists": gooseaiExists,
|
||||
"GoogleExists": googleExists,
|
||||
"PerplexityExists": perplexityExists,
|
||||
"AnyExists": openaiExists || anthropicExists || mistralExists || groqExists || gooseaiExists || googleExists || perplexityExists,
|
||||
"FireworksExists": fireworksExists,
|
||||
"AnyExists": fireworksExists || openaiExists || anthropicExists || mistralExists || groqExists || gooseaiExists || googleExists || perplexityExists,
|
||||
"isPremium": isPremium,
|
||||
"isBasic": isBasic,
|
||||
"StripeSubLink": stripeSubLink,
|
||||
|
18
MyUtils.go
@ -78,9 +78,9 @@ func addCodeHeader(htmlContent string, languages []string) string {
|
||||
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 {
|
||||
return false, false, false, false, false, false, false
|
||||
return false, false, false, false, false, false, false, false
|
||||
}
|
||||
|
||||
var (
|
||||
@ -91,6 +91,7 @@ func getExistingKeys(c *fiber.Ctx) (bool, bool, bool, bool, bool, bool, bool) {
|
||||
gooseaiExists bool
|
||||
googleExists bool
|
||||
perplexityExists bool
|
||||
fireworksExists bool
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -164,6 +164,8 @@ func GenerateMultipleMessagesHandler(c *fiber.Ctx) error {
|
||||
addMessageFunc = addGoogleMessage
|
||||
case "perplexity":
|
||||
addMessageFunc = addPerplexityMessage
|
||||
case "fireworks":
|
||||
addMessageFunc = addFireworkMessage
|
||||
}
|
||||
|
||||
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"),
|
||||
"google": c.FormValue("google_key"),
|
||||
"perplexity": c.FormValue("perplexity_key"),
|
||||
"fireworks": c.FormValue("fireworks_key"),
|
||||
}
|
||||
|
||||
testFunctions := map[string]func(string) bool{
|
||||
@ -201,6 +202,7 @@ func addKeys(c *fiber.Ctx) error {
|
||||
"gooseai": TestGooseaiKey,
|
||||
"google": TestGoogleKey,
|
||||
"perplexity": TestPerplexityKey,
|
||||
"fireworks": TestFireworkKey,
|
||||
}
|
||||
|
||||
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>hljs.highlightAll();</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>
|
||||
|
||||
<body hx-ext="sse" sse-connect="/sse">
|
||||
<body>
|
||||
|
||||
{{ embed }}
|
||||
|
||||
<script>
|
||||
// run printHello(); every 5 seconds
|
||||
setInterval(function () {
|
||||
printHello();
|
||||
}, 5000);
|
||||
|
||||
function generateMessagePlaceholder(content) {
|
||||
marked.setOptions({
|
||||
highlight: function (code, lang) {
|
||||
|
@ -69,6 +69,15 @@
|
||||
</span>
|
||||
</p>
|
||||
</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"
|
||||
title="GooseAI chat API will be available soon">
|
||||
<p class="control has-icons-left is-expanded">
|
||||
|